bgr / mingus

Automatically exported from code.google.com/p/mingus
GNU General Public License v3.0
1 stars 1 forks source link

enhancement: accommodate_note() #123

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
The add_notes() function for adding notes to Tracks did not allow for adding 
note durations which would tie into subsequent bars (because the place_notes() 
function for a Bar, without any context of a Track, could not allow it), so I 
wrote a function which will accommodate for values which would not fit into the 
current bar of the track and adds as many bars as needed to fit the value into 
the track. It also updates current_beat so that the next note added will be 
placed at the correct beat. I think the add_notes() function could have some 
issues beyond this limitation, so using this might be a better alternative. If 
any bugs are found please post a comment or solution - the project managers 
haven't communicated with me, so I haven't been able to officially submit a 
contribution.

This is the function, you can copy and paste it into your Track.py file or 
download the attachment and replace the file entirely if you want:

def accommodate_note(self, note, duration = None):
        """Adds the given note to the Track while adding enough bars to the
        track to accommodate the duration value, allowing for notes to tie
        into subsequent bars."""

        if self.instrument != None:
            if not(self.instrument.can_play_notes(note)):
                raise InstrumentRangeError,\
                "Note '%s' is not in range of the instrument (%s)"\
                % (note, self.instrument)

        if duration == None:
            duration = 4

        if len(self.bars) == 0:
            self.bars.append(Bar())
        last_bar = self.bars[-1]

        if self.bars[-1].space_left() != 0:
            # place as much of the duration value as will fit in the bar
            value_left = self.bars[-1].value_left()
            cur_beat = self.bars[-1].current_beat
            self.bars[-1].place_notes(note, value_left)
            value_needed = value.subtract(duration, value_left)
        else:
            cur_beat = self.bars[-1].current_beat
            value_needed = duration

        # save to assign to current_beat at end to properly set up the position the subsequent note entry
        next_beat = 1.0/value_needed

        # add a bar and see how much of the duration value it will accommodate 
        bars_added = 0
        self.add_bar(Bar(self.bars[-1].key, self.bars[-1].meter))
        value_bar = self.bars[-1].value_left()
        bars_added+=1

        # add additional bars as needed to accommodate the duration value
        while 1.0/value_needed > 1.0/value_bar:
            self.add_bar(Bar())
            self.bars[-1].set_meter(self.bars[-2].meter)
            value_needed = value.subtract(value_needed, value_bar)
            bars_added+=1

        # change the note duration now that there are enough bars to fit the full value
        if self.bars[-(bars_added+1)].change_note_duration(cur_beat, duration):
            self.bars[-1].current_beat = next_beat
            return True
        else:
            return False 

Original issue reported on code.google.com by OrtalisM...@gmail.com on 15 May 2013 at 2:50

Attachments: