示例#1
0
 def to_midi(self):
     """
     Constructs a L{MIDI EventStream<midi.EventStream>} from the 
     data in this stream.
     This can then be output to a file to be played.
     
     Note that TPCNotes will be output as normal MIDI notes. We 
     can't do anything of the clever tuning stuff that we can do 
     with tonal space coordinates, since we'd need to do a further 
     step of analysis to work out the fully specified TS point from 
     the pitch class.
     
     """
     tempo = 120
     
     from midi import EventStream, NoteOffEvent, NoteOnEvent, SetTempoEvent
     mid = EventStream()
     mid.add_track()
     # Set the tempo first at the beginning
     temp = SetTempoEvent()
     temp.tempo = tempo
     temp.tick = 0
     mid.add_event(temp)
     # Work out how many ticks there are in a millisecond
     ticks_per_ms = float(mid.resolution) * tempo / 60000
     # Create midi events for every event in our stream
     for ev in self.events:
         if isinstance(ev, TPCNoteEvent):
             # Create note-on and note-off events
             note = ev.note
             
             noteon = NoteOnEvent()
             noteon.pitch = note
             noteon.tick = int(ev.start * ticks_per_ms)
             noteon.velocity = 100
             mid.add_event(noteon)
             
             noteoff = NoteOffEvent()
             noteoff.pitch = note
             noteoff.tick = int(ev.end * ticks_per_ms)
             noteoff.velocity = 100
             mid.add_event(noteoff)
         elif isinstance(ev, (ChordEvent,BeatEvent)):
             # These events don't affect the midi data
             continue
         else:
             raise TypeError, "event type %s not recognised by "\
                 "MIDI converter." % type(ev).__name__
     return mid
示例#2
0
    def to_midi(self):
        """
        Constructs a L{MIDI EventStream<midi.EventStream>} from the 
        data in this stream.
        This can then be output to a file to be played.
        
        Note that TPCNotes will be output as normal MIDI notes. We 
        can't do anything of the clever tuning stuff that we can do 
        with tonal space coordinates, since we'd need to do a further 
        step of analysis to work out the fully specified TS point from 
        the pitch class.
        
        """
        tempo = 120

        from midi import EventStream, NoteOffEvent, NoteOnEvent, SetTempoEvent
        mid = EventStream()
        mid.add_track()
        # Set the tempo first at the beginning
        temp = SetTempoEvent()
        temp.tempo = tempo
        temp.tick = 0
        mid.add_event(temp)
        # Work out how many ticks there are in a millisecond
        ticks_per_ms = float(mid.resolution) * tempo / 60000
        # Create midi events for every event in our stream
        for ev in self.events:
            if isinstance(ev, TPCNoteEvent):
                # Create note-on and note-off events
                note = ev.note

                noteon = NoteOnEvent()
                noteon.pitch = note
                noteon.tick = int(ev.start * ticks_per_ms)
                noteon.velocity = 100
                mid.add_event(noteon)

                noteoff = NoteOffEvent()
                noteoff.pitch = note
                noteoff.tick = int(ev.end * ticks_per_ms)
                noteoff.velocity = 100
                mid.add_event(noteoff)
            elif isinstance(ev, (ChordEvent, BeatEvent)):
                # These events don't affect the midi data
                continue
            else:
                raise TypeError, "event type %s not recognised by "\
                    "MIDI converter." % type(ev).__name__
        return mid
示例#3
0
 def copy_event(event):
     if type(event) is SetTempoEvent:
         new_event = SetTempoEvent()
         new_event.tick = event.tick
         new_event.data[0] = event.data[0]
         new_event.data[1] = event.data[1]
         new_event.data[2] = event.data[2]
         return new_event
     elif type(event) is NoteOnEvent:
         new_event = NoteOnEvent()
         new_event.tick = event.tick
         new_event.channel = event.channel
         new_event.data[0] = event.data[0]
         new_event.data[1] = event.data[1]
         return new_event
     elif type(event) is NoteOffEvent:
         new_event = NoteOffEvent()
         new_event.tick = event.tick
         new_event.channel = event.channel
         new_event.data[0] = event.data[0]
         new_event.data[1] = event.data[1]
         return new_event
     elif type(event) is ProgramChangeEvent:
         new_event = ProgramChangeEvent
         new_event.tick = event.tick
         new_event.channel = event.channel
         new_event.data[0] = event.data[0]
         return new_event
     else:
         raise ('Not Supported')
