Skip to content

Commit

Permalink
Tidy up examples
Browse files Browse the repository at this point in the history
  • Loading branch information
ideoforms committed Feb 18, 2024
1 parent 418d0eb commit ecca0aa
Show file tree
Hide file tree
Showing 11 changed files with 374 additions and 340 deletions.
51 changes: 28 additions & 23 deletions examples/audio-through-example.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,34 @@
#!/usr/bin/env python3

#--------------------------------------------------------------------------------
# --------------------------------------------------------------------------------
# Example: Audio playthrough, from input to output.
# (Be careful to listen through headphones or feedback might occur.)
#--------------------------------------------------------------------------------
# (Listen through headphones to avoid feedback)
# --------------------------------------------------------------------------------

from signalflow import *

graph = AudioGraph()

#--------------------------------------------------------------------------------
# Read single channel input.
# To specify the audio device to use, add to ~/.signalflow/config:
#
# [audio]
# input_device_name = "My Device"
#--------------------------------------------------------------------------------
audio_in = AudioIn()

#--------------------------------------------------------------------------------
# Add some ringmod and delay.
#--------------------------------------------------------------------------------
audio_out = audio_in * SineOscillator(200)
audio_out = audio_out + CombDelay(audio_out, 0.2, 0.8) * 0.3
output = ChannelArray([ audio_out, audio_out ])

graph.play(output)
graph.wait()

def main():
graph = AudioGraph()

#--------------------------------------------------------------------------------
# Read mono audio input.
# To specify the audio device to use, add to ~/.signalflow/config:
#
# [audio]
# input_device_name = "My Device"
#--------------------------------------------------------------------------------
audio_in = AudioIn(1)

#--------------------------------------------------------------------------------
# Add some delay, and play
#--------------------------------------------------------------------------------
output = audio_in + CombDelay(audio_in, 0.2, 0.8) * 0.3
stereo = StereoPanner(output)

graph.play(stereo)
graph.wait()


if __name__ == "__main__":
main()
32 changes: 19 additions & 13 deletions examples/buffer-play-example.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,25 @@
from signalflow import *
import os

graph = AudioGraph()

#--------------------------------------------------------------------------------
# Read samples into a Buffer by passing the filename
#--------------------------------------------------------------------------------
audio_path = os.path.join(os.path.dirname(__file__), "audio", "stereo-count.wav")
buf = Buffer(audio_path)
print("Loaded buffer with %d channel(s), duration: %.1fs" % (buf.num_channels, buf.duration))
def main():
graph = AudioGraph()

#--------------------------------------------------------------------------------
# Read samples into a Buffer by passing the filename
#--------------------------------------------------------------------------------
audio_path = os.path.join(os.path.dirname(__file__), "audio", "stereo-count.wav")
buf = Buffer(audio_path)
print("Loaded buffer with %d channel(s), duration: %.1fs" % (buf.num_channels, buf.duration))

#--------------------------------------------------------------------------------
# Begin looping playback
#--------------------------------------------------------------------------------
player = BufferPlayer(buf, loop=True)

graph.play(player)
graph.wait()

#--------------------------------------------------------------------------------
# Begin looping playback
#--------------------------------------------------------------------------------
player = BufferPlayer(buf, loop=True)

graph.play(player)
graph.wait()
if __name__ == "__main__":
main()
80 changes: 42 additions & 38 deletions examples/chaotic-feedback-example.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,41 +5,45 @@
#------------------------------------------------------------------------
from signalflow import *

graph = AudioGraph()
graph.poll(1)

#------------------------------------------------------------------------
# Change frequency on average once per second.
#------------------------------------------------------------------------
f0 = RandomExponential(40, 2000, clock=RandomImpulse(1))

#------------------------------------------------------------------------
# Allocate a one-second buffer for use in the feedback line.
#------------------------------------------------------------------------
buf = Buffer(1, graph.sample_rate)

#------------------------------------------------------------------------
# op1 self-modulates by sending its output value to a
# FeedbackBufferWriter, and reading its previous outputs from a
# FeedbackBufferReader.
#------------------------------------------------------------------------
feedback = FeedbackBufferReader(buf)
op0 = SineOscillator(f0 + f0 * feedback * 14)

#------------------------------------------------------------------------
# Alter the level of self-oscillation once per second.
# Pass an array to RandomImpulse to generate different randomised
# sequences in the L/R channels, for stereo output.
#------------------------------------------------------------------------
level = Smooth(RandomUniform(0, 1, clock=RandomImpulse([0.5, 0.5])))
level = ScaleLinExp(level, 0, 1, 0.0001, 1.0)
op0 = op0 * level
graph.add_node(FeedbackBufferWriter(buf, op0, 0.5))

#------------------------------------------------------------------------
# Use the chaotic output of op0 to modulate a second sine oscillator.
#------------------------------------------------------------------------
op1 = SineOscillator(f0 + f0 * op0 * 14)

