Exemplo n.º 1
0
    def set_pan(self, newpan, interval=0.5):
        """set_pan(newpan, interval=0.5) -> None

        Change the channel to a new pan position. This affects all notes
        in the channel and any subchannels.

        The position is specified relative to the parent. A value of 0
        (or None, or stereo.default()) places the channel in the same
        position as its parent. A positive number shifts it to the right
        of the parent; a negative number shifts it left. The value may
        also be any object created by the stereo module.

        The change begins immediately, and occurs smoothly over the
        interval given (in seconds). If no value is given, the interval
        defaults to 0.5 (half a second). You should not use a shorter
        interval; it may not be rendered correctly, particularly for
        large changes.

        Due to the way the stereo code is written (a cheap and dirty hack),
        two stereo changes scheduled too close together on the same channel
        (within about one second) can interfere with each other. The earlier
        one may be ignored entirely in favor of the later. Therefore, you
        should not rely on rapid sequences of set_pan() calls for your
        sound effects. Set pan positions on individual notes instead, or
        else create several channels.
        """

        newpan = stereo.cast(newpan)
        starttm = self.generator.agentruntime
        endtm = starttm + int(interval * cboodle.framespersec())

        (oldstarttm, oldendtm, oldstartpan, oldendpan) = self.stereo
        if endtm < oldendtm:
            # The current swoop runs past this one, so we leave it in place.
            return

        # Work out the pan position at the start of this buffer -- not at
        # agentruntime. This is because we're discarding the old pan
        # change. It's not going to have a chance to run up to the correct
        # changeover point.

        attm = self.generator.bufferstarttime
        if attm >= oldendtm:
            atstart = oldendpan
        elif attm >= oldstarttm:
            pan0 = stereo.extend_tuple(oldstartpan)
            pan1 = stereo.extend_tuple(oldendpan)
            ratio = (attm - oldstarttm) / float(oldendtm - oldstarttm)
            atstart = [(ratio * (pan1[ix] - pan0[ix]) + pan0[ix])
                       for ix in range(4)]
            atstart = tuple(atstart)
        else:
            atstart = oldstartpan

        self.stereo = (starttm, endtm, atstart, newpan)
Exemplo n.º 2
0
    def sched_note_duration_pan(self,
                                samp,
                                duration,
                                pan=None,
                                pitch=1.0,
                                volume=1.0,
                                delay=0,
                                chan=None):
        """sched_note_duration_pan(sample, duration, pan=0, pitch=1, volume=1,
            delay=0, chan=self.channel) -> duration

        Schedule a note to play, panning the stereo origin of the sound.
        The pan value defaults to 0, meaning no shift in origin;
        -1 means directly to the left; 1 means directly to the right. The
        value may also be an object created by the stereo module.

        The sound is loaded from samp (which can be a filename, File,
        or Sample object). The pitch is given as a multiple of the
        sound's original frequency; the volume is given as a fraction
        of the sound's original volume. The delay is a time (in seconds)
        to delay before the note is played. The channel, if None or not
        supplied, defaults to the same channel the agent is running in.

        This extends the original sound sample to a longer period of time.
        The duration is given in seconds. This returns the expected duration
        of the sound, in seconds. Due to the way sounds are looped, this may
        be slightly longer than the given duration.
        """

        if self.generator is None or self.channel is None:
            raise generator.ScheduleError('scheduler has never been scheduled')
        if chan is None:
            chan = self.channel
        if not chan.active:
            raise generator.ChannelError(
                'cannot schedule note to inactive channel')
        gen = self.generator
        samp = sample.get(samp)

        starttime = gen.select_time(delay)
        fduration = gen.select_duration(duration)

        pan = stereo.cast(pan)
        dur = samp.queue_note_duration(pitch, volume, pan, starttime,
                                       fduration, chan)
        return float(dur) / float(cboodle.framespersec())
Exemplo n.º 3
0
    def new_channel_pan(self, pan=None, startvolume=1.0, parent=None):
        """new_channel_pan(pan=0, startvolume=1, parent=self.channel) -> channel

        Create a new channel, panning the stereo origin of its sounds.
        (See the stereo module.) The startvolume is the volume the channel
        is initially set to; this will affect all sounds played in the
        channel and any subchannels. The new channel will be a subchannel
        of parent -- if None or not supplied, it will be a subchannel of
        the channel that the agent (self) is running in.
        """

        if self.channel is None:
            raise generator.ChannelError('creator is not in a channel')
        if parent is None:
            parent = self.channel

        pan = stereo.cast(pan)
        chan = generator.Channel(parent, self.generator, self, startvolume,
                                 pan)
        return chan
Exemplo n.º 4
0
    def test_construct(self):
        self.assertStereo(default(), ())

        self.assertStereo(shift(0), ())
        self.assertStereo(shift(-2), (1, -2))

        self.assertStereo(scale(1), ())
        self.assertStereo(scale(3), (3, 0))

        self.assertStereo(shiftxy(), ())
        self.assertStereo(shiftxy(0), ())
        self.assertStereo(shiftxy(0, 0), ())
        self.assertStereo(shiftxy(3), (1, 3))
        self.assertStereo(shiftxy(0, 3), (1, 0, 1, 3))
        self.assertStereo(shiftxy(2, 3), (1, 2, 1, 3))
        self.assertStereo(shiftxy(0.2, 0.3), (1, 0.2, 1, 0.3))

        self.assertStereo(scalexy(), ())
        self.assertStereo(scalexy(1), ())
        self.assertStereo(scalexy(1, 1), ())
        self.assertStereo(scalexy(3), (3, 0))
        self.assertStereo(scalexy(1, 3), (1, 0, 3, 0))
        self.assertStereo(scalexy(2, 3), (2, 0, 3, 0))
        self.assertStereo(scalexy(0.4, -0.5), (0.4, 0, -0.5, 0))

        self.assertStereo(fixed(2), (0, 2))
        self.assertStereo(fixedx(-2), (0, -2))
        self.assertStereo(fixedy(3), (1, 0, 0, 3))
        self.assertStereo(fixedxy(2, 3), (0, 2, 0, 3))

        self.assertStereo(cast(None), ())
        self.assertStereo(cast(()), ())
        self.assertStereo(cast(0), ())
        self.assertStereo(cast(0.0), ())
        self.assertStereo(cast(-2), (1, -2))
        self.assertStereo(cast(-2), (1, -2))
        self.assertStereo(cast(-2.0), (1, -2))
Exemplo n.º 5
0
 def assertStereo(self, val, tup):
     self.assertEqual(val, tup)
     self.assertEqual(val, cast(val))