04-ping-pong-delay.py - Stereo ping-pong delay.
============================================================================================================================================


A stereo ping-pong delay is when you use two delays, one hard left and the
other hard right, and the delays alternate. 

This exemple illustrates how we can pass the signal of a first object to
the input of a second even if the first object does not exist yet when the
second is created.

.. code-block:: python

    from pyo import *
    import random
    
    s = Server(duplex=0).boot()
    
    # Compute the duration, in seconds, of one buffer size.
    buftime = s.getBufferSize() / s.getSamplingRate()
    
    # Delay parameters
    delay_time_l = Sig(0.125)  # Delay time for the left channel delay.
    delay_time_l.ctrl()
    delay_feed = Sig(0.75)  # Feedback value for both delays.
    delay_feed.ctrl()
    
    # Because the right delay gets its input sound from the left delay, while
    # it is computed before (to send its output sound to the left delay), it
    # will be one buffer size late. To compensate this additional delay on the
    # right, we substract one buffer size from the real delay time.
    delay_time_r = Sig(delay_time_l, add=-buftime)
    
    # Setup up a soundfile player.
    sf = SfPlayer("../snds/alum1.wav").stop()
    
    # Send the original sound to both speakers.
    sfout = sf.mix(2).out()
    
    # Initialize the right delay with zeros as input because the left delay
    # does not exist yet.
    right = Delay(Sig(0), delay=delay_time_r).out(1)
    
    # Initialize the left delay with the original mono source and the right
    # delay signal (multiplied by the feedback value) as input.
    left = Delay(sf + right * delay_feed, delay=delay_time_l).out()
    
    # One issue with recursive cross-delay is if we set the feedback to
    # 0, the right delay never gets any signal. To resolve this, we add a
    # non-recursive delay, with a gain that is the inverse of the feedback,
    # to the right delay input.
    original_delayed = Delay(sf, delay_time_l, mul=1 - delay_feed)
    
    # Change the right delay input (now that the left delay exists).
    right.setInput(original_delayed + left * delay_feed)
    
    
    def playit():
        "Assign a sound to the player and start playback."
        which = random.randint(1, 4)
        path = "../snds/alum%d.wav" % which
        sf.path = path
        sf.play()
    
    
    # Call the function "playit" every second.
    pat = Pattern(playit, 1).play()
    
    s.gui(locals())

