Ejemplo n.º 1
0
def write_midi(solo=None,
               chords=None,
               outfile="jazzy-bot-solo.mid",
               channel=0,
               tempo=220):
    """
		write a midi file based on solo, a list of Note objects, and chords, a
		list of chord objects
	"""
    assert (solo or chords)
    if solo and chords:
        midi = MIDIFile(2, adjust_origin=False)
        midi.addTempo(0, 0, tempo)
        write_midi_solo(midi, 0, solo, channel)
        write_midi_chords(midi, 1, chords, channel)
    else:
        midi = MIDIFile(1, adjust_origin=False)
        midi.addTempo(0, 0, tempo)
        if solo:
            write_midi_solo(midi, 0, solo, channel)
        elif chords:
            write_midi_chords(midi, 0, chords, channel)
    midi.addKeySignature(0, 0, 1, SHARPS, MAJOR)
    with open(outfile, "wb") as f:
        midi.writeFile(f)
Ejemplo n.º 2
0
    def to_midi_file(self, file):
        midi = MIDIFile(1)
        midi.addTempo(0, 0, self.tempo)
        midi.addTimeSignature(0, 0, self.time_signature[0],
                              int(np.sqrt(self.time_signature[1])), 24)
        if self.key.scale == Scale.MAJOR:
            mode = midiutil.MAJOR
        else:
            mode = midiutil.MINOR
        if self.key.get_circle_of_fifths()[1] == 'Sharps':
            accidental_type = midiutil.SHARPS
        else:
            accidental_type = midiutil.FLATS
        midi.addKeySignature(0, 0,
                             self.key.get_circle_of_fifths()[0],
                             accidental_type, mode)

        for note in self.notes:
            midi.addNote(0, 0, note.pitch.midi_number,
                         note.duration.start_beat * 4,
                         note.duration.total_beat * 4, utils.MIDI_VOLUME)
        with open(file, "wb") as output_file:
            midi.writeFile(output_file)
Ejemplo n.º 3
0
def make_midi(tbon, outfile, firstbar=0, quiet=False, metronome=0):
    """
    Parse and evaluate the source string. Write the output
    to the specified outfile name.

    kwargs:
      transpose -- Number of semitones to transpose the output.
                   May be positive or negative.
      volume -- MIDI track volume
      track  -- Midi file track number
      channel -- MIDI channel number
      octave  -- Initial MIDI octave number (0 - 10)
      numeric -- tbon notation can be either named pitches (cdefgab) or
                 numbers (1234567) with 1 corresponding to 'c'.
    """

    parts = tbon.output
    numparts = len(parts)
    print("Found {} parts".format(numparts))
    metronotes = tbon.metronome_output
    if metronome == 0:
        numTracks = numparts
    elif metronome == 1:
        numTracks = 1
    else:
        numTracks = 1 + numparts
    meta = tbon.meta_output
    beat_map = tbon.beat_map
    MyMIDI = MIDIFile(numTracks,
                      adjust_origin=True,
                      removeDuplicates=False,
                      deinterleave=False)
    #MyMIDI.addTempo(track, 0, tempo)
    trk0 = 0
    for m in meta:
        if m[0] == 'T':
            MyMIDI.addTempo(trk0, m[1], m[2])
        elif m[0] == 'K' and metronome != 1:
            time = m[1]
            sf, mi = m[2]
            track = m[3]
            mode = MINOR if mi == 1 else MAJOR
            accidentals = abs(sf)
            acc_type = SHARPS if sf > 0 else FLATS
            #print("Inserting key signature at time {}".format(time))
            #print(accidentals, acc_type, mode)
            MyMIDI.addKeySignature(track, time, accidentals, acc_type, mode)
        elif m[0] == 'M':
            ## Time signature
            time = m[1]
            numerator = m[2]
            denominator = m[3]
            track = m[4]
            ## midi denominator specified a power of 2
            midi_denom = {2: 1, 4: 2, 8: 3, 16: 4}[denominator]
            ## We want to make the midi metronome match beat duration.
            ## This requires recognizing compound meters
            ## See http://midiutil.readthedocs.io/en/1.1.3/class.html
            ## for discussion of arguments to addTimeSignature()
            ## including clocks_per_tick.
            if denominator == 16 and (numerator % 3 == 0):
                metro_clocks = 18
            elif denominator == 16:
                metro_clocks = 6
            elif denominator == 8 and (numerator % 3 == 0):
                metro_clocks = 36
            elif denominator == 8:
                metro_clocks = 12
            elif denominator == 4:
                metro_clocks = 24
            elif denominator == 2:
                metro_clocks = 48
            MyMIDI.addTimeSignature(track,
                                    time,
                                    numerator,
                                    denominator=midi_denom,
                                    clocks_per_tick=metro_clocks)
        elif m[0] == 'I' and metronome != 1:
            ## Instrument change
            time = m[1]
            instrument = m[2] - 1  ## convert to 0 index
            track = m[3] + 1
            chan = m[4] - 1
            MyMIDI.addProgramChange(track, chan, time, instrument)

    def add_notes(source, trk):
        """ Add all notes in source to trk on chan. """
        for pitch, start, stop, velocity, chan in source:
            if pitch is not None:
                MyMIDI.addNote(trk, chan - 1, pitch, start, stop - start,
                               int(velocity * 127))

    if metronome == 0:
        for track, notes in enumerate(parts):
            add_notes(notes, track)
    elif metronome == 1:
        ## Metronome output only.
        add_notes(metronotes, trk0)
    else:
        ## Both
        for track, notes in enumerate(parts):
            add_notes(notes, track)
        metrotrack = numparts  ## because 0-indexing
        add_notes(metronotes, metrotrack)

    with open(outfile, "wb") as output_file:
        MyMIDI.writeFile(output_file)

    if not quiet:
        for partnum, pmap in beat_map.items():
            print_beat_map(partnum, pmap, first_bar_number=firstbar)