graph.play(op1)
graph.wait()
def main():
graph = AudioGraph()
graph.poll(1)

#------------------------------------------------------------------------
# Change frequency on average once per second.
#------------------------------------------------------------------------
f0 = RandomExponential(40, 2000, clock=RandomImpulse(1))

#------------------------------------------------------------------------
# Allocate a one-second buffer for use in the feedback line.
#------------------------------------------------------------------------
buf = Buffer(1, graph.sample_rate)

#------------------------------------------------------------------------
# op1 self-modulates by sending its output value to a
# FeedbackBufferWriter, and reading its previous outputs from a
# FeedbackBufferReader.
#------------------------------------------------------------------------
feedback = FeedbackBufferReader(buf)
op0 = SineOscillator(f0 + f0 * feedback * 14)

#------------------------------------------------------------------------
# Alter the level of self-oscillation once per second.
# Pass an array to RandomImpulse to generate different randomised
# sequences in the L/R channels, for stereo output.
#------------------------------------------------------------------------
level = Smooth(RandomUniform(0, 1, clock=RandomImpulse([0.5, 0.5])))
level = ScaleLinExp(level, 0, 1, 0.0001, 1.0)
op0 = op0 * level
graph.add_node(FeedbackBufferWriter(buf, op0, 0.5))

#------------------------------------------------------------------------
# Use the chaotic output of op0 to modulate a second sine oscillator.
#------------------------------------------------------------------------
op1 = SineOscillator(f0 + f0 * op0 * 14)

graph.play(op1)
graph.wait()

if __name__ == "__main__":
main()
113 changes: 59 additions & 54 deletions examples/euclidean-rhythm-example.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,65 +6,70 @@
# Impulses are passed through resonant filters of different freqencies.
#------------------------------------------------------------------------
from signalflow import *
import random

graph = AudioGraph()
graph.poll(1)

#------------------------------------------------------------------------
# Subclass Patch to create a re-usable subgraph.
# Notes:
# - __init__() must always be called from Patch subclass constructors
# - add_input is not required in this case, but it's good practice
# as it is needed when serialising Patch json to provide info on
# which component nodes should be labelled as named inputs.
# - set_output must be called finally to label the Patch's output node
#------------------------------------------------------------------------
class EuclideanPatch (Patch):
def __init__(self, clock, divider=1, sequence_length=24, num_events=8, cutoff=8000, resonance=0.99, pan=0.0, amp=0.5):
super().__init__()
self.clock = clock
self.cutoff = self.add_input("cutoff", cutoff)
self.resonance = self.add_input("resonance", resonance)
self.divider = self.add_input("divider", divider)
self.sequence_length = self.add_input("sequence_length", sequence_length)
self.num_events = self.add_input("num_events", num_events)
self.amp = self.add_input("amp", amp)
self.pan = self.add_input("pan", pan)
self.eu = Euclidean(ClockDivider(self.clock, self.divider), self.sequence_length, self.num_events)
self.flt = SVFilter(self.eu, "low_pass", cutoff=self.cutoff, resonance=self.resonance)
self.panned = StereoPanner(self.flt * self.amp, self.pan)
self.set_output(self.panned)
def main():
graph = AudioGraph()
graph.poll(1)

#------------------------------------------------------------------------
# Subclass Patch to create a re-usable subgraph.
# Notes:
# - __init__() must always be called from Patch subclass constructors
# - add_input is not required in this case, but it's good practice
# as it is needed when serialising Patch json to provide info on
# which component nodes should be labelled as named inputs.
# - set_output must be called finally to label the Patch's output node
#------------------------------------------------------------------------
class EuclideanPatch (Patch):
def __init__(self, clock, divider=1, sequence_length=24, num_events=8, cutoff=8000, resonance=0.99, pan=0.0, amp=0.5):
super().__init__()
self.clock = clock
self.cutoff = self.add_input("cutoff", cutoff)
self.resonance = self.add_input("resonance", resonance)
self.divider = self.add_input("divider", divider)
self.sequence_length = self.add_input("sequence_length", sequence_length)
self.num_events = self.add_input("num_events", num_events)
self.amp = self.add_input("amp", amp)
self.pan = self.add_input("pan", pan)
self.eu = Euclidean(ClockDivider(self.clock, self.divider), self.sequence_length, self.num_events)
self.flt = SVFilter(self.eu, "low_pass", cutoff=self.cutoff, resonance=self.resonance)
self.panned = StereoPanner(self.flt * self.amp, self.pan)
self.set_output(self.panned)

class PingPongDelayPatch (Patch):
def __init__(self, input=0, delay_time=1/8, feedback=0.7, wet=0.3):
super().__init__()
mono_input = ChannelMixer(1, input)
delay_l = AllpassDelay(mono_input, delay_time=delay_time, feedback=feedback)
delay_r = OneTapDelay(delay_l, delay_time=(delay_time/2))
wetdry = WetDry(input, [ delay_l, delay_r ], wet)
self.set_output(wetdry)

