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)
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)
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)