def test_one_text_column(): ''' A data frame with a single integer column should be converted correctly. ''' expected = MIDIFile(1) expected.addTrackName(0,0,"vocals") expected.addTempo(0,0,120) for time,note in enumerate([38, 40, 42, 43]): expected.addNote(0,0,note,time,1,100) df = pandas.DataFrame([ {'vocals':'badger'}, {'vocals':'badger'}, {'vocals':'badger'}, {'vocals':'badger'}, {'vocals':'badger'}, {'vocals':'badger'}, {'vocals':'badger'}, {'vocals':'mushroom'}, {'vocals':'mushroom'}, ]) observed = df_to_midi(df, bpm = 120) n.assert_equal(observed, expected)
def playMIDI(x,counter,counter2, O): from midiutil.MidiFile import MIDIFile MyMIDI=MIDIFile(1, removeDuplicates=False, deinterleave=False) track=0 time=0 MyMIDI.addTrackName(track,time,"Sample") MyMIDI.addTempo(track,time,60) track=0 channel=0 a=North[x] b=East[x] c=West[x] averagex=round(((a+b+c)/3),0) pitchcalc=pitchnum(averagex) pitch=pitchcalc timecalc,O=deltatime(counter, O) time=2 duration=timecalc if counter2==0: volume=10*(int(round(math.pow(North[x],1.0/3)))) elif counter2==1: volume=10*(int(round(math.pow(East[x],1.0/3)))) elif counter2==2: volume=10*(int(round(math.pow(West[x],1.0/3)))) else: print("numcount error", counter2) volume=127 MyMIDI.addNote(track,channel,pitch,time,duration,volume) outcount=str(counter) numcount=str(counter2) binfile=open(outpath+"/output "+outcount+" "+numcount+".mid",'wb') MyMIDI.writeFile(binfile) print(counter,"\n",track,channel,pitch,time,duration,volume) binfile.close() return O
def matrix_to_midi(notes, filename = 'matrix.mid', tempo = 60): """ Simplify midi generation note format: PITCH|START|DURATION|VOLUME """ # Midi file with one track mf = MIDIFile(1) track = 0 time = 0 mf.addTrackName(track, time, filename[7:-4]) # Default # FIXME tempo -- time relation is not well defined mf.addTempo(track, time, tempo) channel = 0 time_per_tick = 2**-5 for note in notes: pitch = note[0] start = note[1] * time_per_tick stop = note[2] * time_per_tick vol = note[3] mf.addNote(track, channel, pitch, start, stop, vol) # Save as file with open(filename, 'wb') as fout: mf.writeFile(fout)
class MidiFileOut: def __init__(self, numtracks = 16): self.score = MIDIFile(numtracks) self.track = 0 self.channel = 0 self.volume = 64 self.time = 0 def tick(self, ticklen): self.time += ticklen def noteOn(self, note = 60, velocity = 64, channel = 0, duration = 1): #------------------------------------------------------------------------ # avoid rounding errors #------------------------------------------------------------------------ time = round(self.time, 5) self.score.addNote(channel, channel, note, time, duration, velocity) def noteOff(self, note = 60, channel = 0): pass def writeFile(self, filename = "score.mid"): fd = open(filename, 'wb') self.score.writeFile(fd) fd.close()
class PatternWriterMIDI: def __init__(self, numtracks = 1): self.score = MIDIFile(numtracks) self.track = 0 self.channel = 0 self.volume = 64 def addTrack(self, pattern, tracknumber = 0, trackname = "track", dur = 1.0): time = 0 # naive approach: assume every duration is 1 # TODO: accept dicts or PDicts for note in pattern: if note is not None: self.score.addNote(tracknumber, self.channel, note, time, dur, self.volume) time += dur else: time += dur def addTimeline(self, timeline): # TODO: translate entire timeline into MIDI # difficulties: need to handle degree/transpose params # need to handle channels properly, and reset numtracks pass def writeFile(self, filename = "score.mid"): fd = open(filename, 'wb') self.score.writeFile(fd) fd.close()
class MidiFileOut: """ Write events to a MIDI file. Requires the MIDIUtil package: https://code.google.com/p/midiutil/ """ def __init__(self, filename = "score.mid", num_tracks = 16): from midiutil.MidiFile import MIDIFile self.filename = filename self.score = MIDIFile(num_tracks) self.time = 0 def tick(self, tick_length): self.time += tick_length def note_on(self, note = 60, velocity = 64, channel = 0, duration = 1): #------------------------------------------------------------------------ # avoid rounding errors #------------------------------------------------------------------------ time = round(self.time, 5) self.score.addNote(channel, channel, note, time, duration, velocity) def note_off(self, note = 60, channel = 0): time = round(self.time, 5) self.score.addNote(channel, channel, note, time, 0, 0) def write(self): fd = open(self.filename, 'wb') self.score.writeFile(fd) fd.close()
def saveMIDI(filename, noteOnsets, melody, tempo, Fs, hopSize): barOnsets = (noteOnsets*hopSize/float(Fs))*(tempo/60) #Onsets dado en barra notes = quantizeNote(melody) track = 0 time = 0 MIDI = MIDIFile(1) # Add track name and tempo. MIDI.addTrackName(track,time,"MIDI TRACK") MIDI.addTempo(track,time,tempo) channel = 0 volume = 100 for i in range(np.size(barOnsets)): pitch = notes[noteOnsets[i]+1] #leer el pitch en el siguiente frame al onset if pitch > 0: time = barOnsets[i] if i == np.size(barOnsets)-1: duration = 1 else: duration = barOnsets[i+1]-barOnsets[i] MIDI.addNote(track,channel,pitch,time,duration,volume) # And write it to disk. binfile = open(filename, 'wb') MIDI.writeFile(binfile) binfile.close()
class PatternWriterMIDI: def __init__(self, numtracks = 1): self.score = MIDIFile(numtracks) self.track = 0 self.channel = 0 self.volume = 64 def addTrack(self, pattern, tracknumber = 0, trackname = "track", dur = 1.0): time = 0 # naive approach: assume every duration is 1 # TODO: accept dicts or PDicts try: for note in pattern: vdur = Pattern.value(dur) if note is not None and vdur is not None: self.score.addNote(tracknumber, self.channel, note, time, vdur, self.volume) time += vdur else: time += vdur except StopIteration: # a StopIteration exception means that an input pattern has been exhausted. # catch it and treat the track as completed. pass def addTimeline(self, timeline): # TODO: translate entire timeline into MIDI # difficulties: need to handle degree/transpose params # need to handle channels properly, and reset numtracks pass def writeFile(self, filename = "score.mid"): fd = open(filename, 'wb') self.score.writeFile(fd) fd.close()
def midFile(melody): MyMIDI = MIDIFile(1) track = 0 time = 0 MyMIDI.addTrackName(track, time, "Vireo") MyMIDI.addTempo(track, time, 340) track = 0 channel = 0 time = 0 volume = 100 for i in melody: data = i.split() MyMIDI.addNote(track, channel, int(data[0].strip()), time, int(data[1].strip()), volume) time = time + int(data[1].strip()) midi = "" binfile = open("./static/test.mid", "wb") MyMIDI.writeFile(binfile) binfile.close() binfile = open("./static/test.mid", "rb") midi = binfile.read() binfile.close() return midi
class Generator: def __init__(self, tempo = 120): self.midi_file = MIDIFile(1) self.midi_file.addTrackName(0, 0, "track") self.midi_file.addTempo(0, 0, tempo) self.current_time = 1 def add_pause(self, length = 1): self.current_time = self.current_time + length def add_chord(self, base, notes, length = 1): for note in notes: self.midi_file.addNote(0, 0, base + note, self.current_time, length, VOLUME_TABLE[len(notes)]) self.add_pause(length) def add_pattern(self, base, pattern): for item in pattern: length = item[len(item) - 1] self.add_chord(base, item[0 : len(item) - 1], length) def write(self, filename): output_file = open(filename, 'wb') self.midi_file.writeFile(output_file) output_file.close()
def MidiFileCreator(melody,song): bpm = melody['bpm'] pitches = melody['pitches'] parts = [t.split('.') for t in melody['times']] times = [4*int(l)+int(r)-1 for l,r in parts] durations = melody['durations'] chord_pitches = song['chord_pitches'] chord_times = song['chord_times'] chord_center = song['chord_center'] ListOfRelativeChordVoicings = song['chord_pitches'] token = melody['token'] MyMIDI = MIDIFile(1) track = 0 channel = 0 time = 0 duration = 4 volume = 100 MyMIDI.addTrackName(track,time,"Herp derp") MyMIDI.addTempo(track,time,bpm) #Sends Chords to MIDI root = int(chord_center) for chord in ListOfRelativeChordVoicings: for note in chord: Intnote = int(note + root) MyMIDI.addNote(track,channel,Intnote,time,duration,volume) time = time + 4 for note,time in zip(pitches,times): MyMIDI.addNote(track,channel,int(note),int(time),1,volume) binfile = open(base + "static/songs/" + token + ".mid", 'wb') MyMIDI.writeFile(binfile) binfile.close() return "blah"
def write_midi_file(self, file_object): """Writes midi generated from this tab to the given file object.""" # Throw an exception if there are note names for which we can't # determine the proper note numbers. unmappable_note_names = self.note_types.difference( self.note_name_to_number_map.keys()) if unmappable_note_names: raise UnmappableNoteNamesException(unmappable_note_names) midifile = MIDIFile(1) track = 0 channel = 9 duration = round(4.0 / self.divisions_in_bar, 10) # 4.0 is because midiutil's unit of time is the quarter note. midifile.addTrackName(track, 0, "") midifile.addTempo(track, 0, self._bpm) for note in self.walk_notes(): strike_type = note['strike_type'] volume = self._volume_for_strke_type(strike_type) if strike_type == 'r': pitch = GM_SPEC_NOTE_NAME_TO_NUMBER_MAP['Sticks'] else: pitch = self.note_name_to_number_map[note['note_type']] midifile.addNote(track, channel, pitch, note['time'], duration, volume) midifile.writeFile(file_object)
def play(request): global outputId json = simplejson.loads(request.POST.get('notes')) midiFile = MIDIFile(1) track = 0 time = 0 midiFile.addTrackName(track, time, "Sample Track") midiFile.addTempo(track, time, 120) channel = 0 volume = 100 string = "" for note in json['notes']: pitch = strToMidiPitch(note['pitch']) duration = note['duration'] start = note['start'] midiFile.addNote(track, channel, pitch, start, duration, volume) string += "added note " + note['pitch'] + ": " + str(pitch) + ", " binfile = open("/tmp/output.mid", 'wb') midiFile.writeFile(binfile) binfile.close() call(['fluidsynth', '-l', '-F', '/tmp/output_'+str(outputId)+'.wav', '/usr/share/sounds/sf2/FluidR3_GM.sf2', '/tmp/output.mid']) call(['lame', '--preset', 'standard', '/tmp/output_'+str(outputId)+'.wav', '/tmp/output_'+str(outputId)+'.mp3']) outputId += 1 return HttpResponse(outputId-1)
def convert_to_song(file_name): mf = MIDIFile(1) track = 0 time = 0 mf.addTempo(track, time, 240) channel = 0 volume = 100 file_loc = os.path.join(os.getcwd(), file_name+'.csv') with open(file_loc, "rb") as csvfile: reader = csv.reader(csvfile) reader = list(reader) """ row_count = sum(1 for row in reader) for i in range(1, row_count): print reader[i] """ i = 1 while i < len(reader): #for i in range(1, len(reader)): close = reader[i][4] pitch = get_pitch(float(close)) time += 1 duration = 1 mf.addNote(track, channel, pitch, time, duration, volume) i += 20 #print i with open('static/' + file_name + '.mid', 'wb') as outf: mf.writeFile(outf) outf.close()
class FileOutput(Output): url_example = "file://foo.mid" def __init__(self, url): Output.__init__(self) outfile = url.netloc + url.path if not outfile: print "file:// output needs a filename" raise ValueError("File output needs a filename") log.info("Opening File output: %s", outfile) self.midi = MIDIFile(1) self.midi.addTrackName(0, 0, "Mic2Mid Track 0") self.midi.addTempo(0, 0, 60) self.midi.addProgramChange(0, 0, 0, 27) self.start = time.time() self.filename = outfile def close(self): Output.close(self) log.info("Closing File output: %s", self.filename) fp = open(self.filename, "wb") self.midi.writeFile(fp) fp.close() def note_on(self, note): self.midi.addNote(0, 0, self.note_to_midi(note), time.time() - self.start, 1, 100)
def savefile(self): """Construct MIDI file and save""" global pad_records, instrument, pitch MyMIDI = MIDIFile(1) MyMIDI.addTempo(0, 0, 600) for i in range(0, total_pads): print len(pad_records["pad{0}".format(i+1)]) MyMIDI.addProgramChange(0, i, 0, instrument[i]) # set channel instrument print instrument[i] for j in range(0, len(pad_records["pad{0}".format(i+1)])): # print pad_records["pad{0}".format(i+1)][j]/8 if j == 0: MyMIDI.addNote(0, i, pitch[i], 0, len(pad_records["pad{0}".format(i+1)]), pad_records["pad{0}".format(i+1)][j]/8) print "ch" + str(i) + " pitch: " + str(pitch[i]) + " vol:" + str(pad_records["pad{0}".format(i+1)][j]/8) else: MyMIDI.addControllerEvent(0, i, j, 0x07, pad_records["pad{0}".format(i+1)][j]/8) print " vol:" + str(pad_records["pad{0}".format(i+1)][j]/8) filename = self.browse_filepath.get() + "/" + self.saveFileName.get() # try: binfile = open(filename, 'wb') MyMIDI.writeFile(binfile) binfile.close() print "saved"
class Midi: """Musique midi""" def __init__(self, partition, titre, tempo): # Définition des paramètres MIDI. piste = 0 temps = 0 self.tempo = tempo / 2 self.sortiemidi = MIDIFile(1, file_format=1) # Nom de la piste. self.sortiemidi.addTrackName(piste, temps, sansaccents(titre)) # Tempo. self.sortiemidi.addTempo(piste, temps, self.tempo) # Instrument (74 : flûte). self.sortiemidi.addProgramChange(piste, 0, temps, 74) self.traiter_partition(partition, piste, temps) def traiter_partition(self, partition, piste, temps): """Création des évènements MIDI""" transposition = partition.transposition channel = 0 volume = 127 for mot in partition: for i, syllabe in enumerate(mot): syl = str(syllabe) if i + 1 < len(mot): syl = syl + '-' for j, note in enumerate( notes for notes in syllabe.musique if isinstance(notes, Note) ): pitch = note.hauteur + transposition duree = int(note.duree) self.sortiemidi.addTempo( piste, temps, (self.tempo * duree / note.duree) ) self.sortiemidi.addNote( piste, channel, pitch, temps, duree / 2, volume ) if j == 0: self.sortiemidi.addText( piste, temps, syl ) temps += duree / 2 def ecrire(self, chemin): """Écriture effective du fichier MIDI""" with ( open(sys.stdout.fileno(), 'wb') if chemin == '-' else open(chemin, 'wb') ) as sortie: self.sortiemidi.writeFile(sortie)
def testAddNote(self): MyMIDI = MIDIFile(1) MyMIDI.addNote(0, 0, 100, 0, 1, 100) self.assertEquals(MyMIDI.tracks[0].eventList[0].type, "note") self.assertEquals(MyMIDI.tracks[0].eventList[0].pitch, 100) self.assertEquals(MyMIDI.tracks[0].eventList[0].time, 0) self.assertEquals(MyMIDI.tracks[0].eventList[0].duration, 1) self.assertEquals(MyMIDI.tracks[0].eventList[0].volume, 100)
class midiFile: """ Allows MIDI files to be gradually built up. On creation, a MIDI file track is created, and notes are added through calls to addNote. The file can be saved through a call to writeFile. More information on the library being used at: http://www.emergentmusics.org/mididutil-class-reference """ def __init__(self, trackName, maxPackageDepth, bpm): self.state = MIDIFile(1) #Number of tracks. self.time = 0 self.track = 0 self.state.addTempo(self.track,self.time,bpm) self.maxPackageDepth = maxPackageDepth self.minPitch = 0 self.maxPitch = 127 def setPitchRange(self, min, max): """ Set the range (somewhere between 0-127) that will be used in assigning pitch to notes, which is based on package depth. """ self.minPitch = min self.maxPitch = max def addNote(self, depth, instrument, duration): """ Adds a new note to the MIDI file. Increments the time by 1 on addition of every note. depth: Package structure depth. Used to determine the pitch of the note. instrument: Number from 0-127 (see: http://en.wikipedia.org/wiki/General_MIDI#Program_change_events) duration: Number of beats note should be played over. """ channel = 0 pitch = getPitch(depth, self.maxPackageDepth, self.minPitch, self.maxPitch) volume = 127 logging.info("Adding note, with instrument {0}, pitch {1}, duration {2}".format(instrument, pitch, duration)) self.state.addProgramChange(self.track,channel, self.time, instrument) self.state.addNote(0,channel,pitch,self.time,duration,volume) self.time+=1 def writeFile(self, savePath): """ Write the current state of the MIDI file to disk. savePath: Name+Path of the MIDI file to be saved. """ binfile = open(savePath, 'wb') self.state.writeFile(binfile) binfile.close()
def run(self): inputObj = self.get_input("input") #obiekt interfejsu wejściowego outputGraph = self.get_output("outputGraph") #obiekt interfejsu wyjściowego outputPitch = self.get_output("outputPitch") #obiekt interfejsu wyjściowego prev_note = 0 #init midi track = 0 time = 0 MyMIDI = MIDIFile(1) MyMIDI.addTrackName(track,time,"Sample Track") MyMIDI.addTempo(track,time,120) try: while self.running(): data_input = inputObj.read() N = data_input["N"] audioData = base64.b64decode(data_input["data"]) MAX_y = data_input["MAX_y"] y = np.array(struct.unpack("%dh" % (N * CHANNELS), audioData)) / MAX_y y_L = y[::2] y_R = y[1::2] Y_L = np.fft.fft(y_L, nFFT) Y_R = np.fft.fft(y_R, nFFT) # Łączenie kanałów FFT, DC - prawy kanał Y = abs(np.hstack((Y_L[-nFFT/2:-1], Y_R[:nFFT/2]))) samples = np.fromstring(audioData, dtype=np.int16) #wyliczenie dzwieku rawnote = analyse.musical_detect_pitch(samples) if rawnote is not None: note = np.rint(rawnote) #wyślij nutę na wyjście outputPitch.send(note) if note != prev_note: #MyMIDI.addNote(track,channel,pitch,time,duration,volume) MyMIDI.addNote(0,0,note,time,1,100) time+=1 prev_note = note output = {"db_table": list(Y)} outputGraph.send(output) #save midi on exit except: binfile = open("output.mid", 'wb') MyMIDI.writeFile(binfile) binfile.close()
def write(predicted, min_pitch): from midiutil.MidiFile import MIDIFile m = MIDIFile(1) m.addTempo(0, 0, 70) for t, pitches in enumerate(predicted.T): for i, on in enumerate(pitches): note = i + min_pitch if on: m.addNote(0, 0, note, t / 8.0, 1 / 8.0, 100) with open('out.mid', 'wb') as f: m.writeFile(f)
def testDeinterleaveNotes(self): MyMIDI = MIDIFile(1) MyMIDI.addNote(0, 0, 100, 0, 2, 100) MyMIDI.addNote(0, 0, 100, 1, 2, 100) MyMIDI.close() self.assertEquals(MyMIDI.tracks[0].MIDIEventList[0].type, "NoteOn") self.assertEquals(MyMIDI.tracks[0].MIDIEventList[0].time, 0) self.assertEquals(MyMIDI.tracks[0].MIDIEventList[1].type, "NoteOff") self.assertEquals(MyMIDI.tracks[0].MIDIEventList[1].time, 128) self.assertEquals(MyMIDI.tracks[0].MIDIEventList[2].type, "NoteOn") self.assertEquals(MyMIDI.tracks[0].MIDIEventList[2].time, 0) self.assertEquals(MyMIDI.tracks[0].MIDIEventList[3].type, "NoteOff") self.assertEquals(MyMIDI.tracks[0].MIDIEventList[3].time, 256)
def create_midi(frequency): my_midi = MIDIFile(1) track = 0 channel = 0 pitch = 69 + 12 * log(max(frequency) / 440, 2) time = 0 duration = 1 volume = 100 my_midi.addTempo(track, time, 120) my_midi.addNote(track, channel, pitch, time, duration, volume) return my_midi
def WriteMidi(notes, tempo, file): MyMIDI = MIDIFile(1) MyMIDI.addTrackName(0,0,"Sample Track") MyMIDI.addTempo(0,0,tempo) time= 0 for (name, d, length) in notes: MyMIDI.addNote(0,0,60,time,length*4,100) time+= length*4 binfile = open(file, 'wb') MyMIDI.writeFile(binfile) binfile.close()
def main(argv=None): if argv is None: argv = sys.argv txtFileName = argv[1] txtFile = open(txtFileName, 'r') charsForNotes = txtFile.read() txtFile.close() #Setup default values rootNote = 0; track = 0 time = 0 tempo = 120 channel = 0 duration = 1 volume = 100 midiFile = MIDIFile(12) midiFile.addTrackName(0, time, "1") midiFile.addTrackName(1, time, "2") midiFile.addTrackName(2, time, "3") midiFile.addTrackName(3, time, "4") midiFile.addTrackName(4, time, "5") midiFile.addTempo(track, time, tempo) i = 0 while(i < len(charsForNotes)): j = 0 #double every 4th beat durationMult = (i%4 == 0) + 1 while(j < 5): pitch = pickPitch(charsForNotes[i], rootNote+(12*j)) if charsForNotes[i] is ' ': midiFile.addNote(j, channel, pitch, time, duration*durationMult, 0) else: midiFile.addNote(j, channel, pitch, time, duration*durationMult, volume) j += 1 time += 1 i += 1 mFile = open("mozart.mid", 'wb') midiFile.writeFile(mFile) mFile.close()
def write_midi(filename, sequence): filename = "music/"+filename midi = MIDIFile(1) track = 0 start_time = 0 midi.addTrackName(track, start_time, filename[:-4]) tempo = random.randrange(120, 480) midi.addTempo(track, start_time, tempo) for seq in range(len(sequence)): for note in sequence[seq]: midi.addNote(track, 9, note.pitch, note.time, note.duration, note.volume) # midi.addProgramChange(0, seq, 0, instrList[seq]) f = open(filename, 'w') midi.writeFile(f) f.close()
def createWav(word_lengths): note_lengths = map(wordlen_to_notelen, word_lengths) print note_lengths note_library = notes('c', 'major') print note_library MyMIDI = MIDIFile(1) MyMIDI.addTempo(0,0,120) total = 0.0 for d in note_lengths: MyMIDI.addNote(0,0,int(note_library[random.randint(0,7)]),total,d,100) total += d binfile = open("output.mid", 'wb') MyMIDI.writeFile(binfile) binfile.close()
def testTimeShift(self): # With one track MyMIDI = MIDIFile(1) MyMIDI.addNote(0, 0, 100, 5, 1, 100) MyMIDI.close() self.assertEquals(MyMIDI.tracks[0].MIDIEventList[0].type, "NoteOn") self.assertEquals(MyMIDI.tracks[0].MIDIEventList[0].time, 0) self.assertEquals(MyMIDI.tracks[0].MIDIEventList[1].type, "NoteOff") self.assertEquals(MyMIDI.tracks[0].MIDIEventList[1].time, 128) # With two tracks MyMIDI = MIDIFile(2) MyMIDI.addNote(0, 0, 100, 5, 1, 100) MyMIDI.addNote(1, 0, 100, 6, 1, 100) MyMIDI.close() self.assertEquals(MyMIDI.tracks[0].MIDIEventList[0].type, "NoteOn") self.assertEquals(MyMIDI.tracks[0].MIDIEventList[0].time, 0) self.assertEquals(MyMIDI.tracks[0].MIDIEventList[1].type, "NoteOff") self.assertEquals(MyMIDI.tracks[0].MIDIEventList[1].time, 128) self.assertEquals(MyMIDI.tracks[1].MIDIEventList[0].type, "NoteOn") self.assertEquals(MyMIDI.tracks[1].MIDIEventList[0].time, 128) self.assertEquals(MyMIDI.tracks[1].MIDIEventList[1].type, "NoteOff") self.assertEquals(MyMIDI.tracks[1].MIDIEventList[1].time, 128) # Negative Time MyMIDI = MIDIFile(1) MyMIDI.addNote(0, 0, 100, -5, 1, 100) MyMIDI.close() self.assertEquals(MyMIDI.tracks[0].MIDIEventList[0].type, "NoteOn") self.assertEquals(MyMIDI.tracks[0].MIDIEventList[0].time, 0) self.assertEquals(MyMIDI.tracks[0].MIDIEventList[1].type, "NoteOff") self.assertEquals(MyMIDI.tracks[0].MIDIEventList[1].time, 128) # Negative time, two tracks MyMIDI = MIDIFile(2) MyMIDI.addNote(0, 0, 100, -1, 1, 100) MyMIDI.addNote(1, 0, 100, 0, 1, 100) MyMIDI.close() self.assertEquals(MyMIDI.tracks[0].MIDIEventList[0].type, "NoteOn") self.assertEquals(MyMIDI.tracks[0].MIDIEventList[0].time, 0) self.assertEquals(MyMIDI.tracks[0].MIDIEventList[1].type, "NoteOff") self.assertEquals(MyMIDI.tracks[0].MIDIEventList[1].time, 128) self.assertEquals(MyMIDI.tracks[1].MIDIEventList[0].type, "NoteOn") self.assertEquals(MyMIDI.tracks[1].MIDIEventList[0].time, 128) self.assertEquals(MyMIDI.tracks[1].MIDIEventList[1].type, "NoteOff") self.assertEquals(MyMIDI.tracks[1].MIDIEventList[1].time, 128)
def write_midi(filename, sequence): filename = "markov/"+filename midi = MIDIFile(1) track = 0 start_time = 0 midi.addTrackName(track, start_time, filename[:-4]) tempo = random.randrange(360, 480) midi.addTempo(track, start_time, tempo) midi.addProgramChange(0, 0, 0, 1) for i in range(len(sequence)): note = sequence[i] midi.addNote(track, 0, note.pitch, note.time, note.duration, note.volume) f = open(filename, 'w') midi.writeFile(f) f.close()
def write_song(song, dest, tempo=240): num_channels = len(song) midi_scratch_file = MIDIFile(num_channels) for i in range(0, num_channels): midi_scratch_file.addTrackName(i, 0, "Pop Flute {0}".format(i)) midi_scratch_file.addTempo(i, 0, tempo) time = 0 for x in range(0, song_length(song)): duration = 0.5 pitch = song[i][x] midi_scratch_file.addNote(i, i, pitch, time, duration, 100) time += duration bin_file = open(dest, 'w') midi_scratch_file.writeFile(bin_file) bin_file.close()
def testWriteFile(self): # Just to make sure the stream can be written without throwing an error. MyMIDI = MIDIFile(1) MyMIDI.addNote(0, 0, 100, 0, 1, 100) with open("/tmp/test.mid", "wb") as output_file: MyMIDI.writeFile(output_file)
class song(): """Defines the song""" def __init__(self, rand_seed=None, tempo=None, divs_per_beat=None, beats_per_bar=None, key=None, structure=None): """Initializes properties of the song""" self.set_rand_seed(rand_seed) self.name = datetime.datetime.fromtimestamp( time.time()).strftime('%Y_%m_%d__%H_%M_%S') + "_seed_" + str( self.rand_seed) self.track = 0 self.time = 0 self.tempo = tempo or random.randint(70, 135) # value is bpm self.divs_per_beat = divs_per_beat or 4 # default 1/4 notes self.beats_per_bar = beats_per_bar or 4 # default 4 beats per bar self.cur_channel = -1 self.channel_sample_map = {} self.set_midi_obj() self.set_key(key) self.set_structure(structure) self.verse = verse(self, prev_part=None) self.chorus = chorus(self, prev_part=self.verse) self.gen_song() def get_channel(self): """Returns the midi channel for an instrument""" # get the next available midi channel. channel 9 is reserved for drums, so skip it if self.cur_channel == 8: self.cur_channel = 10 else: self.cur_channel = self.cur_channel + 1 return self.cur_channel def set_key(self, key): """Set the musical key of the song""" keys = music_theory.keys self.key = key or keys[random.randint(0, len(keys) - 1)] def set_structure(self, structure=None): """Sets song structure, e.g. [verse, chorus, verse, verse, chorus]""" self.structure = structure or [ 'verse', 'verse', 'chorus', 'chorus', 'verse', 'verse', 'chorus', 'chorus', 'verse', 'verse', 'chorus', 'chorus' ] def set_rand_seed(self, rand_seed=None): """Sets the random seed for the song""" self.rand_seed = rand_seed or random.randint(0, 100000000) random.seed(self.rand_seed) def set_midi_obj(self): """Sets the MIDIUtil midi object""" self.midi_obj = MIDIFile(1) self.midi_obj.addTrackName(self.track, self.time, self.name) self.midi_obj.addTempo(self.track, self.time, self.tempo * self.divs_per_beat) def gen_song(self): """Puts the parts of the song together""" start = 0 # addNote below is a MIDIUtil function that adds a note to the midi file for part in self.structure: if part == 'verse': for note in self.verse.notes_list: self.midi_obj.addNote(self.track, note['channel'], note['pitch'], note['time'] + start, note['duration'], note['volume']) start = start + self.verse.bars * self.divs_per_beat * self.beats_per_bar if part == 'chorus': for note in self.chorus.notes_list: self.midi_obj.addNote(self.track, note['channel'], note['pitch'], note['time'] + start, note['duration'], note['volume']) start = start + self.chorus.bars * self.divs_per_beat * self.beats_per_bar # add some silent seconds to the end of the song blank_seconds = 4 for i in range( int(self.divs_per_beat * (self.tempo / 60.0) * blank_seconds)): self.midi_obj.addNote(self.track, 0, 0, i + start, 1, 0) def write_midi(self): """Writes the midi file generated by MIDIUtil""" binfile = open( OUTPUT_FILE_PATH.replace('\\', '') + self.name + ".mid", 'wb') self.midi_obj.writeFile(binfile) binfile.close() def write_fs_script(self): """Writes the FluidSynth script file""" f = open(OUTPUT_FILE_PATH.replace('\\', '') + self.name + ".txt", 'w') load = '' select = '' channel_sample_map_keys = self.channel_sample_map.keys() # generates lines of "load <sample file path>" for key in channel_sample_map_keys: line = 'load {}{}'.format(SAMPLES_PATH, self.channel_sample_map[key]) load = load + line + '\n' # generates lines of "select <channel> <SoundFont number (in order loaded above)> <bank> <preset>" for i in range(len(channel_sample_map_keys)): key = channel_sample_map_keys[i] line = 'select {} {} {} {}'.format(key, i + 1, 0, 0) select = select + line + '\n' f.write( load + select + 'fonts \n' + 'channels \n' ) # prompt SoundFonts and channel assignments to be displayed in terminal f.close() def play_audio_fs(self): """Plays the generated audio file with FluidSynth, and saves the midi file and FluidSynth script""" self.write_midi() self.write_fs_script() subprocess.call("fluidsynth " + OUTPUT_FILE_PATH + self.name + ".mid -f " + OUTPUT_FILE_PATH + self.name + ".txt -o player.reset-synth=FALSE -i", shell=True) def write_raw_audio(self): """Saves the .raw audio file and saves the midi file and FluidSynth script""" self.write_midi() self.write_fs_script() subprocess.call("fluidsynth " + OUTPUT_FILE_PATH + self.name + ".mid -f " + OUTPUT_FILE_PATH + self.name + ".txt -o player.reset-synth=FALSE -i -F " + OUTPUT_FILE_PATH + self.name + ".raw", shell=True) def convert_raw_to_wav(self): """Saves .wav version of the .raw audio file. Requires SoX, and the .raw file must exist""" subprocess.call("sox -b 16 -c 2 -s -r 44100 " + OUTPUT_FILE_PATH + self.name + ".raw " + OUTPUT_FILE_PATH + self.name + ".wav", shell=True)
class Sequence: """ MIDIシーケンスのクラス """ TPB = 480 # 4分音符分解能(Ticks Per Beat) DEFAULT_BPM = 120 # デフォルトBPM def __init__(self): """ コンストラクタ """ self.sequence = MIDIFile(file_format=0, ticks_per_quarternote=Sequence.TPB, eventtime_is_ticks=True) self.set_tempo(Sequence.DEFAULT_BPM) def set_tempo(self, bpm=DEFAULT_BPM): """ MIDIシーケンスのテンポをセットする Parameters ---------- bpm : int BPM """ # すでにテンポイベントが登録されていたらそのイベントを削除する for event in self.sequence.tracks[0].eventList: if event.evtname == 'Tempo': self.sequence.tracks[0].eventList.remove(event) # 新しいBPM値でテンポイベントをセット self.sequence.addTempo(0, 0, bpm) def add_note(self, pitch, position, duration, velocity): """ MIDIシーケンスへノートイベントを追加する Parameters ---------- pitch : int ノートナンバー position : int 発音時刻 duration : int 音価(発音時間長) velocity : int ベロシティ """ self.sequence.addNote(0, 0, pitch, position, duration, velocity) def show(self): """ MIDIシーケンスが持つ全MIDIイベントを表示する """ for track in self.sequence.tracks: for event in track.eventList: if event.evtname == 'Tempo': bpm = int(60000000 / event.tempo) tick = event.tick print('BPM {} at tick {}'.format(bpm, tick)) else: print(event) def write_to_file(self, path): """ MIDIシーケンスの内容をファイルに書き込む Parameters ---------- path : str MIDIファイルのファイルパス """ with open(path, 'wb') as file: self.sequence.writeFile(file)
def notes(tonality, track_interval_one, track_interval_two, loop_length, meter, melody_iteration, first_note, root_note, track_name, verbose): beats_in_loop = meter * loop_length - 1 inverse_melody_iteration = melody_iteration # Song Settings track_tempo = 120 beat = 0 process_loop = zeroes(beats_in_loop + 1) process_interval = track_interval_one # Initialise Tonality scale = NoteMap(root_note, tonality) current_note = int(root_note) for i in range(first_note, 0): current_note = scale.next_step(current_note) # MIDI STUFF # # some of these fields could be approached at a # later date to achieve a more humanised feel (for # example velocity) but for now I am lazy track_index = 0 time_index = 0 track_channel = 0 track_volume = 100 note_duration = 1 track_handle = MIDIFile(1) track_handle.addTrackName(track_index, time_index, track_name) track_handle.addTempo(track_index, time_index, track_tempo) # COMPOSITIONAL LOGIC while melody_iteration > 0: if process_loop[beat] > 0.0: if verbose: print switch_string.format(str(melody_iteration), str(beat), str(process_interval), str(process_loop[beat]), str(process_loop[beat])) if process_interval == track_interval_one: process_interval = track_interval_two else: process_interval = track_interval_one process_loop[beat] += 1 track_handle.addNote(track_index, track_channel, current_note, beat, note_duration, track_volume) current_note = scale.next_step(current_note) beat += process_interval if beat > beats_in_loop: if verbose: end_of_loop_string.format(str(beat)) melody_iteration -= 1 beat -= beats_in_loop + 1 # The +1 returns the cursor to beat 1 rather than beat 0 (out of bounds) if verbose: beat_reset_string.format(str(beat)) if verbose: print iteration_string.format( str(inverse_melody_iteration - melody_iteration), str(beat), str(process_loop)) print 'I made you {!s} \nhttp://jamescarthew.com/notes for more info'.format( track_name) # MIDI print with open(track_name, 'wb') as bin_file: track_handle.writeFile(bin_file)
def write_midi_roll_to_midi(x, out_path): """Write out midi_roll to midi file. Args: x: (n_time, n_pitch), midi roll. out_path: string, path to write out the midi. """ step_sec = cfg.step_sec def _get_bgn_fin_pairs(ary): pairs = [] bgn_fr, fin_fr = -1, -1 for i2 in xrange(1, len(ary)): if ary[i2 - 1] == 0 and ary[i2] == 0: pass elif ary[i2 - 1] == 0 and ary[i2] == 1: bgn_fr = i2 elif ary[i2 - 1] == 1 and ary[i2] == 0: fin_fr = i2 if fin_fr > bgn_fr: pairs.append((bgn_fr, fin_fr)) elif ary[i2 - 1] == 1 and ary[i2] == 1: pass else: raise Exception("Input must be binary matrix!") return pairs # Get (pitch, bgn_frame, fin_frame) triple. triples = [] (n_time, n_pitch) = x.shape for i1 in xrange(n_pitch): ary = x[:, i1] pairs_per_pitch = _get_bgn_fin_pairs(ary) if pairs_per_pitch: triples_per_pitch = [(i1, ) + pair for pair in pairs_per_pitch] triples += triples_per_pitch # Sort by begin frame. triples = sorted(triples, key=lambda x: x[1]) # Write out midi. MyMIDI = MIDIFile(1) # Create the MIDIFile Object with 1 track track = 0 time = 0 tempo = 120 beat_per_sec = 60. / float(tempo) MyMIDI.addTrackName(track, time, "Sample Track") # Add track name MyMIDI.addTempo(track, time, tempo) # Add track tempo for triple in triples: (midi_pitch, bgn_fr, fin_fr) = triple bgn_beat = bgn_fr * step_sec / float(beat_per_sec) fin_beat = fin_fr * step_sec / float(beat_per_sec) dur_beat = fin_beat - bgn_beat MyMIDI.addNote( track=0, # The track to which the note is added. channel=0, # the MIDI channel to assign to the note. [Integer, 0-15] pitch=midi_pitch, # the MIDI pitch number [Integer, 0-127]. time= bgn_beat, # the time (in beats) at which the note sounds [Float]. duration=dur_beat, # the duration of the note (in beats) [Float]. volume=100) # the volume (velocity) of the note. [Integer, 0-127]. out_file = open(out_path, 'wb') MyMIDI.writeFile(out_file) out_file.close()
class SongGenerator(object): def __init__(self, song): self.BPM = song.BPM self.ticks_per_beat = song.ticks_per_beat self.song = song self.tracks = [] self.channels = [] self.next_channel = 0 self.track_notes = [] self.track_instruments = [] def addDrums(self): if len(self.song.idx_drums) > 0: drums = self.song.notes[self.song.idx_drums[0]] self.addInstrument(drums, 0, 9) def addMelody(self): print("ADD MELODY ") for i in range(len(self.song.idx_melody)): voices = self.song.notes[self.song.idx_melody[i]] voices_add = musicfunctions.createChorus(voices, octaves_augmentation=1) channel = self.song.channels[self.song.idx_melody[i]] voices_add_regularized = utils.deleteDuration0( musicfunctions.rythmRegularization(voices, voices_add, 100, constants.DIFFICULTY_LVL)) # print(voices_add_regularized) instrument_number = self.song.instruments_list[ self.song.idx_melody[i]] - 1 instrument_number = 0 self.addInstrument(voices_add_regularized, instrument_number, channel) def addAccompaniment(self): for idx in range(len(self.song.notes)): if (idx not in self.song.idx_melody) & ( idx not in self.song.idx_drums): voices = self.song.notes[idx] voices = utils.deleteDuration0(voices) channel = self.song.channels[idx] instrument_number = self.song.instruments_list[idx] - 1 self.addInstrument(voices, instrument_number, channel) def addInstrument(self, notes, instrument_number, channel): self.tracks += [len(self.tracks)] self.track_instruments += [instrument_number] track = self.tracks[len(self.tracks) - 1] self.channels += [channel] self.track_notes += [notes] def generateSong(self): print("Generating music ...") print("Melody : " + str(self.song.idx_melody) + " = " + str( utils.convertInstrumentNumbers2InstrumentName( [self.song.instruments_list[i] for i in self.song.idx_melody]))) print("Final Tracks : " + str(self.tracks)) print("Final Channels : " + str(self.channels)) print("Final midi Instruments : " + str(self.track_instruments)) time = 0 self.MyMIDI = MIDIFile(len(self.tracks)) for i in range(len(self.tracks)): idx_channel = (self.song.channels).index(self.channels[i]) print(idx_channel) if idx_channel in self.song.idx_melody: volume = constants.VOLUME_MELODY elif idx_channel in self.song.idx_drums: volume = constants.VOLUME_DRUMS else: volume = constants.VOLUME_ACCOMPANIMENT track_voices = self.tracks[i] channel_voices = self.channels[i] self.MyMIDI.addTempo(track_voices, 0, self.BPM) notes = self.track_notes[i] self.MyMIDI.addProgramChange(track_voices, channel_voices, 0, self.track_instruments[i]) for (i, info) in enumerate(notes): if info[1] != 0: self.MyMIDI.addNote( track_voices, channel_voices, info[0], utils.convertTicks2Beat(info[3], self.ticks_per_beat), utils.convertTicks2Beat(info[1], self.ticks_per_beat), volume) with open(constants.PATH_GENERATED_SONG, "wb") as output_file: self.MyMIDI.writeFile(output_file) print("generateSong done") return constants.PATH_GENERATED_SONG
def getVolume(value): ratio = value / max_value volume_range = max_volume - min_volume return round(volume_range * ratio) + min_volume # second pass, generate music current_note = 0 beat = 0 with open("quarter-hour-chunked.csv", "r") as csv_file: csv_reader = csv.reader(csv_file) for row in csv_reader: value = int(row[0]) prob = value * base_prob bad_login = random() < prob if bad_login: print("Do the things!") m.addNote(0, seventh_channel, seventh_pattern[int(current_note / 8) % len(seventh_pattern)], beat, eighth_note, chord_volume) m.addNote(0, arp_channel, pattern[current_note], beat, eighth_note, getVolume(value)) current_note = (current_note + 1) % len(pattern) if beat % 4 == 0: current_chord = chord_pattern[int(current_note / 8) % len(chord_pattern)] for current_chord_note in current_chord: m.addNote(0, chord_channel, current_chord_note + 12, beat, whole_note, chord_volume) beat += eighth_note # write MIDI output with open("logins-with-bad.mid", "wb") as f: m.writeFile(f)
class Composition: # Private vars # _mf # _voices # _tempo # _marks # Todo: Update these vars to match the style of the Voices class. def __init__(self, numTracks, tempo): self._mf = MIDIFile(numTracks) self._voices = [] self._tempo = tempo self._marks = {} def buildVoice(self, instrument, name): voiceAmt = len(self._voices) chan = voiceAmt if voiceAmt != 9 else 10 # Channel 9 (10 in MIDI docs) is strictly percussion. voiceDum = Voice( self._mf, chan, instrument, self._tempo, name, 0, # For now, start all at zero. ) self._voices.append(voiceDum) return voiceDum def buildPerc(self): voiceDum = Percussion(self._mf, self._tempo, 0) self._voices.append(voiceDum) return voiceDum def addVoice(self, newVoice): # This adds a new voice, but it won't work if it uses a different # MIDIFile object. self._voices.append(newVoice) def adjustPitchOffset(self, newOffset): for voice in self._voices: voice.adjustPitchOffset(newOffset) def setScale(self, scale): ''' Set the scale for every voice in composition. ''' for voice in self._voices: voice.setScale(scale) def setKey(self, key): ''' Set key for every voice in composition. ''' for voice in self._voices: voice.setKey(key) def setTempo(self, tempo): ''' Set tempo for every voice in composition at current time. ''' curtime = self._getLastBeat() for voice in self._voices: voice.setTempo(tempo, curtime) def writeToFile(self, filename): # First, add a buffer silent note, so player doesn't cut it off # prematurely. lastBeat = self._getLastBeat() self._mf.addNote( 0, # There will always be a track 0. 0, # There will always be a channel 0. 42, # Pitch is irrelevant lastBeat + 5, # Buffer of five beats. Might not be too helpful if tempo is high, so might want to adjust this later. 1, 0 # Zero volume ) with open(filename, 'wb') as outf: self._mf.writeFile(outf) def mark(self, markName, markTime): """ This function is to help "mark" a time. (This has nothing to do with time signatures.) Once a time has been marked, it cannot be overwritten. """ if markName not in self._marks: self._marks[markName] = markTime def getMark(self, markName): ''' This function gets a time that was previously marked. ''' return self._marks[markName] def catchUpAll(self): ''' Catch up all voices to last beat. ''' curtime = self._getLastBeat() for voice in self._voices: voice.catchUp(curtime) def stop(self): ''' Stop moving forward. See docstring for function of same name in the Voice class. ''' for voice in self._voices: voice.stop() def start(self): ''' Start moving forward, assuming that stop had previously been called. ''' for voice in self._voices: voice.start() # Helper functions below this line. def _getLastBeat(self): timedum = 0 for voice in self._voices: if (voice.whereAreWe() > timedum): timedum = voice.whereAreWe() return timedum
line = [] with open('output.txt', 'r') as f: line = f.readline() music = json.loads(line, object_hook=lambda d: namedtuple('X', d.keys())(*d.values())) # print music # create your MIDI object mf = MIDIFile(1) # only 1 track track = 0 # the only track time = 0 # start at the beginning mf.addTrackName(track, time, "Sample Track") mf.addTempo(track, time, music.header.bpm) # add some notes channel = music.tracks[0].channelNumber volume = 100 notes = music.tracks[0].notes one_beat = 60000.0/music.header.bpm for note in notes: pitch = note.midi t = float(note.time[1:]) time = t*1.0/one_beat duration = note.duration*1.0/one_beat mf.addNote(track, channel, pitch, time, duration, volume) # write it to disk with open("output.mid", 'wb') as outf: mf.writeFile(outf)
def testRemoveDuplicates(self): # First notes track = 0 channel = 0 pitch = 69 time = 0 duration = 1 volume = 64 MyMIDI = MIDIFile(1) MyMIDI.addNote(track, channel, pitch, time, duration, volume) # also adds a corresponding NoteOff MyMIDI.addNote(track, channel, pitch, time, duration, volume) # also adds a corresponding NoteOff MyMIDI.close() self.assertEqual(2, len(MyMIDI.tracks[1].eventList)) # One NoteOn event, one NoteOff event MyMIDI = MIDIFile(1) MyMIDI.addNote(track, channel, pitch, time, duration, volume) pitch = 70 MyMIDI.addNote(track, channel, pitch, time, duration, volume) MyMIDI.close() self.assertEqual(4, len(MyMIDI.tracks[1].eventList)) # Two NoteOn events, two NoteOff events # Next tempo tempo = 60 track = 0 time = 0 MyMIDI = MIDIFile(1) MyMIDI.addTempo(track, time, tempo) MyMIDI.addTempo(track, time, tempo) MyMIDI.close() self.assertEqual(1, len(MyMIDI.tracks[0].eventList)) MyMIDI = MIDIFile(1) MyMIDI.addTempo(track, time, tempo) tempo = 80 MyMIDI.addTempo(track, time, tempo) MyMIDI.close() self.assertEqual(2, len(MyMIDI.tracks[0].eventList)) # Program Number time = 0 track = 0 program = 10 channel = 0 MyMIDI = MIDIFile(1) MyMIDI.addProgramChange(track, channel, time, program) MyMIDI.addProgramChange(track, channel, time, program) MyMIDI.close() self.assertEqual(1, len(MyMIDI.tracks[track + 1].eventList)) MyMIDI = MIDIFile(1) MyMIDI.addProgramChange(track, channel, time, program) program = 11 MyMIDI.addProgramChange(track, channel, time, program) MyMIDI.close() self.assertEqual(2, len(MyMIDI.tracks[track + 1].eventList)) # Track Name track = 0 time = 0 track_name = "track" MyMIDI = MIDIFile(1) MyMIDI.addTrackName(track, time, track_name) MyMIDI.addTrackName(track, time, track_name) MyMIDI.close() self.assertEqual(1, len(MyMIDI.tracks[1].eventList)) MyMIDI = MIDIFile(1) MyMIDI.addTrackName(track, time, track_name) track_name = "track 2" MyMIDI.addTrackName(track, time, track_name) MyMIDI.close() self.assertEqual(2, len(MyMIDI.tracks[1].eventList)) # SysEx. These are never removed track = 0 time = 0 manufacturer = 10 MyMIDI = MIDIFile(1) MyMIDI.addSysEx(track, time, manufacturer, struct.pack('>B', 0x01)) MyMIDI.addSysEx(track, time, manufacturer, struct.pack('>B', 0x01)) MyMIDI.close() self.assertEqual(2, len(MyMIDI.tracks[1].eventList)) # UniversalSysEx. Same thing -- never remove track = 0 time = 0 code = 1 subcode = 2 payload_number = 47 payload = struct.pack('>B', payload_number) MyMIDI = MIDIFile(1) MyMIDI.addUniversalSysEx(track, time, code, subcode, payload, realTime=True) MyMIDI.addUniversalSysEx(track, time, code, subcode, payload, realTime=True) MyMIDI.close() self.assertEqual(2, len(MyMIDI.tracks[1].eventList))
def save_to_midifile(input_data, track_type='single', key=None,number_of_octaves=4,output_path='',name='mymidifile'): """ Save your midifile with this function instead of playing it! data: (same list like play_to_midifile) list of tuples of x, y coordinates for pitch and timing Optional: add a string to the start of the data list to specify instrument! type: the type of data passed to create tracks. Either 'single' or 'multiple' key: key to play back the graph -- see constants.py for current choices number_of_octaves: number of octaves used to restrict the music playback when converting to a key output_path: folder path where you want to save your midi files. Path like 'sounds/example/'. Always include the last '/'. If you dont specify the path, files will be saved in the actual directory. name = Include a name for your midi file, if name is not included, name will be "mymidifile" If you use a loop and you don't include a name, output will be like: mymidifile.midi ,mymidifile(0).midi, mymidifile(1).midi ... (n files) """ if key: if track_type == 'multiple': data = [] for data_list in input_data: data.append(convert_to_key(data_list, key, number_of_octaves)) else: data = convert_to_key(input_data, key, number_of_octaves) else: data = input_data if track_type not in ['single', 'multiple']: raise ValueError('Track type must be single or multiple') if track_type == 'single': data = [data] midifile = MIDIFile(numTracks=len(data), adjust_origin=False) track = 0 time = 0 program = 0 channel = 0 duration = 1 volume = 90 for data_list in data: midifile.addTrackName(track, time, 'Track {}'.format(track)) midifile.addTempo(track, time, 120) instrument_type = 'melodic' if type(data_list[0]) != tuple: program, instrument_type = get_instrument(data_list.pop(0)) if instrument_type == 'percussion': volume = 100 channel = 9 # Write the notes we want to appear in the file for point in data_list: time = point[0] pitch = int(point[1]) if instrument_type == 'melodic' else program midifile.addNote(track, channel, pitch, time, duration, volume) midifile.addProgramChange(track, channel, time, program) track += 1 channel = 0 with open(auto_save_file(output_path+name+'.midi'), 'wb') as output_file: midifile.writeFile(output_file)
def testTimeShift(self): # With one track MyMIDI = MIDIFile(1, adjust_origin=True) track = 0 channel = 0 pitch = 100 time1 = 5 duration = 1 volume = 100 MyMIDI.addNote(track, channel, pitch, time1, duration, volume) MyMIDI.close() self.assertEqual(MyMIDI.tracks[1].MIDIEventList[0].evtname, 'NoteOn') self.assertEqual(MyMIDI.tracks[1].MIDIEventList[0].tick, MyMIDI.time_to_ticks(0)) self.assertEqual(MyMIDI.tracks[1].MIDIEventList[1].evtname, 'NoteOff') self.assertEqual(MyMIDI.tracks[1].MIDIEventList[1].tick, MyMIDI.time_to_ticks(duration)) # With two tracks track2 = 1 MyMIDI = MIDIFile(2, adjust_origin=True) MyMIDI.addNote(track, channel, pitch, time1, duration, volume) time2 = 6 MyMIDI.addNote(track2, channel, pitch, time2, duration, volume) MyMIDI.close() # ticks have already been converted to delta ticks self.assertEqual(MyMIDI.tracks[1].MIDIEventList[0].evtname, 'NoteOn') self.assertEqual(MyMIDI.tracks[1].MIDIEventList[0].tick, MyMIDI.time_to_ticks(0)) self.assertEqual(MyMIDI.tracks[1].MIDIEventList[1].evtname, 'NoteOff') self.assertEqual(MyMIDI.tracks[1].MIDIEventList[1].tick, MyMIDI.time_to_ticks(duration)) self.assertEqual(MyMIDI.tracks[2].MIDIEventList[0].evtname, 'NoteOn') self.assertEqual(MyMIDI.tracks[2].MIDIEventList[0].tick, MyMIDI.time_to_ticks(0 + duration)) self.assertEqual(MyMIDI.tracks[2].MIDIEventList[1].evtname, 'NoteOff') self.assertEqual(MyMIDI.tracks[2].MIDIEventList[1].tick, MyMIDI.time_to_ticks(0 + duration)) # Negative Time MyMIDI = MIDIFile(1, adjust_origin=True) track = 0 channel = 0 pitch = 100 time = -5 duration = 1 volume = 100 MyMIDI.addNote(track, channel, pitch, time, duration, volume) MyMIDI.close() self.assertEqual(MyMIDI.tracks[1].MIDIEventList[0].evtname, 'NoteOn') self.assertEqual(MyMIDI.tracks[1].MIDIEventList[0].tick, MyMIDI.time_to_ticks(0)) self.assertEqual(MyMIDI.tracks[1].MIDIEventList[1].evtname, 'NoteOff') self.assertEqual(MyMIDI.tracks[1].MIDIEventList[1].tick, MyMIDI.time_to_ticks(0 + duration)) # Negative time, two tracks MyMIDI = MIDIFile(2, adjust_origin=True) track = 0 channel = 0 pitch = 100 time = -1 duration = 1 volume = 100 MyMIDI.addNote(track, channel, pitch, time, duration, volume) track2 = 1 time2 = 0 MyMIDI.addNote(track2, channel, pitch, time2, duration, volume) MyMIDI.close() self.assertEqual(MyMIDI.tracks[1].MIDIEventList[0].evtname, 'NoteOn') self.assertEqual(MyMIDI.tracks[1].MIDIEventList[0].tick, MyMIDI.time_to_ticks(0)) self.assertEqual(MyMIDI.tracks[1].MIDIEventList[1].evtname, 'NoteOff') self.assertEqual(MyMIDI.tracks[1].MIDIEventList[1].tick, MyMIDI.time_to_ticks(1)) self.assertEqual(MyMIDI.tracks[2].MIDIEventList[0].evtname, 'NoteOn') self.assertEqual(MyMIDI.tracks[2].MIDIEventList[0].tick, MyMIDI.time_to_ticks(1)) self.assertEqual(MyMIDI.tracks[2].MIDIEventList[1].evtname, 'NoteOff') self.assertEqual(MyMIDI.tracks[2].MIDIEventList[1].tick, MyMIDI.time_to_ticks(1))