示例#4
0
def tonal_space_note_events(coord,
                            start,
                            duration,
                            origin_note=60,
                            velocity=100):
    """
    Creates the MIDI events needed to play the given tonal space 
    coordinate. These will be a single-note tuning event (to retune 
    the appropriate note), a note-on event and a note-off event.
    
    @type coord: tuple
    @param coord: 3D tonal space coordinate
    @type start: int
    @param start: start time of note in ticks
    @type duration: int
    @param duration: length of the note in ticks
    @type origin_note: int
    @param origin_note: midi note number to assume the origin of the 
      tonal space is equal to in pitch (default 60, middle C)
    @rtype: tuple
    @return: (tuning event, note on event, note off event)
    
    """
    # Work out what note to retune for the root and how
    change = tonal_space_tuning(coord)
    note = change[0]

    # Create the tuning event
    tuning = single_note_tuning_event([change])
    tuning.tick = start
    # Play the note
    note_on = NoteOnEvent()
    note_on.pitch = note
    note_on.velocity = velocity
    note_on.tick = start
    # Stop the note
    note_off = NoteOffEvent()
    note_off.pitch = note
    note_off.tick = start + duration
    note_off.velocity = velocity

    return (tuning, note_on, note_off)
示例#5
0
 def add_note_on_abs(track,
                     pitch,
                     start,
                     loudness,
                     channel,
                     resolution=default_resolution):
     on = NoteOnEvent(tick=int(resolution * start),
                      channel=channel,
                      velocity=loudness,
                      pitch=pitch)
     track.append(on)
     return track
示例#6
0
def tonal_space_note_events(coord, start, duration, origin_note=60, velocity=100):
    """
    Creates the MIDI events needed to play the given tonal space 
    coordinate. These will be a single-note tuning event (to retune 
    the appropriate note), a note-on event and a note-off event.
    
    @type coord: tuple
    @param coord: 3D tonal space coordinate
    @type start: int
    @param start: start time of note in ticks
    @type duration: int
    @param duration: length of the note in ticks
    @type origin_note: int
    @param origin_note: midi note number to assume the origin of the 
      tonal space is equal to in pitch (default 60, middle C)
    @rtype: tuple
    @return: (tuning event, note on event, note off event)
    
    """
    # Work out what note to retune for the root and how
    change = tonal_space_tuning(coord)
    note = change[0]
    
    # Create the tuning event
    tuning = single_note_tuning_event([change])
    tuning.tick = start
    # Play the note
    note_on = NoteOnEvent()
    note_on.pitch = note
    note_on.velocity = velocity
    note_on.tick = start
    # Stop the note
    note_off = NoteOffEvent()
    note_off.pitch = note
    note_off.tick = start+duration
    note_off.velocity = velocity
    
    return (tuning, note_on, note_off)
