def __init__(self, attack=.01, decay=.1, sustain=.1, release=.01, dur=.121, mul=.5, freq_time=.03, mul_time=.03): self.freq = SigTo(value=0, time=freq_time) self.mul = SigTo(value=mul, time=mul_time) self.adsr = Adsr( attack=attack, decay=decay, sustain=sustain, release=release, dur=dur, mul=self.mul ) self.noises = {} self.effects = {}
def __init__(self, freq=1000, dur=1, mul=1, add=0): PyoObject.__init__(self, mul, add) self._freq = freq self._dur = dur self._mul = mul self._add = add # Begin processing. # 1st Saw oscillator. saw1Table = SawTable(order=50, size=24000).normalize() self._saw1 = Osc(saw1Table, self._freq, interp=4, mul=0.6839) # Dummy amplitude knobs to split Saw 1 into two paths with independent # amplitudes. # Out to Reson1. saw1Dummy1 = self._saw1 * 1.0 saw1Dummy1.setMul(0.63) # Out to Reson2. saw1Dummy2 = self._saw1 * 1.0 saw1Dummy2.setMul(0.38) # 1st Resonant filter. # total duration = note value + 1954ms # sustain at 95% self._reson1Env = Adsr(1.280, 0.097, 0.95, 0.577, dur=self._dur) reson1 = EQ(saw1Dummy1, freq=self._freq, q=100, boost=3.0, type=1, mul=self._reson1Env * 0.7079) # Dummy amplitude knob; lets us more easily balance the filter levels. reson1Dummy = reson1 * 1.0 # 2nd Saw oscillator. saw2Table = SawTable(order=50, size=24000).normalize() self._saw2 = Osc(saw2Table, self._freq / 2, interp=4, mul=0.5433) # Dummy amplitude knob to allow mixing with Saw1, going into Reson2. saw2Dummy = self._saw2 * 1.0 saw2Dummy.setMul(0.38) # 2nd Resonant filter. # total duration = note value + 1954ms # sustain at 53% self._reson2Env = Adsr(1.280, 0.097, 0.53, 0.577, dur=self._dur) reson2 = EQ(saw1Dummy2 + saw2Dummy, freq=self._freq + 1300, q=100, boost=3.0, type=1, mul=self._reson2Env * 0.7079) # Dummy amplitude knob; lets us more easily balance the filter levels. reson2Dummy = reson2 * 1.0 # Amplitude envelopes for the filters. # total duration = note value + 1954ms # sustain at %100 self._amp1Env = Adsr(0.577, 0.097, 1.0, 1.280, dur=self._dur) # total duration = note value + 1862ms # sustain at %100 self._amp2Env = Adsr(0.577, 0.005, 1.0, 1.280, dur=self._dur) # Tweak filter levels reson1Dummy.setMul(self._amp1Env * 0.3) reson2Dummy.setMul(self._amp2Env * 0.4842) filtersDummy = reson1Dummy + reson2Dummy bpf = ButBP(filtersDummy, freq=325, q=1) # Volume knob aqueous = Mix(bpf, mul=self._mul) self._base_objs = aqueous.getBaseObjects()
class Aqueous(PyoObject): """ Aqueous 1.0 This instrument is (loosely) based on a favorite patch from the Analog synthesizer device in Ableton Live. Doesn't really sound like the original at all, but I like it... Meant for a MIDI range of 30-77. Signal chain: saw1 -> reson1 -> resonEnv -> ampEnv -> filter -> out |________ ^ | | saw2 -> reson2 -> resonEnv --->| We have four independent envelopes (reson1Env, reson2Env, amp1Env, amp2Env) with slightly different sustain levels/timing. The envelopes are the most complex aspect of this instrument. I don't entirely understand what goes on here (design by tweak). :Parent: :py:class:`PyoObject` :Args: freq : PyoObject Frequency to generate. dur : float Time in seconds for the instrument to play once triggered. """ def __init__(self, freq=1000, dur=1, mul=1, add=0): PyoObject.__init__(self, mul, add) self._freq = freq self._dur = dur self._mul = mul self._add = add # Begin processing. # 1st Saw oscillator. saw1Table = SawTable(order=50, size=24000).normalize() self._saw1 = Osc(saw1Table, self._freq, interp=4, mul=0.6839) # Dummy amplitude knobs to split Saw 1 into two paths with independent # amplitudes. # Out to Reson1. saw1Dummy1 = self._saw1 * 1.0 saw1Dummy1.setMul(0.63) # Out to Reson2. saw1Dummy2 = self._saw1 * 1.0 saw1Dummy2.setMul(0.38) # 1st Resonant filter. # total duration = note value + 1954ms # sustain at 95% self._reson1Env = Adsr(1.280, 0.097, 0.95, 0.577, dur=self._dur) reson1 = EQ(saw1Dummy1, freq=self._freq, q=100, boost=3.0, type=1, mul=self._reson1Env * 0.7079) # Dummy amplitude knob; lets us more easily balance the filter levels. reson1Dummy = reson1 * 1.0 # 2nd Saw oscillator. saw2Table = SawTable(order=50, size=24000).normalize() self._saw2 = Osc(saw2Table, self._freq / 2, interp=4, mul=0.5433) # Dummy amplitude knob to allow mixing with Saw1, going into Reson2. saw2Dummy = self._saw2 * 1.0 saw2Dummy.setMul(0.38) # 2nd Resonant filter. # total duration = note value + 1954ms # sustain at 53% self._reson2Env = Adsr(1.280, 0.097, 0.53, 0.577, dur=self._dur) reson2 = EQ(saw1Dummy2 + saw2Dummy, freq=self._freq + 1300, q=100, boost=3.0, type=1, mul=self._reson2Env * 0.7079) # Dummy amplitude knob; lets us more easily balance the filter levels. reson2Dummy = reson2 * 1.0 # Amplitude envelopes for the filters. # total duration = note value + 1954ms # sustain at %100 self._amp1Env = Adsr(0.577, 0.097, 1.0, 1.280, dur=self._dur) # total duration = note value + 1862ms # sustain at %100 self._amp2Env = Adsr(0.577, 0.005, 1.0, 1.280, dur=self._dur) # Tweak filter levels reson1Dummy.setMul(self._amp1Env * 0.3) reson2Dummy.setMul(self._amp2Env * 0.4842) filtersDummy = reson1Dummy + reson2Dummy bpf = ButBP(filtersDummy, freq=325, q=1) # Volume knob aqueous = Mix(bpf, mul=self._mul) self._base_objs = aqueous.getBaseObjects() def setFreq(self, x): """ Replace the `freq` attribute. :Args: x : float or PyoObject New `freq` attribute. """ self._freq = x self._saw1.freq = x self._saw2.freq = x @property def freq(self): """float or PyoObject. Frequency.""" return self._freq @freq.setter def freq(self, x): self.setFreq(x) def __dir__(self): return ["freq", "mul", "add"] def play(self, dur=0, delay=0): self._reson1Env.play(dur, delay) self._reson2Env.play(dur, delay) self._amp1Env.play(dur, delay) self._amp2Env.play(dur, delay) return PyoObject.play(self, dur, delay) def stop(self): self._reson1Env.stop() self._reson2Env.stop() self._amp1Env.stop() self._amp2Env.stop() return PyoObject.stop(self) def out(self, chnl=0, inc=1, dur=0, delay=0): self._reson1Env.play(dur, delay) self._reson2Env.play(dur, delay) self._amp1Env.play(dur, delay) self._amp2Env.play(dur, delay) return PyoObject.out(self, chnl, inc, dur, delay)
class MidiAdsrInstrument(object): def __init__(self, attack=.01, decay=.1, sustain=.1, release=.01, dur=.121, mul=.5, freq_time=.03, mul_time=.03): self.freq = SigTo(value=0, time=freq_time) self.mul = SigTo(value=mul, time=mul_time) self.adsr = Adsr( attack=attack, decay=decay, sustain=sustain, release=release, dur=dur, mul=self.mul ) self.noises = {} self.effects = {} def addNoise(self, name, klass, **kwargs): """ klass can be like, Sine, Noise, Osc... we'll see. """ try: n = klass(freq=self.freq, mul=self.adsr, **kwargs).out() except TypeError: # Noise doesn't take frequency @TODO n = klass(mul=self.adsr, **kwargs).out() self.noises[name] = n # add the effects to the new noise. for name, effect in self.effects.iteritems(): klass = effect["klass"] instance = klass(n, **effect["kwargs"]).out() self.effects[name]["instances"].append(instance) def addEffect(self, name, klass, **kwargs): """ An effect `klass` gets instantiated with each noise as src. And gets sent .out(). """ if name in self.effects: log.msg("Already an effect of that name.") return None #raise ValueError("Already and effect with that name.") effect = { "klass": klass, "kwargs": kwargs, "instances": [], } for noise in self.noises.values(): instance = klass(noise, **kwargs).out() effect["instances"].append(instance) self.effects[name] = effect def playfreq(self, freq, mul): """ Sets the frequency signal to `freq` and plays the Adsr envelope. """ #self.frequency.value = freq if self.freq.value != freq: self.freq.value = freq if mul != self.mul.value: self.mul.value = mul self.adsr.play() def playnote(self, note, velocity=None): if velocity is None: mul = self.adsr.mul.value else: mul = velocity / 127. self.playfreq(twelve_tone_equal_440[note], mul) def stopnote(self, note): """ Stop is defined in the ADSR. """ pass