Changeset 088760e for python/lib
- Timestamp:
- Oct 31, 2018, 10:26:52 PM (6 years ago)
- Branches:
- feature/constantq
- Children:
- c03d191
- Parents:
- 45c2c5c (diff), 7a54b37 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Location:
- python/lib
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
python/lib/aubio/__init__.py
r45c2c5c r088760e 1 1 #! /usr/bin/env python 2 # -*- coding: utf8 -*- 3 4 """ 5 aubio 6 ===== 7 8 Provides a number of classes and functions for music and audio signal 9 analysis. 10 11 How to use the documentation 12 ---------------------------- 13 14 Documentation of the python module is available as docstrings provided 15 within the code, and a reference guide available online from `the 16 aubio homepage <https://aubio.org/documentation>`_. 17 18 The docstrings examples are written assuming `aubio` and `numpy` have been 19 imported with: 20 21 >>> import aubio 22 >>> import numpy as np 23 """ 2 24 3 25 import numpy … … 9 31 10 32 class fvec(numpy.ndarray): 11 """a numpy vector holding audio samples""" 33 """fvec(input_arg=1024) 34 A vector holding float samples. 12 35 13 def __new__(cls, input_arg=1024, **kwargs): 36 If `input_arg` is an `int`, a 1-dimensional vector of length `input_arg` 37 will be created and filled with zeros. Otherwise, if `input_arg` is an 38 `array_like` object, it will be converted to a 1-dimensional vector of 39 type :data:`float_type`. 40 41 Parameters 42 ---------- 43 input_arg : `int` or `array_like` 44 Can be a positive integer, or any object that can be converted to 45 a numpy array with :func:`numpy.array`. 46 47 Examples 48 -------- 49 >>> aubio.fvec(10) 50 array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], dtype=float32) 51 >>> aubio.fvec([0,1,2]) 52 array([0., 1., 2.], dtype=float32) 53 >>> a = np.arange(10); type(a), type(aubio.fvec(a)) 54 (<class 'numpy.ndarray'>, <class 'numpy.ndarray'>) 55 >>> a.dtype, aubio.fvec(a).dtype 56 (dtype('int64'), dtype('float32')) 57 58 Notes 59 ----- 60 61 In the Python world, `fvec` is simply a subclass of 62 :class:`numpy.ndarray`. In practice, any 1-dimensional `numpy.ndarray` of 63 `dtype` :data:`float_type` may be passed to methods accepting 64 `fvec` as parameter. For instance, `sink()` or `pvoc()`. 65 66 See Also 67 -------- 68 cvec : a container holding spectral data 69 numpy.ndarray : parent class of :class:`fvec` 70 numpy.zeros : create a numpy array filled with zeros 71 numpy.array : create a numpy array from an existing object 72 """ 73 def __new__(cls, input_arg=1024): 14 74 if isinstance(input_arg, int): 15 75 if input_arg == 0: 16 76 raise ValueError("vector length of 1 or more expected") 17 return numpy.zeros(input_arg, dtype=float_type, **kwargs)77 return numpy.zeros(input_arg, dtype=float_type, order='C') 18 78 else: 19 return numpy.array(input_arg, dtype=float_type, **kwargs) 79 np_input = numpy.array(input_arg, dtype=float_type, order='C') 80 if len(np_input.shape) != 1: 81 raise ValueError("input_arg should have shape (n,)") 82 if np_input.shape[0] == 0: 83 raise ValueError("vector length of 1 or more expected") 84 return np_input -
python/lib/aubio/cmd.py
r45c2c5c r088760e 102 102 subparser.add_input() 103 103 subparser.add_buf_hop_size() 104 subparser.add_silence() 105 subparser.add_release_drop() 104 106 subparser.add_time_format() 105 107 subparser.add_verbose_help() … … 138 140 139 141 def parser_add_subcommand_cut(subparsers): 140 # quiet subcommand142 # cut subcommand 141 143 subparser = subparsers.add_parser('cut', 142 144 help='slice at timestamps') … … 207 209 action="store", dest="silence", default=-70, 208 210 help="silence threshold") 211 212 def add_release_drop(self): 213 self.add_argument("-d", "--release-drop", 214 metavar = "<value>", type=float, 215 action="store", dest="release_drop", default=10, 216 help="release drop threshold") 209 217 210 218 def add_minioi(self, default="12ms"): … … 248 256 action = "store", dest = "cut_until_nslices", default = None, 249 257 help="how many extra slices should be added at the end of each slice") 258 self.add_argument("--create-first", 259 action = "store_true", dest = "create_first", default = False, 260 help="always include first slice") 250 261 251 262 # some utilities … … 380 391 self.parse_options(args, self.valid_opts) 381 392 self.notes = aubio.notes(**self.options) 393 if args.silence is not None: 394 self.notes.set_silence(args.silence) 395 if args.release_drop is not None: 396 self.notes.set_release_drop(args.release_drop) 382 397 super(process_notes, self).__init__(args) 383 398 def __call__(self, block): … … 500 515 def main(): 501 516 parser = aubio_parser() 502 args = parser.parse_args() 517 if sys.version_info[0] != 3: 518 # on py2, create a dummy ArgumentParser to workaround the 519 # optional subcommand issue. See https://bugs.python.org/issue9253 520 # This ensures that: 521 # - version string is shown when only '-V' is passed 522 # - help is printed if '-V' is passed with any other argument 523 # - any other argument get forwarded to the real parser 524 parser_root = argparse.ArgumentParser(add_help=False) 525 parser_root.add_argument('-V', '--version', help="show version", 526 action="store_true", dest="show_version") 527 args, extras = parser_root.parse_known_args() 528 if args.show_version == False: # no -V, forward to parser 529 args = parser.parse_args(extras, namespace=args) 530 elif len(extras) != 0: # -V with other arguments, print help 531 parser.print_help() 532 sys.exit(1) 533 else: # in py3, we can simply use parser directly 534 args = parser.parse_args() 503 535 if 'show_version' in args and args.show_version: 504 536 sys.stdout.write('aubio version ' + aubio.version + '\n') -
python/lib/aubio/cut.py
r45c2c5c r088760e 102 102 s = source(source_uri, samplerate, hopsize) 103 103 if samplerate == 0: 104 samplerate = s. get_samplerate()104 samplerate = s.samplerate 105 105 options.samplerate = samplerate 106 106 … … 151 151 timestamps, timestamps_end = timestamps_end, 152 152 output_dir = options.output_directory, 153 samplerate = options.samplerate) 153 samplerate = options.samplerate, 154 create_first = options.create_first) 154 155 155 156 def main(): -
python/lib/aubio/midiconv.py
r45c2c5c r088760e 2 2 """ utilities to convert midi note number to and from note names """ 3 3 4 __all__ = ['note2midi', 'midi2note', 'freq2note' ]4 __all__ = ['note2midi', 'midi2note', 'freq2note', 'note2freq'] 5 5 6 6 import sys 7 from ._aubio import freqtomidi, miditofreq 8 7 9 py3 = sys.version_info[0] == 3 8 10 if py3: … … 14 16 15 17 def note2midi(note): 16 " convert note name to midi note number, e.g. [C-1, G9] -> [0, 127] " 18 """Convert note name to midi note number. 19 20 Input string `note` should be composed of one note root 21 and one octave, with optionally one modifier in between. 22 23 List of valid components: 24 25 - note roots: `C`, `D`, `E`, `F`, `G`, `A`, `B`, 26 - modifiers: `b`, `#`, as well as unicode characters 27 `𝄫`, `♭`, `♮`, `♯` and `𝄪`, 28 - octave numbers: `-1` -> `11`. 29 30 Parameters 31 ---------- 32 note : str 33 note name 34 35 Returns 36 ------- 37 int 38 corresponding midi note number 39 40 Examples 41 -------- 42 >>> aubio.note2midi('C#4') 43 61 44 >>> aubio.note2midi('B♭5') 45 82 46 47 Raises 48 ------ 49 TypeError 50 If `note` was not a string. 51 ValueError 52 If an error was found while converting `note`. 53 54 See Also 55 -------- 56 midi2note, freqtomidi, miditofreq 57 """ 17 58 _valid_notenames = {'C': 0, 'D': 2, 'E': 4, 'F': 5, 'G': 7, 'A': 9, 'B': 11} 18 59 _valid_modifiers = { … … 25 66 _valid_octaves = range(-1, 10) 26 67 if not isinstance(note, str_instances): 27 raise TypeError("a string is required, got %s (%s)" % (note, str(type(note)))) 68 msg = "a string is required, got {:s} ({:s})" 69 raise TypeError(msg.format(str(type(note)), repr(note))) 28 70 if len(note) not in range(2, 5): 29 raise ValueError("string of 2 to 4 characters expected, got %d (%s)" \30 %(len(note), note))71 msg = "string of 2 to 4 characters expected, got {:d} ({:s})" 72 raise ValueError(msg.format(len(note), note)) 31 73 notename, modifier, octave = [None]*3 32 74 … … 52 94 raise ValueError("%s is not a valid octave" % octave) 53 95 54 midi = 12 + octave * 12 + _valid_notenames[notename] + _valid_modifiers[modifier] 96 midi = 12 + octave * 12 + _valid_notenames[notename] \ 97 + _valid_modifiers[modifier] 55 98 if midi > 127: 56 99 raise ValueError("%s is outside of the range C-2 to G8" % note) … … 58 101 59 102 def midi2note(midi): 60 " convert midi note number to note name, e.g. [0, 127] -> [C-1, G9] " 103 """Convert midi note number to note name. 104 105 Parameters 106 ---------- 107 midi : int [0, 128] 108 input midi note number 109 110 Returns 111 ------- 112 str 113 note name 114 115 Examples 116 -------- 117 >>> aubio.midi2note(70) 118 'A#4' 119 >>> aubio.midi2note(59) 120 'B3' 121 122 Raises 123 ------ 124 TypeError 125 If `midi` was not an integer. 126 ValueError 127 If `midi` is out of the range `[0, 128]`. 128 129 See Also 130 -------- 131 note2midi, miditofreq, freqtomidi 132 """ 61 133 if not isinstance(midi, int_instances): 62 134 raise TypeError("an integer is required, got %s" % midi) 63 135 if midi not in range(0, 128): 64 raise ValueError("an integer between 0 and 127 is excepted, got %d" % midi) 65 _valid_notenames = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B'] 136 msg = "an integer between 0 and 127 is excepted, got {:d}" 137 raise ValueError(msg.format(midi)) 138 _valid_notenames = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 139 'A', 'A#', 'B'] 66 140 return _valid_notenames[midi % 12] + str(int(midi / 12) - 1) 67 141 68 142 def freq2note(freq): 69 " convert frequency in Hz to nearest note name, e.g. [0, 22050.] -> [C-1, G9] " 70 from aubio import freqtomidi 71 return midi2note(int(freqtomidi(freq))) 143 """Convert frequency in Hz to nearest note name. 144 145 Parameters 146 ---------- 147 freq : float [0, 23000[ 148 input frequency, in Hz 149 150 Returns 151 ------- 152 str 153 name of the nearest note 154 155 Example 156 ------- 157 >>> aubio.freq2note(440) 158 'A4' 159 >>> aubio.freq2note(220.1) 160 'A3' 161 """ 162 nearest_note = int(freqtomidi(freq) + .5) 163 return midi2note(nearest_note) 164 165 def note2freq(note): 166 """Convert note name to corresponding frequency, in Hz. 167 168 Parameters 169 ---------- 170 note : str 171 input note name 172 173 Returns 174 ------- 175 freq : float [0, 23000[ 176 frequency, in Hz 177 178 Example 179 ------- 180 >>> aubio.note2freq('A4') 181 440 182 >>> aubio.note2freq('A3') 183 220.1 184 """ 185 midi = note2midi(note) 186 return miditofreq(midi) -
python/lib/aubio/slicing.py
r45c2c5c r088760e 7 7 8 8 def slice_source_at_stamps(source_file, timestamps, timestamps_end=None, 9 output_dir=None, samplerate=0, hopsize=256): 10 """ slice a sound file at given timestamps """ 9 output_dir=None, samplerate=0, hopsize=256, 10 create_first=False): 11 """Slice a sound file at given timestamps. 12 13 This function reads `source_file` and creates slices, new smaller 14 files each starting at `t` in `timestamps`, a list of integer 15 corresponding to time locations in `source_file`, in samples. 16 17 If `timestamps_end` is unspecified, the slices will end at 18 `timestamps_end[n] = timestamps[n+1]-1`, or the end of file. 19 Otherwise, `timestamps_end` should be a list with the same length 20 as `timestamps` containing the locations of the end of each slice. 21 22 If `output_dir` is unspecified, the new slices will be written in 23 the current directory. If `output_dir` is a string, new slices 24 will be written in `output_dir`, after creating the directory if 25 required. 26 27 The default `samplerate` is 0, meaning the original sampling rate 28 of `source_file` will be used. When using a sampling rate 29 different to the one of the original files, `timestamps` and 30 `timestamps_end` should be expressed in the re-sampled signal. 31 32 The `hopsize` parameter simply tells :class:`source` to use this 33 hopsize and does not change the output slices. 34 35 If `create_first` is True and `timestamps` does not start with `0`, the 36 first slice from `0` to `timestamps[0] - 1` will be automatically added. 37 38 Parameters 39 ---------- 40 source_file : str 41 path of the resource to slice 42 timestamps : :obj:`list` of :obj:`int` 43 time stamps at which to slice, in samples 44 timestamps_end : :obj:`list` of :obj:`int` (optional) 45 time stamps at which to end the slices 46 output_dir : str (optional) 47 output directory to write the slices to 48 samplerate : int (optional) 49 samplerate to read the file at 50 hopsize : int (optional) 51 number of samples read from source per iteration 52 create_first : bool (optional) 53 always create the slice at the start of the file 54 55 Examples 56 -------- 57 Create two slices: the first slice starts at the beginning of the 58 input file `loop.wav` and lasts exactly one second, starting at 59 sample `0` and ending at sample `44099`; the second slice starts 60 at sample `44100` and lasts until the end of the input file: 61 62 >>> aubio.slice_source_at_stamps('loop.wav', [0, 44100]) 63 64 Create one slice, from 1 second to 2 seconds: 65 66 >>> aubio.slice_source_at_stamps('loop.wav', [44100], [44100 * 2 - 1]) 67 68 Notes 69 ----- 70 Slices may be overlapping. If `timestamps_end` is `1` element 71 shorter than `timestamps`, the last slice will end at the end of 72 the file. 73 """ 11 74 12 75 if timestamps is None or len(timestamps) == 0: 13 76 raise ValueError("no timestamps given") 14 77 15 if timestamps[0] != 0 :78 if timestamps[0] != 0 and create_first: 16 79 timestamps = [0] + timestamps 17 80 if timestamps_end is not None: … … 19 82 20 83 if timestamps_end is not None: 21 if len(timestamps_end) != len(timestamps): 84 if len(timestamps_end) == len(timestamps) - 1: 85 timestamps_end = timestamps_end + [_max_timestamp] 86 elif len(timestamps_end) != len(timestamps): 22 87 raise ValueError("len(timestamps_end) != len(timestamps)") 23 88 else: … … 49 114 vec, read = _source.do_multi() 50 115 # if the total number of frames read will exceed the next region start 51 iflen(regions) and total_frames + read >= regions[0][0]:116 while len(regions) and total_frames + read >= regions[0][0]: 52 117 #print "getting", regions[0], "at", total_frames 53 118 # get next region … … 76 141 # write remaining samples from current region 77 142 _sink.do_multi(vec[:, start:remaining], remaining - start) 78 #print "closing region", "remaining", remaining143 #print("closing region", "remaining", remaining) 79 144 # close this file 80 145 _sink.close() … … 83 148 _sink.do_multi(vec[:, start:read], read - start) 84 149 total_frames += read 150 # remove old slices 151 slices = list(filter(lambda s: s['end_stamp'] > total_frames, 152 slices)) 85 153 if read < hopsize: 86 154 break -
python/lib/gen_code.py
r45c2c5c r088760e 483 483 484 484 if (err > 0) {{ 485 PyErr_SetString (PyExc_ValueError, "error running aubio_{shortname}_set_{param}"); 485 if (PyErr_Occurred() == NULL) {{ 486 PyErr_SetString (PyExc_ValueError, "error running aubio_{shortname}_set_{param}"); 487 }} else {{ 488 // change the RuntimeError into ValueError 489 PyObject *type, *value, *traceback; 490 PyErr_Fetch(&type, &value, &traceback); 491 PyErr_Restore(PyExc_ValueError, value, traceback); 492 }} 486 493 return NULL; 487 494 }} -
python/lib/gen_external.py
r45c2c5c r088760e 78 78 cpp_cmd = os.environ.get('CC', 'cc').split() 79 79 cpp_cmd += ['-E'] 80 cpp_cmd += ['-x', 'c'] # force C language (emcc defaults to c++) 80 if 'emcc' in cpp_cmd: 81 cpp_cmd += ['-x', 'c'] # emcc defaults to c++, force C language 81 82 return cpp_cmd 82 83 … … 85 86 ''' return a dense and preprocessed string of all c declarations implied by aubio.h 86 87 ''' 88 cpp_output = get_cpp_output(header=header, usedouble=usedouble) 89 return filter_cpp_output (cpp_output) 90 91 92 def get_cpp_output(header=header, usedouble=False): 93 ''' find and run a C pre-processor on aubio.h ''' 87 94 cpp_cmd = get_preprocessor() 88 95 … … 105 112 cpp_output = proc.stdout.read() 106 113 err_output = proc.stderr.read() 114 if err_output: 115 print("Warning: preprocessor produced errors or warnings:\n%s" \ 116 % err_output.decode('utf8')) 107 117 if not cpp_output: 108 raise Exception("preprocessor output is empty:\n%s" % err_output) 109 elif err_output: 110 print("Warning: preprocessor produced warnings:\n%s" % err_output) 118 raise_msg = "preprocessor output is empty! Running command " \ 119 + "\"%s\" failed" % " ".join(cpp_cmd) 120 if err_output: 121 raise_msg += " with stderr: \"%s\"" % err_output.decode('utf8') 122 else: 123 raise_msg += " with no stdout or stderr" 124 raise Exception(raise_msg) 111 125 if not isinstance(cpp_output, list): 112 126 cpp_output = [l.strip() for l in cpp_output.decode('utf8').split('\n')] 113 127 114 cpp_output = filter(lambda y: len(y) > 1, cpp_output) 128 return cpp_output 129 130 def filter_cpp_output(cpp_raw_output): 131 ''' prepare cpp-output for parsing ''' 132 cpp_output = filter(lambda y: len(y) > 1, cpp_raw_output) 115 133 cpp_output = list(filter(lambda y: not y.startswith('#'), cpp_output)) 116 134
Note: See TracChangeset
for help on using the changeset viewer.