Changes in / [3e48568:2a4ce6d]
- Files:
-
- 4 added
- 24 edited
Legend:
- Unmodified
- Added
- Removed
-
.appveyor.yml
r3e48568 r2a4ce6d 8 8 # pre-installed python version, see: 9 9 # http://www.appveyor.com/docs/installed-software#python 10 - PYTHON : "C:\\Python27"10 - PYTHONDIR: "C:\\Python27" 11 11 PYTHON_VERSION: "2.7.x" 12 12 PYTHON_ARCH: "32" 13 13 14 - PYTHON : "C:\\Python27-x64"14 - PYTHONDIR: "C:\\Python27-x64" 15 15 PYTHON_VERSION: "2.7.x" 16 16 PYTHON_ARCH: "64" 17 17 18 - PYTHON : "C:\\Python34"18 - PYTHONDIR: "C:\\Python34" 19 19 PYTHON_VERSION: "3.4.x" 20 20 PYTHON_ARCH: "32" 21 21 22 - PYTHON : "C:\\Python34-x64"22 - PYTHONDIR: "C:\\Python34-x64" 23 23 PYTHON_VERSION: "3.4.x" 24 24 PYTHON_ARCH: "64" 25 25 26 - PYTHON : "C:\\Python35"26 - PYTHONDIR: "C:\\Python35" 27 27 PYTHON_VERSION: "3.5.x" 28 28 PYTHON_ARCH: "32" 29 29 30 - PYTHON : "C:\\Python35-x64"30 - PYTHONDIR: "C:\\Python35-x64" 31 31 PYTHON_VERSION: "3.5.x" 32 32 PYTHON_ARCH: "64" … … 40 40 41 41 # Check that we have the expected version and architecture for Python 42 - "%PYTHON %\\python.exe --version"43 - "%PYTHON %\\python.exe -c \"import struct; print(struct.calcsize('P') * 8)\""42 - "%PYTHONDIR%\\python.exe --version" 43 - "%PYTHONDIR%\\python.exe -c \"import struct; print(struct.calcsize('P') * 8)\"" 44 44 45 45 # We need wheel installed to build wheels 46 - "%PYTHON %\\python.exe -m pip install wheel"46 - "%PYTHONDIR%\\python.exe -m pip install wheel" 47 47 48 - "SET PATH=%PATH_EXTRAS%;%PYTHON %;%PYTHON%\\Scripts;%PATH%"48 - "SET PATH=%PATH_EXTRAS%;%PYTHONDIR%;%PYTHONDIR%\\Scripts;%PATH%" 49 49 50 50 - "pip install --disable-pip-version-check --user --upgrade pip" … … 52 52 53 53 before_build: 54 - curl -fsS -o waf https://waf.io/waf-1.8.22 55 - curl -fsS -o waf.bat https://raw.githubusercontent.com/waf-project/waf/master/utils/waf.bat 54 - "bash scripts/get_waf.sh" 56 55 57 56 build_script: … … 63 62 - "nose2 --verbose" 64 63 # clean up 65 - waf distclean64 - "python waf distclean" 66 65 # build libaubio 67 - waf configure build --verbose66 - python waf configure build --verbose --msvc_version="msvc 14.0" 68 67 # build python module using libaubio dll 69 68 - "python setup.py build" -
.travis.yml
r3e48568 r2a4ce6d 82 82 - libfftw3-dev 83 83 - sox 84 - lcov 84 85 85 86 before_install: … … 90 91 brew install ffmpeg 91 92 brew install libsndfile 93 brew install lcov 92 94 export PATH="$HOME/Library/Python/2.7/bin/:$PATH" 93 95 fi; … … 98 100 - which pip 99 101 - pip --version 102 - pip install python-coveralls 103 - gem install coveralls-lcov 100 104 101 105 script: … … 104 108 if [[ -z "$AUBIO_NOTESTS" ]]; then 105 109 make test_lib_python_clean 106 make test_python_only_clean110 make coverage 107 111 else 108 112 make test_lib_only_clean 109 113 fi; 114 115 after_success: 116 - | 117 if [[ -z "$AUBIO_NOTESTS" ]]; then 118 # upload lcov coverage to coveralls.io 119 coveralls-lcov build/coverage.info 120 # upload python coverage 121 #coveralls 122 # upload to codecov 123 bash <(curl -s https://codecov.io/bash) 124 fi 110 125 111 126 notifications: -
Makefile
r3e48568 r2a4ce6d 36 36 MANDIR?=$(DATAROOTDIR)/man 37 37 38 # default nose2 command 39 NOSE2?=nose2 -N 4 --verbose 40 38 41 SOX=sox 39 42 … … 136 139 test_python: local_dylib 137 140 # run test with installed package 138 ./python/tests/run_all_tests --verbose139 # also run with nose, multiple processes140 nose2 -N 4141 # ./python/tests/run_all_tests --verbose 142 # run with nose2, multiple processes 143 $(NOSE2) 141 144 142 145 clean_python: … … 232 235 check_clean_python 233 236 237 coverage: export CFLAGS=--coverage 238 coverage: export LDFLAGS=--coverage 239 coverage: export PYTHONPATH=$(PWD)/python/lib 240 coverage: export LD_LIBRARY_PATH=$(PWD)/build/src 241 coverage: force_uninstall_python deps_python \ 242 clean_python clean distclean build local_dylib 243 lcov --capture --no-external --directory . --output-file build/coverage_lib.info 244 pip install -v -e . 245 coverage run `which nose2` 246 lcov --capture --no-external --directory . --output-file build/coverage_python.info 247 lcov -a build/coverage_python.info -a build/coverage_lib.info -o build/coverage.info 248 249 coverage_report: coverage 250 genhtml build/coverage.info --output-directory lcov_html 251 mkdir -p gcovr_html/ 252 gcovr -r . --html --html-details \ 253 --output gcovr_html/index.html \ 254 --exclude ".*tests/.*" --exclude ".*examples/.*" 255 coverage report 256 coverage html 257 234 258 sphinx: configure 235 259 $(WAFCMD) sphinx $(WAFOPTS) -
aubio.pc.in
r3e48568 r2a4ce6d 8 8 Version: @VERSION@ 9 9 Libs: -L${libdir} -laubio 10 Cflags: -I${includedir} 10 Cflags: -I${includedir} -
python/demos/demo_bpm_extract.py
r3e48568 r2a4ce6d 4 4 from numpy import median, diff 5 5 6 def get_file_bpm(path, params =None):6 def get_file_bpm(path, params=None): 7 7 """ Calculate the beats per minute (bpm) of a given file. 8 8 path: path to the file … … 11 11 if params is None: 12 12 params = {} 13 try: 14 win_s = params['win_s'] 15 samplerate = params['samplerate'] 16 hop_s = params['hop_s'] 17 except KeyError: 18 """ 19 # super fast 20 samplerate, win_s, hop_s = 4000, 128, 64 21 # fast 22 samplerate, win_s, hop_s = 8000, 512, 128 23 """ 24 # default: 25 samplerate, win_s, hop_s = 44100, 1024, 512 13 # default: 14 samplerate, win_s, hop_s = 44100, 1024, 512 15 if 'mode' in params: 16 if params.mode in ['super-fast']: 17 # super fast 18 samplerate, win_s, hop_s = 4000, 128, 64 19 elif params.mode in ['fast']: 20 # fast 21 samplerate, win_s, hop_s = 8000, 512, 128 22 elif params.mode in ['default']: 23 pass 24 else: 25 print("unknown mode {:s}".format(params.mode)) 26 # manual settings 27 if 'samplerate' in params: 28 samplerate = params.samplerate 29 if 'win_s' in params: 30 win_s = params.win_s 31 if 'hop_s' in params: 32 hop_s = params.hop_s 26 33 27 34 s = source(path, samplerate, hop_s) … … 45 52 break 46 53 47 # Convert to periods and to bpm 48 if len(beats) > 1: 49 if len(beats) < 4: 50 print("few beats found in {:s}".format(path)) 51 bpms = 60./diff(beats) 52 b = median(bpms) 53 else: 54 b = 0 55 print("not enough beats found in {:s}".format(path)) 56 return b 54 def beats_to_bpm(beats, path): 55 # if enough beats are found, convert to periods then to bpm 56 if len(beats) > 1: 57 if len(beats) < 4: 58 print("few beats found in {:s}".format(path)) 59 bpms = 60./diff(beats) 60 return median(bpms) 61 else: 62 print("not enough beats found in {:s}".format(path)) 63 return 0 64 65 return beats_to_bpm(beats, path) 57 66 58 67 if __name__ == '__main__': 59 import sys 60 for f in sys.argv[1:]: 61 bpm = get_file_bpm(f) 68 import argparse 69 parser = argparse.ArgumentParser() 70 parser.add_argument('-m', '--mode', 71 help="mode [default|fast|super-fast]", 72 dest="mode") 73 parser.add_argument('sources', 74 nargs='*', 75 help="input_files") 76 args = parser.parse_args() 77 for f in args.sources: 78 bpm = get_file_bpm(f, params = args) 62 79 print("{:6s} {:s}".format("{:2f}".format(bpm), f)) -
python/demos/demo_tapthebeat.py
r3e48568 r2a4ce6d 45 45 46 46 # pyaudio callback 47 def pyaudio_callback( in_data, frame_count, time_info,status):47 def pyaudio_callback(_in_data, _frame_count, _time_info, _status): 48 48 samples, read = a_source() 49 49 is_beat = a_tempo(samples) -
python/ext/py-cvec.c
r3e48568 r2a4ce6d 143 143 npy_intp length; 144 144 if (!PyAubio_IsValidVector(input)) { 145 return 1;145 return -1; 146 146 } 147 147 length = PyArray_SIZE ((PyArrayObject *)input); … … 150 150 "input array has length %" NPY_INTP_FMT ", but cvec has length %d", length, 151 151 vec->length); 152 return 1;152 return -1; 153 153 } 154 154 … … 164 164 npy_intp length; 165 165 if (!PyAubio_IsValidVector(input)) { 166 return 1;166 return -1; 167 167 } 168 168 length = PyArray_SIZE ((PyArrayObject *)input); … … 171 171 "input array has length %" NPY_INTP_FMT ", but cvec has length %d", length, 172 172 vec->length); 173 return 1;173 return -1; 174 174 } 175 175 -
python/ext/py-phasevoc.c
r3e48568 r2a4ce6d 156 156 } 157 157 158 static PyObject * 159 Pyaubio_pvoc_set_window (Py_pvoc *self, PyObject *args) 160 { 161 uint_t err = 0; 162 char_t *window = NULL; 163 164 if (!PyArg_ParseTuple (args, "s", &window)) { 165 return NULL; 166 } 167 err = aubio_pvoc_set_window (self->o, window); 168 169 if (err > 0) { 170 PyErr_SetString (PyExc_ValueError, "error running aubio_pvoc_set_window"); 171 return NULL; 172 } 173 Py_RETURN_NONE; 174 } 175 158 176 static PyMethodDef Py_pvoc_methods[] = { 159 177 {"rdo", (PyCFunction) Py_pvoc_rdo, METH_VARARGS, 160 178 "synthesis of spectral grain"}, 179 {"set_window", (PyCFunction) Pyaubio_pvoc_set_window, METH_VARARGS, ""}, 161 180 {NULL} 162 181 }; -
python/lib/aubio/cmd.py
r3e48568 r2a4ce6d 21 21 22 22 subparsers = parser.add_subparsers(title='commands', dest='command', 23 parser_class= AubioArgumentParser, 23 24 metavar="") 24 25 26 parser_add_subcommand_help(subparsers) 27 28 parser_add_subcommand_onset(subparsers) 29 parser_add_subcommand_pitch(subparsers) 30 parser_add_subcommand_beat(subparsers) 31 parser_add_subcommand_tempo(subparsers) 32 parser_add_subcommand_notes(subparsers) 33 parser_add_subcommand_mfcc(subparsers) 34 parser_add_subcommand_melbands(subparsers) 35 parser_add_subcommand_quiet(subparsers) 36 parser_add_subcommand_cut(subparsers) 37 38 return parser 39 40 def parser_add_subcommand_help(subparsers): 41 # global help subcommand 42 subparsers.add_parser('help', 43 help='show help message', 44 formatter_class = argparse.ArgumentDefaultsHelpFormatter) 45 46 def parser_add_subcommand_onset(subparsers): 25 47 # onset subcommand 26 48 subparser = subparsers.add_parser('onset', 27 49 help='estimate time of onsets (beginning of sound event)', 28 50 formatter_class = argparse.ArgumentDefaultsHelpFormatter) 29 parser_add_input(subparser)30 parser_add_buf_hop_size(subparser)51 subparser.add_input() 52 subparser.add_buf_hop_size() 31 53 helpstr = "onset novelty function" 32 54 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)55 subparser.add_method(helpstr=helpstr) 56 subparser.add_threshold() 57 subparser.add_silence() 58 subparser.add_minioi() 59 subparser.add_time_format() 60 subparser.add_verbose_help() 39 61 subparser.set_defaults(process=process_onset) 40 62 63 def parser_add_subcommand_pitch(subparsers): 41 64 # pitch subcommand 42 65 subparser = subparsers.add_parser('pitch', 43 66 help='estimate fundamental frequency (monophonic)') 44 parser_add_input(subparser)45 parser_add_buf_hop_size(subparser,buf_size=2048)67 subparser.add_input() 68 subparser.add_buf_hop_size(buf_size=2048) 46 69 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_pitch_unit(subparser)50 parser_add_silence(subparser)51 parser_add_time_format(subparser)52 parser_add_verbose_help(subparser)70 subparser.add_method(helpstr=helpstr) 71 subparser.add_threshold() 72 subparser.add_pitch_unit() 73 subparser.add_silence() 74 subparser.add_time_format() 75 subparser.add_verbose_help() 53 76 subparser.set_defaults(process=process_pitch) 54 77 78 def parser_add_subcommand_beat(subparsers): 55 79 # beat subcommand 56 80 subparser = subparsers.add_parser('beat', 57 81 help='estimate location of beats') 58 parser_add_input(subparser)59 parser_add_buf_hop_size(subparser,buf_size=1024, hop_size=512)60 parser_add_time_format(subparser)61 parser_add_verbose_help(subparser)82 subparser.add_input() 83 subparser.add_buf_hop_size(buf_size=1024, hop_size=512) 84 subparser.add_time_format() 85 subparser.add_verbose_help() 62 86 subparser.set_defaults(process=process_beat) 63 87 88 def parser_add_subcommand_tempo(subparsers): 64 89 # tempo subcommand 65 90 subparser = subparsers.add_parser('tempo', 66 91 help='estimate overall tempo in bpm') 67 parser_add_input(subparser)68 parser_add_buf_hop_size(subparser,buf_size=1024, hop_size=512)69 parser_add_time_format(subparser)70 parser_add_verbose_help(subparser)92 subparser.add_input() 93 subparser.add_buf_hop_size(buf_size=1024, hop_size=512) 94 subparser.add_time_format() 95 subparser.add_verbose_help() 71 96 subparser.set_defaults(process=process_tempo) 72 97 98 def parser_add_subcommand_notes(subparsers): 73 99 # notes subcommand 74 100 subparser = subparsers.add_parser('notes', 75 101 help='estimate midi-like notes (monophonic)') 76 parser_add_input(subparser)77 parser_add_buf_hop_size(subparser)78 parser_add_time_format(subparser)79 parser_add_verbose_help(subparser)102 subparser.add_input() 103 subparser.add_buf_hop_size() 104 subparser.add_time_format() 105 subparser.add_verbose_help() 80 106 subparser.set_defaults(process=process_notes) 81 107 108 def parser_add_subcommand_mfcc(subparsers): 82 109 # mfcc subcommand 83 110 subparser = subparsers.add_parser('mfcc', 84 111 help='extract Mel-Frequency Cepstrum Coefficients') 85 parser_add_input(subparser)86 parser_add_buf_hop_size(subparser)87 parser_add_time_format(subparser)88 parser_add_verbose_help(subparser)112 subparser.add_input() 113 subparser.add_buf_hop_size() 114 subparser.add_time_format() 115 subparser.add_verbose_help() 89 116 subparser.set_defaults(process=process_mfcc) 90 117 118 def parser_add_subcommand_melbands(subparsers): 91 119 # melbands subcommand 92 120 subparser = subparsers.add_parser('melbands', 93 121 help='extract energies in Mel-frequency bands') 94 parser_add_input(subparser)95 parser_add_buf_hop_size(subparser)96 parser_add_time_format(subparser)97 parser_add_verbose_help(subparser)122 subparser.add_input() 123 subparser.add_buf_hop_size() 124 subparser.add_time_format() 125 subparser.add_verbose_help() 98 126 subparser.set_defaults(process=process_melbands) 99 127 100 return parser 101 102 def parser_add_input(parser): 103 parser.add_argument("source_uri", default=None, nargs='?', 104 help="input sound file to analyse", metavar = "<source_uri>") 105 parser.add_argument("-i", "--input", dest = "source_uri2", 106 help="input sound file to analyse", metavar = "<source_uri>") 107 parser.add_argument("-r", "--samplerate", 108 metavar = "<freq>", type=int, 109 action="store", dest="samplerate", default=0, 110 help="samplerate at which the file should be represented") 111 112 def parser_add_verbose_help(parser): 113 parser.add_argument("-v","--verbose", 114 action="count", dest="verbose", default=1, 115 help="make lots of noise [default]") 116 parser.add_argument("-q","--quiet", 117 action="store_const", dest="verbose", const=0, 118 help="be quiet") 119 120 def parser_add_buf_hop_size(parser, buf_size=512, hop_size=256): 121 parser.add_argument("-B","--bufsize", 122 action="store", dest="buf_size", default=buf_size, 123 metavar = "<size>", type=int, 124 help="buffer size [default=%d]" % buf_size) 125 parser.add_argument("-H","--hopsize", 126 metavar = "<size>", type=int, 127 action="store", dest="hop_size", default=hop_size, 128 help="overlap size [default=%d]" % hop_size) 129 130 def parser_add_method(parser, method='default', helpstr='method'): 131 parser.add_argument("-m","--method", 132 metavar = "<method>", type=str, 133 action="store", dest="method", default=method, 134 help="%s [default=%s]" % (helpstr, method)) 135 136 def parser_add_threshold(parser, default=None): 137 parser.add_argument("-t","--threshold", 138 metavar = "<threshold>", type=float, 139 action="store", dest="threshold", default=default, 140 help="threshold [default=%s]" % default) 141 142 def parser_add_silence(parser): 143 parser.add_argument("-s", "--silence", 144 metavar = "<value>", type=float, 145 action="store", dest="silence", default=-70, 146 help="silence threshold") 147 148 def parser_add_minioi(parser): 149 parser.add_argument("-M", "--minioi", 150 metavar = "<value>", type=str, 151 action="store", dest="minioi", default="12ms", 152 help="minimum Inter-Onset Interval") 153 154 def parser_add_pitch_unit(parser, default="Hz"): 155 help_str = "frequency unit, should be one of Hz, midi, bin, cent" 156 help_str += " [default=%s]" % default 157 parser.add_argument("-u", "--pitch-unit", 158 metavar = "<value>", type=str, 159 action="store", dest="pitch_unit", default=default, 160 help=help_str) 161 162 def parser_add_time_format(parser): 163 helpstr = "select time values output format (samples, ms, seconds)" 164 helpstr += " [default=seconds]" 165 parser.add_argument("-T", "--time-format", 166 metavar='format', 167 dest="time_format", 168 default=None, 169 help=helpstr) 128 def parser_add_subcommand_quiet(subparsers): 129 # quiet subcommand 130 subparser = subparsers.add_parser('quiet', 131 help='extract timestamps of quiet and loud regions') 132 subparser.add_input() 133 subparser.add_hop_size() 134 subparser.add_silence() 135 subparser.add_time_format() 136 subparser.add_verbose_help() 137 subparser.set_defaults(process=process_quiet) 138 139 def parser_add_subcommand_cut(subparsers): 140 # quiet subcommand 141 subparser = subparsers.add_parser('cut', 142 help='slice at timestamps') 143 subparser.add_input() 144 helpstr = "onset novelty function" 145 helpstr += " <default|energy|hfc|complex|phase|specdiff|kl|mkl|specflux>" 146 subparser.add_method(helpstr=helpstr) 147 subparser.add_buf_hop_size() 148 subparser.add_silence() 149 subparser.add_threshold(default=0.3) 150 subparser.add_minioi() 151 subparser.add_slicer_options() 152 subparser.add_time_format() 153 subparser.add_verbose_help() 154 subparser.set_defaults(process=process_cut) 155 156 class AubioArgumentParser(argparse.ArgumentParser): 157 158 def add_input(self): 159 self.add_argument("source_uri", default=None, nargs='?', 160 help="input sound file to analyse", metavar = "<source_uri>") 161 self.add_argument("-i", "--input", dest = "source_uri2", 162 help="input sound file to analyse", metavar = "<source_uri>") 163 self.add_argument("-r", "--samplerate", 164 metavar = "<freq>", type=int, 165 action="store", dest="samplerate", default=0, 166 help="samplerate at which the file should be represented") 167 168 def add_verbose_help(self): 169 self.add_argument("-v","--verbose", 170 action="count", dest="verbose", default=1, 171 help="make lots of noise [default]") 172 self.add_argument("-q","--quiet", 173 action="store_const", dest="verbose", const=0, 174 help="be quiet") 175 176 def add_buf_hop_size(self, buf_size=512, hop_size=256): 177 self.add_buf_size(buf_size=buf_size) 178 self.add_hop_size(hop_size=hop_size) 179 180 def add_buf_size(self, buf_size=512): 181 self.add_argument("-B","--bufsize", 182 action="store", dest="buf_size", default=buf_size, 183 metavar = "<size>", type=int, 184 help="buffer size [default=%d]" % buf_size) 185 186 def add_hop_size(self, hop_size=256): 187 self.add_argument("-H","--hopsize", 188 metavar = "<size>", type=int, 189 action="store", dest="hop_size", default=hop_size, 190 help="overlap size [default=%d]" % hop_size) 191 192 def add_method(self, method='default', helpstr='method'): 193 self.add_argument("-m","--method", 194 metavar = "<method>", type=str, 195 action="store", dest="method", default=method, 196 help="%s [default=%s]" % (helpstr, method)) 197 198 def add_threshold(self, default=None): 199 self.add_argument("-t","--threshold", 200 metavar = "<threshold>", type=float, 201 action="store", dest="threshold", default=default, 202 help="threshold [default=%s]" % default) 203 204 def add_silence(self): 205 self.add_argument("-s", "--silence", 206 metavar = "<value>", type=float, 207 action="store", dest="silence", default=-70, 208 help="silence threshold") 209 210 def add_minioi(self, default="12ms"): 211 self.add_argument("-M", "--minioi", 212 metavar = "<value>", type=str, 213 action="store", dest="minioi", default=default, 214 help="minimum Inter-Onset Interval [default=%s]" % default) 215 216 def add_pitch_unit(self, default="Hz"): 217 help_str = "frequency unit, should be one of Hz, midi, bin, cent" 218 help_str += " [default=%s]" % default 219 self.add_argument("-u", "--pitch-unit", 220 metavar = "<value>", type=str, 221 action="store", dest="pitch_unit", default=default, 222 help=help_str) 223 224 def add_time_format(self): 225 helpstr = "select time values output format (samples, ms, seconds)" 226 helpstr += " [default=seconds]" 227 self.add_argument("-T", "--time-format", 228 metavar='format', 229 dest="time_format", 230 default=None, 231 help=helpstr) 232 233 def add_slicer_options(self): 234 self.add_argument("-o","--output", type = str, 235 metavar = "<outputdir>", 236 action="store", dest="output_directory", default=None, 237 help="specify path where slices of the original file should be created") 238 self.add_argument("--cut-until-nsamples", type = int, 239 metavar = "<samples>", 240 action = "store", dest = "cut_until_nsamples", default = None, 241 help="how many extra samples should be added at the end of each slice") 242 self.add_argument("--cut-every-nslices", type = int, 243 metavar = "<samples>", 244 action = "store", dest = "cut_every_nslices", default = None, 245 help="how many slices should be groupped together at each cut") 246 self.add_argument("--cut-until-nslices", type = int, 247 metavar = "<slices>", 248 action = "store", dest = "cut_until_nslices", default = None, 249 help="how many extra slices should be added at the end of each slice") 170 250 171 251 # some utilities … … 177 257 return "%f\t" % (1000. * n_frames / float(samplerate)) 178 258 179 def samples2samples(n_frames, samplerate):259 def samples2samples(n_frames, _samplerate): 180 260 return "%d\t" % n_frames 181 261 … … 200 280 optstr = ' '.join(['running', name, 'with options', repr(self.options), '\n']) 201 281 sys.stderr.write(optstr) 202 def flush(self, n_frames, samplerate):282 def flush(self, frames_read, samplerate): 203 283 # optionally called at the end of process 204 284 pass … … 239 319 def __call__(self, block): 240 320 return self.onset(block) 241 def repr_res(self, res, frames_read, samplerate):321 def repr_res(self, res, _frames_read, samplerate): 242 322 if res[0] != 0: 243 323 outstr = self.time2string(self.onset.get_last(), samplerate) … … 270 350 def __call__(self, block): 271 351 return self.tempo(block) 272 def repr_res(self, res, frames_read, samplerate):352 def repr_res(self, res, _frames_read, samplerate): 273 353 if res[0] != 0: 274 354 outstr = self.time2string(self.tempo.get_last(), samplerate) … … 279 359 super(process_tempo, self).__init__(args) 280 360 self.beat_locations = [] 281 def repr_res(self, res, frames_read, samplerate):361 def repr_res(self, res, _frames_read, samplerate): 282 362 if res[0] != 0: 283 363 self.beat_locations.append(self.tempo.get_last_s()) … … 363 443 sys.stdout.write(fmt_out + '\n') 364 444 445 class process_quiet(default_process): 446 def __init__(self, args): 447 self.args = args 448 valid_opts = ['hop_size', 'silence'] 449 self.parse_options(args, valid_opts) 450 self.wassilence = 1 451 452 if args.silence is not None: 453 self.silence = args.silence 454 super(process_quiet, self).__init__(args) 455 456 def __call__(self, block): 457 if aubio.silence_detection(block, self.silence) == 1: 458 if self.wassilence != 1: 459 self.wassilence = 1 460 return 2 # newly found silence 461 return 1 # silence again 462 else: 463 if self.wassilence != 0: 464 self.wassilence = 0 465 return -1 # newly found noise 466 return 0 # noise again 467 468 def repr_res(self, res, frames_read, samplerate): 469 fmt_out = None 470 if res == -1: 471 fmt_out = "NOISY: " 472 if res == 2: 473 fmt_out = "QUIET: " 474 if fmt_out is not None: 475 fmt_out += self.time2string(frames_read, samplerate) 476 sys.stdout.write(fmt_out + '\n') 477 478 class process_cut(process_onset): 479 def __init__(self, args): 480 super(process_cut, self).__init__(args) 481 self.slices = [] 482 self.options = args 483 484 def __call__(self, block): 485 ret = super(process_cut, self).__call__(block) 486 if ret: self.slices.append(self.onset.get_last()) 487 return ret 488 489 def flush(self, frames_read, samplerate): 490 from aubio.cut import _cut_slice 491 _cut_slice(self.options, self.slices) 492 duration = float (frames_read) / float(samplerate) 493 base_info = '%(source_file)s' % {'source_file': self.options.source_uri} 494 base_info += ' (total %(duration).2fs at %(samplerate)dHz)\n' % \ 495 {'duration': duration, 'samplerate': samplerate} 496 info = "created %d slices from " % len(self.slices) 497 info += base_info 498 sys.stderr.write(info) 499 365 500 def main(): 366 501 parser = aubio_parser() … … 371 506 elif 'verbose' in args and args.verbose > 3: 372 507 sys.stderr.write('aubio version ' + aubio.version + '\n') 373 if 'command' not in args or args.command is None :508 if 'command' not in args or args.command is None or args.command in ['help']: 374 509 # no command given, print help and return 1 375 510 parser.print_help() 376 sys.exit(1) 511 if args.command and args.command in ['help']: 512 sys.exit(0) 513 else: 514 sys.exit(1) 377 515 elif not args.source_uri and not args.source_uri2: 378 516 sys.stderr.write("Error: a source is required\n") -
python/lib/aubio/cut.py
r3e48568 r2a4ce6d 6 6 7 7 import sys 8 import argparse 8 from aubio.cmd import AubioArgumentParser 9 9 10 def parse_args(): 11 usage = "usage: %s [options] -i soundfile" % sys.argv[0] 12 usage += "\n help: %s -h" % sys.argv[0] 13 parser = argparse.ArgumentParser() 14 parser.add_argument("source_file", default=None, nargs='?', 15 help="input sound file to analyse", metavar = "<source_file>") 16 parser.add_argument("-i", "--input", action = "store", dest = "source_file2", 17 help="input sound file to analyse", metavar = "<source_file>") 10 def aubio_cut_parser(): 11 parser = AubioArgumentParser() 12 parser.add_input() 18 13 parser.add_argument("-O","--onset-method", 19 14 action="store", dest="onset_method", default='default', … … 24 19 parser.add_argument("-b","--beat", 25 20 action="store_true", dest="beat", default=False, 26 help=" usebeat locations")21 help="slice at beat locations") 27 22 """ 28 23 parser.add_argument("-S","--silencecut", … … 35 30 """ 36 31 # algorithm parameters 37 parser.add_argument("-r", "--samplerate", 38 metavar = "<freq>", type=int, 39 action="store", dest="samplerate", default=0, 40 help="samplerate at which the file should be represented") 41 parser.add_argument("-B","--bufsize", 42 action="store", dest="bufsize", default=512, 43 metavar = "<size>", type=int, 44 help="buffer size [default=512]") 45 parser.add_argument("-H","--hopsize", 46 metavar = "<size>", type=int, 47 action="store", dest="hopsize", default=256, 48 help="overlap size [default=256]") 49 parser.add_argument("-t","--onset-threshold", 50 metavar = "<value>", type=float, 32 parser.add_buf_hop_size() 33 parser.add_argument("-t","--threshold", "--onset-threshold", 34 metavar = "<threshold>", type=float, 51 35 action="store", dest="threshold", default=0.3, 52 36 help="onset peak picking threshold [default=0.3]") 53 37 parser.add_argument("-c","--cut", 54 38 action="store_true", dest="cut", default=False, 55 help="cut input sound file at detected labels \ 56 best used with option -L") 57 58 # minioi 59 parser.add_argument("-M","--minioi", 60 metavar = "<value>", type=str, 61 action="store", dest="minioi", default="12ms", 62 help="minimum inter onset interval [default=12ms]") 39 help="cut input sound file at detected labels") 40 parser.add_minioi() 63 41 64 42 """ … … 82 60 action="store", dest="zerothres", default=0.008, 83 61 help="zero-crossing threshold for slicing [default=0.00008]") 84 """85 62 # plotting functions 86 """87 63 parser.add_argument("-p","--plot", 88 64 action="store_true", dest="plot", default=False, … … 110 86 help="add spectrogram to the plot") 111 87 """ 112 parser.add_argument("-o","--output", type = str, 113 metavar = "<outputdir>", 114 action="store", dest="output_directory", default=None, 115 help="specify path where slices of the original file should be created") 116 parser.add_argument("--cut-until-nsamples", type = int, 117 metavar = "<samples>", 118 action = "store", dest = "cut_until_nsamples", default = None, 119 help="how many extra samples should be added at the end of each slice") 120 parser.add_argument("--cut-every-nslices", type = int, 121 metavar = "<samples>", 122 action = "store", dest = "cut_every_nslices", default = None, 123 help="how many slices should be groupped together at each cut") 124 parser.add_argument("--cut-until-nslices", type = int, 125 metavar = "<slices>", 126 action = "store", dest = "cut_until_nslices", default = None, 127 help="how many extra slices should be added at the end of each slice") 88 parser.add_slicer_options() 89 parser.add_verbose_help() 90 return parser 128 91 129 parser.add_argument("-v","--verbose",130 action="store_true", dest="verbose", default=True,131 help="make lots of noise [default]")132 parser.add_argument("-q","--quiet",133 action="store_false", dest="verbose", default=True,134 help="be quiet")135 args = parser.parse_args()136 if not args.source_file and not args.source_file2:137 sys.stderr.write("Error: no file name given\n")138 parser.print_help()139 sys.exit(1)140 elif args.source_file2 is not None:141 args.source_file = args.source_file2142 return args143 92 144 def main(): 145 options = parse_args() 93 def _cut_analyze(options): 94 hopsize = options.hop_size 95 bufsize = options.buf_size 96 samplerate = options.samplerate 97 source_uri = options.source_uri 146 98 147 source_file = options.source_file 148 hopsize = options.hopsize 149 bufsize = options.bufsize 150 samplerate = options.samplerate 151 source_file = options.source_file 152 99 # analyze pass 153 100 from aubio import onset, tempo, source 154 101 155 s = source(source_file, samplerate, hopsize) 156 if samplerate == 0: samplerate = s.get_samplerate() 102 s = source(source_uri, samplerate, hopsize) 103 if samplerate == 0: 104 samplerate = s.get_samplerate() 105 options.samplerate = samplerate 157 106 158 107 if options.beat: … … 171 120 timestamps = [] 172 121 total_frames = 0 173 # analyze pass174 122 while True: 175 123 samples, read = s() … … 180 128 if read < hopsize: break 181 129 del s 182 # print some info 130 return timestamps, total_frames 131 132 def _cut_slice(options, timestamps): 133 # cutting pass 183 134 nstamps = len(timestamps) 184 duration = float (total_frames) / float(samplerate) 185 info = 'found %(nstamps)d timestamps in %(source_file)s' % locals() 186 info += ' (total %(duration).2fs at %(samplerate)dHz)\n' % locals() 187 sys.stderr.write(info) 188 189 # cutting pass 190 if options.cut and nstamps > 0: 135 if nstamps > 0: 191 136 # generate output files 192 137 from aubio.slicing import slice_source_at_stamps … … 203 148 timestamps_end = [t for t in timestamps[1 + options.cut_until_nslices:]] 204 149 timestamps_end += [ 1e120 ] * (options.cut_until_nslices + 1) 205 slice_source_at_stamps(source_file, timestamps, timestamps_end = timestamps_end, 150 slice_source_at_stamps(options.source_uri, 151 timestamps, timestamps_end = timestamps_end, 206 152 output_dir = options.output_directory, 207 samplerate = samplerate)153 samplerate = options.samplerate) 208 154 209 # print some info 210 duration = float (total_frames) / float(samplerate) 211 info = 'created %(nstamps)d slices from %(source_file)s' % locals() 212 info += ' (total %(duration).2fs at %(samplerate)dHz)\n' % locals() 155 def main(): 156 parser = aubio_cut_parser() 157 options = parser.parse_args() 158 if not options.source_uri and not options.source_uri2: 159 sys.stderr.write("Error: no file name given\n") 160 parser.print_help() 161 sys.exit(1) 162 elif options.source_uri2 is not None: 163 options.source_uri = options.source_uri2 164 165 # analysis 166 timestamps, total_frames = _cut_analyze(options) 167 168 # print some info 169 duration = float (total_frames) / float(options.samplerate) 170 base_info = '%(source_uri)s' % {'source_uri': options.source_uri} 171 base_info += ' (total %(duration).2fs at %(samplerate)dHz)\n' % \ 172 {'duration': duration, 'samplerate': options.samplerate} 173 174 info = "found %d timestamps in " % len(timestamps) 175 info += base_info 176 sys.stderr.write(info) 177 178 if options.cut: 179 _cut_slice(options, timestamps) 180 info = "created %d slices from " % len(timestamps) 181 info += base_info 213 182 sys.stderr.write(info) -
python/tests/test_filterbank.py
r3e48568 r2a4ce6d 1 1 #! /usr/bin/env python 2 2 3 from unittest import main4 from numpy.testing import TestCase5 from numpy.testing import assert_equal, assert_almost_equal6 3 import numpy as np 4 from numpy.testing import TestCase, assert_equal, assert_almost_equal 5 7 6 from aubio import cvec, filterbank, float_type 8 7 from .utils import array_from_text_file … … 63 62 assert_almost_equal ( expected, f.get_coeffs() ) 64 63 64 def test_mfcc_coeffs_get_coeffs(self): 65 f = filterbank(40, 512) 66 coeffs = f.get_coeffs() 67 self.assertIsInstance(coeffs, np.ndarray) 68 assert_equal (coeffs, 0) 69 assert_equal (np.shape(coeffs), (40, 512 / 2 + 1)) 70 65 71 class aubio_filterbank_wrong_values(TestCase): 66 72 … … 82 88 83 89 if __name__ == '__main__': 84 main() 90 import nose2 91 nose2.main() -
python/tests/test_filterbank_mel.py
r3e48568 r2a4ce6d 1 1 #! /usr/bin/env python 2 2 3 from unittest import main 4 from numpy.testing import TestCase 5 from numpy.testing import assert_equal, assert_almost_equal 6 from numpy import array, shape 3 import numpy as np 4 from numpy.testing import TestCase, assert_equal, assert_almost_equal 5 7 6 from aubio import cvec, filterbank, float_type 7 8 import warnings 9 warnings.filterwarnings('ignore', category=UserWarning, append=True) 8 10 9 11 class aubio_filterbank_mel_test_case(TestCase): … … 13 15 f.set_mel_coeffs_slaney(16000) 14 16 a = f.get_coeffs() 15 assert_equal( shape (a), (40, 512/2 + 1) )17 assert_equal(np.shape (a), (40, 512/2 + 1) ) 16 18 17 19 def test_other_slaney(self): 18 20 f = filterbank(40, 512*2) 19 21 f.set_mel_coeffs_slaney(44100) 20 _ = f.get_coeffs()22 self.assertIsInstance(f.get_coeffs(), np.ndarray) 21 23 #print "sum is", sum(sum(a)) 22 24 for win_s in [256, 512, 1024, 2048, 4096]: 23 25 f = filterbank(40, win_s) 24 26 f.set_mel_coeffs_slaney(32000) 25 _ = f.get_coeffs()26 27 #print "sum is", sum(sum(a)) 28 self.assertIsInstance(f.get_coeffs(), np.ndarray) 27 29 28 30 def test_triangle_freqs_zeros(self): 29 31 f = filterbank(9, 1024) 30 32 freq_list = [40, 80, 200, 400, 800, 1600, 3200, 6400, 12800, 15000, 24000] 31 freqs = array(freq_list, dtype = float_type)33 freqs = np.array(freq_list, dtype = float_type) 32 34 f.set_triangle_bands(freqs, 48000) 33 _ = f.get_coeffs().T34 35 assert_equal ( f(cvec(1024)), 0) 36 self.assertIsInstance(f.get_coeffs(), np.ndarray) 35 37 36 38 def test_triangle_freqs_ones(self): 37 39 f = filterbank(9, 1024) 38 40 freq_list = [40, 80, 200, 400, 800, 1600, 3200, 6400, 12800, 15000, 24000] 39 freqs = array(freq_list, dtype = float_type)41 freqs = np.array(freq_list, dtype = float_type) 40 42 f.set_triangle_bands(freqs, 48000) 41 _ = f.get_coeffs().T43 self.assertIsInstance(f.get_coeffs(), np.ndarray) 42 44 spec = cvec(1024) 43 45 spec.norm[:] = 1 … … 47 49 48 50 if __name__ == '__main__': 49 main() 51 import nose2 52 nose2.main() -
scripts/build_emscripten
r3e48568 r2a4ce6d 1 #! /bin/ sh1 #! /bin/bash 2 2 3 3 function checkprog() { … … 10 10 11 11 # clean 12 emmake./waf distclean12 ./waf distclean 13 13 14 14 # configure 15 emconfigure ./waf configure -- prefix=$EMSCRIPTEN/system/local/ --with-target-platform emscripten15 emconfigure ./waf configure --with-target-platform emscripten $* 16 16 17 17 # build 18 emmake ./waf --testcmd="node %s" 19 20 # intall 21 #emmake ./waf install 18 emmake ./waf build -
scripts/get_waf.sh
r3e48568 r2a4ce6d 1 #! /bin/ sh1 #! /bin/bash 2 2 3 3 set -e 4 4 set -x 5 5 6 WAFURL=https://waf.io/waf-1.9.12 6 WAFVERSION=2.0.1 7 WAFTARBALL=waf-$WAFVERSION.tar.bz2 8 WAFURL=https://waf.io/$WAFTARBALL 7 9 8 ( which wget > /dev/null && wget -qO waf $WAFURL ) || ( which curl > /dev/null && curl $WAFURL > waf ) 10 WAFBUILDDIR=`mktemp -d` 9 11 10 chmod +x waf 12 function cleanup () { 13 rm -rf $WAFBUILDDIR 14 } 15 16 trap cleanup SIGINT SIGTERM 17 18 function buildwaf () { 19 pushd $WAFBUILDDIR 20 21 ( which wget > /dev/null && wget -qO $WAFTARBALL $WAFURL ) || ( which curl > /dev/null && curl $WAFURL > $WAFTARBALL ) 22 23 tar xf $WAFTARBALL 24 pushd waf-$WAFVERSION 25 NOCLIMB=1 python waf-light --tools=c_emscripten,syms $* 26 27 popd 28 popd 29 30 cp -prv $WAFBUILDDIR/waf-$WAFVERSION/waf $PWD 31 32 chmod +x waf 33 } 34 35 buildwaf 36 37 cleanup -
src/io/source_avcodec.c
r3e48568 r2a4ce6d 314 314 //av_opt_set_int(avr, "out_sample_fmt", AV_SAMPLE_FMT_FLTP, 0); 315 315 #ifdef HAVE_AVRESAMPLE 316 if ( ( err = avresample_open(avr) ) < 0) {317 #elif defined(HAVE_SWRESAMPLE) 318 if ( ( err = swr_init(avr) ) < 0) {316 if ( ( err = avresample_open(avr) ) < 0) 317 #elif defined(HAVE_SWRESAMPLE) 318 if ( ( err = swr_init(avr) ) < 0) 319 319 #endif /* HAVE_AVRESAMPLE || HAVE_SWRESAMPLE */ 320 { 320 321 char errorstr[256]; 321 322 av_strerror (err, errorstr, sizeof(errorstr)); 322 AUBIO_ERR("source_avcodec: Could not open AVAudioResampleContext for %s (%s)\n",323 AUBIO_ERR("source_avcodec: Could not open resampling context for %s (%s)\n", 323 324 s->path, errorstr); 324 //goto beach;325 325 return; 326 326 } -
src/mathutils.c
r3e48568 r2a4ce6d 29 29 typedef enum 30 30 { 31 aubio_win_ones, 31 32 aubio_win_rectangle, 32 33 aubio_win_hamming, … … 64 65 AUBIO_ERR ("window type can not be null.\n"); 65 66 return 1; 66 } else if (strcmp (window_type, "rectangle") == 0) 67 } else if (strcmp (window_type, "ones") == 0) 68 wintype = aubio_win_ones; 69 else if (strcmp (window_type, "rectangle") == 0) 67 70 wintype = aubio_win_rectangle; 68 71 else if (strcmp (window_type, "hamming") == 0) … … 89 92 } 90 93 switch(wintype) { 94 case aubio_win_ones: 95 fvec_ones(win); 96 break; 91 97 case aubio_win_rectangle: 92 for (i=0;i<size;i++) 93 w[i] = 0.5; 98 fvec_set_all(win, .5); 94 99 break; 95 100 case aubio_win_hamming: -
src/spectral/mfcc.c
r3e48568 r2a4ce6d 37 37 uint_t win_s; /** grain length */ 38 38 uint_t samplerate; /** sample rate (needed?) */ 39 uint_t n_filters; /** number of *filters */39 uint_t n_filters; /** number of filters */ 40 40 uint_t n_coefs; /** number of coefficients (<= n_filters/2 +1) */ 41 41 aubio_filterbank_t *fb; /** filter bank */ -
src/spectral/phasevoc.c
r3e48568 r2a4ce6d 142 142 AUBIO_FREE (pv); 143 143 return NULL; 144 } 145 146 uint_t aubio_pvoc_set_window(aubio_pvoc_t *pv, const char_t *window) { 147 return fvec_set_window(pv->w, (char_t*)window); 144 148 } 145 149 -
src/spectral/phasevoc.h
r3e48568 r2a4ce6d 96 96 uint_t aubio_pvoc_get_hop(aubio_pvoc_t* pv); 97 97 98 /** set window type 99 100 \param pv phase vocoder to set the window type 101 \param window_type a string representing a window 102 103 \return 0 if successful, non-zero otherwise 104 105 */ 106 uint_t aubio_pvoc_set_window(aubio_pvoc_t *pv, const char_t *window_type); 107 98 108 #ifdef __cplusplus 99 109 } -
tests/src/io/test-sink-multi.c
r3e48568 r2a4ce6d 1 #define AUBIO_UNSTABLE 12 1 #include <aubio.h> 3 2 #include "utils_tests.h" 4 3 5 // this file uses the unstable aubio api, please use aubio_sink instead6 // see src/io/sink.h and tests/src/sink/test-sink.c4 // same as test-sink.c, but uses aubio_source_do_multi to read multiple 5 // channels 7 6 8 7 int main (int argc, char **argv) -
tests/src/io/test-sink_apple_audio-multi.c
r3e48568 r2a4ce6d 3 3 #include "utils_tests.h" 4 4 5 // this file uses the unstable aubio api , please use aubio_sink instead6 // see src/io/sink.h and tests/src/sink/test-sink.c5 // this file uses the unstable aubio api to test aubio_sink_apple_audio, please 6 // use aubio_sink instead see src/io/sink.h and tests/src/sink/test-sink.c 7 7 8 8 int main (int argc, char **argv) -
tests/src/io/test-sink_sndfile-multi.c
r3e48568 r2a4ce6d 3 3 #include "utils_tests.h" 4 4 5 // this file uses the unstable aubio api , please use aubio_sink instead6 // see src/io/sink.h and tests/src/sink/test-sink.c5 // this file uses the unstable aubio api to test aubio_sink_sndfile, please 6 // use aubio_sink instead see src/io/sink.h and tests/src/sink/test-sink.c 7 7 8 8 int main (int argc, char **argv) -
tests/src/io/test-sink_wavwrite-multi.c
r3e48568 r2a4ce6d 3 3 #include "utils_tests.h" 4 4 5 // this file uses the unstable aubio api , please use aubio_sink instead6 // see src/io/sink.h and tests/src/sink/test-sink.c5 // this file uses the unstable aubio api to test aubio_sink_wavwrite, please 6 // use aubio_sink instead see src/io/sink.h and tests/src/sink/test-sink.c 7 7 8 8 int main (int argc, char **argv) -
wscript
r3e48568 r2a4ce6d 103 103 104 104 def configure(ctx): 105 from waflib import Options106 ctx.load('compiler_c')107 ctx.load('waf_unit_test')108 ctx.load('gnu_dirs')109 110 105 target_platform = sys.platform 111 106 if ctx.options.target_platform: 112 107 target_platform = ctx.options.target_platform 113 108 109 from waflib import Options 114 110 115 111 if target_platform=='emscripten': 116 # need to force spaces between flag -o and path 117 # inspired from : 118 # https://github.com/waf-project/waf/blob/master/waflib/extras/c_emscripten.py (#1885) 119 # (OSX /emscripten 1.37.9) 120 ctx.env.CC_TGT_F = ['-c', '-o', ''] 121 ctx.env.CCLNK_TGT_F = ['-o', ''] 112 ctx.load('c_emscripten') 113 else: 114 ctx.load('compiler_c') 115 116 ctx.load('waf_unit_test') 117 ctx.load('gnu_dirs') 118 122 119 # check for common headers 123 120 ctx.check(header_name='stdlib.h') … … 152 149 else: 153 150 # enable debug symbols 154 ctx.env.CFLAGS += ['/Z7', '/FS'] 151 ctx.env.CFLAGS += ['/Z7'] 152 # /FS flag available in msvc >= 12 (2013) 153 if 'MSVC_VERSION' in ctx.env and ctx.env.MSVC_VERSION >= 12: 154 ctx.env.CFLAGS += ['/FS'] 155 155 ctx.env.LINKFLAGS += ['/DEBUG', '/INCREMENTAL:NO'] 156 156 # configure warnings … … 227 227 228 228 if target_platform == 'emscripten': 229 import os.path230 ctx.env.CFLAGS += [ '-I' + os.path.join(os.environ['EMSCRIPTEN'], 'system', 'include') ]231 232 229 if ctx.options.build_type == "debug": 233 230 ctx.env.cshlib_PATTERN = '%s.js' … … 250 247 from python.lib.gen_external import get_c_declarations, get_cpp_objects_from_c_declarations, get_all_func_names_from_lib, generate_lib_from_c_declarations 251 248 c_decls = get_c_declarations(usedouble=False) # emscripten can't use double 252 objects = get_cpp_objects_from_c_declarations(c_decls)249 objects = list(get_cpp_objects_from_c_declarations(c_decls)) 253 250 # ensure that aubio structs are exported 254 251 objects += ['fvec_t', 'cvec_t', 'fmat_t'] … … 447 444 # add sub directories 448 445 if bld.env['DEST_OS'] not in ['ios', 'iosimulator', 'android']: 446 if bld.env['DEST_OS']=='emscripten' and not bld.options.testcmd: 447 bld.options.testcmd = 'node %s' 449 448 bld.recurse('examples') 450 449 bld.recurse('tests')
Note: See TracChangeset
for help on using the changeset viewer.