From 3c6a3c4642bca33cdd5b8951092f037dbc5bcae7 Mon Sep 17 00:00:00 2001 From: Paul Brossier Date: Mon, 4 Sep 2017 15:19:10 +0200 Subject: [PATCH] python/demos/demo_wav2midi.py: add simple midi file writer using mido (closes: #134) --- python/demos/demo_wav2midi.py | 81 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100755 python/demos/demo_wav2midi.py diff --git a/python/demos/demo_wav2midi.py b/python/demos/demo_wav2midi.py new file mode 100755 index 00000000..f503dc0a --- /dev/null +++ b/python/demos/demo_wav2midi.py @@ -0,0 +1,81 @@ +#! /usr/bin/env python + +# Simple demo to extract notes from a sound file, and store them in a midi file +# using mido. +# +# Install mido: `pip instal mido` +# +# Documentation: https://mido.readthedocs.io/ + +import sys +from aubio import source, notes +from mido import Message, MetaMessage, MidiFile, MidiTrack, second2tick, bpm2tempo + +if len(sys.argv) < 3: + print("Usage: %s [samplerate]" % sys.argv[0]) + sys.exit(1) + +filename = sys.argv[1] +midioutput = sys.argv[2] + +downsample = 1 +samplerate = 44100 // downsample +if len( sys.argv ) > 3: samplerate = int(sys.argv[3]) + +win_s = 512 // downsample # fft size +hop_s = 256 // downsample # hop size + +s = source(filename, samplerate, hop_s) +samplerate = s.samplerate + +tolerance = 0.8 + +notes_o = notes("default", win_s, hop_s, samplerate) + +print("%8s" % "time","[ start","vel","last ]") + +# create a midi file +mid = MidiFile() +track = MidiTrack() +mid.tracks.append(track) + +ticks_per_beat = mid.ticks_per_beat # default: 480 +bpm = 120 # default midi tempo + +tempo = bpm2tempo(bpm) +track.append(MetaMessage('set_tempo', tempo=tempo)) +track.append(MetaMessage('time_signature', numerator=4, denominator=4)) + +def frames2tick(frames, samplerate=samplerate): + sec = frames / float(samplerate) + tick = int(second2tick(sec, ticks_per_beat, tempo)) + return tick + +sec = 7 +previous_note = None + +last_time = 0 + +# total number of frames read +total_frames = 0 +while True: + samples, read = s() + new_note = notes_o(samples) + if (new_note[0] != 0): + note_str = ' '.join(["%.2f" % i for i in new_note]) + print("%.6f" % (total_frames/float(samplerate)), new_note) + delta = frames2tick(total_frames) - last_time + if new_note[2] > 0: + track.append(Message('note_off', note=int(new_note[2]), + velocity=127, time=0) + ) + track.append(Message('note_on', + note=int(new_note[0]), + velocity=int(new_note[1]), + time=delta) + ) + last_time = frames2tick(total_frames) + total_frames += read + if read < hop_s: break + +mid.save(midioutput) -- 2.11.0