Example #1
0
    def count(self, time=None):

        # Count the events that should have taken place between 0 and now()

        n = 0
        acc = 0
        dur = 0
        now = (time if time is not None else
               self.metro.now()) + self.metro.get_latency()

        durations = self.rhythm()
        total_dur = float(sum(durations))

        if total_dur == 0:

            WarningMsg("Player object has a total duration of 0. Set to 1")

            durations = [1]
            total_dur = 1
            self.dur = 1

        acc = now - (now % total_dur)

        try:

            n = int(len(durations) * (acc / total_dur))

        except TypeError as e:

            WarningMsg(e)

            self.stop()

            return 0, 0

        while True:

            dur = float(modi(durations, n))

            if acc + dur > now:

                break

            else:

                acc += dur
                n += 1

        # Store duration times

        self.old_dur = self.attr['dur']

        # Returns value for self.event_n and self.event_index

        self.notes_played = n

        return n, acc
Example #2
0
 def shuffle(self, attr=None):
     """ Shuffles """
     if attr is None:
         shuffle(self.attr['degree'])
     elif attr in self.attr:
         shuffle(self.attr[attr])
     else:
         WarningMsg("Player Object has no attribute '{}'".format(attr))
Example #3
0
 def __setattr__(self, name, value):
     try:
         for p in self.players:
             try:
                 setattr(p, name, value)
             except:
                 WarningMsg("'%s' object has no attribute '%s'" % (str(p), name))
     except:
         self.__dict__[name] = value 
     return self        
Example #4
0
    def calculate_freq(self):
        """ Uses the scale, octave, and degree to calculate the frequency values to send to SuperCollider """

        # If the scale is frequency only, just return the degree

        if self.scale == Scale.freq:

            try:

                return list(self.event['degree'])

            except:

                return [self.event['degree']]

        now = {}

        for attr in ('degree', 'oct'):

            now[attr] = self.event[attr]

            try:

                now[attr] = list(now[attr])

            except:

                now[attr] = [now[attr]]

        size = max(len(now['oct']), len(now['degree']))

        f = []

        for i in range(size):

            try:

                midinum = midi(self.scale, modi(now['oct'], i),
                               modi(now['degree'], i), self.now('root'))

            except:

                WarningMsg(
                    "Invalid degree / octave arguments for frequency calculation, reset to default"
                )

                print now['degree'], modi(now['degree'], i)

                raise

            f.append(miditofreq(midinum))

        return f
Example #5
0
File: Repeat.py Project: lvm/FoxDot
    def whenmod(self, mod, n, cmd, *args, **kwargs):
        """ Every n beats, do self.cmd(args) """

        try:

            # Make sure cmd is a method

            attr = cmd.split(".")

            if len(attr) == 1:
                method = getattr(self, attr[0])

            elif len(attr) == 2:

                #sub_method = getattr(self.attr[attr[0]], attr[1])

                sub_method = lambda *args, **kwargs: getattr(self.attr[attr[0]], attr[1]).__call__(*args, **kwargs)

                method = lambda *args, **kwargs: self.attr.update({attr[0]: sub_method(*args, **kwargs)})

            assert callable(method)

        except:

            WarningMsg("{} is not a valid method for type {}".format(cmd, self.__class__))

            return self

        # If the method call already exists, just update it

        key = ('whenmod', cmd)

        if key in self.repeat_events:

            self.repeat_events[key].update(n, args, kwargs)

            if not self.repeat_events[key].isScheduled():

                self.repeat_events[key].schedule()

        else:

            call = WhenModMethodCall(self, method, mod, n, args, kwargs)

            self.repeat_events[key] = call

            call.schedule()

        return self
Example #6
0
    def every(self, n, cmd, args=()):
        """ Every n beats, do self.cmd(args) """

        try:

            # Make sure cmd is a method

            method = getattr(self, cmd)

            assert callable(method)

        except:

            WarningMsg("{} is not a valid method for type {}".format(
                cmd, self.__class__))

            return self

        # If the method call already exists, just update it

        if cmd in self.repeat_events:

            self.repeat_events[cmd].update(n, args)

            if not self.repeat_events[cmd].isScheduled():

                self.repeat_events[cmd].schedule()

        else:

            call = MethodCall(self, cmd, n, args)

            self.repeat_events[cmd] = call

            call.schedule()

        return self
