Showing the changes to python (2 of 4 files). Show all
Unified · Split
| @@ -0,0 +1,408 @@ | |||
| 1 | #! /usr/bin/env python | ||
| 2 | # -*- coding: utf-8 -*- | ||
| 3 | |||
| 4 | """aubio command line tool | ||
| 5 | |||
| 6 | This file was written by Paul Brossier <piem@aubio.org> and is released under | ||
| 7 | the GNU/GPL v3. | ||
| 8 | |||
| 9 | Note: this script is mostly about parsing command line arguments. For more | ||
| 10 | readable code examples, check out the `python/demos` folder.""" | ||
| 11 | |||
| 12 | import sys | ||
| 13 | import argparse | ||
| 14 | import aubio | ||
| 15 | |||
| 16 | def aubio_parser(): | ||
| 17 | epilog = 'use "%(prog)s <command> --help" for more info about each command' | ||
| 18 | parser = argparse.ArgumentParser(epilog=epilog) | ||
| 19 | parser.add_argument('-V', '--version', help="show version", | ||
| 20 | action="store_true", dest="show_version") | ||
| 21 | |||
| 22 | subparsers = parser.add_subparsers(title='commands', dest='command', | ||
| 23 | metavar="") | ||
| 24 | |||
| 25 | # onset subcommand | ||
| 26 | subparser = subparsers.add_parser('onset', | ||
| 27 | help='estimate time of onsets (beginning of sound event)', | ||
| 28 | formatter_class = argparse.ArgumentDefaultsHelpFormatter) | ||
| 29 | parser_add_input(subparser) | ||
| 30 | parser_add_buf_hop_size(subparser) | ||
| 31 | helpstr = "onset novelty function" | ||
| 32 | helpstr += " <default|energy|hfc|complex|phase|specdiff|kl|mkl|specflux>" | ||
| 33 | parser_add_method(subparser, helpstr=helpstr) | ||
| 34 | parser_add_threshold(subparser) | ||
| 35 | parser_add_silence(subparser) | ||
| 36 | parser_add_minioi(subparser) | ||
| 37 | parser_add_time_format(subparser) | ||
| 38 | parser_add_verbose_help(subparser) | ||
| 39 | subparser.set_defaults(process=process_onset) | ||
| 40 | |||
| 41 | # pitch subcommand | ||
| 42 | subparser = subparsers.add_parser('pitch', | ||
| 43 | help='estimate fundamental frequency (monophonic)') | ||
| 44 | parser_add_input(subparser) | ||
| 45 | parser_add_buf_hop_size(subparser, buf_size=2048) | ||
| 46 | helpstr = "pitch detection method <default|yinfft|yin|mcomb|fcomb|schmitt>" | ||
| 47 | parser_add_method(subparser, helpstr=helpstr) | ||
| 48 | parser_add_threshold(subparser) | ||
| 49 | parser_add_silence(subparser) | ||
| 50 | parser_add_time_format(subparser) | ||
| 51 | parser_add_verbose_help(subparser) | ||
| 52 | subparser.set_defaults(process=process_pitch) | ||
| 53 | |||
| 54 | # beat subcommand | ||
| 55 | subparser = subparsers.add_parser('beat', | ||
| 56 | help='estimate location of beats') | ||
| 57 | parser_add_input(subparser) | ||
| 58 | parser_add_buf_hop_size(subparser, buf_size=1024, hop_size=512) | ||
| 59 | parser_add_time_format(subparser) | ||
| 60 | parser_add_verbose_help(subparser) | ||
| 61 | subparser.set_defaults(process=process_beat) | ||
| 62 | |||
| 63 | # tempo subcommand | ||
| 64 | subparser = subparsers.add_parser('tempo', | ||
| 65 | help='estimate overall tempo in bpm') | ||
| 66 | parser_add_input(subparser) | ||
| 67 | parser_add_buf_hop_size(subparser, buf_size=1024, hop_size=512) | ||
| 68 | parser_add_time_format(subparser) | ||
| 69 | parser_add_verbose_help(subparser) | ||
| 70 | subparser.set_defaults(process=process_tempo) | ||
| 71 | |||
| 72 | # notes subcommand | ||
| 73 | subparser = subparsers.add_parser('notes', | ||
| 74 | help='estimate midi-like notes (monophonic)') | ||
| 75 | parser_add_input(subparser) | ||
| 76 | parser_add_buf_hop_size(subparser) | ||
| 77 | parser_add_time_format(subparser) | ||
| 78 | parser_add_verbose_help(subparser) | ||
| 79 | subparser.set_defaults(process=process_notes) | ||
| 80 | |||
| 81 | # mfcc subcommand | ||
| 82 | subparser = subparsers.add_parser('mfcc', | ||
| 83 | help='extract Mel-Frequency Cepstrum Coefficients') | ||
| 84 | parser_add_input(subparser) | ||
| 85 | parser_add_buf_hop_size(subparser) | ||
| 86 | parser_add_time_format(subparser) | ||
| 87 | parser_add_verbose_help(subparser) | ||
| 88 | subparser.set_defaults(process=process_mfcc) | ||
| 89 | |||
| 90 | # melbands subcommand | ||
| 91 | subparser = subparsers.add_parser('melbands', | ||
| 92 | help='extract energies in Mel-frequency bands') | ||
| 93 | parser_add_input(subparser) | ||
| 94 | parser_add_buf_hop_size(subparser) | ||
| 95 | parser_add_time_format(subparser) | ||
| 96 | parser_add_verbose_help(subparser) | ||
| 97 | subparser.set_defaults(process=process_melbands) | ||
| 98 | |||
| 99 | return parser | ||
| 100 | |||
| 101 | def parser_add_input(parser): | ||
| 102 | parser.add_argument("source_uri", default=None, nargs='?', | ||
| 103 | help="input sound file to analyse", metavar = "<source_uri>") | ||
| 104 | parser.add_argument("-i", "--input", dest = "source_uri2", | ||
| 105 | help="input sound file to analyse", metavar = "<source_uri>") | ||
| 106 | parser.add_argument("-r", "--samplerate", | ||
| 107 | metavar = "<freq>", type=int, | ||
| 108 | action="store", dest="samplerate", default=0, | ||
| 109 | help="samplerate at which the file should be represented") | ||
| 110 | |||
| 111 | def parser_add_verbose_help(parser): | ||
| 112 | parser.add_argument("-v","--verbose", | ||
| 113 | action="count", dest="verbose", default=1, | ||
| 114 | help="make lots of noise [default]") | ||
| 115 | parser.add_argument("-q","--quiet", | ||
| 116 | action="store_const", dest="verbose", const=0, | ||
| 117 | help="be quiet") | ||
| 118 | |||
| 119 | def parser_add_buf_hop_size(parser, buf_size=512, hop_size=256): | ||
| 120 | parser.add_argument("-B","--bufsize", | ||
| 121 | action="store", dest="buf_size", default=buf_size, | ||
| 122 | metavar = "<size>", type=int, | ||
| 123 | help="buffer size [default=%d]" % buf_size) | ||
| 124 | parser.add_argument("-H","--hopsize", | ||
| 125 | metavar = "<size>", type=int, | ||
| 126 | action="store", dest="hop_size", default=hop_size, | ||
| 127 | help="overlap size [default=%d]" % hop_size) | ||
| 128 | |||
| 129 | def parser_add_method(parser, method='default', helpstr='method'): | ||
| 130 | parser.add_argument("-m","--method", | ||
| 131 | metavar = "<method>", type=str, | ||
| 132 | action="store", dest="method", default=method, | ||
| 133 | help="%s [default=%s]" % (helpstr, method)) | ||
| 134 | |||
| 135 | def parser_add_threshold(parser, default=None): | ||
| 136 | parser.add_argument("-t","--threshold", | ||
| 137 | metavar = "<threshold>", type=float, | ||
| 138 | action="store", dest="threshold", default=default, | ||
| 139 | help="threshold [default=%s]" % default) | ||
| 140 | |||
| 141 | def parser_add_silence(parser): | ||
| 142 | parser.add_argument("-s", "--silence", | ||
| 143 | metavar = "<value>", type=float, | ||
| 144 | action="store", dest="silence", default=-70, | ||
| 145 | help="silence threshold") | ||
| 146 | |||
| 147 | def parser_add_minioi(parser): | ||
| 148 | parser.add_argument("-M", "--minioi", | ||
| 149 | metavar = "<value>", type=str, | ||
| 150 | action="store", dest="minioi", default="12ms", | ||
| 151 | help="minimum Inter-Onset Interval") | ||
| 152 | |||
| 153 | def parser_add_time_format(parser): | ||
| 154 | helpstr = "select time values output format (samples, ms, seconds)" | ||
| 155 | helpstr += " [default=seconds]" | ||
| 156 | parser.add_argument("-T", "--time-format", | ||
| 157 | metavar='format', | ||
| 158 | dest="time_format", | ||
| 159 | default=None, | ||
| 160 | help=helpstr) | ||
| 161 | |||
| 162 | # some utilities | ||
| 163 | |||
| 164 | def samples2seconds(n_frames, samplerate): | ||
| 165 | return "%f\t" % (n_frames / float(samplerate)) | ||
| 166 | |||
| 167 | def samples2milliseconds(n_frames, samplerate): | ||
| 168 | return "%f\t" % (1000. * n_frames / float(samplerate)) | ||
| 169 | |||
| 170 | def samples2samples(n_frames, samplerate): | ||
| 171 | return "%d\t" % n_frames | ||
| 172 | |||
| 173 | def timefunc(mode): | ||
| 174 | if mode is None or mode == 'seconds' or mode == 's': | ||
| 175 | return samples2seconds | ||
| 176 | elif mode == 'ms' or mode == 'milliseconds': | ||
| 177 | return samples2milliseconds | ||
| 178 | elif mode == 'samples': | ||
| 179 | return samples2samples | ||
| 180 | else: | ||
| 181 | raise ValueError('invalid time format %s' % mode) | ||
| 182 | |||
| 183 | # definition of processing classes | ||
| 184 | |||
| 185 | class default_process(object): | ||
| 186 | def __init__(self, args): | ||
| 187 | if 'time_format' in args: | ||
| 188 | self.time2string = timefunc(args.time_format) | ||
| 189 | if args.verbose > 2 and hasattr(self, 'options'): | ||
| 190 | name = type(self).__name__.split('_')[1] | ||
| 191 | optstr = ' '.join(['running', name, 'with options', repr(self.options), '\n']) | ||
| 192 | sys.stderr.write(optstr) | ||
| 193 | def flush(self, n_frames, samplerate): | ||
| 194 | # optionally called at the end of process | ||
| 195 | pass | ||
| 196 | |||
| 197 | def parse_options(self, args, valid_opts): | ||
| 198 | # get any valid options found in a dictionnary of arguments | ||
| 199 | options = {k :v for k,v in vars(args).items() if k in valid_opts} | ||
| 200 | self.options = options | ||
| 201 | |||
| 202 | def remap_pvoc_options(self, options): | ||
| 203 | # FIXME: we need to remap buf_size to win_s, hop_size to hop_s | ||
| 204 | # adjust python/ext/py-phasevoc.c to understand buf_size/hop_size | ||
| 205 | if 'buf_size' in options: | ||
| 206 | options['win_s'] = options['buf_size'] | ||
| 207 | del options['buf_size'] | ||
| 208 | if 'hop_size' in options: | ||
| 209 | options['hop_s'] = options['hop_size'] | ||
| 210 | del options['hop_size'] | ||
| 211 | self.options = options | ||
| 212 | |||
| 213 | class process_onset(default_process): | ||
| 214 | valid_opts = ['method', 'hop_size', 'buf_size', 'samplerate'] | ||
| 215 | def __init__(self, args): | ||
| 216 | self.parse_options(args, self.valid_opts) | ||
| 217 | self.onset = aubio.onset(**self.options) | ||
| 218 | if args.threshold is not None: | ||
| 219 | self.onset.set_threshold(args.threshold) | ||
| 220 | if args.minioi: | ||
| 221 | if args.minioi.endswith('ms'): | ||
| 222 | self.onset.set_minioi_ms(float(args.minioi[:-2])) | ||
| 223 | elif args.minioi.endswith('s'): | ||
| 224 | self.onset.set_minioi_s(float(args.minioi[:-1])) | ||
| 225 | else: | ||
| 226 | self.onset.set_minioi(int(args.minioi)) | ||
| 227 | if args.silence: | ||
| 228 | self.onset.set_silence(args.silence) | ||
| 229 | super(process_onset, self).__init__(args) | ||
| 230 | def __call__(self, block): | ||
| 231 | return self.onset(block) | ||
| 232 | def repr_res(self, res, frames_read, samplerate): | ||
| 233 | if res[0] != 0: | ||
| 234 | outstr = self.time2string(self.onset.get_last(), samplerate) | ||
| 235 | sys.stdout.write(outstr + '\n') | ||
| 236 | |||
| 237 | class process_pitch(default_process): | ||
| 238 | valid_opts = ['method', 'hop_size', 'buf_size', 'samplerate'] | ||
| 239 | def __init__(self, args): | ||
| 240 | self.parse_options(args, self.valid_opts) | ||
| 241 | self.pitch = aubio.pitch(**self.options) | ||
| 242 | if args.threshold is not None: | ||
| 243 | self.pitch.set_tolerance(args.threshold) | ||
| 244 | if args.silence is not None: | ||
| 245 | self.pitch.set_silence(args.silence) | ||
| 246 | super(process_pitch, self).__init__(args) | ||
| 247 | def __call__(self, block): | ||
| 248 | return self.pitch(block) | ||
| 249 | def repr_res(self, res, frames_read, samplerate): | ||
| 250 | fmt_out = self.time2string(frames_read, samplerate) | ||
| 251 | sys.stdout.write(fmt_out + "%.6f\n" % res[0]) | ||
| 252 | |||
| 253 | class process_beat(default_process): | ||
| 254 | valid_opts = ['method', 'hop_size', 'buf_size', 'samplerate'] | ||
| 255 | def __init__(self, args): | ||
| 256 | self.parse_options(args, self.valid_opts) | ||
| 257 | self.tempo = aubio.tempo(**self.options) | ||
| 258 | super(process_beat, self).__init__(args) | ||
| 259 | def __call__(self, block): | ||
| 260 | return self.tempo(block) | ||
| 261 | def repr_res(self, res, frames_read, samplerate): | ||
| 262 | if res[0] != 0: | ||
| 263 | outstr = self.time2string(self.tempo.get_last(), samplerate) | ||
| 264 | sys.stdout.write(outstr + '\n') | ||
| 265 | |||
| 266 | class process_tempo(process_beat): | ||
| 267 | def __init__(self, args): | ||
| 268 | super(process_tempo, self).__init__(args) | ||
| 269 | self.beat_locations = [] | ||
| 270 | def repr_res(self, res, frames_read, samplerate): | ||
| 271 | if res[0] != 0: | ||
| 272 | self.beat_locations.append(self.tempo.get_last_s()) | ||
| 273 | def flush(self, frames_read, samplerate): | ||
| 274 | import numpy as np | ||
| 275 | if len(self.beat_locations) < 2: | ||
| 276 | outstr = "unknown bpm" | ||
| 277 | else: | ||
| 278 | bpms = 60./ np.diff(self.beat_locations) | ||
| 279 | median_bpm = np.mean(bpms) | ||
| 280 | if len(self.beat_locations) < 10: | ||
| 281 | outstr = "%.2f bpm (uncertain)" % median_bpm | ||
| 282 | else: | ||
| 283 | outstr = "%.2f bpm" % median_bpm | ||
| 284 | sys.stdout.write(outstr + '\n') | ||
| 285 | |||
| 286 | class process_notes(default_process): | ||
| 287 | valid_opts = ['method', 'hop_size', 'buf_size', 'samplerate'] | ||
| 288 | def __init__(self, args): | ||
| 289 | self.parse_options(args, self.valid_opts) | ||
| 290 | self.notes = aubio.notes(**self.options) | ||
| 291 | super(process_notes, self).__init__(args) | ||
| 292 | def __call__(self, block): | ||
| 293 | return self.notes(block) | ||
| 294 | def repr_res(self, res, frames_read, samplerate): | ||
| 295 | if res[2] != 0: # note off | ||
| 296 | fmt_out = self.time2string(frames_read, samplerate) | ||
| 297 | sys.stdout.write(fmt_out + '\n') | ||
| 298 | if res[0] != 0: # note on | ||
| 299 | lastmidi = res[0] | ||
| 300 | fmt_out = "%f\t" % lastmidi | ||
| 301 | fmt_out += self.time2string(frames_read, samplerate) | ||
| 302 | sys.stdout.write(fmt_out) # + '\t') | ||
| 303 | def flush(self, frames_read, samplerate): | ||
| 304 | eof = self.time2string(frames_read, samplerate) | ||
| 305 | sys.stdout.write(eof + '\n') | ||
| 306 | |||
| 307 | class process_mfcc(default_process): | ||
| 308 | def __init__(self, args): | ||
| 309 | valid_opts1 = ['hop_size', 'buf_size'] | ||
| 310 | self.parse_options(args, valid_opts1) | ||
| 311 | self.remap_pvoc_options(self.options) | ||
| 312 | self.pv = aubio.pvoc(**self.options) | ||
| 313 | |||
| 314 | valid_opts2 = ['buf_size', 'n_filters', 'n_coeffs', 'samplerate'] | ||
| 315 | self.parse_options(args, valid_opts2) | ||
| 316 | self.mfcc = aubio.mfcc(**self.options) | ||
| 317 | |||
| 318 | # remember all options | ||
| 319 | self.parse_options(args, list(set(valid_opts1 + valid_opts2))) | ||
| 320 | |||
| 321 | super(process_mfcc, self).__init__(args) | ||
| 322 | |||
| 323 | def __call__(self, block): | ||
| 324 | fftgrain = self.pv(block) | ||
| 325 | return self.mfcc(fftgrain) | ||
| 326 | def repr_res(self, res, frames_read, samplerate): | ||
| 327 | fmt_out = self.time2string(frames_read, samplerate) | ||
| 328 | fmt_out += ' '.join(["% 9.7f" % f for f in res.tolist()]) | ||
| 329 | sys.stdout.write(fmt_out + '\n') | ||
| 330 | |||
| 331 | class process_melbands(default_process): | ||
| 332 | def __init__(self, args): | ||
| 333 | self.args = args | ||
| 334 | valid_opts = ['hop_size', 'buf_size'] | ||
| 335 | self.parse_options(args, valid_opts) | ||
| 336 | self.remap_pvoc_options(self.options) | ||
| 337 | self.pv = aubio.pvoc(**self.options) | ||
| 338 | |||
| 339 | valid_opts = ['buf_size', 'n_filters'] | ||
| 340 | self.parse_options(args, valid_opts) | ||
| 341 | self.remap_pvoc_options(self.options) | ||
| 342 | self.filterbank = aubio.filterbank(**self.options) | ||
| 343 | self.filterbank.set_mel_coeffs_slaney(args.samplerate) | ||
| 344 | |||
| 345 | super(process_melbands, self).__init__(args) | ||
| 346 | def __call__(self, block): | ||
| 347 | fftgrain = self.pv(block) | ||
| 348 | return self.filterbank(fftgrain) | ||
| 349 | def repr_res(self, res, frames_read, samplerate): | ||
| 350 | fmt_out = self.time2string(frames_read, samplerate) | ||
| 351 | fmt_out += ' '.join(["% 9.7f" % f for f in res.tolist()]) | ||
| 352 | sys.stdout.write(fmt_out + '\n') | ||
| 353 | |||
| 354 | def main(): | ||
| 355 | parser = aubio_parser() | ||
| 356 | args = parser.parse_args() | ||
| 357 | if 'show_version' in args and args.show_version: | ||
| 358 | sys.stdout.write('aubio version ' + aubio.version + '\n') | ||
| 359 | sys.exit(0) | ||
| 360 | elif 'verbose' in args and args.verbose > 3: | ||
| 361 | sys.stderr.write('aubio version ' + aubio.version + '\n') | ||
| 362 | if 'command' not in args or args.command is None: | ||
| 363 | # no command given, print help and return 1 | ||
| 364 | parser.print_help() | ||
| 365 | sys.exit(1) | ||
| 366 | elif not args.source_uri and not args.source_uri2: | ||
| 367 | sys.stderr.write("Error: a source is required\n") | ||
| 368 | parser.print_help() | ||
| 369 | sys.exit(1) | ||
| 370 | elif args.source_uri2 is not None: | ||
| 371 | args.source_uri = args.source_uri2 | ||
| 372 | try: | ||
| 373 | # open source_uri | ||
| 374 | with aubio.source(args.source_uri, hop_size=args.hop_size, | ||
| 375 | samplerate=args.samplerate) as a_source: | ||
| 376 | # always update args.samplerate to native samplerate, in case | ||
| 377 | # source was opened with args.samplerate=0 | ||
| 378 | args.samplerate = a_source.samplerate | ||
| 379 | # create the processor for this subcommand | ||
| 380 | processor = args.process(args) | ||
| 381 | frames_read = 0 | ||
| 382 | while True: | ||
| 383 | # read new block from source | ||
| 384 | block, read = a_source() | ||
| 385 | # execute processor on this block | ||
| 386 | res = processor(block) | ||
| 387 | # print results for this block | ||
| 388 | if args.verbose > 0: | ||
| 389 | processor.repr_res(res, frames_read, a_source.samplerate) | ||
| 390 | # increment total number of frames read | ||
| 391 | frames_read += read | ||
| 392 | # exit loop at end of file | ||
| 393 | if read < a_source.hop_size: break | ||
| 394 | # flush the processor if needed | ||
| 395 | processor.flush(frames_read, a_source.samplerate) | ||
| 396 | if args.verbose > 1: | ||
| 397 | fmt_string = "read {:.2f}s" | ||
| 398 | fmt_string += " ({:d} samples in {:d} blocks of {:d})" | ||
| 399 | fmt_string += " from {:s} at {:d}Hz\n" | ||
| 400 | sys.stderr.write(fmt_string.format( | ||
| 401 | frames_read/float(a_source.samplerate), | ||
| 402 | frames_read, | ||
| 403 | frames_read // a_source.hop_size + 1, | ||
| 404 | a_source.hop_size, | ||
| 405 | a_source.uri, | ||
| 406 | a_source.samplerate)) | ||
| 407 | except KeyboardInterrupt as e: | ||
| 408 | sys.exit(1) | ||
| @@ -6,11 +6,10 @@ · 5 unmodified lines | |||
| 6 | 6 | ||
| 7 | import sys | 7 | import sys |
| 8 | 8 | ||
| 9 | usage = "usage: %s [options] -i soundfile" % sys.argv[0] | ||
| 10 | usage += "\n help: %s -h" % sys.argv[0] | ||
| 11 | |||
| 12 | def parse_args(): | 9 | def parse_args(): |
| 13 | from optparse import OptionParser | 10 | from optparse import OptionParser |
| 11 | usage = "usage: %s [options] -i soundfile" % sys.argv[0] | ||
| 12 | usage += "\n help: %s -h" % sys.argv[0] | ||
| 14 | parser = OptionParser(usage=usage) | 13 | parser = OptionParser(usage=usage) |
| 15 | parser.add_option("-i", "--input", action = "store", dest = "source_file", | 14 | parser.add_option("-i", "--input", action = "store", dest = "source_file", |
| 16 | help="input sound file to analyse", metavar = "<source_file>") | 15 | help="input sound file to analyse", metavar = "<source_file>") |
| @@ -133,7 +132,6 @@ def parse_args(): · 116 unmodified lines | |||
| 133 | help="be quiet") | 132 | help="be quiet") |
| 134 | (options, args) = parser.parse_args() | 133 | (options, args) = parser.parse_args() |
| 135 | if not options.source_file: | 134 | if not options.source_file: |
| 136 | import os.path | ||
| 137 | if len(args) == 1: | 135 | if len(args) == 1: |
| 138 | options.source_file = args[0] | 136 | options.source_file = args[0] |
| 139 | else: | 137 | else: |
| @@ -141,7 +139,7 @@ def parse_args(): · 1 unmodified line | |||
| 141 | sys.exit(1) | 139 | sys.exit(1) |
| 142 | return options, args | 140 | return options, args |
| 143 | 141 | ||
| 144 | if __name__ == '__main__': | 142 | def main(): |
| 145 | options, args = parse_args() | 143 | options, args = parse_args() |
| 146 | 144 | ||
| 147 | hopsize = options.hopsize | 145 | hopsize = options.hopsize |
| @@ -149,7 +147,7 @@ if __name__ == '__main__': · 1 unmodified line | |||
| 149 | samplerate = options.samplerate | 147 | samplerate = options.samplerate |
| 150 | source_file = options.source_file | 148 | source_file = options.source_file |
| 151 | 149 | ||
| 152 | from aubio import onset, tempo, source, sink | 150 | from aubio import onset, tempo, source |
| 153 | 151 | ||
| 154 | s = source(source_file, samplerate, hopsize) | 152 | s = source(source_file, samplerate, hopsize) |
| 155 | if samplerate == 0: samplerate = s.get_samplerate() | 153 | if samplerate == 0: samplerate = s.get_samplerate() |