3 # Simple demo to extract notes from a sound file, and store them in a midi file
6 # Install mido: `pip instal mido`
8 # Documentation: https://mido.readthedocs.io/
11 from aubio import source, notes
12 from mido import Message, MetaMessage, MidiFile, MidiTrack, second2tick, bpm2tempo
15 print("Usage: %s <filename> <output> [samplerate]" % sys.argv[0])
18 filename = sys.argv[1]
19 midioutput = sys.argv[2]
22 samplerate = 44100 // downsample
23 if len( sys.argv ) > 3: samplerate = int(sys.argv[3])
25 win_s = 512 // downsample # fft size
26 hop_s = 256 // downsample # hop size
28 s = source(filename, samplerate, hop_s)
29 samplerate = s.samplerate
33 notes_o = notes("default", win_s, hop_s, samplerate)
35 print("%8s" % "time","[ start","vel","last ]")
40 mid.tracks.append(track)
42 ticks_per_beat = mid.ticks_per_beat # default: 480
43 bpm = 120 # default midi tempo
45 tempo = bpm2tempo(bpm)
46 track.append(MetaMessage('set_tempo', tempo=tempo))
47 track.append(MetaMessage('time_signature', numerator=4, denominator=4))
49 def frames2tick(frames, samplerate=samplerate):
50 sec = frames / float(samplerate)
51 return int(second2tick(sec, ticks_per_beat, tempo))
55 # total number of frames read
59 new_note = notes_o(samples)
60 if (new_note[0] != 0):
61 note_str = ' '.join(["%.2f" % i for i in new_note])
62 print("%.6f" % (total_frames/float(samplerate)), new_note)
63 delta = frames2tick(total_frames) - last_time
65 track.append(Message('note_off', note=int(new_note[2]),
68 track.append(Message('note_on',
69 note=int(new_note[0]),
70 velocity=int(new_note[1]),
73 last_time = frames2tick(total_frames)
75 if read < hop_s: break