Example #7
0
    def every(self, n, cmd, *args, **kwargs):
        """ Every n beats, call a method (defined as a string) on the
            object and use the args and kwargs. To call the method
            every n-th beat of a timeframe, use the `cycle` keyword argument
            to specify that timeframe.

            ```
            # Call the shuffle method every 4 beats

            p1.every(4, 'shuffle')

            # Call the stutter method on the 5th beat of every 8 beat cycle

            p1.every(5, 'stutter', 4, cycle=8)
            
            ```

        """

        try:

            # Make sure cmd is a method

            attr = cmd.split(".")

            if len(attr) == 1:
                method = getattr(self, attr[0])

            elif len(attr) == 2:

                #sub_method = getattr(self.attr[attr[0]], attr[1])

                sub_method = lambda *args, **kwargs: getattr(self.attr[attr[0]], attr[1]).__call__(*args, **kwargs)

                method = lambda *args, **kwargs: self.attr.update({attr[0]: sub_method(*args, **kwargs)})

            assert callable(method)

        except:

            WarningMsg("{} is not a valid method for type {}".format(cmd, self.__class__))

            return self

        # Collect the cycle length

        cycle = kwargs.get("cycle", None)

        kwargs = {key: value for key, value in kwargs.items() if key != "cycle"}

        # If the method call already exists, just update it

        # key = ('every', cmd)

        key = cmd

        if key in self.repeat_events:

            self.repeat_events[key].update(n, cycle, args, kwargs)

            if not self.repeat_events[key].isScheduled():

                self.repeat_events[key].schedule()

        else:

            call = MethodCall(self, method, n, cycle, args, kwargs)

            self.repeat_events[key] = call

            call.schedule()

        return self
Example #8
0
    def count(self, time=None, event_after=False):
        """ Counts the number of events that will have taken place between 0 and `time`. If
            `time` is not specified the function uses self.metro.now(). Setting `event_after`
            to `True` will find the next event *after* `time`"""

        n = 0
        acc = 0
        dur = 0
        now = (time if time is not None else self.metro.now())

        durations = self.rhythm()
        total_dur = float(sum(durations))

        if total_dur == 0:

            WarningMsg("Player object has a total duration of 0. Set to 1")

            durations = [1]
            total_dur = 1
            self.dur = 1

        acc = now - (now % total_dur)

        try:

            n = int(len(durations) * (acc / total_dur))

        except TypeError as e:

            WarningMsg(e)

            self.stop()

            return 0, 0

        if acc != now:

            while True:

                dur = float(modi(durations, n))

                if acc + dur == now:

                    acc += dur

                    n += 1

                    break

                elif acc + dur > now:

                    if event_after:

                        acc += dur
                        n += 1

                    break

                else:

                    acc += dur
                    n += 1

        # Store duration times

        self.old_dur = self.attr['dur']

        # Returns value for self.event_n and self.event_index

        return n, acc
