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.

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())