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