Example #9
0
    def osc_message(self, index=0, **kwargs):
        """ Creates an OSC packet to play a SynthDef in SuperCollider,
            use kwargs to force values in the packet, e.g. pan=1 will force ['pan', 1] """

        message = []
        fx_dict = {}

        # Calculate frequency / buffer number

        if self.synthdef != SamplePlayer:

            degree = group_modi(kwargs.get("degree", self.event["degree"]),
                                index)
            octave = group_modi(kwargs.get("oct", self.event["oct"]), index)
            root = group_modi(kwargs.get("root", self.event["root"]), index)

            freq = miditofreq(
                midi(kwargs.get("scale", self.scale), octave, degree, root))

            message = ['freq', freq]

        else:

            degree = group_modi(kwargs.get("degree", self.event['degree']),
                                index)
            sample = group_modi(kwargs.get("sample", self.event["sample"]),
                                index)

            buf = int(Samples[str(degree)].bufnum(sample))

            message = ['buf', buf]

        attributes = self.attr.copy()

        # Go through the attr dictionary and add kwargs

        for key in attributes:

            try:

                # Don't use fx keywords or foxdot keywords

                if key not in FxList.kwargs() and key not in self.keywords:

                    group_value = kwargs.get(key, self.event[key])

                    val = group_modi(group_value, index)

                    ## DEBUG

                    if isinstance(val, (Pattern, PGroup)):

                        print "In osc_message:", key, group_value, self.event[
                            key], val

                    # Special case modulation

                    if key == "sus":

                        val = val * self.metro.beat_dur() * group_modi(
                            kwargs.get('blur', self.event['blur']), index)

                    elif key == "amp":

                        val = val * group_modi(
                            kwargs.get('amplify', self.event['amplify']),
                            index)

                    message += [key, val]

            except KeyError as e:

                WarningMsg("KeyError in function 'osc_message'", key, e)

        # See if any fx_attributes

        for key in self.fx_attributes:

            if key in attributes:

                # All effects use sustain to release nodes

                fx_dict[key] = []

                # Look for any other attributes require e.g. room and verb

                for sub_key in FxList[key].args:

                    if sub_key in self.event:

                        if sub_key in message:

                            i = message.index(sub_key) + 1

                            val = message[i]

                        else:

                            try:

                                val = group_modi(
                                    kwargs.get(sub_key, self.event[sub_key]),
                                    index)

                                if isinstance(val, Pattern):

                                    print sub_key, val

                            except TypeError as e:

                                val = 0

                            except KeyError as e:

                                del fx_dict[key]
                                break

                        # Don't send fx with zero values, unless it is a timevar or playerkey i.e. has a "now" attr

                        if val == 0 and not hasattr(val, 'now'):

                            del fx_dict[key]

                            break

                        else:

                            fx_dict[key] += [sub_key, val]

        return message, fx_dict
Example #10
0
    def get_event(self):
        """ Returns a dictionary of attr -> now values """

        # Get the current event

        # self.event = {}

        attributes = copy(self.attr)

        for key in attributes:

            # Eg. sp.sus returns the currently used value for sustain

            value = self.event[key] = self.now(key)

            #  Make sure the object's dict uses PlayerKey instances

            if key not in self.__dict__:

                self.__dict__[key] = PlayerKey(value, parent=self)

            elif not isinstance(self.__dict__[key], PlayerKey):

                self.__dict__[key] = PlayerKey(value, parent=self)

            else:

                self.__dict__[key].update(value)

        # Special case: sample player

        if self.synthdef == SamplePlayer:

            try:

                event_dur = float(self.event['dur'])

                event = self.event['degree'].now() if hasattr(
                    self.event['degree'], "now") else self.event['degree']

                # Store a "char" variable

                size = self.largest_attribute()

                event_buf = list(range(size))

                if isinstance(event, PlayGroup):

                    # Nest the Play Group

                    buf_list = [event]

                else:

                    try:

                        buf_list = list(event)

                    except TypeError as e:

                        buf_list = [event]

                # buf_list is our list of samples to play as characters
                # event_buf is the list of buffer id's

                ##############
                # TODO - Allow for different sample bank IDs in the buffer delay

                self.buf_delay = []

                #for i, bufchar in buf_list: # This should iter over largest event?

                for i in range(size):

                    # Get the char / group from the buf_list

                    bufchar = group_modi(buf_list, i)

                    # If it is a group

                    if isinstance(bufchar, PlayGroup):

                        # Get the first character, then "delay" the rest

                        self.__dict__['char'].update(bufchar[0])

                        char = Samples[bufchar[0]]

                        # Get the buffer number to play for this sample bank (char)

                        buf_mod_index = int(group_modi(self.event['sample'],
                                                       i))

                        event_buf[i] = char.bufnum(buf_mod_index).bufnum

                        # Begin delay

                        delay = 0

                        for n, b in enumerate(bufchar[1:]):

                            # If it is a timevar / random play group, get the value

                            if hasattr(b, 'now'):

                                b = b.now()

                            # Get the sample bank / char

                            char = Samples[b]

                            # Find the appropriate sample in the bank

                            buf_mod_index = int(modi(self.event['sample'], i))

                            # Add the delay

                            delay += (bufchar[n].dur * event_dur)

                            # Add it to our delay list

                            self.buf_delay.append(
                                (char.bufnum(buf_mod_index), delay))

                    else:

                        # Get the char / bank

                        char = Samples[bufchar]

                        self.__dict__['char'].update(bufchar)

                        # Get the buffer number to play

                        buf_mod_index = int(modi(self.event['sample'], i))

                        event_buf[i] = char.bufnum(buf_mod_index).bufnum

                self.event['buf'] = P(event_buf)

            except TypeError as e:

                WarningMsg("Sample player get_event", e, bufchar)

        return self
