Showing the changes to python (1 of 1 file). Show all
Unified · Split
| @@ -0,0 +1,81 @@ | |||
| 1 | #! /usr/bin/env python | ||
| 2 | |||
| 3 | # Simple demo to extract notes from a sound file, and store them in a midi file | ||
| 4 | # using mido. | ||
| 5 | # | ||
| 6 | # Install mido: `pip instal mido` | ||
| 7 | # | ||
| 8 | # Documentation: https://mido.readthedocs.io/ | ||
| 9 | |||
| 10 | import sys | ||
| 11 | from aubio import source, notes | ||
| 12 | from mido import Message, MetaMessage, MidiFile, MidiTrack, second2tick, bpm2tempo | ||
| 13 | |||
| 14 | if len(sys.argv) < 3: | ||
| 15 | print("Usage: %s <filename> <output> [samplerate]" % sys.argv[0]) | ||
| 16 | sys.exit(1) | ||
| 17 | |||
| 18 | filename = sys.argv[1] | ||
| 19 | midioutput = sys.argv[2] | ||
| 20 | |||
| 21 | downsample = 1 | ||
| 22 | samplerate = 44100 // downsample | ||
| 23 | if len( sys.argv ) > 3: samplerate = int(sys.argv[3]) | ||
| 24 | |||
| 25 | win_s = 512 // downsample # fft size | ||
| 26 | hop_s = 256 // downsample # hop size | ||
| 27 | |||
| 28 | s = source(filename, samplerate, hop_s) | ||
| 29 | samplerate = s.samplerate | ||
| 30 | |||
| 31 | tolerance = 0.8 | ||
| 32 | |||
| 33 | notes_o = notes("default", win_s, hop_s, samplerate) | ||
| 34 | |||
| 35 | print("%8s" % "time","[ start","vel","last ]") | ||
| 36 | |||
| 37 | # create a midi file | ||
| 38 | mid = MidiFile() | ||
| 39 | track = MidiTrack() | ||
| 40 | mid.tracks.append(track) | ||
| 41 | |||
| 42 | ticks_per_beat = mid.ticks_per_beat # default: 480 | ||
| 43 | bpm = 120 # default midi tempo | ||
| 44 | |||
| 45 | tempo = bpm2tempo(bpm) | ||
| 46 | track.append(MetaMessage('set_tempo', tempo=tempo)) | ||
| 47 | track.append(MetaMessage('time_signature', numerator=4, denominator=4)) | ||
| 48 | |||
| 49 | def frames2tick(frames, samplerate=samplerate): | ||
| 50 | sec = frames / float(samplerate) | ||
| 51 | tick = int(second2tick(sec, ticks_per_beat, tempo)) | ||
| 52 | return tick | ||
| 53 | |||
| 54 | sec = 7 | ||
| 55 | previous_note = None | ||
| 56 | |||
| 57 | last_time = 0 | ||
| 58 | |||
| 59 | # total number of frames read | ||
| 60 | total_frames = 0 | ||
| 61 | while True: | ||
| 62 | samples, read = s() | ||
| 63 | new_note = notes_o(samples) | ||
| 64 | if (new_note[0] != 0): | ||
| 65 | note_str = ' '.join(["%.2f" % i for i in new_note]) | ||
| 66 | print("%.6f" % (total_frames/float(samplerate)), new_note) | ||
| 67 | delta = frames2tick(total_frames) - last_time | ||
| 68 | if new_note[2] > 0: | ||
| 69 | track.append(Message('note_off', note=int(new_note[2]), | ||
| 70 | velocity=127, time=0) | ||
| 71 | ) | ||
| 72 | track.append(Message('note_on', | ||
| 73 | note=int(new_note[0]), | ||
| 74 | velocity=int(new_note[1]), | ||
| 75 | time=delta) | ||
| 76 | ) | ||
| 77 | last_time = frames2tick(total_frames) | ||
| 78 | total_frames += read | ||
| 79 | if read < hop_s: break | ||
| 80 | |||
| 81 | mid.save(midioutput) | ||