Exemple #1
0
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)