From 459e46f3fb2f28aaf722ddfd23764a004d5b1788 Mon Sep 17 00:00:00 2001 From: Paul Brossier Date: Fri, 8 Mar 2013 13:13:43 -0500 Subject: [PATCH] python/demos/: update and add some demos --- python/demos/aubiocut | 155 --------------------------- python/demos/demo_beats_and_tempo.py | 41 ------- python/demos/demo_onset.py | 8 +- python/demos/demo_onset_plot.py | 17 ++- python/demos/demo_tempo.py | 40 +++++++ python/demos/demo_tempo_plot.py | 84 +++++++++++++++ 6 files changed, 142 insertions(+), 203 deletions(-) delete mode 100755 python/demos/aubiocut delete mode 100755 python/demos/demo_beats_and_tempo.py create mode 100755 python/demos/demo_tempo.py create mode 100755 python/demos/demo_tempo_plot.py diff --git a/python/demos/aubiocut b/python/demos/aubiocut deleted file mode 100755 index e8017334..00000000 --- a/python/demos/aubiocut +++ /dev/null @@ -1,155 +0,0 @@ -#! /usr/bin/env python - -""" this file was written by Paul Brossier - it is released under the GNU/GPL license. -""" - -import sys -#from aubio.task import * - -usage = "usage: %s [options] -i soundfile" % sys.argv[0] - -def parse_args(): - from optparse import OptionParser - parser = OptionParser(usage=usage) - parser.add_option("-i", "--input", action = "store", dest = "source_file", - help="input sound file to analyse", metavar = "") - parser.add_option("-m","--method", - action="store", dest="onset_method", default='default', - metavar = "", - help="onset detection method [default=default] \ - complexdomain|hfc|phase|specdiff|energy|kl|mkl") - # cutting methods - """ - parser.add_option("-b","--beat", - action="store_true", dest="beat", default=False, - help="use beat locations") - parser.add_option("-S","--silencecut", - action="store_true", dest="silencecut", default=False, - help="use silence locations") - parser.add_option("-s","--silence", - metavar = "", - action="store", dest="silence", default=-70, - help="silence threshold [default=-70]") - """ - # algorithm parameters - parser.add_option("--samplerate", - metavar = "", type='int', - action="store", dest="samplerate", default=0, - help="samplerate at which the file should be represented") - parser.add_option("-B","--bufsize", - action="store", dest="bufsize", default=512, - metavar = "", - help="buffer size [default=512]") - parser.add_option("-H","--hopsize", - metavar = "", - action="store", dest="hopsize", default=256, - help="overlap size [default=256]") - parser.add_option("-t","--threshold", - metavar = "", type="float", - action="store", dest="threshold", default=0.3, - help="onset peak picking threshold [default=0.3]") - """ - parser.add_option("-c","--cut", - action="store_true", dest="cut", default=False, - help="cut input sound file at detected labels \ - best used with option -L") - parser.add_option("-D","--delay", - action = "store", dest = "delay", type = "float", - metavar = "", default=0, - help="number of seconds to take back [default=system]\ - default system delay is 3*hopsize/samplerate") - parser.add_option("-C","--dcthreshold", - metavar = "", - action="store", dest="dcthreshold", default=1., - help="onset peak picking DC component [default=1.]") - parser.add_option("-M","--mintol", - metavar = "", - action="store", dest="mintol", default=0.048, - help="minimum inter onset interval [default=0.048]") - parser.add_option("-L","--localmin", - action="store_true", dest="localmin", default=False, - help="use local minima after peak detection") - parser.add_option("-d","--derivate", - action="store_true", dest="derivate", default=False, - help="derivate onset detection function") - parser.add_option("-z","--zerocross", - metavar = "", - action="store", dest="zerothres", default=0.008, - help="zero-crossing threshold for slicing [default=0.00008]") - """ - # plotting functions - """ - parser.add_option("-p","--plot", - action="store_true", dest="plot", default=False, - help="draw plot") - parser.add_option("-x","--xsize", - metavar = "", - action="store", dest="xsize", default=1., - type='float', help="define xsize for plot") - parser.add_option("-y","--ysize", - metavar = "", - action="store", dest="ysize", default=1., - type='float', help="define ysize for plot") - parser.add_option("-f","--function", - action="store_true", dest="func", default=False, - help="print detection function") - parser.add_option("-n","--no-onsets", - action="store_true", dest="nplot", default=False, - help="do not plot detected onsets") - parser.add_option("-O","--outplot", - metavar = "", - action="store", dest="outplot", default=None, - help="save plot to output.{ps,png}") - parser.add_option("-F","--spectrogram", - action="store_true", dest="spectro", default=False, - help="add spectrogram to the plot") - """ - parser.add_option("-v","--verbose", - action="store_true", dest="verbose", default=True, - help="make lots of noise [default]") - parser.add_option("-q","--quiet", - action="store_false", dest="verbose", default=True, - help="be quiet") - (options, args) = parser.parse_args() - if not options.source_file: - print "no file name given\n", usage - sys.exit(1) - return options, args - -if __name__ == '__main__': - options, args = parse_args() - - hopsize = options.hopsize - bufsize = options.bufsize - samplerate = options.samplerate - source_file = options.source_file - - from aubio import onset, source - - s = source(source_file, samplerate, hopsize) - if samplerate == 0: samplerate = s.get_samplerate() - - o = onset(options.onset_method, bufsize, hopsize) - o.set_threshold(options.threshold) - - - timestamps = [] - block_read = 0 - while True: - samples, read = s() - is_onset = o(samples) - if is_onset: - this_onset = (block_read * hopsize - is_onset[0]) - if options.verbose: - print "%.4f" % ( this_onset / samplerate ) - timestamps.append (this_onset) - block_read += 1 - if read < hopsize: break - - # print some info - duration = float ( block_read * hopsize + read ) / samplerate - nstamps = len(timestamps) - info = 'found %(nstamps)d timestamps in %(source_file)s' % locals() - info += ' (read %(duration).2fs at %(samplerate)dHz)\n' % locals() - sys.stderr.write(info) diff --git a/python/demos/demo_beats_and_tempo.py b/python/demos/demo_beats_and_tempo.py deleted file mode 100755 index 76094e1f..00000000 --- a/python/demos/demo_beats_and_tempo.py +++ /dev/null @@ -1,41 +0,0 @@ -#! /usr/bin/env python - -import sys -from aubio import tempo, source - -win_s = 512 # fft size -hop_s = win_s / 2 # hop size -samplerate = 44100 - -if len(sys.argv) < 2: - print "Usage: %s " % sys.argv[0] - sys.exit(1) - -filename = sys.argv[1] -beats = [] - -s = source(filename, samplerate, hop_s) -t = tempo("default", win_s, hop_s) - -block_read = 0 -while True: - samples, read = s() - isbeat = t(samples) - if isbeat: - thisbeat = (block_read * hop_s + isbeat[0]) / samplerate - print "%.4f" % thisbeat - beats.append (thisbeat) - block_read += 1 - if read < hop_s: break - -periods = [60./(b - a) for a,b in zip(beats[:-1],beats[1:])] - -from numpy import mean, median -if len(periods): - print 'mean period:', "%.2f" % mean(periods), 'bpm', 'median', "%.2f" % median(periods), 'bpm' - if 0: - from pylab import plot, show - plot(beats[1:], periods) - show() -else: - print 'mean period:', "%.2f" % 0, 'bpm', 'median', "%.2f" % 0, 'bpm' diff --git a/python/demos/demo_onset.py b/python/demos/demo_onset.py index 20e7bf05..75c6f1c5 100755 --- a/python/demos/demo_onset.py +++ b/python/demos/demo_onset.py @@ -18,12 +18,16 @@ if len( sys.argv ) > 2: samplerate = int(sys.argv[2]) s = source(filename, samplerate, hop_s) samplerate = s.samplerate -o = onset("default", win_s, hop_s) +o = onset("default", win_s, hop_s, samplerate) -# onset detection delay, in blocks +# onset detection delay, in samples +# default to 4 blocks delay to catch up with delay = 4. * hop_s +# list of onsets, in samples onsets = [] + +# total number of frames read total_frames = 0 while True: samples, read = s() diff --git a/python/demos/demo_onset_plot.py b/python/demos/demo_onset_plot.py index cfdf16b9..513c579d 100755 --- a/python/demos/demo_onset_plot.py +++ b/python/demos/demo_onset_plot.py @@ -18,11 +18,13 @@ if len( sys.argv ) > 2: samplerate = int(sys.argv[2]) s = source(filename, samplerate, hop_s) samplerate = s.samplerate -o = onset("default", win_s, hop_s) +o = onset("default", win_s, hop_s, samplerate) -# onset detection delay, in blocks +# onset detection delay, in samples +# default to 4 blocks delay to catch up with delay = 4. * hop_s +# list of onsets, in samples onsets = [] # storage for plotted data @@ -31,6 +33,7 @@ tdesc = [] allsamples_max = zeros(0,) downsample = 2 # to plot n samples / hop_s +# total number of frames read total_frames = 0 while True: samples, read = s() @@ -38,7 +41,7 @@ while True: if is_onset: this_onset = int(total_frames - delay + is_onset[0] * hop_s) print "%f" % (this_onset / float(samplerate)) - onsets.append(this_onset / float(samplerate)) + onsets.append(this_onset) # keep some data to plot it later new_maxes = (abs(samples.reshape(hop_s/downsample, downsample))).max(axis=0) allsamples_max = hstack([allsamples_max, new_maxes]) @@ -58,7 +61,9 @@ if 1: plt.rc('lines',linewidth='.8') plt1.plot(allsamples_max_times, allsamples_max, '-b') plt1.plot(allsamples_max_times, -allsamples_max, '-b') - for stamp in onsets: plt1.plot([stamp, stamp], [-1., 1.], '-r') + for stamp in onsets: + stamp /= float(samplerate) + plt1.plot([stamp, stamp], [-1., 1.], '-r') plt1.axis(xmin = 0., xmax = max(allsamples_max_times) ) plt1.xaxis.set_visible(False) plt1.yaxis.set_visible(False) @@ -66,7 +71,9 @@ if 1: desc_plot = [d / max(desc) for d in desc] plt2.plot(desc_times, desc_plot, '-g') tdesc_plot = [d / max(desc) for d in tdesc] - for stamp in onsets: plt2.plot([stamp, stamp], [min(tdesc_plot), max(desc_plot)], '-r') + for stamp in onsets: + stamp /= float(samplerate) + plt2.plot([stamp, stamp], [min(tdesc_plot), max(desc_plot)], '-r') plt2.plot(desc_times, tdesc_plot, '-y') plt2.axis(ymin = min(tdesc_plot), ymax = max(desc_plot)) plt.xlabel('time (s)') diff --git a/python/demos/demo_tempo.py b/python/demos/demo_tempo.py new file mode 100755 index 00000000..17b959be --- /dev/null +++ b/python/demos/demo_tempo.py @@ -0,0 +1,40 @@ +#! /usr/bin/env python + +import sys +from aubio import tempo, source + +win_s = 512 # fft size +hop_s = win_s / 2 # hop size + +if len(sys.argv) < 2: + print "Usage: %s [samplerate]" % sys.argv[0] + sys.exit(1) + +filename = sys.argv[1] + +samplerate = 0 +if len( sys.argv ) > 2: samplerate = int(sys.argv[2]) + +s = source(filename, samplerate, hop_s) +samplerate = s.samplerate +o = tempo("default", win_s, hop_s, samplerate) + +# tempo detection delay, in samples +# default to 4 blocks delay to catch up with +delay = 4. * hop_s + +# list of beats, in samples +beats = [] + +# total number of frames read +total_frames = 0 +while True: + samples, read = s() + is_beat = o(samples) + if is_beat: + this_beat = int(total_frames - delay + is_beat[0] * hop_s) + print "%f" % (this_beat / float(samplerate)) + beats.append(this_beat) + total_frames += read + if read < hop_s: break +#print len(beats) diff --git a/python/demos/demo_tempo_plot.py b/python/demos/demo_tempo_plot.py new file mode 100755 index 00000000..dd1cd9b1 --- /dev/null +++ b/python/demos/demo_tempo_plot.py @@ -0,0 +1,84 @@ +#! /usr/bin/env python + +import sys +from aubio import tempo, source + +win_s = 512 # fft size +hop_s = win_s / 2 # hop size + +if len(sys.argv) < 2: + print "Usage: %s [samplerate]" % sys.argv[0] + sys.exit(1) + +filename = sys.argv[1] + +samplerate = 0 +if len( sys.argv ) > 2: samplerate = int(sys.argv[2]) + +s = source(filename, samplerate, hop_s) +samplerate = s.samplerate +o = tempo("default", win_s, hop_s, samplerate) + +# tempo detection delay, in samples +# default to 4 blocks delay to catch up with +delay = 4. * hop_s + +# list of beats, in samples +beats = [] + +# total number of frames read +total_frames = 0 +while True: + samples, read = s() + is_beat = o(samples) + if is_beat: + this_beat = int(total_frames - delay + is_beat[0] * hop_s) + #print "%f" % (this_beat / float(samplerate)) + beats.append(this_beat) + total_frames += read + if read < hop_s: break + +#convert samples to seconds +beats = map( lambda x: x / float(samplerate), beats) + +bpms = [60./(b - a) for a,b in zip(beats[:-1],beats[1:])] + +if len(bpms): + print 'mean period:', "%.2f" % mean(bpms), 'bpm', 'median', "%.2f" % median(bpms), 'bpm' + print 'plotting', filename + # do plotting + from numpy import array, arange, mean, median + import matplotlib.pyplot as plt + plt1 = plt.axes([0.1, 0.75, 0.8, 0.19]) + plt2 = plt.axes([0.1, 0.1, 0.8, 0.65], sharex = plt1) + plt.rc('lines',linewidth='.8') + for stamp in beats: plt1.plot([stamp, stamp], [-1., 1.], '-r') + plt1.axis(xmin = 0., xmax = total_frames / float(samplerate) ) + plt1.xaxis.set_visible(False) + plt1.yaxis.set_visible(False) + + # plot actual periods + plt2.plot(beats[1:], bpms, '-', label = 'raw') + + # plot moving median of 5 last periods + median_win_s = 5 + bpms_median = [ median(bpms[i:i + median_win_s:1]) for i in range(len(bpms) - median_win_s ) ] + plt2.plot(beats[median_win_s+1:], bpms_median, '-', label = 'median of %d' % median_win_s) + # plot moving median of 10 last periods + median_win_s = 20 + bpms_median = [ median(bpms[i:i + median_win_s:1]) for i in range(len(bpms) - median_win_s ) ] + plt2.plot(beats[median_win_s+1:], bpms_median, '-', label = 'median of %d' % median_win_s) + + plt2.axis(ymin = min(bpms), ymax = max(bpms)) + #plt2.axis(ymin = 40, ymax = 240) + plt.xlabel('time (mm:ss)') + plt.ylabel('beats per minute (bpm)') + plt2.set_xticklabels([ "%02d:%02d" % (t/60, t%60) for t in plt2.get_xticks()[:-1]], rotation = 50) + + #plt.savefig('/tmp/t.png', dpi=200) + plt2.legend() + plt.show() + +else: + print 'mean period:', "%.2f" % 0, 'bpm', 'median', "%.2f" % 0, 'bpm', + print 'nothing to plot, file too short?' -- 2.26.2