Example #11
0
    def osc_message(self, index=0, **kwargs):
        """ Creates an OSC packet to play a SynthDef in SuperCollider,
            use kwargs to force values in the packet, e.g. pan=1 will force ['pan', 1] """

        freq = float(group_modi(self.attr['freq'], index))

        message = ['freq', freq]
        fx_dict = {}

        attributes = self.attr.copy()

        # Go through the attr dictionary and add kwargs

        for key in attributes:

            try:

                # Don't use fx keywords or foxdot keywords

                if key not in FxList.kwargs() and key not in self.keywords:

                    val = group_modi(kwargs.get(key, self.event[key]), index)

                    # Special case modulation

                    if key == "sus":

                        val = val * self.metro.beat_dur() * modi(
                            kwargs.get('blur', self.event['blur']), index)

                    elif key == "amp":

                        val = val * modi(
                            kwargs.get('amplify', self.event['amplify']),
                            index)

                    message += [key, val]

            except KeyError as e:

                WarningMsg("KeyError in function 'osc_message'", key, e)

        # See if any fx_attributes

        for key in self.fx_attributes:

            if key in attributes:

                # All effects use sustain to release nodes

                fx_dict[key] = []

                # Look for any other attributes require e.g. room and verb

                for sub_key in FxList[key].args:

                    if sub_key in self.event:

                        if sub_key in message:

                            i = message.index(sub_key) + 1

                            val = message[i]

                        else:

                            try:

                                val = group_modi(
                                    kwargs.get(sub_key, self.event[sub_key]),
                                    index)

                            except TypeError as e:

                                val = 0

                            except KeyError as e:

                                del fx_dict[key]
                                break

                        # Don't send fx with zero values, unless it is a timevar or playerkey i.e. has a "now" attr

                        if val == 0 and not hasattr(val, 'now'):

                            del fx_dict[key]

                            break

                        else:

                            fx_dict[key] += [sub_key, val]

        return message, fx_dict
Example #12
0
    def sendPlayerMessage(self, synthdef, packet, effects, player=None):
        # Create a bundle
        bundle = OSCBundle()

        # Create a group for the note
        group_id = self.nextnodeID()
        msg = OSCMessage("/g_new")
        msg.append([group_id, 1, 1])
        bundle.append(msg)

        # Get the bus and SynthDef nodes
        this_bus = self.nextbusID()
        this_node = self.nextnodeID()

        # Make sure messages release themselves after 8 * the duration at max (temp)
        i = packet.index('sus') + 1
        max_sus = float(packet[i] * 8)

        # Synth
        msg = OSCMessage("/s_new")

        new_packet = []

        for i in range(0, len(packet), 2):

            try:

                packet[i + 1] = float(packet[i + 1])

            except TypeError as e:

                WarningMsg(
                    "Could not convert '{}' argument '{}' to float. Set to 0".
                    format(packet[i], packet[i + 1]))
                packet[i + 1] = 0.0

        packet = [synthdef, this_node, 0, group_id, 'bus', this_bus] + packet
        msg.append(packet)
        bundle.append(msg)

        # Effects
        for fx in effects:

            this_effect = effects[fx]

            # effects should not have 0 values

            nonzero = True

            for i in range(0, len(this_effect), 2):

                try:

                    val = float(this_effect[i + 1])

                except TypeError as e:

                    WarningMsg(
                        "Could not convert '{}' argument '{}' to float. Set to 0"
                        .format(this_effect[i], this_effect[i + 1]))

                    val = 0

                if val == 0:

                    nonzero = False

                else:

                    this_effect[i + 1] = val

            if nonzero:

                # Get next node ID
                this_node, last_node = self.nextnodeID(), this_node
                msg = OSCMessage("/s_new")
                packet = [
                    self.fx_names[fx], this_node, 1, group_id, 'bus', this_bus
                ] + this_effect
                msg.append(packet)
                bundle.append(msg)

        # Finally, output sound through end node "makeSound"
        msg = OSCMessage("/s_new")
        this_node, last_node = self.nextnodeID(), this_node
        packet = [
            'makeSound', this_node, 1, group_id, 'bus', this_bus, 'sus',
            max_sus
        ]
        msg.append(packet)
        bundle.append(msg)

        return bundle