1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
|
05-control-change.py - Adding control changes to our MIDI synthesizer class.
============================================================================================================================================
This example adds three continuous MIDI controllers to the previous one
(04-simple-midi-synth.py). The first one applied the pitch bend to the
`transpo` argument, which multiply the pitches from the Notein object.
The second is a continuous controller used to change the cutoff frequency
(`hfdamp` argument) of the lowpass filter. The last one sets the speed
(`lfofreq` argument) of moving notche oscillations in the spectrum.
.. code-block:: python
from pyo import *
from random import random
class Synth:
# Added some arguments that will be controlled with MIDI controllers.
def __init__(self, transpo=1, hfdamp=5000, lfofreq=0.2, mul=1):
# Transposition factor.
self.transpo = Sig(transpo)
# Receive midi notes, convert pitch to Hz and manage 10 voices of polyphony.
self.note = Notein(poly=10, scale=1, first=0, last=127)
# Handle pitch and velocity (Notein outputs normalized amplitude (0 -> 1)).
self.pit = self.note["pitch"] * self.transpo
self.amp = MidiAdsr(self.note["velocity"], attack=0.001, decay=0.1, sustain=0.7, release=1, mul=0.1,)
# Anti-aliased stereo square waves, mixed from 10 streams to 1 stream
# to avoid channel alternation on new notes.
self.osc1 = LFO(self.pit, sharp=0.5, type=2, mul=self.amp).mix(1)
self.osc2 = LFO(self.pit * 0.997, sharp=0.5, type=2, mul=self.amp).mix(1)
# Stereo mix.
self.mix = Mix([self.osc1, self.osc2], voices=2)
# High frequencies damping, use argument `hfdamp` to allow MIDI control.
self.damp = ButLP(self.mix, freq=hfdamp)
# Moving notches, use argument `lfofreq` to allow MIDI control.
self.lfo = Sine(lfofreq, phase=[random(), random()]).range(250, 4000)
self.notch = ButBR(self.damp, self.lfo, mul=mul)
def out(self):
"Sends the synth's signal to the audio output and return the object itself."
self.notch.out()
return self
def sig(self):
"Returns the synth's signal for future processing."
return self.notch
s = Server()
s.setMidiInputDevice(99) # Open all input devices.
s.boot()
### Setup the MIDI controllers.
# Bendin can output MIDI note values or transposition factors (scale=1).
# A value of 2 to `brange` argument means that the bending range will be
# 2 semitones above and below the current note.
transpo = Bendin(brange=2, scale=1)
# High frequency damping mapped to controller number 1.
hfdamp = Midictl(ctlnumber=1, minscale=500, maxscale=10000, init=5000)
# Frequency of the LFO applied to the speed of the moving notches.
lfofreq = Midictl(ctlnumber=2, minscale=0.1, maxscale=8, init=0.2)
# Create the midi synth.
a1 = Synth(transpo, hfdamp, lfofreq)
# Send the synth's signal into a reverb processor.
rev = STRev(a1.sig(), inpos=[0.1, 0.9], revtime=2, cutoff=4000, bal=0.15).out()
s.gui(locals())
|