示例#7
0
    def generate(self, overlay=None, offset=0):
        """
        Generates a midi stream.
        
        """
        octaves = 1

        if overlay is not None:
            stream = overlay
            # Use organ sound
            instrument = 23
            # Find the last channel used in the file we're overlaying
            channel = max(ev.channel for ev in stream.trackpool) + 1
            volume = 50
        else:
            stream = EventStream()
            stream.resolution = self.resolution
            # Just use piano
            instrument = 0
            channel = 0
            volume = 127

        stream.add_track()
        pc = ProgramChangeEvent()
        pc.value = instrument
        pc.tick = 0
        pc.channel = channel
        stream.add_event(pc)

        # Length of each chord in midi ticks
        chord_length = int(self.resolution * self.chord_length)

        times = [i * chord_length + offset for i in range(len(self.labels))]

        pending_note_offs = []
        for label, time in zip(self.labels, times):
            chord_root = label.root
            # Work out the notes for this chord
            triad_notes = [(chord_root + note) % (octaves*12) + 72 for \
                                        note in self.chord_vocab[label.label]]
            # Add the root in the octave two below
            triad_notes.append(chord_root + 48)

            # Add note offs for notes already on
            for noff in pending_note_offs:
                noff.tick = time - 1
                stream.add_event(noff)
            pending_note_offs = []

            if self.text_events:
                # Add a text event to represent the chord label
                tevent = LyricsEvent()
                tevent.data = "%s\n" % label
                tevent.tick = time
                stream.add_event(tevent)

            # Add a note-on and off event for each note
            for note in triad_notes:
                non = NoteOnEvent()
                non.tick = time
                non.pitch = note
                non.channel = channel
                non.velocity = volume
                stream.add_event(non)

                # Hold the note until the next chord is played
                noff = NoteOffEvent()
                noff.pitch = note
                noff.channel = channel
                noff.velocity = volume
                pending_note_offs.append(noff)

        # Add the last remaining note offs
        for noff in pending_note_offs:
            noff.tick = time + chord_length
            stream.add_event(noff)
        return stream
示例#8
0
 def generate(self, overlay=None, offset=0):
     """
     Generates a midi stream.
     
     """
     octaves = 1
     
     if overlay is not None:
         stream = overlay
         # Use organ sound
         instrument = 23
         # Find the last channel used in the file we're overlaying
         channel = max(ev.channel for ev in stream.trackpool) + 1
         volume = 50
     else:
         stream = EventStream()
         stream.resolution = self.resolution
         # Just use piano
         instrument = 0
         channel = 0
         volume = 127
     
     stream.add_track()
     pc = ProgramChangeEvent()
     pc.value = instrument
     pc.tick = 0
     pc.channel = channel
     stream.add_event(pc)
     
     # Length of each chord in midi ticks
     chord_length = int(self.resolution * self.chord_length)
     
     times = [i*chord_length + offset for i in range(len(self.labels))]
     
     pending_note_offs = []
     for label,time in zip(self.labels, times):
         chord_root = label.root
         # Work out the notes for this chord
         triad_notes = [(chord_root + note) % (octaves*12) + 72 for \
                                     note in self.chord_vocab[label.label]]
         # Add the root in the octave two below
         triad_notes.append(chord_root + 48)
         
         # Add note offs for notes already on
         for noff in pending_note_offs:
             noff.tick = time-1
             stream.add_event(noff)
         pending_note_offs = []
         
         if self.text_events:
             # Add a text event to represent the chord label
             tevent = LyricsEvent()
             tevent.data = "%s\n" % label
             tevent.tick = time
             stream.add_event(tevent)
         
         # Add a note-on and off event for each note
         for note in triad_notes:
             non = NoteOnEvent()
             non.tick = time
             non.pitch = note
             non.channel = channel
             non.velocity = volume
             stream.add_event(non)
             
             # Hold the note until the next chord is played
             noff = NoteOffEvent()
             noff.pitch = note
             noff.channel = channel
             noff.velocity = volume
             pending_note_offs.append(noff)
     
     # Add the last remaining note offs
     for noff in pending_note_offs:
         noff.tick = time+chord_length
         stream.add_event(noff)
     return stream