class PingPongDelayPatch (Patch):
def __init__(self, input=0, delay_time=1/8, feedback=0.7, wet=0.3):
super().__init__()
mono_input = ChannelMixer(1, input)
delay_l = AllpassDelay(mono_input, delay_time=delay_time, feedback=feedback)
delay_r = OneTapDelay(delay_l, delay_time=(delay_time/2))
wetdry = WetDry(input, [ delay_l, delay_r ], wet)
self.set_output(wetdry)
clock = Impulse(8)

clock = Impulse(8)
#--------------------------------------------------------------------------------
# Create four parallel Euclidean rhythm lines with different parameters.
#--------------------------------------------------------------------------------
a = EuclideanPatch(clock, 2, 23, 7, 80, 0.99, 0.0, 10.0)
b = EuclideanPatch(clock, 3, 13, 9, 800, 0.98, 0.7, 0.2)
c = EuclideanPatch(clock, 4, 16, 11, 8000, 0.97, -0.7, 0.05)
d = EuclideanPatch(clock, 2, 19, 12, 480, 0.99, 0.0, 0.2)

#--------------------------------------------------------------------------------
# Create four parallel Euclidean rhythm lines with different parameters.
#--------------------------------------------------------------------------------
a = EuclideanPatch(clock, 2, 23, 7, 80, 0.99, 0.0, 10.0)
b = EuclideanPatch(clock, 3, 13, 9, 800, 0.98, 0.7, 0.2)
c = EuclideanPatch(clock, 4, 16, 11, 8000, 0.97, -0.7, 0.05)
d = EuclideanPatch(clock, 2, 19, 12, 480, 0.99, 0.0, 0.2)
#--------------------------------------------------------------------------------
# Sum the rhythm lines, boost and pass through a tanh soft clipper.
#--------------------------------------------------------------------------------
mix = a + b + c + d
mix = Tanh(mix * 10)

#--------------------------------------------------------------------------------
# Sum the rhythm lines, boost and pass through a tanh soft clipper.
#--------------------------------------------------------------------------------
mix = a + b + c + d
mix = Tanh(mix * 10)
#--------------------------------------------------------------------------------
# Mix the wet/dry signals and play the output.
#--------------------------------------------------------------------------------
pingpong = PingPongDelayPatch(mix)
pingpong.play()

#--------------------------------------------------------------------------------
# Mix the wet/dry signals and play the output.
#--------------------------------------------------------------------------------
pingpong = PingPongDelayPatch(mix)
pingpong.play()
graph.wait()

graph.wait()

if __name__ == "__main__":
main()
52 changes: 29 additions & 23 deletions examples/granulation-example.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,38 @@
#!/usr/bin/env python3

#------------------------------------------------------------------------
# SignalFlow: Modulation example.
# SignalFlow: Granulation example.
#------------------------------------------------------------------------
from signalflow import *
import os

#------------------------------------------------------------------------
# Create the global processing graph.
#------------------------------------------------------------------------
graph = AudioGraph()
graph.poll(2)
def main():
#------------------------------------------------------------------------
# Create the global processing graph.
#------------------------------------------------------------------------
graph = AudioGraph()
graph.poll(1)

#------------------------------------------------------------------------
# Load an audio buffer.
#------------------------------------------------------------------------
audio_path = os.path.join(os.path.dirname(__file__), "audio", "gliss.aif")
buf = Buffer(audio_path)
clock = RandomImpulse(50)
pos = WhiteNoise(1, min=0, max=buf.duration, interpolate=False)
pan = RandomUniform(-1, 1, clock=clock)
rate = RandomExponential(0.5, 2.0, clock=clock)
granulator = Granulator(buf, clock, pan=pan, pos=pos, rate=rate, duration=0.5)
envelope = EnvelopeBuffer("triangle")
granulator.set_buffer("envelope", envelope)
#------------------------------------------------------------------------
# Load an audio buffer.
#------------------------------------------------------------------------
audio_path = os.path.join(os.path.dirname(__file__), "audio", "gliss.aif")
buf = Buffer(audio_path)
clock = RandomImpulse(50)
granulator = Granulator(buffer=buf,
clock=clock,
pan=RandomUniform(-1, 1, clock=clock),
pos=RandomUniform(0, buf.duration, clock=clock),
rate=RandomExponential(0.5, 2.0, clock=clock),
duration=0.5)
envelope = EnvelopeBuffer("triangle")
granulator.set_buffer("envelope", envelope)

#------------------------------------------------------------------------
# Play the output.
#------------------------------------------------------------------------
graph.play(granulator)
graph.wait()
#------------------------------------------------------------------------
# Play the output.
#------------------------------------------------------------------------
graph.play(granulator)
graph.wait()

if __name__ == "__main__":
main()
Loading

0 comments on commit ecca0aa

Please sign in to comment.