History

Merge branch 'master' into feature/pytest

Paul Brossier committed 8 years ago

Commit 568fc602 parents a9e3bd0 bc1ed6315 files · +236 −170Browse files

Showing the changes to python (10 of 15 files). Show all

Unified · Split

10 files
  1. python/demos/demo_filter.py +6 −4
  2. python/demos/demo_filterbank.py +31 −17
  3. python/demos/demo_source_simple.py +10 −6
  4. python/ext/py-sink.c +1 −1
  5. python/ext/py-source.c +3 −3
  6. python/lib/aubio/__init__.py +1 −0
  7. python/lib/aubio/cmd.py +65 −31
  8. python/lib/aubio/cut.py +29 −49
  9. python/lib/aubio/midiconv.py +17 −12
  10. python/lib/aubio/slicing.py +10 −11
python/demos/demo_filter.py+6−4
@@ -4,6 +4,7 @@ import sys · 3 unmodified lines
4import os.path4import os.path
5import aubio5import aubio
6 6
7
7def apply_filter(path, target):8def apply_filter(path, target):
8 # open input file, get its samplerate9 # open input file, get its samplerate
9 s = aubio.source(path)10 s = aubio.source(path)
@@ -27,19 +28,20 @@ def apply_filter(path, target): · 17 unmodified lines
27 # count frames read28 # count frames read
28 total_frames += read29 total_frames += read
29 # end of file reached30 # end of file reached
30 if read < s.hop_size: break31 if read < s.hop_size:
32 break
31 33
32 # print some info34 # print some info
33 duration = total_frames / float(samplerate)35 duration = total_frames / float(samplerate)
34 input_str = "input: {:s} ({:.2f} s, {:d} Hz)"36 input_str = "input: {:s} ({:.2f} s, {:d} Hz)"
35 output_str = "output: {:s}, A-weighting filtered ({:d} frames total)"37 output_str = "output: {:s}, A-weighting filtered ({:d} frames total)"
36 print (input_str.format(s.uri, duration, samplerate))38 print(input_str.format(s.uri, duration, samplerate))
37 print (output_str.format(o.uri, total_frames))39 print(output_str.format(o.uri, total_frames))
38 40
39if __name__ == '__main__':41if __name__ == '__main__':
40 usage = "{:s} <input_file> [output_file]".format(sys.argv[0])42 usage = "{:s} <input_file> [output_file]".format(sys.argv[0])
41 if not 1 < len(sys.argv) < 4:43 if not 1 < len(sys.argv) < 4:
42 print (usage)44 print(usage)
43 sys.exit(1)45 sys.exit(1)
44 if len(sys.argv) < 3:46 if len(sys.argv) < 3:
45 input_path = sys.argv[1]47 input_path = sys.argv[1]
python/demos/demo_filterbank.py+31−17
@@ -1,30 +1,44 @@
1#! /usr/bin/env python1#! /usr/bin/env python
2 2
3from aubio import filterbank, fvec3"""Create a filterbank from a list of frequencies.
4from pylab import loglog, show, xlim, ylim, xlabel, ylabel, title
5from numpy import vstack, arange
6 4
7win_s = 20485This demo uses `aubio.filterbank.set_triangle_bands` to build a set of
6triangular filters from a list of frequencies.
7
8The filterbank coefficients are then modified before being displayed."""
9
10import aubio
11import numpy as np
12import matplotlib.pyplot as plt
13
14# sampling rate and size of the fft
8samplerate = 4800015samplerate = 48000
16win_s = 2048
9 17
18# define a list of custom frequency
10freq_list = [60, 80, 200, 400, 800, 1600, 3200, 6400, 12800, 24000]19freq_list = [60, 80, 200, 400, 800, 1600, 3200, 6400, 12800, 24000]
20# number of filters to create
11n_filters = len(freq_list) - 221n_filters = len(freq_list) - 2
12 22
13f = filterbank(n_filters, win_s)23# create a new filterbank
14freqs = fvec(freq_list)24f = aubio.filterbank(n_filters, win_s)
25freqs = aubio.fvec(freq_list)
15f.set_triangle_bands(freqs, samplerate)26f.set_triangle_bands(freqs, samplerate)
16 27
28# get the coefficients from the filterbank
17coeffs = f.get_coeffs()29coeffs = f.get_coeffs()
18coeffs[4] *= 5.30# apply a gain to fifth band
19 31coeffs[4] *= 6.
32# load the modified coeffs into the filterbank
20f.set_coeffs(coeffs)33f.set_coeffs(coeffs)
21 34
22times = vstack([arange(win_s // 2 + 1) * samplerate / win_s] * n_filters)35# display the band gains in a loglog plot
23title('Bank of filters built using a simple list of boundaries\nThe middle band has been amplified by 2.')36freqs = np.vstack([np.arange(win_s // 2 + 1) * samplerate / win_s] * n_filters)
24loglog(times.T, f.get_coeffs().T, '.-')37plt.title('filterbank built from a list of frequencies\n'
25xlim([50, samplerate/2])38 'The 5th band has been amplified by a factor 6.')
26ylim([1.0e-6, 2.0e-2])39plt.loglog(freqs.T, f.get_coeffs().T, '.-')
27xlabel('log frequency (Hz)')40plt.xlim([50, samplerate/2])
28ylabel('log amplitude')41plt.ylim([1.0e-6, 2.0e-2])
29 42plt.xlabel('log frequency (Hz)')
30show()43plt.ylabel('log amplitude')
44plt.show()
python/demos/demo_source_simple.py+10−6
@@ -1,16 +1,20 @@
1#! /usr/bin/env python1#! /usr/bin/env python
2
3"""A simple example using aubio.source."""
4
2import sys5import sys
3import aubio6import aubio
4 7
5samplerate = 0 # use original source samplerate8samplerate = 0 # use original source samplerate
6hop_size = 256 # number of frames to read in one block9hop_size = 256 # number of frames to read in one block
7src = aubio.source(sys.argv[1], samplerate, hop_size)10src = aubio.source(sys.argv[1], samplerate, hop_size)
8total_frames = 011total_frames = 0
9 12
10while True:13while True:
11 samples, read = src() # read hop_size new samples from source14 samples, read = src() # read hop_size new samples from source
12 total_frames += read # increment total number of frames15 total_frames += read # increment total number of frames
13 if read < hop_size: break # end of file reached16 if read < hop_size: # end of file reached
17 break
14 18
15fmt_string = "read {:d} frames at {:d}Hz from {:s}"19fmt_string = "read {:d} frames at {:d}Hz from {:s}"
16print (fmt_string.format(total_frames, src.samplerate, src.uri))20print(fmt_string.format(total_frames, src.samplerate, src.uri))
python/ext/py-sink.c+1−1
@@ -14,7 +14,7 @@ typedef struct · 13 unmodified lines
14static char Py_sink_doc[] = ""14static char Py_sink_doc[] = ""
15"sink(path, samplerate=44100, channels=1)\n"15"sink(path, samplerate=44100, channels=1)\n"
16"\n"16"\n"
17"Open `path` to write a WAV file.\n"17"Write audio samples to file.\n"
18"\n"18"\n"
19"Parameters\n"19"Parameters\n"
20"----------\n"20"----------\n"
python/ext/py-source.c+3−3
@@ -18,7 +18,7 @@ typedef struct · 17 unmodified lines
18static char Py_source_doc[] = ""18static char Py_source_doc[] = ""
19"source(path, samplerate=0, hop_size=512, channels=0)\n"19"source(path, samplerate=0, hop_size=512, channels=0)\n"
20"\n"20"\n"
21"Create a new source, opening the given pathname for reading.\n"21"Read audio samples from a media file.\n"
22"\n"22"\n"
23"`source` open the file specified in `path` and creates a callable\n"23"`source` open the file specified in `path` and creates a callable\n"
24"returning `hop_size` new audio samples at each invocation.\n"24"returning `hop_size` new audio samples at each invocation.\n"
@@ -247,7 +247,7 @@ static char Py_source_do_doc[] = "" · 222 unmodified lines
247"\n"247"\n"
248"Returns\n"248"Returns\n"
249"-------\n"249"-------\n"
250"samples : numpy.ndarray, shape `(hop_size,)`, dtype aubio.float_type\n"250"samples : numpy.ndarray\n"
251" `fvec` of size `hop_size` containing the new samples.\n"251" `fvec` of size `hop_size` containing the new samples.\n"
252"read : int\n"252"read : int\n"
253" Number of samples read from the source, equals to `hop_size`\n"253" Number of samples read from the source, equals to `hop_size`\n"
@@ -283,7 +283,7 @@ static char Py_source_do_multi_doc[] = "" · 29 unmodified lines
283"\n"283"\n"
284"Returns\n"284"Returns\n"
285"-------\n"285"-------\n"
286"samples : np.ndarray([hop_size, channels], dtype=aubio.float_type)\n"286"samples : numpy.ndarray\n"
287" NumPy array of shape `(hop_size, channels)` containing the new\n"287" NumPy array of shape `(hop_size, channels)` containing the new\n"
288" audio samples.\n"288" audio samples.\n"
289"read : int\n"289"read : int\n"
python/lib/aubio/__init__.py+1−0
@@ -29,6 +29,7 @@ from ._aubio import * · 28 unmodified lines
29from .midiconv import *29from .midiconv import *
30from .slicing import *30from .slicing import *
31 31
32
32class fvec(numpy.ndarray):33class fvec(numpy.ndarray):
33 """fvec(input_arg=1024)34 """fvec(input_arg=1024)
34 A vector holding float samples.35 A vector holding float samples.
python/lib/aubio/cmd.py+65−31
@@ -11,6 +11,7 @@ readable code examples, check out the `python/demos` folder.""" · 10 unmodified lines
11 11
12import sys12import sys
13import argparse13import argparse
14import warnings
14import aubio15import aubio
15 16
16def aubio_parser():17def aubio_parser():
@@ -168,10 +169,10 @@ class AubioArgumentParser(argparse.ArgumentParser): · 151 unmodified lines
168 help="samplerate at which the file should be represented")169 help="samplerate at which the file should be represented")
169 170
170 def add_verbose_help(self):171 def add_verbose_help(self):
171 self.add_argument("-v","--verbose",172 self.add_argument("-v", "--verbose",
172 action="count", dest="verbose", default=1,173 action="count", dest="verbose", default=1,
173 help="make lots of noise [default]")174 help="make lots of noise [default]")
174 self.add_argument("-q","--quiet",175 self.add_argument("-q", "--quiet",
175 action="store_const", dest="verbose", const=0,176 action="store_const", dest="verbose", const=0,
176 help="be quiet")177 help="be quiet")
177 178
@@ -180,25 +181,25 @@ class AubioArgumentParser(argparse.ArgumentParser): · 2 unmodified lines
180 self.add_hop_size(hop_size=hop_size)181 self.add_hop_size(hop_size=hop_size)
181 182
182 def add_buf_size(self, buf_size=512):183 def add_buf_size(self, buf_size=512):
183 self.add_argument("-B","--bufsize",184 self.add_argument("-B", "--bufsize",
184 action="store", dest="buf_size", default=buf_size,185 action="store", dest="buf_size", default=buf_size,
185 metavar = "<size>", type=int,186 metavar = "<size>", type=int,
186 help="buffer size [default=%d]" % buf_size)187 help="buffer size [default=%d]" % buf_size)
187 188
188 def add_hop_size(self, hop_size=256):189 def add_hop_size(self, hop_size=256):
189 self.add_argument("-H","--hopsize",190 self.add_argument("-H", "--hopsize",
190 metavar = "<size>", type=int,191 metavar = "<size>", type=int,
191 action="store", dest="hop_size", default=hop_size,192 action="store", dest="hop_size", default=hop_size,
192 help="overlap size [default=%d]" % hop_size)193 help="overlap size [default=%d]" % hop_size)
193 194
194 def add_method(self, method='default', helpstr='method'):195 def add_method(self, method='default', helpstr='method'):
195 self.add_argument("-m","--method",196 self.add_argument("-m", "--method",
196 metavar = "<method>", type=str,197 metavar = "<method>", type=str,
197 action="store", dest="method", default=method,198 action="store", dest="method", default=method,
198 help="%s [default=%s]" % (helpstr, method))199 help="%s [default=%s]" % (helpstr, method))
199 200
200 def add_threshold(self, default=None):201 def add_threshold(self, default=None):
201 self.add_argument("-t","--threshold",202 self.add_argument("-t", "--threshold",
202 metavar = "<threshold>", type=float,203 metavar = "<threshold>", type=float,
203 action="store", dest="threshold", default=default,204 action="store", dest="threshold", default=default,
204 help="threshold [default=%s]" % default)205 help="threshold [default=%s]" % default)
@@ -239,14 +240,16 @@ class AubioArgumentParser(argparse.ArgumentParser): · 34 unmodified lines
239 help=helpstr)240 help=helpstr)
240 241
241 def add_slicer_options(self):242 def add_slicer_options(self):
242 self.add_argument("-o","--output", type = str,243 self.add_argument("-o", "--output", type = str,
243 metavar = "<outputdir>",244 metavar = "<outputdir>",
244 action="store", dest="output_directory", default=None,245 action="store", dest="output_directory", default=None,
245 help="specify path where slices of the original file should be created")246 help="specify path where slices of the original file should"
247 " be created")
246 self.add_argument("--cut-until-nsamples", type = int,248 self.add_argument("--cut-until-nsamples", type = int,
247 metavar = "<samples>",249 metavar = "<samples>",
248 action = "store", dest = "cut_until_nsamples", default = None,250 action = "store", dest = "cut_until_nsamples", default = None,
249 help="how many extra samples should be added at the end of each slice")251 help="how many extra samples should be added at the end of"
252 " each slice")
250 self.add_argument("--cut-every-nslices", type = int,253 self.add_argument("--cut-every-nslices", type = int,
251 metavar = "<samples>",254 metavar = "<samples>",
252 action = "store", dest = "cut_every_nslices", default = None,255 action = "store", dest = "cut_every_nslices", default = None,
@@ -254,7 +257,8 @@ class AubioArgumentParser(argparse.ArgumentParser): · 1 unmodified line
254 self.add_argument("--cut-until-nslices", type = int,257 self.add_argument("--cut-until-nslices", type = int,
255 metavar = "<slices>",258 metavar = "<slices>",
256 action = "store", dest = "cut_until_nslices", default = None,259 action = "store", dest = "cut_until_nslices", default = None,
257 help="how many extra slices should be added at the end of each slice")260 help="how many extra slices should be added at the end of"
261 " each slice")
258 self.add_argument("--create-first",262 self.add_argument("--create-first",
259 action = "store_true", dest = "create_first", default = False,263 action = "store_true", dest = "create_first", default = False,
260 help="always include first slice")264 help="always include first slice")
@@ -288,7 +292,8 @@ class default_process(object): · 27 unmodified lines
288 self.time2string = timefunc(args.time_format)292 self.time2string = timefunc(args.time_format)
289 if args.verbose > 2 and hasattr(self, 'options'):293 if args.verbose > 2 and hasattr(self, 'options'):
290 name = type(self).__name__.split('_')[1]294 name = type(self).__name__.split('_')[1]
291 optstr = ' '.join(['running', name, 'with options', repr(self.options), '\n'])295 optstr = ' '.join(['running', name, 'with options',
296 repr(self.options), '\n'])
292 sys.stderr.write(optstr)297 sys.stderr.write(optstr)
293 def flush(self, frames_read, samplerate):298 def flush(self, frames_read, samplerate):
294 # optionally called at the end of process299 # optionally called at the end of process
@@ -296,7 +301,7 @@ class default_process(object): · 1 unmodified line
296 301
297 def parse_options(self, args, valid_opts):302 def parse_options(self, args, valid_opts):
298 # get any valid options found in a dictionnary of arguments303 # get any valid options found in a dictionnary of arguments
299 options = {k :v for k,v in vars(args).items() if k in valid_opts}304 options = {k: v for k, v in vars(args).items() if k in valid_opts}
300 self.options = options305 self.options = options
301 306
302 def remap_pvoc_options(self, options):307 def remap_pvoc_options(self, options):
@@ -377,7 +382,7 @@ class process_tempo(process_beat): · 74 unmodified lines
377 if len(self.beat_locations) < 2:382 if len(self.beat_locations) < 2:
378 outstr = "unknown bpm"383 outstr = "unknown bpm"
379 else:384 else:
380 bpms = 60./ np.diff(self.beat_locations)385 bpms = 60. / np.diff(self.beat_locations)
381 median_bpm = np.mean(bpms)386 median_bpm = np.mean(bpms)
382 if len(self.beat_locations) < 10:387 if len(self.beat_locations) < 10:
383 outstr = "%.2f bpm (uncertain)" % median_bpm388 outstr = "%.2f bpm (uncertain)" % median_bpm
@@ -398,14 +403,14 @@ class process_notes(default_process): · 14 unmodified lines
398 def __call__(self, block):403 def __call__(self, block):
399 return self.notes(block)404 return self.notes(block)
400 def repr_res(self, res, frames_read, samplerate):405 def repr_res(self, res, frames_read, samplerate):
401 if res[2] != 0: # note off406 if res[2] != 0: # note off
402 fmt_out = self.time2string(frames_read, samplerate)407 fmt_out = self.time2string(frames_read, samplerate)
403 sys.stdout.write(fmt_out + '\n')408 sys.stdout.write(fmt_out + '\n')
404 if res[0] != 0: # note on409 if res[0] != 0: # note on
405 lastmidi = res[0]410 lastmidi = res[0]
406 fmt_out = "%f\t" % lastmidi411 fmt_out = "%f\t" % lastmidi
407 fmt_out += self.time2string(frames_read, samplerate)412 fmt_out += self.time2string(frames_read, samplerate)
408 sys.stdout.write(fmt_out) # + '\t')413 sys.stdout.write(fmt_out) # + '\t')
409 def flush(self, frames_read, samplerate):414 def flush(self, frames_read, samplerate):
410 eof = self.time2string(frames_read, samplerate)415 eof = self.time2string(frames_read, samplerate)
411 sys.stdout.write(eof + '\n')416 sys.stdout.write(eof + '\n')
@@ -472,13 +477,13 @@ class process_quiet(default_process): · 60 unmodified lines
472 if aubio.silence_detection(block, self.silence) == 1:477 if aubio.silence_detection(block, self.silence) == 1:
473 if self.wassilence != 1:478 if self.wassilence != 1:
474 self.wassilence = 1479 self.wassilence = 1
475 return 2 # newly found silence480 return 2 # newly found silence
476 return 1 # silence again481 return 1 # silence again
477 else:482 else:
478 if self.wassilence != 0:483 if self.wassilence != 0:
479 self.wassilence = 0484 self.wassilence = 0
480 return -1 # newly found noise485 return -1 # newly found noise
481 return 0 # noise again486 return 0 # noise again
482 487
483 def repr_res(self, res, frames_read, samplerate):488 def repr_res(self, res, frames_read, samplerate):
484 fmt_out = None489 fmt_out = None
@@ -498,20 +503,47 @@ class process_cut(process_onset): · 13 unmodified lines
498 503
499 def __call__(self, block):504 def __call__(self, block):
500 ret = super(process_cut, self).__call__(block)505 ret = super(process_cut, self).__call__(block)
501 if ret: self.slices.append(self.onset.get_last())506 if ret:
507 self.slices.append(self.onset.get_last())
502 return ret508 return ret
503 509
504 def flush(self, frames_read, samplerate):510 def flush(self, frames_read, samplerate):
505 from aubio.cut import _cut_slice
506 _cut_slice(self.options, self.slices)511 _cut_slice(self.options, self.slices)
507 duration = float (frames_read) / float(samplerate)512 duration = float(frames_read) / float(samplerate)
508 base_info = '%(source_file)s' % {'source_file': self.options.source_uri}513 base_info = '%(source_file)s' % \
514 {'source_file': self.options.source_uri}
509 base_info += ' (total %(duration).2fs at %(samplerate)dHz)\n' % \515 base_info += ' (total %(duration).2fs at %(samplerate)dHz)\n' % \
510 {'duration': duration, 'samplerate': samplerate}516 {'duration': duration, 'samplerate': samplerate}
511 info = "created %d slices from " % len(self.slices)517 info = "created %d slices from " % len(self.slices)
512 info += base_info518 info += base_info
513 sys.stderr.write(info)519 sys.stderr.write(info)
514 520
521def _cut_slice(options, timestamps):
522 # cutting pass
523 nstamps = len(timestamps)
524 if nstamps > 0:
525 # generate output files
526 timestamps_end = None
527 if options.cut_every_nslices:
528 timestamps = timestamps[::options.cut_every_nslices]
529 nstamps = len(timestamps)
530 if options.cut_until_nslices and options.cut_until_nsamples:
531 msg = "using cut_until_nslices, but cut_until_nsamples is set"
532 warnings.warn(msg)
533 if options.cut_until_nsamples:
534 lag = options.cut_until_nsamples
535 timestamps_end = [t + lag for t in timestamps[1:]]
536 timestamps_end += [1e120]
537 if options.cut_until_nslices:
538 slice_lag = options.cut_until_nslices
539 timestamps_end = [t for t in timestamps[1 + slice_lag:]]
540 timestamps_end += [1e120] * (options.cut_until_nslices + 1)
541 aubio.slice_source_at_stamps(options.source_uri,
542 timestamps, timestamps_end = timestamps_end,
543 output_dir = options.output_directory,
544 samplerate = options.samplerate,
545 create_first = options.create_first)
546
515def main():547def main():
516 parser = aubio_parser()548 parser = aubio_parser()
517 if sys.version_info[0] != 3:549 if sys.version_info[0] != 3:
@@ -525,19 +557,20 @@ def main(): · 7 unmodified lines
525 parser_root.add_argument('-V', '--version', help="show version",557 parser_root.add_argument('-V', '--version', help="show version",
526 action="store_true", dest="show_version")558 action="store_true", dest="show_version")
527 args, extras = parser_root.parse_known_args()559 args, extras = parser_root.parse_known_args()
528 if args.show_version == False: # no -V, forward to parser560 if not args.show_version: # no -V, forward to parser
529 args = parser.parse_args(extras, namespace=args)561 args = parser.parse_args(extras, namespace=args)
530 elif len(extras) != 0: # -V with other arguments, print help562 elif len(extras) != 0: # -V with other arguments, print help
531 parser.print_help()563 parser.print_help()
532 sys.exit(1)564 sys.exit(1)
533 else: # in py3, we can simply use parser directly565 else: # in py3, we can simply use parser directly
534 args = parser.parse_args()566 args = parser.parse_args()
535 if 'show_version' in args and args.show_version:567 if 'show_version' in args and args.show_version:
536 sys.stdout.write('aubio version ' + aubio.version + '\n')568 sys.stdout.write('aubio version ' + aubio.version + '\n')
537 sys.exit(0)569 sys.exit(0)
538 elif 'verbose' in args and args.verbose > 3:570 elif 'verbose' in args and args.verbose > 3:
539 sys.stderr.write('aubio version ' + aubio.version + '\n')571 sys.stderr.write('aubio version ' + aubio.version + '\n')
540 if 'command' not in args or args.command is None or args.command in ['help']:572 if 'command' not in args or args.command is None \
573 or args.command in ['help']:
541 # no command given, print help and return 1574 # no command given, print help and return 1
542 parser.print_help()575 parser.print_help()
543 if args.command and args.command in ['help']:576 if args.command and args.command in ['help']:
@@ -571,7 +604,8 @@ def main(): · 27 unmodified lines
571 # increment total number of frames read604 # increment total number of frames read
572 frames_read += read605 frames_read += read
573 # exit loop at end of file606 # exit loop at end of file
574 if read < a_source.hop_size: break607 if read < a_source.hop_size:
608 break
575 # flush the processor if needed609 # flush the processor if needed
576 processor.flush(frames_read, a_source.samplerate)610 processor.flush(frames_read, a_source.samplerate)
577 if args.verbose > 1:611 if args.verbose > 1:
@@ -579,7 +613,7 @@ def main(): · 1 unmodified line
579 fmt_string += " ({:d} samples in {:d} blocks of {:d})"613 fmt_string += " ({:d} samples in {:d} blocks of {:d})"
580 fmt_string += " from {:s} at {:d}Hz\n"614 fmt_string += " from {:s} at {:d}Hz\n"
581 sys.stderr.write(fmt_string.format(615 sys.stderr.write(fmt_string.format(
582 frames_read/float(a_source.samplerate),616 frames_read / float(a_source.samplerate),
583 frames_read,617 frames_read,
584 frames_read // a_source.hop_size + 1,618 frames_read // a_source.hop_size + 1,
585 a_source.hop_size,619 a_source.hop_size,
python/lib/aubio/cut.py+29−49
@@ -5,83 +5,83 @@ · 4 unmodified lines
5"""5"""
6 6
7import sys7import sys
8from aubio.cmd import AubioArgumentParser8from aubio.cmd import AubioArgumentParser, _cut_slice
9 9
10def aubio_cut_parser():10def aubio_cut_parser():
11 parser = AubioArgumentParser()11 parser = AubioArgumentParser()
12 parser.add_input()12 parser.add_input()
13 parser.add_argument("-O","--onset-method",13 parser.add_argument("-O", "--onset-method",
14 action="store", dest="onset_method", default='default',14 action="store", dest="onset_method", default='default',
15 metavar = "<onset_method>",15 metavar = "<onset_method>",
16 help="onset detection method [default=default] \16 help="onset detection method [default=default] \
17 complexdomain|hfc|phase|specdiff|energy|kl|mkl")17 complexdomain|hfc|phase|specdiff|energy|kl|mkl")
18 # cutting methods18 # cutting methods
19 parser.add_argument("-b","--beat",19 parser.add_argument("-b", "--beat",
20 action="store_true", dest="beat", default=False,20 action="store_true", dest="beat", default=False,
21 help="slice at beat locations")21 help="slice at beat locations")
22 """22 """
23 parser.add_argument("-S","--silencecut",23 parser.add_argument("-S", "--silencecut",
24 action="store_true", dest="silencecut", default=False,24 action="store_true", dest="silencecut", default=False,
25 help="use silence locations")25 help="use silence locations")
26 parser.add_argument("-s","--silence",26 parser.add_argument("-s", "--silence",
27 metavar = "<value>",27 metavar = "<value>",
28 action="store", dest="silence", default=-70,28 action="store", dest="silence", default=-70,
29 help="silence threshold [default=-70]")29 help="silence threshold [default=-70]")
30 """30 """
31 # algorithm parameters31 # algorithm parameters
32 parser.add_buf_hop_size()32 parser.add_buf_hop_size()
33 parser.add_argument("-t","--threshold", "--onset-threshold",33 parser.add_argument("-t", "--threshold", "--onset-threshold",
34 metavar = "<threshold>", type=float,34 metavar = "<threshold>", type=float,
35 action="store", dest="threshold", default=0.3,35 action="store", dest="threshold", default=0.3,
36 help="onset peak picking threshold [default=0.3]")36 help="onset peak picking threshold [default=0.3]")
37 parser.add_argument("-c","--cut",37 parser.add_argument("-c", "--cut",
38 action="store_true", dest="cut", default=False,38 action="store_true", dest="cut", default=False,
39 help="cut input sound file at detected labels")39 help="cut input sound file at detected labels")
40 parser.add_minioi()40 parser.add_minioi()
41 41
42 """42 """
43 parser.add_argument("-D","--delay",43 parser.add_argument("-D", "--delay",
44 action = "store", dest = "delay", type = float,44 action = "store", dest = "delay", type = float,
45 metavar = "<seconds>", default=0,45 metavar = "<seconds>", default=0,
46 help="number of seconds to take back [default=system]\46 help="number of seconds to take back [default=system]\
47 default system delay is 3*hopsize/samplerate")47 default system delay is 3*hopsize/samplerate")
48 parser.add_argument("-C","--dcthreshold",48 parser.add_argument("-C", "--dcthreshold",
49 metavar = "<value>",49 metavar = "<value>",
50 action="store", dest="dcthreshold", default=1.,50 action="store", dest="dcthreshold", default=1.,
51 help="onset peak picking DC component [default=1.]")51 help="onset peak picking DC component [default=1.]")
52 parser.add_argument("-L","--localmin",52 parser.add_argument("-L", "--localmin",
53 action="store_true", dest="localmin", default=False,53 action="store_true", dest="localmin", default=False,
54 help="use local minima after peak detection")54 help="use local minima after peak detection")
55 parser.add_argument("-d","--derivate",55 parser.add_argument("-d", "--derivate",
56 action="store_true", dest="derivate", default=False,56 action="store_true", dest="derivate", default=False,
57 help="derivate onset detection function")57 help="derivate onset detection function")
58 parser.add_argument("-z","--zerocross",58 parser.add_argument("-z", "--zerocross",
59 metavar = "<value>",59 metavar = "<value>",
60 action="store", dest="zerothres", default=0.008,60 action="store", dest="zerothres", default=0.008,
61 help="zero-crossing threshold for slicing [default=0.00008]")61 help="zero-crossing threshold for slicing [default=0.00008]")
62 # plotting functions62 # plotting functions
63 parser.add_argument("-p","--plot",63 parser.add_argument("-p", "--plot",
64 action="store_true", dest="plot", default=False,64 action="store_true", dest="plot", default=False,
65 help="draw plot")65 help="draw plot")
66 parser.add_argument("-x","--xsize",66 parser.add_argument("-x", "--xsize",
67 metavar = "<size>",67 metavar = "<size>",
68 action="store", dest="xsize", default=1.,68 action="store", dest="xsize", default=1.,
69 type=float, help="define xsize for plot")69 type=float, help="define xsize for plot")
70 parser.add_argument("-y","--ysize",70 parser.add_argument("-y", "--ysize",
71 metavar = "<size>",71 metavar = "<size>",
72 action="store", dest="ysize", default=1.,72 action="store", dest="ysize", default=1.,
73 type=float, help="define ysize for plot")73 type=float, help="define ysize for plot")
74 parser.add_argument("-f","--function",74 parser.add_argument("-f", "--function",
75 action="store_true", dest="func", default=False,75 action="store_true", dest="func", default=False,
76 help="print detection function")76 help="print detection function")
77 parser.add_argument("-n","--no-onsets",77 parser.add_argument("-n", "--no-onsets",
78 action="store_true", dest="nplot", default=False,78 action="store_true", dest="nplot", default=False,
79 help="do not plot detected onsets")79 help="do not plot detected onsets")
80 parser.add_argument("-O","--outplot",80 parser.add_argument("-O", "--outplot",
81 metavar = "<output_image>",81 metavar = "<output_image>",
82 action="store", dest="outplot", default=None,82 action="store", dest="outplot", default=None,
83 help="save plot to output.{ps,png}")83 help="save plot to output.{ps,png}")
84 parser.add_argument("-F","--spectrogram",84 parser.add_argument("-F", "--spectrogram",
85 action="store_true", dest="spectro", default=False,85 action="store_true", dest="spectro", default=False,
86 help="add spectrogram to the plot")86 help="add spectrogram to the plot")
87 """87 """
@@ -105,9 +105,11 @@ def _cut_analyze(options): · 17 unmodified lines
105 options.samplerate = samplerate105 options.samplerate = samplerate
106 106
107 if options.beat:107 if options.beat:
108 o = tempo(options.onset_method, bufsize, hopsize, samplerate=samplerate)108 o = tempo(options.onset_method, bufsize, hopsize,
109 samplerate=samplerate)
109 else:110 else:
110 o = onset(options.onset_method, bufsize, hopsize, samplerate=samplerate)111 o = onset(options.onset_method, bufsize, hopsize,
112 samplerate=samplerate)
111 if options.minioi:113 if options.minioi:
112 if options.minioi.endswith('ms'):114 if options.minioi.endswith('ms'):
113 o.set_minioi_ms(int(options.minioi[:-2]))115 o.set_minioi_ms(int(options.minioi[:-2]))
@@ -122,37 +124,15 @@ def _cut_analyze(options): · 8 unmodified lines
122 while True:124 while True:
123 samples, read = s()125 samples, read = s()
124 if o(samples):126 if o(samples):
125 timestamps.append (o.get_last())127 timestamps.append(o.get_last())
126 if options.verbose: print ("%.4f" % o.get_last_s())128 if options.verbose:
129 print("%.4f" % o.get_last_s())
127 total_frames += read130 total_frames += read
128 if read < hopsize: break131 if read < hopsize:
132 break
129 del s133 del s
130 return timestamps, total_frames134 return timestamps, total_frames
131 135
132def _cut_slice(options, timestamps):
133 # cutting pass
134 nstamps = len(timestamps)
135 if nstamps > 0:
136 # generate output files
137 from aubio.slicing import slice_source_at_stamps
138 timestamps_end = None
139 if options.cut_every_nslices:
140 timestamps = timestamps[::options.cut_every_nslices]
141 nstamps = len(timestamps)
142 if options.cut_until_nslices and options.cut_until_nsamples:
143 print ("warning: using cut_until_nslices, but cut_until_nsamples is set")
144 if options.cut_until_nsamples:
145 timestamps_end = [t + options.cut_until_nsamples for t in timestamps[1:]]
146 timestamps_end += [ 1e120 ]
147 if options.cut_until_nslices:
148 timestamps_end = [t for t in timestamps[1 + options.cut_until_nslices:]]
149 timestamps_end += [ 1e120 ] * (options.cut_until_nslices + 1)
150 slice_source_at_stamps(options.source_uri,
151 timestamps, timestamps_end = timestamps_end,
152 output_dir = options.output_directory,
153 samplerate = options.samplerate,
154 create_first = options.create_first)
155
156def main():136def main():
157 parser = aubio_cut_parser()137 parser = aubio_cut_parser()
158 options = parser.parse_args()138 options = parser.parse_args()
@@ -167,7 +147,7 @@ def main(): · 8 unmodified lines
167 timestamps, total_frames = _cut_analyze(options)147 timestamps, total_frames = _cut_analyze(options)
168 148
169 # print some info149 # print some info
170 duration = float (total_frames) / float(options.samplerate)150 duration = float(total_frames) / float(options.samplerate)
171 base_info = '%(source_uri)s' % {'source_uri': options.source_uri}151 base_info = '%(source_uri)s' % {'source_uri': options.source_uri}
172 base_info += ' (total %(duration).2fs at %(samplerate)dHz)\n' % \152 base_info += ' (total %(duration).2fs at %(samplerate)dHz)\n' % \
173 {'duration': duration, 'samplerate': options.samplerate}153 {'duration': duration, 'samplerate': options.samplerate}
python/lib/aubio/midiconv.py+17−12
@@ -1,11 +1,11 @@
1# -*- coding: utf-8 -*-1# -*- coding: utf-8 -*-
2""" utilities to convert midi note number to and from note names """2""" utilities to convert midi note number to and from note names """
3 3
4__all__ = ['note2midi', 'midi2note', 'freq2note', 'note2freq']
5
6import sys4import sys
7from ._aubio import freqtomidi, miditofreq5from ._aubio import freqtomidi, miditofreq
8 6
7__all__ = ['note2midi', 'midi2note', 'freq2note', 'note2freq']
8
9py3 = sys.version_info[0] == 39py3 = sys.version_info[0] == 3
10if py3:10if py3:
11 str_instances = str11 str_instances = str
@@ -14,6 +14,7 @@ else: · 2 unmodified lines
14 str_instances = (str, unicode)14 str_instances = (str, unicode)
15 int_instances = (int, long)15 int_instances = (int, long)
16 16
17
17def note2midi(note):18def note2midi(note):
18 """Convert note name to midi note number.19 """Convert note name to midi note number.
19 20
@@ -55,13 +56,14 @@ def note2midi(note): · 35 unmodified lines
55 --------56 --------
56 midi2note, freqtomidi, miditofreq57 midi2note, freqtomidi, miditofreq
57 """58 """
58 _valid_notenames = {'C': 0, 'D': 2, 'E': 4, 'F': 5, 'G': 7, 'A': 9, 'B': 11}59 _valid_notenames = {'C': 0, 'D': 2, 'E': 4, 'F': 5, 'G': 7,
60 'A': 9, 'B': 11}
59 _valid_modifiers = {61 _valid_modifiers = {
60 u'𝄫': -2, # double flat62 u'𝄫': -2, # double flat
61 u'♭': -1, 'b': -1, '\u266d': -1, # simple flat63 u'♭': -1, 'b': -1, '\u266d': -1, # simple flat
62 u'♮': 0, '\u266e': 0, None: 0, # natural64 u'♮': 0, '\u266e': 0, None: 0, # natural
63 '#': +1, u'♯': +1, '\u266f': +1, # sharp65 '#': +1, u'♯': +1, '\u266f': +1, # sharp
64 u'𝄪': +2, # double sharp66 u'𝄪': +2, # double sharp
65 }67 }
66 _valid_octaves = range(-1, 10)68 _valid_octaves = range(-1, 10)
67 if not isinstance(note, str_instances):69 if not isinstance(note, str_instances):
@@ -70,7 +72,7 @@ def note2midi(note): · 2 unmodified lines
70 if len(note) not in range(2, 5):72 if len(note) not in range(2, 5):
71 msg = "string of 2 to 4 characters expected, got {:d} ({:s})"73 msg = "string of 2 to 4 characters expected, got {:d} ({:s})"
72 raise ValueError(msg.format(len(note), note))74 raise ValueError(msg.format(len(note), note))
73 notename, modifier, octave = [None]*375 notename, modifier, octave = [None] * 3
74 76
75 if len(note) == 4:77 if len(note) == 4:
76 notename, modifier, octave_sign, octave = note78 notename, modifier, octave_sign, octave = note
@@ -93,12 +95,13 @@ def note2midi(note): · 16 unmodified lines
93 if octave not in _valid_octaves:95 if octave not in _valid_octaves:
94 raise ValueError("%s is not a valid octave" % octave)96 raise ValueError("%s is not a valid octave" % octave)
95 97
96 midi = 12 + octave * 12 + _valid_notenames[notename] \98 midi = (octave + 1) * 12 + _valid_notenames[notename] \
97 + _valid_modifiers[modifier]99 + _valid_modifiers[modifier]
98 if midi > 127:100 if midi > 127:
99 raise ValueError("%s is outside of the range C-2 to G8" % note)101 raise ValueError("%s is outside of the range C-2 to G8" % note)
100 return midi102 return midi
101 103
104
102def midi2note(midi):105def midi2note(midi):
103 """Convert midi note number to note name.106 """Convert midi note number to note name.
104 107
@@ -136,9 +139,10 @@ def midi2note(midi): · 31 unmodified lines
136 msg = "an integer between 0 and 127 is excepted, got {:d}"139 msg = "an integer between 0 and 127 is excepted, got {:d}"
137 raise ValueError(msg.format(midi))140 raise ValueError(msg.format(midi))
138 _valid_notenames = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#',141 _valid_notenames = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#',
139 'A', 'A#', 'B']142 'A', 'A#', 'B']
140 return _valid_notenames[midi % 12] + str(int(midi / 12) - 1)143 return _valid_notenames[midi % 12] + str(int(midi / 12) - 1)
141 144
145
142def freq2note(freq):146def freq2note(freq):
143 """Convert frequency in Hz to nearest note name.147 """Convert frequency in Hz to nearest note name.
144 148
@@ -162,6 +166,7 @@ def freq2note(freq): · 17 unmodified lines
162 nearest_note = int(freqtomidi(freq) + .5)166 nearest_note = int(freqtomidi(freq) + .5)
163 return midi2note(nearest_note)167 return midi2note(nearest_note)
164 168
169
165def note2freq(note):170def note2freq(note):
166 """Convert note name to corresponding frequency, in Hz.171 """Convert note name to corresponding frequency, in Hz.
167 172
python/lib/aubio/slicing.py+10−11
@@ -5,6 +5,7 @@ from aubio import source, sink · 4 unmodified lines
5 5
6_max_timestamp = 1e1206_max_timestamp = 1e120
7 7
8
8def slice_source_at_stamps(source_file, timestamps, timestamps_end=None,9def slice_source_at_stamps(source_file, timestamps, timestamps_end=None,
9 output_dir=None, samplerate=0, hopsize=256,10 output_dir=None, samplerate=0, hopsize=256,
10 create_first=False):11 create_first=False):
@@ -72,7 +73,7 @@ def slice_source_at_stamps(source_file, timestamps, timestamps_end=None, · 61 unmodified lines
72 the file.73 the file.
73 """74 """
74 75
75 if timestamps is None or len(timestamps) == 0:76 if not timestamps:
76 raise ValueError("no timestamps given")77 raise ValueError("no timestamps given")
77 78
78 if timestamps[0] != 0 and create_first:79 if timestamps[0] != 0 and create_first:
@@ -89,7 +90,6 @@ def slice_source_at_stamps(source_file, timestamps, timestamps_end=None, · 10 unmodified lines
89 timestamps_end = [t - 1 for t in timestamps[1:]] + [_max_timestamp]90 timestamps_end = [t - 1 for t in timestamps[1:]] + [_max_timestamp]
90 91
91 regions = list(zip(timestamps, timestamps_end))92 regions = list(zip(timestamps, timestamps_end))
92 #print regions
93 93
94 source_base_name, _ = os.path.splitext(os.path.basename(source_file))94 source_base_name, _ = os.path.splitext(os.path.basename(source_file))
95 if output_dir is not None:95 if output_dir is not None:
@@ -97,8 +97,8 @@ def slice_source_at_stamps(source_file, timestamps, timestamps_end=None, · 1 unmodified line
97 os.makedirs(output_dir)97 os.makedirs(output_dir)
98 source_base_name = os.path.join(output_dir, source_base_name)98 source_base_name = os.path.join(output_dir, source_base_name)
99 99
100 def new_sink_name(source_base_name, timestamp, samplerate):100 def _new_sink_name(source_base_name, timestamp, samplerate):
101 """ create a sink based on a timestamp in samples, converted in seconds """101 # create name based on a timestamp in samples, converted in seconds
102 timestamp_seconds = timestamp / float(samplerate)102 timestamp_seconds = timestamp / float(samplerate)
103 return source_base_name + "_%011.6f" % timestamp_seconds + '.wav'103 return source_base_name + "_%011.6f" % timestamp_seconds + '.wav'
104 104
@@ -113,16 +113,17 @@ def slice_source_at_stamps(source_file, timestamps, timestamps_end=None, · 8 unmodified lines
113 # get hopsize new samples from source113 # get hopsize new samples from source
114 vec, read = _source.do_multi()114 vec, read = _source.do_multi()
115 # if the total number of frames read will exceed the next region start115 # if the total number of frames read will exceed the next region start
116 while len(regions) and total_frames + read >= regions[0][0]:116 while regions and total_frames + read >= regions[0][0]:
117 #print "getting", regions[0], "at", total_frames
118 # get next region117 # get next region
119 start_stamp, end_stamp = regions.pop(0)118 start_stamp, end_stamp = regions.pop(0)
120 # create a name for the sink119 # create a name for the sink
121 new_sink_path = new_sink_name(source_base_name, start_stamp, samplerate)120 new_sink_path = _new_sink_name(source_base_name, start_stamp,
121 samplerate)
122 # create its sink122 # create its sink
123 _sink = sink(new_sink_path, samplerate, _source.channels)123 _sink = sink(new_sink_path, samplerate, _source.channels)
124 # create a dictionary containing all this124 # create a dictionary containing all this
125 new_slice = {'start_stamp': start_stamp, 'end_stamp': end_stamp, 'sink': _sink}125 new_slice = {'start_stamp': start_stamp, 'end_stamp': end_stamp,
126 'sink': _sink}
126 # append the dictionary to the current list of slices127 # append the dictionary to the current list of slices
127 slices.append(new_slice)128 slices.append(new_slice)
128 129
@@ -134,13 +135,11 @@ def slice_source_at_stamps(source_file, timestamps, timestamps_end=None, · 5 unmodified lines
134 start = max(start_stamp - total_frames, 0)135 start = max(start_stamp - total_frames, 0)
135 # number of samples yet to written be until end of region136 # number of samples yet to written be until end of region
136 remaining = end_stamp - total_frames + 1137 remaining = end_stamp - total_frames + 1
137 #print current_slice, remaining, start
138 # not enough frames remaining, time to split138 # not enough frames remaining, time to split
139 if remaining < read:139 if remaining < read:
140 if remaining > start:140 if remaining > start:
141 # write remaining samples from current region141 # write remaining samples from current region
142 _sink.do_multi(vec[:, start:remaining], remaining - start)142 _sink.do_multi(vec[:, start:remaining], remaining - start)
143 #print("closing region", "remaining", remaining)
144 # close this file143 # close this file
145 _sink.close()144 _sink.close()
146 elif read > start:145 elif read > start:
@@ -149,6 +148,6 @@ def slice_source_at_stamps(source_file, timestamps, timestamps_end=None, · 2 unmodified lines
149 total_frames += read148 total_frames += read
150 # remove old slices149 # remove old slices
151 slices = list(filter(lambda s: s['end_stamp'] > total_frames,150 slices = list(filter(lambda s: s['end_stamp'] > total_frames,
152 slices))151 slices))
153 if read < hopsize:152 if read < hopsize:
154 break153 break

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t