示例#9
0
    def generate(self, overlay=None, offset=0):
        """
        Generates a midi stream.
        
        """
        octaves = 1

        if overlay is not None:
            stream = overlay
            # Use organ sound
            instrument = 23
            # Find the last channel used in the file we're overlaying
            channel = max(ev.channel for ev in stream.trackpool) + 1
            volume = 30
        else:
            stream = EventStream()
            stream.resolution = self.resolution
            # Just use piano
            instrument = 0
            channel = 0
            volume = 127
        stream.add_track()
        pc = ProgramChangeEvent()
        pc.value = instrument
        pc.tick = 0
        pc.channel = channel
        stream.add_event(pc)
        # Length of each chord in midi ticks
        chord_length = int(self.resolution * self.chord_length)

        if self.times is None:
            times = [
                i * chord_length + offset for i in range(len(self.labels))
            ]
        else:
            times = [t + offset for t in self.times]

        formatter = getattr(self, 'formatter')

        pending_note_offs = []
        for (tonic, mode, chord), time in zip(self.labels, times):
            scale_chord_root = constants.CHORD_NOTES[mode][chord][0]
            chord_root = (tonic + scale_chord_root) % 12
            triad_type = constants.SCALE_TRIADS[mode][chord]
            # Work out the notes for this chord
            triad_notes = [(chord_root + note) % (octaves * 12) + 72
                           for note in constants.TRIAD_NOTES[triad_type]]
            # Add the root in the octave two below
            triad_notes.append(chord_root + 48)

            # Add note offs for notes already on
            for noff in pending_note_offs:
                noff.tick = time - 1
                stream.add_event(noff)
            pending_note_offs = []

            if self.text_events:
                # Add a text event to represent the chord label
                tevent = LyricsEvent()
                label = formatter((tonic, mode, chord))
                tevent.data = "%s\n" % label
                tevent.tick = time
                stream.add_event(tevent)

            # Add a note-on and off event for each note
            for note in triad_notes:
                non = NoteOnEvent()
                non.tick = time
                non.pitch = note
                non.channel = channel
                non.velocity = volume
                stream.add_event(non)

                # Hold the note until the next chord is played
                noff = NoteOffEvent()
                noff.pitch = note
                noff.channel = channel
                noff.velocity = volume
                pending_note_offs.append(noff)

        # Add the last remaining note offs
        for noff in pending_note_offs:
            noff.tick = time + chord_length
            stream.add_event(noff)
        return stream
示例#10
0
 def generate(self, overlay=None, offset=0):
     """
     Generates a midi stream.
     
     """
     octaves = 1
     
     if overlay is not None:
         stream = overlay
         # Use organ sound
         instrument = 23
         # Find the last channel used in the file we're overlaying
         channel = max(ev.channel for ev in stream.trackpool) + 1
         volume = 30
     else:
         stream = EventStream()
         stream.resolution = self.resolution
         # Just use piano
         instrument = 0
         channel = 0
         volume = 127
     stream.add_track()
     pc = ProgramChangeEvent()
     pc.value = instrument
     pc.tick = 0
     pc.channel = channel
     stream.add_event(pc)
     # Length of each chord in midi ticks
     chord_length = int(self.resolution * self.chord_length)
     
     if self.times is None:
         times = [i*chord_length + offset for i in range(len(self.labels))]
     else:
         times = [t+offset for t in self.times]
     
     formatter = getattr(self, 'formatter')
     
     pending_note_offs = []
     for (tonic,mode,chord),time in zip(self.labels, times):
         scale_chord_root = constants.CHORD_NOTES[mode][chord][0]
         chord_root = (tonic+scale_chord_root) % 12
         triad_type = constants.SCALE_TRIADS[mode][chord]
         # Work out the notes for this chord
         triad_notes = [(chord_root + note) % (octaves*12) + 72 for note in constants.TRIAD_NOTES[triad_type]]
         # Add the root in the octave two below
         triad_notes.append(chord_root + 48)
         
         # Add note offs for notes already on
         for noff in pending_note_offs:
             noff.tick = time-1
             stream.add_event(noff)
         pending_note_offs = []
         
         if self.text_events:
             # Add a text event to represent the chord label
             tevent = LyricsEvent()
             label = formatter((tonic,mode,chord))
             tevent.data = "%s\n" % label
             tevent.tick = time
             stream.add_event(tevent)
         
         # Add a note-on and off event for each note
         for note in triad_notes:
             non = NoteOnEvent()
             non.tick = time
             non.pitch = note
             non.channel = channel
             non.velocity = volume
             stream.add_event(non)
             
             # Hold the note until the next chord is played
             noff = NoteOffEvent()
             noff.pitch = note
             noff.channel = channel
             noff.velocity = volume
             pending_note_offs.append(noff)
     
     # Add the last remaining note offs
     for noff in pending_note_offs:
         noff.tick = time+chord_length
         stream.add_event(noff)
     return stream