def MainLoop(self): self.piano_input_obj.ClearInput() self.score = None while True: self.piano_display.Clear() self.piano_display.DrawPiano(False) self.ShowHighScore() self.piano_display.SetKeyText(36, 20, u"\u2212") self.piano_display.SetKeyText(40, 20, u"\u2795") self.piano_display.SetKeyText( 38, self.piano_display.KEYBOARD_HEIGHT + 50, " Slowdown") self.piano_display.SetKeyText( 38, self.piano_display.KEYBOARD_HEIGHT + 25, str(self.slowdown)) self.piano_display.SetKeyText(36 + 12, 20, "<") self.piano_display.SetKeyText(40 + 12, 20, ">") self.piano_display.SetKeyText( 38 + 12, self.piano_display.KEYBOARD_HEIGHT + 50, "Select Song") self.piano_display.SetKeyText( 38 + 12, self.piano_display.KEYBOARD_HEIGHT + 25, self.songs[self.current_song][:-4]) self.piano_display.SetKeyText(38 + 12, 20, u"\u266a") self.piano_display.Refresh() if self.piano_input_obj.user_input.empty(): time.sleep(0.1) # Avoid hogging the CPU when idle. while not self.piano_input_obj.user_input.empty(): user_cmd = self.piano_input_obj.user_input.get() if user_cmd[1] > 0: if user_cmd[0] == 36: self.slowdown = max(0.1, self.slowdown - 0.1) if user_cmd[0] == 40: self.slowdown = self.slowdown + 0.1 if user_cmd[0] == 40 + 12: self.score = None self.current_song = (self.current_song + 1) % len( self.songs) self.CreateWaterfall() if user_cmd[0] == 36 + 12: self.score = None self.current_song = (self.current_song + len( self.songs) - 1) % (len(self.songs)) midi_file = midi.MidiFile( self.songs[self.current_song]) self.waterfall = waterfall.Waterfall( self.piano_input_obj, self.piano_display, midi_file) if user_cmd[0] == 38 + 12: if self.waterfall.EndOfSong(): # Reload midi file, because it was destroyed during playback self.CreateWaterfall() self.score = self.waterfall.Continue(self.slowdown) self.ShowHighScore() self.CheckHighScore()
def midi_to_midievents(stream): import midi m = midi.MidiFile() m.open(stream) m.read() m.close() # WARNING: we only use track0 here and ignore others for ev in m.tracks[0].events: if ev.type == "DeltaTime": yield ("play", ev.time) elif ev.type == "NOTE_ON": yield ("noteon", ev.track.index, ev.pitch, ev.velocity) elif ev.type == "NOTE_OFF": yield ("noteoff", ev.track.index, ev.pitch) elif ev.type == "SET_TEMPO": pass # TODO (?) ... else: print "midi warning: event", ev, "ignored"
def __init__(self): self.slowdown = 1.0 self.songs = GetMidiFiles() self.current_song = 0 self.piano_display = piano_output.PianoOutput() try: self.piano_input_obj = piano_input.PianoInput() except IOError: print "Using mock input instead of usb one." print "To install pyusb run:" print " sudo apt-get install python libusb-1.0-0" print " sudo pip install pyusb --pre" self.piano_input_obj = piano_input_mock.PianoInput() midi_file = midi.MidiFile(self.songs[self.current_song]) self.waterfall = waterfall.Waterfall(self.piano_input_obj, self.piano_display, midi_file) self.LoadHighScores()
def main(argv): global quickFlag, SAMPLERATE, DT, BLIPSIZE, profiling quickFlag = 0 midifile = None wavefile = "newguy.wav" starttime, finishtime = -1.e5, 1.e5 optlist, args = getopt.getopt(argv[1:], "s:f:qi:o:p") for (option, value) in optlist: if option == "-s": starttime = eval(value) elif option == "-f": finishtime = eval(value) elif option == "-q": quickFlag = 1 elif option == "-i": midifile = value elif option == "-o": wavefile = value elif option == "-p": profiling = 1 if quickFlag: SAMPLERATE = 4000 else: SAMPLERATE = 44100 DT = 1. / SAMPLERATE BLIPSIZE = int(0.02 / DT) timestamp("reading MIDI file") m = midi.MidiFile(midifile) m.read() m.close() def goAhead(play=play, notelist=notelist, wavefile=wavefile, starttime=starttime, finishtime=finishtime): play(notelist, wavefile, starttime, finishtime) if profiling: import profile globals()['goAhead'] = goAhead profile.run("goAhead()") else: goAhead()
'time=', 'kill=', 'compensation=', 'multiplier=', 'split=', 'minimum=', 'output=' ]) except getopt.GetoptError: exit() for o, a in opts: if o in ("-c", "--compensation"): comp = float(a) if o in ("-k", "--kill"): chord = int(a) if o in ("-m", "--multiplier"): mult = float(a) if o in ("-s", "--split"): split = int(a) if o in ("-n", "--minimum"): mn = int(a) if o in ("-o", "--output"): sys.stdout = file(a, "w") havetoclose = 1 if not args: exit() m = midi.MidiFile() m.open(args[0]) m.read() m.close() tcks = range(len(m.tracks)) if len(args) == 1 else args[1:] xt = list() for i in tcks: xt = xt + m.tracks[int(i)].events ntk = max(ntk, int(i)) for e in xt: if e.type == "NOTE_OFF": e.time += 5 concnotes = [0] for i in range(ntk): concnotes.append(0)
def analyze(filename, delta_min=0.02): notes = midi.MidiFile(filename).getNotes(False) note_low = 21 # lowest midi note on a keyboard note_high = 108 # highest midi note on a keyboard # Analyze note frequency and volume (force) stat_note = np.zeros(note_high - note_low) pos_note = np.arange(note_high - note_low) stat_note_simp = np.zeros(12) pos_note_simp = np.arange(12) lab_note_simp = [ 'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B' ] stat_vol = np.zeros(128) pos_vol = np.arange(128) for t, n, v in notes: stat_note[n - note_low] += 1 stat_note_simp[n % 12] += 1 stat_vol[v] += 1 # Analyze number of simultaneous notes played (single strokes / chords) stat_nb_notes = np.zeros(12) pos_nbnotes = np.arange(12) time = -1 nb_notes = 1 for t, n, v in notes: if (t - time) < delta_min: nb_notes += 1 else: if time >= 0: stat_nb_notes[nb_notes] += 1 time = t nb_notes = 1 # Analyze time (silence) between notes, i.e. playing speed or tempo (bpm) bpm_step = 25 bpm_max = int(60 / delta_min) pos_bpm = np.arange(0, bpm_max + 1, bpm_step) stat_bpm = np.zeros(len(pos_bpm)) time = -1 for t, n, v in notes: delta_t = t - time if t == time or delta_t < delta_min: continue elif time >= 0: bpm = min(round(60. / delta_t / bpm_step), bpm_max) stat_bpm[bpm] += 1 time = t return [[pos_note, stat_note, 'Key'], [pos_note_simp, stat_note_simp, 'Note', lab_note_simp], [pos_vol, stat_vol, 'Volume'], [ pos_nbnotes, stat_nb_notes, 'Nb of simultaneous notes', pos_nbnotes ], [pos_bpm, stat_bpm, 'Tempo (bpm)']]
label=label) if label != None: ax[i].legend(loc='upper right') f.subplots_adjust(hspace=0.5) return f, ax if __name__ == '__main__': set = 'set_3' train_stats = analyze_multi(glob(f'data/{set}/train/*.mid')) test_stats = analyze_multi(glob(f'data/{set}/test/*.mid')) for subset in ('train', 'test'): nb_notes = 0 for f in glob(f'data/{set}/{subset}/*.mid'): nb_notes += len(midi.MidiFile(f).getNotes(False)) print(f'{set} / {subset} : {nb_notes} notes') plt.close('all') f, ax = plot(train_stats, label='train', nb_series=2, serie=0) f, ax = plot(test_stats, label='test', f=f, ax=ax, nb_series=2, serie=1) ax[0].set_title('Set 3') # adjust x scales ax[1].set_xlim(-1, 13) ax[-1].set_xlim(0, 2200) plt.show()
def load_file_mod(name, step=10, timeLimit=-1): """ Charge un fichier, et le converti en tableau de notes échantillonées :param step: pas de quantification de la musique (ms) :param timeLimit: temps total limite de la musique (ms) ignoré si négatif """ m = midi.MidiFile() m.open(name) m.read() m.close() # print(m.tracks[0]) # conversion en notes jouées toutes les <step> ms noteTimeline = {} currentNotes = {p: [-1, 0] for p in range(36)} currentTempo = 500000 lastTempoTimeMicro = 0 lastTempoTimeTick = 0 for e in m.tracks[0].events: pitch = e.pitch%36 if e.type == 'SET_TEMPO': # changement de tempo dans la piste t = (e.time-lastTempoTimeTick)*currentTempo/m.ticksPerQuarterNote + lastTempoTimeMicro # durée en µs currentTempo = e.data lastTempoTimeMicro = t lastTempoTimeTick = e.time elif e.type == 'NOTE_ON': # début/fin d'une note t = (e.time-lastTempoTimeTick)*currentTempo/m.ticksPerQuarterNote + lastTempoTimeMicro # durée en µs n = int( t/(step*1000) ) if e.velocity != 0: # début d'une note -> ajout aux notes actuelles currentNotes[pitch] = [n, e.velocity] else: # fin d'une note: rempli le tableau de 1 depuis le début de cette note if currentNotes[pitch][0] == -1: continue for k in range(currentNotes[pitch][0], n): if k not in noteTimeline: noteTimeline[k] = [] # ajout de la clé de temps <k> vel = currentNotes[pitch][1] noteTimeline[k].append( (pitch, vel) ) currentNotes[pitch] = [-1, 0] # conversion en tableau des notes par étapes timeline = [[0 for k in range(36 + 3)] for n in range(max(noteTimeline.keys())+2)] print('File', name, 'of length:', len(timeline), 'loaded.') for n in noteTimeline: vel = 0 for p, v in noteTimeline[n]: vel += v timeline[n+1][p] = 1 timeline[n+1][36] = (vel/len(noteTimeline[n]))/36 # moyennage de la vitesse # trim les étapes vides au début while all(tm == 0 for tm in timeline[0]): timeline.pop(0) # trim les étapes selon la limite de temps if timeLimit < 0: # trim les étapes vides à la fin while all(tm == 0 for tm in timeline[-1]): timeline.pop() else: # trim les étapes jusqu'à la limite de temps timeline = timeline[:int(timeLimit/step)] # signaux de début et fin timeline = [[1*(i==37) for i in range(39)]] + timeline + [[1*(i==38) for i in range(39)]] return np.asarray(timeline)
def makeFile(data, filename, step=10): """ écrit un fichier à partir d'une liste échantillonée de notes """ # ajout d'une frame vide pour l'arrêt des notes data += [0 for i in range(131)] # création du fichier m = midi.MidiFile() m.ticksPerQuarterNote = 480 m.format = 0 tr = midi.MidiTrack(0) # delta_time 0 e = midi.DeltaTime(tr) e.time = 0 tr.events.append(e) # sequence_track_name (nom général) e = midi.MidiEvent(tr) e.channel = None e.type = 'SEQUENCE_TRACK_NAME' e.data = b'Generated file at '+filename.encode('latin') tr.events.append(e) # delta_time 0 e = midi.DeltaTime(tr) e.time = 0 tr.events.append(e) # sequence_track_name (nom de la piste) e = midi.MidiEvent(tr) e.channel = None e.type = 'SEQUENCE_TRACK_NAME' e.data = b'Generated track' tr.events.append(e) # delta_time 0 e = midi.DeltaTime(tr) e.time = 0 tr.events.append(e) # text_event (détails) e = midi.MidiEvent(tr) e.channel = None e.type = 'TEXT_EVENT' e.data = b'Generated by a LSTM' tr.events.append(e) # delta_time 0 e = midi.DeltaTime(tr) e.time = 0 tr.events.append(e) # smtpe_offset (obligatoire?) e = midi.MidiEvent(tr) e.channel = None e.type = 'SMTPE_OFFSET' e.data = b'`\x00\x03\x00\x00' tr.events.append(e) # delta_time 0 e = midi.DeltaTime(tr) e.time = 0 tr.events.append(e) # key_signature (obligatoire?) e = midi.MidiEvent(tr) e.channel = None e.type = 'KEY_SIGNATURE' e.data = b'\xff\x00' tr.events.append(e) # delta_time 0 e = midi.DeltaTime(tr) e.time = 0 tr.events.append(e) # set_tempo e = midi.MidiEvent(tr) e.channel = None e.type = 'SET_TEMPO' e.data = to3bytes(int(3*step*480*10)) # on choisi 30 ticks/frame, et 480 ticks/noire (limite au 1/8eme de croche) tr.events.append(e) # ajout des notes currentlyPlaying = [0 for i in range(128)] lastChange = -1 print(data[-1]) for n in range(len(data)): # print(len(data[n])) if type(data[n]) == type([]): frame = data[n][:128] changes = [i for i in range(128) if frame[i] != currentlyPlaying[i]] if len(changes) > 0: # delta_time e = midi.DeltaTime(tr) e.time = 30*(n-lastChange) tr.events.append(e) # note 0 e = midi.MidiEvent(tr) e.channel = 1 e.type = 'NOTE_ON' e.pitch = changes[0] if frame[changes[0]] == 1: e.velocity = max(min(int(data[n][128]*128),127),0) else: e.velocity = 0 tr.events.append(e) for i in range(len(changes)-1): # delta_time e = midi.DeltaTime(tr) e.time = 0 tr.events.append(e) # note 0 e = midi.MidiEvent(tr) e.channel = 1 e.type = 'NOTE_ON' e.pitch = changes[i+1] if frame[changes[i+1]] == 1: e.velocity = max(min(int(data[n][128]*128),127),0) else: e.velocity = 0 tr.events.append(e) lastChange = n currentlyPlaying = frame # delta_time 0 e = midi.DeltaTime(tr) e.time = 0 tr.events.append(e) # fin de piste e = midi.MidiEvent(tr) e.channel = None e.type = 'END_OF_TRACK' e.data = b'' tr.events.append(e) m.tracks.append(tr) # débug f = open('midi_write.txt', 'w') print(m.tracks[0], file=f) f.close() # écriture m.open(filename, 'wb') m.write() m.close()
def CreateWaterfall(self): midi_file = midi.MidiFile(self.songs[self.current_song]) self.waterfall = waterfall.Waterfall(self.piano_input_obj, self.piano_display, midi_file)
def main(): midi_file = midi.MidiFile(sys.argv[1]) waterfall = Waterfall(piano_input_mock.PianoInput(), piano_output.PianoOutput(), midi_file) waterfall.Continue(slowdown_factor=1)