--- /dev/null
+# appveyor configuration. See http://www.appveyor.com/docs/appveyor-yml
+# and http://www.appveyor.com/docs/installed-software#python
+
+environment:
+
+ matrix:
+
+ # pre-installed python version, see:
+ # http://www.appveyor.com/docs/installed-software#python
+ - PYTHON: "C:\\Python27"
+ PYTHON_VERSION: "2.7.x"
+ PYTHON_ARCH: "32"
+
+ - PYTHON: "C:\\Python27-x64"
+ PYTHON_VERSION: "2.7.x"
+ PYTHON_ARCH: "64"
+
+ - PYTHON: "C:\\Python34"
+ PYTHON_VERSION: "3.4.x"
+ PYTHON_ARCH: "32"
+
+ - PYTHON: "C:\\Python34-x64"
+ PYTHON_VERSION: "3.4.x"
+ PYTHON_ARCH: "64"
+
+ - PYTHON: "C:\\Python35"
+ PYTHON_VERSION: "3.5.x"
+ PYTHON_ARCH: "32"
+
+ - PYTHON: "C:\\Python35-x64"
+ PYTHON_VERSION: "3.5.x"
+ PYTHON_ARCH: "64"
+ # add path required to run preprocessor step
+ PATH_EXTRAS: "c:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\bin"
+
+install:
+
+ - ECHO "Installed SDKs:"
+ - ps: "ls \"C:/Program Files/Microsoft SDKs/Windows\""
+
+ # Check that we have the expected version and architecture for Python
+ - "%PYTHON%\\python.exe --version"
+ - "%PYTHON%\\python.exe -c \"import struct; print(struct.calcsize('P') * 8)\""
+
+ # We need wheel installed to build wheels
+ - "%PYTHON%\\python.exe -m pip install wheel"
+
+ - "SET PATH=%PATH_EXTRAS%;%PYTHON%;%PYTHON%\\Scripts;%PATH%"
+
+ - "pip install --disable-pip-version-check --user --upgrade pip"
+ - "pip install --upgrade setuptools"
+
+before_build:
+ - curl -fsS -o waf https://waf.io/waf-1.8.22
+ - curl -fsS -o waf.bat https://raw.githubusercontent.com/waf-project/waf/master/utils/waf.bat
+
+build_script:
+ # build python module without using libaubio
+ - "pip install -r requirements.txt"
+ - "python setup.py build"
+ - "pip install ."
+ - "python python\\demos\\demo_create_test_sounds.py"
+ - "nose2 --verbose"
+ # clean up
+ - waf distclean
+ # build libaubio
+ - waf configure build --verbose
+ # build python module using libaubio dll
+ - "python setup.py build"
# doxygen
doc/web/
doc/full/
+doc/_build/
python/gen
python/dist
aubio-*.tar.bz2
aubio-*.zip
+
+# test sounds
+python/tests/sounds
+aubio.egg-info
--- /dev/null
+strictness: medium
+test-warnings: true
+python-targets:
+ - 2
+ - 3
-language: c
+language: python
-sudo: false
+matrix:
+ include:
+ - python: 3.5
+ os: linux
+ compiler: gcc
+ - python: 3.4
+ os: linux
+ compiler: gcc
+ - python: 2.7
+ os: linux
+ compiler: gcc
+ - language: C
+ os: osx
+ osx_image: xcode8
+ compiler: clang
+ - python: 3.5
+ os: linux
+ compiler: gcc
+ env: CFLAGS="-Os" WAFOPTS="--disable-samplerate --disable-sndfile"
+ - python: 3.4
+ os: linux
+ compiler: gcc
+ env: HAVE_AUBIO_DOUBLE=1 CFLAGS="-O3" WAFOPTS="--enable-fftw3"
+ - python: 2.7
+ os: linux
+ compiler: gcc
+ env: CFLAGS="`dpkg-buildflags --get CFLAGS`" LDFLAGS="`dpkg-buildflags --get LDFLAGS`"
+ - language: C
+ os: osx
+ osx_image: xcode8
+ compiler: clang
+ env: CFLAGS="-Os" HAVE_AUBIO_DOUBLE=1 WAFOPTS="--disable-accelerate"
+ - language: C
+ os: osx
+ osx_image: xcode8
+ compiler: clang
+ env: WAFOPTS="--enable-fat --disable-avcodec --disable-sndfile"
+ - language: C
+ os: osx
+ osx_image: xcode8
+ compiler: clang
+ env: WAFOPTS="--with-target-platform=ios --disable-avcodec --disable-sndfile" AUBIO_NOTESTS=1
+ - language: C
+ os: osx
+ osx_image: xcode8
+ compiler: clang
+ env: WAFOPTS="--with-target-platform=iosimulator --disable-avcodec --disable-sndfile" AUBIO_NOTESTS=1
+ - language: C
+ os: osx
+ osx_image: xcode8.2
+ compiler: clang
+ env: WAFOPTS="--enable-fat --disable-avcodec --disable-sndfile"
+ - language: C
+ os: osx
+ osx_image: xcode8.2
+ compiler: clang
+ env: WAFOPTS="--with-target-platform=ios --disable-avcodec --disable-sndfile" AUBIO_NOTESTS=1
+ - language: C
+ os: osx
+ osx_image: xcode8.2
+ compiler: clang
+ env: WAFOPTS="--with-target-platform=iosimulator --disable-avcodec --disable-sndfile" AUBIO_NOTESTS=1
-compiler:
- - gcc
- - clang
-
-env:
- - ARCH=i386
- - ARCH=x86_64
+# use trusty
+dist: trusty
+sudo: required
addons:
apt:
packages:
- bzip2
+ - libavcodec-dev
+ - libavformat-dev
+ - libavresample-dev
+ - libavutil-dev
- libsndfile1-dev
- libsamplerate-dev
- libjack-dev
- libasound2-dev
- libfftw3-dev
- - python-dev
- - python-numpy
+ - sox
+
+before_install:
+ - |
+ if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
+ brew update
+ brew install sox
+ brew install ffmpeg
+ brew install libsndfile
+ export PATH="$HOME/Library/Python/2.7/bin/:$PATH"
+ fi;
+
+install:
+ - travis_retry pip install --upgrade pip
+ - travis_retry make getwaf expandwaf deps_python
+ - which pip
+ - pip --version
script:
- - make build
- - make build_python
- - make clean_python
- - make clean
- - make distcheck
+ - make create_test_sounds
+ - |
+ if [[ -z "$AUBIO_NOTESTS" ]]; then
+ make test_lib_python_clean
+ make test_python_only_clean
+ else
+ make test_lib_only_clean
+ fi;
+
+notifications:
+ irc:
+ channels:
+ - "irc.freenode.org#aubio"
+ use_notice: true
+ webhooks:
+ urls:
+ - https://webhooks.gitter.im/e/81e7733a5b1d977854b4
+ on_success: change # options: [always|never|change] default: always
+ on_failure: always # options: [always|never|change] default: always
+ on_start: never # options: [always|never|change] default: always
+2017-01-08 Paul Brossier <piem@aubio.org>
+
+ [ Overview ]
+
+ * VERSION: bump to 0.4.4
+ * src/utils/log.h: new function to redirect log, error, and warnings
+ * python/: AUBIO_ERR raises python exception, AUBIO_WRN to emit py warning
+ * doc/: add some documentation, fix errors in manpages
+ * wscript: new rules to build 'manpages', 'doxygen', and 'sphinx', new
+ --build-type=<release|debug> option (thanks to Eduard Mueller)
+ * src/notes/notes.h: add minioi and silence methods
+ * examples/: add --minioi (minimum inter-onset interval) option
+ * src/pitch/pitchyin.c: improve msvc compiler optimisations (thanks to
+ Eduard Mueller)
+ * python/, src/: improve error messages, fix minor memory leaks
+ * src/io/source_avcodec.c: improve compatibility with latest ffmpeg and with
+ older libav/ffmpeg versions
+ * python/demos/: new demos to capture microphone in real time
+
+ [ Interface]
+
+ * src/aubio.h: include utils/log.h
+ * src/utils/log.h: add new aubio_log_set_function to redirect log messages
+ * src/notes/notes.h: add aubio_notes_{get,set}_minioi_ms, add
+ _{get,set}_silence methods
+
+ [ Library ]
+
+ * src/aubio_priv.h: add AUBIO_INF to print to stdout with header, use new
+ logging function, add ATAN alias, add stdarg.h, move #include "config.h"
+ * src/{fmat,fvec}.c: avoid integer division
+ * src/pitch/pitchyin.c: [msvc] help compiler to optimize aubio_pitchyin_do
+ by giving it addresses for all arrays which are referenced in inner loops,
+ thanks to Eduard Mueller.
+ * src/pitch/pitch.c: declare internal functions as static, fail on wrong
+ method, warn on wrong unit, improve error messages, fix error string
+ * src/spectral/specdesc.c: return NULL if wrong mode asked, remove trailing
+ spaces
+ * src/onset/onset.c: return null and clean-up if new_aubio_specdesc failed,
+ fix error message
+ * src/notes/notes.c: use midi note to store pitch candidate, round to
+ nearest note, add a variable to define precision, fix out-of-bound write,
+ fix unset silence_threshold, fix error message
+ * src/spectral/ooura_fft8g.c: add cast to avoid conversion warnings, prefix
+ public function with aubio_ooura_ to avoid with other apps using ooura (e.g.
+ puredata), make internal functions static,
+ * src/spectral/fft.c: add message about fftw3 being able to do non-power of
+ two sizes, make calls to fftw_destroy_plan thread-safe, use prefixed
+ aubio_ooura_rdft
+ * src/spectral/phasevoc.c: fix error string
+ * src/temporal/resampler.c: throw an error when using libsamplerate with doubles
+ * src/io/ioutils.h: add functions to check samplerate and channels, use in sink_*.c
+ * src/io/source.c: add error message when aubio was compiled with no source,
+ only show error message from last child source_
+ * src/io/source_avcodec.c: call avformat_free_context after
+ avformat_close_input, keep a reference to packet to remove it when closing
+ file, avoid deprecation warnings with ffmpeg 3.2, add backward compatibility
+ for libavcodec55, fix for old libavcodec54, use AV_SAMPLE_FMT_DBL when
+ compiling with HAVE_AUBIO_DOUBLE, fix missing samples in eof block, avoid
+ function calls before declarations, improve error messages, replace with new
+ context before closing old one, make sure s->path is set to null
+ * src/io/{source_wavread,sink_wavwrite}.c: declare internal functions as static
+ * src/io/source_wavread.c: fix bytes_read for JUNK headers, improve error
+ messages, initialize buffer, skip chunks until data is found, or abort, skip
+ junk chunk
+ * src/io/source_sndfile.c: add support for multi-channel resampling, set
+ handle to null after sucessful close, add missing floor in ratio comparison,
+ improve formatting
+ * src/io/sink.c: only show error message from last child sink_
+ * src/io/sink_apple_audio.c: avoid crash on empty file name
+ * src/io/sink_sndfile.c: improve error message
+ * src/io/sink_{sndfile,wavwrite}.c: use AUBIO_MAX_CHANNELS, fix error message
+
+ [ Documentation ]
+
+ * README.md: update copyright dates, use https
+ * src/aubio.h: add some links to examples, use https
+ * src/pitch/pitch.h: add aubio_pitch_get_tolerance, add basic description of
+ unit modes
+ * src/notes/notes.h: add doxygen header
+ * src/spectral/fft.h: strip example path
+ * doc/*.rst: improve sphinx documentation
+ * doc/android.rst: add reference to it scripts/build_android
+ * doc/debian_packages.rst: added page on debian packages
+ * doc/python_module.rst: add demo_source_simple.py, add note on pip, add
+ `print(aubio.version)`
+ * doc/cli.rst: include command line manpages
+ * doc/cli_features.rst: add matrix of command line features
+ * doc/requirements.rst: add a note about --notests (closes #77), document
+ --msvc options, improve description of options
+ * doc/download.rst: added page on download
+ * doc/installing.rst: update
+ * doc/xcode_frameworks.rst: added page on xcode frameworks
+ * doc/**: use https://aubio.org
+ * doc/conf.py: use pyramid theme, update copyright, remove hardcoded path
+ * doc/web.cfg: exclude ioutils from doc
+ * doc/aubionotes.txt: document -M option (see #18),
+ * doc/aubioonset.txt: add documentation for -M, --minioi, improve threshold
+ description (thanks to Peter Parker), fix typo (onset, not pitch)
+ * doc/aubio*.txt: document -T/--timeformat option
+
+ [ Build ]
+
+ * Makefile: add a brief intro, avoid offline operations, add html and dist
+ targets, add rules for documentation, simplify listing, avoid offline
+ operations, bump waf to 1.9.6, check for waf before clean, chmod go-w
+ waflib, improve clean, use pip to install, factorise pip options, generate
+ more test sounds, improve test_python and test_pure_python, pass build_ext
+ in test_pure_python{,_wheel}, quieten uninstall_python if already
+ uninstalled, improve test targets, use bdist_wheel in test_pure_python,
+ build_ext only for --enable-double, verbose waf rules, add cleanwaf
+ * wscript: added debug/release build type configurations release (default)
+ enables optimizations, debug symbols are enabled in both configurations,
+ thanks to Eduard Mueller.
+ * wscript: add options to disable source_wavread/sink_wavwrite, add check
+ for stdarg.h, new rules 'manpages', 'sphinx', and 'doxygen' to build
+ documentation, add version to sphinx and manpages, disable libsamplerate
+ if double precision enabled (libsamplerate only supports float), fix typos,
+ remove trailing spaces, improve tarball creation (./waf dist), remove
+ full.cfg from tarball, prepend to CFLAGS to honor user cflags
+ * wscript, src/wscript_build: improve install locations using DATAROOTDIR,
+ MANDIR, INCLUDEDIR
+ * wscript: default to no atlas for now
+ * src/wscript_build: always build static library
+ * scripts/build_android: add an example script to build aubio on android,
+
+ [ Tools ]
+
+ * examples/aubionotes.c: use new notes, set minioi, send last note off when
+ needed, add warning for missing options
+ * examples/aubioonset.c: add minioi option, in seconds
+ * examples/: only send a last note off when using jack
+ * examples/: return 1 if object creation failed
+ * examples/: use PROG_HAS_OUTPUT, add PROG_HAS_SILENCE
+
+ [ Tests ]
+
+ * tests/src/spectral/test-fft.c: fix default size
+ * tests/src/spectral/test-phasevoc.c: fix typos
+ * tests/src/utils/test-log.c: add AUBIO_INF, add example for
+ aubio_log_set_function, improve messages
+
+ [ Python ]
+
+ * python/ext/aubiomodule.c: add aubio._aubio.__version__ and import it as
+ aubio.version, use custom logging function for errors and warnings, remove
+ duplicated add_generated_objects, use <> for non local aubio
+ * python/ext/py-cvec.c: use NPY_INTP_FMT
+ * python/ext/py-fft.c: use error string set in src/spectral/fft.c
+ * python/ext/py-phasevoc.c: use error string set in src/spectral/phasevoc.c
+ * python/ext/py-sink.c: always set samplerate and channels in init
+ * python/ext/py-source.c: use error string set in src/io/source.c
+ * python/lib/aubio/midiconv.py: add unicode double sharp and double flat,
+ improve unicode handling, skip UnicodeEncodeError on python 2.x
+
+ [ Python build ]
+
+ * MANIFEST.in: add src/**.c, exclude full.cfg, include waflib, remove
+ python/ext/config.h
+ * setup.py: define AUBIO_VERSION use sorted glob.glob to improve
+ reproducibility, remove extra quotes, remove status from version string,
+ update description, use custom build_ext instead of 'generate' command,
+ define HAVE_AUBIO_DOUBLE to 1 if needed
+ * python/lib/gen_code.py: add support for multiple _do outputs, fix number
+ of output, improve del_ function, safer DECREF, fix indentation, emit RuntimeError
+ * python/lib/gen_external.py: clean-up, enable tss, remove duplicate,
+ sort generated files
+ * python/lib/moresetuptools.py: add HAVE_STDARG_H, also check for
+ HAVE_AUBIO_DOUBLE, cleaner clean, look first for system library, then for
+ local build, then local sources, mo nore fake config.h here, use
+ samplerate in single precision only
+ * python/README.md: add a note about nose2 for python tests (closes #74)
+ * scripts/setenv_local.sh: python3 compat
+
+ [ Python demos ]
+
+ * python/demos/demo_alsa.py: add example using alsaaudio (closes #72)
+ * python/demos/demo_mfcc.py: add options to plot first and second
+ derivatives, and set samplerate/win_s/hop_s, thanks to @jhoelzl (closes #68)
+ * python/demos/demo_notes.py: add simple notes demos
+ * python/demos/demo_pyaudio.py: added simple demo for pyaudio, see #6,
+ closes #78, thanks to @jhoelzl and @notalentgeek, add some comments, avoid
+ overwriting aubio.pitch
+ * python/demos/demo_source_simple.py: fix indentation, make executable
+ * python/demos/demo_timestretch{,_online}.py: fix usage string, remove
+ unused import, use // to yield an integer (closes #71)
+ * python/demos/demo_timestretch_online.py: use 512, fix block counter
+ * python/demos/demo_tss.py: improve default parameters, exit before plotting
+
+ [ Python tests ]
+
+ * python/tests/: use local import, add __init__.py
+ * python/tests/test_cvec.py: simplify
+ * python/tests/test_fft.py: skip test fft(zeros).phas == 0 if needed, expected powerpc
+ * python/tests/test_fvec.py: reduce alpha norm precision to 10.-4
+ * python/tests/test_{midi2note,note2midi}.py: use nose2.params, add unicode tests
+ * python/tests/test_notes.py: add basic tests
+ * python/tests/test_notes.py: test results are correct for 44100Hz_44100f_sine441.wav
+ * python/tests/test_sink.py: add more tests, quiet warnings
+ * python/tests/test_source.py: break long line, check the tail of the file
+ is non-zero on non silent test files, filter user warnings to avoid spamming
+ the console, only check if last frames are non silent on brownnoise (weak),
+ remove fragile brownnoise test, check duration on short files, use nose2
+ params to process one sound file per test
+ * python/tests/test_specdesc.py: RuntimeError is now raised on wrong mode
+ * python/tests/utils.py: by default, use 5 seconds brownoise
+
+ [ Only in git ]
+
+ * .travis.yml: add debian dpkg-buildflags config, switch from precise to
+ trusty, sudo required, add ffmpeg on osx, add targets ios, iosimulator,
+ and osx noopt configs, bump to xcode8, add xcode8.2 config, mimick
+ build_apple_frameworks options, alway upgrade pip, add pip --version and
+ which pip after upgrading, remove --user, use expandwaf in install, remove
+ unused ARCH, shuffle order, remove duplicate, add missing opening quote,
+ use AUBIO_NOTESTS to build only lib on ios, add gitter webhook
+ * .appveyor.yml: fix path for windows+python 3.5, fix typo in path, make
+ nose2 tests verbose
+
+2016-08-16 Paul Brossier <piem@aubio.org>
+
+ [ Interface ]
+
+ * src/io/source.h, src/io/source_*.h: add _get_duration
+ * src/notes/notes.h: add basic notes object
+ * src/tempo/beattracking.{c,h}: add _get_period and _get_period_s
+ * src/mathutils.h: add fvec_ishift
+ * src/fvec.{c,h}: add fvec_weighted_copy
+ * src/tempo/tempo.{c,h}: add _get_period and _get_period_s, also add tatum,
+ a subdivision of the beat period, default to 4, implement get/set_delay
+ * src/**.{c,h}: use #ifdef HAVE_FOO, not #if _HAVE_FOO, add const qualifiers
+ to unmodified pointers (see #35)
+
+ [ Library ]
+
+ * src/{fmat,fvec,mathutils}.c: optimisations (using atlas or Accelerate when
+ available) for fvec_sum, fvec_mean, fvec_shift, aubio_level_lin,
+ fvec_set_all, fvec_zeros, fvec_weight, fvec_copy, fvec_weighted_copy,
+ fmat_vecmul
+ * src/aubio_priv.h: check for atlas cblas, use cblas_xswap, vDSP_dotpr,
+ protect SQR parameters, avoid redefining MIN/MAX, define PATH_MAX and PI
+ when needed, use _isnan on windows msvc 9 to avoid linking error, more
+ windows hacks
+ * src/mathutils.c: avoid for loop initial declarations [gcc], use
+ HAVE_ATLAS, use smpl_t for constants
+ * src/fmat.c: skip asserts
+ * src/spectral/{filterbank,mfcc}.c: use accelerated fmat_vecmul
+ * src/spectral/fft.c: fftw can be used odd length sizes, not Ooura,
+ factorise double / single flags, use memcpy
+ * src/spectral/phasevoc.c: fix arguments checks, return NULL when fft
+ creation failed , apply windowing for resynthesized grain, use ishift for
+ odd windows, fix scaling factors for correct reconstruction at 50 and 75%
+ overlap
+ * src/pitch/pitch.c: allow for silence == 0, improve error messages
+ * src/pitch/pitchmcomb.c: fix candidates sorting function, really comparing
+ current to next
+ * src/notes/notes.c: equivalent to previous examples/aubionotes.c results
+ * src/onset/onset.c: simplify selection of first onset, fix for "conversion
+ from 'smpl_t' to 'uint_t', possible loss of data" with msvc
+ * src/pitch/pitchmcomb.c: scan across all spectrum
+ * src/pitch/pitchyinfft.c: use fvec_weighted_copy
+ * src/{spectral/*.c,onset/*.c,tempo/*.c}: make sure win_size > 1
+ * src/io/*.c: use custom defines for {source,sink}_apple_audio, take a copy
+ of const char* path
+ * src/io/source_avcodec.c:
+ - update to libav10, libavcodec 55.34.1
+ - avoid deprecation warning, detect if we use ffmpeg or libav version
+ - check if the uri is a network stream using av_url_split, call
+ avformat_network_init() if needed
+ - check if we still need max_analyze_duration2 (closes #53, thanks to
+ @anthonylauzon)
+ * src/io/source_{avcodec,sndfile}.c: avoid modifying input param
+ * src/io/{sink,source,utils}_apple_audio.c: fix memory leak calling
+ CFRelease (closes #26, closes #27, and closes #28)
+ * src/io/sink_apple_audio.c: disable async mode for now, factorise code
+ * src/io/source_apple_audio.c: check out of bounds _seek, set s->path, quiet
+ * src/io/source_sndfile.c: fix crash, zero-pad output vector when
+ upsampling, use sf_read_double when compiling with AUBIO_DOUBLE, approximate
+ duration when resampling
+ * src/io/sink_sndfile.c: fix for double precision
+ * src/synth/sampler.c: fix typo, keeps a copy of uri
+ * src/tempo/tempo.c: do not write novelty function in output[1]
+ * src/temporal/resampler.c: make msvc happier adding a dummy variable
+ * src/temporal/filter.c: check parameters, fix filter_do_outplace to really
+ avoid modifying input
+ * src/utils/windll.c: add dll main entry point
+
+ [ Python ]
+
+ * General:
+ - new build system, new code generator
+ - Python 3 compatibility (#33), thanks to Nils Philippsen (@nphilipp)
+ - double precision compatibility
+ - simplify memory allocations, removed unneeded malloc/free calls
+ - fix memory leak (#49), check input sizes (#63) and output sizes (#60)
+ - improve indentation, clean up unused imports and variables
+ - fix comparison to None and to False
+ * setup.py: move from python/setup.py, add option to build libaubio inside
+ python-aubio (for instance with pip), add command 'generate' with option
+ '--enable-double', build with -Wdeclaration-after-statement -Werror
+ * python/ext/aubiomodule.c: fix PyMethodDef sentinel
+ * python/ext/aubioproxy.c: factorize input checks into
+ PyAubio_IsValidVector, fix windows c89 compilation, use npy_intp, not long
+ * python/ext: rewrite and simplify, safer and improved memory usage (#49),
+ improve error strings, verify actual object creation
+ * python/ext/py-source.c: added duration, check seek is not negative
+ * python/ext/py-musicutils.c: do not overwrite PyArg_ParseTuple messages
+ * python/lib/gen_code.py: new generator, switch to using custom PyObjects
+ instead of fvec, cvec, fmat, ready for double precision (defaults to single)
+ * python/lib/aubio__init__.py: use new aubio.float_type, make sure length is
+ not zero and float_type is imported
+ * python/lib/aubio/midiconv.py: fix instance checks, make sure midi2note
+ uses midi int (#33)
+ * python/lib/aubio/slicing.py: fix samplerate
+ * python/ext/aubio-types.h: add new_py_ functions to create PyObjects
+ instead of fvec_t, apply to generated and hard-coded objects
+ * python/lib/gen_external.py: improve compiler detection, fixes build on
+ windows (#55)
+ * python/lib/moresetuptools.py: helpers for windows and macos compilations
+
+ [ Python demos ]
+
+ * python/demos/demo_reading_speed.py: new reading speed tests, external
+ packages disabled by default
+ * python/demos/demo_timestretch.py: new timescale algorithm
+ * python/demos/demo_timestretch_online.py: new timescale algorithm (online
+ version)
+ * python/demos/demo_create_test_sounds.py: add script to create simple sound
+ files to test on using sox
+ * python/demos/demo_a_weighting.py: add simple demo for a_weighting
+ * python/demos/demo_filter.py: moved from _a_weighting
+ * python/demos/demo_mfcc.py: use n_coeffs
+ * python/demos/demo_bpm_extract.py: add exception type, avoid {} as default
+ argument value
+ * python/demos/demo_pysoundcard_*: update to pysoundcard 0.5.2 (closes #42)
+ * python/scripts/aubiocut: fix usage string output
+
+ [ Python tests ]
+
+ * python/tests/run_all_tests,*.py: switch to nose2, fix most prospect warnings
+ * python/tests/test_fvec.py: add test_pass_to_numpy, cope with accumulated
+ errors
+ * python/tests/test_cvec.py: simplify, add more tests
+ * python/tests/test_fft.py: more tests, fft.do to clash on wrong size
+ inputs, f.rdo input size, cvec is large enough, memory tests, avoid
+ VisibleDeprecationWarning
+ * python/tests/test_filterbank.py: check for wrong values, ValueError raised
+ * python/tests/test_filter.py: add tests
+ * python/tests/test_musicutils.py: simplify, check TypeError is raised
+ * python/tests/test_mfcc.py: more tests, check for wrong input size (see #63)
+ * python/tests/test_mathutils: fix test_miditobin test, can also raise
+ NotImplementedError (darwin)
+ * python/tests/test_note2midi.py: more tests, use unicode_literals
+ * python/tests/test_phasevoc.py: add a note about ocasional crash check
+ perfect reconstruction for overlap > 75% add 50% overlap test, fix duplicate
+ test name, add wrong sized input tests
+ * python/tests/test_sink.py: remove useless many_sinks_not_closed and cruft
+ * python/tests/test_source.py: simplify, quieten, skip tests if no test sounds
+ * python/tests/test_specdesc.py: check for wrong values, skip wrong name
+ test, use correct input size (see #63)
+ * python/tests/utils.py: try reopening the file is deleting it fails on windows
+ * python/VERSION: removed, use same VERSION file for libaubio and python-aubio
+ * MANIFEST.in: move from python/, update contents
+ * nose2.cfg: add minimal config, set multiprocess always-on=false (fixes
+ coverage, pass -N to speed up the tests)
+
+ [ Tools ]
+
+ * examples/*.c: add time format option
+ * examples/{aubioonset,aubiotrack}.c: also emit midi note, thanks to
+ @topas-rec (closes #62)
+ * examples/: use outmsg to print notes (fixes #8)
+ * examples/aubionotes.c: use new aubio_notes object
+ * examples/aubiotrack.c: enable -O and -t options, fix is_beat/is_silence
+ types
+ * examples/{parse_args,utils}.h: check in config.h if getopt.h was found, or
+ build without for msvc, more windows hacks
+ * examples/utils.c: change send_noteon to accept floating point midi note number
+
+ [ Tests ]
+
+ * tests/src/io/test-source_apple_audio.c: shorten long line
+ * tests/src/io/test-source_avcodec.c: use HAVE_LIBAV, closes #10
+ * tests/src/temporal: avoid crash, clarify
+ * tests/src/tempo/test-tempo.c: tempo back to only one output
+ * tests/src/test-delnull.c: improve test, avoid segfaults
+ * tests/src/test-lvec.c: use AUBIO_LSMP_FMT
+ * tests/utils_tests.h: add VA_ARGS versions of variadic macros
+ * tests/utils_tests.h: also use custom srandom/random when compiling with
+ -std=c99
+ * tests/utils_tests.h: make sure M_PI and RAND_MAX are defined
+
+ [ Build ]
+
+ * Makefile: set waf to 1.8.22 for now, new targets create_test_sounds,
+ build_python, test_python, clean_python, build_python3, clean_python3,
+ test_pure_python, test_pure_python_wheel, (use test_pure_* targets to build
+ without libaubio), use 'HAVE_DOUBLE=1 make' to build in double precision
+ * scripts/build_apple_frameworks: add script to build macosx and ios
+ frameworks (see #34, #43)
+ * scripts/build_emscripten: add script to build with emcc and co
+ * scripts/build_mingw: add script to cross-compile using mingw
+ * scripts/get_waf.sh: added simple script to fetch latest waf
+ * scripts/setenv_local.sh: set environment to run from built source tree
+ * scripts/setenv_local.sh: update to new python-aubio build location
+ * tests/wscript_build: do not install test programs
+ * tests/wscript_build, src/wscript_build: use 'use =', simplify
+ * src/wscript_build: enable shared lib on ios, static lib on windows
+ * wscript:
+ - update --enable-foo to fail if foo is not found
+ - add -mmacosx-version-min=10.4 on darwin
+ - add '-fembed-bitcode' on ios (closes #31), min to 6.1
+ - make fat build, add option to not build with Accelerate framework
+ - add option to not build with CoreAudio/AudioToolbox
+ - add --disable-docs option
+ - add -lm detection
+ - pass HAVE_AUBIO_DOUBLE in compiler arguments
+ - first check for headers, make getopt.h and unistd.h optional
+ - check HAVE_AV* from ctx.env
+ - make msvc compiler quieter, add /MD and /D_CRT_SECURE_NO_WARNINGS
+ - check if we find atlas/cblas.h
+ - new build platform emscripten
+ - more cleanups and updates
+
+ [ Only in git ]
+
+ * .travis.yml: config for https://travis-ci.org/aubio/aubio
+ * .appveyor.yml: config for https://ci.appveyor.com/project/piem/aubio
+ * .landscape.yml: config for https://landscape.io/github/aubio/aubio
+ * conda recipes: see https://github.com/conda/conda-recipes#387
+ * .gitignore: add python/tests/sounds and .egg-info
+
+ [ General ]
+
+ * src/: remove trailing spaces, improve doxygen strings, update copyrights,
+ fix typos
+ * src/onset/onset.h: fix description of get/set_delay functions
+ * src/spectral/mfcc.h: add link to reference implementation
+ * src/spectral/filterbank_mel.h: update reference url
+ * src/musicutils.h: update link to Bernardini's paper, improve doc
+ * doc/aubiomfcc.txt: add a note about the output
+ * doc/*.cfg: update to Doxygen 1.8.8
+ * python/README.md: fix typo (thanks to Sam Alexander), document how to
+ build in a virtualenv (see #2)
+ * README.md: minor updates, link to python/README.md, switch to https
+ * VERSION: bump to 0.4.3
+
2015-08-01 Paul Brossier <piem@aubio.org>
[ Interface ]
--- /dev/null
+include AUTHORS COPYING README.md VERSION ChangeLog
+include python/README.md
+include Makefile wscript */wscript_build
+include waf waflib/* waflib/*/*
+exclude waflib/__pycache__/*
+include aubio.pc.in
+include nose2.cfg
+include requirements.txt
+include src/*.c src/*.h
+include src/*/*.c src/*/*.h
+include examples/*.c examples/*.h
+include tests/*.h tests/*/*.c tests/*/*/*.c
+include python/ext/*.h
+include python/__init__.py
+include python/lib/__init__.py
+include python/lib/moresetuptools.py
+include python/lib/gen_external.py
+include python/lib/gen_code.py
+include python/tests/run_all_tests
+include python/tests/*.py
+include python/tests/eval_pitch
+include python/demos/*.py
+include python/tests/*.expected
+include doc/*.txt doc/*.rst doc/*.cfg doc/Makefile doc/make.bat doc/conf.py
+exclude doc/full.cfg
+include scripts/* scripts/apple/Info.plist scripts/apple/Modules/module.modulemap
+exclude python/gen/*
+#!/usr/bin/make -f
+# -*- makefile -*-
+#
+# This makefile contains simple rules to prepare, compile, test, and install
+# aubio. Try one of the following rules:
+#
+# $ make configure
+# $ make build
+# $ make install
+# $ make test_python
+
+WAFCMD=python waf
+WAFURL=https://waf.io/waf-1.9.6
+
+#WAFOPTS:=
+# turn on verbose mode
+WAFOPTS += --verbose
+# build wafopts
+WAFOPTS += --destdir $(DESTDIR)
+# multiple jobs
+WAFOPTS += --jobs 4
+# if HAVE_AUBIO_DOUBLE is defined, pass --enable-double to waf
+# python/lib/moresetuptools.py also checks for HAVE_AUBIO_DOUBLE
+WAFOPTS += $(shell [ -z $(HAVE_AUBIO_DOUBLE) ] || echo --enable-double )
+
+PIPOPTS += --verbose
+
+DESTDIR:=$(PWD)/build/dist
+PYDESTDIR:=$(PWD)/build/pydist
+
+# default install locations
+PREFIX?=/usr/local
+EXEC_PREFIX?=$(PREFIX)
+LIBDIR?=$(PREFIX)/lib
+INCLUDEDIR?=$(PREFIX)/include
+DATAROOTDIR?=$(PREFIX)/share
+MANDIR?=$(DATAROOTDIR)/man
+
+SOX=sox
+
+TESTSOUNDS := python/tests/sounds
+
all: build
checkwaf:
@[ -f waf ] || make getwaf
getwaf:
- curl https://waf.io/waf-1.8.14 > waf
- @[ -d wafilb ] || rm -fr waflib
- @chmod +x waf && ./waf --help > /dev/null
- @mv .waf*/waflib . && rm -fr .waf*
- @sed '/^#==>$$/,$$d' waf > waf2 && mv waf2 waf
- @chmod +x waf
+ ./scripts/get_waf.sh
+
+expandwaf: getwaf
+ [ -d wafilb ] || rm -fr waflib
+ $(WAFCMD) --help > /dev/null
+ mv .waf*/waflib . && rm -fr .waf*
+ sed '/^#==>$$/,$$d' waf > waf2 && mv waf2 waf
+ chmod +x waf && chmod -R go-w waflib
+
+cleanwaf:
+ rm -rf waf waflib .waf*
+
+configure: checkwaf
+ $(WAFCMD) configure $(WAFOPTS)
+
+build: configure
+ $(WAFCMD) build $(WAFOPTS)
-build: checkwaf
- ./waf configure
- ./waf build
+install:
+ # install
+ $(WAFCMD) install $(WAFOPTS)
+
+list_installed:
+ find $(DESTDIR) -ls | sed 's|$(DESTDIR)|/«destdir»|'
+
+list_installed_python:
+ pip show -f aubio
+
+list_all_installed: list_installed list_installed_python
+
+uninstall:
+ # uninstall
+ $(WAFCMD) uninstall $(WAFOPTS)
+
+delete_install:
+ rm -rf $(PWD)/dist/test
build_python:
- cd python && ./setup.py build
+ # build python-aubio, using locally built libaubio if found
+ python ./setup.py build
+
+build_python_extlib:
+ # build python-aubio using (locally) installed libaubio
+ [ -f $(DESTDIR)/$(INCLUDEDIR)/aubio/aubio.h ]
+ [ -d $(DESTDIR)/$(LIBDIR) ]
+ [ -f $(DESTDIR)/$(LIBDIR)/pkgconfig/aubio.pc ]
+ PKG_CONFIG_PATH=$(DESTDIR)/$(LIBDIR)/pkgconfig \
+ CFLAGS="-I$(DESTDIR)/$(INCLUDEDIR)" \
+ LDFLAGS="-L$(DESTDIR)/$(LIBDIR)" \
+ make build_python
+
+deps_python:
+ # install or upgrade python requirements
+ pip install $(PIPOPTS) --requirement requirements.txt
+
+# use pip or distutils?
+install_python: install_python_with_pip
+uninstall_python: uninstall_python_with_pip
+#install_python: install_python_with_distutils
+#uninstall_python: uninstall_python_with_distutils
+
+install_python_with_pip:
+ # install package
+ pip install $(PIPOPTS) .
+
+uninstall_python_with_pip:
+ # uninstall package
+ ( pip show aubio | grep -l aubio > /dev/null ) && \
+ pip uninstall -y -v aubio || echo "info: aubio package is not installed"
+
+install_python_with_distutils:
+ ./setup.py install $(PIPOPTS) $(DISTUTILSOPTS)
+
+uninstall_python_with_distutils:
+ #./setup.py uninstall
+ [ -d $(PYDESTDIR)/$(LIBDIR) ] && echo Warning: did not clean $(PYDESTDIR)/$(LIBDIR) || true
+
+force_uninstall_python:
+ # ignore failure if not installed
+ -make uninstall_python
+
+local_dylib:
+ # DYLD_LIBRARY_PATH is no more on mac os
+ # create links from ~/lib/lib* to build/src/lib*
+ [ -f $(PWD)/build/src/libaubio.[0-9].dylib ] && ( mkdir -p ~/lib && cp -prv build/src/libaubio.[0-9].dylib ~/lib ) || true
+
+test_python: export LD_LIBRARY_PATH=$(DESTDIR)/$(LIBDIR)
+test_python: export PYTHONPATH=$(PYDESTDIR)/$(LIBDIR)
+test_python: local_dylib
+ # run test with installed package
+ ./python/tests/run_all_tests --verbose
+ # also run with nose, multiple processes
+ nose2 -N 4
clean_python:
- cd python && ./setup.py clean
+ ./setup.py clean
+
+check_clean_python:
+ # check cleaning a second time works
+ make clean_python
+ make clean_python
+
+clean: checkwaf
+ # optionnaly clean before build
+ -$(WAFCMD) clean
+ # remove possible left overs
+ -rm -rf doc/_build
-clean:
- ./waf clean
+check_clean:
+ # check cleaning after build works
+ $(WAFCMD) clean
+ # check cleaning a second time works
+ $(WAFCMD) clean
-distcheck: build
- ./waf distcheck
+distclean:
+ $(WAFCMD) distclean
+ -rm -rf doc/_build/
+ -rm -rf doc/web/
+
+check_distclean:
+ make distclean
+
+distcheck: checkwaf
+ $(WAFCMD) distcheck $(WAFOPTS)
help:
- ./waf --help
+ $(WAFCMD) --help
+
+create_test_sounds:
+ -[ -z `which $(SOX)` ] && ( echo $(SOX) could not be found) || true
+ -mkdir -p $(TESTSOUNDS)
+ -$(SOX) -r 44100 -b 16 -n "$(TESTSOUNDS)/44100Hz_1f_silence.wav" trim 0 1s
+ -$(SOX) -r 22050 -b 16 -n "$(TESTSOUNDS)/22050Hz_5s_brownnoise.wav" synth 5 brownnoise vol 0.9
+ -$(SOX) -r 32000 -b 16 -n "$(TESTSOUNDS)/32000Hz_127f_sine440.wav" synth 127s sine 440 vol 0.9
+ -$(SOX) -r 8000 -b 16 -n "$(TESTSOUNDS)/8000Hz_30s_silence.wav" trim 0 30
+ -$(SOX) -r 48000 -b 32 -n "$(TESTSOUNDS)/48000Hz_60s_sweep.wav" synth 60 sine 100-20000 vol 0.9
+ -$(SOX) -r 44100 -b 16 -n "$(TESTSOUNDS)/44100Hz_44100f_sine441.wav" synth 44100s sine 441 vol 0.9
+ -$(SOX) -r 44100 -b 16 -n "$(TESTSOUNDS)/44100Hz_100f_sine441.wav" synth 100s sine 441 vol 0.9
+
+# build only libaubio, no python-aubio
+test_lib_only: clean distclean configure build install list_installed
+# additionally, clean after a fresh build
+test_lib_only_clean: test_lib_only uninstall check_clean check_distclean
+
+# build libaubio, build and test python-aubio against it
+test_lib_python: force_uninstall_python deps_python \
+ clean_python clean distclean \
+ configure build build_python \
+ install install_python \
+ test_python \
+ list_all_installed
+
+test_lib_python_clean: test_lib_python \
+ uninstall_python uninstall \
+ check_clean_python \
+ check_clean \
+ check_distclean
+
+# build libaubio, install it, build python-aubio against it
+test_lib_install_python: force_uninstall_python deps_python \
+ clean_python distclean \
+ configure build \
+ install \
+ build_python_extlib \
+ install_python \
+ test_python \
+ list_all_installed
+
+test_lib_install_python_clean: test_lib_install_python \
+ uninstall_python \
+ delete_install \
+ check_clean_python \
+ check_distclean
+
+# build a python-aubio that includes libaubio
+test_python_only: force_uninstall_python deps_python \
+ clean_python clean distclean \
+ build_python \
+ install_python \
+ test_python \
+ list_installed_python
+
+test_python_only_clean: test_python_only \
+ uninstall_python \
+ check_clean_python
+
+sphinx: configure
+ $(WAFCMD) sphinx $(WAFOPTS)
+
+doxygen: configure
+ $(WAFCMD) doxygen $(WAFOPTS)
+
+manpages: configure
+ $(WAFCMD) manpages $(WAFOPTS)
+
+html: doxygen sphinx
+
+docs: html manpages
+
+dist: distclean expandwaf
+ $(WAFCMD) dist
-------------
A python module to access the library functions is also provided. Please see
-the file `python/README` for more information on how to use it.
+the file [`python/README.md`](python/README.md) for more information on how to
+use it.
Examples tools
--------------
https://aubio.org/documentation
-Installation and Build Instructions
------------------------------------
+Build Instructions
+------------------
A number of distributions already include aubio. Check your favorite package
management system, or have a look at the [download
./waf configure
./waf build
- sudo ./waf install
If waf is not found in the directory, you can download and install it with:
make getwaf
-aubio compiles on Linux, Mac OS X, Cygwin, and iOS.
+aubio compiles on Linux, Mac OS X, Windows, Cygwin, and iOS.
+
+Installation
+------------
+
+To install aubio library and headers on your system, use:
+
+ sudo ./waf install
+
+To uninstall:
+
+ sudo ./waf uninstall
+
+If you don't have root access to install libaubio on your system, you can use
+libaubio without installing libaubio either by setting `LD_LIBRARY_PATH`, or by
+copying it to `~/lib`.
+
+On Linux, you should be able to set `LD_LIBRARY_PATH` with:
+
+ $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/build/src
+
+On Mac OS X, a copy or a symlink can be made in `~/lib`:
+
+ $ mkdir -p ~/lib
+ $ ln -sf $PWD/build/src/libaubio*.dylib ~/lib/
+
+Note on Mac OS X systems older than El Capitan (10.11), the `DYLD_LIBRARY_PATH`
+variable can be set as follows:
+
+ $ export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:$PWD/build/src
Credits and Publications
------------------------
mailing list: <aubio-user@aubio.org>.
To subscribe to the list, use the mailman form:
-http://lists.aubio.org/listinfo/aubio-user/
+https://lists.aubio.org/listinfo/aubio-user/
Alternatively, feel free to contact directly the author.
Copyright and License Information
---------------------------------
-Copyright (C) 2003-2013 Paul Brossier <piem@aubio.org>
+Copyright (C) 2003-2016 Paul Brossier <piem@aubio.org>
aubio is free software: you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
AUBIO_MAJOR_VERSION=0
AUBIO_MINOR_VERSION=4
-AUBIO_PATCH_VERSION=3
+AUBIO_PATCH_VERSION=5
AUBIO_VERSION_STATUS='~alpha'
-LIBAUBIO_LT_CUR=4
-LIBAUBIO_LT_REV=2
-LIBAUBIO_LT_AGE=2
+LIBAUBIO_LT_CUR=5
+LIBAUBIO_LT_REV=1
+LIBAUBIO_LT_AGE=5
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
clean:
+ -rm -rf _static
-rm -rf $(BUILDDIR)/*
html:
+ mkdir -p _static
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
--- /dev/null
+.. _android:
+
+Building aubio for Android
+--------------------------
+
+To compile aubio for android, you will need to get the `Android Native
+Development Toolkit (NDK) <https://developer.android.com/ndk/>`_, prepare a
+standalone toolchain, and tell waf to use the NDK toolchain. An example script
+to complete these tasks is available in ``scripts/build_android``.
-b, --beat Use beat locations instead of onset locations.
-t, --onset-threshold thres Set the threshold value for the onset peak
- picking. Typical values are typically within 0.001 and 0.900. Defaults to
- 0.1. Lower threshold values imply more onsets detected. Try 0.5 in case of
- over-detections. Defaults to 0.3.
+ picking. Values are typically in the range [0.001, 0.900]. Lower threshold
+ values imply more onsets detected. Increasing this threshold should reduce
+ the number of incorrect detections. Defaults to 0.3.
-c, --cut Cut input sound file at detected labels. A new sound files for
each slice will be created in the current directory.
aubiomfcc source
aubiomfcc [[-i] source]
[-r rate] [-B win] [-H hop]
+ [-T time-format]
[-v] [-h]
DESCRIPTION
-H, --hopsize hop The number of samples between two consecutive analysis.
Defaults to 256.
+ -T, --timeformat format Set time format (samples, ms, seconds). Defaults to
+ seconds.
+
-h, --help Print a short help message and exit.
-v, --verbose Be verbose.
[-r rate] [-B win] [-H hop]
[-O method] [-t thres]
[-p method] [-u unit] [-l thres]
+ [-T time-format]
[-s sil]
[-j] [-v] [-h]
0.1. Lower threshold values imply more onsets detected. Try 0.5 in case of
over-detections. Defaults to 0.3.
+ -M, --minioi value Set the minimum inter-onset interval, in seconds, the
+ shortest interval between two consecutive notes. Defaults to 0.030
+
-p, --pitch method The pitch detection method to use. See PITCH METHODS
below. Defaults to 'default'.
will not be detected. A value of -20.0 would eliminate most onsets but the
loudest ones. A value of -90.0 would select all onsets. Defaults to -90.0.
+ -T, --timeformat format Set time format (samples, ms, seconds). Defaults to
+ seconds.
+
-j, --jack Use Jack input/output. You will need a Jack connection
controller to feed aubio some signal and listen to its output.
aubioonset [[-i] source] [-o sink]
[-r rate] [-B win] [-H hop]
[-O method] [-t thres]
+ [-T time-format]
[-s sil] [-m] [-f]
- [-j] [-v] [-h]
+ [-j] [-N miditap-note] [-V miditap-velo]
+ [-v] [-h]
DESCRIPTION
below. Defaults to 'default'.
-t, --onset-threshold thres Set the threshold value for the onset peak
- picking. Typical values are typically within 0.001 and 0.900. Defaults to
- 0.1. Lower threshold values imply more onsets detected. Try 0.5 in case of
- over-detections. Defaults to 0.3.
+ picking. Values are typically in the range [0.001, 0.900]. Lower threshold
+ values imply more onsets detected. Increasing this threshold should reduce
+ the number of incorrect detections. Defaults to 0.3.
- -s, --silence sil Set the silence threshold, in dB, under which the pitch
+ -M, --minioi value Set the minimum inter-onset interval, in seconds, the
+ shortest interval between two consecutive onsets. Defaults to 0.020
+
+ -s, --silence sil Set the silence threshold, in dB, under which the onset
will not be detected. A value of -20.0 would eliminate most onsets but the
loudest ones. A value of -90.0 would select all onsets. Defaults to -90.0.
+ -T, --timeformat format Set time format (samples, ms, seconds). Defaults to
+ seconds.
+
-m, --mix-input Mix source signal to the output signal before writing to
sink.
-j, --jack Use Jack input/output. You will need a Jack connection
controller to feed aubio some signal and listen to its output.
+ -N, --miditap-note Override note value for MIDI tap. Defaults to 69.
+
+ -V, --miditap-velop Override velocity value for MIDI tap. Defaults to 65.
+
-h, --help Print a short help message and exit.
-v, --verbose Be verbose.
aubiopitch [[-i] source] [-o sink]
[-r rate] [-B win] [-H hop]
[-p method] [-u unit] [-l thres]
+ [-T time-format]
[-s sil] [-f]
[-v] [-h] [-j]
will not be detected. A value of -20.0 would eliminate most onsets but the
loudest ones. A value of -90.0 would select all onsets. Defaults to -90.0.
+ -T, --timeformat format Set time format (samples, ms, seconds). Defaults to
+ seconds.
+
-m, --mix-input Mix source signal to the output signal before writing to
sink.
aubioquiet source
aubioquiet [[-i] source]
[-r rate] [-B win] [-H hop]
+ [-T time-format]
[-s sil]
[-v] [-h]
-s, --silence sil Set the silence threshold, in dB, under which the pitch
will not be detected. Defaults to -90.0.
+ -T, --timeformat format Set time format (samples, ms, seconds). Defaults to
+ seconds.
+
-h, --help Print a short help message and exit.
-v, --verbose Be verbose.
aubiotrack source
aubiotrack [[-i] source] [-o sink]
[-r rate] [-B win] [-H hop]
+ [-T time-format]
[-s sil] [-m]
- [-j] [-v] [-h]
+ [-j] [-N miditap-note] [-V miditap-velo]
+ [-v] [-h]
DESCRIPTION
-j, --jack Use Jack input/output. You will need a Jack connection
controller to feed aubio some signal and listen to its output.
+ -N, --miditap-note Override note value for MIDI tap. Defaults to 69.
+
+ -V, --miditap-velop Override velocity value for MIDI tap. Defaults to 65.
+
+ -T, --timeformat format Set time format (samples, ms, seconds). Defaults to
+ seconds.
+
-h, --help Print a short help message and exit.
-v, --verbose Be verbose.
--- /dev/null
+.. highlight:: bash
+
+.. _building:
+
+Building aubio
+==============
+
+.. note::
+ To download a prebuilt version of aubio, see :ref:`download`.
+
+aubio uses `waf`_ to configure, compile, and test the source.
+A copy of waf is included in aubio tarball, so all you need is a terminal,
+a compiler, and a recent version of python installed.
+
+.. note::
+ Make sure you have all the :ref:`requirements` you want before building.
+
+Latest release
+--------------
+
+The **latest stable release** can be downloaded from https://aubio.org/download::
+
+ $ curl -O http://aubio.org/pub/aubio-0.4.3.tar.bz2
+ $ tar xf aubio-0.4.3.tar.bz2
+ $ cd aubio-0.4.3
+
+Git repository
+--------------
+
+The **latest git branch** can be obtained with::
+
+ $ git clone git://git.aubio.org/git/aubio
+ $ cd aubio
+
+The following command will fetch the correct `waf`_ version (not included in
+aubio's git)::
+
+ $ ./scripts/get_waf.sh
+
+.. note::
+
+ Windows users without `Git Bash`_ installed will want to use the following
+ commands instead:
+
+ .. code:: bash
+
+ $ curl -fsS -o waf https://waf.io/waf-1.8.22
+ $ curl -fsS -o waf.bat https://raw.githubusercontent.com/waf-project/waf/master/utils/waf.bat
+
+
+Compiling
+---------
+
+To compile the C library, examples programs, and tests, run::
+
+ $ ./waf configure
+
+Check out the available options using ``./waf configure --help``. Once
+you are done with configuration, you can start building::
+
+ $ ./waf build
+
+To install the freshly built C library and tools, simply run the following
+command::
+
+ $ sudo ./waf install
+
+.. note::
+ Windows users should simply run ``waf``, without the leading ``./``. For
+ instance:
+
+ .. code:: bash
+
+ $ waf configure build
+
+Cleaning
+--------
+
+If you wish to uninstall the files installed by the ``install`` command, use
+``uninstall``::
+
+ $ sudo ./waf uninstall
+
+To clean the source directory, use the ``clean`` command::
+
+ $ ./waf clean
+
+To also forget the options previously passed to the last ``./waf configure``
+invocation, use the ``distclean`` command::
+
+ $ ./waf distclean
+
+.. _waf: https://waf.io/
+
+.. _Git Bash: https://git-for-windows.github.io/
+
+.. toctree::
+ :maxdepth: 2
--- /dev/null
+.. _manpages:
+
+Command line tools
+==================
+
+A few simple command line tools are included along with the library.
+
+ - ``aubioonset`` outputs the time stamp of detected note onsets
+ - ``aubiopitch`` attempts to identify a fundamental frequency, or pitch, for
+ each frame of the input sound
+ - ``aubiomfcc`` computes Mel-frequency Cepstrum Coefficients
+ - ``aubiotrack`` outputs the time stamp of detected beats
+ - ``aubionotes`` emits midi-like notes, with an onset, a pitch, and a duration
+ - ``aubioquiet`` extracts quiet and loud regions
+
+Additionally, the python module comes with the following script:
+
+ - ``aubiocut`` slices sound files at onset or beat timestamps
+
+
+.. toctree::
+
+ cli_features
+
+
+``aubioonset``
+--------------
+
+.. literalinclude:: aubioonset.txt
+
+``aubiopitch``
+--------------
+
+.. literalinclude:: aubiopitch.txt
+
+``aubiomfcc``
+--------------
+
+.. literalinclude:: aubiomfcc.txt
+
+``aubiotrack``
+--------------
+
+.. literalinclude:: aubiotrack.txt
+
+``aubionotes``
+--------------
+
+.. literalinclude:: aubionotes.txt
+
+``aubioquiet``
+--------------
+
+.. literalinclude:: aubioquiet.txt
+
+``aubiocut``
+--------------
+
+.. literalinclude:: aubiocut.txt
--- /dev/null
+Command line features
+=====================
+
++--------------+-------+-------+------+-------+-------+-------+------+------------------+
+| feat vs. prg | onset | pitch | mfcc | track | notes | quiet | cut1 | short options |
++==============+=======+=======+======+=======+=======+=======+======+==================+
+| input | Y | Y | Y | Y | Y | Y | Y | -i |
++--------------+-------+-------+------+-------+-------+-------+------+------------------+
+| output | Y | Y | N | Y | Y | N | Y!1 | -o,-m,-f |
++--------------+-------+-------+------+-------+-------+-------+------+------------------+
+| Hz/buf/hop | Y | Y | Y | Y | Y | Y!2 | Y | -r,-B-,H |
++--------------+-------+-------+------+-------+-------+-------+------+------------------+
+| jack | Y | Y | N | Y | Y | N!3 | N | -j |
++--------------+-------+-------+------+-------+-------+-------+------+------------------+
+| onset | Y | N | N | Y!8 | Y!6 | N | Y | -O,-t,-M |
++--------------+-------+-------+------+-------+-------+-------+------+------------------+
+| pitch | N | Y | N | N | Y!6 | N | N!5 | -p,-u,-l |
++--------------+-------+-------+------+-------+-------+-------+------+------------------+
+| silence | Y | Y | N | Y | Y!7 | Y | N!4 | -s |
++--------------+-------+-------+------+-------+-------+-------+------+------------------+
+| timefmt | Y | Y | Y | Y | Y | Y | ! | -T |
++--------------+-------+-------+------+-------+-------+-------+------+------------------+
+| help | Y | Y | Y | Y | Y | Y | Y | -h |
++--------------+-------+-------+------+-------+-------+-------+------+------------------+
+| verbose | Y | Y | Y | Y | Y | Y | Y | -v |
++--------------+-------+-------+------+-------+-------+-------+------+------------------+
+
+1. ``aubiocut --output`` is used to specify a directory, not a file.
+
+2. Option ``--bufsize`` is useless for ``aubioquiet``
+
+3. ``aubioquiet`` could have a jack output
+
+4. Regression, re-add slicing at silences to ``aubiocut``
+
+5. ``aubiocut`` could cut on notes
+
+6. ``aubionotes`` needs onset/pitch setters.
+
+7. Silence was different for pitch and onset, test.
+
+8. Some ``aubiotrack`` options should be disabled (minioi, threshold).
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
-sys.path.insert(0, os.path.abspath('../../python/build/lib.macosx-10.6-intel-2.7'))
+#sys.path.insert(0, os.path.abspath('../../python/build/...'))
# -- General configuration -----------------------------------------------------
# General information about the project.
project = u'aubio'
-copyright = u'2014, Paul Brossier'
+copyright = u'2016, Paul Brossier'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# The short X.Y version.
version = '0.4'
# The full version, including alpha/beta/rc tags.
-release = 'latest'
+release = '0.4.5~alpha'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
-html_theme = 'default'
+#html_theme = 'agogo'
+#html_theme = 'default'
+#html_theme = 'haiku'
+html_theme = 'pyramid'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['_static']
+html_static_path = [] #['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
-#html_show_sphinx = True
+html_show_sphinx = False
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
+
+def setup(app):
+ if release.endswith('~alpha'): app.tags.add('devel')
--- /dev/null
+Debian/Ubuntu packages
+----------------------
+
+For the latest Debian packages, see https://packages.debian.org/src:aubio.
+
+For the latest Ubuntu packages, see http://packages.ubuntu.com/src:aubio.
+
+For the latest version of the packages, see
+https://anonscm.debian.org/cgit/collab-maint/aubio.git/. Use
+``git-buildpackage`` to build from the git repository. For instance:
+
+.. code-block:: bash
+
+ $ git clone git://anonscm.debian.org/collab-maint/aubio.git
+ $ cd aubio
+ $ git buildpackage
--- /dev/null
+.. _develop:
+
+Developping with aubio
+======================
+
+Read `Contribute`_ to report issues and request new features.
+
+See `Doxygen documentation`_ for the complete documentation of the C library,
+built using `Doxygen <http://www.doxygen.org/>`_.
+
+Below is a brief `Library overview`_.
+
+Library overview
+----------------
+
+Here is a brief overview of the C library. See also the `Doxygen
+documentation`_ for a more detailed list of available functions.
+
+Vectors and matrix
+``````````````````
+
+``fvec_t`` are used to hold vectors of float (``smpl_t``).
+
+.. literalinclude:: ../tests/src/test-fvec.c
+ :language: C
+ :lines: 7
+
+
+.. code-block:: C
+
+ // set some elements
+ vec->data[511] = 2.;
+ vec->data[vec->length-2] = 1.;
+
+Similarly, ``fmat_t`` are used to hold matrix of floats.
+
+.. literalinclude:: ../tests/src/test-fmat.c
+ :language: C
+ :lines: 9-19
+
+Reading a sound file
+````````````````````
+In this example, ``aubio_source`` is used to read a media file.
+
+First, create the objects we need.
+
+.. literalinclude:: ../tests/src/io/test-source.c
+ :language: C
+ :lines: 22-24, 30-32, 34
+
+.. note::
+ With ``samplerate = 0``, ``aubio_source`` will be created with the file's
+ original samplerate.
+
+Now for the processing loop:
+
+.. literalinclude:: ../tests/src/io/test-source.c
+ :language: C
+ :lines: 40-44
+
+At the end of the processing loop, clean-up and de-allocate memory:
+
+.. literalinclude:: ../tests/src/io/test-source.c
+ :language: C
+ :lines: 50-56
+
+See the complete example: :download:`test-source.c
+<../tests/src/io/test-source.c>`.
+
+Computing the spectrum
+``````````````````````
+
+Now let's create a phase vocoder:
+
+.. literalinclude:: ../tests/src/spectral/test-phasevoc.c
+ :language: C
+ :lines: 6-11
+
+The processing loop could now look like:
+
+.. literalinclude:: ../tests/src/spectral/test-phasevoc.c
+ :language: C
+ :lines: 21-35
+
+See the complete example: :download:`test-phasevoc.c
+<../tests/src/spectral/test-phasevoc.c>`.
+
+.. _doxygen-documentation:
+
+Doxygen documentation
+---------------------
+
+The latest version of the doxygen documentation is available at:
+
+ https://aubio.org/doc/latest
+
+Contribute
+----------
+
+Please report any issue and feature request at the `Github issue tracker
+<https://github.com/aubio/aubio/issues>`_. Patches and pull-requests welcome!
+
--- /dev/null
+.. _download:
+
+Downloading aubio
+=================
+
+A number of distributions already include aubio. Check your favorite package
+management system, or have a look at the `aubio download page
+<https://aubio.org/download>`_ for more options.
+
+To use aubio in a macOS or iOS application, see :ref:`xcode-frameworks-label`.
+
+To use aubio in an android project, see :ref:`android`.
+
+.. toctree::
+
+ debian_packages
+ xcode_frameworks
+ android
+
+To compile aubio from source, read :ref:`building`.
-# Doxyfile 1.8.5
+# Doxyfile 1.8.8
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
# could be handy for archiving the generated documentation or if some version
# control system is used.
-PROJECT_NUMBER = "0.4.2~alpha full"
+PROJECT_NUMBER = "0.4.5~alpha"
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
CREATE_SUBDIRS = NO
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES = NO
+
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
-# Possible values are: Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-
-# Traditional, Croatian, Czech, Danish, Dutch, English, Esperanto, Farsi,
-# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en,
-# Korean, Korean-en, Latvian, Norwegian, Macedonian, Persian, Polish,
-# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish,
-# Turkish, Ukrainian and Vietnamese.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
# The default value is: English.
OUTPUT_LANGUAGE = English
# extension. Doxygen has a built-in mapping, but you can override or extend it
# using this tag. The format is ext=language, where ext is a file extension, and
# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
-# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make
-# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
-# (default is Fortran), use: inc=Fortran f=C.
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
+# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
+# Fortran. In the later case the parser tries to guess whether the code is fixed
+# or free formatted code, this is the default for Fortran type files), VHDL. For
+# instance to make doxygen treat .inc files as Fortran files (default is PHP),
+# and .f files as C (default is Fortran), use: inc=Fortran f=C.
#
# Note For files without extension you can use no_extension as a placeholder.
#
SHOW_INCLUDE_FILES = YES
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = NO
+
# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
# files with double quotes in the documentation rather than with sharp brackets.
# The default value is: NO.
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
# descriptions of file, namespace and class members alphabetically by member
-# name. If set to NO the members will appear in declaration order.
+# name. If set to NO the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
# The default value is: NO.
SORT_BRIEF_DOCS = NO
# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
# For LaTeX the style of the bibliography can be controlled using
# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
-# search path. Do not use file names with spaces, bibtex cannot handle them. See
-# also \cite for info how to create references.
+# search path. See also \cite for info how to create references.
CITE_BIB_FILES =
VERBATIM_HEADERS = YES
+# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the
+# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
+# cost of reduced performance. This can be particularly helpful with template
+# rich C++ code for which doxygen's built-in parser lacks the necessary type
+# information.
+# Note: The availability of this option depends on whether or not doxygen was
+# compiled with the --with-libclang option.
+# The default value is: NO.
+
+CLANG_ASSISTED_PARSING = NO
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_OPTIONS =
+
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
HTML_STYLESHEET =
-# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user-
-# defined cascading style sheet that is included after the standard style sheets
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
# created by doxygen. Using this option one can overrule certain style aspects.
# This is preferred over using HTML_STYLESHEET since it does not replace the
# standard style sheet and is therefor more robust against future updates.
-# Doxygen will copy the style sheet file to the output directory. For an example
-# see the documentation.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra stylesheet files is of importance (e.g. the last
+# stylesheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_STYLESHEET =
CHM_INDEX_ENCODING =
# The BINARY_TOC flag controls whether a binary table of contents is generated (
-# YES) or a normal table of contents ( NO) in the .chm file.
+# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
# The default value is: http://cdn.mathjax.org/mathjax/latest.
# This tag requires that the tag USE_MATHJAX is set to YES.
-MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+MATHJAX_RELPATH = https://cdn.mathjax.org/mathjax/latest
# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
# extension names that should be enabled during MathJax rendering. For example
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
# implemented using a web server instead of a web client using Javascript. There
-# are two flavours of web server based searching depending on the
-# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
-# searching and an index file used by the script. When EXTERNAL_SEARCH is
-# enabled the indexing and searching needs to be provided by external tools. See
-# the section "External Indexing and Searching" for details.
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
# The default value is: NO.
# This tag requires that the tag SEARCHENGINE is set to YES.
#
# Note: Only use a user-defined header if you know what you are doing! The
# following commands have a special meaning inside the header: $title,
-# $datetime, $date, $doxygenversion, $projectname, $projectnumber. Doxygen will
-# replace them by respectively the title of the page, the current date and time,
-# only the current date, the version number of doxygen, the project name (see
-# PROJECT_NAME), or the project number (see PROJECT_NUMBER).
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empy string,
+# for the replacement values of the other commands the user is refered to
+# HTML_HEADER.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HEADER =
# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
# generated LaTeX document. The footer should contain everything after the last
-# chapter. If it is left blank doxygen will generate a standard footer.
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
#
# Note: Only use a user-defined footer if you know what you are doing!
# This tag requires that the tag GENERATE_LATEX is set to YES.
PDF_HYPERLINKS = YES
-# If the LATEX_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
# the PDF file directly from the LaTeX files. Set this option to YES to get a
# higher quality PDF documentation.
# The default value is: YES.
MAN_EXTENSION = .3
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR =
+
# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
# will generate one additional man file for each entity documented in the real
# man page(s). These additional files only source the real man page, but without
XML_OUTPUT = xml
-# The XML_SCHEMA tag can be used to specify a XML schema, which can be used by a
-# validating XML parser to check the syntax of the XML files.
-# This tag requires that the tag GENERATE_XML is set to YES.
-
-XML_SCHEMA =
-
-# The XML_DTD tag can be used to specify a XML DTD, which can be used by a
-# validating XML parser to check the syntax of the XML files.
-# This tag requires that the tag GENERATE_XML is set to YES.
-
-XML_DTD =
-
# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
# listings (including syntax highlighting and cross-referencing information) to
# the XML output. Note that enabling this will significantly increase the size
DOCBOOK_OUTPUT = docbook
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
#---------------------------------------------------------------------------
# Configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
EXPAND_AS_DEFINED =
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
-# remove all refrences to function-like macros that are alone on a line, have an
-# all uppercase name, and do not end with a semicolon. Such function macros are
-# typically used for boiler-plate code, and will confuse the parser if not
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
# removed.
# The default value is: YES.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
# where loc1 and loc2 can be relative or absolute paths or URLs. See the
# section "Linking to external documentation" for more information about the use
# of tag files.
-# Note: Each tag file must have an unique name (where the name does NOT include
+# Note: Each tag file must have a unique name (where the name does NOT include
# the path). If a tag file is not located in the directory in which doxygen is
# run, you must also specify the path to the tagfile here.
MSCGEN_PATH =
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH =
+
# If set to YES, the inheritance and collaboration graphs will hide inheritance
# and usage relations if the target is undocumented or is not a class.
# The default value is: YES.
# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
# Bell Labs. The other options in this section have no effect if this option is
# set to NO
-# The default value is: NO.
+# The default value is: YES.
HAVE_DOT = NO
DOT_NUM_THREADS = 0
-# When you want a differently looking font n the dot files that doxygen
+# When you want a differently looking font in the dot files that doxygen
# generates you can specify the font name using DOT_FONTNAME. You need to make
# sure dot is able to find the font, which can be done by putting it in a
# standard location or by setting the DOTFONTPATH environment variable or by
# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
# to make the SVG files visible in IE 9+ (other browsers do not have this
# requirement).
-# Possible values are: png, jpg, gif and svg.
+# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd,
+# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo,
+# gif:cairo:gd, gif:gd, gif:gd:gd and svg.
# The default value is: png.
# This tag requires that the tag HAVE_DOT is set to YES.
MSCFILE_DIRS =
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+PLANTUML_JAR_PATH =
+
# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
# that will be shown in the graph. If the number of nodes in a graph becomes
# larger than this value, doxygen will truncate the graph, which is visualized
-aubio documentation
-===================
+Welcome
+=======
-aubio is a collection of algorithms and tools to label music and sounds. It
-listens to audio signals and attempts to detect events. For instance, when a
-drum is hit, at which frequency is a note, or at what tempo is a rhythmic
-melody.
+aubio is a collection of algorithms and tools to label and transform music and
+sounds. It scans or `listens` to audio signals and attempts to detect musical
+events. For instance, when a drum is hit, at which frequency is a note, or at
+what tempo is a rhythmic melody.
-Its features include segmenting a sound file before each of its attacks,
+aubio features include segmenting a sound file before each of its attacks,
performing pitch detection, tapping the beat and producing midi streams from
live audio.
-aubio provide several algorithms and routines, including:
+Quick links
+===========
+
+* :ref:`python`
+* :ref:`manpages`
+* :ref:`develop`
+* :ref:`building`
+
+.. only:: devel
+
+ .. include:: statuslinks.rst
+
+Project pages
+=============
+
+* `Project homepage`_: https://aubio.org
+* `aubio on github`_: https://github.com/aubio/aubio
+* `aubio on pypi`_: https://pypi.python.org/pypi/aubio
+* `Doxygen documentation`_: https://aubio.org/doc/latest/
+* `Mailing lists`_: https://lists.aubio.org
+
+.. _Project homepage: https://aubio.org
+.. _aubio on github: https://github.com/aubio/aubio
+.. _aubio on pypi: https://pypi.python.org/pypi/aubio
+.. _Doxygen documentation: https://aubio.org/doc/latest/
+.. _Mailing lists: https://lists.aubio.org/
+
+* `Travis Continuous integration page <https://travis-ci.org/aubio/aubio>`_
+* `Appveyor Continuous integration page <https://ci.appveyor.com/project/piem/aubio>`_
+* `Landscape python code validation <https://landscape.io/github/aubio/aubio/master>`_
+* `ReadTheDocs documentation <https://aubio.readthedocs.io/en/latest/>`_
+
+Features
+========
+
+aubio provides several algorithms and routines, including:
- several onset detection methods
- different pitch detection methods
- digital filters (low pass, high pass, and more)
- spectral filtering
- transient/steady-state separation
-- sound file and audio devices read and write access
+- sound file read and write access
- various mathematics utilities for music applications
The name aubio comes from *audio* with a typo: some errors are likely to be
found in the results.
-Python module
--------------
-
-A python module to access the library functions is also provided. Please see
-the file ``python/README`` for more information on how to use it.
-
-Examples tools
---------------
-
-A few simple command line tools are included along with the library:
-
- - ``aubioonset`` outputs the time stamp of detected note onsets
- - ``aubiopitch`` attempts to identify a fundamental frequency, or pitch, for
- each frame of the input sound
- - ``aubiomfcc`` computes Mel-frequency Cepstrum Coefficients
- - ``aubiotrack`` outputs the time stamp of detected beats
- - ``aubionotes`` emits midi-like notes, with an onset, a pitch, and a duration
- - ``aubioquiet`` extracts quiet and loud regions
-
-Additionally, the python module comes with the following script:
-
- - ``aubiocut`` slices sound files at onset or beat timestamps
-
-C API basics
-------------
-
-The library is written in C and is optimised for speed and portability.
-
-The C API is designed in the following way:
-
-.. code-block:: c
-
- aubio_something_t * new_aubio_something(void * args);
- audio_something_do(aubio_something_t * t, void * args);
- smpl_t aubio_something_get_a_parameter(aubio_something_t * t);
- uint_t aubio_something_set_a_parameter(aubio_something_t * t, smpl_t a_parameter);
- void del_aubio_something(aubio_something_t * t);
-
-For performance and real-time operation, no memory allocation or freeing take
-place in the ``_do`` methods. Instead, memory allocation should always take place
-in the ``new_`` methods, whereas free operations are done in the ``del_`` methods.
-
-.. code-block:: bash
-
- ./waf configure
- ./waf build
- sudo ./waf install
-
-aubio compiles on Linux, Mac OS X, Cygwin, and iPhone.
-
-Documentation
--------------
-
-- Manual pages: http://aubio.org/documentation
-- API documentation: http://aubio.org/doc/latest/
-
-Contribute
-----------
-
-- Issue Tracker: https://github.com/piem/aubio/issues
-- Source Code: https://github.com/piem/aubio
-
-Contact info
-------------
+Copyright
+=========
-The home page of this project can be found at: http://aubio.org/
+Copyright © 2003-2016 Paul Brossier <piem@aubio.org>
-Questions, comments, suggestions, and contributions are welcome. Use the
-mailing list: <aubio-user@aubio.org>.
+License
+=======
-To subscribe to the list, use the mailman form:
-http://lists.aubio.org/listinfo/aubio-user/
+aubio is a `free <http://www.debian.org/intro/free>`_ and `open source
+<http://www.opensource.org/docs/definition.php>`_ software; **you** can
+redistribute it and/or modify it under the terms of the `GNU
+<https://www.gnu.org/>`_ `General Public License
+<https://www.gnu.org/licenses/gpl.html>`_ as published by the `Free Software
+Foundation <https://fsf.org>`_, either version 3 of the License, or (at your
+option) any later version.
-Alternatively, feel free to contact directly the author.
+.. note::
+ aubio is not MIT or BSD licensed. Contact the author if you need it in your
+ commercial product.
-Contents
---------
+Content
+=======
.. toctree::
- :maxdepth: 1
+ :maxdepth: 2
installing
python_module
+ cli
+ develop
-.. highlight:: bash
-
Installing aubio
================
-A number of distributions already include aubio. Check your favorite package
-management system, or have a look at the `download page
-<http://aubio.org/download>`_.
-
-aubio uses `waf <https://waf.io/>`_ to configure, compile, and test the source.
-A copy of ``waf`` is included along aubio, so all you need is a ``terminal``
-and a recent ``python`` installed.
-
-Source code
------------
-
-Check out the `download page <http://aubio.org/download>`_ for more options:
-http://aubio.org/download.
-
-The latest stable release can be found at http://aubio.org/pub/::
-
- $ curl -O http://aubio.org/pub/aubio-0.4.1.tar.bz2
- $ tar xf aubio-0.4.1.tar.bz2
- $ cd aubio-0.4.1
-
-The latest develop branch can be obtained with::
-
- $ git clone git://git.aubio.org/git/aubio/ aubio-devel
- $ cd aubio-devel
- $ git fetch origin develop:develop
- $ git checkout develop
-
-Compiling
----------
-
-To compile the C library, examples programs, and tests, run::
-
- $ ./waf configure
-
-Check out the available options using ``./waf configure --help | less``. Once
-you are done with configuration, you can start building::
-
- $ ./waf build
-
-To install the freshly built C library and tools, simply run the following
-command::
-
- $ sudo ./waf install
-
-Cleaning
---------
-
-If you wish to uninstall the files installed by the ``install`` command, use
-``uninstall``::
+aubio runs on Linux, Windows, macOS, iOS, Android, and probably a few others
+operating systems.
- $ sudo ./waf uninstall
+To download a pre-compiled version of the library, head to :ref:`download`.
-To clean the source directory, use the ``clean`` command::
+To install the python extension, head to :ref:`python`.
- $ ./waf clean
+To compile aubio form source, first check the :ref:`requirements`, then read
+:ref:`building`.
-To also forget the options previously passed to the last ``./waf configure``
-invocation, use the ``distclean`` command::
+.. toctree::
+ :maxdepth: 2
- $ ./waf distclean
+ download
+ building
+ requirements
-aubio Python module
-===================
+.. _python:
+
+Python module
+=============
+
+The aubio extension for Python is available for Python 2.7 and Python 3.
+
+Installing aubio with pip
+-------------------------
+
+aubio can now be installed using ``pip``:
+
+.. code-block:: bash
+
+ $ pip install aubio
Building the module
-------------------
.. code-block:: bash
- $ cd python
+ $ ./setup.py clean
$ ./setup.py build
$ sudo ./setup.py install
-Using the module
-----------------
+Using aubio in python
+---------------------
+
+Once you have python-aubio installed, you should be able to run ``python -c
+"import aubio; print(aubio.version)"``.
+
+A simple example
+................
+
+Here is a :download:`simple script <../python/demos/demo_source_simple.py>`
+that reads all the samples from a media file:
+
+.. literalinclude:: ../python/demos/demo_source_simple.py
+ :language: python
+
+Filtering an input sound file
+.............................
+
+Here is a more complete example, :download:`demo_filter.py
+<../python/demos/demo_filter.py>`. This files executes the following:
+
+* read an input media file (``aubio.source``)
+
+* filter it using an `A-weighting <https://en.wikipedia.org/wiki/A-weighting>`_
+ filter (``aubio.digital_filter``)
+
+* write result to a new file (``aubio.sink``)
+
+.. literalinclude:: ../python/demos/demo_filter.py
+ :language: python
-To use the python module, simply import aubio:
+More demos
+..........
-.. code-block:: python
+Check out the `python demos folder`_ for more examples.
- #! /usr/bin/env python
- import aubio
+Python tests
+------------
- s = aubio.source(sys.argv[1], 0, 256)
- while True:
- samples, read = s()
- print samples
- if read < 256: break
+A number of `python tests`_ are provided. To run them, use
+``python/tests/run_all_tests``.
-Check out the `python demos for aubio
-<https://github.com/piem/aubio/blob/develop/python/demos/>`_ for more examples.
+.. _python demos folder: https://github.com/aubio/aubio/blob/master/python/demos
+.. _demo_filter.py: https://github.com/aubio/aubio/blob/master/python/demos/demo_filter.py
+.. _python tests: https://github.com/aubio/aubio/blob/master/python/tests
--- /dev/null
+.. _requirements:
+
+Build options
+=============
+
+If built without any external dependencies aubio can be somewhat useful, for
+instance to read, process, and write simple wav files.
+
+To support more media input formas add more features to aubio, you can use one
+or all of the `following libraries <extlibs>`_.
+
+You may also want to know more about the `other options`_ and the `platform
+notes`_
+
+The configure script will automatically for these extra libraries. To make sure
+the library or feature is used, pass the `--enable-flag` to waf. To disable
+this feature, use `--disable-feature`.
+
+To find out more about the build commands, use the `--verbose` option.
+
+External libraries
+------------------
+
+External libraries are checked for using ``pkg-config``. Set the
+``PKG_CONFIG_PATH`` environment variable if you have them installed in an
+unusual location.
+
+
+.. note::
+
+ If ``pkg-config`` is not found in ``PATH``, the configure step will
+ succeed, but none of the external libraries will be used.
+
+libav
+.....
+
+ `libav.org <https://libav.org/>`_, open source audio and video processing
+ tools.
+
+If all of the following libraries are found, they will be used to compile
+``aubio_source_avcodec``. so that ``aubio_source`` will be able to decode audio
+from all formats supported by `libav
+<https://libav.org/documentation/general.html#Audio-Codecs>`_.
+
+* libavcodec
+* libavformat
+* libavutil
+* libavresample
+
+To enable this option, configure with ``--enable-avcodec``. The build will then
+failed if the required libraries are not found. To disable this option,
+configure with ``--disable-avcodec``
+
+
+libsndfile
+..........
+
+ `libsndfile <http://www.mega-nerd.com/libsndfile/>`_, a C library for reading
+ and writing sampled sound files.
+
+With libsndfile built in, ``aubio_source_sndfile`` will be built in and used by
+``aubio_source``.
+
+To enable this option, configure with ``--enable-sndfile``. The build will then
+fail if the required library is not found. To disable this option, configure
+with ``--disable-sndfile``
+
+libsamplerate
+.............
+
+ `libsamplerate <http://www.mega-nerd.com/SRC/>`_, a sample rate converter for
+ audio.
+
+With libsamplerate built in, ``aubio_source_sndfile`` will support resampling,
+and ``aubio_resample`` will be fully functional.
+
+To enable this option, configure with ``--enable-samplerate``. The build will
+then fail if the required library is not found. To disable this option,
+configure with ``--disable-samplerate``
+
+libfftw3
+........
+
+ `FFTW <http://fftw.org/>`_, a C subroutine for computing the discrete Fourier
+ transform
+
+With libfftw3 built in, ``aubio_fft`` will use `FFTW`_ to
+compute Fast Fourier Transform (FFT), allowing aubio to compute FFT on length
+that are not a power of 2.
+
+To enable this option, configure with ``--enable-fftw3``. The build will
+then fail if the required library is not found. To disable this option,
+configure with ``--disable-fftw3``
+
+Platform notes
+--------------
+
+On all platforms, you will need to have installed:
+
+ - a compiler (gcc, clang, msvc, ...)
+ - python (any version >= 2.7, including 3.x)
+ - a terminal to run command lines in
+
+Linux
+.....
+
+The following `External libraries`_ will be used if found: `libav`_,
+`libsamplerate`_, `libsndfile`_, `libfftw3`_.
+
+macOS
+.....
+
+The following system frameworks will be used on Mac OS X systems:
+
+ - `Accelerate <https://developer.apple.com/reference/accelerate>`_ to compute
+ FFTs and other vectorized operations optimally.
+
+ - `CoreAudio <https://developer.apple.com/reference/coreaudio>`_ and
+ `AudioToolbox <https://developer.apple.com/reference/audiotoolbox>`_ to
+ decode audio from files and network streams.
+
+.. note::
+
+ To build a fat binary for both ``i386`` and ``x86_64``, use ``./waf configure
+ --enable-fat``.
+
+The following `External libraries`_ will also be checked: `libav`_,
+`libsamplerate`_, `libsndfile`_, `libfftw3`_.
+
+To build a fat binary on a darwin like system (macOS, tvOS, appleOS, ...)
+platforms, configure with ``--enable-fat``.
+
+Windows
+.......
+
+To use a specific version of the compiler, ``--msvc_version``. To build for a
+specific architecture, use ``--msvc_target``. For instance, to build aubio
+for ``x86`` using ``msvc 12.0``, use:
+
+.. code:: bash
+
+ waf configure --msvc_version='msvc 12.0' --msvc_target='x86'
+
+
+The following `External libraries`_ will be used if found: `libav`_,
+`libsamplerate`_, `libsndfile`_, `libfftw3`_.
+
+iOS
+...
+
+The following system frameworks will be used on iOS and iOS Simulator.
+
+ - `Accelerate <https://developer.apple.com/reference/accelerate>`_ to compute
+ FFTs and other vectorized operations optimally.
+
+ - `CoreAudio <https://developer.apple.com/reference/coreaudio>`_ and
+ `AudioToolbox <https://developer.apple.com/reference/audiotoolbox>`_ to
+ decode audio from files and network streams.
+
+To build aubio for iOS, configure with ``--with-target-platform=ios``. For the
+iOS Simulator, use ``--with-target-platform=iosimulator`` instead.
+
+By default, aubio is built with the following flags on iOS:
+
+.. code:: bash
+
+ CFLAGS="-fembed-bitcode -arch arm64 -arch armv7 -arch armv7s -miphoneos-version-min=6.1"
+
+and on iOS Simulator:
+
+.. code::
+
+ CFLAGS="-arch i386 -arch x86_64 -mios-simulator-version-min=6.1"
+
+Set ``CFLAGS`` and ``LINKFLAGS`` to change these default values, or edit
+``wscript`` directly.
+
+Other options
+-------------
+
+Some additional options can be passed to the configure step. For the complete
+list of options, run:
+
+.. code:: bash
+
+ $ ./waf --help
+
+Here is an example of a custom command:
+
+.. code:: bash
+
+ $ ./waf --verbose configure build install \
+ --enable-avcodec --enable-wavread --disable-wavwrite \
+ --enable-sndfile --enable-samplerate --enable-docs \
+ --destdir $PWD/build/destdir --testcmd="echo %s" \
+ --prefix=/opt --libdir=/opt/lib/multiarch \
+ --manpagesdir=/opt/share/man \
+ uninstall clean distclean dist distcheck
+
+Double precision
+................
+
+To compile aubio in double precision mode, configure with ``--enable-double``.
+
+To compile aubio in single precision mode, use ``--disable-double`` (default).
+
+Disabling the tests
+...................
+
+In some case, for instance when cross-compiling, unit tests should not be run.
+Option ``--notests`` can be used for this purpose. The tests will not be
+executed, but the binaries will be compiled, ensuring that linking against
+libaubio works as expected.
+
+.. note::
+
+ The ``--notests`` option should be passed to both ``build`` and ``install``
+ targets, otherwise waf will try to run them.
+
+Edit wscript
+............
+
+Many of the options are gathered in the file `wscript`. a good starting point
+when looking for additional options.
+
+.. _build_docs:
+
+Building the docs
+-----------------
+
+If the following command line tools are found, the documentation will be built
+built:
+
+ - `doxygen <http://doxygen.org>`_ to build the :ref:`doxygen-documentation`.
+ - `txt2man <https://github.com/mvertes/txt2man>`_ to build the :ref:`manpages`
+ - `sphinx <http://sphinx-doc.org>`_ to build this document
+
+These tools are searched for in the current ``PATH`` environment variable.
+By default, the documentation is built only if the tools are found.
+
+To disable the documentation, configure with ``--disable-docs``. To build with
+the documentation, configure with ``--enable-docs``.
--- /dev/null
+Current status
+==============
+
+.. image:: https://travis-ci.org/aubio/aubio.svg?branch=master
+ :target: https://travis-ci.org/aubio/aubio
+ :alt: Travis build status
+
+.. image:: https://ci.appveyor.com/api/projects/status/f3lhy3a57rkgn5yi?svg=true
+ :target: https://ci.appveyor.com/project/piem/aubio/
+ :alt: Appveyor build status
+
+.. image:: https://landscape.io/github/aubio/aubio/master/landscape.svg?style=flat
+ :target: https://landscape.io/github/aubio/aubio/master
+ :alt: Landscape code health
+
+.. image:: https://readthedocs.org/projects/aubio/badge/?version=latest
+ :target: https://aubio.readthedocs.io/en/latest/?badge=latest
+ :alt: Documentation status
+
+.. image:: https://img.shields.io/github/commits-since/aubio/aubio/0.4.4.svg?maxAge=2592000
+ :target: https://github.com/aubio/aubio
+ :alt: Commits since last release
+
+
-# Doxyfile 1.8.5
+# Doxyfile 1.8.8
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
# could be handy for archiving the generated documentation or if some version
# control system is used.
-PROJECT_NUMBER = "0.4.2~alpha"
+PROJECT_NUMBER = "0.4.5~alpha"
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
CREATE_SUBDIRS = NO
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES = NO
+
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
-# Possible values are: Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-
-# Traditional, Croatian, Czech, Danish, Dutch, English, Esperanto, Farsi,
-# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en,
-# Korean, Korean-en, Latvian, Norwegian, Macedonian, Persian, Polish,
-# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish,
-# Turkish, Ukrainian and Vietnamese.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
# The default value is: English.
OUTPUT_LANGUAGE = English
# extension. Doxygen has a built-in mapping, but you can override or extend it
# using this tag. The format is ext=language, where ext is a file extension, and
# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
-# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make
-# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
-# (default is Fortran), use: inc=Fortran f=C.
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
+# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
+# Fortran. In the later case the parser tries to guess whether the code is fixed
+# or free formatted code, this is the default for Fortran type files), VHDL. For
+# instance to make doxygen treat .inc files as Fortran files (default is PHP),
+# and .f files as C (default is Fortran), use: inc=Fortran f=C.
#
# Note For files without extension you can use no_extension as a placeholder.
#
SHOW_INCLUDE_FILES = YES
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = NO
+
# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
# files with double quotes in the documentation rather than with sharp brackets.
# The default value is: NO.
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
# descriptions of file, namespace and class members alphabetically by member
-# name. If set to NO the members will appear in declaration order.
+# name. If set to NO the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
# The default value is: NO.
SORT_BRIEF_DOCS = NO
# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
# For LaTeX the style of the bibliography can be controlled using
# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
-# search path. Do not use file names with spaces, bibtex cannot handle them. See
-# also \cite for info how to create references.
+# search path. See also \cite for info how to create references.
CITE_BIB_FILES =
EXCLUDE = ../src/aubio_priv.h \
../src/mathutils.h \
+ ../src/io/ioutils.h \
../src/io/audio_unit.h \
../src/io/source_sndfile.h \
../src/io/source_apple_audio.h \
VERBATIM_HEADERS = YES
+# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the
+# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
+# cost of reduced performance. This can be particularly helpful with template
+# rich C++ code for which doxygen's built-in parser lacks the necessary type
+# information.
+# Note: The availability of this option depends on whether or not doxygen was
+# compiled with the --with-libclang option.
+# The default value is: NO.
+
+CLANG_ASSISTED_PARSING = NO
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_OPTIONS =
+
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
HTML_STYLESHEET =
-# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user-
-# defined cascading style sheet that is included after the standard style sheets
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
# created by doxygen. Using this option one can overrule certain style aspects.
# This is preferred over using HTML_STYLESHEET since it does not replace the
# standard style sheet and is therefor more robust against future updates.
-# Doxygen will copy the style sheet file to the output directory. For an example
-# see the documentation.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra stylesheet files is of importance (e.g. the last
+# stylesheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_STYLESHEET =
CHM_INDEX_ENCODING =
# The BINARY_TOC flag controls whether a binary table of contents is generated (
-# YES) or a normal table of contents ( NO) in the .chm file.
+# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
# The default value is: http://cdn.mathjax.org/mathjax/latest.
# This tag requires that the tag USE_MATHJAX is set to YES.
-MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+MATHJAX_RELPATH = https://cdn.mathjax.org/mathjax/latest
# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
# extension names that should be enabled during MathJax rendering. For example
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
# implemented using a web server instead of a web client using Javascript. There
-# are two flavours of web server based searching depending on the
-# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
-# searching and an index file used by the script. When EXTERNAL_SEARCH is
-# enabled the indexing and searching needs to be provided by external tools. See
-# the section "External Indexing and Searching" for details.
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
# The default value is: NO.
# This tag requires that the tag SEARCHENGINE is set to YES.
#
# Note: Only use a user-defined header if you know what you are doing! The
# following commands have a special meaning inside the header: $title,
-# $datetime, $date, $doxygenversion, $projectname, $projectnumber. Doxygen will
-# replace them by respectively the title of the page, the current date and time,
-# only the current date, the version number of doxygen, the project name (see
-# PROJECT_NAME), or the project number (see PROJECT_NUMBER).
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empy string,
+# for the replacement values of the other commands the user is refered to
+# HTML_HEADER.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HEADER =
# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
# generated LaTeX document. The footer should contain everything after the last
-# chapter. If it is left blank doxygen will generate a standard footer.
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
#
# Note: Only use a user-defined footer if you know what you are doing!
# This tag requires that the tag GENERATE_LATEX is set to YES.
PDF_HYPERLINKS = YES
-# If the LATEX_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
# the PDF file directly from the LaTeX files. Set this option to YES to get a
# higher quality PDF documentation.
# The default value is: YES.
MAN_EXTENSION = .3
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR =
+
# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
# will generate one additional man file for each entity documented in the real
# man page(s). These additional files only source the real man page, but without
XML_OUTPUT = xml
-# The XML_SCHEMA tag can be used to specify a XML schema, which can be used by a
-# validating XML parser to check the syntax of the XML files.
-# This tag requires that the tag GENERATE_XML is set to YES.
-
-XML_SCHEMA =
-
-# The XML_DTD tag can be used to specify a XML DTD, which can be used by a
-# validating XML parser to check the syntax of the XML files.
-# This tag requires that the tag GENERATE_XML is set to YES.
-
-XML_DTD =
-
# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
# listings (including syntax highlighting and cross-referencing information) to
# the XML output. Note that enabling this will significantly increase the size
DOCBOOK_OUTPUT = docbook
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
#---------------------------------------------------------------------------
# Configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
EXPAND_AS_DEFINED =
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
-# remove all refrences to function-like macros that are alone on a line, have an
-# all uppercase name, and do not end with a semicolon. Such function macros are
-# typically used for boiler-plate code, and will confuse the parser if not
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
# removed.
# The default value is: YES.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
# where loc1 and loc2 can be relative or absolute paths or URLs. See the
# section "Linking to external documentation" for more information about the use
# of tag files.
-# Note: Each tag file must have an unique name (where the name does NOT include
+# Note: Each tag file must have a unique name (where the name does NOT include
# the path). If a tag file is not located in the directory in which doxygen is
# run, you must also specify the path to the tagfile here.
MSCGEN_PATH =
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH =
+
# If set to YES, the inheritance and collaboration graphs will hide inheritance
# and usage relations if the target is undocumented or is not a class.
# The default value is: YES.
# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
# Bell Labs. The other options in this section have no effect if this option is
# set to NO
-# The default value is: NO.
+# The default value is: YES.
HAVE_DOT = NO
DOT_NUM_THREADS = 0
-# When you want a differently looking font n the dot files that doxygen
+# When you want a differently looking font in the dot files that doxygen
# generates you can specify the font name using DOT_FONTNAME. You need to make
# sure dot is able to find the font, which can be done by putting it in a
# standard location or by setting the DOTFONTPATH environment variable or by
# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
# to make the SVG files visible in IE 9+ (other browsers do not have this
# requirement).
-# Possible values are: png, jpg, gif and svg.
+# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd,
+# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo,
+# gif:cairo:gd, gif:gd, gif:gd:gd and svg.
# The default value is: png.
# This tag requires that the tag HAVE_DOT is set to YES.
MSCFILE_DIRS =
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+PLANTUML_JAR_PATH =
+
# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
# that will be shown in the graph. If the number of nodes in a graph becomes
# larger than this value, doxygen will truncate the graph, which is visualized
--- /dev/null
+.. _xcode-frameworks-label:
+
+Using aubio frameworks in Xcode
+-------------------------------
+
+`Binary frameworks`_ are available and ready to use in your XCode project, for
+`iOS`_ and `macOS`_.
+
+#. Download and extract the corresponding ``framework.zip`` file from the `Download`_ page
+
+#. Select **Build Phases** in your project setting and unfold **Link Binary with Libraries**
+
+#. Add *AudioToolbox* and *Accelerate* system frameworks (or make sure they are listed)
+
+#. Add ``aubio.framework`` from the unzipped ``framework.zip``
+
+#. Include the aubio header in your code:
+
+ * in C/C++:
+
+ .. code-block:: c
+
+ #include <aubio/aubio.h>
+
+ * in Obj-C:
+
+ .. code-block:: obj-c
+
+ #import <aubio/aubio.h>
+
+ * in Swift:
+
+ .. code-block:: swift
+
+ import aubio
+
+Using aubio from swift
+......................
+
+Here is a short example showing how to read a sound file in swift:
+
+
+ .. code-block:: swift
+
+ import aubio
+
+ let path = Bundle.main.path(forResource: "example", ofType: "mp4")
+ if (path != nil) {
+ let hop_size : uint_t = 512
+ let a = new_fvec(hop_size)
+ let b = new_aubio_source(path, 0, hop_size)
+ var read: uint_t = 0
+ var total_frames : uint_t = 0
+ while (true) {
+ aubio_source_do(b, a, &read)
+ total_frames += read
+ if (read < hop_size) { break }
+ }
+ print("read", total_frames, "frames at", aubio_source_get_samplerate(b), "Hz")
+ del_aubio_source(b)
+ del_fvec(a)
+ } else {
+ print("could not find file")
+ }
+
+
+.. _Binary frameworks: https://aubio.org/download
+.. _iOS: https://aubio.org/download#ios
+.. _macOS: https://aubio.org/download#osx
+.. _Download: https://aubio.org/download
}
int main(int argc, char **argv) {
+ int ret = 0;
// change some default params
buffer_size = 512;
hop_size = 256;
fftgrain = new_cvec (buffer_size);
mfcc = new_aubio_mfcc(buffer_size, n_filters, n_coefs, samplerate);
mfcc_out = new_fvec(n_coefs);
+ if (pv == NULL || fftgrain == NULL || mfcc == NULL || mfcc_out == NULL) {
+ ret = 1;
+ goto beach;
+ }
examples_common_process((aubio_process_func_t)process_block, process_print);
del_aubio_mfcc(mfcc);
del_fvec(mfcc_out);
+beach:
examples_common_del();
- return 0;
+ return ret;
}
-
*/
-#define AUBIO_UNSTABLE 1 // for fvec_median
#include "utils.h"
#define PROG_HAS_PITCH 1
#define PROG_HAS_ONSET 1
+#define PROG_HAS_SILENCE 1
#define PROG_HAS_JACK 1
// TODO add PROG_HAS_OUTPUT
#include "parse_args.h"
-uint_t median = 6;
-
-fvec_t *note_buffer;
-fvec_t *note_buffer2;
-
-smpl_t curnote = 0.;
-smpl_t newnote = 0.;
-uint_t isready = 0;
-
-aubio_pitch_t *pitch;
-aubio_onset_t *o;
-fvec_t *onset;
-fvec_t *pitch_obuf;
-
-/** append new note candidate to the note_buffer and return filtered value. we
- * need to copy the input array as fvec_median destroy its input data.*/
-void note_append (fvec_t * note_buffer, smpl_t curnote);
-uint_t get_note (fvec_t * note_buffer, fvec_t * note_buffer2);
+aubio_notes_t *notes;
+smpl_t lastmidi = 0.;
void process_block (fvec_t *ibuf, fvec_t *obuf)
{
- smpl_t new_pitch, curlevel;
- fvec_zeros(obuf);
- aubio_onset_do(o, ibuf, onset);
-
- aubio_pitch_do (pitch, ibuf, pitch_obuf);
- new_pitch = fvec_get_sample(pitch_obuf, 0);
- if(median){
- note_append(note_buffer, new_pitch);
+ aubio_notes_do (notes, ibuf, obuf);
+ // did we get a note off?
+ if (obuf->data[2] != 0) {
+ lastmidi = obuf->data[2];
+ send_noteon(lastmidi, 0);
}
-
- /* curlevel is negatif or 1 if silence */
- curlevel = aubio_level_detection(ibuf, silence_threshold);
- if (fvec_get_sample(onset, 0)) {
- /* test for silence */
- if (curlevel == 1.) {
- if (median) isready = 0;
- /* send note off */
- send_noteon(curnote,0);
- } else {
- if (median) {
- isready = 1;
- } else {
- /* kill old note */
- send_noteon(curnote,0);
- /* get and send new one */
- send_noteon(new_pitch,127+(int)floor(curlevel));
- curnote = new_pitch;
- }
- }
- } else {
- if (median) {
- if (isready > 0)
- isready++;
- if (isready == median)
- {
- /* kill old note */
- send_noteon(curnote,0);
- newnote = get_note(note_buffer, note_buffer2);
- curnote = newnote;
- /* get and send new one */
- if (curnote>45){
- send_noteon(curnote,127+(int)floor(curlevel));
- }
- }
- } // if median
+ // did we get a note on?
+ if (obuf->data[0] != 0) {
+ lastmidi = obuf->data[0];
+ send_noteon(lastmidi, obuf->data[1]);
}
}
//if (verbose) outmsg("%f\n",pitch_obuf->data[0]);
}
-void
-note_append (fvec_t * note_buffer, smpl_t curnote)
-{
- uint_t i = 0;
- for (i = 0; i < note_buffer->length - 1; i++) {
- note_buffer->data[i] = note_buffer->data[i + 1];
- }
- note_buffer->data[note_buffer->length - 1] = curnote;
- return;
-}
-
-uint_t
-get_note (fvec_t * note_buffer, fvec_t * note_buffer2)
-{
- uint_t i;
- for (i = 0; i < note_buffer->length; i++) {
- note_buffer2->data[i] = note_buffer->data[i];
- }
- return fvec_median (note_buffer2);
-}
-
int main(int argc, char **argv) {
+ int ret = 0;
+
examples_common_init(argc,argv);
verbmsg ("using source: %s at %dHz\n", source_uri, samplerate);
verbmsg ("hop_size: %d, ", hop_size);
verbmsg ("tolerance: %f\n", pitch_tolerance);
- o = new_aubio_onset (onset_method, buffer_size, hop_size, samplerate);
- if (onset_threshold != 0.) aubio_onset_set_threshold (o, onset_threshold);
- onset = new_fvec (1);
-
- pitch = new_aubio_pitch (pitch_method, buffer_size * 4, hop_size, samplerate);
- if (pitch_tolerance != 0.) aubio_pitch_set_tolerance (pitch, pitch_tolerance);
- pitch_obuf = new_fvec (1);
+ notes = new_aubio_notes ("default", buffer_size, hop_size, samplerate);
+ if (notes == NULL) { ret = 1; goto beach; }
- if (median) {
- note_buffer = new_fvec (median);
- note_buffer2 = new_fvec (median);
+ if (onset_minioi != 0.) {
+ aubio_notes_set_minioi_ms(notes, onset_minioi);
+ }
+ if (onset_threshold != 0.) {
+ errmsg ("warning: onset threshold not supported yet\n");
+ //aubio_onset_set_threshold(aubio_notes_get_aubio_onset(o), onset_threshold);
+ }
+ if (silence_threshold != -90.) {
+ if (aubio_notes_set_silence (notes, silence_threshold) != 0) {
+ errmsg ("failed setting notes silence threshold to %.2f\n",
+ silence_threshold);
+ }
}
examples_common_process((aubio_process_func_t)process_block, process_print);
- // send a last note off
- send_noteon (curnote, 0);
-
- del_aubio_pitch (pitch);
- if (median) {
- del_fvec (note_buffer);
- del_fvec (note_buffer2);
+ // send a last note off if required
+ if (lastmidi) {
+ send_noteon (lastmidi, 0);
}
- del_fvec (pitch_obuf);
+ del_aubio_notes (notes);
+
+beach:
examples_common_del();
- return 0;
+ return ret;
}
-
#include "utils.h"
#define PROG_HAS_ONSET 1
#define PROG_HAS_OUTPUT 1
+#define PROG_HAS_SILENCE 1
#define PROG_HAS_JACK 1
#include "parse_args.h"
fvec_zeros(obuf);
if ( is_onset ) {
aubio_wavetable_play ( wavetable );
+ /* send a midi tap (default to C0) out to the midi output */
+ if (usejack) send_noteon(miditap_note, miditap_velo);
} else {
aubio_wavetable_stop ( wavetable );
}
}
int main(int argc, char **argv) {
+ int ret = 0;
examples_common_init(argc,argv);
verbmsg ("using source: %s at %dHz\n", source_uri, samplerate);
verbmsg ("threshold: %f\n", onset_threshold);
o = new_aubio_onset (onset_method, buffer_size, hop_size, samplerate);
+ if (o == NULL) { ret = 1; goto beach; }
if (onset_threshold != 0.)
aubio_onset_set_threshold (o, onset_threshold);
if (silence_threshold != -90.)
aubio_onset_set_silence (o, silence_threshold);
+ if (onset_minioi != 0.)
+ aubio_onset_set_minioi_s (o, onset_minioi);
onset = new_fvec (1);
examples_common_process((aubio_process_func_t)process_block, process_print);
+ // send a last note off
+ if (usejack) {
+ send_noteon (miditap_note, 0);
+ }
+
del_aubio_onset (o);
del_aubio_wavetable (wavetable);
del_fvec (onset);
+beach:
examples_common_del();
- return 0;
+ return ret;
}
#include "utils.h"
#define PROG_HAS_PITCH 1
#define PROG_HAS_OUTPUT 1
+#define PROG_HAS_SILENCE 1
#define PROG_HAS_JACK 1
#include "parse_args.h"
}
int main(int argc, char **argv) {
+ int ret = 0;
buffer_size = 2048;
verbmsg ("tolerance: %f\n", pitch_tolerance);
o = new_aubio_pitch (pitch_method, buffer_size, hop_size, samplerate);
+ if (o == NULL) { ret = 1; goto beach; }
if (pitch_tolerance != 0.)
aubio_pitch_set_tolerance (o, pitch_tolerance);
if (silence_threshold != -90.)
del_aubio_wavetable (wavetable);
del_fvec (pitch);
+beach:
examples_common_del();
- return 0;
+ return ret;
}
-
*/
#include "utils.h"
+#define PROG_HAS_SILENCE 1
#include "parse_args.h"
sint_t wassilence = 1, issilence;
#include "utils.h"
#define PROG_HAS_TEMPO 1
+#define PROG_HAS_ONSET 1
+#define PROG_HAS_SILENCE 1
#define PROG_HAS_OUTPUT 1
#define PROG_HAS_JACK 1
#include "parse_args.h"
aubio_tempo_t * tempo;
aubio_wavetable_t *wavetable;
fvec_t * tempo_out;
-smpl_t is_beat = 0;
-uint_t is_silence = 0.;
+smpl_t is_beat = 0.;
+uint_t is_silence = 0;
void process_block(fvec_t * ibuf, fvec_t *obuf) {
aubio_tempo_do (tempo, ibuf, tempo_out);
fvec_zeros (obuf);
if ( is_beat && !is_silence ) {
aubio_wavetable_play ( wavetable );
+ /* send a midi tap (default to C0) out to the midi output */
+ if (usejack) send_noteon(miditap_note, miditap_velo);
} else {
aubio_wavetable_stop ( wavetable );
}
}
int main(int argc, char **argv) {
+ int ret = 0;
// override general settings from utils.c
buffer_size = 1024;
hop_size = 512;
tempo_out = new_fvec(2);
tempo = new_aubio_tempo(tempo_method, buffer_size, hop_size, samplerate);
+ if (tempo == NULL) { ret = 1; goto beach; }
// set silence threshold very low to output beats even during silence
// aubio_tempo_set_silence(tempo, -1000.);
if (onset_threshold != 0.) aubio_tempo_set_threshold (tempo, onset_threshold);
+ if (onset_minioi != 0.) errmsg ("warning: minioio not supported yet\n");
wavetable = new_aubio_wavetable (samplerate, hop_size);
aubio_wavetable_set_freq ( wavetable, 2450.);
examples_common_process((aubio_process_func_t)process_block,process_print);
+ // send a last note off
+ if (usejack) {
+ send_noteon (miditap_note, 0);
+ }
+
del_aubio_tempo(tempo);
del_aubio_wavetable (wavetable);
del_fvec(tempo_out);
+beach:
examples_common_del();
- return 0;
+ return ret;
}
-
#include <aubio.h>
#include "config.h"
-#if HAVE_JACK
+#ifdef HAVE_JACK
#include "utils.h" // for aubio_process_func_t
#include "jackio.h"
#include "aubio_priv.h"
*/
+#include "config.h"
+
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+
extern int verbose;
// input / output
extern int usejack;
// onset stuff
extern char_t * onset_method;
extern smpl_t onset_threshold;
+extern smpl_t onset_minioi;
// pitch stuff
extern char_t * pitch_method;
extern char_t * pitch_unit;
// more general stuff
extern smpl_t silence_threshold;
extern uint_t mix_input;
+// midi tap
+extern smpl_t miditap_note;
+extern smpl_t miditap_velo;
extern uint_t force_overwrite;
void usage (FILE * stream, int exit_code)
{
+#ifdef HAVE_GETOPT_H
fprintf (stream, "usage: %s [ options ] \n", prog_name);
fprintf (stream,
" -i --input input file\n"
" default=hfc\n"
" -t --onset-threshold set onset detection threshold\n"
" a value between 0.1 (more detections) and 1 (less); default=0.3\n"
+ " -M --minioi set minimum inter-onset interval\n"
+ " a value in second; default=0.012\n"
#endif /* PROG_HAS_ONSET */
#ifdef PROG_HAS_PITCH
" -p --pitch select pitch detection algorithm\n"
" -l --pitch-tolerance select pitch tolerance\n"
" (yin, yinfft only) a value between 0.1 and 0.7; default=0.3\n"
#endif /* PROG_HAS_PITCH */
+#ifdef PROG_HAS_SILENCE
" -s --silence select silence threshold\n"
" a value in dB, for instance -70, or -100; default=-90\n"
+#endif /* PROG_HAS_SILENCE */
" -T --time-format select time values output format\n"
" (samples, ms, seconds) default=seconds\n"
#ifdef PROG_HAS_OUTPUT
" input signal will be added to output synthesis\n"
" -f --force-overwrite overwrite output file if needed\n"
" do not fail if output file already exists\n"
-#endif
+#endif /* PROG_HAS_OUTPUT */
#ifdef PROG_HAS_JACK
" -j --jack use Jack\n"
-#endif
+#if defined(PROG_HAS_ONSET) && !defined(PROG_HAS_PITCH)
+ " -N --miditap-note MIDI note; default=69.\n"
+ " -V --miditap-velo MIDI velocity; default=65.\n"
+#endif /* defined(PROG_HAS_ONSET) && !defined(PROG_HAS_PITCH) */
+#endif /* PROG_HAS_JACK */
" -v --verbose be verbose\n"
" -h --help display this message\n"
);
+#else /* HAVE_GETOPT_H */
+ fprintf (stream, "warning: compiled with getopt.h, no argument parsing\n");
+ fprintf (stream, "usage: %s <filename> \n", prog_name);
+#endif /* HAVE_GETOPT_H */
exit (exit_code);
}
int
parse_args (int argc, char **argv)
{
+#ifdef HAVE_GETOPT_H
const char *options = "hv"
"i:r:B:H:"
#ifdef PROG_HAS_JACK
"j"
+#if defined(PROG_HAS_ONSET) && !defined(PROG_HAS_PITCH)
+ "N:V:"
+#endif /* defined(PROG_HAS_ONSET) && !defined(PROG_HAS_PITCH) */
#endif /* PROG_HAS_JACK */
#ifdef PROG_HAS_OUTPUT
"o:"
#endif /* PROG_HAS_OUTPUT */
#ifdef PROG_HAS_ONSET
- "O:t:"
+ "O:t:M:"
#endif /* PROG_HAS_ONSET */
#ifdef PROG_HAS_PITCH
"p:u:l:"
#endif /* PROG_HAS_PITCH */
"T:"
- "s:mf";
+#ifdef PROG_HAS_SILENCE
+ "s:"
+#endif /* PROG_HAS_SILENCE */
+#ifdef PROG_HAS_OUTPUT
+ "mf"
+#endif /* PROG_HAS_OUTPUT */
+ ;
int next_option;
struct option long_options[] = {
{"help", 0, NULL, 'h'},
{"hopsize", 1, NULL, 'H'},
#ifdef PROG_HAS_JACK
{"jack", 0, NULL, 'j'},
+#if defined(PROG_HAS_ONSET) && !defined(PROG_HAS_PITCH)
+ {"miditap-note", 1, NULL, 'N'},
+ {"miditap-velo", 1, NULL, 'V'},
+#endif /* PROG_HAS_ONSET !PROG_HAS_PITCH */
#endif /* PROG_HAS_JACK */
#ifdef PROG_HAS_OUTPUT
{"output", 1, NULL, 'o'},
#ifdef PROG_HAS_ONSET
{"onset", 1, NULL, 'O'},
{"onset-threshold", 1, NULL, 't'},
+ {"onset-minioi", 1, NULL, 'M'},
#endif /* PROG_HAS_ONSET */
#ifdef PROG_HAS_PITCH
{"pitch", 1, NULL, 'p'},
{"pitch-unit", 1, NULL, 'u'},
{"pitch-tolerance", 1, NULL, 'l'},
#endif /* PROG_HAS_PITCH */
+#ifdef PROG_HAS_SILENCE
{"silence", 1, NULL, 's'},
+#endif /* PROG_HAS_SILENCE */
{"time-format", 1, NULL, 'T'},
+#ifdef PROG_HAS_OUTPUT
{"mix-input", 0, NULL, 'm'},
{"force-overwrite", 0, NULL, 'f'},
+#endif /* PROG_HAS_OUTPUT */
{NULL, 0, NULL, 0}
};
+#endif /* HAVE_GETOPT_H */
prog_name = argv[0];
if (argc < 1) {
usage (stderr, 1);
return -1;
}
+#ifdef HAVE_GETOPT_H
do {
next_option = getopt_long (argc, argv, options, long_options, NULL);
switch (next_option) {
case 'j':
usejack = 1;
break;
+ case 'N':
+ miditap_note = (smpl_t) atoi (optarg);
+ break;
+ case 'V':
+ miditap_velo = (smpl_t) atoi (optarg);
+ break;
case 'i':
source_uri = optarg;
break;
case 't': /* threshold value for onset */
onset_threshold = (smpl_t) atof (optarg);
break;
+ case 'M': /* minimum inter-onset-interval */
+ onset_minioi = (smpl_t) atof (optarg);
+ break;
case 'p':
pitch_method = optarg;
break;
}
}
while (next_option != -1);
+#else /* HAVE_GETOPT_H */
+ int optind = 1;
+#endif /* HAVE_GETOPT_H */
// if unique, use the non option argument as the source
if ( source_uri == NULL ) {
// onset stuff
char_t * onset_method = "default";
smpl_t onset_threshold = 0.0; // will be set if != 0.
+smpl_t onset_minioi = 0.0; // will be set if != 0.
// pitch stuff
char_t * pitch_unit = "default";
char_t * pitch_method = "default";
fvec_t *ibuf;
fvec_t *obuf;
+smpl_t miditap_note = 69.;
+smpl_t miditap_velo = 65.;
+
/* settings */
int blocks = 0;
#if HAVE_JACK
aubio_jack_t *jack_setup;
-#endif
+jack_midi_event_t ev;
+#endif /* HAVE_JACK */
void examples_common_init (int argc, char **argv);
void examples_common_del (void);
jack_setup = new_aubio_jack (hop_size, 1, 1, 0, 1);
samplerate = aubio_jack_get_samplerate (jack_setup);
source_uri = "jack";
-#endif
+#endif /* HAVE_JACK */
}
ibuf = new_fvec (hop_size);
obuf = new_fvec (hop_size);
void examples_common_del (void)
{
+#ifdef HAVE_JACK
+ if (ev.buffer) free(ev.buffer);
+#endif
del_fvec (ibuf);
del_fvec (obuf);
aubio_cleanup ();
uint_t read = 0;
if (usejack) {
-#if HAVE_JACK
+#ifdef HAVE_JACK
+ ev.size = 3;
+ ev.buffer = malloc (3 * sizeof (jack_midi_data_t));
+ ev.time = 0; // send it now
debug ("Jack activation ...\n");
aubio_jack_activate (jack_setup, process_func);
debug ("Processing (Ctrl+C to quit) ...\n");
pause ();
aubio_jack_close (jack_setup);
-#else
+#else /* HAVE_JACK */
usage (stderr, 1);
outmsg ("Compiled without jack output, exiting.\n");
-#endif
+#endif /* HAVE_JACK */
} else {
}
void
-send_noteon (int pitch, int velo)
+send_noteon (smpl_t pitch, smpl_t velo)
{
- smpl_t mpitch = floor (aubio_freqtomidi (pitch) + .5);
-#if HAVE_JACK
- jack_midi_event_t ev;
- ev.size = 3;
- ev.buffer = malloc (3 * sizeof (jack_midi_data_t)); // FIXME
- ev.time = 0;
+#ifdef HAVE_JACK
if (usejack) {
ev.buffer[2] = velo;
- ev.buffer[1] = mpitch;
+ ev.buffer[1] = pitch;
if (velo == 0) {
ev.buffer[0] = 0x80; /* note off */
} else {
print_time (blocks * hop_size);
outmsg ("\n");
} else {
- outmsg ("%f\t", mpitch);
+ outmsg ("%f\t", pitch);
print_time (blocks * hop_size);
outmsg ("\t");
}
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <getopt.h>
-#include <unistd.h>
-#include <math.h> /* for isfinite */
-#include <string.h> /* for strcmp */
#include <aubio.h>
+
#include "config.h"
+#ifdef HAVE_STDIO_H
+#include <stdio.h> // for fprintf
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h> // for exit
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h> // for access
+#elif defined(HAVE_WIN_HACKS)
+#include <io.h>
+#define access _access
+#define F_OK 0
+#endif
+#ifdef HAVE_MATH_H
+#include <math.h> // for isfinite
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h> // for strcmp
+#endif
+
#ifdef HAVE_C99_VARARGS_MACROS
#ifdef HAVE_DEBUG
#define debug(...) fprintf (stderr, __VA_ARGS__)
#endif
typedef void (aubio_print_func_t) (void);
-void send_noteon (int pitch, int velo);
+void send_noteon (smpl_t pitch, smpl_t velo);
/** common process function */
typedef int (*aubio_process_func_t) (fvec_t * input, fvec_t * output);
# vim:set syntax=python:
-uselib = []
-uselib += ['FFTW3', 'FFTW3F']
-uselib += ['SAMPLERATE']
-uselib += ['SNDFILE']
-uselib += ['AVCODEC']
-uselib += ['AVFORMAT']
-uselib += ['AVRESAMPLE']
-uselib += ['AVUTIL']
+import os.path
+
+uselib = ['aubio']
uselib += ['JACK']
-uselib += ['BLAS']
+includes = ['../src']
utils_source = ['utils.c', 'jackio.c']
programs_source = ctx.path.ant_glob('*.c', excl = utils_source)
# build examples
bld(features = 'c',
source = utils_source,
- includes = ['../src'],
- uselib = uselib,
+ includes = includes,
+ use = uselib,
target = 'utilsio')
# loop over all *.c filenames in examples to build them all
for source_file in programs_source:
+ target = os.path.basename(os.path.splitext(str(source_file))[0])
bld(features = 'c cprogram',
- includes = '../src',
- lib = 'm',
- use = ['aubio', 'utilsio'],
- uselib = uselib,
source = source_file,
- target = str(source_file).split('.')[0]
- )
+ target = target,
+ includes = includes,
+ use = uselib + ['utilsio'],
+ )
--- /dev/null
+[unittest]
+start-dir = python/tests/
+plugins = nose2.plugins.mp
+
+[multiprocess]
+always-on = false
+++ /dev/null
-include README COPYING VERSION
-include ext/*.h
-include lib/generator.py
-include lib/gen_pyobject.py
-include gen/aubio-generated.h
-include tests/run_all_tests
-include tests/*.py
-include demos/*.py
+++ /dev/null
-Python aubio module
-===================
-
-This module wraps the aubio library for Python using the numpy module.
-
-Before compiling this module, you must have compiled libaubio.
-
-For more information about how this module works, please refer to the [Python/C
-API Reference Manual] (http://docs.python.org/c-api/index.html) and the
-[Numpy/C API Reference](http://docs.scipy.org/doc/numpy/reference/c-api.html).
-
-Compiling python aubio
-----------------------
-
-After libaubio has been build successfully, and provided Python development
-headers and numpy can be found on your system, you should be able to build the
-aubio Python module:
-
- $ ./setup.py build
-
-To find out more about `setup.py` options:
-
- $ ./setup.py --help
-
-Installing
-----------
-
-To install the Python module:
-
- $ ./setup.py install
-
-Using the Python module
------------------------
-
-Once the aubio library and the Python module are installed, you will be able to
-import the aubio module:
-
- $ python
- [...]
- >>> import aubio
- >>>
-
-Alternatively, you may want to use the Python module without installing it by
-setting PYTHONPATH:
-
- $ export PYTHONPATH=$PYTHONPATH:$PWD/`ls -rtd build/lib.* | head -1`:$PWD/tests
-
-Similarly, you can use the aubio module without installing libaubio by pointing
-LD_LIBRARY_PATH to the path libaubio can be found at:
-
- $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:PWD/../build/src
-
-Or on Mac OS X systems, setting DYLD_LIBRARY_PATH:
-
- $ export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:$PWD/../build/src
-
-Testing the Python module
--------------------------
-
-Once both the C library and the Python module have been built correctly, and
-after you have installed them (or setting the environment variable correctly),
-you should be able to run the tests:
-
- $ ./tests/run_all_tests
-
-And to try out the demos:
-
- $ ./demos/demo_source.wav /path/to/sound/sample.wav
-
-You need to install additional modules to run some of the demos. For
-instance, several demos use [matplotlib](http://matplotlib.org/) to draw plots.
-Some more demos use [PySoundCard](https://github.com/bastibe/PySoundCard) to
-play and record sounds.
--- /dev/null
+Python aubio module
+===================
+
+This module wraps the aubio library for Python using the numpy module.
+
+Using the Python aubio module
+-----------------------------
+
+After installing python-aubio, you will be able to import the aubio module:
+
+ $ python
+ [...]
+ >>> import aubio
+ >>> help(aubio.miditofreq)
+
+Finding some inspiration
+------------------------
+
+Some examples are available in the `python/demos` directory. These scripts are
+small programs written in python and using python-aubio.
+
+For instance, `demo_source.py` reads a media file.
+
+ $ ./python/demos/demo_source.py /path/to/sound/sample.wav
+
+and `demo_timestretch_online.py` stretches the original file into a new one:
+
+ $ ./python/demo/demo_timestretch_online.py loop.wav stretched_loop.wav 0.92`
+
+Note: you might need to install additional modules to run some of the demos.
+Some demos use [matplotlib](http://matplotlib.org/) to draw plots, others use
+[PySoundCard](https://github.com/bastibe/PySoundCard) to play and record
+sounds.
+
+Testing the Python module
+-------------------------
+
+Python tests are in `python/tests` and use the [nose2 python package][nose2].
+
+To run the all the python tests, use the script:
+
+ $ ./python/tests/run_all_tests
+
+Each test script can also be called one at a time. For instance:
+
+ $ ./python/tests/test_note2midi.py -v
+
+[nose2]: https://github.com/nose-devs/nose2
+
+Install in a virtualenv
+-----------------------
+
+You should be able to install python-aubio directly from the top source
+directory of aubio.
+
+First, create a virtualenv to hold the required python module:
+
+ $ virtualenv pyaubio
+ $ source pyaubio/bin/activate
+
+Now install and build the python extension using:
+
+ $ pip install .
+
+Install requirements
+--------------------
+
+Before compiling this module, you must have compiled libaubio.
+
+A simple way to do this is with pip:
+
+ $ pip install -r requirements.txt
+
+For more information about how this module works, please refer to the [Python/C
+API Reference Manual] (http://docs.python.org/c-api/index.html) and the
+[Numpy/C API Reference](http://docs.scipy.org/doc/numpy/reference/c-api.html).
+
+Compiling python aubio
+----------------------
+
+To build the aubio Python module, run the following command from the top source
+directory of aubio:
+
+ $ ./setup.py build
+
+Note: if libaubio was previously built using waf, the script will use it.
+Otherwise, the entire library will be built inside the python extension.
+
+To find out more about `setup.py` options:
+
+ $ ./setup.py --help
+
+Installing
+----------
+
+To install the Python module:
+
+ $ ./setup.py install
+
+Alternatively, you may want to use the Python module without installing it by
+setting your PYTHONPATH, for instance as follows:
+
+ $ export PYTHONPATH=$PYTHONPATH:$PWD/`ls -rtd build/lib.* | head -1`:$PWD/tests
+
+++ /dev/null
-AUBIO_MAJOR_VERSION=0
-AUBIO_MINOR_VERSION=4
-AUBIO_PATCH_VERSION=2
-AUBIO_VERSION_STATUS='~alpha'
-LIBAUBIO_LT_CUR=4
-LIBAUBIO_LT_REV=1
-LIBAUBIO_LT_AGE=1
+++ /dev/null
-#! /usr/bin/env python
-
-
-def apply_filter(path, params = {}):
- from aubio import source, sink, digital_filter
- from os.path import basename, splitex, splitextt
- s = source(path)
- f = digital_filter(7)
- f.set_a_weighting(s.samplerate)
- #f = digital_filter(3)
- #f.set_biquad(...)
- o = sink("filtered_" + splitext(basename(path))[0] + ".wav")
- # Total number of frames read
- total_frames = 0
-
- while True:
- samples, read = s()
- filtered_samples = f(samples)
- o(samples, read)
- total_frames += read
- if read < s.hop_size: break
- print "filtered", s.uri, "to", o.uri, "using an A-weighting filter"
-
-if __name__ == '__main__':
- import sys
- for f in sys.argv[1:]:
- apply_filter(f)
--- /dev/null
+#! /usr/bin/env python
+
+import alsaaudio
+import numpy as np
+import aubio
+
+# constants
+samplerate = 44100
+win_s = 2048
+hop_s = win_s // 2
+framesize = hop_s
+
+# set up audio input
+recorder = alsaaudio.PCM(type=alsaaudio.PCM_CAPTURE)
+recorder.setperiodsize(framesize)
+recorder.setrate(samplerate)
+recorder.setformat(alsaaudio.PCM_FORMAT_FLOAT_LE)
+recorder.setchannels(1)
+
+# create aubio pitch detection (first argument is method, "default" is
+# "yinfft", can also be "yin", "mcomb", fcomb", "schmitt").
+pitcher = aubio.pitch("default", win_s, hop_s, samplerate)
+# set output unit (can be 'midi', 'cent', 'Hz', ...)
+pitcher.set_unit("Hz")
+# ignore frames under this level (dB)
+pitcher.set_silence(-40)
+
+print("Starting to listen, press Ctrl+C to stop")
+
+# main loop
+while True:
+ try:
+ # read data from audio input
+ _, data = recorder.read()
+ # convert data to aubio float samples
+ samples = np.fromstring(data, dtype=aubio.float_type)
+ # pitch of current frame
+ freq = pitcher(samples)[0]
+ # compute energy of current block
+ energy = np.sum(samples**2)/len(samples)
+ # do something with the results
+ print("{:10.4f} {:10.4f}".format(freq,energy))
+ except KeyboardInterrupt:
+ print("Ctrl+C pressed, exiting")
+ break
--- /dev/null
+#! /usr/bin/env python
+
+import numpy as np
+from aubio import pitch
+import pylab as plt
+
+buf_size = 2048 * 1
+hop_size = buf_size // 4
+
+samplerate = 44100
+minfreq = 40
+maxfreq = 6000
+
+def sinewave(freq, duration, samplerate = samplerate):
+ """ generate a sinewave """
+ length = hop_size
+ while length < duration * samplerate:
+ length += hop_size
+ return np.sin( 2. * np.pi * np.arange(length) * freq / samplerate ).astype("float32")
+
+def get_stats_for_pitch_method(method, freqs, samplerate = samplerate):
+ """ for a given pitch method and a list of frequency, generate a sinewave
+ and get mean deviation """
+ means = np.zeros(len(freqs))
+ medians = np.zeros(len(freqs))
+ for freq, fn in zip(freqs, range(len(freqs))):
+ s = sinewave(freq, .50).reshape(-1, hop_size)
+ #s = (sinewave(freq, .50) + .0*sinewave(freq/2., .50)).reshape(-1, hop_size)
+ p = pitch(method, buf_size, hop_size, samplerate = samplerate)
+ candidates = np.zeros(len(s))
+ #samples = np.zeros(buf_size)
+ for frame, i in zip(s, range(len(s))):
+ candidates[i] = p(frame)[0]
+ # skip first few candidates
+ candidates = candidates[4:]
+ means[fn] = np.mean(candidates[candidates != 0] - freq)
+ medians[fn] = np.median(candidates[candidates != 0] - freq)
+ print (freq, means[fn], medians[fn])
+ return means, medians
+
+if __name__ == '__main__':
+ freqs = np.arange(minfreq, maxfreq, 1.)
+ modes = ["yin", "yinfft"]
+ for mode in modes:
+ means, medians = get_stats_for_pitch_method(mode, freqs)
+ plt.figure()
+ plt.plot(freqs, means, 'g-')
+ plt.plot(freqs, medians, 'r--')
+ #plt.savefig(mode + '_deviations_test.png', dpi=300)
+ plt.show()
from aubio import source, tempo
from numpy import median, diff
-def get_file_bpm(path, params = {}):
+def get_file_bpm(path, params = None):
""" Calculate the beats per minute (bpm) of a given file.
path: path to the file
param: dictionary of parameters
"""
+ if params is None:
+ params = {}
try:
win_s = params['win_s']
samplerate = params['samplerate']
hop_s = params['hop_s']
- except:
+ except KeyError:
"""
# super fast
samplerate, win_s, hop_s = 4000, 128, 64
break
# Convert to periods and to bpm
- bpms = 60./diff(beats)
- b = median(bpms)
+ if len(beats) > 1:
+ if len(beats) < 4:
+ print("few beats found in {:s}".format(path))
+ bpms = 60./diff(beats)
+ b = median(bpms)
+ else:
+ b = 0
+ print("not enough beats found in {:s}".format(path))
return b
if __name__ == '__main__':
import sys
for f in sys.argv[1:]:
bpm = get_file_bpm(f)
- print "%6s" % ("%.2f" % bpm), f
+ print("{:6s} {:s}".format("{:2f}".format(bpm), f))
--- /dev/null
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import sys, os
+import numpy as np
+from aubio import fvec, sink, float_type
+
+if __name__ == '__main__':
+ if len(sys.argv) < 1:
+ print('usage: %s' % sys.argv[0])
+ sys.exit(1)
+
+ samplerate = 44100
+ hop_size = 256
+
+ # create python/tests/sounds if needed
+ output_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+ output_dir = os.path.join(output_dir, 'tests', 'sounds')
+ if not os.path.isdir(output_dir):
+ os.makedirs(output_dir)
+
+ filenames = ['44100Hz_1f_silence.wav',
+ '22050Hz_5s_brownnoise.wav',
+ '32000Hz_127f_sine440.wav',
+ ]
+ samplerates = [44100, 22050, 32000]
+ durations = [1, 5*22050, 127]
+
+ for fname, samplerate, duration in zip(filenames, samplerates, durations):
+ output_name = os.path.join(output_dir, fname)
+ g = sink(output_name, samplerate)
+ total_frames = 0
+ while total_frames < duration:
+ write = min(hop_size, duration - total_frames)
+ if 'brownnoise' in fname:
+ vec = np.random.rand(write).astype(float_type) * 2. - 1.
+ elif 'sine' in fname:
+ freq = 440
+ t = np.arange(write).astype(float_type) + total_frames
+ vec = np.sin(2. * np.pi * freq * t / float(samplerate))
+ else:
+ # silence
+ vec = fvec(write)
+ g(vec, write)
+ total_frames += write
+ outstr = "wrote {:2f}s".format(total_frames / float(samplerate))
+ outstr += " ({:d} frames".format(total_frames)
+ outstr += " at {:d}Hz)".format(g.samplerate)
+ outstr += " to {:s}".format(g.uri)
+ print(outstr)
--- /dev/null
+#! /usr/bin/env python
+
+
+def apply_filter(path):
+ from aubio import source, sink, digital_filter
+ from os.path import basename, splitext
+
+ # open input file, get its samplerate
+ s = source(path)
+ samplerate = s.samplerate
+
+ # create an A-weighting filter
+ f = digital_filter(7)
+ f.set_a_weighting(samplerate)
+ # alternatively, apply another filter
+
+ # create output file
+ o = sink("filtered_" + splitext(basename(path))[0] + ".wav", samplerate)
+
+ total_frames = 0
+ while True:
+ samples, read = s()
+ filtered_samples = f(samples)
+ o(filtered_samples, read)
+ total_frames += read
+ if read < s.hop_size: break
+
+ duration = total_frames / float(samplerate)
+ print ("read {:s}".format(s.uri))
+ print ("applied A-weighting filtered ({:d} Hz)".format(samplerate))
+ print ("wrote {:s} ({:.2f} s)".format(o.uri, duration))
+
+if __name__ == '__main__':
+ import sys
+ for f in sys.argv[1:]:
+ apply_filter(f)
#! /usr/bin/env python
from aubio import filterbank, fvec
-from pylab import loglog, show, subplot, xlim, ylim, xlabel, ylabel, title
+from pylab import loglog, show, xlim, ylim, xlabel, ylabel, title
from numpy import vstack, arange
win_s = 2048
f.set_coeffs(coeffs)
-times = vstack([arange(win_s / 2 + 1) * samplerate / win_s] * n_filters)
+times = vstack([arange(win_s // 2 + 1) * samplerate / win_s] * n_filters)
title('Bank of filters built using a simple list of boundaries\nThe middle band has been amplified by 2.')
loglog(times.T, f.get_coeffs().T, '.-')
xlim([50, samplerate/2])
#! /usr/bin/env python
from aubio import filterbank
-from numpy import array, arange, vstack
+from numpy import arange, vstack
win_s = 8192
samplerate = 16000
from pylab import loglog, title, show, xlim, ylim, xlabel, ylabel
xlim([0,samplerate / 2])
-times = vstack([arange(win_s / 2 + 1) * samplerate / win_s] * 40)
+times = vstack([arange(win_s // 2 + 1) * samplerate / win_s] * 40)
loglog(times.T, f.get_coeffs().T, '.-')
title('Mel frequency bands coefficients')
xlim([100, 7500])
subplot(211)
title('Examples of filterbank built with set_triangle_bands and set_coeffs')
-times = vstack([arange(win_s / 2 + 1) * samplerate / win_s] * n_filters)
+times = vstack([arange(win_s // 2 + 1) * samplerate / win_s] * n_filters)
loglog(times.T, f.get_coeffs().T, '.-')
xlim([50, samplerate/2])
ylim([1.0e-6, 2.0e-2])
f.set_coeffs(coeffs)
subplot(212)
-times = vstack([arange(win_s / 2 + 1) * samplerate / win_s] * n_filters)
+times = vstack([arange(win_s // 2 + 1) * samplerate / win_s] * n_filters)
loglog(times.T, f.get_coeffs().T, '.-')
xlim([50, samplerate/2])
ylim([1.0e-6, 2.0e-2])
return xb, xw, 2/3. *scaleb, 1/2. * scalew
def create_keyboard_patches(firstnote, lastnote, ax = None):
- import numpy as np
import matplotlib.pyplot as plt
from matplotlib.path import Path
import matplotlib.patches as mpatches
#! /usr/bin/env python
import sys
-from aubio import fvec, source, pvoc, filterbank
+from aubio import source, pvoc, filterbank
from numpy import vstack, zeros
win_s = 512 # fft size
-hop_s = win_s / 4 # hop size
+hop_s = win_s // 4 # hop size
if len(sys.argv) < 2:
- print "Usage: %s <filename> [samplerate]" % sys.argv[0]
+ print("Usage: %s <filename> [samplerate]" % sys.argv[0])
sys.exit(1)
filename = sys.argv[1]
samples, read = s()
fftgrain = pv(samples)
new_energies = f(fftgrain)
- print '%f' % (total_frames / float(samplerate) ),
- print ' '.join(['%f' % b for b in new_energies])
+ timestr = '%f' % (total_frames / float(samplerate) )
+ print('{:s} {:s}'.format(timestr, ' '.join(['%f' % b for b in new_energies])))
energies = vstack( [energies, new_energies] )
total_frames += read
if read < hop_s: break
if 1:
- print "done computing, now plotting"
+ print("done computing, now plotting")
import matplotlib.pyplot as plt
from demo_waveform_plot import get_waveform_plot
from demo_waveform_plot import set_xlabels_sample2time
import sys
from aubio import source, pvoc, mfcc
-from numpy import array, vstack, zeros
+from numpy import vstack, zeros, diff
-win_s = 512 # fft size
-hop_s = win_s / 4 # hop size
n_filters = 40 # must be 40 for mfcc
n_coeffs = 13
-samplerate = 44100
if len(sys.argv) < 2:
- print "Usage: %s <source_filename>" % sys.argv[0]
+ print("Usage: %s <source_filename> [samplerate] [win_s] [hop_s] [mode]" % sys.argv[0])
+ print(" where [mode] can be 'delta' or 'ddelta' for first and second derivatives")
sys.exit(1)
source_filename = sys.argv[1]
+if len(sys.argv) > 2: samplerate = int(sys.argv[2])
+else: samplerate = 0
+if len(sys.argv) > 3: win_s = int(sys.argv[3])
+else: win_s = 512
+if len(sys.argv) > 4: hop_s = int(sys.argv[4])
+else: hop_s = win_s // 4
+if len(sys.argv) > 5: mode = sys.argv[5]
+else: mode = "default"
+
samplerate = 0
if len( sys.argv ) > 2: samplerate = int(sys.argv[2])
wave.xaxis.set_visible(False)
wave.yaxis.set_visible(False)
+# compute first and second derivatives
+if mode in ["delta", "ddelta"]:
+ mfccs = diff(mfccs, axis = 0)
+if mode == "ddelta":
+ mfccs = diff(mfccs, axis = 0)
+
all_times = arange(mfccs.shape[0]) * hop_s
n_coeffs = mfccs.shape[1]
for i in range(n_coeffs):
ax = plt.axes ( [0.1, 0.75 - ((i+1) * 0.65 / n_coeffs), 0.8, 0.65 / n_coeffs], sharex = wave )
ax.xaxis.set_visible(False)
- ax.yaxis.set_visible(False)
+ ax.set_yticks([])
+ ax.set_ylabel('%d' % i)
ax.plot(all_times, mfccs.T[i])
# add time to the last axis
-set_xlabels_sample2time( ax, frames_read, samplerate)
+set_xlabels_sample2time( ax, frames_read, samplerate)
#plt.ylabel('spectral descriptor value')
ax.xaxis.set_visible(True)
-wave.set_title('MFCC for %s' % source_filename)
+title = 'MFCC for %s' % source_filename
+if mode == "delta": title = mode + " " + title
+elif mode == "ddelta": title = "double-delta" + " " + title
+wave.set_title(title)
plt.show()
--- /dev/null
+#! /usr/bin/env python
+
+import sys
+from aubio import source, notes
+
+if len(sys.argv) < 2:
+ print("Usage: %s <filename> [samplerate]" % sys.argv[0])
+ sys.exit(1)
+
+filename = sys.argv[1]
+
+downsample = 1
+samplerate = 44100 // downsample
+if len( sys.argv ) > 2: samplerate = int(sys.argv[2])
+
+win_s = 512 // downsample # fft size
+hop_s = 256 // downsample # hop size
+
+s = source(filename, samplerate, hop_s)
+samplerate = s.samplerate
+
+tolerance = 0.8
+
+notes_o = notes("default", win_s, hop_s, samplerate)
+
+print("%8s" % "time","[ start","vel","last ]")
+
+# total number of frames read
+total_frames = 0
+while True:
+ samples, read = s()
+ new_note = notes_o(samples)
+ if (new_note[0] != 0):
+ note_str = ' '.join(["%.2f" % i for i in new_note])
+ print("%.6f" % (total_frames/float(samplerate)), new_note)
+ total_frames += read
+ if read < hop_s: break
from aubio import source, onset
win_s = 512 # fft size
-hop_s = win_s / 2 # hop size
+hop_s = win_s // 2 # hop size
if len(sys.argv) < 2:
- print "Usage: %s <filename> [samplerate]" % sys.argv[0]
+ print("Usage: %s <filename> [samplerate]" % sys.argv[0])
sys.exit(1)
filename = sys.argv[1]
while True:
samples, read = s()
if o(samples):
- print "%f" % o.get_last_s()
+ print("%f" % o.get_last_s())
onsets.append(o.get_last())
total_frames += read
if read < hop_s: break
import sys
from aubio import onset, source
-from numpy import array, hstack, zeros
+from numpy import hstack, zeros
win_s = 512 # fft size
-hop_s = win_s / 2 # hop size
+hop_s = win_s // 2 # hop size
if len(sys.argv) < 2:
- print "Usage: %s <filename> [samplerate]" % sys.argv[0]
+ print("Usage: %s <filename> [samplerate]" % sys.argv[0])
sys.exit(1)
filename = sys.argv[1]
while True:
samples, read = s()
if o(samples):
- print "%f" % (o.get_last_s())
+ print("%f" % (o.get_last_s()))
onsets.append(o.get_last())
# keep some data to plot it later
- new_maxes = (abs(samples.reshape(hop_s/downsample, downsample))).max(axis=0)
+ new_maxes = (abs(samples.reshape(hop_s//downsample, downsample))).max(axis=0)
allsamples_max = hstack([allsamples_max, new_maxes])
desc.append(o.get_descriptor())
tdesc.append(o.get_thresholded_descriptor())
if 1:
# do plotting
- from numpy import arange
import matplotlib.pyplot as plt
allsamples_max = (allsamples_max > 0) * allsamples_max
allsamples_max_times = [ float(t) * hop_s / downsample / samplerate for t in range(len(allsamples_max)) ]
plt1.xaxis.set_visible(False)
plt1.yaxis.set_visible(False)
desc_times = [ float(t) * hop_s / samplerate for t in range(len(desc)) ]
- desc_plot = [d / max(desc) for d in desc]
+ desc_max = max(desc) if max(desc) != 0 else 1.
+ desc_plot = [d / desc_max for d in desc]
plt2.plot(desc_times, desc_plot, '-g')
- tdesc_plot = [d / max(desc) for d in tdesc]
+ tdesc_plot = [d / desc_max for d in tdesc]
for stamp in onsets:
stamp /= float(samplerate)
plt2.plot([stamp, stamp], [min(tdesc_plot), max(desc_plot)], '-r')
#! /usr/bin/env python
import sys
-from aubio import source, pitch, freqtomidi
+from aubio import source, pitch
if len(sys.argv) < 2:
- print "Usage: %s <filename> [samplerate]" % sys.argv[0]
+ print("Usage: %s <filename> [samplerate]" % sys.argv[0])
sys.exit(1)
filename = sys.argv[1]
downsample = 1
-samplerate = 44100 / downsample
+samplerate = 44100 // downsample
if len( sys.argv ) > 2: samplerate = int(sys.argv[2])
-win_s = 4096 / downsample # fft size
-hop_s = 512 / downsample # hop size
+win_s = 4096 // downsample # fft size
+hop_s = 512 // downsample # hop size
s = source(filename, samplerate, hop_s)
samplerate = s.samplerate
#pitch = int(round(pitch))
confidence = pitch_o.get_confidence()
#if confidence < 0.8: pitch = 0.
- #print "%f %f %f" % (total_frames / float(samplerate), pitch, confidence)
+ print("%f %f %f" % (total_frames / float(samplerate), pitch, confidence))
pitches += [pitch]
confidences += [confidence]
total_frames += read
if 0: sys.exit(0)
#print pitches
+import os.path
from numpy import array, ma
import matplotlib.pyplot as plt
from demo_waveform_plot import get_waveform_plot, set_xlabels_sample2time
ax1.set_xlabel('')
def array_from_text_file(filename, dtype = 'float'):
- import os.path
- from numpy import array
filename = os.path.join(os.path.dirname(__file__), filename)
return array([line.split() for line in open(filename).readlines()],
dtype = dtype)
ax2 = fig.add_subplot(312, sharex = ax1)
-import sys, os.path
ground_truth = os.path.splitext(filename)[0] + '.f0.Corrected'
if os.path.isfile(ground_truth):
ground_truth = array_from_text_file(ground_truth)
#! /usr/bin/env python
-from numpy import random, sin, arange, ones, zeros
-from math import pi
-from aubio import fvec, pitch
+import numpy as np
+import aubio
def build_sinusoid(length, freqs, samplerate):
- return sin( 2. * pi * arange(length) * freqs / samplerate)
+ return np.sin( 2. * np.pi * np.arange(length) * freqs / samplerate).astype(aubio.float_type)
def run_pitch(p, input_vec):
- f = fvec (p.hop_size)
- cands = []
- count = 0
- for vec_slice in input_vec.reshape((-1, p.hop_size)):
- f[:] = vec_slice
- cands.append(p(f))
- return cands
+ cands = []
+ for vec_slice in input_vec.reshape((-1, p.hop_size)):
+ a = p(vec_slice)[0]
+ cands.append(a)
+ return cands
methods = ['default', 'schmitt', 'fcomb', 'mcomb', 'yin', 'yinfft']
hop_size = 512
samplerate = 44100
sin_length = (samplerate * 10) % 512 * 512
-freqs = zeros(sin_length)
+freqs = np.zeros(sin_length)
-partition = sin_length / 8
+partition = sin_length // 8
pointer = 0
pointer += partition
pointer += partition
pointer += partition
-freqs[ pointer : pointer + partition ] = 400 + 5 * random.random(sin_length/8)
+freqs[ pointer : pointer + partition ] = 400 + 5 * np.random.random(sin_length/8)
a = build_sinusoid(sin_length, freqs, samplerate)
for method in methods:
- p = pitch(method, buf_size, hop_size, samplerate)
- cands[method] = run_pitch(p, a)
+ p = aubio.pitch(method, buf_size, hop_size, samplerate)
+ cands[method] = run_pitch(p, a)
+ print(method)
+ print(cands[method])
-print "done computing"
+print("done computing")
if 1:
- from pylab import plot, show, xlabel, ylabel, legend, ylim
- ramp = arange(0, sin_length / hop_size).astype('float') * hop_size / samplerate
- for method in methods:
- plot(ramp, cands[method],'.-')
+ import matplotlib.pyplot as plt
- # plot ground truth
- ramp = arange(0, sin_length).astype('float') / samplerate
- plot(ramp, freqs, ':')
+ # times
+ ramp = np.arange(0, sin_length / hop_size).astype('float') * hop_size / samplerate
- legend(methods+['ground truth'], 'upper right')
- xlabel('time (s)')
- ylabel('frequency (Hz)')
- ylim([0,2000])
- show()
+ # plot each result
+ for method in methods:
+ plt.plot(ramp, cands[method], '.-', label=method)
+ # plot ground truth
+ ramp = np.arange(0, sin_length).astype('float') / samplerate
+ plt.plot(ramp, freqs, ':', label = 'ground truth')
+
+ plt.legend(loc='upper left')
+
+ plt.xlabel('time (s)')
+ plt.ylabel('frequency (Hz)')
+ plt.ylim([0,2000])
+ plt.show()
--- /dev/null
+#! /usr/bin/env python
+
+# Use pyaudio to open the microphone and run aubio.pitch on the stream of
+# incoming samples. If a filename is given as the first argument, it will
+# record 5 seconds of audio to this location. Otherwise, the script will
+# run until Ctrl+C is pressed.
+
+# Examples:
+# $ ./python/demos/demo_pyaudio.py
+# $ ./python/demos/demo_pyaudio.py /tmp/recording.wav
+
+import pyaudio
+import sys
+import numpy as np
+import aubio
+
+# initialise pyaudio
+p = pyaudio.PyAudio()
+
+# open stream
+buffer_size = 1024
+pyaudio_format = pyaudio.paFloat32
+n_channels = 1
+samplerate = 44100
+stream = p.open(format=pyaudio_format,
+ channels=n_channels,
+ rate=samplerate,
+ input=True,
+ frames_per_buffer=buffer_size)
+
+if len(sys.argv) > 1:
+ # record 5 seconds
+ output_filename = sys.argv[1]
+ record_duration = 5 # exit 1
+ outputsink = aubio.sink(sys.argv[1], samplerate)
+ total_frames = 0
+else:
+ # run forever
+ outputsink = None
+ record_duration = None
+
+# setup pitch
+tolerance = 0.8
+win_s = 4096 # fft size
+hop_s = buffer_size # hop size
+pitch_o = aubio.pitch("default", win_s, hop_s, samplerate)
+pitch_o.set_unit("midi")
+pitch_o.set_tolerance(tolerance)
+
+print("*** starting recording")
+while True:
+ try:
+ audiobuffer = stream.read(buffer_size)
+ signal = np.fromstring(audiobuffer, dtype=np.float32)
+
+ pitch = pitch_o(signal)[0]
+ confidence = pitch_o.get_confidence()
+
+ print("{} / {}".format(pitch,confidence))
+
+ if outputsink:
+ outputsink(signal, len(signal))
+
+ if record_duration:
+ total_frames += len(signal)
+ if record_duration * samplerate < total_frames:
+ break
+ except KeyboardInterrupt:
+ print("*** Ctrl+C pressed, exiting")
+ break
+
+print("*** done recording")
+stream.stop_stream()
+stream.close()
+p.terminate()
duration = 5 # in seconds
s = Stream(blocksize = hop_size, channels = 1)
g = sink(sink_path, samplerate = int(s.samplerate))
- print s.channels
s.start()
total_frames = 0
mono_vec = vec.sum(-1) / float(s.channels[0])
g(mono_vec, hop_size)
total_frames += hop_size
- except KeyboardInterrupt, e:
- print "stopped after", "%.2f seconds" % (total_frames / s.samplerate)
- pass
+ except KeyboardInterrupt:
+ duration = total_frames / float(s.samplerate)
+ print("stopped after %.2f seconds" % duration)
s.stop()
if __name__ == '__main__':
--- /dev/null
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+
+Compare the speed of several methods for reading and loading a sound file.
+
+Optionally, this file can make use of the following packages:
+
+ - audioread https://github.com/beetbox/audioread
+ - scipy https://scipy.org
+ - librosa https://github.com/bmcfee/librosa
+ - pydub https://github.com/jiaaro/pydub
+
+Uncomment the function names below and send us your speed results!
+
+"""
+
+
+test_functions = [
+ "read_file_aubio",
+ "load_file_aubio",
+ #"load_file_scipy",
+ #"load_file_scipy_mmap",
+ #"read_file_audioread",
+ #"load_file_librosa",
+ #"read_file_pydub",
+ #"load_file_pydub",
+ ]
+
+
+import numpy as np
+
+def read_file_audioread(filename):
+ import audioread
+ # taken from librosa.util.utils
+ def convert_buffer_to_float(buf, n_bytes = 2, dtype = np.float32):
+ # Invert the scale of the data
+ scale = 1./float(1 << ((8 * n_bytes) - 1))
+ # Construct the format string
+ fmt = '<i{:d}'.format(n_bytes)
+ # Rescale and format the data buffer
+ out = scale * np.frombuffer(buf, fmt).astype(dtype)
+ return out
+
+ with audioread.audio_open(filename) as f:
+ total_frames = 0
+ for buf in f:
+ samples = convert_buffer_to_float(buf)
+ samples = samples.reshape(f.channels, -1)
+ total_frames += samples.shape[1]
+ return total_frames, f.samplerate
+
+def load_file_librosa(filename):
+ import librosa
+ y, sr = librosa.load(filename, sr = None)
+ #print y.mean(), y.shape
+ return len(y), sr
+
+def load_file_scipy(filename):
+ import scipy.io.wavfile
+ sr, y = scipy.io.wavfile.read(filename)
+ y = y.astype('float32') / 32767
+ #print y.mean(), y.shape
+ return len(y), sr
+
+def load_file_scipy_mmap(filename):
+ import scipy.io.wavfile
+ sr, y = scipy.io.wavfile.read(filename, mmap = True)
+ #print y.mean(), y.shape
+ return len(y), sr
+
+def read_file_pydub(filename):
+ from pydub import AudioSegment
+ song = AudioSegment.from_file(filename)
+ song.get_array_of_samples()
+ return song.frame_count(), song.frame_rate
+
+def load_file_pydub(filename):
+ from pydub import AudioSegment
+ song = AudioSegment.from_file(filename)
+ y = np.asarray(song.get_array_of_samples(), dtype = 'float32')
+ y = y.reshape(song.channels, -1) / 32767.
+ return song.frame_count(), song.frame_rate
+
+def read_file_aubio(filename):
+ import aubio
+ f = aubio.source(filename, hop_size = 1024)
+ total_frames = 0
+ while True:
+ _, read = f()
+ total_frames += read
+ if read < f.hop_size: break
+ return total_frames, f.samplerate
+
+def load_file_aubio(filename):
+ import aubio
+ f = aubio.source(filename, hop_size = 1024)
+ y = np.zeros(f.duration, dtype = aubio.float_type)
+ total_frames = 0
+ while True:
+ samples, read = f()
+ y[total_frames:total_frames + read] = samples[:read]
+ total_frames += read
+ if read < f.hop_size: break
+ assert len(y) == total_frames
+ #print y.mean(), y.shape
+ return total_frames, f.samplerate
+
+def test_speed(function, filename):
+ times = []
+ for _ in range(10):
+ start = time.time()
+ try:
+ total_frames, samplerate = function(filename)
+ except ImportError as e:
+ print ("error: failed importing {:s}".format(e))
+ return
+ elapsed = time.time() - start
+ #print ("{:5f} ".format(elapsed)),
+ times.append(elapsed)
+
+ #print
+ times = np.array(times)
+ duration_min = int(total_frames/float(samplerate) // 60)
+ str_format = '{:25s} took {:5f} seconds avg (±{:5f}) to run on a ~ {:d} minutes long file'
+ print (str_format.format(function.__name__, times.mean(), times.std(), duration_min ))
+
+if __name__ == '__main__':
+ import sys, time
+ if len(sys.argv) < 2:
+ print ("not enough arguments")
+ sys.exit(1)
+ filename = sys.argv[1]
+
+ for f in test_functions:
+ # get actual function from globals
+ test_function = globals()[f]
+ test_speed(test_function, filename)
from aubio import source, sink, pvoc
if __name__ == '__main__':
- if len(sys.argv) < 2:
- print 'usage: %s <inputfile> <outputfile>' % sys.argv[0]
- sys.exit(1)
- samplerate = 44100
- f = source(sys.argv[1], samplerate, 256)
- g = sink(sys.argv[2], samplerate)
- total_frames, read = 0, 256
+ if len(sys.argv) < 2:
+ print('usage: %s <inputfile> <outputfile>' % sys.argv[0])
+ sys.exit(1)
+ samplerate = 44100
+ f = source(sys.argv[1], samplerate, 256)
+ g = sink(sys.argv[2], samplerate)
+ total_frames, read = 0, 256
- win_s = 512 # fft size
- hop_s = win_s / 2 # hop size
- pv = pvoc(win_s, hop_s) # phase vocoder
+ win_s = 512 # fft size
+ hop_s = win_s // 2 # hop size
+ pv = pvoc(win_s, hop_s) # phase vocoder
- while read:
- samples, read = f()
- spectrum = pv(samples) # compute spectrum
- #spectrum.norm *= .8 # reduce amplitude a bit
- spectrum.phas[:] = 0. # zero phase
- new_samples = pv.rdo(spectrum) # compute modified samples
- g(new_samples, read) # write to output
- total_frames += read
+ while read:
+ samples, read = f()
+ spectrum = pv(samples) # compute spectrum
+ #spectrum.norm *= .8 # reduce amplitude a bit
+ spectrum.phas[:] = 0. # zero phase
+ new_samples = pv.rdo(spectrum) # compute modified samples
+ g(new_samples, read) # write to output
+ total_frames += read
- print "wrote", total_frames, "from", f.uri, "to", g.uri
-
-
+ format_str = "read {:d} samples from {:s}, written to {:s}"
+ print(format_str.format(total_frames, f.uri, g.uri))
if __name__ == '__main__':
if len(sys.argv) < 2:
- print 'usage: %s <inputfile> <outputfile>' % sys.argv[0]
+ print('usage: %s <inputfile> <outputfile>' % sys.argv[0])
sys.exit(1)
samplerate = 0
if len(sys.argv) > 3: samplerate = int(sys.argv[3])
g = sink(sys.argv[2], samplerate)
win_s = 512 # fft size
- hop_s = win_s / 2 # hop size
+ hop_s = win_s // 2 # hop size
pv = pvoc(win_s, hop_s) # phase vocoder
# spectral weighting vector
.8 * hanningz(80)[40:],
zeros( 50 ),
1.3 * hanningz(100),
- zeros (win_s / 2 + 1 - 40 - 50 - 100),
+ zeros (win_s // 2 + 1 - 40 - 50 - 100),
] )
if 0:
g(new_samples, read)
total_frames += read
- print "read", total_frames / float(samplerate), "seconds from", f.uri
+ duration = total_frames / float(samplerate)
+ print("read {:.3f}s from {:s}".format(duration, f.uri))
if __name__ == '__main__':
if len(sys.argv) < 3:
- print 'usage: %s <inputfile> <outputfile> [samplerate] [hop_size]' % sys.argv[0]
+ print('usage: %s <inputfile> <outputfile> [samplerate] [hop_size]' % sys.argv[0])
sys.exit(1)
if len(sys.argv) > 3: samplerate = int(sys.argv[3])
vec, read = f()
g(vec, read)
total_frames += read
- print "wrote", "%.2fs" % (total_frames / float(samplerate) ),
- print "(", total_frames, "frames", "in",
- print total_frames / f.hop_size, "blocks", "at", "%dHz" % f.samplerate, ")",
- print "from", f.uri,
- print "to", g.uri
+ outstr = "wrote %.2fs" % (total_frames / float(samplerate))
+ outstr += " (%d frames in" % total_frames
+ outstr += " %d blocks" % (total_frames // f.hop_size)
+ outstr += " at %dHz)" % f.samplerate
+ outstr += " from " + f.uri
+ outstr += " to " + g.uri
+ print(outstr)
import sys
from math import pi, e
-from aubio import sink
-from numpy import arange, resize, sin, exp, zeros
+from aubio import sink, float_type
+from numpy import arange, sin, exp, zeros
if len(sys.argv) < 2:
- print 'usage: %s <outputfile> [samplerate]' % sys.argv[0]
+ print('usage: %s <outputfile> [samplerate]' % sys.argv[0])
sys.exit(1)
samplerate = 44100 # samplerate in Hz
period = float(samplerate) / pitch
# create a sine lookup table
tablelen = 1000
-sinetable = arange(tablelen + 1, dtype = 'float32')
+sinetable = arange(tablelen + 1, dtype = float_type)
sinetable = 0.7 * sin(twopi * sinetable/tablelen)
-sinetone = zeros((duration,), dtype = 'float32')
+sinetone = zeros((duration,), dtype = float_type)
# compute sinetone at floating point period
for i in range(duration):
sinetone[i] = a + frac * (b -a)
# apply some envelope
-float_ramp = arange(duration, dtype = 'float32')
+float_ramp = arange(duration, dtype = float_type)
sinetone *= exp( - e * float_ramp / duration / decay)
sinetone[:attack] *= exp( e * ( float_ramp[:attack] / attack - 1 ) )
if __name__ == '__main__':
if len(sys.argv) < 3:
- print 'usage: %s <inputfile> <outputfile> [samplerate] [hop_size]' % sys.argv[0]
+ print('usage: %s <inputfile> <outputfile> [samplerate] [hop_size]' % sys.argv[0])
sys.exit(1)
if len(sys.argv) > 3: samplerate = int(sys.argv[3])
vec, read = f.do_multi()
g.do_multi(vec, read)
total_frames += read
- print "wrote", "%.2fs" % (total_frames / float(samplerate) ),
- print "(", total_frames, "frames", "in",
- print total_frames / f.hop_size, "blocks",
- print "of", f.channels, "channels",
- print "at", "%dHz" % f.samplerate, ")",
- print "from", f.uri,
- print "to", g.uri
+ outstr = "wrote %.2fs" % (total_frames / float(samplerate))
+ outstr += " (%d frames in" % total_frames
+ outstr += " %d blocks" % (total_frames // f.hop_size)
+ outstr += " of %d channels" % f.channels
+ outstr += " at %dHz)" % f.samplerate
+ outstr += " from " + f.uri
+ outstr += " to " + g.uri
+ print(outstr)
if __name__ == '__main__':
if len(sys.argv) < 3:
- print 'usage: %s <inputfile> <duration>' % sys.argv[0]
+ print('usage: %s <inputfile> <duration>' % sys.argv[0])
sys.exit(1)
source_file = sys.argv[1]
duration = float(sys.argv[2])
total_frames_written += read
total_duration = total_frames_written / float(samplerate)
slice_n += 1
- print 'created %(slice_n)s slices from %(source_base_name)s%(source_ext)s' % locals(),
- print ' (total duration %(total_duration).2fs)' % locals()
+ outstr = 'created %(slice_n)s slices from %(source_base_name)s%(source_ext)s' % locals()
+ outstr += ' (total duration %(total_duration).2fs)' % locals()
+ print(outstr)
# close source and sink files
del f, g
if __name__ == '__main__':
if len(sys.argv) < 2:
- print 'usage: %s <inputfile> [samplerate] [hop_size]' % sys.argv[0]
+ print('usage: %s <inputfile> [samplerate] [hop_size]' % sys.argv[0])
sys.exit(1)
samplerate = 0
hop_size = 256
vec, read = f()
total_frames += read
if read < f.hop_size: break
- print "read", "%.2fs" % (total_frames / float(samplerate) ),
- print "(", total_frames, "frames", "in",
- print total_frames / f.hop_size, "blocks", "at", "%dHz" % f.samplerate, ")",
- print "from", f.uri
+ outstr = "read %.2fs" % (total_frames / float(samplerate))
+ outstr += " (%d frames in" % total_frames
+ outstr += " %d blocks" % (total_frames // f.hop_size)
+ outstr += " at %dHz)" % f.samplerate
+ outstr += " from " + f.uri
+ print(outstr)
--- /dev/null
+#! /usr/bin/env python
+import sys, aubio
+
+samplerate = 0 # use original source samplerate
+hop_size = 256 # number of frames to read in one block
+s = aubio.source(sys.argv[1], samplerate, hop_size)
+total_frames = 0
+
+while True: # reading loop
+ samples, read = s()
+ total_frames += read
+ if read < hop_size: break # end of file reached
+
+fmt_string = "read {:d} frames at {:d}Hz from {:s}"
+print (fmt_string.format(total_frames, s.samplerate, sys.argv[1]))
+
#! /usr/bin/env python
import sys
-from aubio import fvec, source, pvoc, specdesc
-from numpy import hstack
+import numpy as np
+from aubio import source, pvoc, specdesc
win_s = 512 # fft size
-hop_s = win_s / 4 # hop size
+hop_s = win_s // 4 # hop size
if len(sys.argv) < 2:
- print "Usage: %s <filename> [samplerate]" % sys.argv[0]
+ print("Usage: %s <filename> [samplerate]" % sys.argv[0])
sys.exit(1)
filename = sys.argv[1]
for method in methods:
cands = []
- all_descs[method] = fvec(0)
+ all_descs[method] = np.array([])
o[method] = specdesc(method, win_s)
total_frames = 0
while True:
samples, read = s()
fftgrain = pv(samples)
- #print "%f" % ( total_frames / float(samplerate) ),
+ #outstr = "%f" % ( total_frames / float(samplerate) )
for method in methods:
specdesc_val = o[method](fftgrain)[0]
- all_descs[method] = hstack ( [all_descs[method], specdesc_val] )
- #print "%f" % specdesc_val,
- #print
+ all_descs[method] = np.append(all_descs[method], specdesc_val)
+ #outstr += " %f" % specdesc_val
+ #print(outstr)
total_frames += read
if read < hop_s: break
if 1:
- print "done computing, now plotting"
+ print("done computing, now plotting")
import matplotlib.pyplot as plt
from demo_waveform_plot import get_waveform_plot
from demo_waveform_plot import set_xlabels_sample2time
#! /usr/bin/env python
-import sys
-from aubio import pvoc, source
-from numpy import array, arange, zeros, shape, log10, vstack
-from pylab import imshow, show, cm, axis, ylabel, xlabel, xticks, yticks
+import sys, os.path
+from aubio import pvoc, source, float_type
+from numpy import zeros, log10, vstack
+import matplotlib.pyplot as plt
def get_spectrogram(filename, samplerate = 0):
- win_s = 512 # fft window size
- hop_s = win_s / 2 # hop size
- fft_s = win_s / 2 + 1 # spectrum bins
+ win_s = 512 # fft window size
+ hop_s = win_s // 2 # hop size
+ fft_s = win_s // 2 + 1 # spectrum bins
- a = source(filename, samplerate, hop_s) # source file
- if samplerate == 0: samplerate = a.samplerate
- pv = pvoc(win_s, hop_s) # phase vocoder
- specgram = zeros([0, fft_s], dtype='float32') # numpy array to store spectrogram
+ a = source(filename, samplerate, hop_s) # source file
+ if samplerate == 0: samplerate = a.samplerate
+ pv = pvoc(win_s, hop_s) # phase vocoder
+ specgram = zeros([0, fft_s], dtype=float_type) # numpy array to store spectrogram
- # analysis
- while True:
- samples, read = a() # read file
- specgram = vstack((specgram,pv(samples).norm)) # store new norm vector
- if read < a.hop_size: break
+ # analysis
+ while True:
+ samples, read = a() # read file
+ specgram = vstack((specgram,pv(samples).norm)) # store new norm vector
+ if read < a.hop_size: break
- # plotting
- imshow(log10(specgram.T + .001), origin = 'bottom', aspect = 'auto', cmap=cm.gray_r)
- axis([0, len(specgram), 0, len(specgram[0])])
- # show axes in Hz and seconds
- time_step = hop_s / float(samplerate)
- total_time = len(specgram) * time_step
- print "total time: %0.2fs" % total_time,
- print ", samplerate: %.2fkHz" % (samplerate / 1000.)
- n_xticks = 10
- n_yticks = 10
+ # plotting
+ fig = plt.imshow(log10(specgram.T + .001), origin = 'bottom', aspect = 'auto', cmap=plt.cm.gray_r)
+ ax = fig.axes
+ ax.axis([0, len(specgram), 0, len(specgram[0])])
+ # show axes in Hz and seconds
+ time_step = hop_s / float(samplerate)
+ total_time = len(specgram) * time_step
+ outstr = "total time: %0.2fs" % total_time
+ print(outstr + ", samplerate: %.2fkHz" % (samplerate / 1000.))
+ n_xticks = 10
+ n_yticks = 10
- def get_rounded_ticks( top_pos, step, n_ticks ):
- top_label = top_pos * step
- # get the first label
- ticks_first_label = top_pos * step / n_ticks
- # round to the closest .1
- ticks_first_label = round ( ticks_first_label * 10. ) / 10.
- # compute all labels from the first rounded one
- ticks_labels = [ ticks_first_label * n for n in range(n_ticks) ] + [ top_label ]
- # get the corresponding positions
- ticks_positions = [ ticks_labels[n] / step for n in range(n_ticks) ] + [ top_pos ]
- # convert to string
- ticks_labels = [ "%.1f" % x for x in ticks_labels ]
- # return position, label tuple to use with x/yticks
- return ticks_positions, ticks_labels
-
- # apply to the axis
- xticks( *get_rounded_ticks ( len(specgram), time_step, n_xticks ) )
- yticks( *get_rounded_ticks ( len(specgram[0]), (samplerate / 2. / 1000.) / len(specgram[0]), n_yticks ) )
- ylabel('Frequency (kHz)')
- xlabel('Time (s)')
+ def get_rounded_ticks( top_pos, step, n_ticks ):
+ top_label = top_pos * step
+ # get the first label
+ ticks_first_label = top_pos * step / n_ticks
+ # round to the closest .1
+ ticks_first_label = round ( ticks_first_label * 10. ) / 10.
+ # compute all labels from the first rounded one
+ ticks_labels = [ ticks_first_label * n for n in range(n_ticks) ] + [ top_label ]
+ # get the corresponding positions
+ ticks_positions = [ ticks_labels[n] / step for n in range(n_ticks) ] + [ top_pos ]
+ # convert to string
+ ticks_labels = [ "%.1f" % x for x in ticks_labels ]
+ # return position, label tuple to use with x/yticks
+ return ticks_positions, ticks_labels
+
+ # apply to the axis
+ x_ticks, x_labels = get_rounded_ticks ( len(specgram), time_step, n_xticks )
+ y_ticks, y_labels = get_rounded_ticks ( len(specgram[0]), (samplerate / 1000. / 2.) / len(specgram[0]), n_yticks )
+ ax.set_xticks( x_ticks )
+ ax.set_yticks ( y_ticks )
+ ax.set_xticklabels( x_labels )
+ ax.set_yticklabels ( y_labels )
+ ax.set_ylabel('Frequency (kHz)')
+ ax.set_xlabel('Time (s)')
+ ax.set_title(os.path.basename(filename))
+ for item in ([ax.title, ax.xaxis.label, ax.yaxis.label] +
+ ax.get_xticklabels() + ax.get_yticklabels()):
+ item.set_fontsize('x-small')
+ return fig
if __name__ == '__main__':
- if len(sys.argv) < 2:
- print "Usage: %s <filename>" % sys.argv[0]
- else:
- for soundfile in sys.argv[1:]:
- get_spectrogram(soundfile)
- # display graph
- show()
+ if len(sys.argv) < 2:
+ print("Usage: %s <filename>" % sys.argv[0])
+ else:
+ for soundfile in sys.argv[1:]:
+ fig = get_spectrogram(soundfile)
+ # display graph
+ plt.show()
+ #outimage = os.path.basename(soundfile) + '.png'
+ #print ("writing: " + outimage)
+ #plt.savefig(outimage)
+ plt.close()
from aubio import tempo, source
win_s = 512 # fft size
-hop_s = win_s / 2 # hop size
+hop_s = win_s // 2 # hop size
if len(sys.argv) < 2:
- print "Usage: %s <filename> [samplerate]" % sys.argv[0]
+ print("Usage: %s <filename> [samplerate]" % sys.argv[0])
sys.exit(1)
filename = sys.argv[1]
is_beat = o(samples)
if is_beat:
this_beat = int(total_frames - delay + is_beat[0] * hop_s)
- print "%f" % (this_beat / float(samplerate))
+ print("%f" % (this_beat / float(samplerate)))
beats.append(this_beat)
total_frames += read
if read < hop_s: break
from aubio import tempo, source
win_s = 512 # fft size
-hop_s = win_s / 2 # hop size
+hop_s = win_s // 2 # hop size
if len(sys.argv) < 2:
- print "Usage: %s <filename> [samplerate]" % sys.argv[0]
+ print("Usage: %s <filename> [samplerate]" % sys.argv[0])
sys.exit(1)
filename = sys.argv[1]
if len(beats) > 1:
# do plotting
- from numpy import array, arange, mean, median, diff
+ from numpy import mean, median, diff
import matplotlib.pyplot as plt
bpms = 60./ diff(beats)
- print 'mean period:', "%.2f" % mean(bpms), 'bpm', 'median', "%.2f" % median(bpms), 'bpm'
- print 'plotting', filename
+ print('mean period: %.2fbpm, median: %.2fbpm' % (mean(bpms), median(bpms)))
+ print('plotting %s' % filename)
plt1 = plt.axes([0.1, 0.75, 0.8, 0.19])
plt2 = plt.axes([0.1, 0.1, 0.8, 0.65], sharex = plt1)
plt.rc('lines',linewidth='.8')
plt.show()
else:
- print 'mean period:', "%.2f" % 0, 'bpm', 'median', "%.2f" % 0, 'bpm',
- print 'nothing to plot, file too short?'
+ print('mean period: %.2fbpm, median: %.2fbpm' % (0, 0))
+ print('plotting %s' % filename)
--- /dev/null
+#! /usr/bin/env python
+
+# Implementation of the timescale algorithm according to Dan Ellis, *A Phase
+# Vocoder in Matlab*. http://www.ee.columbia.edu/~dpwe/resources/matlab/pvoc/
+
+# This file follows the original implementation, with analysis in a first pass,
+# and synthesis in a second pass.
+
+import sys
+from aubio import source, sink, pvoc, cvec
+from aubio import unwrap2pi, float_type
+import numpy as np
+
+win_s = 1024
+hop_s = win_s // 8 # 87.5 % overlap
+
+warmup = win_s // hop_s - 1
+
+if len(sys.argv) < 3:
+ print("Usage: {:s} <source_filename> <output_filename> <rate> [samplerate]".format(sys.argv[0]))
+ print("""Examples:
+ # twice faster
+ {0} track_01.mp3 track_01_faster.wav 2.0
+ # twice slower
+ {0} track_02.flac track_02_slower.wav 0.5
+ # one and a half time faster, resampling first the input to 22050
+ {0} track_02.flac track_02_slower.wav 1.5 22050""".format(sys.argv[0]))
+ sys.exit(1)
+
+source_filename = sys.argv[1]
+output_filename = sys.argv[2]
+rate = float(sys.argv[3])
+
+samplerate = 0 if len(sys.argv) < 5 else int(sys.argv[4])
+source_in = source(source_filename, samplerate, hop_s)
+samplerate = source_in.samplerate
+p = pvoc(win_s, hop_s)
+
+# allocate memory to store norms and phases
+n_blocks = source_in.duration // hop_s + 1
+# adding an empty frame at end of spectrogram
+norms = np.zeros((n_blocks + 1, win_s // 2 + 1), dtype = float_type)
+phases = np.zeros((n_blocks + 1, win_s // 2 + 1), dtype = float_type)
+
+block_read = 0
+while True:
+ # read from source
+ samples, read = source_in()
+ # compute fftgrain
+ spec = p(samples)
+ # store current grain
+ norms[block_read] = spec.norm
+ phases[block_read] = spec.phas
+ # until end of file
+ if read < hop_s: break
+ # increment block counter
+ block_read += 1
+
+# just to make sure
+#source_in.close()
+
+sink_out = sink(output_filename, samplerate)
+
+# interpolated time steps (j = alpha * i)
+steps = np.arange(0, n_blocks, rate, dtype = float_type)
+# initial phase
+phas_acc = phases[0]
+# excepted phase advance in each bin
+phi_advance = np.linspace(0, np.pi * hop_s, win_s / 2 + 1).astype (float_type)
+
+new_grain = cvec(win_s)
+
+for (t, step) in enumerate(steps):
+
+ frac = 1. - np.mod(step, 1.0)
+ # get pair of frames
+ t_norms = norms[int(step):int(step+2)]
+ t_phases = phases[int(step):int(step+2)]
+
+ # compute interpolated frame
+ new_grain.norm = frac * t_norms[0] + (1. - frac) * t_norms[1]
+ new_grain.phas = phas_acc
+ #print t, step, new_grain.norm
+ #print t, step, phas_acc
+
+ # psola
+ samples = p.rdo(new_grain)
+ if t > warmup: # skip the first few frames to warm up phase vocoder
+ # write to sink
+ sink_out(samples, hop_s)
+
+ # calculate phase advance
+ dphas = t_phases[1] - t_phases[0] - phi_advance
+ # unwrap angle to [-pi; pi]
+ dphas = unwrap2pi(dphas)
+ # cumulate phase, to be used for next frame
+ phas_acc += phi_advance + dphas
+
+for t in range(warmup + 1): # purge the last frames from the phase vocoder
+ new_grain.norm[:] = 0
+ new_grain.phas[:] = 0
+ samples = p.rdo(new_grain)
+ sink_out(samples, read if t == warmup else hop_s)
+
+# just to make sure
+#sink_out.close()
+
+format_out = "read {:d} blocks from {:s} at {:d}Hz and rate {:f}, wrote {:d} blocks to {:s}"
+print (format_out.format(block_read, source_filename, samplerate, rate,
+ len(steps), output_filename))
--- /dev/null
+#! /usr/bin/env python
+
+# Implementation of the timescale algorithm according to Dan Ellis, *A Phase
+# Vocoder in Matlab*. http://www.ee.columbia.edu/~dpwe/resources/matlab/pvoc/
+
+# This file performs both analysis and synthesis in a single pass. See also
+# `demo_timestretch.py` for a version following the original implementation.
+
+import sys
+from aubio import source, sink, pvoc, cvec
+from aubio import unwrap2pi, float_type
+import numpy as np
+
+win_s = 512
+hop_s = win_s // 8 # 87.5 % overlap
+
+warmup = win_s // hop_s - 1
+
+if len(sys.argv) < 3:
+ print("Usage: {:s} <source_filename> <output_filename> <rate> [samplerate]".format(sys.argv[0]))
+ print("""Examples:
+ # twice faster
+ {0} track_01.mp3 track_01_faster.wav 2.0
+ # twice slower
+ {0} track_02.flac track_02_slower.wav 0.5
+ # one and a half time faster, resampling first the input to 22050
+ {0} track_02.flac track_02_slower.wav 1.5 22050""".format(sys.argv[0]))
+ sys.exit(1)
+
+source_filename = sys.argv[1]
+output_filename = sys.argv[2]
+rate = float(sys.argv[3])
+
+samplerate = 0 if len(sys.argv) < 5 else int(sys.argv[4])
+source_in = source(source_filename, samplerate, hop_s)
+samplerate = source_in.samplerate
+p = pvoc(win_s, hop_s)
+
+sink_out = sink(output_filename, samplerate)
+
+# excepted phase advance in each bin
+phi_advance = np.linspace(0, np.pi * hop_s, win_s / 2 + 1).astype (float_type)
+
+old_grain = cvec(win_s)
+new_grain = cvec(win_s)
+
+block_read = 0
+interp_read = 0
+interp_block = 0
+while True:
+
+ samples, read = source_in()
+ cur_grain = p(samples)
+
+ if block_read == 1:
+ phas_acc = old_grain.phas
+
+ #print "block_read", block_read
+ while True and (block_read > 0):
+ if interp_read >= block_read:
+ break
+ #print "`--- interp_block:", interp_block,
+ #print 'at orig_block', interp_read, '<- from', block_read - 1, block_read,
+ #print 'old_grain', old_grain, 'cur_grain', cur_grain
+ # time to compute interp grain
+ frac = 1. - np.mod(interp_read, 1.0)
+
+ # compute interpolated frame
+ new_grain.norm = frac * old_grain.norm + (1. - frac) * cur_grain.norm
+ new_grain.phas = phas_acc
+
+ # psola
+ samples = p.rdo(new_grain)
+ if interp_read > warmup: # skip the first frames to warm up phase vocoder
+ # write to sink
+ sink_out(samples, hop_s)
+
+ # calculate phase advance
+ dphas = cur_grain.phas - old_grain.phas - phi_advance
+ # unwrap angle to [-pi; pi]
+ dphas = unwrap2pi(dphas)
+ # cumulate phase, to be used for next frame
+ phas_acc += phi_advance + dphas
+
+ # prepare for next interp block
+ interp_block += 1
+ interp_read = interp_block * rate
+ if interp_read >= block_read:
+ break
+
+ # copy cur_grain to old_grain
+ old_grain.norm = np.copy(cur_grain.norm)
+ old_grain.phas = np.copy(cur_grain.phas)
+
+ # until end of file
+ if read < hop_s: break
+ # increment block counter
+ block_read += 1
+
+for t in range(warmup + 2): # purge the last frames from the phase vocoder
+ new_grain.norm[:] = 0
+ new_grain.phas[:] = 0
+ samples = p.rdo(new_grain)
+ sink_out(samples, read if t == warmup + 1 else hop_s)
+
+# just to make sure
+source_in.close()
+sink_out.close()
+
+format_out = "read {:d} blocks from {:s} at {:d}Hz and rate {:f}, wrote {:d} blocks to {:s}"
+print (format_out.format(block_read, source_filename, samplerate, rate,
+ interp_block, output_filename))
from aubio import source, sink, pvoc, tss
if __name__ == '__main__':
- if len(sys.argv) < 2:
- print 'usage: %s <inputfile> <outputfile_transient> <outputfile_steady>' % sys.argv[0]
- sys.exit(1)
-
- samplerate = 44100
- win_s = 1024 # fft size
- hop_s = win_s / 4 # block size
- threshold = 0.5
-
- f = source(sys.argv[1], samplerate, hop_s)
- g = sink(sys.argv[2], samplerate)
- h = sink(sys.argv[3], samplerate)
-
- pva = pvoc(win_s, hop_s) # a phase vocoder
- pvb = pvoc(win_s, hop_s) # another phase vocoder
- t = tss(win_s, hop_s) # transient steady state separation
-
- t.set_threshold(threshold)
-
- read = hop_s
-
- while read:
- samples, read = f() # read file
- spec = pva(samples) # compute spectrum
- trans_spec, stead_spec = t(spec) # transient steady-state separation
- transients = pva.rdo(trans_spec) # overlap-add synthesis of transients
- steadstate = pvb.rdo(stead_spec) # overlap-add synthesis of steady states
- g(transients, read) # write transients to output
- h(steadstate, read) # write steady states to output
-
- del f, g, h # finish writing the files now
-
- from demo_spectrogram import get_spectrogram
- from pylab import subplot, show
- subplot(311)
- get_spectrogram(sys.argv[1])
- subplot(312)
- get_spectrogram(sys.argv[2])
- subplot(313)
- get_spectrogram(sys.argv[3])
- show()
+ if len(sys.argv) < 2:
+ print('usage: %s <inputfile> <outputfile_transient> <outputfile_steady>' % sys.argv[0])
+ sys.exit(1)
+
+ samplerate = 44100
+ win_s = 1024 # fft size
+ hop_s = win_s // 8 # block size
+
+ f = source(sys.argv[1], samplerate, hop_s)
+ g = sink(sys.argv[2], samplerate)
+ h = sink(sys.argv[3], samplerate)
+
+ pva = pvoc(win_s, hop_s) # a phase vocoder
+ pvb = pvoc(win_s, hop_s) # another phase vocoder
+ t = tss(win_s, hop_s) # transient steady state separation
+
+ t.set_threshold(0.01)
+ t.set_alpha(3.)
+ t.set_beta(4.)
+
+ read = hop_s
+
+ while read:
+ samples, read = f() # read file
+ spec = pva(samples) # compute spectrum
+ trans_spec, stead_spec = t(spec) # transient steady-state separation
+ transients = pva.rdo(trans_spec) # overlap-add synthesis of transients
+ steadstate = pvb.rdo(stead_spec) # overlap-add synthesis of steady states
+ g(transients, read) # write transients to output
+ h(steadstate, read) # write steady states to output
+
+ del f, g, h # finish writing the files now
+ sys.exit(0)
+
+ from demo_spectrogram import get_spectrogram
+ from pylab import subplot, show
+ subplot(311)
+ get_spectrogram(sys.argv[1])
+ subplot(312)
+ get_spectrogram(sys.argv[2])
+ subplot(313)
+ get_spectrogram(sys.argv[3])
+ show()
#! /usr/bin/env python
import sys
-from aubio import pvoc, source
+from aubio import source
from numpy import zeros, hstack
def get_waveform_plot(filename, samplerate = 0, block_size = 4096, ax = None, downsample = 2**4):
while True:
samples, read = a()
# keep some data to plot it later
- new_maxes = (abs(samples.reshape(hop_s/downsample, downsample))).max(axis=0)
+ new_maxes = (abs(samples.reshape(hop_s//downsample, downsample))).max(axis=0)
allsamples_max = hstack([allsamples_max, new_maxes])
total_frames += read
if read < hop_s: break
if __name__ == '__main__':
import matplotlib.pyplot as plt
if len(sys.argv) < 2:
- print "Usage: %s <filename>" % sys.argv[0]
+ print("Usage: %s <filename>" % sys.argv[0])
else:
for soundfile in sys.argv[1:]:
get_waveform_plot(soundfile)
#include <Python.h>
#include <structmember.h>
+#include "aubio-generated.h"
+
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
// define numpy unique symbols for aubio
#ifdef USE_LOCAL_AUBIO
#include "aubio.h"
#else
-#include "aubio/aubio.h"
+#include <aubio/aubio.h>
#endif
#define Py_default_vector_length 1024
#define Py_aubio_default_samplerate 44100
#if HAVE_AUBIO_DOUBLE
-#error "Ouch! Python interface for aubio has not been much tested yet."
+// 64 bit precision with HAVE_AUBIO_DOUBLE=1
#define AUBIO_NPY_SMPL NPY_DOUBLE
+#define AUBIO_NPY_SMPL_STR "float64"
+#define AUBIO_NPY_SMPL_CHR "d"
#else
+// default is 32 bit precision
#define AUBIO_NPY_SMPL NPY_FLOAT
+#define AUBIO_NPY_SMPL_STR "float32"
+#define AUBIO_NPY_SMPL_CHR "f"
+#endif
+
+#ifndef PATH_MAX
+#ifdef MAX_PATH
+#define PATH_MAX MAX_PATH
+#else
+#define PATH_MAX 1024
+#endif
+#endif
+
+// compat with Python < 2.6
+#ifndef Py_TYPE
+#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
#endif
-// special python type for cvec
-typedef struct
-{
- PyObject_HEAD
- cvec_t * o;
- uint_t length;
- uint_t channels;
-} Py_cvec;
extern PyTypeObject Py_cvecType;
+PyObject * new_py_fvec(uint_t length);
+PyObject * new_py_cvec(uint_t length);
+PyObject * new_py_fmat(uint_t height, uint_t length);
+
// defined in aubio-proxy.c
+extern int PyAubio_IsValidVector (PyObject *input);
+
extern PyObject *PyAubio_CFvecToArray (fvec_t * self);
-extern fvec_t *PyAubio_ArrayToCFvec (PyObject * self);
+extern int PyAubio_ArrayToCFvec (PyObject * self, fvec_t *out);
-extern Py_cvec *PyAubio_CCvecToPyCvec (cvec_t * self);
-extern cvec_t *PyAubio_ArrayToCCvec (PyObject *input);
+extern int PyAubio_PyCvecToCCvec (PyObject *input, cvec_t *i);
extern PyObject *PyAubio_CFmatToArray (fmat_t * self);
-extern fmat_t *PyAubio_ArrayToCFmat (PyObject *input);
+extern int PyAubio_ArrayToCFmat (PyObject *input, fmat_t *out);
// hand written wrappers
extern PyTypeObject Py_filterType;
#define PY_AUBIO_MODULE_MAIN
#include "aubio-types.h"
-#include "aubio-generated.h"
#include "py-musicutils.h"
+// this dummy macro is used to convince windows that a string passed as -D flag
+// is just that, a string, and not a double.
+#define REDEFINESTRING(x) #x
+#define DEFINEDSTRING(x) REDEFINESTRING(x)
+
static char aubio_module_doc[] = "Python module for the aubio library";
static char Py_alpha_norm_doc[] = ""
"\n"
">>> min_removal(a)";
-extern void add_generated_objects ( PyObject *m );
extern void add_ufuncs ( PyObject *m );
extern int generated_types_ready(void);
Py_alpha_norm (PyObject * self, PyObject * args)
{
PyObject *input;
- fvec_t *vec;
+ fvec_t vec;
smpl_t alpha;
PyObject *result;
- if (!PyArg_ParseTuple (args, "Of:alpha_norm", &input, &alpha)) {
+ if (!PyArg_ParseTuple (args, "O" AUBIO_NPY_SMPL_CHR ":alpha_norm", &input, &alpha)) {
return NULL;
}
return NULL;
}
- vec = PyAubio_ArrayToCFvec (input);
-
- if (vec == NULL) {
+ if (!PyAubio_ArrayToCFvec(input, &vec)) {
return NULL;
}
// compute the function
- result = Py_BuildValue ("f", fvec_alpha_norm (vec, alpha));
+ result = Py_BuildValue (AUBIO_NPY_SMPL_CHR, fvec_alpha_norm (&vec, alpha));
if (result == NULL) {
return NULL;
}
smpl_t input, samplerate, fftsize;
smpl_t output;
- if (!PyArg_ParseTuple (args, "|fff", &input, &samplerate, &fftsize)) {
+ if (!PyArg_ParseTuple (args, "|" AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR , &input, &samplerate, &fftsize)) {
return NULL;
}
smpl_t input, samplerate, fftsize;
smpl_t output;
- if (!PyArg_ParseTuple (args, "|fff", &input, &samplerate, &fftsize)) {
+ if (!PyArg_ParseTuple (args, "|" AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR , &input, &samplerate, &fftsize)) {
return NULL;
}
smpl_t input, samplerate, fftsize;
smpl_t output;
- if (!PyArg_ParseTuple (args, "|fff", &input, &samplerate, &fftsize)) {
+ if (!PyArg_ParseTuple (args, "|" AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR, &input, &samplerate, &fftsize)) {
return NULL;
}
smpl_t input, samplerate, fftsize;
smpl_t output;
- if (!PyArg_ParseTuple (args, "|fff", &input, &samplerate, &fftsize)) {
+ if (!PyArg_ParseTuple (args, "|" AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR, &input, &samplerate, &fftsize)) {
return NULL;
}
Py_zero_crossing_rate (PyObject * self, PyObject * args)
{
PyObject *input;
- fvec_t *vec;
+ fvec_t vec;
PyObject *result;
if (!PyArg_ParseTuple (args, "O:zero_crossing_rate", &input)) {
return NULL;
}
- vec = PyAubio_ArrayToCFvec (input);
-
- if (vec == NULL) {
+ if (!PyAubio_ArrayToCFvec(input, &vec)) {
return NULL;
}
// compute the function
- result = Py_BuildValue ("f", aubio_zero_crossing_rate (vec));
+ result = Py_BuildValue (AUBIO_NPY_SMPL_CHR, aubio_zero_crossing_rate (&vec));
if (result == NULL) {
return NULL;
}
Py_min_removal(PyObject * self, PyObject * args)
{
PyObject *input;
- fvec_t *vec;
+ fvec_t vec;
if (!PyArg_ParseTuple (args, "O:min_removal", &input)) {
return NULL;
return NULL;
}
- vec = PyAubio_ArrayToCFvec (input);
-
- if (vec == NULL) {
+ if (!PyAubio_ArrayToCFvec(input, &vec)) {
return NULL;
}
// compute the function
- fvec_min_removal (vec);
+ fvec_min_removal (&vec);
// since this function does not return, we could return None
//Py_RETURN_NONE;
// however it is convenient to return the modified vector
- return (PyObject *) PyAubio_CFvecToArray(vec);
+ return (PyObject *) PyAubio_CFvecToArray(&vec);
// or even without converting it back to an array
//Py_INCREF(vec);
//return (PyObject *)vec;
{"silence_detection", Py_aubio_silence_detection, METH_VARARGS, Py_aubio_silence_detection_doc},
{"level_detection", Py_aubio_level_detection, METH_VARARGS, Py_aubio_level_detection_doc},
{"window", Py_aubio_window, METH_VARARGS, Py_aubio_window_doc},
- {NULL, NULL} /* Sentinel */
+ {NULL, NULL, 0, NULL} /* Sentinel */
};
-PyMODINIT_FUNC
-init_aubio (void)
+#if PY_MAJOR_VERSION >= 3
+// Python3 module definition
+static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT,
+ "_aubio", /* m_name */
+ aubio_module_doc, /* m_doc */
+ -1, /* m_size */
+ aubio_methods, /* m_methods */
+ NULL, /* m_reload */
+ NULL, /* m_traverse */
+ NULL, /* m_clear */
+ NULL, /* m_free */
+};
+#endif
+
+void
+aubio_log_function(int level, const char *message, void *data)
{
- PyObject *m;
+ // remove trailing \n
+ char *pos;
+ if ((pos=strchr(message, '\n')) != NULL) {
+ *pos = '\0';
+ }
+ // warning or error
+ if (level == AUBIO_LOG_ERR) {
+ PyErr_Format(PyExc_RuntimeError, "%s", message);
+ } else {
+ PyErr_WarnEx(PyExc_UserWarning, message, 1);
+ }
+}
+
+static PyObject *
+initaubio (void)
+{
+ PyObject *m = NULL;
int err;
// fvec is defined in __init__.py
// generated objects
|| (generated_types_ready() < 0 )
) {
- return;
+ return m;
}
+#if PY_MAJOR_VERSION >= 3
+ m = PyModule_Create(&moduledef);
+#else
m = Py_InitModule3 ("_aubio", aubio_methods, aubio_module_doc);
+#endif
if (m == NULL) {
- return;
+ return m;
}
err = _import_array ();
Py_INCREF (&Py_sinkType);
PyModule_AddObject (m, "sink", (PyObject *) & Py_sinkType);
+ PyModule_AddStringConstant(m, "float_type", AUBIO_NPY_SMPL_STR);
+ PyModule_AddStringConstant(m, "__version__", DEFINEDSTRING(AUBIO_VERSION));
+
// add generated objects
add_generated_objects(m);
// add ufunc
add_ufuncs(m);
+
+ aubio_log_set_level_function(AUBIO_LOG_ERR, aubio_log_function, NULL);
+ aubio_log_set_level_function(AUBIO_LOG_WRN, aubio_log_function, NULL);
+ return m;
}
+
+#if PY_MAJOR_VERSION >= 3
+ // Python3 init
+ PyMODINIT_FUNC PyInit__aubio(void)
+ {
+ return initaubio();
+ }
+#else
+ // Python 2 init
+ PyMODINIT_FUNC init_aubio(void)
+ {
+ initaubio();
+ }
+#endif
#include "aubio-types.h"
-fvec_t *
-PyAubio_ArrayToCFvec (PyObject *input) {
- PyObject *array;
- fvec_t *vec;
+PyObject *
+new_py_fvec(uint_t length) {
+ npy_intp dims[] = { length, 1 };
+ return PyArray_ZEROS(1, dims, AUBIO_NPY_SMPL, 0);
+}
+
+PyObject *
+new_py_fmat(uint_t height, uint_t length) {
+ npy_intp dims[] = { height, length, 1 };
+ return PyArray_ZEROS(2, dims, AUBIO_NPY_SMPL, 0);
+}
+
+PyObject *
+PyAubio_CFvecToArray (fvec_t * self)
+{
+ npy_intp dims[] = { self->length, 1 };
+ return PyArray_SimpleNewFromData (1, dims, AUBIO_NPY_SMPL, self->data);
+}
+
+int
+PyAubio_IsValidVector (PyObject * input) {
+ npy_intp length;
if (input == NULL) {
PyErr_SetString (PyExc_ValueError, "input array is not a python object");
- goto fail;
+ return 0;
}
// parsing input object into a Py_fvec
if (PyArray_Check(input)) {
// we got an array, convert it to an fvec
if (PyArray_NDIM ((PyArrayObject *)input) == 0) {
PyErr_SetString (PyExc_ValueError, "input array is a scalar");
- goto fail;
+ return 0;
} else if (PyArray_NDIM ((PyArrayObject *)input) > 1) {
PyErr_SetString (PyExc_ValueError,
"input array has more than one dimensions");
- goto fail;
+ return 0;
}
if (!PyArray_ISFLOAT ((PyArrayObject *)input)) {
PyErr_SetString (PyExc_ValueError, "input array should be float");
- goto fail;
+ return 0;
} else if (PyArray_TYPE ((PyArrayObject *)input) != AUBIO_NPY_SMPL) {
- PyErr_SetString (PyExc_ValueError, "input array should be float32");
- goto fail;
- } else {
- // input data type is float32, nothing else to do
- array = input;
+ PyErr_SetString (PyExc_ValueError, "input array should be " AUBIO_NPY_SMPL_STR);
+ return 0;
}
- // vec = new_fvec (vec->length);
- // no need to really allocate fvec, just its struct member
- vec = (fvec_t *)malloc(sizeof(fvec_t));
- long length = PyArray_SIZE ((PyArrayObject *)array);
- if (length > 0) {
- vec->length = (uint_t)length;
- } else {
+ length = PyArray_SIZE ((PyArrayObject *)input);
+ if (length <= 0) {
PyErr_SetString (PyExc_ValueError, "input array size should be greater than 0");
- goto fail;
+ return 0;
}
- vec->data = (smpl_t *) PyArray_GETPTR1 ((PyArrayObject *)array, 0);
} else if (PyObject_TypeCheck (input, &PyList_Type)) {
PyErr_SetString (PyExc_ValueError, "does not convert from list yet");
- return NULL;
+ return 0;
} else {
PyErr_SetString (PyExc_ValueError, "can only accept vector of float as input");
- return NULL;
+ return 0;
}
-
- return vec;
-
-fail:
- return NULL;
+ return 1;
}
-PyObject *
-PyAubio_CFvecToArray (fvec_t * self)
-{
- npy_intp dims[] = { self->length, 1 };
- return PyArray_SimpleNewFromData (1, dims, AUBIO_NPY_SMPL, self->data);
-}
-
-Py_cvec *
-PyAubio_CCvecToPyCvec (cvec_t * input) {
- Py_cvec *vec = (Py_cvec*) PyObject_New (Py_cvec, &Py_cvecType);
- vec->length = input->length;
- vec->o = input;
- Py_INCREF(vec);
- return vec;
-}
+int
+PyAubio_ArrayToCFvec (PyObject *input, fvec_t *out) {
-cvec_t *
-PyAubio_ArrayToCCvec (PyObject *input) {
- if (PyObject_TypeCheck (input, &Py_cvecType)) {
- return ((Py_cvec*)input)->o;
- } else {
- PyErr_SetString (PyExc_ValueError, "input array should be float32");
- return NULL;
+ if (!PyAubio_IsValidVector(input)){
+ return 0;
}
+
+ out->length = (uint_t) PyArray_SIZE ((PyArrayObject *)input);
+ out->data = (smpl_t *) PyArray_GETPTR1 ((PyArrayObject *)input, 0);
+ return 1;
}
PyObject *
return array;
}
-fmat_t *
-PyAubio_ArrayToCFmat (PyObject *input) {
- PyObject *array;
- fmat_t *mat;
- uint_t i;
+int
+PyAubio_ArrayToCFmat (PyObject *input, fmat_t *mat) {
+ uint_t i, new_height;
+ npy_intp length, height;
if (input == NULL) {
PyErr_SetString (PyExc_ValueError, "input array is not a python object");
- goto fail;
+ return 0;
}
// parsing input object into a Py_fvec
if (PyArray_Check(input)) {
// we got an array, convert it to an fvec
if (PyArray_NDIM ((PyArrayObject *)input) == 0) {
PyErr_SetString (PyExc_ValueError, "input array is a scalar");
- goto fail;
+ return 0;
} else if (PyArray_NDIM ((PyArrayObject *)input) > 2) {
PyErr_SetString (PyExc_ValueError,
"input array has more than two dimensions");
- goto fail;
+ return 0;
}
if (!PyArray_ISFLOAT ((PyArrayObject *)input)) {
PyErr_SetString (PyExc_ValueError, "input array should be float");
- goto fail;
+ return 0;
} else if (PyArray_TYPE ((PyArrayObject *)input) != AUBIO_NPY_SMPL) {
- PyErr_SetString (PyExc_ValueError, "input array should be float32");
- goto fail;
- } else {
- // input data type is float32, nothing else to do
- array = input;
+ PyErr_SetString (PyExc_ValueError, "input array should be " AUBIO_NPY_SMPL_STR);
+ return 0;
}
// no need to really allocate fvec, just its struct member
- mat = (fmat_t *)malloc(sizeof(fmat_t));
- long length = PyArray_DIM ((PyArrayObject *)array, 1);
- if (length > 0) {
- mat->length = (uint_t)length;
- } else {
+ length = PyArray_DIM ((PyArrayObject *)input, 1);
+ if (length <= 0) {
PyErr_SetString (PyExc_ValueError, "input array dimension 1 should be greater than 0");
- goto fail;
+ return 0;
}
- long height = PyArray_DIM ((PyArrayObject *)array, 0);
- if (height > 0) {
- mat->height = (uint_t)height;
- } else {
+ height = PyArray_DIM ((PyArrayObject *)input, 0);
+ if (height <= 0) {
PyErr_SetString (PyExc_ValueError, "input array dimension 0 should be greater than 0");
- goto fail;
- }
- mat->data = (smpl_t **)malloc(sizeof(smpl_t*) * mat->height);
- for (i=0; i< mat->height; i++) {
- mat->data[i] = (smpl_t*)PyArray_GETPTR1 ((PyArrayObject *)array, i);
+ return 0;
}
} else if (PyObject_TypeCheck (input, &PyList_Type)) {
PyErr_SetString (PyExc_ValueError, "can not convert list to fmat");
- return NULL;
+ return 0;
} else {
PyErr_SetString (PyExc_ValueError, "can only accept matrix of float as input");
- return NULL;
+ return 0;
}
- return mat;
+ new_height = (uint_t)PyArray_DIM ((PyArrayObject *)input, 0);
+ if (mat->height != new_height) {
+ if (mat->data) {
+ free(mat->data);
+ }
+ mat->data = (smpl_t **)malloc(sizeof(smpl_t*) * new_height);
+ }
-fail:
- return NULL;
+ mat->height = new_height;
+ mat->length = (uint_t)PyArray_DIM ((PyArrayObject *)input, 1);
+ for (i=0; i< mat->height; i++) {
+ mat->data[i] = (smpl_t*)PyArray_GETPTR1 ((PyArrayObject *)input, i);
+ }
+ return 1;
}
-
+++ /dev/null
-#include "aubio-types.h"
-
-#define AUBIO_DECLARE(NAME, PARAMS...) \
-typedef struct { \
- PyObject_HEAD \
- aubio_ ## NAME ## _t * o; \
- PARAMS; \
-} Py_## NAME;
-
-#define AUBIO_INIT(NAME, PARAMS... ) \
-static int \
-Py_ ## NAME ## _init (Py_ ## NAME * self, PyObject * args, PyObject * kwds) \
-{ \
- self->o = new_aubio_## NAME ( PARAMS ); \
- if (self->o == NULL) { \
- PyErr_SetString (PyExc_StandardError, "error creating object"); \
- return -1; \
- } \
-\
- return 0; \
-}
-
-#define AUBIO_DEL(NAME) \
-static void \
-Py_ ## NAME ## _del ( Py_ ## NAME * self) \
-{ \
- del_aubio_ ## NAME (self->o); \
- self->ob_type->tp_free ((PyObject *) self); \
-}
-
-#define AUBIO_MEMBERS_START(NAME) \
-static PyMemberDef Py_ ## NAME ## _members[] = {
-
-#define AUBIO_MEMBERS_STOP(NAME) \
- {NULL} \
-};
-
-#define AUBIO_METHODS(NAME) \
-static PyMethodDef Py_ ## NAME ## _methods[] = { \
- {NULL} \
-};
-
-
-#define AUBIO_TYPEOBJECT(NAME, PYNAME) \
-PyTypeObject Py_ ## NAME ## Type = { \
- PyObject_HEAD_INIT (NULL) \
- 0, \
- PYNAME, \
- sizeof (Py_ ## NAME), \
- 0, \
- (destructor) Py_ ## NAME ## _del, \
- 0, \
- 0, \
- 0, \
- 0, \
- 0, \
- 0, \
- 0, \
- 0, \
- 0, \
- (ternaryfunc)Py_ ## NAME ## _do, \
- 0, \
- 0, \
- 0, \
- 0, \
- Py_TPFLAGS_DEFAULT, \
- Py_ ## NAME ## _doc, \
- 0, \
- 0, \
- 0, \
- 0, \
- 0, \
- 0, \
- Py_ ## NAME ## _methods, \
- Py_ ## NAME ## _members, \
- 0, \
- 0, \
- 0, \
- 0, \
- 0, \
- 0, \
- (initproc) Py_ ## NAME ## _init, \
- 0, \
- Py_ ## NAME ## _new, \
-};
-
-// some more helpers
-#define AUBIO_NEW_VEC(name, type, lengthval) \
- name = (type *) PyObject_New (type, & type ## Type); \
- name->length = lengthval;
#include "aubio-types.h"
-/* cvec type definition
+/* cvec type definition
class cvec():
- def __init__(self, length = 1024):
- self.length = length
- self.norm = array(length)
- self.phas = array(length)
+ def __new__(self, length = 1024):
+ self.length = length / 2 + 1
+ self.norm = np.zeros(length / 2 + 1)
+ self.phas = np.zeros(length / 2 + 1)
*/
+// special python type for cvec
+typedef struct
+{
+ PyObject_HEAD
+ PyObject *norm;
+ PyObject *phas;
+ uint_t length;
+} Py_cvec;
+
static char Py_cvec_doc[] = "cvec object";
+
+PyObject *
+new_py_cvec(uint_t length) {
+ Py_cvec* vec = (Py_cvec*) PyObject_New (Py_cvec, &Py_cvecType);
+ npy_intp dims[] = { length / 2 + 1, 1 };
+ vec->norm = PyArray_ZEROS(1, dims, AUBIO_NPY_SMPL, 0);
+ vec->phas = PyArray_ZEROS(1, dims, AUBIO_NPY_SMPL, 0);
+ vec->length = length / 2 + 1;
+ return (PyObject*)vec;
+}
+
+int
+PyAubio_PyCvecToCCvec (PyObject *input, cvec_t *i) {
+ if (PyObject_TypeCheck (input, &Py_cvecType)) {
+ Py_cvec * in = (Py_cvec *)input;
+ i->norm = (smpl_t *) PyArray_GETPTR1 ((PyArrayObject *)(in->norm), 0);
+ i->phas = (smpl_t *) PyArray_GETPTR1 ((PyArrayObject *)(in->phas), 0);
+ i->length = ((Py_cvec*)input)->length;
+ return 1;
+ } else {
+ PyErr_SetString (PyExc_ValueError, "input array should be aubio.cvec");
+ return 0;
+ }
+}
+
static PyObject *
Py_cvec_new (PyTypeObject * type, PyObject * args, PyObject * kwds)
{
return NULL;
}
-
self = (Py_cvec *) type->tp_alloc (type, 0);
self->length = Py_default_vector_length / 2 + 1;
static int
Py_cvec_init (Py_cvec * self, PyObject * args, PyObject * kwds)
{
- self->o = new_cvec ((self->length - 1) * 2);
- if (self->o == NULL) {
- return -1;
- }
-
+ npy_intp dims[] = { self->length, 1 };
+ self->phas = PyArray_ZEROS(1, dims, AUBIO_NPY_SMPL, 0);
+ self->norm = PyArray_ZEROS(1, dims, AUBIO_NPY_SMPL, 0);
return 0;
}
static void
Py_cvec_del (Py_cvec * self)
{
- del_cvec (self->o);
- self->ob_type->tp_free ((PyObject *) self);
+ Py_DECREF(self->norm);
+ Py_DECREF(self->phas);
+ Py_TYPE(self)->tp_free ((PyObject *) self);
}
static PyObject *
PyObject *args = NULL;
PyObject *result = NULL;
- format = PyString_FromString ("aubio cvec of %d elements");
+ format = PyUnicode_FromString ("aubio cvec of %d elements");
if (format == NULL) {
goto fail;
}
if (args == NULL) {
goto fail;
}
- cvec_print ( self->o );
+ // hide actual norm / phas content
- result = PyString_Format (format, args);
+ result = PyUnicode_Format (format, args);
fail:
Py_XDECREF (format);
}
PyObject *
-PyAubio_CvecNormToArray (Py_cvec * self)
-{
- npy_intp dims[] = { self->o->length, 1 };
- return PyArray_SimpleNewFromData (1, dims, NPY_FLOAT, self->o->norm);
-}
-
-
-PyObject *
-PyAubio_CvecPhasToArray (Py_cvec * self)
-{
- npy_intp dims[] = { self->o->length, 1 };
- return PyArray_SimpleNewFromData (1, dims, NPY_FLOAT, self->o->phas);
-}
-
-PyObject *
-PyAubio_ArrayToCvecPhas (PyObject * self)
-{
- return NULL;
-}
-
-PyObject *
Py_cvec_get_norm (Py_cvec * self, void *closure)
{
- return PyAubio_CvecNormToArray(self);
+ // we want self->norm to still exist after our caller return it
+ Py_INCREF(self->norm);
+ return (PyObject*)(self->norm);
}
PyObject *
Py_cvec_get_phas (Py_cvec * self, void *closure)
{
- return PyAubio_CvecPhasToArray(self);
+ // we want self->phas to still exist after our caller return it
+ Py_INCREF(self->phas);
+ return (PyObject *)(self->phas);
}
static int
Py_cvec_set_norm (Py_cvec * vec, PyObject *input, void * closure)
{
- PyArrayObject * array;
- if (input == NULL) {
- PyErr_SetString (PyExc_ValueError, "input array is not a python object");
- goto fail;
+ npy_intp length;
+ if (!PyAubio_IsValidVector(input)) {
+ return 1;
}
- if (PyArray_Check(input)) {
-
- // we got an array, convert it to a cvec.norm
- if (PyArray_NDIM ((PyArrayObject *)input) == 0) {
- PyErr_SetString (PyExc_ValueError, "input array is a scalar");
- goto fail;
- } else if (PyArray_NDIM ((PyArrayObject *)input) > 2) {
- PyErr_SetString (PyExc_ValueError,
- "input array has more than two dimensions");
- goto fail;
- }
-
- if (!PyArray_ISFLOAT ((PyArrayObject *)input)) {
- PyErr_SetString (PyExc_ValueError, "input array should be float");
- goto fail;
- } else if (PyArray_TYPE ((PyArrayObject *)input) != AUBIO_NPY_SMPL) {
- PyErr_SetString (PyExc_ValueError, "input array should be float32");
- goto fail;
- }
- array = (PyArrayObject *)input;
-
- // check input array dimensions
- if (PyArray_NDIM (array) != 1) {
- PyErr_Format (PyExc_ValueError,
- "input array has %d dimensions, not 1",
- PyArray_NDIM (array));
- goto fail;
- } else {
- if (vec->o->length != PyArray_SIZE (array)) {
- PyErr_Format (PyExc_ValueError,
- "input array has length %d, but cvec has length %d",
- (int)PyArray_SIZE (array), vec->o->length);
- goto fail;
- }
- }
-
- vec->o->norm = (smpl_t *) PyArray_GETPTR1 (array, 0);
-
- } else {
- PyErr_SetString (PyExc_ValueError, "can only accept array as input");
+ length = PyArray_SIZE ((PyArrayObject *)input);
+ if (length != vec->length) {
+ PyErr_Format (PyExc_ValueError,
+ "input array has length %" NPY_INTP_FMT ", but cvec has length %d", length,
+ vec->length);
return 1;
}
- Py_INCREF(array);
+ Py_XDECREF(vec->norm);
+ vec->norm = input;
+ Py_INCREF(vec->norm);
return 0;
-
-fail:
- return 1;
}
static int
Py_cvec_set_phas (Py_cvec * vec, PyObject *input, void * closure)
{
- PyArrayObject * array;
- if (input == NULL) {
- PyErr_SetString (PyExc_ValueError, "input array is not a python object");
- goto fail;
+ npy_intp length;
+ if (!PyAubio_IsValidVector(input)) {
+ return 1;
}
- if (PyArray_Check(input)) {
-
- // we got an array, convert it to a cvec.phas
- if (PyArray_NDIM ((PyArrayObject *)input) == 0) {
- PyErr_SetString (PyExc_ValueError, "input array is a scalar");
- goto fail;
- } else if (PyArray_NDIM ((PyArrayObject *)input) > 2) {
- PyErr_SetString (PyExc_ValueError,
- "input array has more than two dimensions");
- goto fail;
- }
-
- if (!PyArray_ISFLOAT ((PyArrayObject *)input)) {
- PyErr_SetString (PyExc_ValueError, "input array should be float");
- goto fail;
- } else if (PyArray_TYPE ((PyArrayObject *)input) != AUBIO_NPY_SMPL) {
- PyErr_SetString (PyExc_ValueError, "input array should be float32");
- goto fail;
- }
- array = (PyArrayObject *)input;
-
- // check input array dimensions
- if (PyArray_NDIM (array) != 1) {
- PyErr_Format (PyExc_ValueError,
- "input array has %d dimensions, not 1",
- PyArray_NDIM (array));
- goto fail;
- } else {
- if (vec->o->length != PyArray_SIZE (array)) {
- PyErr_Format (PyExc_ValueError,
- "input array has length %d, but cvec has length %d",
- (int)PyArray_SIZE (array), vec->o->length);
- goto fail;
- }
- }
-
- vec->o->phas = (smpl_t *) PyArray_GETPTR1 (array, 0);
-
- } else {
- PyErr_SetString (PyExc_ValueError, "can only accept array as input");
+ length = PyArray_SIZE ((PyArrayObject *)input);
+ if (length != vec->length) {
+ PyErr_Format (PyExc_ValueError,
+ "input array has length %" NPY_INTP_FMT ", but cvec has length %d", length,
+ vec->length);
return 1;
}
- Py_INCREF(array);
+ Py_XDECREF(vec->phas);
+ vec->phas = input;
+ Py_INCREF(vec->phas);
return 0;
-
-fail:
- return 1;
}
static PyMemberDef Py_cvec_members[] = {
};
PyTypeObject Py_cvecType = {
- PyObject_HEAD_INIT (NULL)
- 0, /* ob_size */
+ PyVarObject_HEAD_INIT(NULL, 0)
"aubio.cvec", /* tp_name */
sizeof (Py_cvec), /* tp_basicsize */
0, /* tp_itemsize */
0, /* tp_compare */
(reprfunc) Py_cvec_repr, /* tp_repr */
0, /* tp_as_number */
- 0, //&Py_cvec_tp_as_sequence, /* tp_as_sequence */
+ 0, //&Py_cvec_tp_as_sequence, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
(initproc) Py_cvec_init, /* tp_init */
0, /* tp_alloc */
Py_cvec_new, /* tp_new */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
};
-#include "aubiowraphell.h"
+#include "aubio-types.h"
static char Py_fft_doc[] = "fft object";
-AUBIO_DECLARE(fft, uint_t win_s)
+typedef struct
+{
+ PyObject_HEAD
+ aubio_fft_t * o;
+ uint_t win_s;
+ // do / rdo input vectors
+ fvec_t vecin;
+ cvec_t cvecin;
+ // do / rdo output results
+ PyObject *doout;
+ PyObject *rdoout;
+} Py_fft;
-//AUBIO_NEW(fft)
static PyObject *
Py_fft_new (PyTypeObject * type, PyObject * args, PyObject * kwds)
{
return (PyObject *) self;
}
+static int
+Py_fft_init (Py_fft * self, PyObject * args, PyObject * kwds)
+{
+ self->o = new_aubio_fft (self->win_s);
+ if (self->o == NULL) {
+ // PyErr_Format(PyExc_RuntimeError, ...) was set above by new_ which called
+ // AUBIO_ERR when failing
+ return -1;
+ }
+
+ self->doout = new_py_cvec(self->win_s);
+ self->rdoout = new_py_fvec(self->win_s);
-AUBIO_INIT(fft, self->win_s)
+ return 0;
+}
-AUBIO_DEL(fft)
+static void
+Py_fft_del (Py_fft *self, PyObject *unused)
+{
+ Py_XDECREF(self->doout);
+ Py_XDECREF(self->rdoout);
+ if (self->o) {
+ del_aubio_fft(self->o);
+ }
+ Py_TYPE(self)->tp_free((PyObject *) self);
+}
-static PyObject *
-Py_fft_do(PyObject * self, PyObject * args)
+static PyObject *
+Py_fft_do(Py_fft * self, PyObject * args)
{
PyObject *input;
- fvec_t *vec;
- cvec_t *output;
+ cvec_t c_out;
if (!PyArg_ParseTuple (args, "O", &input)) {
return NULL;
}
- vec = PyAubio_ArrayToCFvec (input);
-
- if (vec == NULL) {
+ if (!PyAubio_ArrayToCFvec(input, &(self->vecin))) {
return NULL;
}
- output = new_cvec(((Py_fft *) self)->win_s);
+ if (self->vecin.length != self->win_s) {
+ PyErr_Format(PyExc_ValueError,
+ "input array has length %d, but fft expects length %d",
+ self->vecin.length, self->win_s);
+ return NULL;
+ }
+ Py_INCREF(self->doout);
+ if (!PyAubio_PyCvecToCCvec(self->doout, &c_out)) {
+ return NULL;
+ }
// compute the function
- aubio_fft_do (((Py_fft *)self)->o, vec, output);
- return (PyObject *)PyAubio_CCvecToPyCvec(output);
+ aubio_fft_do (self->o, &(self->vecin), &c_out);
+ return self->doout;
}
-AUBIO_MEMBERS_START(fft)
+static PyMemberDef Py_fft_members[] = {
{"win_s", T_INT, offsetof (Py_fft, win_s), READONLY,
"size of the window"},
-AUBIO_MEMBERS_STOP(fft)
+ {NULL}
+};
-static PyObject *
+static PyObject *
Py_fft_rdo(Py_fft * self, PyObject * args)
{
PyObject *input;
- cvec_t *vec;
- fvec_t *output;
+ fvec_t out;
if (!PyArg_ParseTuple (args, "O", &input)) {
return NULL;
}
- vec = PyAubio_ArrayToCCvec (input);
-
- if (vec == NULL) {
+ if (!PyAubio_PyCvecToCCvec (input, &(self->cvecin)) ) {
return NULL;
}
- output = new_fvec(self->win_s);
+ if (self->cvecin.length != self->win_s / 2 + 1) {
+ PyErr_Format(PyExc_ValueError,
+ "input cvec has length %d, but fft expects length %d",
+ self->cvecin.length, self->win_s / 2 + 1);
+ return NULL;
+ }
+ Py_INCREF(self->rdoout);
+ if (!PyAubio_ArrayToCFvec(self->rdoout, &out) ) {
+ return NULL;
+ }
// compute the function
- aubio_fft_rdo (((Py_fft *)self)->o, vec, output);
- return (PyObject *)PyAubio_CFvecToArray(output);
+ aubio_fft_rdo (self->o, &(self->cvecin), &out);
+ return self->rdoout;
}
static PyMethodDef Py_fft_methods[] = {
{NULL}
};
-AUBIO_TYPEOBJECT(fft, "aubio.fft")
+PyTypeObject Py_fftType = {
+ PyVarObject_HEAD_INIT (NULL, 0)
+ "aubio.fft",
+ sizeof (Py_fft),
+ 0,
+ (destructor) Py_fft_del,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ (ternaryfunc)Py_fft_do,
+ 0,
+ 0,
+ 0,
+ 0,
+ Py_TPFLAGS_DEFAULT,
+ Py_fft_doc,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ Py_fft_methods,
+ Py_fft_members,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ (initproc) Py_fft_init,
+ 0,
+ Py_fft_new,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+};
PyObject_HEAD
aubio_filter_t * o;
uint_t order;
+ fvec_t vec;
+ PyObject *out;
+ fvec_t c_out;
} Py_filter;
static char Py_filter_doc[] = "filter object";
if (self->o == NULL) {
return -1;
}
-
+ self->out = NULL;
return 0;
}
static void
Py_filter_del (Py_filter * self)
{
+ Py_XDECREF(self->out);
del_aubio_filter (self->o);
- self->ob_type->tp_free ((PyObject *) self);
+ Py_TYPE(self)->tp_free ((PyObject *) self);
}
-static PyObject *
+static PyObject *
Py_filter_do(Py_filter * self, PyObject * args)
{
PyObject *input;
- fvec_t *vec;
if (!PyArg_ParseTuple (args, "O:digital_filter.do", &input)) {
return NULL;
return NULL;
}
- vec = PyAubio_ArrayToCFvec (input);
-
- if (vec == NULL) {
+ if (!PyAubio_ArrayToCFvec(input, &(self->vec))) {
return NULL;
}
+ // initialize output now
+ if (self->out == NULL) {
+ self->out = new_py_fvec(self->vec.length);
+ }
+
+ Py_INCREF(self->out);
+ if (!PyAubio_ArrayToCFvec(self->out, &(self->c_out)) ) {
+ return NULL;
+ }
// compute the function
- fvec_t * out = new_fvec(vec->length);
- aubio_filter_do_outplace (self->o, vec, out);
- return PyAubio_CFvecToArray(out);
+ aubio_filter_do_outplace (self->o, &(self->vec), &(self->c_out));
+ return self->out;
}
-static PyObject *
+static PyObject *
Py_filter_set_c_weighting (Py_filter * self, PyObject *args)
{
uint_t err = 0;
Py_RETURN_NONE;
}
-static PyObject *
+static PyObject *
Py_filter_set_a_weighting (Py_filter * self, PyObject *args)
{
uint_t err = 0;
};
PyTypeObject Py_filterType = {
- PyObject_HEAD_INIT (NULL)
- 0, /* ob_size */
+ PyVarObject_HEAD_INIT(NULL, 0)
"aubio.digital_filter", /* tp_name */
sizeof (Py_filter), /* tp_basicsize */
0, /* tp_itemsize */
(initproc) Py_filter_init, /* tp_init */
0, /* tp_alloc */
Py_filter_new, /* tp_new */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
};
-#include "aubiowraphell.h"
+#include "aubio-types.h"
static char Py_filterbank_doc[] = "filterbank object";
-AUBIO_DECLARE(filterbank, uint_t n_filters; uint_t win_s)
+typedef struct
+{
+ PyObject_HEAD
+ aubio_filterbank_t * o;
+ uint_t n_filters;
+ uint_t win_s;
+ cvec_t vec;
+ fvec_t freqs;
+ fmat_t coeffs;
+ PyObject *out;
+ fvec_t c_out;
+} Py_filterbank;
-//AUBIO_NEW(filterbank)
static PyObject *
Py_filterbank_new (PyTypeObject * type, PyObject * args, PyObject * kwds)
{
return (PyObject *) self;
}
+static int
+Py_filterbank_init (Py_filterbank * self, PyObject * args, PyObject * kwds)
+{
+ self->o = new_aubio_filterbank (self->n_filters, self->win_s);
+ if (self->o == NULL) {
+ PyErr_Format(PyExc_RuntimeError, "error creating filterbank with"
+ " n_filters=%d, win_s=%d", self->n_filters, self->win_s);
+ return -1;
+ }
+ self->out = new_py_fvec(self->n_filters);
-AUBIO_INIT(filterbank, self->n_filters, self->win_s)
+ return 0;
+}
-AUBIO_DEL(filterbank)
+static void
+Py_filterbank_del (Py_filterbank *self, PyObject *unused)
+{
+ if (self->o) {
+ free(self->coeffs.data);
+ del_aubio_filterbank(self->o);
+ }
+ Py_XDECREF(self->out);
+ Py_TYPE(self)->tp_free((PyObject *) self);
+}
static PyObject *
Py_filterbank_do(Py_filterbank * self, PyObject * args)
{
PyObject *input;
- cvec_t *vec;
- fvec_t *out;
if (!PyArg_ParseTuple (args, "O", &input)) {
return NULL;
}
- vec = PyAubio_ArrayToCCvec (input);
-
- if (vec == NULL) {
+ if (!PyAubio_PyCvecToCCvec(input, &(self->vec) )) {
return NULL;
}
- out = new_fvec (self->n_filters);
+ if (self->vec.length != self->win_s / 2 + 1) {
+ PyErr_Format(PyExc_ValueError,
+ "input cvec has length %d, but fft expects length %d",
+ self->vec.length, self->win_s / 2 + 1);
+ return NULL;
+ }
+ Py_INCREF(self->out);
+ if (!PyAubio_ArrayToCFvec(self->out, &(self->c_out))) {
+ return NULL;
+ }
// compute the function
- aubio_filterbank_do (self->o, vec, out);
- return (PyObject *)PyAubio_CFvecToArray(out);
+ aubio_filterbank_do (self->o, &(self->vec), &(self->c_out));
+ return self->out;
}
-AUBIO_MEMBERS_START(filterbank)
+static PyMemberDef Py_filterbank_members[] = {
{"win_s", T_INT, offsetof (Py_filterbank, win_s), READONLY,
"size of the window"},
{"n_filters", T_INT, offsetof (Py_filterbank, n_filters), READONLY,
"number of filters"},
-AUBIO_MEMBERS_STOP(filterbank)
+ {NULL} /* sentinel */
+};
static PyObject *
Py_filterbank_set_triangle_bands (Py_filterbank * self, PyObject *args)
PyObject *input;
uint_t samplerate;
- fvec_t *freqs;
if (!PyArg_ParseTuple (args, "OI", &input, &samplerate)) {
return NULL;
}
return NULL;
}
- freqs = PyAubio_ArrayToCFvec (input);
-
- if (freqs == NULL) {
+ if (!PyAubio_ArrayToCFvec(input, &(self->freqs) )) {
return NULL;
}
err = aubio_filterbank_set_triangle_bands (self->o,
- freqs, samplerate);
+ &(self->freqs), samplerate);
if (err > 0) {
PyErr_SetString (PyExc_ValueError,
"error when setting filter to A-weighting");
uint_t err = 0;
PyObject *input;
- fmat_t *coeffs;
-
if (!PyArg_ParseTuple (args, "O", &input)) {
return NULL;
}
- coeffs = PyAubio_ArrayToCFmat (input);
-
- if (coeffs == NULL) {
- PyErr_SetString (PyExc_ValueError,
- "unable to parse input array");
+ if (!PyAubio_ArrayToCFmat(input, &(self->coeffs))) {
return NULL;
}
- err = aubio_filterbank_set_coeffs (self->o, coeffs);
+ err = aubio_filterbank_set_coeffs (self->o, &(self->coeffs));
if (err > 0) {
PyErr_SetString (PyExc_ValueError,
{NULL}
};
-AUBIO_TYPEOBJECT(filterbank, "aubio.filterbank")
+PyTypeObject Py_filterbankType = {
+ PyVarObject_HEAD_INIT (NULL, 0)
+ "aubio.filterbank",
+ sizeof (Py_filterbank),
+ 0,
+ (destructor) Py_filterbank_del,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ (ternaryfunc)Py_filterbank_do,
+ 0,
+ 0,
+ 0,
+ 0,
+ Py_TPFLAGS_DEFAULT,
+ Py_filterbank_doc,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ Py_filterbank_methods,
+ Py_filterbank_members,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ (initproc) Py_filterbank_init,
+ 0,
+ Py_filterbank_new,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+};
fvec_t *window = NULL;
if (!PyArg_ParseTuple (args, "|sI", &wintype, &winlen)) {
- PyErr_SetString (PyExc_ValueError, "failed parsing arguments");
return NULL;
}
Py_aubio_level_lin(PyObject *self, PyObject *args)
{
PyObject *input;
- fvec_t *vec;
+ fvec_t vec;
PyObject *level_lin;
if (!PyArg_ParseTuple (args, "O:level_lin", &input)) {
- PyErr_SetString (PyExc_ValueError, "failed parsing arguments");
return NULL;
}
return NULL;
}
- vec = PyAubio_ArrayToCFvec (input);
- if (vec == NULL) {
+ if (!PyAubio_ArrayToCFvec(input, &vec)) {
return NULL;
}
- level_lin = Py_BuildValue("f", aubio_level_lin(vec));
+ level_lin = Py_BuildValue(AUBIO_NPY_SMPL_CHR, aubio_level_lin(&vec));
if (level_lin == NULL) {
PyErr_SetString (PyExc_ValueError, "failed computing level_lin");
return NULL;
Py_aubio_db_spl(PyObject *self, PyObject *args)
{
PyObject *input;
- fvec_t *vec;
+ fvec_t vec;
PyObject *db_spl;
if (!PyArg_ParseTuple (args, "O:db_spl", &input)) {
- PyErr_SetString (PyExc_ValueError, "failed parsing arguments");
return NULL;
}
return NULL;
}
- vec = PyAubio_ArrayToCFvec (input);
- if (vec == NULL) {
+ if (!PyAubio_ArrayToCFvec(input, &vec)) {
return NULL;
}
- db_spl = Py_BuildValue("f", aubio_db_spl(vec));
+ db_spl = Py_BuildValue(AUBIO_NPY_SMPL_CHR, aubio_db_spl(&vec));
if (db_spl == NULL) {
PyErr_SetString (PyExc_ValueError, "failed computing db_spl");
return NULL;
Py_aubio_silence_detection(PyObject *self, PyObject *args)
{
PyObject *input;
- fvec_t *vec;
+ fvec_t vec;
PyObject *silence_detection;
smpl_t threshold;
- if (!PyArg_ParseTuple (args, "Of:silence_detection", &input, &threshold)) {
- PyErr_SetString (PyExc_ValueError, "failed parsing arguments");
+ if (!PyArg_ParseTuple (args, "O" AUBIO_NPY_SMPL_CHR ":silence_detection", &input, &threshold)) {
return NULL;
}
return NULL;
}
- vec = PyAubio_ArrayToCFvec (input);
- if (vec == NULL) {
+ if (!PyAubio_ArrayToCFvec(input, &vec)) {
return NULL;
}
- silence_detection = Py_BuildValue("I", aubio_silence_detection(vec, threshold));
+ silence_detection = Py_BuildValue("I", aubio_silence_detection(&vec, threshold));
if (silence_detection == NULL) {
PyErr_SetString (PyExc_ValueError, "failed computing silence_detection");
return NULL;
Py_aubio_level_detection(PyObject *self, PyObject *args)
{
PyObject *input;
- fvec_t *vec;
+ fvec_t vec;
PyObject *level_detection;
smpl_t threshold;
- if (!PyArg_ParseTuple (args, "Of:level_detection", &input, &threshold)) {
- PyErr_SetString (PyExc_ValueError, "failed parsing arguments");
+ if (!PyArg_ParseTuple (args, "O" AUBIO_NPY_SMPL_CHR ":level_detection", &input, &threshold)) {
return NULL;
}
return NULL;
}
- vec = PyAubio_ArrayToCFvec (input);
- if (vec == NULL) {
+ if (!PyAubio_ArrayToCFvec(input, &vec)) {
return NULL;
}
- level_detection = Py_BuildValue("f", aubio_level_detection(vec, threshold));
+ level_detection = Py_BuildValue(AUBIO_NPY_SMPL_CHR, aubio_level_detection(&vec, threshold));
if (level_detection == NULL) {
PyErr_SetString (PyExc_ValueError, "failed computing level_detection");
return NULL;
-#ifndef _PY_AUBIO_MUSICUTILS_H_
-#define _PY_AUBIO_MUSICUTILS_H_
+#ifndef PY_AUBIO_MUSICUTILS_H
+#define PY_AUBIO_MUSICUTILS_H
static char Py_aubio_window_doc[] = ""
"window(string, integer) -> fvec\n"
PyObject * Py_aubio_level_detection(PyObject *self, PyObject *args);
-#endif /* _PY_AUBIO_MUSICUTILS_H_ */
+#endif /* PY_AUBIO_MUSICUTILS_H */
-#include "aubiowraphell.h"
+#include "aubio-types.h"
static char Py_pvoc_doc[] = "pvoc object";
-AUBIO_DECLARE(pvoc, uint_t win_s; uint_t hop_s)
+typedef struct
+{
+ PyObject_HEAD
+ aubio_pvoc_t * o;
+ uint_t win_s;
+ uint_t hop_s;
+ fvec_t vecin;
+ cvec_t cvecin;
+ PyObject *output;
+ cvec_t c_output;
+ PyObject *routput;
+ fvec_t c_routput;
+} Py_pvoc;
+
-//AUBIO_NEW(pvoc)
static PyObject *
Py_pvoc_new (PyTypeObject * type, PyObject * args, PyObject * kwds)
{
return (PyObject *) self;
}
+static int
+Py_pvoc_init (Py_pvoc * self, PyObject * args, PyObject * kwds)
+{
+ self->o = new_aubio_pvoc ( self->win_s, self->hop_s);
+ if (self->o == NULL) {
+ // PyErr_Format(PyExc_RuntimeError, ...) was set above by new_ which called
+ // AUBIO_ERR when failing
+ return -1;
+ }
-AUBIO_INIT(pvoc, self->win_s, self->hop_s)
+ self->output = new_py_cvec(self->win_s);
+ self->routput = new_py_fvec(self->hop_s);
+
+ return 0;
+}
-AUBIO_DEL(pvoc)
-static PyObject *
+static void
+Py_pvoc_del (Py_pvoc *self, PyObject *unused)
+{
+ Py_XDECREF(self->output);
+ Py_XDECREF(self->routput);
+ if (self->o) {
+ del_aubio_pvoc(self->o);
+ }
+ Py_TYPE(self)->tp_free((PyObject *) self);
+}
+
+
+static PyObject *
Py_pvoc_do(Py_pvoc * self, PyObject * args)
{
PyObject *input;
- fvec_t *vec;
- cvec_t *output;
if (!PyArg_ParseTuple (args, "O", &input)) {
return NULL;
}
- vec = PyAubio_ArrayToCFvec (input);
-
- if (vec == NULL) {
+ if (!PyAubio_ArrayToCFvec (input, &(self->vecin) )) {
return NULL;
}
- output = new_cvec(self->win_s);
+ if (self->vecin.length != self->hop_s) {
+ PyErr_Format(PyExc_ValueError,
+ "input fvec has length %d, but pvoc expects length %d",
+ self->vecin.length, self->hop_s);
+ return NULL;
+ }
+ Py_INCREF(self->output);
+ if (!PyAubio_PyCvecToCCvec (self->output, &(self->c_output))) {
+ return NULL;
+ }
// compute the function
- aubio_pvoc_do (self->o, vec, output);
- return (PyObject *)PyAubio_CCvecToPyCvec(output);
+ aubio_pvoc_do (self->o, &(self->vecin), &(self->c_output));
+ return self->output;
}
-AUBIO_MEMBERS_START(pvoc)
+static PyMemberDef Py_pvoc_members[] = {
{"win_s", T_INT, offsetof (Py_pvoc, win_s), READONLY,
"size of the window"},
{"hop_s", T_INT, offsetof (Py_pvoc, hop_s), READONLY,
"size of the hop"},
-AUBIO_MEMBERS_STOP(pvoc)
+ { NULL } // sentinel
+};
-static PyObject *
+static PyObject *
Py_pvoc_rdo(Py_pvoc * self, PyObject * args)
{
PyObject *input;
- cvec_t *vec;
- fvec_t *output;
-
if (!PyArg_ParseTuple (args, "O", &input)) {
return NULL;
}
- vec = PyAubio_ArrayToCCvec (input);
-
- if (vec == NULL) {
+ if (!PyAubio_PyCvecToCCvec (input, &(self->cvecin) )) {
return NULL;
}
- output = new_fvec(self->hop_s);
+ if (self->cvecin.length != self->win_s / 2 + 1) {
+ PyErr_Format(PyExc_ValueError,
+ "input cvec has length %d, but pvoc expects length %d",
+ self->cvecin.length, self->win_s / 2 + 1);
+ return NULL;
+ }
+ Py_INCREF(self->routput);
+ if (!PyAubio_ArrayToCFvec(self->routput, &(self->c_routput)) ) {
+ return NULL;
+ }
// compute the function
- aubio_pvoc_rdo (self->o, vec, output);
- return (PyObject *)PyAubio_CFvecToArray(output);
+ aubio_pvoc_rdo (self->o, &(self->cvecin), &(self->c_routput));
+ return self->routput;
}
static PyMethodDef Py_pvoc_methods[] = {
{NULL}
};
-AUBIO_TYPEOBJECT(pvoc, "aubio.pvoc")
+PyTypeObject Py_pvocType = {
+ PyVarObject_HEAD_INIT (NULL, 0)
+ "aubio.pvoc",
+ sizeof (Py_pvoc),
+ 0,
+ (destructor) Py_pvoc_del,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ (ternaryfunc)Py_pvoc_do,
+ 0,
+ 0,
+ 0,
+ 0,
+ Py_TPFLAGS_DEFAULT,
+ Py_pvoc_doc,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ Py_pvoc_methods,
+ Py_pvoc_members,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ (initproc) Py_pvoc_init,
+ 0,
+ Py_pvoc_new,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+};
-#include "aubiowraphell.h"
+#include "aubio-types.h"
typedef struct
{
char_t* uri;
uint_t samplerate;
uint_t channels;
+ fvec_t write_data;
+ fmat_t mwrite_data;
} Py_sink;
static char Py_sink_doc[] = ""
return NULL;
}
- self->uri = "none";
+ self->uri = NULL;
if (uri != NULL) {
- self->uri = uri;
+ self->uri = (char_t *)malloc(sizeof(char_t) * (strnlen(uri, PATH_MAX) + 1));
+ strncpy(self->uri, uri, strnlen(uri, PATH_MAX) + 1);
}
self->samplerate = Py_aubio_default_samplerate;
- if ((sint_t)samplerate > 0) {
+ if (samplerate != 0) {
self->samplerate = samplerate;
- } else if ((sint_t)samplerate < 0) {
- PyErr_SetString (PyExc_ValueError,
- "can not use negative value for samplerate");
- return NULL;
}
self->channels = 1;
- if ((sint_t)channels > 0) {
+ if (channels != 0) {
self->channels = channels;
- } else if ((sint_t)channels < 0) {
- PyErr_SetString (PyExc_ValueError,
- "can not use negative or null value for channels");
- return NULL;
}
return (PyObject *) self;
static int
Py_sink_init (Py_sink * self, PyObject * args, PyObject * kwds)
{
- if (self->channels == 1) {
- self->o = new_aubio_sink ( self->uri, self->samplerate );
- } else {
- self->o = new_aubio_sink ( self->uri, 0 );
- aubio_sink_preset_channels ( self->o, self->channels );
- aubio_sink_preset_samplerate ( self->o, self->samplerate );
- }
+ self->o = new_aubio_sink ( self->uri, 0 );
if (self->o == NULL) {
- PyErr_SetString (PyExc_StandardError, "error creating sink with this uri");
+ // error string was set in new_aubio_sink
+ return -1;
+ }
+ if (aubio_sink_preset_channels(self->o, self->channels) != 0) {
+ // error string was set in aubio_sink_preset_channels
+ return -1;
+ }
+ if (aubio_sink_preset_samplerate(self->o, self->samplerate) != 0) {
+ // error string was set in aubio_sink_preset_samplerate
return -1;
}
+
self->samplerate = aubio_sink_get_samplerate ( self->o );
self->channels = aubio_sink_get_channels ( self->o );
return 0;
}
-AUBIO_DEL(sink)
+static void
+Py_sink_del (Py_sink *self, PyObject *unused)
+{
+ del_aubio_sink(self->o);
+ free(self->mwrite_data.data);
+ if (self->uri) {
+ free(self->uri);
+ }
+ Py_TYPE(self)->tp_free((PyObject *) self);
+}
/* function Py_sink_do */
static PyObject *
PyObject * write_data_obj;
/* input vectors prototypes */
- fvec_t* write_data;
uint_t write;
return NULL;
}
-
/* input vectors parsing */
- write_data = PyAubio_ArrayToCFvec (write_data_obj);
-
- if (write_data == NULL) {
+ if (!PyAubio_ArrayToCFvec(write_data_obj, &(self->write_data))) {
return NULL;
}
-
-
-
/* compute _do function */
- aubio_sink_do (self->o, write_data, write);
+ aubio_sink_do (self->o, &(self->write_data), write);
Py_RETURN_NONE;
}
PyObject * write_data_obj;
/* input vectors prototypes */
- fmat_t * write_data;
uint_t write;
/* input vectors parsing */
- write_data = PyAubio_ArrayToCFmat (write_data_obj);
-
- if (write_data == NULL) {
+ if (!PyAubio_ArrayToCFmat(write_data_obj, &(self->mwrite_data))) {
return NULL;
}
-
-
-
-
/* compute _do function */
- aubio_sink_do_multi (self->o, write_data, write);
+ aubio_sink_do_multi (self->o, &(self->mwrite_data), write);
Py_RETURN_NONE;
}
-AUBIO_MEMBERS_START(sink)
+static PyMemberDef Py_sink_members[] = {
{"uri", T_STRING, offsetof (Py_sink, uri), READONLY,
"path at which the sink was created"},
{"samplerate", T_INT, offsetof (Py_sink, samplerate), READONLY,
"samplerate at which the sink was created"},
{"channels", T_INT, offsetof (Py_sink, channels), READONLY,
"number of channels with which the sink was created"},
-AUBIO_MEMBERS_STOP(sink)
+ { NULL } // sentinel
+};
static PyObject *
Pyaubio_sink_close (Py_sink *self, PyObject *unused)
Py_RETURN_NONE;
}
+static char Pyaubio_sink_enter_doc[] = "";
+static PyObject* Pyaubio_sink_enter(Py_sink *self, PyObject *unused) {
+ Py_INCREF(self);
+ return (PyObject*)self;
+}
+
+static char Pyaubio_sink_exit_doc[] = "";
+static PyObject* Pyaubio_sink_exit(Py_sink *self, PyObject *unused) {
+ return Pyaubio_sink_close(self, unused);
+}
+
static PyMethodDef Py_sink_methods[] = {
{"do", (PyCFunction) Py_sink_do, METH_VARARGS, Py_sink_do_doc},
{"do_multi", (PyCFunction) Py_sink_do_multi, METH_VARARGS, Py_sink_do_multi_doc},
{"close", (PyCFunction) Pyaubio_sink_close, METH_NOARGS, Py_sink_close_doc},
+ {"__enter__", (PyCFunction)Pyaubio_sink_enter, METH_NOARGS,
+ Pyaubio_sink_enter_doc},
+ {"__exit__", (PyCFunction)Pyaubio_sink_exit, METH_VARARGS,
+ Pyaubio_sink_exit_doc},
{NULL} /* sentinel */
};
-AUBIO_TYPEOBJECT(sink, "aubio.sink")
+PyTypeObject Py_sinkType = {
+ PyVarObject_HEAD_INIT (NULL, 0)
+ "aubio.sink",
+ sizeof (Py_sink),
+ 0,
+ (destructor) Py_sink_del,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ (ternaryfunc)Py_sink_do,
+ 0,
+ 0,
+ 0,
+ 0,
+ Py_TPFLAGS_DEFAULT,
+ Py_sink_doc,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ Py_sink_methods,
+ Py_sink_members,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ (initproc) Py_sink_init,
+ 0,
+ Py_sink_new,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+};
-#include "aubiowraphell.h"
+#include "aubio-types.h"
typedef struct
{
uint_t samplerate;
uint_t channels;
uint_t hop_size;
+ uint_t duration;
+ PyObject *read_to;
+ fvec_t c_read_to;
+ PyObject *mread_to;
+ fmat_t c_mread_to;
} Py_source;
static char Py_source_doc[] = ""
return NULL;
}
- self->uri = "none";
+ self->uri = NULL;
if (uri != NULL) {
- self->uri = uri;
+ self->uri = (char_t *)malloc(sizeof(char_t) * (strnlen(uri, PATH_MAX) + 1));
+ strncpy(self->uri, uri, strnlen(uri, PATH_MAX) + 1);
}
self->samplerate = 0;
{
self->o = new_aubio_source ( self->uri, self->samplerate, self->hop_size );
if (self->o == NULL) {
- char_t errstr[30 + strlen(self->uri)];
- sprintf(errstr, "error creating source with %s", self->uri);
- PyErr_SetString (PyExc_StandardError, errstr);
+ // PyErr_Format(PyExc_RuntimeError, ...) was set above by new_ which called
+ // AUBIO_ERR when failing
return -1;
}
self->samplerate = aubio_source_get_samplerate ( self->o );
if (self->channels == 0) {
self->channels = aubio_source_get_channels ( self->o );
}
+ self->duration = aubio_source_get_duration ( self->o );
+
+ self->read_to = new_py_fvec(self->hop_size);
+ self->mread_to = new_py_fmat(self->channels, self->hop_size);
return 0;
}
-AUBIO_DEL(source)
+static void
+Py_source_del (Py_source *self, PyObject *unused)
+{
+ if (self->o) {
+ del_aubio_source(self->o);
+ free(self->c_mread_to.data);
+ }
+ if (self->uri) {
+ free(self->uri);
+ }
+ Py_XDECREF(self->read_to);
+ Py_XDECREF(self->mread_to);
+ Py_TYPE(self)->tp_free((PyObject *) self);
+}
+
/* function Py_source_do */
static PyObject *
Py_source_do(Py_source * self, PyObject * args)
{
-
-
- /* output vectors prototypes */
- fvec_t* read_to;
+ PyObject *outputs;
uint_t read;
-
-
-
-
-
-
- /* creating output read_to as a new_fvec of length self->hop_size */
- read_to = new_fvec (self->hop_size);
read = 0;
-
+ Py_INCREF(self->read_to);
+ if (!PyAubio_ArrayToCFvec(self->read_to, &(self->c_read_to))) {
+ return NULL;
+ }
/* compute _do function */
- aubio_source_do (self->o, read_to, &read);
+ aubio_source_do (self->o, &(self->c_read_to), &read);
- PyObject *outputs = PyList_New(0);
- PyList_Append( outputs, (PyObject *)PyAubio_CFvecToArray (read_to));
- //del_fvec (read_to);
- PyList_Append( outputs, (PyObject *)PyInt_FromLong (read));
+ outputs = PyTuple_New(2);
+ PyTuple_SetItem( outputs, 0, self->read_to );
+ PyTuple_SetItem( outputs, 1, (PyObject *)PyLong_FromLong(read));
return outputs;
}
static PyObject *
Py_source_do_multi(Py_source * self, PyObject * args)
{
-
-
- /* output vectors prototypes */
- fmat_t* read_to;
+ PyObject *outputs;
uint_t read;
-
-
-
-
-
-
- /* creating output read_to as a new_fvec of length self->hop_size */
- read_to = new_fmat (self->channels, self->hop_size);
read = 0;
-
+ Py_INCREF(self->mread_to);
+ if (!PyAubio_ArrayToCFmat(self->mread_to, &(self->c_mread_to))) {
+ return NULL;
+ }
/* compute _do function */
- aubio_source_do_multi (self->o, read_to, &read);
+ aubio_source_do_multi (self->o, &(self->c_mread_to), &read);
- PyObject *outputs = PyList_New(0);
- PyList_Append( outputs, (PyObject *)PyAubio_CFmatToArray (read_to));
- //del_fvec (read_to);
- PyList_Append( outputs, (PyObject *)PyInt_FromLong (read));
+ outputs = PyTuple_New(2);
+ PyTuple_SetItem( outputs, 0, self->mread_to);
+ PyTuple_SetItem( outputs, 1, (PyObject *)PyLong_FromLong(read));
return outputs;
}
-AUBIO_MEMBERS_START(source)
+static PyMemberDef Py_source_members[] = {
{"uri", T_STRING, offsetof (Py_source, uri), READONLY,
"path at which the source was created"},
{"samplerate", T_INT, offsetof (Py_source, samplerate), READONLY,
"number of channels found in the source"},
{"hop_size", T_INT, offsetof (Py_source, hop_size), READONLY,
"number of consecutive frames that will be read at each do or do_multi call"},
-AUBIO_MEMBERS_STOP(source)
-
+ {"duration", T_INT, offsetof (Py_source, duration), READONLY,
+ "total number of frames in the source (estimated)"},
+ { NULL } // sentinel
+};
static PyObject *
Pyaubio_source_get_samplerate (Py_source *self, PyObject *unused)
{
uint_t tmp = aubio_source_get_samplerate (self->o);
- return (PyObject *)PyInt_FromLong (tmp);
+ return (PyObject *)PyLong_FromLong (tmp);
}
static PyObject *
Pyaubio_source_get_channels (Py_source *self, PyObject *unused)
{
uint_t tmp = aubio_source_get_channels (self->o);
- return (PyObject *)PyInt_FromLong (tmp);
+ return (PyObject *)PyLong_FromLong (tmp);
}
static PyObject *
Pyaubio_source_close (Py_source *self, PyObject *unused)
{
- aubio_source_close (self->o);
+ if (aubio_source_close(self->o) != 0) return NULL;
Py_RETURN_NONE;
}
{
uint_t err = 0;
- uint_t position;
+ int position;
if (!PyArg_ParseTuple (args, "I", &position)) {
return NULL;
}
+ if (position < 0) {
+ PyErr_Format(PyExc_ValueError,
+ "error when seeking in source: can not seek to negative value %d",
+ position);
+ return NULL;
+ }
+
err = aubio_source_seek(self->o, position);
if (err != 0) {
PyErr_SetString (PyExc_ValueError,
Py_RETURN_NONE;
}
+static char Pyaubio_source_enter_doc[] = "";
+static PyObject* Pyaubio_source_enter(Py_source *self, PyObject *unused) {
+ Py_INCREF(self);
+ return (PyObject*)self;
+}
+
+static char Pyaubio_source_exit_doc[] = "";
+static PyObject* Pyaubio_source_exit(Py_source *self, PyObject *unused) {
+ return Pyaubio_source_close(self, unused);
+}
+
+static PyObject* Pyaubio_source_iter(PyObject *self) {
+ Py_INCREF(self);
+ return (PyObject*)self;
+}
+
+static PyObject* Pyaubio_source_iter_next(Py_source *self) {
+ PyObject *done, *size;
+ if (self->channels == 1) {
+ done = Py_source_do(self, NULL);
+ } else {
+ done = Py_source_do_multi(self, NULL);
+ }
+ if (!PyTuple_Check(done)) {
+ PyErr_Format(PyExc_ValueError,
+ "error when reading source: not opened?");
+ return NULL;
+ }
+ size = PyTuple_GetItem(done, 1);
+ if (size != NULL && PyLong_Check(size)) {
+ if (PyLong_AsLong(size) == (long)self->hop_size) {
+ PyObject *vec = PyTuple_GetItem(done, 0);
+ return vec;
+ } else if (PyLong_AsLong(size) > 0) {
+ // short read, return a shorter array
+ PyArrayObject *shortread = (PyArrayObject*)PyTuple_GetItem(done, 0);
+ PyArray_Dims newdims;
+ PyObject *reshaped;
+ newdims.len = PyArray_NDIM(shortread);
+ newdims.ptr = PyArray_DIMS(shortread);
+ // mono or multiple channels?
+ if (newdims.len == 1) {
+ newdims.ptr[0] = PyLong_AsLong(size);
+ } else {
+ newdims.ptr[1] = PyLong_AsLong(size);
+ }
+ reshaped = PyArray_Newshape(shortread, &newdims, NPY_CORDER);
+ Py_DECREF(shortread);
+ return reshaped;
+ } else {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+ } else {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+}
+
static PyMethodDef Py_source_methods[] = {
{"get_samplerate", (PyCFunction) Pyaubio_source_get_samplerate,
METH_NOARGS, Py_source_get_samplerate_doc},
METH_NOARGS, Py_source_close_doc},
{"seek", (PyCFunction) Pyaubio_source_seek,
METH_VARARGS, Py_source_seek_doc},
+ {"__enter__", (PyCFunction)Pyaubio_source_enter, METH_NOARGS,
+ Pyaubio_source_enter_doc},
+ {"__exit__", (PyCFunction)Pyaubio_source_exit, METH_VARARGS,
+ Pyaubio_source_exit_doc},
{NULL} /* sentinel */
};
-AUBIO_TYPEOBJECT(source, "aubio.source")
+PyTypeObject Py_sourceType = {
+ PyVarObject_HEAD_INIT (NULL, 0)
+ "aubio.source",
+ sizeof (Py_source),
+ 0,
+ (destructor) Py_source_del,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ (ternaryfunc)Py_source_do,
+ 0,
+ 0,
+ 0,
+ 0,
+ Py_TPFLAGS_DEFAULT,
+ Py_source_doc,
+ 0,
+ 0,
+ 0,
+ 0,
+ Pyaubio_source_iter,
+ (unaryfunc)Pyaubio_source_iter_next,
+ Py_source_methods,
+ Py_source_members,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ (initproc) Py_source_init,
+ 0,
+ Py_source_new,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+};
void add_ufuncs ( PyObject *m )
{
int err = 0;
+ PyObject *dict, *f, *g, *h;
err = _import_umath ();
if (err != 0) {
"Unable to import Numpy umath from aubio module (error %d)\n", err);
}
- PyObject *f, *dict;
dict = PyModule_GetDict(m);
f = PyUFunc_FromFuncAndData(Py_aubio_unary_functions, Py_unwrap2pi_data, Py_aubio_unary_types,
Py_aubio_unary_n_types, Py_aubio_unary_n_inputs, Py_aubio_unary_n_outputs,
PyDict_SetItemString(dict, "unwrap2pi", f);
Py_DECREF(f);
- PyObject *g;
g = PyUFunc_FromFuncAndData(Py_aubio_unary_functions, Py_freqtomidi_data, Py_aubio_unary_types,
Py_aubio_unary_n_types, Py_aubio_unary_n_inputs, Py_aubio_unary_n_outputs,
PyUFunc_None, "freqtomidi", Py_freqtomidi_doc, 0);
PyDict_SetItemString(dict, "freqtomidi", g);
Py_DECREF(g);
- PyObject *h;
h = PyUFunc_FromFuncAndData(Py_aubio_unary_functions, Py_miditofreq_data, Py_aubio_unary_types,
Py_aubio_unary_n_types, Py_aubio_unary_n_inputs, Py_aubio_unary_n_outputs,
PyUFunc_None, "miditofreq", Py_miditofreq_doc, 0);
#! /usr/bin/env python
import numpy
-from _aubio import *
-from midiconv import *
-from slicing import *
+from ._aubio import __version__ as version
+from ._aubio import float_type
+from ._aubio import *
+from .midiconv import *
+from .slicing import *
class fvec(numpy.ndarray):
- " a simple numpy array holding a vector of float32 "
- def __new__(self, length = 1024, **kwargs):
- self.length = length
- if type(length) == type([]):
- return numpy.array(length, dtype='float32', **kwargs)
- return numpy.zeros(length, dtype='float32', **kwargs)
+ """a numpy vector holding audio samples"""
+
+ def __new__(cls, input_arg=1024, **kwargs):
+ if isinstance(input_arg, int):
+ if input_arg == 0:
+ raise ValueError("vector length of 1 or more expected")
+ return numpy.zeros(input_arg, dtype=float_type, **kwargs)
+ else:
+ return numpy.array(input_arg, dtype=float_type, **kwargs)
# -*- coding: utf-8 -*-
+""" utilities to convert midi note number to and from note names """
+
+__all__ = ['note2midi', 'midi2note', 'freq2note']
+
+import sys
+py3 = sys.version_info[0] == 3
+if py3:
+ str_instances = str
+ int_instances = int
+else:
+ str_instances = (str, unicode)
+ int_instances = (int, long)
def note2midi(note):
" convert note name to midi note number, e.g. [C-1, G9] -> [0, 127] "
_valid_notenames = {'C': 0, 'D': 2, 'E': 4, 'F': 5, 'G': 7, 'A': 9, 'B': 11}
- _valid_modifiers = {None: 0, u'♮': 0, '#': +1, u'♯': +1, u'\udd2a': +2, 'b': -1, u'♭': -1, u'\ufffd': -2}
+ _valid_modifiers = {
+ u'𝄫': -2, # double flat
+ u'♭': -1, 'b': -1, '\u266d': -1, # simple flat
+ u'♮': 0, '\u266e': 0, None: 0, # natural
+ '#': +1, u'♯': +1, '\u266f': +1, # sharp
+ u'𝄪': +2, # double sharp
+ }
_valid_octaves = range(-1, 10)
- if type(note) not in (str, unicode):
- raise TypeError, "a string is required, got %s" % note
- if not (1 < len(note) < 5):
- raise ValueError, "string of 2 to 4 characters expected, got %d (%s)" % (len(note), note)
+ if not isinstance(note, str_instances):
+ raise TypeError("a string is required, got %s (%s)" % (note, str(type(note))))
+ if len(note) not in range(2, 5):
+ raise ValueError("string of 2 to 4 characters expected, got %d (%s)" \
+ % (len(note), note))
notename, modifier, octave = [None]*3
if len(note) == 4:
octave = int(octave)
if notename not in _valid_notenames:
- raise ValueError, "%s is not a valid note name" % notename
+ raise ValueError("%s is not a valid note name" % notename)
if modifier not in _valid_modifiers:
- raise ValueError, "%s is not a valid modifier" % modifier
+ raise ValueError("%s is not a valid modifier" % modifier)
if octave not in _valid_octaves:
- raise ValueError, "%s is not a valid octave" % octave
+ raise ValueError("%s is not a valid octave" % octave)
midi = 12 + octave * 12 + _valid_notenames[notename] + _valid_modifiers[modifier]
if midi > 127:
- raise ValueError, "%s is outside of the range C-2 to G8" % note
+ raise ValueError("%s is outside of the range C-2 to G8" % note)
return midi
def midi2note(midi):
" convert midi note number to note name, e.g. [0, 127] -> [C-1, G9] "
- if type(midi) != int:
- raise TypeError, "an integer is required, got %s" % midi
- if not (-1 < midi < 128):
- raise ValueError, "an integer between 0 and 127 is excepted, got %d" % midi
- midi = int(midi)
+ if not isinstance(midi, int_instances):
+ raise TypeError("an integer is required, got %s" % midi)
+ if midi not in range(0, 128):
+ raise ValueError("an integer between 0 and 127 is excepted, got %d" % midi)
_valid_notenames = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']
- return _valid_notenames[midi % 12] + str( midi / 12 - 1)
+ return _valid_notenames[midi % 12] + str(int(midi / 12) - 1)
def freq2note(freq):
+ " convert frequency in Hz to nearest note name, e.g. [0, 22050.] -> [C-1, G9] "
from aubio import freqtomidi
return midi2note(int(freqtomidi(freq)))
-from aubio import source, sink
+"""utility routines to slice sound files at given timestamps"""
+
import os
+from aubio import source, sink
-max_timestamp = 1e120
+_max_timestamp = 1e120
-def slice_source_at_stamps(source_file, timestamps, timestamps_end = None,
- output_dir = None,
- samplerate = 0,
- hopsize = 256):
+def slice_source_at_stamps(source_file, timestamps, timestamps_end=None,
+ output_dir=None, samplerate=0, hopsize=256):
+ """ slice a sound file at given timestamps """
- if timestamps == None or len(timestamps) == 0:
- raise ValueError ("no timestamps given")
+ if timestamps is None or len(timestamps) == 0:
+ raise ValueError("no timestamps given")
if timestamps[0] != 0:
timestamps = [0] + timestamps
- if timestamps_end != None:
+ if timestamps_end is not None:
timestamps_end = [timestamps[1] - 1] + timestamps_end
- if timestamps_end != None:
+ if timestamps_end is not None:
if len(timestamps_end) != len(timestamps):
- raise ValueError ("len(timestamps_end) != len(timestamps)")
+ raise ValueError("len(timestamps_end) != len(timestamps)")
else:
- timestamps_end = [t - 1 for t in timestamps[1:] ] + [ max_timestamp ]
+ timestamps_end = [t - 1 for t in timestamps[1:]] + [_max_timestamp]
- regions = zip(timestamps, timestamps_end)
+ regions = list(zip(timestamps, timestamps_end))
#print regions
- source_base_name, source_ext = os.path.splitext(os.path.basename(source_file))
- if output_dir != None:
+ source_base_name, _ = os.path.splitext(os.path.basename(source_file))
+ if output_dir is not None:
if not os.path.isdir(output_dir):
os.makedirs(output_dir)
source_base_name = os.path.join(output_dir, source_base_name)
def new_sink_name(source_base_name, timestamp, samplerate):
+ """ create a sink based on a timestamp in samples, converted in seconds """
timestamp_seconds = timestamp / float(samplerate)
return source_base_name + "_%011.6f" % timestamp_seconds + '.wav'
- # reopen source file
- s = source(source_file, samplerate, hopsize)
- samplerate = s.get_samplerate()
+ # open source file
+ _source = source(source_file, samplerate, hopsize)
+ samplerate = _source.samplerate
total_frames = 0
slices = []
while True:
# get hopsize new samples from source
- vec, read = s.do_multi()
+ vec, read = _source.do_multi()
# if the total number of frames read will exceed the next region start
if len(regions) and total_frames + read >= regions[0][0]:
#print "getting", regions[0], "at", total_frames
# create a name for the sink
new_sink_path = new_sink_name(source_base_name, start_stamp, samplerate)
# create its sink
- g = sink(new_sink_path, samplerate, s.channels)
+ _sink = sink(new_sink_path, samplerate, _source.channels)
# create a dictionary containing all this
- new_slice = {'start_stamp': start_stamp, 'end_stamp': end_stamp, 'sink': g}
+ new_slice = {'start_stamp': start_stamp, 'end_stamp': end_stamp, 'sink': _sink}
# append the dictionary to the current list of slices
slices.append(new_slice)
for current_slice in slices:
start_stamp = current_slice['start_stamp']
end_stamp = current_slice['end_stamp']
- g = current_slice['sink']
+ _sink = current_slice['sink']
# sample index to start writing from new source vector
start = max(start_stamp - total_frames, 0)
# number of samples yet to written be until end of region
if remaining < read:
if remaining > start:
# write remaining samples from current region
- g.do_multi(vec[:,start:remaining], remaining - start)
+ _sink.do_multi(vec[:, start:remaining], remaining - start)
#print "closing region", "remaining", remaining
# close this file
- g.close()
+ _sink.close()
elif read > start:
# write all the samples
- g.do_multi(vec[:,start:read], read - start)
+ _sink.do_multi(vec[:, start:read], read - start)
total_frames += read
- if read < hopsize: break
+ if read < hopsize:
+ break
--- /dev/null
+aubiodefvalue = {
+ # we have some clean up to do
+ 'buf_size': 'Py_default_vector_length',
+ 'win_s': 'Py_default_vector_length',
+ # and here too
+ 'hop_size': 'Py_default_vector_length / 2',
+ 'hop_s': 'Py_default_vector_length / 2',
+ # these should be alright
+ 'samplerate': 'Py_aubio_default_samplerate',
+ # now for the non obvious ones
+ 'n_filters': '40',
+ 'n_coeffs': '13',
+ 'nelems': '10',
+ 'flow': '0.',
+ 'fhig': '1.',
+ 'ilow': '0.',
+ 'ihig': '1.',
+ 'thrs': '0.5',
+ 'ratio': '0.5',
+ 'method': '"default"',
+ 'uri': '"none"',
+ }
+
+member_types = {
+ 'name': 'type',
+ 'char_t*': 'T_STRING',
+ 'uint_t': 'T_INT',
+ 'smpl_t': 'AUBIO_NPY_SMPL',
+ }
+
+pyfromtype_fn = {
+ 'smpl_t': 'PyFloat_FromDouble',
+ 'uint_t': 'PyLong_FromLong', # was: 'PyInt_FromLong',
+ 'fvec_t*': 'PyAubio_CFvecToArray',
+ 'fmat_t*': 'PyAubio_CFmatToArray',
+ }
+
+pytoaubio_fn = {
+ 'fvec_t*': 'PyAubio_ArrayToCFvec',
+ 'cvec_t*': 'PyAubio_PyCvecToCCvec',
+ #'fmat_t*': 'PyAubio_ArrayToCFmat',
+ }
+
+newfromtype_fn = {
+ 'fvec_t*': 'new_py_fvec',
+ 'fmat_t*': 'new_py_fmat',
+ 'cvec_t*': 'new_py_cvec',
+ }
+
+delfromtype_fn = {
+ 'fvec_t*': 'Py_DECREF',
+ 'fmat_t*': 'Py_DECREF',
+ 'cvec_t*': 'Py_DECREF',
+ }
+
+param_init = {
+ 'char_t*': 'NULL',
+ 'uint_t': '0',
+ 'sint_t': 0,
+ 'smpl_t': 0.,
+ 'lsmp_t': 0.,
+ }
+
+pyargparse_chars = {
+ 'smpl_t': 'f', # if not usedouble else 'd',
+ 'uint_t': 'I',
+ 'sint_t': 'I',
+ 'char_t*': 's',
+ 'fmat_t*': 'O',
+ 'fvec_t*': 'O',
+ 'cvec_t*': 'O',
+ }
+
+objoutsize = {
+ 'onset': '1',
+ 'pitch': '1',
+ 'notes': '3',
+ 'wavetable': 'self->hop_size',
+ 'sampler': 'self->hop_size',
+ 'mfcc': 'self->n_coeffs',
+ 'specdesc': '1',
+ 'tempo': '1',
+ 'filterbank': 'self->n_filters',
+ 'tss': 'self->buf_size',
+ }
+
+objinputsize = {
+ 'mfcc': 'self->buf_size / 2 + 1',
+ 'notes': 'self->hop_size',
+ 'onset': 'self->hop_size',
+ 'pitch': 'self->hop_size',
+ 'sampler': 'self->hop_size',
+ 'specdesc': 'self->buf_size / 2 + 1',
+ 'tempo': 'self->hop_size',
+ 'wavetable': 'self->hop_size',
+ 'tss': 'self->buf_size / 2 + 1',
+ }
+
+def get_name(proto):
+ name = proto.replace(' *', '* ').split()[1].split('(')[0]
+ name = name.replace('*','')
+ if name == '': raise ValueError(proto + "gave empty name")
+ return name
+
+def get_return_type(proto):
+ import re
+ paramregex = re.compile('(\w+ ?\*?).*')
+ outputs = paramregex.findall(proto)
+ assert len(outputs) == 1
+ return outputs[0].replace(' ', '')
+
+def split_type(arg):
+ """ arg = 'foo *name'
+ return ['foo*', 'name'] """
+ l = arg.split()
+ type_arg = {} #'type': l[0], 'name': l[1]}
+ type_arg['type'] = " ".join(l[:-1])
+ type_arg['name'] = l[-1]
+ # fix up type / name
+ if type_arg['name'].startswith('*'):
+ # ['foo', '*name'] -> ['foo*', 'name']
+ type_arg['type'] += '*'
+ type_arg['name'] = type_arg['name'][1:]
+ if type_arg['type'].endswith(' *'):
+ # ['foo *', 'name'] -> ['foo*', 'name']
+ type_arg['type'] = type_arg['type'].replace(' *','*')
+ if type_arg['type'].startswith('const '):
+ # ['foo *', 'name'] -> ['foo*', 'name']
+ type_arg['type'] = type_arg['type'].replace('const ','')
+ return type_arg
+
+def get_params(proto):
+ """ get the list of parameters from a function prototype
+ example: proto = "int main (int argc, char ** argv)"
+ returns: ['int argc', 'char ** argv']
+ """
+ import re
+ paramregex = re.compile('.*\((.*)\);')
+ a = paramregex.findall(proto)[0].split(', ')
+ #a = [i.replace('const ', '') for i in a]
+ return a
+
+def get_input_params(proto):
+ a = get_params(proto)
+ return [i.replace('const ', '') for i in a if (i.startswith('const ') or i.startswith('uint_t ') or i.startswith('smpl_t '))]
+
+def get_output_params(proto):
+ a = get_params(proto)
+ return [i for i in a if not i.startswith('const ')][1:]
+
+def get_params_types_names(proto):
+ """ get the list of parameters from a function prototype
+ example: proto = "int main (int argc, char ** argv)"
+ returns: [['int', 'argc'], ['char **','argv']]
+ """
+ a = list(map(split_type, get_params(proto)))
+ #print proto, a
+ #import sys; sys.exit(1)
+ return a
+
+class MappedObject(object):
+
+ def __init__(self, prototypes, usedouble = False):
+ if usedouble:
+ pyargparse_chars['smpl_t'] = 'd'
+ self.prototypes = prototypes
+
+ self.shortname = prototypes['shortname']
+ self.longname = prototypes['longname']
+ self.new_proto = prototypes['new'][0]
+ self.del_proto = prototypes['del'][0]
+ self.do_proto = prototypes['do'][0]
+ self.input_params = get_params_types_names(self.new_proto)
+ self.input_params_list = "; ".join(get_input_params(self.new_proto))
+ self.outputs = get_params_types_names(self.do_proto)[2:]
+ self.do_inputs = [get_params_types_names(self.do_proto)[1]]
+ self.do_outputs = get_params_types_names(self.do_proto)[2:]
+ struct_output_str = ["PyObject *{0[name]}; {1} c_{0[name]}".format(i, i['type'][:-1]) for i in self.do_outputs]
+ self.struct_outputs = ";\n ".join(struct_output_str)
+
+ #print ("input_params: ", map(split_type, get_input_params(self.do_proto)))
+ #print ("output_params", map(split_type, get_output_params(self.do_proto)))
+
+ def gen_code(self):
+ out = ""
+ out += self.gen_struct()
+ out += self.gen_doc()
+ out += self.gen_new()
+ out += self.gen_init()
+ out += self.gen_del()
+ out += self.gen_do()
+ out += self.gen_memberdef()
+ out += self.gen_set()
+ out += self.gen_get()
+ out += self.gen_methodef()
+ out += self.gen_typeobject()
+ return out
+
+ def gen_struct(self):
+ out = """
+// {shortname} structure
+typedef struct{{
+ PyObject_HEAD
+ // pointer to aubio object
+ {longname} *o;
+ // input parameters
+ {input_params_list};
+ // do input vectors
+ {do_inputs_list};
+ // output results
+ {struct_outputs};
+}} Py_{shortname};
+"""
+ # fmat_t* / fvec_t* / cvec_t* inputs -> full fvec_t /.. struct in Py_{shortname}
+ do_inputs_list = "; ".join(get_input_params(self.do_proto)).replace('fvec_t *','fvec_t').replace('fmat_t *', 'fmat_t').replace('cvec_t *', 'cvec_t')
+ return out.format(do_inputs_list = do_inputs_list, **self.__dict__)
+
+ def gen_doc(self):
+ out = """
+// TODO: add documentation
+static char Py_{shortname}_doc[] = \"undefined\";
+"""
+ return out.format(**self.__dict__)
+
+ def gen_new(self):
+ out = """
+// new {shortname}
+static PyObject *
+Py_{shortname}_new (PyTypeObject * pytype, PyObject * args, PyObject * kwds)
+{{
+ Py_{shortname} *self;
+""".format(**self.__dict__)
+ params = self.input_params
+ for p in params:
+ out += """
+ {type} {name} = {defval};""".format(defval = param_init[p['type']], **p)
+ plist = ", ".join(["\"%s\"" % p['name'] for p in params])
+ out += """
+ static char *kwlist[] = {{ {plist}, NULL }};""".format(plist = plist)
+ argchars = "".join([pyargparse_chars[p['type']] for p in params])
+ arglist = ", ".join(["&%s" % p['name'] for p in params])
+ out += """
+ if (!PyArg_ParseTupleAndKeywords (args, kwds, "|{argchars}", kwlist,
+ {arglist})) {{
+ return NULL;
+ }}
+""".format(argchars = argchars, arglist = arglist)
+ out += """
+ self = (Py_{shortname} *) pytype->tp_alloc (pytype, 0);
+ if (self == NULL) {{
+ return NULL;
+ }}
+""".format(**self.__dict__)
+ params = self.input_params
+ for p in params:
+ out += self.check_valid(p)
+ out += """
+ return (PyObject *)self;
+}
+"""
+ return out
+
+ def check_valid(self, p):
+ if p['type'] == 'uint_t':
+ return self.check_valid_uint(p)
+ if p['type'] == 'char_t*':
+ return self.check_valid_char(p)
+ else:
+ print ("ERROR, no idea how to check %s for validity" % p['type'])
+
+ def check_valid_uint(self, p):
+ name = p['name']
+ return """
+ self->{name} = {defval};
+ if ((sint_t){name} > 0) {{
+ self->{name} = {name};
+ }} else if ((sint_t){name} < 0) {{
+ PyErr_SetString (PyExc_ValueError, "can not use negative value for {name}");
+ return NULL;
+ }}
+""".format(defval = aubiodefvalue[name], name = name)
+
+ def check_valid_char(self, p):
+ name = p['name']
+ return """
+ self->{name} = {defval};
+ if ({name} != NULL) {{
+ self->{name} = {name};
+ }}
+""".format(defval = aubiodefvalue[name], name = name)
+
+ def gen_init(self):
+ out = """
+// init {shortname}
+static int
+Py_{shortname}_init (Py_{shortname} * self, PyObject * args, PyObject * kwds)
+{{
+""".format(**self.__dict__)
+ new_name = get_name(self.new_proto)
+ new_params = ", ".join(["self->%s" % s['name'] for s in self.input_params])
+ out += """
+ self->o = {new_name}({new_params});
+""".format(new_name = new_name, new_params = new_params)
+ paramchars = "%s"
+ paramvals = "self->method"
+ out += """
+ // return -1 and set error string on failure
+ if (self->o == NULL) {{
+ PyErr_Format (PyExc_RuntimeError, "failed creating {shortname}");
+ return -1;
+ }}
+""".format(paramchars = paramchars, paramvals = paramvals, **self.__dict__)
+ output_create = ""
+ for o in self.outputs:
+ output_create += """
+ self->{name} = {create_fn}({output_size});""".format(name = o['name'], create_fn = newfromtype_fn[o['type']], output_size = objoutsize[self.shortname])
+ out += """
+ // TODO get internal params after actual object creation?
+"""
+ out += """
+ // create outputs{output_create}
+""".format(output_create = output_create)
+ out += """
+ return 0;
+}
+"""
+ return out
+
+ def gen_memberdef(self):
+ out = """
+static PyMemberDef Py_{shortname}_members[] = {{
+""".format(**self.__dict__)
+ for p in get_params_types_names(self.new_proto):
+ tmp = " {{\"{name}\", {ttype}, offsetof (Py_{shortname}, {name}), READONLY, \"TODO documentation\"}},\n"
+ pytype = member_types[p['type']]
+ out += tmp.format(name = p['name'], ttype = pytype, shortname = self.shortname)
+ out += """ {NULL}, // sentinel
+};
+"""
+ return out
+
+ def gen_del(self):
+ out = """
+// del {shortname}
+static void
+Py_{shortname}_del (Py_{shortname} * self, PyObject * unused)
+{{""".format(**self.__dict__)
+ for input_param in self.do_inputs:
+ if input_param['type'] == 'fmat_t *':
+ out += """
+ free(self->{0[name]}.data);""".format(input_param)
+ for o in self.outputs:
+ name = o['name']
+ del_out = delfromtype_fn[o['type']]
+ out += """
+ if (self->{name}) {{
+ {del_out}(self->{name});
+ }}""".format(del_out = del_out, name = name)
+ del_fn = get_name(self.del_proto)
+ out += """
+ if (self->o) {{
+ {del_fn}(self->o);
+ }}
+ Py_TYPE(self)->tp_free((PyObject *) self);
+}}
+""".format(del_fn = del_fn)
+ return out
+
+ def gen_do(self):
+ out = """
+// do {shortname}
+static PyObject*
+Py_{shortname}_do (Py_{shortname} * self, PyObject * args)
+{{""".format(**self.__dict__)
+ input_params = self.do_inputs
+ output_params = self.do_outputs
+ #print input_params
+ #print output_params
+ out += """
+ PyObject *outputs;"""
+ for input_param in input_params:
+ out += """
+ PyObject *py_{0};""".format(input_param['name'])
+ refs = ", ".join(["&py_%s" % p['name'] for p in input_params])
+ pyparamtypes = "".join([pyargparse_chars[p['type']] for p in input_params])
+ out += """
+ if (!PyArg_ParseTuple (args, "{pyparamtypes}", {refs})) {{
+ return NULL;
+ }}""".format(refs = refs, pyparamtypes = pyparamtypes, **self.__dict__)
+ for input_param in input_params:
+ out += """
+
+ if (!{pytoaubio}(py_{0[name]}, &(self->{0[name]}))) {{
+ return NULL;
+ }}""".format(input_param, pytoaubio = pytoaubio_fn[input_param['type']])
+ if self.shortname in objinputsize:
+ out += """
+
+ if (self->{0[name]}.length != {expected_size}) {{
+ PyErr_Format (PyExc_ValueError,
+ "input size of {shortname} should be %d, not %d",
+ {expected_size}, self->{0[name]}.length);
+ return NULL;
+ }}""".format(input_param, expected_size = objinputsize[self.shortname], **self.__dict__)
+ else:
+ out += """
+
+ // TODO: check input sizes"""
+ for output_param in output_params:
+ out += """
+
+ Py_INCREF(self->{0[name]});
+ if (!{pytoaubio}(self->{0[name]}, &(self->c_{0[name]}))) {{
+ return NULL;
+ }}""".format(output_param, pytoaubio = pytoaubio_fn[output_param['type']])
+ do_fn = get_name(self.do_proto)
+ inputs = ", ".join(['&(self->'+p['name']+')' for p in input_params])
+ c_outputs = ", ".join(["&(self->c_%s)" % p['name'] for p in self.do_outputs])
+ outputs = ", ".join(["self->%s" % p['name'] for p in self.do_outputs])
+ out += """
+
+ {do_fn}(self->o, {inputs}, {c_outputs});
+""".format(
+ do_fn = do_fn,
+ inputs = inputs, c_outputs = c_outputs,
+ )
+ if len(self.do_outputs) > 1:
+ out += """
+ outputs = PyTuple_New({:d});""".format(len(self.do_outputs))
+ for i, p in enumerate(self.do_outputs):
+ out += """
+ PyTuple_SetItem( outputs, {i}, self->{p[name]});""".format(i = i, p = p)
+ else:
+ out += """
+ outputs = self->{p[name]};""".format(p = self.do_outputs[0])
+ out += """
+
+ return outputs;
+}}
+""".format(
+ outputs = outputs,
+ )
+ return out
+
+ def gen_set(self):
+ out = """
+// {shortname} setters
+""".format(**self.__dict__)
+ for set_param in self.prototypes['set']:
+ params = get_params_types_names(set_param)[1]
+ paramtype = params['type']
+ method_name = get_name(set_param)
+ param = method_name.split('aubio_'+self.shortname+'_set_')[-1]
+ pyparamtype = pyargparse_chars[paramtype]
+ out += """
+static PyObject *
+Pyaubio_{shortname}_set_{param} (Py_{shortname} *self, PyObject *args)
+{{
+ uint_t err = 0;
+ {paramtype} {param};
+
+ if (!PyArg_ParseTuple (args, "{pyparamtype}", &{param})) {{
+ return NULL;
+ }}
+ err = aubio_{shortname}_set_{param} (self->o, {param});
+
+ if (err > 0) {{
+ PyErr_SetString (PyExc_ValueError, "error running aubio_{shortname}_set_{param}");
+ return NULL;
+ }}
+ Py_RETURN_NONE;
+}}
+""".format(param = param, paramtype = paramtype, pyparamtype = pyparamtype, **self.__dict__)
+ return out
+
+ def gen_get(self):
+ out = """
+// {shortname} getters
+""".format(**self.__dict__)
+ for method in self.prototypes['get']:
+ params = get_params_types_names(method)
+ method_name = get_name(method)
+ assert len(params) == 1, \
+ "get method has more than one parameter %s" % params
+ param = method_name.split('aubio_'+self.shortname+'_get_')[-1]
+ paramtype = get_return_type(method)
+ ptypeconv = pyfromtype_fn[paramtype]
+ out += """
+static PyObject *
+Pyaubio_{shortname}_get_{param} (Py_{shortname} *self, PyObject *unused)
+{{
+ {ptype} {param} = aubio_{shortname}_get_{param} (self->o);
+ return (PyObject *){ptypeconv} ({param});
+}}
+""".format(param = param, ptype = paramtype, ptypeconv = ptypeconv,
+ **self.__dict__)
+ return out
+
+ def gen_methodef(self):
+ out = """
+static PyMethodDef Py_{shortname}_methods[] = {{""".format(**self.__dict__)
+ for m in self.prototypes['set']:
+ name = get_name(m)
+ shortname = name.replace('aubio_%s_' % self.shortname, '')
+ out += """
+ {{"{shortname}", (PyCFunction) Py{name},
+ METH_VARARGS, ""}},""".format(name = name, shortname = shortname)
+ for m in self.prototypes['get']:
+ name = get_name(m)
+ shortname = name.replace('aubio_%s_' % self.shortname, '')
+ out += """
+ {{"{shortname}", (PyCFunction) Py{name},
+ METH_NOARGS, ""}},""".format(name = name, shortname = shortname)
+ out += """
+ {NULL} /* sentinel */
+};
+"""
+ return out
+
+ def gen_typeobject(self):
+ return """
+PyTypeObject Py_{shortname}Type = {{
+ //PyObject_HEAD_INIT (NULL)
+ //0,
+ PyVarObject_HEAD_INIT (NULL, 0)
+ "aubio.{shortname}",
+ sizeof (Py_{shortname}),
+ 0,
+ (destructor) Py_{shortname}_del,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ (ternaryfunc)Py_{shortname}_do,
+ 0,
+ 0,
+ 0,
+ 0,
+ Py_TPFLAGS_DEFAULT,
+ Py_{shortname}_doc,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ Py_{shortname}_methods,
+ Py_{shortname}_members,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ (initproc) Py_{shortname}_init,
+ 0,
+ Py_{shortname}_new,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+}};
+""".format(**self.__dict__)
--- /dev/null
+import distutils.ccompiler
+import sys, os, subprocess, glob
+
+header = os.path.join('src', 'aubio.h')
+output_path = os.path.join('python', 'gen')
+
+source_header = """// this file is generated! do not modify
+#include "aubio-types.h"
+"""
+
+skip_objects = [
+ # already in ext/
+ 'fft',
+ 'pvoc',
+ 'filter',
+ 'filterbank',
+ # AUBIO_UNSTABLE
+ 'hist',
+ 'parameter',
+ 'scale',
+ 'beattracking',
+ 'resampler',
+ 'peakpicker',
+ 'pitchfcomb',
+ 'pitchmcomb',
+ 'pitchschmitt',
+ 'pitchspecacf',
+ 'pitchyin',
+ 'pitchyinfft',
+ 'sink',
+ 'sink_apple_audio',
+ 'sink_sndfile',
+ 'sink_wavwrite',
+ #'mfcc',
+ 'source',
+ 'source_apple_audio',
+ 'source_sndfile',
+ 'source_avcodec',
+ 'source_wavread',
+ #'sampler',
+ 'audio_unit',
+ ]
+
+def get_preprocessor():
+ # findout which compiler to use
+ from distutils.sysconfig import customize_compiler
+ compiler_name = distutils.ccompiler.get_default_compiler()
+ compiler = distutils.ccompiler.new_compiler(compiler=compiler_name)
+ try:
+ customize_compiler(compiler)
+ except AttributeError as e:
+ print("Warning: failed customizing compiler ({:s})".format(repr(e)))
+
+ if hasattr(compiler, 'initialize'):
+ try:
+ compiler.initialize()
+ except ValueError as e:
+ print("Warning: failed initializing compiler ({:s})".format(repr(e)))
+
+ cpp_cmd = None
+ if hasattr(compiler, 'preprocessor'): # for unixccompiler
+ cpp_cmd = compiler.preprocessor
+ elif hasattr(compiler, 'compiler'): # for ccompiler
+ cpp_cmd = compiler.compiler.split()
+ cpp_cmd += ['-E']
+ elif hasattr(compiler, 'cc'): # for msvccompiler
+ cpp_cmd = compiler.cc.split()
+ cpp_cmd += ['-E']
+
+ if not cpp_cmd:
+ print("Warning: could not guess preprocessor, using env's CC")
+ cpp_cmd = os.environ.get('CC', 'cc').split()
+ cpp_cmd += ['-E']
+
+ return cpp_cmd
+
+def get_cpp_objects(header=header, usedouble=False):
+ cpp_cmd = get_preprocessor()
+
+ macros = [('AUBIO_UNSTABLE', 1)]
+ if usedouble:
+ macros += [('HAVE_AUBIO_DOUBLE', 1)]
+
+ if not os.path.isfile(header):
+ raise Exception("could not find include file " + header)
+
+ includes = [os.path.dirname(header)]
+ cpp_cmd += distutils.ccompiler.gen_preprocess_options(macros, includes)
+ cpp_cmd += [header]
+
+ print("Running command: {:s}".format(" ".join(cpp_cmd)))
+ proc = subprocess.Popen(cpp_cmd,
+ stderr=subprocess.PIPE,
+ stdout=subprocess.PIPE)
+ assert proc, 'Proc was none'
+ cpp_output = proc.stdout.read()
+ err_output = proc.stderr.read()
+ if not cpp_output:
+ raise Exception("preprocessor output is empty:\n%s" % err_output)
+ elif err_output:
+ print ("Warning: preprocessor produced warnings:\n%s" % err_output)
+ if not isinstance(cpp_output, list):
+ cpp_output = [l.strip() for l in cpp_output.decode('utf8').split('\n')]
+
+ cpp_output = filter(lambda y: len(y) > 1, cpp_output)
+ cpp_output = list(filter(lambda y: not y.startswith('#'), cpp_output))
+
+ i = 1
+ while 1:
+ if i >= len(cpp_output): break
+ if cpp_output[i-1].endswith(',') or cpp_output[i-1].endswith('{') or cpp_output[i].startswith('}'):
+ cpp_output[i] = cpp_output[i-1] + ' ' + cpp_output[i]
+ cpp_output.pop(i-1)
+ else:
+ i += 1
+
+ typedefs = filter(lambda y: y.startswith ('typedef struct _aubio'), cpp_output)
+
+ cpp_objects = [a.split()[3][:-1] for a in typedefs]
+
+ return cpp_output, cpp_objects
+
+
+def analyze_cpp_output(cpp_objects, cpp_output):
+ lib = {}
+
+ for o in cpp_objects:
+ if o[:6] != 'aubio_':
+ continue
+ shortname = o[6:-2]
+ if shortname in skip_objects:
+ continue
+ lib[shortname] = {'struct': [], 'new': [], 'del': [], 'do': [], 'get': [], 'set': [], 'other': []}
+ lib[shortname]['longname'] = o
+ lib[shortname]['shortname'] = shortname
+ for fn in cpp_output:
+ if o[:-1] in fn:
+ #print "found", o[:-1], "in", fn
+ if 'typedef struct ' in fn:
+ lib[shortname]['struct'].append(fn)
+ elif '_do' in fn:
+ lib[shortname]['do'].append(fn)
+ elif 'new_' in fn:
+ lib[shortname]['new'].append(fn)
+ elif 'del_' in fn:
+ lib[shortname]['del'].append(fn)
+ elif '_get_' in fn:
+ lib[shortname]['get'].append(fn)
+ elif '_set_' in fn:
+ lib[shortname]['set'].append(fn)
+ else:
+ #print "no idea what to do about", fn
+ lib[shortname]['other'].append(fn)
+ return lib
+
+def print_cpp_output_results(lib, cpp_output):
+ for fn in cpp_output:
+ found = 0
+ for o in lib:
+ for family in lib[o]:
+ if fn in lib[o][family]:
+ found = 1
+ if found == 0:
+ print ("missing", fn)
+
+ for o in lib:
+ for family in lib[o]:
+ if type(lib[o][family]) == str:
+ print ( "{:15s} {:10s} {:s}".format(o, family, lib[o][family] ) )
+ elif len(lib[o][family]) == 1:
+ print ( "{:15s} {:10s} {:s}".format(o, family, lib[o][family][0] ) )
+ else:
+ print ( "{:15s} {:10s} {:s}".format(o, family, lib[o][family] ) )
+
+
+def generate_external(header=header, output_path=output_path, usedouble=False, overwrite=True):
+ if not os.path.isdir(output_path): os.mkdir(output_path)
+ elif not overwrite: return sorted(glob.glob(os.path.join(output_path, '*.c')))
+
+ cpp_output, cpp_objects = get_cpp_objects(header, usedouble=usedouble)
+
+ lib = analyze_cpp_output(cpp_objects, cpp_output)
+ # print_cpp_output_results(lib, cpp_output)
+
+ sources_list = []
+ try:
+ from .gen_code import MappedObject
+ except (SystemError, ValueError):
+ from gen_code import MappedObject
+ for o in lib:
+ out = source_header
+ mapped = MappedObject(lib[o], usedouble = usedouble)
+ out += mapped.gen_code()
+ output_file = os.path.join(output_path, 'gen-%s.c' % o)
+ with open(output_file, 'w') as f:
+ f.write(out)
+ print ("wrote %s" % output_file )
+ sources_list.append(output_file)
+
+ out = source_header
+ out += "#include \"aubio-generated.h\""
+ check_types = "\n || ".join(["PyType_Ready(&Py_%sType) < 0" % o for o in lib])
+ out += """
+
+int generated_types_ready (void)
+{{
+ return ({pycheck_types});
+}}
+""".format(pycheck_types = check_types)
+
+ add_types = "".join(["""
+ Py_INCREF (&Py_{name}Type);
+ PyModule_AddObject(m, "{name}", (PyObject *) & Py_{name}Type);""".format(name = o) for o in lib])
+ out += """
+
+void add_generated_objects ( PyObject *m )
+{{
+{add_types}
+}}
+""".format(add_types = add_types)
+
+ output_file = os.path.join(output_path, 'aubio-generated.c')
+ with open(output_file, 'w') as f:
+ f.write(out)
+ print ("wrote %s" % output_file )
+ sources_list.append(output_file)
+
+ objlist = "".join(["extern PyTypeObject Py_%sType;\n" % p for p in lib])
+ out = """// generated list of objects created with gen_external.py
+
+#include <Python.h>
+"""
+ if usedouble:
+ out += """
+#ifndef HAVE_AUBIO_DOUBLE
+#define HAVE_AUBIO_DOUBLE 1
+#endif
+"""
+ out += """
+{objlist}
+int generated_objects ( void );
+void add_generated_objects( PyObject *m );
+""".format(objlist = objlist)
+
+ output_file = os.path.join(output_path, 'aubio-generated.h')
+ with open(output_file, 'w') as f:
+ f.write(out)
+ print ("wrote %s" % output_file )
+ # no need to add header to list of sources
+
+ return sorted(sources_list)
+
+if __name__ == '__main__':
+ if len(sys.argv) > 1: header = sys.argv[1]
+ if len(sys.argv) > 2: output_path = sys.argv[2]
+ generate_external(header, output_path)
+++ /dev/null
-#! /usr/bin/python
-
-""" This madness of code is used to generate the C code of the python interface
-to aubio. Don't try this at home.
-
-The list of typedefs and functions is obtained from the command line 'cpp
-aubio.h'. This list is then used to parse all the functions about this object.
-
-I hear the ones asking "why not use swig, or cython, or something like that?"
-
-The requirements for this extension are the following:
-
- - aubio vectors can be viewed as numpy arrays, and vice versa
- - aubio 'object' should be python classes, not just a bunch of functions
-
-I haven't met any python interface generator that can meet both these
-requirements. If you know of one, please let me know, it will spare me
-maintaining this bizarre file.
-"""
-
-param_numbers = {
- 'source': [0, 2],
- 'sink': [2, 0],
- 'sampler': [1, 1],
-}
-
-# TODO
-# do function: for now, only the following pattern is supported:
-# void aubio_<foo>_do (aubio_foo_t * o,
-# [input1_t * input, [output1_t * output, ..., output3_t * output]]);
-# There is no way of knowing that output1 is actually input2. In the future,
-# const could be used for the inputs in the C prototypes.
-
-def write_msg(*args):
- pass
- # uncomment out for debugging
- #print args
-
-def split_type(arg):
- """ arg = 'foo *name'
- return ['foo*', 'name'] """
- l = arg.split()
- type_arg = {'type': l[0], 'name': l[1]}
- # ['foo', '*name'] -> ['foo*', 'name']
- if l[-1].startswith('*'):
- #return [l[0]+'*', l[1][1:]]
- type_arg['type'] = l[0] + '*'
- type_arg['name'] = l[1][1:]
- # ['foo', '*', 'name'] -> ['foo*', 'name']
- if len(l) == 3:
- #return [l[0]+l[1], l[2]]
- type_arg['type'] = l[0]+l[1]
- type_arg['name'] = l[2]
- else:
- #return l
- pass
- return type_arg
-
-def get_params(proto):
- """ get the list of parameters from a function prototype
- example: proto = "int main (int argc, char ** argv)"
- returns: ['int argc', 'char ** argv']
- """
- import re
- paramregex = re.compile('[\(, ](\w+ \*?\*? ?\w+)[, \)]')
- return paramregex.findall(proto)
-
-def get_params_types_names(proto):
- """ get the list of parameters from a function prototype
- example: proto = "int main (int argc, char ** argv)"
- returns: [['int', 'argc'], ['char **','argv']]
- """
- return map(split_type, get_params(proto))
-
-def get_return_type(proto):
- import re
- paramregex = re.compile('(\w+ ?\*?).*')
- outputs = paramregex.findall(proto)
- assert len(outputs) == 1
- return outputs[0].replace(' ', '')
-
-def get_name(proto):
- name = proto.split()[1].split('(')[0]
- return name.replace('*','')
-
-# the important bits: the size of the output for each objects. this data should
-# move into the C library at some point.
-defaultsizes = {
- 'resampler': ['input->length * self->ratio'],
- 'specdesc': ['1'],
- 'onset': ['1'],
- 'pitchyin': ['1'],
- 'pitchyinfft': ['1'],
- 'pitchschmitt': ['1'],
- 'pitchmcomb': ['1'],
- 'pitchfcomb': ['1'],
- 'pitch': ['1'],
- 'tss': ['self->buf_size', 'self->buf_size'],
- 'mfcc': ['self->n_coeffs'],
- 'beattracking': ['self->hop_size'],
- 'tempo': ['1'],
- 'peakpicker': ['1'],
- 'source': ['self->hop_size', '1'],
- 'sampler': ['self->hop_size'],
- 'wavetable': ['self->hop_size'],
-}
-
-# default value for variables
-aubioinitvalue = {
- 'uint_t': 0,
- 'smpl_t': 0,
- 'lsmp_t': 0.,
- 'char_t*': 'NULL',
- }
-
-aubiodefvalue = {
- # we have some clean up to do
- 'buf_size': 'Py_default_vector_length',
- # and here too
- 'hop_size': 'Py_default_vector_length / 2',
- # these should be alright
- 'samplerate': 'Py_aubio_default_samplerate',
- # now for the non obvious ones
- 'n_filters': '40',
- 'n_coeffs': '13',
- 'nelems': '10',
- 'flow': '0.',
- 'fhig': '1.',
- 'ilow': '0.',
- 'ihig': '1.',
- 'thrs': '0.5',
- 'ratio': '0.5',
- 'method': '"default"',
- 'uri': '"none"',
- }
-
-# aubio to python
-aubio2pytypes = {
- 'uint_t': 'I',
- 'smpl_t': 'f',
- 'lsmp_t': 'd',
- 'fvec_t*': 'O',
- 'cvec_t*': 'O',
- 'char_t*': 's',
-}
-
-# python to aubio
-aubiovecfrompyobj = {
- 'fvec_t*': 'PyAubio_ArrayToCFvec',
- 'cvec_t*': 'PyAubio_ArrayToCCvec',
- 'uint_t': '(uint_t)PyInt_AsLong',
-}
-
-# aubio to python
-aubiovectopyobj = {
- 'fvec_t*': 'PyAubio_CFvecToArray',
- 'cvec_t*': 'PyAubio_CCvecToPyCvec',
- 'smpl_t': 'PyFloat_FromDouble',
- 'uint_t*': 'PyInt_FromLong',
- 'uint_t': 'PyInt_FromLong',
-}
-
-def gen_new_init(newfunc, name):
- newparams = get_params_types_names(newfunc)
- # self->param1, self->param2, self->param3
- if len(newparams):
- selfparams = ', self->'+', self->'.join([p['name'] for p in newparams])
- else:
- selfparams = ''
- # "param1", "param2", "param3"
- paramnames = ", ".join(["\""+p['name']+"\"" for p in newparams])
- pyparams = "".join(map(lambda p: aubio2pytypes[p['type']], newparams))
- paramrefs = ", ".join(["&" + p['name'] for p in newparams])
- s = """\
-// WARNING: this file is generated, DO NOT EDIT
-
-// WARNING: if you haven't read the first line yet, please do so
-#include "aubiowraphell.h"
-
-typedef struct
-{
- PyObject_HEAD
- aubio_%(name)s_t * o;
-""" % locals()
- for p in newparams:
- ptype = p['type']
- pname = p['name']
- s += """\
- %(ptype)s %(pname)s;
-""" % locals()
- s += """\
-} Py_%(name)s;
-
-static char Py_%(name)s_doc[] = "%(name)s object";
-
-static PyObject *
-Py_%(name)s_new (PyTypeObject * pytype, PyObject * args, PyObject * kwds)
-{
- Py_%(name)s *self;
-""" % locals()
- for p in newparams:
- ptype = p['type']
- pname = p['name']
- initval = aubioinitvalue[ptype]
- s += """\
- %(ptype)s %(pname)s = %(initval)s;
-""" % locals()
- # now the actual PyArg_Parse
- if len(paramnames):
- s += """\
- static char *kwlist[] = { %(paramnames)s, NULL };
-
- if (!PyArg_ParseTupleAndKeywords (args, kwds, "|%(pyparams)s", kwlist,
- %(paramrefs)s)) {
- return NULL;
- }
-""" % locals()
- s += """\
-
- self = (Py_%(name)s *) pytype->tp_alloc (pytype, 0);
-
- if (self == NULL) {
- return NULL;
- }
-""" % locals()
- for p in newparams:
- ptype = p['type']
- pname = p['name']
- defval = aubiodefvalue[pname]
- if ptype == 'char_t*':
- s += """\
-
- self->%(pname)s = %(defval)s;
- if (%(pname)s != NULL) {
- self->%(pname)s = %(pname)s;
- }
-""" % locals()
- elif ptype == 'uint_t':
- s += """\
-
- self->%(pname)s = %(defval)s;
- if ((sint_t)%(pname)s > 0) {
- self->%(pname)s = %(pname)s;
- } else if ((sint_t)%(pname)s < 0) {
- PyErr_SetString (PyExc_ValueError,
- "can not use negative value for %(pname)s");
- return NULL;
- }
-""" % locals()
- elif ptype == 'smpl_t':
- s += """\
-
- self->%(pname)s = %(defval)s;
- if (%(pname)s != %(defval)s) {
- self->%(pname)s = %(pname)s;
- }
-""" % locals()
- else:
- write_msg ("ERROR, unknown type of parameter %s %s" % (ptype, pname) )
- s += """\
-
- return (PyObject *) self;
-}
-
-AUBIO_INIT(%(name)s %(selfparams)s)
-
-AUBIO_DEL(%(name)s)
-
-""" % locals()
- return s
-
-def gen_do_input_params(inputparams):
- inputdefs = ''
- parseinput = ''
- inputrefs = ''
- inputvecs = ''
- pytypes = ''
-
- if len(inputparams):
- # build the parsing string for PyArg_ParseTuple
- pytypes = "".join([aubio2pytypes[p['type']] for p in inputparams])
-
- inputdefs = " /* input vectors python prototypes */\n"
- for p in inputparams:
- if p['type'] != 'uint_t':
- inputdefs += " PyObject * " + p['name'] + "_obj;\n"
-
- inputvecs = " /* input vectors prototypes */\n "
- inputvecs += "\n ".join(map(lambda p: p['type'] + ' ' + p['name'] + ";", inputparams))
-
- parseinput = " /* input vectors parsing */\n "
- for p in inputparams:
- inputvec = p['name']
- if p['type'] != 'uint_t':
- inputdef = p['name'] + "_obj"
- else:
- inputdef = p['name']
- converter = aubiovecfrompyobj[p['type']]
- if p['type'] != 'uint_t':
- parseinput += """%(inputvec)s = %(converter)s (%(inputdef)s);
-
- if (%(inputvec)s == NULL) {
- return NULL;
- }
-
- """ % locals()
-
- # build the string for the input objects references
- inputreflist = []
- for p in inputparams:
- if p['type'] != 'uint_t':
- inputreflist += [ "&" + p['name'] + "_obj" ]
- else:
- inputreflist += [ "&" + p['name'] ]
- inputrefs = ", ".join(inputreflist)
- # end of inputs strings
- return inputdefs, parseinput, inputrefs, inputvecs, pytypes
-
-def gen_do_output_params(outputparams, name):
- outputvecs = ""
- outputcreate = ""
- if len(outputparams):
- outputvecs = " /* output vectors prototypes */\n"
- for p in outputparams:
- params = {
- 'name': p['name'], 'pytype': p['type'], 'autype': p['type'][:-3],
- 'length': defaultsizes[name].pop(0) }
- if (p['type'] == 'uint_t*'):
- outputvecs += ' uint_t' + ' ' + p['name'] + ";\n"
- outputcreate += " %(name)s = 0;\n" % params
- else:
- outputvecs += " " + p['type'] + ' ' + p['name'] + ";\n"
- outputcreate += " /* creating output %(name)s as a new_%(autype)s of length %(length)s */\n" % params
- outputcreate += " %(name)s = new_%(autype)s (%(length)s);\n" % params
-
- returnval = "";
- if len(outputparams) > 1:
- returnval += " PyObject *outputs = PyList_New(0);\n"
- for p in outputparams:
- returnval += " PyList_Append( outputs, (PyObject *)" + aubiovectopyobj[p['type']] + " (" + p['name'] + ")" +");\n"
- returnval += " return outputs;"
- elif len(outputparams) == 1:
- if defaultsizes[name] == '1':
- returnval += " return (PyObject *)PyFloat_FromDouble(" + p['name'] + "->data[0])"
- else:
- returnval += " return (PyObject *)" + aubiovectopyobj[p['type']] + " (" + p['name'] + ")"
- else:
- returnval += " Py_RETURN_NONE"
- # end of output strings
- return outputvecs, outputcreate, returnval
-
-def gen_do(dofunc, name):
- funcname = dofunc.split()[1].split('(')[0]
- doparams = get_params_types_names(dofunc)
- # make sure the first parameter is the object
- assert doparams[0]['type'] == "aubio_"+name+"_t*", \
- "method is not in 'aubio_<name>_t"
- # and remove it
- doparams = doparams[1:]
-
- n_param = len(doparams)
-
- if name in param_numbers.keys():
- n_input_param, n_output_param = param_numbers[name]
- else:
- n_input_param, n_output_param = 1, n_param - 1
-
- assert n_output_param + n_input_param == n_param, "n_output_param + n_input_param != n_param for %s" % name
-
- inputparams = doparams[:n_input_param]
- outputparams = doparams[n_input_param:n_input_param + n_output_param]
-
- inputdefs, parseinput, inputrefs, inputvecs, pytypes = gen_do_input_params(inputparams);
- outputvecs, outputcreate, returnval = gen_do_output_params(outputparams, name)
-
- # build strings for outputs
- # build the parameters for the _do() call
- doparams_string = "self->o"
- for p in doparams:
- if p['type'] == 'uint_t*':
- doparams_string += ", &" + p['name']
- else:
- doparams_string += ", " + p['name']
-
- if n_input_param:
- arg_parse_tuple = """\
- if (!PyArg_ParseTuple (args, "%(pytypes)s", %(inputrefs)s)) {
- return NULL;
- }
-""" % locals()
- else:
- arg_parse_tuple = ""
- # put it all together
- s = """\
-/* function Py_%(name)s_do */
-static PyObject *
-Py_%(name)s_do(Py_%(name)s * self, PyObject * args)
-{
-%(inputdefs)s
-%(inputvecs)s
-%(outputvecs)s
-
-%(arg_parse_tuple)s
-
-%(parseinput)s
-
-%(outputcreate)s
-
- /* compute _do function */
- %(funcname)s (%(doparams_string)s);
-
-%(returnval)s;
-}
-""" % locals()
- return s
-
-def gen_members(new_method, name):
- newparams = get_params_types_names(new_method)
- s = """
-AUBIO_MEMBERS_START(%(name)s)""" % locals()
- for param in newparams:
- if param['type'] == 'char_t*':
- s += """
- {"%(pname)s", T_STRING, offsetof (Py_%(name)s, %(pname)s), READONLY, ""},""" \
- % { 'pname': param['name'], 'ptype': param['type'], 'name': name}
- elif param['type'] == 'uint_t':
- s += """
- {"%(pname)s", T_INT, offsetof (Py_%(name)s, %(pname)s), READONLY, ""},""" \
- % { 'pname': param['name'], 'ptype': param['type'], 'name': name}
- elif param['type'] == 'smpl_t':
- s += """
- {"%(pname)s", T_FLOAT, offsetof (Py_%(name)s, %(pname)s), READONLY, ""},""" \
- % { 'pname': param['name'], 'ptype': param['type'], 'name': name}
- else:
- write_msg ("-- ERROR, unknown member type ", param )
- s += """
-AUBIO_MEMBERS_STOP(%(name)s)
-
-""" % locals()
- return s
-
-
-def gen_methods(get_methods, set_methods, name):
- s = ""
- method_defs = ""
- for method in set_methods:
- method_name = get_name(method)
- params = get_params_types_names(method)
- out_type = get_return_type(method)
- assert params[0]['type'] == "aubio_"+name+"_t*", \
- "get method is not in 'aubio_<name>_t"
- write_msg (method )
- write_msg (params[1:])
- setter_args = "self->o, " +",".join([p['name'] for p in params[1:]])
- parse_args = ""
- for p in params[1:]:
- parse_args += p['type'] + " " + p['name'] + ";\n"
- argmap = "".join([aubio2pytypes[p['type']] for p in params[1:]])
- arglist = ", ".join(["&"+p['name'] for p in params[1:]])
- parse_args += """
- if (!PyArg_ParseTuple (args, "%(argmap)s", %(arglist)s)) {
- return NULL;
- } """ % locals()
- s += """
-static PyObject *
-Py%(funcname)s (Py_%(objname)s *self, PyObject *args)
-{
- uint_t err = 0;
-
- %(parse_args)s
-
- err = %(funcname)s (%(setter_args)s);
-
- if (err > 0) {
- PyErr_SetString (PyExc_ValueError,
- "error running %(funcname)s");
- return NULL;
- }
- Py_RETURN_NONE;
-}
-""" % {'funcname': method_name, 'objname': name,
- 'out_type': out_type, 'setter_args': setter_args, 'parse_args': parse_args }
- shortname = method_name.split('aubio_'+name+'_')[-1]
- method_defs += """\
- {"%(shortname)s", (PyCFunction) Py%(method_name)s,
- METH_VARARGS, ""},
-""" % locals()
-
- for method in get_methods:
- method_name = get_name(method)
- params = get_params_types_names(method)
- out_type = get_return_type(method)
- assert params[0]['type'] == "aubio_"+name+"_t*", \
- "get method is not in 'aubio_<name>_t %s" % params[0]['type']
- assert len(params) == 1, \
- "get method has more than one parameter %s" % params
- getter_args = "self->o"
- returnval = "(PyObject *)" + aubiovectopyobj[out_type] + " (tmp)"
- shortname = method_name.split('aubio_'+name+'_')[-1]
- method_defs += """\
- {"%(shortname)s", (PyCFunction) Py%(method_name)s,
- METH_NOARGS, ""},
-""" % locals()
- s += """
-static PyObject *
-Py%(funcname)s (Py_%(objname)s *self, PyObject *unused)
-{
- %(out_type)s tmp = %(funcname)s (%(getter_args)s);
- return %(returnval)s;
-}
-""" % {'funcname': method_name, 'objname': name,
- 'out_type': out_type, 'getter_args': getter_args, 'returnval': returnval }
-
- s += """
-static PyMethodDef Py_%(name)s_methods[] = {
-""" % locals()
- s += method_defs
- s += """\
- {NULL} /* sentinel */
-};
-""" % locals()
- return s
-
-def gen_finish(name):
- s = """\
-
-AUBIO_TYPEOBJECT(%(name)s, "aubio.%(name)s")
-""" % locals()
- return s
+++ /dev/null
-#! /usr/bin/python
-
-""" This file generates a c file from a list of cpp prototypes. """
-
-import os, sys, shutil
-from gen_pyobject import write_msg, gen_new_init, gen_do, gen_members, gen_methods, gen_finish
-
-def get_cpp_objects():
-
- cpp_output = [l.strip() for l in os.popen('cpp -DAUBIO_UNSTABLE=1 -I../build/src ../src/aubio.h').readlines()]
-
- cpp_output = filter(lambda y: len(y) > 1, cpp_output)
- cpp_output = filter(lambda y: not y.startswith('#'), cpp_output)
-
- i = 1
- while 1:
- if i >= len(cpp_output): break
- if cpp_output[i-1].endswith(',') or cpp_output[i-1].endswith('{') or cpp_output[i].startswith('}'):
- cpp_output[i] = cpp_output[i-1] + ' ' + cpp_output[i]
- cpp_output.pop(i-1)
- else:
- i += 1
-
- typedefs = filter(lambda y: y.startswith ('typedef struct _aubio'), cpp_output)
-
- cpp_objects = [a.split()[3][:-1] for a in typedefs]
-
- return cpp_output, cpp_objects
-
-def generate_object_files(output_path):
- if os.path.isdir(output_path): shutil.rmtree(output_path)
- os.mkdir(output_path)
-
- generated_objects = []
- cpp_output, cpp_objects = get_cpp_objects()
- skip_objects = [
- # already in ext/
- 'fft',
- 'pvoc',
- 'filter',
- 'filterbank',
- #'resampler',
- # AUBIO_UNSTABLE
- 'hist',
- 'parameter',
- 'scale',
- 'beattracking',
- 'resampler',
- 'sndfile',
- 'peakpicker',
- 'pitchfcomb',
- 'pitchmcomb',
- 'pitchschmitt',
- 'pitchspecacf',
- 'pitchyin',
- 'pitchyinfft',
- 'sink',
- 'sink_apple_audio',
- 'sink_sndfile',
- 'sink_wavwrite',
- 'source',
- 'source_apple_audio',
- 'source_sndfile',
- 'source_avcodec',
- 'source_wavread',
- #'sampler',
- 'audio_unit',
- ]
-
- write_msg("-- INFO: %d objects in total" % len(cpp_objects))
-
- for this_object in cpp_objects:
- lint = 0
-
- if this_object[-2:] == '_t':
- object_name = this_object[:-2]
- else:
- object_name = this_object
- write_msg("-- WARNING: %s does not end in _t" % this_object)
-
- if object_name[:len('aubio_')] != 'aubio_':
- write_msg("-- WARNING: %s does not start n aubio_" % this_object)
-
- write_msg("-- INFO: looking at", object_name)
- object_methods = filter(lambda x: this_object in x, cpp_output)
- object_methods = [a.strip() for a in object_methods]
- object_methods = filter(lambda x: not x.startswith('typedef'), object_methods)
- #for method in object_methods:
- # write_msg(method)
- new_methods = filter(lambda x: 'new_'+object_name in x, object_methods)
- if len(new_methods) > 1:
- write_msg("-- WARNING: more than one new method for", object_name)
- for method in new_methods:
- write_msg(method)
- elif len(new_methods) < 1:
- write_msg("-- WARNING: no new method for", object_name)
- elif 0:
- for method in new_methods:
- write_msg(method)
-
- del_methods = filter(lambda x: 'del_'+object_name in x, object_methods)
- if len(del_methods) > 1:
- write_msg("-- WARNING: more than one del method for", object_name)
- for method in del_methods:
- write_msg(method)
- elif len(del_methods) < 1:
- write_msg("-- WARNING: no del method for", object_name)
-
- do_methods = filter(lambda x: object_name+'_do' in x, object_methods)
- if len(do_methods) > 1:
- pass
- #write_msg("-- WARNING: more than one do method for", object_name)
- #for method in do_methods:
- # write_msg(method)
- elif len(do_methods) < 1:
- write_msg("-- WARNING: no do method for", object_name)
- elif 0:
- for method in do_methods:
- write_msg(method)
-
- # check do methods return void
- for method in do_methods:
- if (method.split()[0] != 'void'):
- write_msg("-- ERROR: _do method does not return void:", method )
-
- get_methods = filter(lambda x: object_name+'_get_' in x, object_methods)
-
- set_methods = filter(lambda x: object_name+'_set_' in x, object_methods)
- for method in set_methods:
- if (method.split()[0] != 'uint_t'):
- write_msg("-- ERROR: _set method does not return uint_t:", method )
-
- other_methods = filter(lambda x: x not in new_methods, object_methods)
- other_methods = filter(lambda x: x not in del_methods, other_methods)
- other_methods = filter(lambda x: x not in do_methods, other_methods)
- other_methods = filter(lambda x: x not in get_methods, other_methods)
- other_methods = filter(lambda x: x not in set_methods, other_methods)
-
- if len(other_methods) > 0:
- write_msg("-- WARNING: some methods for", object_name, "were unidentified")
- for method in other_methods:
- write_msg(method)
-
-
- # generate this_object
- short_name = object_name[len('aubio_'):]
- if short_name in skip_objects:
- write_msg("-- INFO: skipping object", short_name )
- continue
- if 1: #try:
- s = gen_new_init(new_methods[0], short_name)
- s += gen_do(do_methods[0], short_name)
- s += gen_members(new_methods[0], short_name)
- s += gen_methods(get_methods, set_methods, short_name)
- s += gen_finish(short_name)
- generated_filepath = os.path.join(output_path,'gen-'+short_name+'.c')
- fd = open(generated_filepath, 'w')
- fd.write(s)
- #except Exception, e:
- # write_msg("-- ERROR:", type(e), str(e), "in", short_name)
- # continue
- generated_objects += [this_object]
-
- s = """// generated list of objects created with generator.py
-
-"""
-
- types_ready = []
- for each in generated_objects:
- types_ready.append(" PyType_Ready (&Py_%sType) < 0" % \
- each.replace('aubio_','').replace('_t','') )
-
- s = """// generated list of objects created with generator.py
-
-#include "aubio-generated.h"
-"""
-
- s += """
-int generated_types_ready (void)
-{
- return (
-"""
- s += ('\n ||').join(types_ready)
- s += """);
-}
-"""
-
- s += """
-void add_generated_objects ( PyObject *m )
-{"""
- for each in generated_objects:
- s += """
- Py_INCREF (&Py_%(name)sType);
- PyModule_AddObject (m, "%(name)s", (PyObject *) & Py_%(name)sType);""" % \
- { 'name': ( each.replace('aubio_','').replace('_t','') ) }
-
- s += """
-}"""
-
- fd = open(os.path.join(output_path,'aubio-generated.c'), 'w')
- fd.write(s)
-
- s = """// generated list of objects created with generator.py
-
-#include <Python.h>
-
-"""
-
- for each in generated_objects:
- s += "extern PyTypeObject Py_%sType;\n" % \
- each.replace('aubio_','').replace('_t','')
-
- s+= "int generated_objects ( void );\n"
- s+= "void add_generated_objects( PyObject *m );\n"
-
- fd = open(os.path.join(output_path,'aubio-generated.h'), 'w')
- fd.write(s)
-
- from os import listdir
- generated_files = listdir(output_path)
- generated_files = filter(lambda x: x.endswith('.c'), generated_files)
- generated_files = [output_path+'/'+f for f in generated_files]
- return generated_files
-
-if __name__ == '__main__':
- generate_object_files('gen')
--- /dev/null
+""" A collection of function used from setup.py distutils script """
+#
+import sys, os, glob, subprocess
+import distutils, distutils.command.clean, distutils.dir_util
+from .gen_external import generate_external, header, output_path
+
+def get_aubio_version():
+ # read from VERSION
+ this_file_dir = os.path.dirname(os.path.abspath(__file__))
+ version_file = os.path.join(this_file_dir, '..', '..', 'VERSION')
+
+ if not os.path.isfile(version_file):
+ raise SystemError("VERSION file not found.")
+
+ for l in open(version_file).readlines():
+ #exec (l.strip())
+ if l.startswith('AUBIO_MAJOR_VERSION'):
+ AUBIO_MAJOR_VERSION = int(l.split('=')[1])
+ if l.startswith('AUBIO_MINOR_VERSION'):
+ AUBIO_MINOR_VERSION = int(l.split('=')[1])
+ if l.startswith('AUBIO_PATCH_VERSION'):
+ AUBIO_PATCH_VERSION = int(l.split('=')[1])
+ if l.startswith('AUBIO_VERSION_STATUS'):
+ AUBIO_VERSION_STATUS = l.split('=')[1].strip()[1:-1]
+
+ if AUBIO_MAJOR_VERSION is None or AUBIO_MINOR_VERSION is None \
+ or AUBIO_PATCH_VERSION is None:
+ raise SystemError("Failed parsing VERSION file.")
+
+ verstr = '.'.join(map(str, [AUBIO_MAJOR_VERSION,
+ AUBIO_MINOR_VERSION,
+ AUBIO_PATCH_VERSION]))
+
+ if AUBIO_VERSION_STATUS is not None:
+ verstr += AUBIO_VERSION_STATUS
+ return verstr
+
+def get_aubio_pyversion():
+ # convert to version for python according to pep 440
+ # see https://www.python.org/dev/peps/pep-0440/
+ verstr = get_aubio_version()
+ if '~alpha' in verstr:
+ verstr = verstr.split('~')[0] + 'a1'
+ # TODO: add rc, .dev, and .post suffixes, add numbering
+ return verstr
+
+# inspired from https://gist.github.com/abergmeier/9488990
+def add_packages(packages, ext=None, **kw):
+ """ use pkg-config to search which of 'packages' are installed """
+ flag_map = {
+ '-I': 'include_dirs',
+ '-L': 'library_dirs',
+ '-l': 'libraries'}
+
+ # if a setuptools extension is passed, fill it with pkg-config results
+ if ext:
+ kw = {'include_dirs': ext.include_dirs,
+ 'extra_link_args': ext.extra_link_args,
+ 'library_dirs': ext.library_dirs,
+ 'libraries': ext.libraries,
+ }
+
+ for package in packages:
+ print("checking for {:s}".format(package))
+ cmd = ['pkg-config', '--libs', '--cflags', package]
+ try:
+ tokens = subprocess.check_output(cmd)
+ except Exception as e:
+ print("Running \"{:s}\" failed: {:s}".format(' '.join(cmd), repr(e)))
+ continue
+ tokens = tokens.decode('utf8').split()
+ for token in tokens:
+ key = token[:2]
+ try:
+ arg = flag_map[key]
+ value = token[2:]
+ except KeyError:
+ arg = 'extra_link_args'
+ value = token
+ kw.setdefault(arg, []).append(value)
+ for key, value in iter(kw.items()): # remove duplicated
+ kw[key] = list(set(value))
+ return kw
+
+def add_local_aubio_header(ext):
+ """ use local "src/aubio.h", not <aubio/aubio.h>"""
+ ext.define_macros += [('USE_LOCAL_AUBIO', 1)]
+ ext.include_dirs += ['src'] # aubio.h
+
+def add_local_aubio_lib(ext):
+ """ add locally built libaubio from build/src """
+ print("Info: using locally built libaubio")
+ ext.library_dirs += [os.path.join('build', 'src')]
+ ext.libraries += ['aubio']
+
+def add_local_aubio_sources(ext, usedouble = False):
+ """ build aubio inside python module instead of linking against libaubio """
+ print("Info: libaubio was not installed or built locally with waf, adding src/")
+ aubio_sources = sorted(glob.glob(os.path.join('src', '**.c')))
+ aubio_sources += sorted(glob.glob(os.path.join('src', '*', '**.c')))
+ ext.sources += aubio_sources
+
+def add_local_macros(ext, usedouble = False):
+ # define macros (waf puts them in build/src/config.h)
+ for define_macro in ['HAVE_STDLIB_H', 'HAVE_STDIO_H',
+ 'HAVE_MATH_H', 'HAVE_STRING_H',
+ 'HAVE_C99_VARARGS_MACROS',
+ 'HAVE_LIMITS_H', 'HAVE_STDARG_H',
+ 'HAVE_MEMCPY_HACKS']:
+ ext.define_macros += [(define_macro, 1)]
+
+def add_external_deps(ext, usedouble = False):
+ # loof for additional packages
+ print("Info: looking for *optional* additional packages")
+ packages = ['libavcodec', 'libavformat', 'libavutil', 'libavresample',
+ 'jack',
+ 'jack',
+ 'sndfile',
+ #'fftw3f',
+ ]
+ # samplerate only works with float
+ if usedouble is False:
+ packages += ['samplerate']
+ else:
+ print("Info: not adding libsamplerate in double precision mode")
+ add_packages(packages, ext=ext)
+ if 'avcodec' in ext.libraries \
+ and 'avformat' in ext.libraries \
+ and 'avutil' in ext.libraries \
+ and 'avresample' in ext.libraries:
+ ext.define_macros += [('HAVE_LIBAV', 1)]
+ if 'jack' in ext.libraries:
+ ext.define_macros += [('HAVE_JACK', 1)]
+ if 'sndfile' in ext.libraries:
+ ext.define_macros += [('HAVE_SNDFILE', 1)]
+ if 'samplerate' in ext.libraries:
+ ext.define_macros += [('HAVE_SAMPLERATE', 1)]
+ if 'fftw3f' in ext.libraries:
+ ext.define_macros += [('HAVE_FFTW3F', 1)]
+ ext.define_macros += [('HAVE_FFTW3', 1)]
+
+ # add accelerate on darwin
+ if sys.platform.startswith('darwin'):
+ ext.extra_link_args += ['-framework', 'Accelerate']
+ ext.define_macros += [('HAVE_ACCELERATE', 1)]
+ ext.define_macros += [('HAVE_SOURCE_APPLE_AUDIO', 1)]
+ ext.define_macros += [('HAVE_SINK_APPLE_AUDIO', 1)]
+
+ if sys.platform.startswith('win'):
+ ext.define_macros += [('HAVE_WIN_HACKS', 1)]
+
+ ext.define_macros += [('HAVE_WAVWRITE', 1)]
+ ext.define_macros += [('HAVE_WAVREAD', 1)]
+ # TODO:
+ # add cblas
+ if 0:
+ ext.libraries += ['cblas']
+ ext.define_macros += [('HAVE_ATLAS_CBLAS_H', 1)]
+
+def add_system_aubio(ext):
+ # use pkg-config to find aubio's location
+ aubio_version = get_aubio_version()
+ add_packages(['aubio = ' + aubio_version], ext)
+ if 'aubio' not in ext.libraries:
+ print("Info: aubio " + aubio_version + " was not found by pkg-config")
+ else:
+ print("Info: using system aubio " + aubio_version + " found in " + ' '.join(ext.library_dirs))
+
+class CleanGenerated(distutils.command.clean.clean):
+ def run(self):
+ if os.path.isdir(output_path):
+ distutils.dir_util.remove_tree(output_path)
+
+from distutils.command.build_ext import build_ext as _build_ext
+class build_ext(_build_ext):
+
+ user_options = _build_ext.user_options + [
+ # The format is (long option, short option, description).
+ ('enable-double', None, 'use HAVE_AUBIO_DOUBLE=1 (default: 0)'),
+ ]
+
+ def initialize_options(self):
+ _build_ext.initialize_options(self)
+ self.enable_double = False
+
+ def finalize_options(self):
+ _build_ext.finalize_options(self)
+ if self.enable_double:
+ self.announce(
+ 'will generate code for aubio compiled with HAVE_AUBIO_DOUBLE=1',
+ level=distutils.log.INFO)
+
+ def build_extension(self, extension):
+ if self.enable_double or 'HAVE_AUBIO_DOUBLE' in os.environ:
+ extension.define_macros += [('HAVE_AUBIO_DOUBLE', 1)]
+ enable_double = True
+ else:
+ enable_double = False
+ # seack for aubio headers and lib in PKG_CONFIG_PATH
+ add_system_aubio(extension)
+ # the lib was not installed on this system
+ if 'aubio' not in extension.libraries:
+ # use local src/aubio.h
+ if os.path.isfile(os.path.join('src', 'aubio.h')):
+ add_local_aubio_header(extension)
+ add_local_macros(extension)
+ # look for a local waf build
+ if os.path.isfile(os.path.join('build','src', 'fvec.c.1.o')):
+ add_local_aubio_lib(extension)
+ else:
+ # check for external dependencies
+ add_external_deps(extension, usedouble=enable_double)
+ # add libaubio sources and look for optional deps with pkg-config
+ add_local_aubio_sources(extension, usedouble=enable_double)
+ # generate files python/gen/*.c, python/gen/aubio-generated.h
+ extension.sources += generate_external(header, output_path, overwrite = False,
+ usedouble=enable_double)
+ return _build_ext.build_extension(self, extension)
"""
import sys
-#from aubio.task import *
usage = "usage: %s [options] -i soundfile" % sys.argv[0]
usage += "\n help: %s -h" % sys.argv[0]
metavar = "<samples>",
action = "store", dest = "cut_until_nsamples", default = None,
help="how many extra samples should be added at the end of each slice")
+ parser.add_option("--cut-every-nslices", type = int,
+ metavar = "<samples>",
+ action = "store", dest = "cut_every_nslices", default = None,
+ help="how many slices should be groupped together at each cut")
parser.add_option("--cut-until-nslices", type = int,
metavar = "<slices>",
action = "store", dest = "cut_until_nslices", default = None,
if len(args) == 1:
options.source_file = args[0]
else:
- print "no file name given\n", usage
+ print ("no file name given\n" + usage)
sys.exit(1)
return options, args
samples, read = s()
if o(samples):
timestamps.append (o.get_last())
- if options.verbose: print "%.4f" % o.get_last_s()
+ if options.verbose: print ("%.4f" % o.get_last_s())
total_frames += read
if read < hopsize: break
del s
# generate output files
from aubio.slicing import slice_source_at_stamps
timestamps_end = None
+ if options.cut_every_nslices:
+ timestamps = timestamps[::options.cut_every_nslices]
+ nstamps = len(timestamps)
if options.cut_until_nslices and options.cut_until_nsamples:
- print "warning: using cut_until_nslices, but cut_until_nsamples is set"
+ print ("warning: using cut_until_nslices, but cut_until_nsamples is set")
if options.cut_until_nsamples:
timestamps_end = [t + options.cut_until_nsamples for t in timestamps[1:]]
timestamps_end += [ 1e120 ]
+++ /dev/null
-#! /usr/bin/env python
-
-from setuptools import setup, Extension
-
-import sys
-import os.path
-import numpy
-
-# read from VERSION
-for l in open('VERSION').readlines(): exec (l.strip())
-__version__ = '.'.join \
- ([str(x) for x in [AUBIO_MAJOR_VERSION, AUBIO_MINOR_VERSION, AUBIO_PATCH_VERSION]]) \
- + AUBIO_VERSION_STATUS
-
-
-include_dirs = []
-library_dirs = []
-define_macros = []
-extra_link_args = []
-
-include_dirs += ['ext']
-include_dirs += [ numpy.get_include() ]
-
-if sys.platform.startswith('darwin'):
- extra_link_args += ['-framework','CoreFoundation', '-framework','AudioToolbox']
-
-output_path = 'gen'
-generated_object_files = []
-
-if not os.path.isdir(output_path):
- from lib.generator import generate_object_files
- generated_object_files = generate_object_files(output_path)
- # define include dirs
-else:
- import glob
- generated_object_files = glob.glob(os.path.join(output_path, '*.c'))
-include_dirs += [output_path]
-
-if os.path.isfile('../src/aubio.h'):
- define_macros += [('USE_LOCAL_AUBIO', 1)]
- include_dirs += ['../src'] # aubio.h
- include_dirs += ['../build/src'] # config.h
- library_dirs += ['../build/src']
-
-aubio_extension = Extension("aubio._aubio", [
- "ext/aubiomodule.c",
- "ext/aubioproxy.c",
- "ext/ufuncs.c",
- "ext/py-musicutils.c",
- "ext/py-cvec.c",
- # example without macro
- "ext/py-filter.c",
- # macroised
- "ext/py-filterbank.c",
- "ext/py-fft.c",
- "ext/py-phasevoc.c",
- "ext/py-source.c",
- "ext/py-sink.c",
- # generated files
- ] + generated_object_files,
- include_dirs = include_dirs,
- library_dirs = library_dirs,
- extra_link_args = extra_link_args,
- define_macros = define_macros,
- libraries=['aubio'])
-
-classifiers = [
- 'Development Status :: 4 - Beta',
- 'Environment :: Console',
- 'Intended Audience :: Science/Research',
- 'Topic :: Software Development :: Libraries',
- 'Topic :: Multimedia :: Sound/Audio :: Analysis',
- 'Topic :: Multimedia :: Sound/Audio :: Sound Synthesis',
- 'Operating System :: POSIX',
- 'Operating System :: MacOS :: MacOS X',
- 'Operating System :: Microsoft :: Windows',
- 'Programming Language :: C',
- 'Programming Language :: Python',
- 'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)',
- ]
-
-distrib = setup(name='aubio',
- version = __version__,
- packages = ['aubio'],
- package_dir = {'aubio':'lib/aubio'},
- scripts = ['scripts/aubiocut'],
- ext_modules = [aubio_extension],
- description = 'interface to the aubio library',
- long_description = 'interface to the aubio library',
- license = 'GNU/GPL version 3',
- author = 'Paul Brossier',
- author_email = 'piem@aubio.org',
- maintainer = 'Paul Brossier',
- maintainer_email = 'piem@aubio.org',
- url = 'http://aubio.org/',
- platforms = 'any',
- classifiers = classifiers,
- install_requires = ['numpy'],
- )
import time
import os.path
import numpy
-from utils import array_from_text_file, array_from_yaml_file
+from .utils import array_from_text_file, array_from_yaml_file
from aubio import source, pitch, freqtomidi
start = time.time()
#! /usr/bin/env python
if __name__ == '__main__':
- import os, sys, unittest
- def load_test():
- # get relevant files
- curdir = os.path.dirname(sys.argv[0])
- if curdir == '': curdir = '.'
- files = os.listdir(curdir)
- modfiles = filter (lambda y: y.endswith('.py'), files)
- modfiles = filter (lambda f: f.startswith('test_'), modfiles)
- modfiles = filter (lambda y: not 'beattracking' in y, modfiles)
- modfiles = filter (lambda y: not 'hist' in y, modfiles)
- modfiles = filter (lambda y: not 'scale' in y, modfiles)
- modfiles = filter (lambda y: not 'peakpicker' in y, modfiles)
- # get module names
- modnames = map (lambda x: os.path.splitext(x)[0], modfiles)
- # import them
- modules = map (__import__, modnames)
- # create a test suites from the imported module
- load_from_module = unittest.defaultTestLoader.loadTestsFromModule
- tests = map(load_from_module, modules)
- return unittest.TestSuite(tests)
- unittest.main(defaultTest = 'load_test')
+ import nose2.main
+ nose2.discover()
#! /usr/bin/env python
-from numpy.testing import TestCase, run_module_suite
+from unittest import main
+from numpy.testing import TestCase
class aubiomodule_test_case(TestCase):
- def test_import(self):
- """ try importing aubio """
- import aubio
+ def test_import(self):
+ """ try importing aubio """
+ import aubio
+
+ def test_version(self):
+ """ test aubio.version """
+ import aubio
+ self.assertEqual('0', aubio.version[0])
if __name__ == '__main__':
- from unittest import main
- main()
+ main()
#! /usr/bin/env python
-from numpy.testing import TestCase, run_module_suite
-from numpy.testing import assert_equal, assert_almost_equal
-from aubio import cvec
-from numpy import array, shape, pi
+from unittest import main
+import numpy as np
+from numpy.testing import TestCase, assert_equal
+from aubio import cvec, fvec, float_type
+
+wrong_type = 'float32' if float_type == 'float64' else 'float64'
class aubio_cvec_test_case(TestCase):
def test_vector_created_with_zeroes(self):
a = cvec(10)
- shape(a.norm)
- shape(a.phas)
- a.norm[0]
+ assert_equal(a.norm.shape[0], 10 // 2 + 1)
+ assert_equal(a.phas.shape[0], 10 // 2 + 1)
assert_equal(a.norm, 0.)
assert_equal(a.phas, 0.)
def test_assign_cvec_phas_slice(self):
spec = cvec(1024)
- spec.phas[39:-1] = -pi
+ spec.phas[39:-1] = -np.pi
assert_equal(spec.phas[0:39], 0)
- assert_equal(spec.phas[39:-1], -pi)
+ assert_equal(spec.phas[39:-1], -np.pi)
assert_equal(spec.norm, 0)
+ def test_assign_cvec_with_other_cvec(self):
+ """ check dest cvec is still reachable after source was deleted """
+ spec = cvec(1024)
+ a = np.random.rand(1024//2+1).astype(float_type)
+ b = np.random.rand(1024//2+1).astype(float_type)
+ spec.norm = a
+ spec.phas = b
+ new_spec = spec
+ del spec
+ assert_equal(a, new_spec.norm)
+ assert_equal(b, new_spec.phas)
+ assert_equal(id(a), id(new_spec.norm))
+ assert_equal(id(b), id(new_spec.phas))
+
+ def test_pass_to_numpy(self):
+ spec = cvec(1024)
+ norm = spec.norm
+ phas = spec.phas
+ del spec
+ new_spec = cvec(1024)
+ new_spec.norm = norm
+ new_spec.phas = phas
+ assert_equal(norm, new_spec.norm)
+ assert_equal(phas, new_spec.phas)
+ assert_equal(id(norm), id(new_spec.norm))
+ assert_equal(id(phas), id(new_spec.phas))
+ del norm
+ del phas
+ assert_equal(new_spec.norm, 0.)
+ assert_equal(new_spec.phas, 0.)
+ del new_spec
+
+ def test_assign_norm_too_large(self):
+ a = cvec(512)
+ b = fvec(512//2+1 + 4)
+ with self.assertRaises(ValueError):
+ a.norm = b
+
+ def test_assign_norm_too_small(self):
+ a = cvec(512)
+ b = fvec(512//2+1 - 4)
+ with self.assertRaises(ValueError):
+ a.norm = b
+
+ def test_assign_phas_too_large(self):
+ a = cvec(512)
+ b = fvec(512//2+1 + 4)
+ with self.assertRaises(ValueError):
+ a.phas = b
+
+ def test_assign_phas_too_small(self):
+ a = cvec(512)
+ b = fvec(512//2+1 - 4)
+ with self.assertRaises(ValueError):
+ a.phas = b
+
+ def test_cvec_repr(self):
+ win_s = 512
+ c = cvec(win_s)
+ expected_repr = "aubio cvec of {:d} elements".format(win_s//2+1)
+ self.assertEqual(repr(c), expected_repr)
+
+class aubio_cvec_wrong_norm_input(TestCase):
+
+ def test_wrong_length(self):
+ with self.assertRaises(ValueError):
+ cvec(-1)
+
+ def test_set_norm_with_scalar(self):
+ a = cvec(512)
+ with self.assertRaises(ValueError):
+ a.norm = 1
+
+ def test_set_norm_with_scalar_array(self):
+ a = cvec(512)
+ with self.assertRaises(ValueError):
+ a.norm = np.ndarray(1, dtype = 'int')
+
+ def test_set_norm_with_int_array(self):
+ a = cvec(512)
+ with self.assertRaises(ValueError):
+ a.norm = np.zeros(512//2+1, dtype = 'int')
+
+ def test_set_norm_with_wrong_float_array(self):
+ a = cvec(512)
+ with self.assertRaises(ValueError):
+ a.norm = np.zeros(512//2+1, dtype = wrong_type)
+
+ def test_set_norm_with_wrong_2d_array(self):
+ a = cvec(512)
+ with self.assertRaises(ValueError):
+ a.norm = np.zeros((512//2+1, 2), dtype = float_type)
+
if __name__ == '__main__':
- from unittest import main
main()
#! /usr/bin/env python
-from numpy.testing import TestCase, run_module_suite
+from unittest import main
+from numpy.testing import TestCase
from numpy.testing import assert_equal, assert_almost_equal
+import numpy as np
from aubio import fvec, fft, cvec
-from numpy import array, shape
-from math import pi
+from math import pi, floor
+from random import random
class aubio_fft_test_case(TestCase):
timegrain = fvec(win_s)
f = fft (win_s)
fftgrain = f (timegrain)
- assert_equal (shape(fftgrain.norm), (win_s/2+1,))
- assert_equal (shape(fftgrain.phas), (win_s/2+1,))
+ del f
+ assert_equal (fftgrain.norm.shape, (win_s/2+1,))
+ assert_equal (fftgrain.phas.shape, (win_s/2+1,))
def test_zeros(self):
""" check the transform of zeros is all zeros """
f = fft (win_s)
fftgrain = f (timegrain)
assert_equal ( fftgrain.norm, 0 )
- assert_equal ( fftgrain.phas, 0 )
+ try:
+ assert_equal ( fftgrain.phas, 0 )
+ except AssertionError:
+ assert_equal (fftgrain.phas[fftgrain.phas > 0], +pi)
+ assert_equal (fftgrain.phas[fftgrain.phas < 0], -pi)
+ assert_equal (np.abs(fftgrain.phas[np.abs(fftgrain.phas) != pi]), 0)
+ self.skipTest('fft(fvec(%d)).phas != +0, ' % win_s \
+ + 'This is expected when using fftw3 on powerpc.')
def test_impulse(self):
""" check the transform of one impulse at a random place """
- from random import random
- from math import floor
win_s = 256
- i = floor(random()*win_s)
+ i = int(floor(random()*win_s))
impulse = pi * random()
f = fft(win_s)
timegrain = fvec(win_s)
assert_equal ( fftgrain.phas >= -pi, True)
def test_impulse_negative(self):
- """ check the transform of one impulse at a random place """
- from random import random
- from math import floor
+ """ check the transform of a negative impulse at a random place """
win_s = 256
- i = 0
- impulse = -10.
+ i = int(floor(random()*win_s))
+ impulse = -.1
f = fft(win_s)
timegrain = fvec(win_s)
+ timegrain[0] = 0
timegrain[i] = impulse
fftgrain = f ( timegrain )
#self.plot_this ( fftgrain.phas )
- assert_almost_equal ( fftgrain.norm, abs(impulse), decimal = 6 )
+ assert_almost_equal ( fftgrain.norm, abs(impulse), decimal = 5 )
if impulse < 0:
# phase can be pi or -pi, as it is not unwrapped
- assert_almost_equal ( abs(fftgrain.phas[1:-1]) , pi, decimal = 6 )
+ #assert_almost_equal ( abs(fftgrain.phas[1:-1]) , pi, decimal = 6 )
assert_almost_equal ( fftgrain.phas[0], pi, decimal = 6)
- assert_almost_equal ( fftgrain.phas[-1], pi, decimal = 6)
+ assert_almost_equal ( np.fmod(fftgrain.phas[-1], pi), 0, decimal = 6)
else:
- assert_equal ( fftgrain.phas[1:-1] == 0, True)
- assert_equal ( fftgrain.phas[0] == 0, True)
- assert_equal ( fftgrain.phas[-1] == 0, True)
+ #assert_equal ( fftgrain.phas[1:-1] == 0, True)
+ assert_equal ( fftgrain.phas[0], 0)
+ assert_almost_equal ( np.fmod(fftgrain.phas[-1], pi), 0, decimal = 6)
# now check the resynthesis
synthgrain = f.rdo ( fftgrain )
#self.plot_this ( fftgrain.phas.T )
def test_rdo_before_do(self):
""" check running fft.rdo before fft.do works """
win_s = 1024
- impulse = pi
f = fft(win_s)
fftgrain = cvec(win_s)
t = f.rdo( fftgrain )
plot ( this )
show ()
+ def test_local_fftgrain(self):
+ """ check aubio.fft() result can be accessed after deletion """
+ def compute_grain(impulse):
+ win_s = 1024
+ timegrain = fvec(win_s)
+ timegrain[0] = impulse
+ f = fft(win_s)
+ fftgrain = f ( timegrain )
+ return fftgrain
+ impulse = pi
+ fftgrain = compute_grain(impulse)
+ assert_equal ( fftgrain.phas[0], 0)
+ assert_almost_equal ( fftgrain.phas[1], 0)
+ assert_almost_equal ( fftgrain.norm[0], impulse, decimal = 6 )
+
+ def test_local_reconstruct(self):
+ """ check aubio.fft.rdo() result can be accessed after deletion """
+ def compute_grain(impulse):
+ win_s = 1024
+ timegrain = fvec(win_s)
+ timegrain[0] = impulse
+ f = fft(win_s)
+ fftgrain = f ( timegrain )
+ r = f.rdo(fftgrain)
+ return r
+ impulse = pi
+ r = compute_grain(impulse)
+ assert_almost_equal ( r[0], impulse, decimal = 6)
+ assert_almost_equal ( r[1:], 0)
+
+ def test_large_input_timegrain(self):
+ win_s = 1024
+ f = fft(win_s)
+ t = fvec(win_s + 1)
+ with self.assertRaises(ValueError):
+ f(t)
+
+ def test_small_input_timegrain(self):
+ win_s = 1024
+ f = fft(win_s)
+ t = fvec(1)
+ with self.assertRaises(ValueError):
+ f(t)
+
+ def test_large_input_fftgrain(self):
+ win_s = 1024
+ f = fft(win_s)
+ s = cvec(win_s + 5)
+ with self.assertRaises(ValueError):
+ f.rdo(s)
+
+ def test_small_input_fftgrain(self):
+ win_s = 1024
+ f = fft(win_s)
+ s = cvec(16)
+ with self.assertRaises(ValueError):
+ f.rdo(s)
+
+class aubio_fft_wrong_params(TestCase):
+
+ def test_wrong_buf_size(self):
+ win_s = -1
+ with self.assertRaises(ValueError):
+ fft(win_s)
+
+ def test_buf_size_not_power_of_two(self):
+ # when compiled with fftw3, aubio supports non power of two fft sizes
+ win_s = 320
+ try:
+ with self.assertRaises(RuntimeError):
+ fft(win_s)
+ except AssertionError:
+ self.skipTest('creating aubio.fft with size %d did not fail' % win_s)
+
+ def test_buf_size_too_small(self):
+ win_s = 1
+ with self.assertRaises(RuntimeError):
+ fft(win_s)
+
if __name__ == '__main__':
- from unittest import main
main()
-
#! /usr/bin/env python
+from unittest import main
from numpy.testing import TestCase, assert_equal, assert_almost_equal
from aubio import fvec, digital_filter
-from numpy import array
-from utils import array_from_text_file
+from .utils import array_from_text_file
class aubio_filter_test_case(TestCase):
- def test_members(self):
- f = digital_filter()
- assert_equal (f.order, 7)
- f = digital_filter(5)
- assert_equal (f.order, 5)
- f(fvec())
-
- def test_cweighting_error(self):
- f = digital_filter (2)
- self.assertRaises ( ValueError, f.set_c_weighting, 44100 )
- f = digital_filter (8)
- self.assertRaises ( ValueError, f.set_c_weighting, 44100 )
- f = digital_filter (5)
- self.assertRaises ( ValueError, f.set_c_weighting, 4000 )
- f = digital_filter (5)
- self.assertRaises ( ValueError, f.set_c_weighting, 193000 )
- f = digital_filter (7)
- self.assertRaises ( ValueError, f.set_a_weighting, 193000 )
- f = digital_filter (5)
- self.assertRaises ( ValueError, f.set_a_weighting, 192000 )
+ def test_members(self):
+ f = digital_filter()
+ assert_equal (f.order, 7)
+ f = digital_filter(5)
+ assert_equal (f.order, 5)
+ f(fvec())
- def test_c_weighting(self):
- expected = array_from_text_file('c_weighting_test_simple.expected')
- f = digital_filter(5)
- f.set_c_weighting(44100)
- v = fvec(32)
- v[12] = .5
- u = f(v)
- assert_almost_equal (expected[1], u)
+ def test_cweighting_error(self):
+ f = digital_filter (2)
+ self.assertRaises ( ValueError, f.set_c_weighting, 44100 )
+ f = digital_filter (8)
+ self.assertRaises ( ValueError, f.set_c_weighting, 44100 )
+ f = digital_filter (5)
+ self.assertRaises ( ValueError, f.set_c_weighting, 4000 )
+ f = digital_filter (5)
+ self.assertRaises ( ValueError, f.set_c_weighting, 193000 )
+ f = digital_filter (7)
+ self.assertRaises ( ValueError, f.set_a_weighting, 193000 )
+ f = digital_filter (5)
+ self.assertRaises ( ValueError, f.set_a_weighting, 192000 )
- def test_c_weighting_8000(self):
- expected = array_from_text_file('c_weighting_test_simple_8000.expected')
- f = digital_filter(5)
- f.set_c_weighting(8000)
- v = fvec(32)
- v[12] = .5
- u = f(v)
- assert_almost_equal (expected[1], u)
+ def test_c_weighting(self):
+ expected = array_from_text_file('c_weighting_test_simple.expected')
+ f = digital_filter(5)
+ f.set_c_weighting(44100)
+ v = fvec(32)
+ v[12] = .5
+ u = f(v)
+ assert_almost_equal (expected[1], u)
- def test_a_weighting(self):
- expected = array_from_text_file('a_weighting_test_simple.expected')
- f = digital_filter(7)
- f.set_a_weighting(44100)
- v = fvec(32)
- v[12] = .5
- u = f(v)
- assert_almost_equal (expected[1], u)
+ def test_c_weighting_8000(self):
+ expected = array_from_text_file('c_weighting_test_simple_8000.expected')
+ f = digital_filter(5)
+ f.set_c_weighting(8000)
+ v = fvec(32)
+ v[12] = .5
+ u = f(v)
+ assert_almost_equal (expected[1], u)
- def test_a_weighting_parted(self):
- expected = array_from_text_file('a_weighting_test_simple.expected')
- f = digital_filter(7)
- f.set_a_weighting(44100)
- v = fvec(16)
- v[12] = .5
- u = f(v)
- assert_almost_equal (expected[1][:16], u)
- # one more time
- v = fvec(16)
- u = f(v)
- assert_almost_equal (expected[1][16:], u)
+ def test_a_weighting(self):
+ expected = array_from_text_file('a_weighting_test_simple.expected')
+ f = digital_filter(7)
+ f.set_a_weighting(44100)
+ v = fvec(32)
+ v[12] = .5
+ u = f(v)
+ assert_almost_equal (expected[1], u)
-if __name__ == '__main__':
- from unittest import main
- main()
+ def test_a_weighting_parted(self):
+ expected = array_from_text_file('a_weighting_test_simple.expected')
+ f = digital_filter(7)
+ f.set_a_weighting(44100)
+ v = fvec(16)
+ v[12] = .5
+ u = f(v)
+ assert_almost_equal (expected[1][:16], u)
+ # one more time
+ v = fvec(16)
+ u = f(v)
+ assert_almost_equal (expected[1][16:], u)
+
+ def test_set_biquad(self):
+ f = digital_filter(3)
+ f.set_biquad(0., 0., 0, 0., 0.)
+
+ def test_set_biquad_wrong_order(self):
+ f = digital_filter(4)
+ with self.assertRaises(ValueError):
+ f.set_biquad(0., 0., 0, 0., 0.)
+class aubio_filter_wrong_params(TestCase):
+
+ def test_negative_order(self):
+ with self.assertRaises(ValueError):
+ digital_filter(-1)
+
+if __name__ == '__main__':
+ main()
#! /usr/bin/env python
-from numpy.testing import TestCase, run_module_suite
+from unittest import main
+from numpy.testing import TestCase
from numpy.testing import assert_equal, assert_almost_equal
-from numpy import random
-from math import pi
-from numpy import array
-from aubio import cvec, filterbank
-from utils import array_from_text_file
+import numpy as np
+from aubio import cvec, filterbank, float_type
+from .utils import array_from_text_file
class aubio_filterbank_test_case(TestCase):
- def test_members(self):
- f = filterbank(40, 512)
- assert_equal ([f.n_filters, f.win_s], [40, 512])
-
- def test_set_coeffs(self):
- f = filterbank(40, 512)
- r = random.random([40, 512 / 2 + 1]).astype('float32')
- f.set_coeffs(r)
- assert_equal (r, f.get_coeffs())
-
- def test_phase(self):
- f = filterbank(40, 512)
- c = cvec(512)
- c.phas[:] = pi
- assert_equal( f(c), 0);
-
- def test_norm(self):
- f = filterbank(40, 512)
- c = cvec(512)
- c.norm[:] = 1
- assert_equal( f(c), 0);
-
- def test_random_norm(self):
- f = filterbank(40, 512)
- c = cvec(512)
- c.norm[:] = random.random((512 / 2 + 1,)).astype('float32')
- assert_equal( f(c), 0)
-
- def test_random_coeffs(self):
- f = filterbank(40, 512)
- c = cvec(512)
- r = random.random([40, 512 / 2 + 1]).astype('float32')
- r /= r.sum()
- f.set_coeffs(r)
- c.norm[:] = random.random((512 / 2 + 1,)).astype('float32')
- assert_equal ( f(c) < 1., True )
- assert_equal ( f(c) > 0., True )
-
- def test_mfcc_coeffs(self):
- f = filterbank(40, 512)
- c = cvec(512)
- f.set_mel_coeffs_slaney(44100)
- c.norm[:] = random.random((512 / 2 + 1,)).astype('float32')
- assert_equal ( f(c) < 1., True )
- assert_equal ( f(c) > 0., True )
-
- def test_mfcc_coeffs_16000(self):
- expected = array_from_text_file('filterbank_mfcc_16000_512.expected')
- f = filterbank(40, 512)
- f.set_mel_coeffs_slaney(16000)
- assert_almost_equal ( expected, f.get_coeffs() )
+ def test_members(self):
+ f = filterbank(40, 512)
+ assert_equal ([f.n_filters, f.win_s], [40, 512])
-if __name__ == '__main__':
- from unittest import main
- main()
+ def test_set_coeffs(self):
+ f = filterbank(40, 512)
+ r = np.random.random([40, int(512 / 2) + 1]).astype(float_type)
+ f.set_coeffs(r)
+ assert_equal (r, f.get_coeffs())
+
+ def test_phase(self):
+ f = filterbank(40, 512)
+ c = cvec(512)
+ c.phas[:] = np.pi
+ assert_equal( f(c), 0);
+
+ def test_norm(self):
+ f = filterbank(40, 512)
+ c = cvec(512)
+ c.norm[:] = 1
+ assert_equal( f(c), 0);
+
+ def test_random_norm(self):
+ f = filterbank(40, 512)
+ c = cvec(512)
+ c.norm[:] = np.random.random((int(512 / 2) + 1,)).astype(float_type)
+ assert_equal( f(c), 0)
+
+ def test_random_coeffs(self):
+ win_s = 128
+ f = filterbank(40, win_s)
+ c = cvec(win_s)
+ r = np.random.random([40, int(win_s / 2) + 1]).astype(float_type)
+ r /= r.sum()
+ f.set_coeffs(r)
+ c.norm[:] = np.random.random((int(win_s / 2) + 1,)).astype(float_type)
+ assert_equal ( f(c) < 1., True )
+ assert_equal ( f(c) > 0., True )
+
+ def test_mfcc_coeffs(self):
+ f = filterbank(40, 512)
+ c = cvec(512)
+ f.set_mel_coeffs_slaney(44100)
+ c.norm[:] = np.random.random((int(512 / 2) + 1,)).astype(float_type)
+ assert_equal ( f(c) < 1., True )
+ assert_equal ( f(c) > 0., True )
+
+ def test_mfcc_coeffs_16000(self):
+ expected = array_from_text_file('filterbank_mfcc_16000_512.expected')
+ f = filterbank(40, 512)
+ f.set_mel_coeffs_slaney(16000)
+ assert_almost_equal ( expected, f.get_coeffs() )
+class aubio_filterbank_wrong_values(TestCase):
+
+ def test_negative_window(self):
+ self.assertRaises(ValueError, filterbank, 40, -20)
+
+ def test_negative_filters(self):
+ self.assertRaises(ValueError, filterbank, -40, 1024)
+
+ def test_filterbank_long_cvec(self):
+ f = filterbank(40, 512)
+ with self.assertRaises(ValueError):
+ f(cvec(1024))
+
+ def test_filterbank_short_cvec(self):
+ f = filterbank(40, 512)
+ with self.assertRaises(ValueError):
+ f(cvec(256))
+
+if __name__ == '__main__':
+ main()
#! /usr/bin/env python
-from numpy.testing import TestCase, run_module_suite
+from unittest import main
+from numpy.testing import TestCase
from numpy.testing import assert_equal, assert_almost_equal
from numpy import array, shape
-from aubio import cvec, filterbank
+from aubio import cvec, filterbank, float_type
class aubio_filterbank_mel_test_case(TestCase):
- def test_slaney(self):
- f = filterbank(40, 512)
- f.set_mel_coeffs_slaney(16000)
- a = f.get_coeffs()
- assert_equal(shape (a), (40, 512/2 + 1) )
-
- def test_other_slaney(self):
- f = filterbank(40, 512*2)
- f.set_mel_coeffs_slaney(44100)
- a = f.get_coeffs()
- #print "sum is", sum(sum(a))
- for win_s in [256, 512, 1024, 2048, 4096]:
- f = filterbank(40, win_s)
- f.set_mel_coeffs_slaney(320000)
- a = f.get_coeffs()
- #print "sum is", sum(sum(a))
-
- def test_triangle_freqs_zeros(self):
- f = filterbank(9, 1024)
- freq_list = [40, 80, 200, 400, 800, 1600, 3200, 6400, 12800, 15000, 24000]
- freqs = array(freq_list, dtype = 'float32')
- f.set_triangle_bands(freqs, 48000)
- f.get_coeffs().T
- assert_equal ( f(cvec(1024)), 0)
-
- def test_triangle_freqs_ones(self):
- f = filterbank(9, 1024)
- freq_list = [40, 80, 200, 400, 800, 1600, 3200, 6400, 12800, 15000, 24000]
- freqs = array(freq_list, dtype = 'float32')
- f.set_triangle_bands(freqs, 48000)
- f.get_coeffs().T
- spec = cvec(1024)
- spec.norm[:] = 1
- assert_almost_equal ( f(spec),
- [ 0.02070313, 0.02138672, 0.02127604, 0.02135417,
- 0.02133301, 0.02133301, 0.02133311, 0.02133334, 0.02133345])
+ def test_slaney(self):
+ f = filterbank(40, 512)
+ f.set_mel_coeffs_slaney(16000)
+ a = f.get_coeffs()
+ assert_equal(shape (a), (40, 512/2 + 1) )
+
+ def test_other_slaney(self):
+ f = filterbank(40, 512*2)
+ f.set_mel_coeffs_slaney(44100)
+ _ = f.get_coeffs()
+ #print "sum is", sum(sum(a))
+ for win_s in [256, 512, 1024, 2048, 4096]:
+ f = filterbank(40, win_s)
+ f.set_mel_coeffs_slaney(32000)
+ _ = f.get_coeffs()
+ #print "sum is", sum(sum(a))
+
+ def test_triangle_freqs_zeros(self):
+ f = filterbank(9, 1024)
+ freq_list = [40, 80, 200, 400, 800, 1600, 3200, 6400, 12800, 15000, 24000]
+ freqs = array(freq_list, dtype = float_type)
+ f.set_triangle_bands(freqs, 48000)
+ _ = f.get_coeffs().T
+ assert_equal ( f(cvec(1024)), 0)
+
+ def test_triangle_freqs_ones(self):
+ f = filterbank(9, 1024)
+ freq_list = [40, 80, 200, 400, 800, 1600, 3200, 6400, 12800, 15000, 24000]
+ freqs = array(freq_list, dtype = float_type)
+ f.set_triangle_bands(freqs, 48000)
+ _ = f.get_coeffs().T
+ spec = cvec(1024)
+ spec.norm[:] = 1
+ assert_almost_equal ( f(spec),
+ [ 0.02070313, 0.02138672, 0.02127604, 0.02135417,
+ 0.02133301, 0.02133301, 0.02133311, 0.02133334, 0.02133345])
if __name__ == '__main__':
- from unittest import main
- main()
-
-
+ main()
#! /usr/bin/env python
-from numpy.testing import TestCase, run_module_suite
-from numpy.testing import assert_equal, assert_almost_equal
+from unittest import main
+import numpy as np
+from numpy.testing import TestCase, assert_equal, assert_almost_equal
from aubio import fvec, zero_crossing_rate, alpha_norm, min_removal
-from numpy import array, shape
+from aubio import float_type
+
+wrong_type = 'float32' if float_type == 'float64' else 'float64'
default_size = 512
def test_vector_created_with_zeroes(self):
a = fvec(10)
- assert a.dtype == 'float32'
+ assert a.dtype == float_type
assert a.shape == (10,)
- assert_equal (a, 0)
+ assert_equal(a, 0)
def test_vector_create_with_list(self):
- a = fvec([0,1,2,3])
- assert a.dtype == 'float32'
+ a = fvec([0, 1, 2, 3])
+ assert a.dtype == float_type
assert a.shape == (4,)
- assert_equal (range(4), a)
+ assert_equal(list(range(4)), a)
def test_vector_assign_element(self):
a = fvec(default_size)
def test_vector(self):
a = fvec()
- a, len(a) #a.length
- a[0]
- array(a)
- a = fvec(10)
+ len(a)
+ _ = a[0]
+ np.array(a)
a = fvec(1)
- a.T
- array(a).T
- a = range(len(a))
+ a = fvec(10)
+ _ = a.T
- def test_wrong_values(self):
- self.assertRaises (ValueError, fvec, -10)
-
- a = fvec(2)
- self.assertRaises (IndexError, a.__getitem__, 3)
- self.assertRaises (IndexError, a.__getitem__, 2)
+class aubio_fvec_wrong_values(TestCase):
- def test_alpha_norm_of_fvec(self):
+ def test_negative_length(self):
+ """ test creating fvec with negative length fails (pure python) """
+ self.assertRaises(ValueError, fvec, -10)
+
+ def test_zero_length(self):
+ """ test creating fvec with zero length fails (pure python) """
+ self.assertRaises(ValueError, fvec, 0)
+
+ def test_out_of_bound(self):
+ """ test assiging fvec out of bounds fails (pure python) """
a = fvec(2)
- self.assertEquals (alpha_norm(a, 1), 0)
- a[0] = 1
- self.assertEquals (alpha_norm(a, 1), 0.5)
- a[1] = 1
- self.assertEquals (alpha_norm(a, 1), 1)
- a = array([0, 1], dtype='float32')
- from math import sqrt
- assert_almost_equal (alpha_norm(a, 2), sqrt(2)/2.)
-
- def test_alpha_norm_of_none(self):
- self.assertRaises (ValueError, alpha_norm, None, 1)
-
- def test_alpha_norm_of_array_of_float32(self):
- # check scalar fails
- a = array(1, dtype = 'float32')
- self.assertRaises (ValueError, alpha_norm, a, 1)
- # check 2d array fails
- a = array([[2],[4]], dtype = 'float32')
- self.assertRaises (ValueError, alpha_norm, a, 1)
- # check 1d array
- a = array(range(10), dtype = 'float32')
- self.assertEquals (alpha_norm(a, 1), 4.5)
-
- def test_alpha_norm_of_array_of_int(self):
- a = array(1, dtype = 'int')
- self.assertRaises (ValueError, alpha_norm, a, 1)
- a = array([[[1,2],[3,4]]], dtype = 'int')
- self.assertRaises (ValueError, alpha_norm, a, 1)
- a = array(range(10), dtype = 'int')
- self.assertRaises (ValueError, alpha_norm, a, 1)
-
- def test_alpha_norm_of_array_of_string (self):
- a = "hello"
- self.assertRaises (ValueError, alpha_norm, a, 1)
+ self.assertRaises(IndexError, a.__getitem__, 3)
+ self.assertRaises(IndexError, a.__getitem__, 2)
+
+class aubio_wrong_fvec_input(TestCase):
+ """ uses min_removal to test PyAubio_IsValidVector """
+
+ def test_no_input(self):
+ self.assertRaises(TypeError, min_removal)
+
+ def test_none(self):
+ self.assertRaises(ValueError, min_removal, None)
+
+ def test_wrong_scalar(self):
+ a = np.array(10, dtype=float_type)
+ self.assertRaises(ValueError, min_removal, a)
+
+ def test_wrong_dimensions(self):
+ a = np.array([[[1, 2], [3, 4]]], dtype=float_type)
+ self.assertRaises(ValueError, min_removal, a)
+
+ def test_wrong_array_size(self):
+ x = np.array([], dtype=float_type)
+ self.assertRaises(ValueError, min_removal, x)
+
+ def test_wrong_type(self):
+ a = np.zeros(10, dtype=wrong_type)
+ self.assertRaises(ValueError, min_removal, a)
+
+ def test_wrong_list_input(self):
+ self.assertRaises(ValueError, min_removal, [0., 1.])
+
+ def test_good_input(self):
+ a = np.zeros(10, dtype=float_type)
+ assert_equal(np.zeros(10, dtype=float_type), min_removal(a))
+
+class aubio_alpha_norm(TestCase):
+
+ def test_alpha_norm_of_random(self):
+ x = np.random.rand(1024).astype(float_type)
+ alpha = np.random.rand() * 5.
+ x_alpha_norm = (np.sum(np.abs(x)**alpha)/len(x))**(1/alpha)
+ assert_almost_equal(alpha_norm(x, alpha), x_alpha_norm, decimal = 4)
+
+class aubio_zero_crossing_rate_test(TestCase):
def test_zero_crossing_rate(self):
- a = array([0,1,-1], dtype='float32')
- assert_almost_equal (zero_crossing_rate(a), 1./3. )
- a = array([0.]*100, dtype='float32')
- self.assertEquals (zero_crossing_rate(a), 0 )
- a = array([-1.]*100, dtype='float32')
- self.assertEquals (zero_crossing_rate(a), 0 )
- a = array([1.]*100, dtype='float32')
- self.assertEquals (zero_crossing_rate(a), 0 )
-
- def test_alpha_norm_of_array_of_float64(self):
- # check scalar fail
- a = array(1, dtype = 'float64')
- self.assertRaises (ValueError, alpha_norm, a, 1)
- # check 3d array fail
- a = array([[[1,2],[3,4]]], dtype = 'float64')
- self.assertRaises (ValueError, alpha_norm, a, 1)
- # check float64 1d array fail
- a = array(range(10), dtype = 'float64')
- self.assertRaises (ValueError, alpha_norm, a, 1)
- # check float64 2d array fail
- a = array([range(10), range(10)], dtype = 'float64')
- self.assertRaises (ValueError, alpha_norm, a, 1)
+ a = np.array([0, 1, -1], dtype=float_type)
+ assert_almost_equal(zero_crossing_rate(a), 1./3.)
+
+ def test_zero_crossing_rate_zeros(self):
+ a = np.zeros(100, dtype=float_type)
+ self.assertEqual(zero_crossing_rate(a), 0)
+
+ def test_zero_crossing_rate_minus_ones(self):
+ a = np.ones(100, dtype=float_type)
+ self.assertEqual(zero_crossing_rate(a), 0)
+
+ def test_zero_crossing_rate_plus_ones(self):
+ a = np.ones(100, dtype=float_type)
+ self.assertEqual(zero_crossing_rate(a), 0)
+
+class aubio_fvec_min_removal(TestCase):
def test_fvec_min_removal_of_array(self):
- a = array([20,1,19], dtype='float32')
- b = min_removal(a)
- assert_equal (array(b), [19, 0, 18])
- assert_equal (b, [19, 0, 18])
- assert_equal (a, b)
- a[0] = 0
- assert_equal (a, b)
-
- def test_fvec_min_removal_of_array_float64(self):
- a = array([20,1,19], dtype='float64')
- self.assertRaises (ValueError, min_removal, a)
-
- def test_fvec_min_removal_of_fvec(self):
- a = fvec(3)
- a = array([20, 1, 19], dtype = 'float32')
+ a = np.array([20, 1, 19], dtype=float_type)
b = min_removal(a)
- assert_equal (array(b), [19, 0, 18])
- assert_equal (b, [19, 0, 18])
- assert_equal (a, b)
+ assert_equal(b, [19, 0, 18])
+
+class aubio_fvec_test_memory(TestCase):
+
+ def test_pass_to_numpy(self):
+ a = fvec(10)
+ a[:] = 1.
+ b = a
+ del a
+ assert_equal(b, 1.)
+ c = fvec(10)
+ c = b
+ del b
+ assert_equal(c, 1.)
+ del c
if __name__ == '__main__':
- from unittest import main
main()
#! /usr/bin/env python
+from unittest import main
from numpy.testing import TestCase, assert_equal
from numpy import array, arange, isnan, isinf
from aubio import bintomidi, miditobin, freqtobin, bintofreq, freqtomidi, miditofreq
def test_unwrap2pi(self):
unwrap2pi(int(23))
unwrap2pi(float(23.))
- unwrap2pi(long(23.))
+ unwrap2pi(int(23.))
unwrap2pi(arange(10))
unwrap2pi(arange(10).astype("int"))
unwrap2pi(arange(10).astype("float"))
a[:] = 4.
unwrap2pi(a)
a = pi/100. * arange(-600,600).astype("float")
- b = unwrap2pi (a)
+ unwrap2pi(a)
#print zip(a, b)
- try:
- print unwrap2pi(["23.","24.",25.])
- except Exception, e:
- pass
+ def test_unwrap2pi_fails_on_list(self):
+ with self.assertRaises((TypeError, NotImplementedError)):
+ unwrap2pi(["23.","24.",25.])
def test_unwrap2pi_takes_fvec(self):
a = fvec(10)
assert ( b <= pi ).all()
def test_freqtomidi(self):
- a = array(range(-20, 50000, 100) + [ -1e32, 1e32 ])
+ a = array(list(range(-20, 50000, 100)) + [ -1e32, 1e32 ])
b = freqtomidi(a)
#print zip(a, b)
assert_equal ( isnan(array(b)), False )
assert_equal ( array(b) < 0, False )
def test_miditofreq(self):
- a = range(-30, 200) + [-100000, 10000]
+ a = list(range(-30, 200)) + [-100000, 10000]
b = miditofreq(a)
#print zip(a, b)
assert_equal ( isnan(b), False )
assert_equal ( b < 0, False )
def test_miditobin(self):
- a = range(-30, 200) + [-100000, 10000]
- b = [ bintomidi(x, 44100, 512) for x in a ]
+ a = list(range(-30, 200)) + [-100000, 10000]
+ b = [ miditobin(x, 44100, 512) for x in a ]
#print zip(a, b)
assert_equal ( isnan(array(b)), False )
assert_equal ( isinf(array(b)), False )
assert_equal ( array(b) < 0, False )
def test_bintomidi(self):
- a = range(-100, 512)
+ a = list(range(-100, 512))
b = [ bintomidi(x, 44100, 512) for x in a ]
#print zip(a, b)
assert_equal ( isnan(array(b)), False )
assert_equal ( array(b) < 0, False )
def test_freqtobin(self):
- a = range(-20, 50000, 100) + [ -1e32, 1e32 ]
+ a = list(range(-20, 50000, 100)) + [ -1e32, 1e32 ]
b = [ freqtobin(x, 44100, 512) for x in a ]
#print zip(a, b)
assert_equal ( isnan(array(b)), False )
assert_equal ( array(b) < 0, False )
def test_bintofreq(self):
- a = range(-20, 148)
+ a = list(range(-20, 148))
b = [ bintofreq(x, 44100, 512) for x in a ]
#print zip(a, b)
assert_equal ( isnan(array(b)), False )
assert_equal ( array(b) < 0, False )
if __name__ == '__main__':
- from unittest import main
main()
--- /dev/null
+#! /usr/bin/env python
+
+from nose2 import main
+from nose2.tools import params
+from numpy import random, count_nonzero
+from numpy.testing import TestCase
+from aubio import mfcc, cvec, float_type
+
+buf_size = 2048
+n_filters = 40
+n_coeffs = 13
+samplerate = 44100
+
+
+new_params = ['buf_size', 'n_filters', 'n_coeffs', 'samplerate']
+new_deflts = [1024, 40, 13, 44100]
+
+class aubio_mfcc(TestCase):
+
+ def setUp(self):
+ self.o = mfcc()
+
+ def test_default_creation(self):
+ pass
+
+ def test_delete(self):
+ del self.o
+
+ @params(*new_params)
+ def test_read_only_member(self, name):
+ o = self.o
+ with self.assertRaises((TypeError, AttributeError)):
+ setattr(o, name, 0)
+
+ @params(*zip(new_params, new_deflts))
+ def test_default_param(self, name, expected):
+ """ test mfcc.{:s} = {:d} """.format(name, expected)
+ o = self.o
+ self.assertEqual( getattr(o, name), expected)
+
+class aubio_mfcc_wrong_params(TestCase):
+
+ def test_wrong_buf_size(self):
+ with self.assertRaises(ValueError):
+ mfcc(buf_size = -1)
+
+ def test_wrong_n_filters(self):
+ with self.assertRaises(ValueError):
+ mfcc(n_filters = -1)
+
+ def test_wrong_n_coeffs(self):
+ with self.assertRaises(ValueError):
+ mfcc(n_coeffs = -1)
+
+ def test_wrong_samplerate(self):
+ with self.assertRaises(ValueError):
+ mfcc(samplerate = -1)
+
+ def test_wrong_input_size(self):
+ m = mfcc(buf_size = 1024)
+ with self.assertRaises(ValueError):
+ m(cvec(512))
+
+class aubio_mfcc_compute(TestCase):
+
+ def test_members(self):
+
+ o = mfcc(buf_size, n_filters, n_coeffs, samplerate)
+ #assert_equal ([o.buf_size, o.method], [buf_size, method])
+
+ spec = cvec(buf_size)
+ #spec.norm[0] = 1
+ #spec.norm[1] = 1./2.
+ #print "%20s" % method, str(o(spec))
+ coeffs = o(spec)
+ self.assertEqual(coeffs.size, n_coeffs)
+ #print coeffs
+ spec.norm = random.random_sample((len(spec.norm),)).astype(float_type)
+ spec.phas = random.random_sample((len(spec.phas),)).astype(float_type)
+ #print "%20s" % method, str(o(spec))
+ self.assertEqual(count_nonzero(o(spec) != 0.), n_coeffs)
+ #print coeffs
+
+
+class aubio_mfcc_all_parameters(TestCase):
+
+ @params(
+ (2048, 40, 13, 44100),
+ (1024, 40, 13, 44100),
+ (512, 40, 13, 44100),
+ (512, 40, 13, 16000),
+ (256, 40, 13, 16000),
+ (128, 40, 13, 16000),
+ (128, 40, 12, 16000),
+ (128, 40, 13, 15000),
+ (512, 40, 20, 44100),
+ (512, 40, 40, 44100),
+ (512, 40, 3, 44100),
+ (1024, 40, 20, 44100),
+ #(1024, 30, 20, 44100),
+ (1024, 40, 40, 44100),
+ (1024, 40, 3, 44100),
+ )
+ def test_run_with_params(self, buf_size, n_filters, n_coeffs, samplerate):
+ " check mfcc can run with reasonable parameters "
+ o = mfcc(buf_size, n_filters, n_coeffs, samplerate)
+ spec = cvec(buf_size)
+ spec.phas[0] = 0.2
+ for _ in range(10):
+ o(spec)
+ #print coeffs
+
+if __name__ == '__main__':
+ main()
# -*- coding: utf-8 -*-
from aubio import midi2note
+from nose2.tools import params
import unittest
list_of_known_midis = (
class midi2note_good_values(unittest.TestCase):
- def test_midi2note_known_values(self):
+ @params(*list_of_known_midis)
+ def test_midi2note_known_values(self, midi, note):
" known values are correctly converted "
- for midi, note in list_of_known_midis:
- self.assertEqual ( midi2note(midi), note )
+ self.assertEqual ( midi2note(midi), note )
class midi2note_wrong_values(unittest.TestCase):
" fails when passed a negative value "
self.assertRaises(ValueError, midi2note, -2)
- def test_midi2note_negative_value(self):
+ def test_midi2note_large(self):
" fails when passed a value greater than 127 "
self.assertRaises(ValueError, midi2note, 128)
self.assertRaises(TypeError, midi2note, "a")
if __name__ == '__main__':
- unittest.main()
+ import nose2
+ nose2.main()
#! /usr/bin/env python
+from unittest import main
+import numpy as np
from numpy.testing import TestCase
from numpy.testing.utils import assert_equal, assert_almost_equal
-from numpy import cos, arange
-from math import pi
-
from aubio import window, level_lin, db_spl, silence_detection, level_detection
-
-from aubio import fvec
+from aubio import fvec, float_type
class aubio_window(TestCase):
window("default", 1024)
def test_fail_name_not_string(self):
- try:
+ with self.assertRaises(TypeError):
window(10, 1024)
- except ValueError, e:
- pass
- else:
- self.fail('non-string window type does not raise a ValueError')
def test_fail_size_not_int(self):
- try:
+ with self.assertRaises(TypeError):
window("default", "default")
- except ValueError, e:
- pass
- else:
- self.fail('non-integer window length does not raise a ValueError')
def test_compute_hanning_1024(self):
size = 1024
aubio_window = window("hanning", size)
- numpy_window = .5 - .5 * cos(2. * pi * arange(size) / size)
+ numpy_window = .5 - .5 * np.cos(2. * np.pi * np.arange(size) / size)
assert_almost_equal(aubio_window, numpy_window)
class aubio_level_lin(TestCase):
level_lin(fvec(1024))
def test_fail_not_fvec(self):
- try:
+ with self.assertRaises(ValueError):
level_lin("default")
- except ValueError, e:
- pass
- else:
- self.fail('non-number input phase does not raise a TypeError')
def test_zeros_is_zeros(self):
assert_equal(level_lin(fvec(1024)), 0.)
def test_minus_ones_is_one(self):
- from numpy import ones
- assert_equal(level_lin(-ones(1024, dtype="float32")), 1.)
+ assert_equal(level_lin(-np.ones(1024, dtype = float_type)), 1.)
class aubio_db_spl(TestCase):
def test_accept_fvec(self):
db_spl(fvec(1024))
def test_fail_not_fvec(self):
- try:
+ with self.assertRaises(ValueError):
db_spl("default")
- except ValueError, e:
- pass
- else:
- self.fail('non-number input phase does not raise a TypeError')
def test_zeros_is_inf(self):
- from math import isinf
- assert isinf(db_spl(fvec(1024)))
+ assert np.isinf(db_spl(fvec(1024)))
def test_minus_ones_is_zero(self):
- from numpy import ones
- assert_equal(db_spl(-ones(1024, dtype="float32")), 0.)
+ assert_equal(db_spl(-np.ones(1024, dtype = float_type)), 0.)
class aubio_silence_detection(TestCase):
def test_accept_fvec(self):
silence_detection(fvec(1024), -70.)
def test_fail_not_fvec(self):
- try:
+ with self.assertRaises(ValueError):
silence_detection("default", -70)
- except ValueError, e:
- pass
- else:
- self.fail('non-number input phase does not raise a TypeError')
def test_zeros_is_one(self):
- from math import isinf
assert silence_detection(fvec(1024), -70) == 1
def test_minus_ones_is_zero(self):
from numpy import ones
- assert silence_detection(ones(1024, dtype="float32"), -70) == 0
+ assert silence_detection(ones(1024, dtype = float_type), -70) == 0
class aubio_level_detection(TestCase):
def test_accept_fvec(self):
level_detection(fvec(1024), -70.)
def test_fail_not_fvec(self):
- try:
+ with self.assertRaises(ValueError):
level_detection("default", -70)
- except ValueError, e:
- pass
- else:
- self.fail('non-number input phase does not raise a TypeError')
def test_zeros_is_one(self):
- from math import isinf
assert level_detection(fvec(1024), -70) == 1
def test_minus_ones_is_zero(self):
from numpy import ones
- assert level_detection(ones(1024, dtype="float32"), -70) == 0
+ assert level_detection(ones(1024, dtype = float_type), -70) == 0
if __name__ == '__main__':
- from unittest import main
main()
#! /usr/bin/env python
# -*- coding: utf-8 -*-
-from aubio import note2midi
+from __future__ import unicode_literals
+
+from aubio import note2midi, freq2note
+from nose2.tools import params
import unittest
list_of_known_notes = (
( 'C3', 48 ),
( 'B3', 59 ),
( 'B#3', 60 ),
+ ( 'C♯4', 61 ),
( 'A4', 69 ),
( 'A#4', 70 ),
+ ( 'A♯4', 70 ),
+ ( 'A\u266f4', 70 ),
( 'Bb4', 70 ),
- ( u'B♭4', 70 ),
+ ( 'B♭4', 70 ),
+ ( 'B\u266d4', 70 ),
( 'G8', 115 ),
- ( u'G♯8', 116 ),
+ ( 'G♯8', 116 ),
( 'G9', 127 ),
- ( u'G\udd2a2', 45 ),
- ( u'B\ufffd2', 45 ),
- ( u'A♮2', 45 ),
+ ( 'A♮2', 45 ),
+ )
+
+list_of_known_notes_with_unicode_issues = (
+ ('C𝄪4', 62 ),
+ ('E𝄫4', 62 ),
+ )
+
+list_of_unknown_notes = (
+ ( 'G\udd2a2' ),
+ ( 'B\ufffd2' ),
+ ( 'B\u266e\u266e2' ),
+ ( 'B\u266f\u266d3' ),
+ ( 'B33' ),
+ ( 'C.3' ),
+ ( 'A' ),
+ ( '2' ),
)
class note2midi_good_values(unittest.TestCase):
- def test_note2midi_known_values(self):
+ @params(*list_of_known_notes)
+ def test_note2midi_known_values(self, note, midi):
" known values are correctly converted "
- for note, midi in list_of_known_notes:
+ self.assertEqual ( note2midi(note), midi )
+
+ @params(*list_of_known_notes_with_unicode_issues)
+ def test_note2midi_known_values_with_unicode_issues(self, note, midi):
+ " known values are correctly converted, unless decoding is expected to fail"
+ try:
self.assertEqual ( note2midi(note), midi )
+ except UnicodeEncodeError as e:
+ import sys
+ strfmt = "len(u'\\U0001D12A') != 1, excpected decoding failure | {:s} | {:s} {:s}"
+ strres = strfmt.format(e, sys.platform, sys.version)
+ # happens with: darwin 2.7.10, windows 2.7.12
+ if len('\U0001D12A') != 1 and sys.version[0] == '2':
+ self.skipTest(strres + " | upgrade to Python 3 to fix")
+ else:
+ raise
class note2midi_wrong_values(unittest.TestCase):
self.assertRaises(ValueError, note2midi, 'CBc')
def test_note2midi_out_of_range(self):
- " fails when passed a out of range note"
+ " fails when passed a note out of range"
self.assertRaises(ValueError, note2midi, 'A9')
+ def test_note2midi_wrong_note_name(self):
+ " fails when passed a note with a wrong name"
+ self.assertRaises(ValueError, note2midi, 'W9')
+
+ def test_note2midi_low_octave(self):
+ " fails when passed a note with a too low octave"
+ self.assertRaises(ValueError, note2midi, 'C-9')
+
def test_note2midi_wrong_data_type(self):
" fails when passed a non-string value "
self.assertRaises(TypeError, note2midi, 123)
+ def test_note2midi_wrong_data_too_long(self):
+ " fails when passed a note with a note name longer than expected"
+ self.assertRaises(ValueError, note2midi, 'CB+-3')
+
+ @params(*list_of_unknown_notes)
+ def test_note2midi_unknown_values(self, note):
+ " unknown values throw out an error "
+ self.assertRaises(ValueError, note2midi, note)
+
+class freq2note_simple_test(unittest.TestCase):
+
+ def test_freq2note(self):
+ " make sure freq2note(441) == A4 "
+ self.assertEqual("A4", freq2note(441))
+
if __name__ == '__main__':
- unittest.main()
+ import nose2
+ nose2.main()
--- /dev/null
+#! /usr/bin/env python
+
+from unittest import main
+from numpy.testing import TestCase, assert_equal, assert_almost_equal
+from aubio import notes
+
+AUBIO_DEFAULT_NOTES_SILENCE = -70.
+AUBIO_DEFAULT_NOTES_MINIOI_MS = 30.
+
+class aubio_notes_default(TestCase):
+
+ def test_members(self):
+ o = notes()
+ assert_equal ([o.buf_size, o.hop_size, o.method, o.samplerate],
+ [1024,512,'default',44100])
+
+
+class aubio_notes_params(TestCase):
+
+ samplerate = 44100
+
+ def setUp(self):
+ self.o = notes(samplerate = self.samplerate)
+
+ def test_get_minioi_ms(self):
+ assert_equal (self.o.get_minioi_ms(), AUBIO_DEFAULT_NOTES_MINIOI_MS)
+
+ def test_set_minioi_ms(self):
+ val = 40.
+ self.o.set_minioi_ms(val)
+ assert_almost_equal (self.o.get_minioi_ms(), val)
+
+ def test_get_silence(self):
+ assert_equal (self.o.get_silence(), AUBIO_DEFAULT_NOTES_SILENCE)
+
+ def test_set_silence(self):
+ val = -50
+ self.o.set_silence(val)
+ assert_equal (self.o.get_silence(), val)
+
+from .utils import list_all_sounds
+list_of_sounds = list_all_sounds('sounds')
+
+class aubio_notes_sinewave(TestCase):
+
+ def analyze_file(self, filepath, samplerate=0):
+ from aubio import source
+ import numpy as np
+ win_s = 512 # fft size
+ hop_s = 256 # hop size
+
+ s = source(filepath, samplerate, hop_s)
+ samplerate = s.samplerate
+
+ tolerance = 0.8
+
+ notes_o = notes("default", win_s, hop_s, samplerate)
+ total_frames = 0
+
+ results = []
+ while True:
+ samples, read = s()
+ new_note = notes_o(samples)
+ if (new_note[0] != 0):
+ note_str = ' '.join(["%.2f" % i for i in new_note])
+ results.append( [total_frames, np.copy(new_note)] )
+ total_frames += read
+ if read < hop_s: break
+ return results
+
+ def test_sinewave(self):
+ for filepath in list_of_sounds:
+ if '44100Hz_44100f_sine441.wav' in filepath:
+ results = self.analyze_file(filepath)
+ assert_equal (len(results), 1)
+ assert_equal (len(results[0]), 2)
+ assert_equal (results[0][0], 1280)
+ assert_equal (results[0][1], [69, 123, -1])
+
+if __name__ == '__main__':
+ main()
#! /usr/bin/env python
-from numpy.testing import TestCase, run_module_suite
-from numpy.testing import assert_equal, assert_almost_equal
+from unittest import main
+from numpy.testing import TestCase, assert_equal, assert_almost_equal
from aubio import onset
class aubio_onset_default(TestCase):
samplerate = 8000
if __name__ == '__main__':
- from unittest import main
main()
#! /usr/bin/env python
-from numpy.testing import TestCase, assert_equal, assert_almost_equal
-from aubio import fvec, cvec, pvoc
-from numpy import array, shape
-from numpy.random import random
+from numpy.testing import TestCase, assert_equal, assert_array_less
+from aubio import fvec, cvec, pvoc, float_type
+from nose2 import main
+from nose2.tools import params
+import numpy as np
-precision = 6
+if float_type == 'float32':
+ max_sq_error = 1.e-12
+else:
+ max_sq_error = 1.e-29
+
+def create_sine(hop_s, freq, samplerate):
+ t = np.arange(hop_s).astype(float_type)
+ return np.sin( 2. * np.pi * freq * t / float(samplerate))
+
+def create_noise(hop_s):
+ return np.random.rand(hop_s).astype(float_type) * 2. - 1.
class aubio_pvoc_test_case(TestCase):
""" pvoc object test case """
win_s, hop_s = 1024, 256
f = pvoc (win_s, hop_s)
t = fvec (hop_s)
- for time in range( 4 * win_s / hop_s ):
+ for _ in range( int ( 4 * win_s / hop_s ) ):
s = f(t)
r = f.rdo(s)
- assert_equal ( array(t), 0)
- assert_equal ( s.norm, 0)
- assert_equal ( s.phas, 0)
- assert_equal ( r, 0)
-
- def test_resynth_two_steps(self):
- """ check the resynthesis of steps is correct with 50% overlap """
- hop_s = 512
- buf_s = hop_s * 2
+ assert_equal ( t, 0.)
+ assert_equal ( s.norm, 0.)
+ try:
+ assert_equal ( s.phas, 0 )
+ except AssertionError:
+ assert_equal (s.phas[s.phas > 0], +np.pi)
+ assert_equal (s.phas[s.phas < 0], -np.pi)
+ assert_equal (np.abs(s.phas[np.abs(s.phas) != np.pi]), 0)
+ self.skipTest('pvoc(fvec(%d)).phas != +0, ' % win_s \
+ + 'This is expected when using fftw3 on powerpc.')
+ assert_equal ( r, 0.)
+
+ @params(
+ ( 256, 8),
+ ( 256, 4),
+ ( 256, 2),
+ ( 512, 8),
+ ( 512, 4),
+ ( 512, 2),
+ #( 129, 2),
+ #( 320, 4),
+ #( 13, 8),
+ (1024, 8),
+ (1024, 4),
+ (1024, 2),
+ (2048, 8),
+ (2048, 4),
+ (2048, 2),
+ (4096, 8),
+ (4096, 4),
+ (4096, 2),
+ (8192, 8),
+ (8192, 4),
+ (8192, 2),
+ )
+ def test_resynth_steps_noise(self, hop_s, ratio):
+ """ check the resynthesis of a random signal is correct """
+ sigin = create_noise(hop_s)
+ self.reconstruction(sigin, hop_s, ratio)
+
+ @params(
+ (44100, 256, 8, 441),
+ (44100, 256, 4, 1203),
+ (44100, 256, 2, 3045),
+ (44100, 512, 8, 445),
+ (44100, 512, 4, 445),
+ (44100, 512, 2, 445),
+ (44100, 1024, 8, 445),
+ (44100, 1024, 4, 445),
+ (44100, 1024, 2, 445),
+ ( 8000, 1024, 2, 445),
+ (22050, 1024, 2, 445),
+ (22050, 256, 8, 445),
+ (96000, 1024, 8, 47000),
+ (96000, 1024, 8, 20),
+ )
+ def test_resynth_steps_sine(self, samplerate, hop_s, ratio, freq):
+ """ check the resynthesis of a sine is correct """
+ sigin = create_sine(hop_s, freq, samplerate)
+ self.reconstruction(sigin, hop_s, ratio)
+
+ def reconstruction(self, sigin, hop_s, ratio):
+ buf_s = hop_s * ratio
f = pvoc(buf_s, hop_s)
- sigin = fvec(hop_s)
zeros = fvec(hop_s)
- # negative step
- sigin[20:50] = -.1
- # positive step
- sigin[100:200] = .1
- s1 = f(sigin)
- r1 = f.rdo(s1)
- s2 = f(zeros)
- r2 = f.rdo(s2)
- #self.plot_this ( s2.norm.T )
- assert_almost_equal ( r2, sigin, decimal = precision )
-
- def test_resynth_three_steps(self):
- """ check the resynthesis of steps is correct with 25% overlap """
- hop_s = 16
- buf_s = hop_s * 4
- sigin = fvec(hop_s)
- zeros = fvec(hop_s)
- f = pvoc(buf_s, hop_s)
- for i in xrange(hop_s):
- sigin[i] = random() * 2. - 1.
- t2 = f.rdo( f(sigin) )
- t2 = f.rdo( f(zeros) )
- t2 = f.rdo( f(zeros) )
- t2 = f.rdo( f(zeros) )
- assert_almost_equal( sigin, t2, decimal = precision )
-
- def plot_this( self, this ):
- from pylab import semilogy, show
- semilogy ( this )
- show ()
+ r2 = f.rdo( f(sigin) )
+ for _ in range(1, ratio):
+ r2 = f.rdo( f(zeros) )
+ # compute square errors
+ sq_error = (r2 - sigin)**2
+ # make sure all square errors are less than desired precision
+ assert_array_less(sq_error, max_sq_error)
+
+class aubio_pvoc_strange_params(TestCase):
+
+ def test_win_size_short(self):
+ with self.assertRaises(RuntimeError):
+ pvoc(1, 1)
+
+ def test_hop_size_long(self):
+ with self.assertRaises(RuntimeError):
+ pvoc(1024, 1025)
+
+ def test_large_input_timegrain(self):
+ win_s = 1024
+ f = pvoc(win_s)
+ t = fvec(win_s + 1)
+ with self.assertRaises(ValueError):
+ f(t)
+
+ def test_small_input_timegrain(self):
+ win_s = 1024
+ f = pvoc(win_s)
+ t = fvec(1)
+ with self.assertRaises(ValueError):
+ f(t)
+
+ def test_large_input_fftgrain(self):
+ win_s = 1024
+ f = pvoc(win_s)
+ s = cvec(win_s + 5)
+ with self.assertRaises(ValueError):
+ f.rdo(s)
+
+ def test_small_input_fftgrain(self):
+ win_s = 1024
+ f = pvoc(win_s)
+ s = cvec(16)
+ with self.assertRaises(ValueError):
+ f.rdo(s)
+
+class aubio_pvoc_wrong_params(TestCase):
+
+ def test_wrong_buf_size(self):
+ win_s = -1
+ with self.assertRaises(ValueError):
+ pvoc(win_s)
+
+ def test_buf_size_too_small(self):
+ win_s = 1
+ with self.assertRaises(RuntimeError):
+ pvoc(win_s)
+
+ def test_hop_size_negative(self):
+ win_s = 512
+ hop_s = -2
+ with self.assertRaises(ValueError):
+ pvoc(win_s, hop_s)
+
+ def test_hop_size_too_small(self):
+ win_s = 1
+ hop_s = 1
+ with self.assertRaises(RuntimeError):
+ pvoc(win_s, hop_s)
+
+ def test_buf_size_not_power_of_two(self):
+ win_s = 320
+ hop_s = win_s // 2
+ try:
+ with self.assertRaises(RuntimeError):
+ pvoc(win_s, hop_s)
+ except AssertionError:
+ # when compiled with fftw3, aubio supports non power of two fft sizes
+ self.skipTest('creating aubio.pvoc with size %d did not fail' % win_s)
if __name__ == '__main__':
- from unittest import main
- main()
+ main()
#! /usr/bin/env python
-from unittest import TestCase
-from numpy.testing import assert_equal, assert_almost_equal
-from numpy import random, sin, arange, mean, median, isnan
-from math import pi
-from aubio import fvec, pitch, freqtomidi
+from unittest import TestCase, main
+from numpy.testing import assert_equal
+from numpy import sin, arange, mean, median, isnan, pi
+from aubio import fvec, pitch, freqtomidi, float_type
class aubio_pitch_Good_Values(TestCase):
" running on silence gives 0 "
p = pitch('default', 2048, 512, 32000)
f = fvec (512)
- for i in xrange(10): assert_equal (p(f), 0.)
+ for _ in range(10): assert_equal (p(f), 0.)
def test_run_on_ones(self):
" running on ones gives 0 "
p = pitch('default', 2048, 512, 32000)
f = fvec (512)
f[:] = 1
- for i in xrange(10): assert_equal (p(f), 0.)
+ for _ in range(10): assert_equal (p(f), 0.)
class aubio_pitch_Sinusoid(TestCase):
self.run_pitch(p, sinvec, freq)
def build_sinusoid(self, length, freq, samplerate):
- return sin( 2. * pi * arange(length).astype('float32') * freq / samplerate)
+ return sin( 2. * pi * arange(length).astype(float_type) * freq / samplerate)
def run_pitch(self, p, input_vec, freq):
- count = 0
pitches, errors = [], []
input_blocks = input_vec.reshape((-1, p.hop_size))
for new_block in input_blocks:
assert_equal ( len(input_blocks), len(pitches) )
assert_equal ( isnan(pitches), False )
# cut the first candidates
- cut = ( p.buf_size - p.hop_size ) / p.hop_size
+ #cut = ( p.buf_size - p.hop_size ) / p.hop_size
pitches = pitches[2:]
errors = errors[2:]
# check that the mean of all relative errors is less than 10%
setattr (aubio_pitch_Sinusoid, test_method.__name__, test_method)
if __name__ == '__main__':
- from unittest import main
main()
#! /usr/bin/env python
-from numpy.testing import TestCase, assert_equal, assert_almost_equal
+from nose2 import main
+from nose2.tools import params
+from numpy.testing import TestCase
from aubio import fvec, source, sink
-from numpy import array
-from utils import list_all_sounds, get_tmp_sink_path, del_tmp_sink_path
+from .utils import list_all_sounds, get_tmp_sink_path, del_tmp_sink_path
+
+import warnings
+warnings.filterwarnings('ignore', category=UserWarning, append=True)
list_of_sounds = list_all_sounds('sounds')
+samplerates = [0, 44100, 8000, 32000]
+hop_sizes = [512, 1024, 64]
+
path = None
many_files = 300 # 256 opened files is too much
+all_params = []
+for soundfile in list_of_sounds:
+ for hop_size in hop_sizes:
+ for samplerate in samplerates:
+ all_params.append((hop_size, samplerate, soundfile))
+
class aubio_sink_test_case(TestCase):
+ def setUp(self):
+ if not len(list_of_sounds):
+ self.skipTest('add some sound files in \'python/tests/sounds\'')
+
+ def test_wrong_filename(self):
+ with self.assertRaises(RuntimeError):
+ sink('')
+
+ def test_wrong_samplerate(self):
+ with self.assertRaises(RuntimeError):
+ sink(get_tmp_sink_path(), -1)
+
+ def test_wrong_samplerate_too_large(self):
+ with self.assertRaises(RuntimeError):
+ sink(get_tmp_sink_path(), 1536001, 2)
+
+ def test_wrong_channels(self):
+ with self.assertRaises(RuntimeError):
+ sink(get_tmp_sink_path(), 44100, -1)
+
+ def test_wrong_channels_too_large(self):
+ with self.assertRaises(RuntimeError):
+ sink(get_tmp_sink_path(), 44100, 202020)
+
def test_many_sinks(self):
from tempfile import mkdtemp
import os.path
g = sink(path, 0)
sink_list.append(g)
write = 32
- for n in range(200):
+ for _ in range(200):
vec = fvec(write)
g(vec, write)
g.close()
shutil.rmtree(tmpdir)
- def test_many_sinks_not_closed(self):
- from tempfile import mkdtemp
- import os.path
- import shutil
- tmpdir = mkdtemp()
- sink_list = []
- try:
- for i in range(many_files):
- path = os.path.join(tmpdir, 'f-' + str(i) + '.wav')
- g = sink(path, 0)
- sink_list.append(g)
- write = 256
- for n in range(200):
- vec = fvec(write)
- g(vec, write)
- except StandardError:
- pass
- else:
- self.fail("does not fail on too many files open")
- for g in sink_list:
- g.close()
- shutil.rmtree(tmpdir)
-
- def test_read_and_write(self):
+ @params(*all_params)
+ def test_read_and_write(self, hop_size, samplerate, path):
- if not len(list_of_sounds):
- self.skipTest('add some sound files in \'python/tests/sounds\'')
-
- for path in list_of_sounds:
- for samplerate, hop_size in zip([0, 44100, 8000, 32000], [512, 1024, 64, 256]):
- f = source(path, samplerate, hop_size)
- if samplerate == 0: samplerate = f.samplerate
- sink_path = get_tmp_sink_path()
- g = sink(sink_path, samplerate)
- total_frames = 0
- while True:
- vec, read = f()
- g(vec, read)
- total_frames += read
- if read < f.hop_size: break
- if 0:
- print "read", "%.2fs" % (total_frames / float(f.samplerate) ),
- print "(", total_frames, "frames", "in",
- print total_frames / f.hop_size, "blocks", "at", "%dHz" % f.samplerate, ")",
- print "from", f.uri,
- print "to", g.uri
- del_tmp_sink_path(sink_path)
-
- def test_read_and_write_multi(self):
-
- if not len(list_of_sounds):
- self.skipTest('add some sound files in \'python/tests/sounds\'')
+ try:
+ f = source(path, samplerate, hop_size)
+ except RuntimeError as e:
+ self.skipTest('failed opening with hop_s = {:d}, samplerate = {:d} ({:s})'.format(hop_size, samplerate, str(e)))
+ if samplerate == 0: samplerate = f.samplerate
+ sink_path = get_tmp_sink_path()
+ g = sink(sink_path, samplerate)
+ total_frames = 0
+ while True:
+ vec, read = f()
+ g(vec, read)
+ total_frames += read
+ if read < f.hop_size: break
+ del_tmp_sink_path(sink_path)
- for path in list_of_sounds:
- for samplerate, hop_size in zip([0, 44100, 8000, 32000], [512, 1024, 64, 256]):
- f = source(path, samplerate, hop_size)
- if samplerate == 0: samplerate = f.samplerate
- sink_path = get_tmp_sink_path()
- g = sink(sink_path, samplerate, channels = f.channels)
- total_frames = 0
- while True:
- vec, read = f.do_multi()
- g.do_multi(vec, read)
- total_frames += read
- if read < f.hop_size: break
- if 0:
- print "read", "%.2fs" % (total_frames / float(f.samplerate) ),
- print "(", total_frames, "frames", "in",
- print f.channels, "channels", "in",
- print total_frames / f.hop_size, "blocks", "at", "%dHz" % f.samplerate, ")",
- print "from", f.uri,
- print "to", g.uri,
- print "in", g.channels, "channels"
- del_tmp_sink_path(sink_path)
+ @params(*all_params)
+ def test_read_and_write_multi(self, hop_size, samplerate, path):
+ try:
+ f = source(path, samplerate, hop_size)
+ except RuntimeError as e:
+ self.skipTest('failed opening with hop_s = {:d}, samplerate = {:d} ({:s})'.format(hop_size, samplerate, str(e)))
+ if samplerate == 0: samplerate = f.samplerate
+ sink_path = get_tmp_sink_path()
+ g = sink(sink_path, samplerate, channels = f.channels)
+ total_frames = 0
+ while True:
+ vec, read = f.do_multi()
+ g.do_multi(vec, read)
+ total_frames += read
+ if read < f.hop_size: break
+ del_tmp_sink_path(sink_path)
def test_close_file(self):
samplerate = 44100
g.close()
del_tmp_sink_path(sink_path)
+ def test_read_with(self):
+ sink_path =get_tmp_sink_path()
+ vec = fvec(128)
+ with sink(sink_path, samplerate) as g:
+ for i in range(10):
+ g(vec, 128)
+
if __name__ == '__main__':
- from unittest import main
main()
#! /usr/bin/env python
-from numpy.testing import TestCase, run_module_suite
-from numpy.testing import assert_equal, assert_almost_equal
-
+from unittest import main
+from numpy.testing import TestCase, assert_equal
from aubio import slice_source_at_stamps
-from utils import *
+from .utils import count_files_in_directory, get_default_test_sound
+from .utils import count_samples_in_directory, count_samples_in_file
import tempfile
import shutil
shutil.rmtree(self.output_dir)
if __name__ == '__main__':
- from unittest import main
main()
#! /usr/bin/env python
-from numpy.testing import TestCase, assert_equal, assert_almost_equal
-from aubio import fvec, source
-from numpy import array
-from utils import list_all_sounds
+from nose2 import main
+from nose2.tools import params
+from numpy.testing import TestCase, assert_equal
+from aubio import source
+from .utils import list_all_sounds
+import numpy as np
+
+import warnings
+warnings.filterwarnings('ignore', category=UserWarning, append=True)
list_of_sounds = list_all_sounds('sounds')
+samplerates = [0, 44100, 8000, 32000]
+hop_sizes = [512, 1024, 64]
+
path = None
+all_params = []
+for soundfile in list_of_sounds:
+ for hop_size in hop_sizes:
+ for samplerate in samplerates:
+ all_params.append((hop_size, samplerate, soundfile))
+
+
class aubio_source_test_case_base(TestCase):
def setUp(self):
- if not len(list_of_sounds): self.skipTest('add some sound files in \'python/tests/sounds\'')
+ if not len(list_of_sounds):
+ self.skipTest('add some sound files in \'python/tests/sounds\'')
+ self.default_test_sound = list_of_sounds[0]
class aubio_source_test_case(aubio_source_test_case_base):
- def test_close_file(self):
+ @params(*list_of_sounds)
+ def test_close_file(self, filename):
samplerate = 0 # use native samplerate
hop_size = 256
- for p in list_of_sounds:
- f = source(p, samplerate, hop_size)
- f.close()
+ f = source(filename, samplerate, hop_size)
+ f.close()
- def test_close_file_twice(self):
+ @params(*list_of_sounds)
+ def test_close_file_twice(self, filename):
samplerate = 0 # use native samplerate
hop_size = 256
- for p in list_of_sounds:
- f = source(p, samplerate, hop_size)
- f.close()
- f.close()
+ f = source(filename, samplerate, hop_size)
+ f.close()
+ f.close()
class aubio_source_read_test_case(aubio_source_test_case_base):
def read_from_source(self, f):
total_frames = 0
while True:
- vec, read = f()
+ samples , read = f()
total_frames += read
- if read < f.hop_size: break
- print "read", "%.2fs" % (total_frames / float(f.samplerate) ),
- print "(", total_frames, "frames", "in",
- print total_frames / f.hop_size, "blocks", "at", "%dHz" % f.samplerate, ")",
- print "from", f.uri
+ if read < f.hop_size:
+ assert_equal(samples[read:], 0)
+ break
+ #result_str = "read {:.2f}s ({:d} frames in {:d} blocks at {:d}Hz) from {:s}"
+ #result_params = total_frames / float(f.samplerate), total_frames, total_frames//f.hop_size, f.samplerate, f.uri
+ #print (result_str.format(*result_params))
return total_frames
- def test_samplerate_hopsize(self):
- for p in list_of_sounds:
- for samplerate, hop_size in zip([0, 44100, 8000, 32000], [ 512, 512, 64, 256]):
- f = source(p, samplerate, hop_size)
- assert f.samplerate != 0
- self.read_from_source(f)
-
- def test_samplerate_none(self):
- for p in list_of_sounds:
- f = source(p)
- assert f.samplerate != 0
- self.read_from_source(f)
-
- def test_samplerate_0(self):
- for p in list_of_sounds:
- f = source(p, 0)
- assert f.samplerate != 0
- self.read_from_source(f)
+ @params(*all_params)
+ def test_samplerate_hopsize(self, hop_size, samplerate, soundfile):
+ try:
+ f = source(soundfile, samplerate, hop_size)
+ except RuntimeError as e:
+ self.skipTest('failed opening with hop_s = {:d}, samplerate = {:d} ({:s})'.format(hop_size, samplerate, str(e)))
+ assert f.samplerate != 0
+ read_frames = self.read_from_source(f)
+ if 'f_' in soundfile and samplerate == 0:
+ import re
+ f = re.compile('.*_\([0:9]*f\)_.*')
+ match_f = re.findall('([0-9]*)f_', soundfile)
+ if len(match_f) == 1:
+ expected_frames = int(match_f[0])
+ self.assertEqual(expected_frames, read_frames)
+
+ @params(*list_of_sounds)
+ def test_samplerate_none(self, p):
+ f = source(p)
+ assert f.samplerate != 0
+ self.read_from_source(f)
+
+ @params(*list_of_sounds)
+ def test_samplerate_0(self, p):
+ f = source(p, 0)
+ assert f.samplerate != 0
+ self.read_from_source(f)
+
+ @params(*list_of_sounds)
+ def test_zero_hop_size(self, p):
+ f = source(p, 0, 0)
+ assert f.samplerate != 0
+ assert f.hop_size != 0
+ self.read_from_source(f)
+
+ @params(*list_of_sounds)
+ def test_seek_to_half(self, p):
+ from random import randint
+ f = source(p, 0, 0)
+ assert f.samplerate != 0
+ assert f.hop_size != 0
+ a = self.read_from_source(f)
+ c = randint(0, a)
+ f.seek(c)
+ b = self.read_from_source(f)
+ assert a == b + c
+
+ @params(*list_of_sounds)
+ def test_duration(self, p):
+ total_frames = 0
+ f = source(p)
+ duration = f.duration
+ while True:
+ _, read = f()
+ total_frames += read
+ if read < f.hop_size: break
+ self.assertEqual(duration, total_frames)
+
+
+class aubio_source_test_wrong_params(TestCase):
+
+ def test_wrong_file(self):
+ with self.assertRaises(RuntimeError):
+ source('path_to/unexisting file.mp3')
+
+class aubio_source_test_wrong_params_with_file(aubio_source_test_case_base):
def test_wrong_samplerate(self):
- for p in list_of_sounds:
- try:
- f = source(p, -1)
- except ValueError, e:
- pass
- else:
- self.fail('negative samplerate does not raise ValueError')
+ with self.assertRaises(ValueError):
+ source(self.default_test_sound, -1)
def test_wrong_hop_size(self):
- for p in list_of_sounds:
- try:
- f = source(p, 0, -1)
- except ValueError, e:
- pass
- else:
- self.fail('negative hop_size does not raise ValueError')
-
- def test_zero_hop_size(self):
- for p in list_of_sounds:
- f = source(p, 0, 0)
- assert f.samplerate != 0
- assert f.hop_size != 0
- self.read_from_source(f)
-
- def test_seek_to_half(self):
- from random import randint
- for p in list_of_sounds:
- f = source(p, 0, 0)
- assert f.samplerate != 0
- assert f.hop_size != 0
- a = self.read_from_source(f)
- c = randint(0, a)
- f.seek(c)
- b = self.read_from_source(f)
- assert a == b + c
+ with self.assertRaises(ValueError):
+ source(self.default_test_sound, 0, -1)
+
+ def test_wrong_channels(self):
+ with self.assertRaises(ValueError):
+ source(self.default_test_sound, 0, 0, -1)
+
+ def test_wrong_seek(self):
+ f = source(self.default_test_sound)
+ with self.assertRaises(ValueError):
+ f.seek(-1)
+
+ def test_wrong_seek_too_large(self):
+ f = source(self.default_test_sound)
+ try:
+ with self.assertRaises(ValueError):
+ f.seek(f.duration + f.samplerate * 10)
+ except AssertionError:
+ self.skipTest('seeking after end of stream failed raising ValueError')
class aubio_source_readmulti_test_case(aubio_source_read_test_case):
def read_from_source(self, f):
total_frames = 0
while True:
- vec, read = f.do_multi()
+ samples, read = f.do_multi()
total_frames += read
- if read < f.hop_size: break
- print "read", "%.2fs" % (total_frames / float(f.samplerate) ),
- print "(", total_frames, "frames", "in",
- print f.channels, "channels and",
- print total_frames / f.hop_size, "blocks", "at", "%dHz" % f.samplerate, ")",
- print "from", f.uri
+ if read < f.hop_size:
+ assert_equal(samples[:,read:], 0)
+ break
+ #result_str = "read {:.2f}s ({:d} frames in {:d} channels and {:d} blocks at {:d}Hz) from {:s}"
+ #result_params = total_frames / float(f.samplerate), total_frames, f.channels, int(total_frames/f.hop_size), f.samplerate, f.uri
+ #print (result_str.format(*result_params))
return total_frames
+class aubio_source_with(aubio_source_test_case_base):
+
+ #@params(*list_of_sounds)
+ @params(*list_of_sounds)
+ def test_read_from_mono(self, filename):
+ total_frames = 0
+ hop_size = 2048
+ with source(filename, 0, hop_size) as input_source:
+ assert_equal(input_source.hop_size, hop_size)
+ #assert_equal(input_source.samplerate, samplerate)
+ total_frames = 0
+ for frames in input_source:
+ total_frames += frames.shape[-1]
+ # check we read as many samples as we expected
+ assert_equal(total_frames, input_source.duration)
+
if __name__ == '__main__':
- from unittest import main
main()
#! /usr/bin/env python
+from unittest import main
from numpy.testing import TestCase, assert_equal, assert_almost_equal
from numpy import random, arange, log, zeros
-from aubio import specdesc, cvec
-from math import pi
+from aubio import specdesc, cvec, float_type
methods = ["default",
"energy",
o = specdesc()
for method in methods:
- o = specdesc(method, buf_size)
- assert_equal ([o.buf_size, o.method], [buf_size, method])
-
- spec = cvec(buf_size)
- spec.norm[0] = 1
- spec.norm[1] = 1./2.
- #print "%20s" % method, str(o(spec))
- o(spec)
- spec.norm = random.random_sample((len(spec.norm),)).astype('float32')
- spec.phas = random.random_sample((len(spec.phas),)).astype('float32')
- #print "%20s" % method, str(o(spec))
- assert (o(spec) != 0.)
-
- def test_hfc(self):
- o = specdesc("hfc", buf_size)
- spec = cvec(buf_size)
- # hfc of zeros is zero
- assert_equal (o(spec), 0.)
- # hfc of ones is sum of all bin numbers
- spec.norm[:] = 1
- expected = sum(range(buf_size/2 + 2))
- assert_equal (o(spec), expected)
- # changing phase doesn't change anything
- spec.phas[:] = 1
- assert_equal (o(spec), sum(range(buf_size/2 + 2)))
+ o = specdesc(method, buf_size)
+ assert_equal ([o.buf_size, o.method], [buf_size, method])
+
+ spec = cvec(buf_size)
+ spec.norm[0] = 1
+ spec.norm[1] = 1./2.
+ #print "%20s" % method, str(o(spec))
+ o(spec)
+ spec.norm = random.random_sample((len(spec.norm),)).astype(float_type)
+ spec.phas = random.random_sample((len(spec.phas),)).astype(float_type)
+ #print "%20s" % method, str(o(spec))
+ assert (o(spec) != 0.)
def test_phase(self):
o = specdesc("phase", buf_size)
spec = cvec(buf_size)
# phase of zeros is zero
assert_equal (o(spec), 0.)
- spec.phas = random.random_sample((len(spec.phas),)).astype('float32')
+ spec.phas = random.random_sample((len(spec.phas),)).astype(float_type)
# phase of random is not zero
spec.norm[:] = 1
assert (o(spec) != 0.)
spec = cvec(buf_size)
# specdiff of zeros is zero
assert_equal (o(spec), 0.)
- spec.phas = random.random_sample((len(spec.phas),)).astype('float32')
+ spec.phas = random.random_sample((len(spec.phas),)).astype(float_type)
# phase of random is not zero
spec.norm[:] = 1
assert (o(spec) != 0.)
o = specdesc("hfc")
c = cvec()
assert_equal( 0., o(c))
- a = arange(c.length, dtype='float32')
+ a = arange(c.length, dtype=float_type)
c.norm = a
assert_equal (a, c.norm)
assert_equal ( sum(a*(a+1)), o(c))
o = specdesc("complex")
c = cvec()
assert_equal( 0., o(c))
- a = arange(c.length, dtype='float32')
+ a = arange(c.length, dtype=float_type)
c.norm = a
assert_equal (a, c.norm)
# the previous run was on zeros, so previous frames are still 0
o = specdesc("kl")
c = cvec()
assert_equal( 0., o(c))
- a = arange(c.length, dtype='float32')
+ a = arange(c.length, dtype=float_type)
c.norm = a
assert_almost_equal( sum(a * log(1.+ a/1.e-1 ) ) / o(c), 1., decimal=6)
o = specdesc("mkl")
c = cvec()
assert_equal( 0., o(c))
- a = arange(c.length, dtype='float32')
+ a = arange(c.length, dtype=float_type)
c.norm = a
assert_almost_equal( sum(log(1.+ a/1.e-1 ) ) / o(c), 1, decimal=6)
o = specdesc("specflux")
c = cvec()
assert_equal( 0., o(c))
- a = arange(c.length, dtype='float32')
+ a = arange(c.length, dtype=float_type)
c.norm = a
assert_equal( sum(a), o(c))
assert_equal( 0, o(c))
- c.norm = zeros(c.length, dtype='float32')
+ c.norm = zeros(c.length, dtype=float_type)
assert_equal( 0, o(c))
def test_centroid(self):
c = cvec()
# make sure centroid of zeros is zero
assert_equal( 0., o(c))
- a = arange(c.length, dtype='float32')
+ a = arange(c.length, dtype=float_type)
c.norm = a
centroid = sum(a*a) / sum(a)
assert_almost_equal (centroid, o(c), decimal = 2)
def test_spread(self):
o = specdesc("spread")
- c = cvec(2048)
- ramp = arange(c.length, dtype='float32')
+ c = cvec(1024)
+ ramp = arange(c.length, dtype=float_type)
assert_equal( 0., o(c))
a = ramp
o = specdesc("skewness")
c = cvec()
assert_equal( 0., o(c))
- a = arange(c.length, dtype='float32')
+ a = arange(c.length, dtype=float_type)
c.norm = a
centroid = sum(a*a) / sum(a)
spread = sum( (a - centroid)**2 *a) / sum(a)
o = specdesc("kurtosis")
c = cvec()
assert_equal( 0., o(c))
- a = arange(c.length, dtype='float32')
+ a = arange(c.length, dtype=float_type)
c.norm = a
centroid = sum(a*a) / sum(a)
spread = sum( (a - centroid)**2 *a) / sum(a)
o = specdesc("slope")
c = cvec()
assert_equal( 0., o(c))
- a = arange(c.length * 2, 0, -2, dtype='float32')
- k = arange(c.length, dtype='float32')
+ a = arange(c.length * 2, 0, -2, dtype=float_type)
+ k = arange(c.length, dtype=float_type)
c.norm = a
num = len(a) * sum(k*a) - sum(k)*sum(a)
den = (len(a) * sum(k**2) - sum(k)**2)
slope = num/den/sum(a)
assert_almost_equal (slope, o(c), decimal = 5)
- a = arange(0, c.length * 2, +2, dtype='float32')
+ a = arange(0, c.length * 2, +2, dtype=float_type)
c.norm = a
num = len(a) * sum(k*a) - sum(k)*sum(a)
den = (len(a) * sum(k**2) - sum(k)**2)
slope = num/den/sum(a)
assert_almost_equal (slope, o(c), decimal = 5)
- a = arange(0, c.length * 2, +2, dtype='float32')
+ a = arange(0, c.length * 2, +2, dtype=float_type)
c.norm = a * 2
assert_almost_equal (slope, o(c), decimal = 5)
o = specdesc("decrease")
c = cvec()
assert_equal( 0., o(c))
- a = arange(c.length * 2, 0, -2, dtype='float32')
- k = arange(c.length, dtype='float32')
+ a = arange(c.length * 2, 0, -2, dtype=float_type)
+ k = arange(c.length, dtype=float_type)
c.norm = a
decrease = sum((a[1:] - a [0]) / k[1:]) / sum(a[1:])
assert_almost_equal (decrease, o(c), decimal = 5)
- a = arange(0, c.length * 2, +2, dtype='float32')
+ a = arange(0, c.length * 2, +2, dtype=float_type)
c.norm = a
decrease = sum((a[1:] - a [0]) / k[1:]) / sum(a[1:])
assert_almost_equal (decrease, o(c), decimal = 5)
- a = arange(0, c.length * 2, +2, dtype='float32')
+ a = arange(0, c.length * 2, +2, dtype=float_type)
c.norm = a * 2
decrease = sum((a[1:] - a [0]) / k[1:]) / sum(a[1:])
assert_almost_equal (decrease, o(c), decimal = 5)
o = specdesc("rolloff")
c = cvec()
assert_equal( 0., o(c))
- a = arange(c.length * 2, 0, -2, dtype='float32')
- k = arange(c.length, dtype='float32')
+ a = arange(c.length * 2, 0, -2, dtype=float_type)
c.norm = a
cumsum = .95*sum(a*a)
i = 0; rollsum = 0
while rollsum < cumsum:
- rollsum += a[i]*a[i]
- i+=1
+ rollsum += a[i]*a[i]
+ i+=1
rolloff = i
assert_equal (rolloff, o(c))
+class aubio_specdesc_wrong(TestCase):
+
+ def test_negative(self):
+ with self.assertRaises(ValueError):
+ specdesc("default", -10)
+
+ def test_unknown(self):
+ with self.assertRaises(RuntimeError):
+ specdesc("unknown", 512)
if __name__ == '__main__':
- from unittest import main
main()
#! /usr/bin/env python
+from unittest import main
from numpy.testing import TestCase
-
from aubio import fvec, zero_crossing_rate
buf_size = 2048
def test_impulse(self):
""" check zero crossing rate on a buffer with an impulse """
- self.vector[buf_size / 2] = 1.
+ self.vector[int(buf_size / 2)] = 1.
self.assertEqual(0., zero_crossing_rate(self.vector))
def test_negative_impulse(self):
""" check zero crossing rate on a buffer with a negative impulse """
- self.vector[buf_size / 2] = -1.
+ self.vector[int(buf_size / 2)] = -1.
self.assertEqual(2./buf_size, zero_crossing_rate(self.vector))
def test_single(self):
""" check zero crossing rate on single crossing """
- self.vector[buf_size / 2 - 1] = 1.
- self.vector[buf_size / 2] = -1.
+ self.vector[int(buf_size / 2) - 1] = 1.
+ self.vector[int(buf_size / 2)] = -1.
self.assertEqual(2./buf_size, zero_crossing_rate(self.vector))
def test_single_with_gap(self):
""" check zero crossing rate on single crossing with a gap"""
- self.vector[buf_size / 2 - 2] = 1.
- self.vector[buf_size / 2] = -1.
+ self.vector[int(buf_size / 2) - 2] = 1.
+ self.vector[int(buf_size / 2)] = -1.
self.assertEqual(2./buf_size, zero_crossing_rate(self.vector))
if __name__ == '__main__':
- from unittest import main
main()
#! /usr/bin/env python
+import os
+import glob
+import numpy as np
+from tempfile import mkstemp
+
+DEFAULT_SOUND = '22050Hz_5s_brownnoise.wav'
+
def array_from_text_file(filename, dtype = 'float'):
- import os.path
- from numpy import array
filename = os.path.join(os.path.dirname(__file__), filename)
- return array([line.split() for line in open(filename).readlines()],
- dtype = dtype)
+ with open(filename) as f:
+ lines = f.readlines()
+ return np.array([line.split() for line in lines],
+ dtype = dtype)
def list_all_sounds(rel_dir):
- import os.path, glob
datadir = os.path.join(os.path.dirname(__file__), rel_dir)
return glob.glob(os.path.join(datadir,'*.*'))
if len(all_sounds) == 0:
TestCase.skipTest("please add some sounds in \'python/tests/sounds\'")
else:
- return all_sounds[0]
+ default_sound = all_sounds[0]
+ if DEFAULT_SOUND in map(os.path.basename, all_sounds):
+ while os.path.basename(default_sound) != DEFAULT_SOUND:
+ default_sound = all_sounds.pop(0)
+ return default_sound
def get_tmp_sink_path():
- from tempfile import mkstemp
- import os
fd, path = mkstemp()
os.close(fd)
return path
def del_tmp_sink_path(path):
- import os
- os.unlink(path)
+ try:
+ os.unlink(path)
+ except WindowsError as e:
+ print("deleting {:s} failed ({:s}), reopening".format(path, repr(e)))
+ with open(path, 'wb') as f:
+ f.close()
+ try:
+ os.unlink(path)
+ except WindowsError as f:
+ print("deleting {:s} failed ({:s}), aborting".format(path, repr(e)))
def array_from_yaml_file(filename):
import yaml
s = source(file_path, 0, hopsize)
total_frames = 0
while True:
- samples, read = s()
+ _, read = s()
total_frames += read
if read < hopsize: break
return total_frames
def count_samples_in_directory(samples_dir):
- import os
total_frames = 0
for f in os.walk(samples_dir):
if len(f[2]):
return total_frames
def count_files_in_directory(samples_dir):
- import os
total_files = 0
for f in os.walk(samples_dir):
if len(f[2]):
--- /dev/null
+numpy
+nose2
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleExecutable</key>
+ <string>$(EXECUTABLE_NAME)</string>
+ <key>CFBundleIdentifier</key>
+ <string>org.aubio.$(PRODUCT_NAME:rfc1034identifier)</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>$(PRODUCT_NAME)</string>
+ <key>CFBundlePackageType</key>
+ <string>FMWK</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>$(CURRENT_PROJECT_VERSION)</string>
+ <key>NSHumanReadableCopyright</key>
+ <string>Copyright © 2015 Paul Brossier. All rights reserved.</string>
+ <key>NSPrincipalClass</key>
+ <string></string>
+</dict>
+</plist>
--- /dev/null
+framework module aubio {
+ umbrella header "aubio.h"
+
+ export *
+ module * { export * }
+}
--- /dev/null
+#! /bin/bash
+
+set -e
+set -x
+
+# location of android NDK
+NDK_PATH=$PWD/../contrib/android-ndk-r12
+
+WAFOPTS="--disable-avcodec --disable-samplerate --disable-jack --disable-sndfile"
+
+# set these variables to change the default values
+[ -z $PLATFORM ] && PLATFORM=android-19
+[ -z $ARCH ] && ARCH=arm
+
+# location nof the standalone toolchains, created with
+# $NDK_PATH/build/tools/make-standalone-toolchains.sh
+NDK_TOOLCHAINS=$PWD/contrib
+
+# location of the current toolchain
+CURRENT_TOOLCHAIN=$NDK_TOOLCHAINS/toolchain-$PLATFORM-$ARCH
+
+# if it does not exist, create the toolchain
+[ -d $CURRENT_TOOLCHAIN ] || \
+ $NDK_PATH/build/tools/make-standalone-toolchain.sh \
+ --platform=$PLATFORM --arch=$ARCH \
+ --install-dir=$CURRENT_TOOLCHAIN
+
+# aubio install destination directory
+DESTDIR=$PWD/dist-$PLATFORM-$ARCH
+
+# wipe it out if it exists
+[ -d $DESTDIR ] && rm -rf $DESTDIR
+
+# get the link to gcc
+CC=`ls $CURRENT_TOOLCHAIN/*-linux-android*/bin/gcc`
+
+CFLAGS="-Os" \
+ CC=$CC \
+ ./waf distclean configure build install --destdir=$DESTDIR \
+ --verbose \
+ --with-target-platform=android $WAFOPTS
--- /dev/null
+#! /bin/sh
+
+# cd to aubio directory for consistency
+cd `dirname $0`/..
+
+AUBIO_TMPDIR=`mktemp -d /var/tmp/aubio-build-XXXX`
+PACKAGE=aubio
+source VERSION
+VERSION=$AUBIO_MAJOR_VERSION.$AUBIO_MINOR_VERSION.$AUBIO_PATCH_VERSION$AUBIO_VERSION_STATUS
+LIBVERSION=$LIBAUBIO_LT_CUR.$LIBAUBIO_LT_REV.$LIBAUBIO_LT_AGE
+OUTPUTDIR=$PWD/dist
+mkdir -p "$OUTPUTDIR"
+# add git abbreviated commit hash
+#VERSION+=+$(git log --pretty=format:"%h" -1)
+
+CFLAGS="-Werror -Ofast"
+WAFCONF="--disable-sndfile --disable-avcodec --disable-samplerate --enable-fat" # --disable-memcpy --disable-accelerate"
+
+export VERSION
+
+function cleanup () {
+ rm -rf $AUBIO_TMPDIR
+}
+
+trap cleanup SIGINT SIGTERM
+
+function create_tarballs() {
+ # name version platform
+ # create tarball
+ tarfile=$OUTPUTDIR/$1-$2.$3_binary.tar.bz2
+ tar -C $AUBIO_TMPDIR/dist-$3/ -jcf "$tarfile" .
+ #rm -rf $AUBIO_TMPDIR/dist-$3
+}
+
+function create_framework() {
+ rm -rf $AUBIO_TMPDIR/framework-$3
+ mkdir -p $AUBIO_TMPDIR/framework-$3/$1-$2.$3_framework/$1.framework
+ cp -pr COPYING README.md $AUBIO_TMPDIR/framework-$3/$1-$2.$3_framework
+ pushd $AUBIO_TMPDIR/framework-$3
+ cp -pr "$OLDPWD/build/src/lib$1.a" $1-$2.$3_framework/$1.framework/$1 || \
+ cp -pr $AUBIO_TMPDIR/dist-$3/usr/local/lib/lib$1.$LIBVERSION.dylib \
+ $AUBIO_TMPDIR/framework-$3/$1-$2.$3_framework/$1.framework/$1
+ cp -pr $AUBIO_TMPDIR/dist-$3/usr/local/include/$1 $1-$2.$3_framework/$1.framework/Headers
+ cp -pr "$OLDPWD/scripts/apple/Modules" $1-$2.$3_framework/$1.framework/
+ popd
+}
+
+function create_framework_fat() {
+ rm -rf $AUBIO_TMPDIR/framework-$3
+ mkdir -p $AUBIO_TMPDIR/framework-$3/$1-$2.$3_framework/$1.framework
+ cp -pr COPYING README.md $AUBIO_TMPDIR/framework-$3/$1-$2.$3_framework
+ pushd $AUBIO_TMPDIR/framework-$3
+ cp -pr $AUBIO_TMPDIR/framework-ios/$1-$2.ios_framework/$1.framework/Headers $1-$2.$3_framework/$1.framework
+ cp -pr $AUBIO_TMPDIR/framework-ios/$1-$2.ios_framework/$1.framework/Modules $1-$2.$3_framework/$1.framework
+ lipo $AUBIO_TMPDIR/framework-ios/$1-$2.ios_framework/$1.framework/$1 \
+ $AUBIO_TMPDIR/framework-iosimulator/$1-$2.iosimulator_framework/$1.framework/$1 \
+ -output $1-$2.$3_framework/$1.framework/$1 -create
+ popd
+}
+
+function create_framework_zip() {
+ # create zip
+ pushd $AUBIO_TMPDIR/framework-$3
+ zipfile=$1-$2.$3_framework.zip
+ zip -qr $zipfile $1-$2.$3_framework
+ popd
+ mv $AUBIO_TMPDIR/framework-$3/$zipfile "$OUTPUTDIR"
+}
+
+set -x
+set -e
+
+#./waf dist --verbose
+
+for PLATFORM in darwin ios iosimulator
+do
+ rm -rf $AUBIO_TMPDIR/dist-$PLATFORM
+ WAF_OPTIONS="--verbose --destdir $AUBIO_TMPDIR/dist-$PLATFORM --with-target-platform $PLATFORM $WAFCONF"
+ for target in distclean configure build install
+ do
+ CFLAGS="$CFLAGS" ./waf $target $WAF_OPTIONS
+ done
+
+ create_framework $PACKAGE $VERSION $PLATFORM
+ if [ $PLATFORM == 'darwin' ]
+ then
+ # on darwin, build a .tar.bz2 of /usr and a .zip of aubio.framework
+ create_tarballs $PACKAGE $VERSION $PLATFORM
+ create_framework_zip $PACKAGE $VERSION $PLATFORM
+ fi
+ ./waf uninstall $WAF_OPTIONS
+
+done
+
+# after both ios and iosimulator have been built
+PLATFORM=iosuniversal
+create_framework_fat $PACKAGE $VERSION $PLATFORM
+create_framework_zip $PACKAGE $VERSION $PLATFORM
+
+./waf clean
+./waf distclean
+
+cleanup
--- /dev/null
+#! /bin/sh
+
+function checkprog() {
+ type $1 >/dev/null 2>&1 || { echo >&2 "$1 required but not found, aborting."; exit 1; }
+}
+
+checkprog emcc
+checkprog emconfigure
+checkprog emmake
+
+# clean
+emmake ./waf distclean
+
+# configure
+emconfigure ./waf configure --prefix=$EMSCRIPTEN/system/local/ --with-target-platform emscripten
+
+# build
+emmake ./waf --testcmd="node %s"
+
+# intall
+#emmake ./waf install
--- /dev/null
+#! /bin/bash
+
+# This script cross compiles aubio for windows using mingw, both for 32 and 64
+# bits. Built binaries will be placed in ./dist-win32 and ./dist-win64.
+
+# On debian or ubuntu, you will want to 'apt-get install gcc-mingw-w64'
+
+set -e
+set -x
+
+WAFOPTS="-v --disable-avcodec --disable-samplerate --disable-jack --disable-sndfile"
+
+[ -d dist-win32 ] && rm -rf dist-win32
+[ -d dist-win64 ] && rm -rf dist-win64
+
+CFLAGS="-Os" \
+ LDFLAGS="" \
+ CC=x86_64-w64-mingw32-gcc \
+ ./waf distclean configure build install --destdir=$PWD/dist-win64 \
+ --testcmd="echo %s" \
+ $WAFOPTS --with-target-platform=win64
+
+CFLAGS="-Os" \
+ LDFLAGS="" \
+ CC=i686-w64-mingw32-gcc \
+ ./waf distclean configure build install --destdir=$PWD/dist-win32 \
+ --testcmd="echo %s" \
+ $WAFOPTS --with-target-platform=win32
--- /dev/null
+#! /bin/sh
+
+set -e
+set -x
+
+WAFURL=https://waf.io/waf-1.8.22
+
+( which wget > /dev/null && wget -qO waf $WAFURL ) || ( which curl > /dev/null && curl $WAFURL > waf )
+
+chmod +x waf
--- /dev/null
+#! /usr/bin/env bash
+
+# This script sets the environment to execute aubio binaries and python code
+# directly from build/ python/build/ without installing libaubio on the system
+
+# Usage: $ source ./scripts/setenv_local.sh
+
+# WARNING: this script will *overwrite* existing (DY)LD_LIBRARY_PATH and
+# PYTHONPATH variables.
+
+PYTHON_PLATFORM=`python -c "import pkg_resources, sys; print ('%s-%s' % (pkg_resources.get_build_platform(), '.'.join(map(str, sys.version_info[0:2]))))"`
+
+AUBIODIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )"
+AUBIOLIB=$AUBIODIR/build/src
+AUBIOPYTHON=$AUBIODIR/build/lib.$PYTHON_PLATFORM
+
+if [ "$(dirname $PWD)" == "scripts" ]; then
+ AUBIODIR=$(basename $PWD)
+else
+ AUBIODIR=$(basename $PWD)
+fi
+
+if [ "$(uname)" == "Darwin" ]; then
+ export DYLD_LIBRARY_PATH=$AUBIOLIB
+ echo export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH
+else
+ export LD_LIBRARY_PATH=$AUBIOLIB
+ echo export LD_LIBRARY_PATH=$LD_LIBRARY_PATH
+fi
+
+export PYTHONPATH=$AUBIOPYTHON
+echo export PYTHONPATH=$PYTHONPATH
--- /dev/null
+#! /usr/bin/env python
+
+import sys, os.path, glob
+from setuptools import setup, Extension
+from python.lib.moresetuptools import *
+# function to generate gen/*.{c,h}
+from python.lib.gen_external import generate_external, header, output_path
+
+__version__ = get_aubio_pyversion()
+
+include_dirs = []
+library_dirs = []
+define_macros = [('AUBIO_VERSION', '%s' % __version__)]
+extra_link_args = []
+
+include_dirs += [ 'python/ext' ]
+include_dirs += [ output_path ] # aubio-generated.h
+try:
+ import numpy
+ include_dirs += [ numpy.get_include() ]
+except ImportError:
+ pass
+
+if sys.platform.startswith('darwin'):
+ extra_link_args += ['-framework','CoreFoundation', '-framework','AudioToolbox']
+
+sources = sorted(glob.glob(os.path.join('python', 'ext', '*.c')))
+
+aubio_extension = Extension("aubio._aubio",
+ sources,
+ include_dirs = include_dirs,
+ library_dirs = library_dirs,
+ extra_link_args = extra_link_args,
+ define_macros = define_macros)
+
+if os.path.isfile('src/aubio.h'):
+ if not os.path.isdir(os.path.join('build','src')):
+ pass
+ #__version__ += 'a2' # python only version
+
+classifiers = [
+ 'Development Status :: 4 - Beta',
+ 'Environment :: Console',
+ 'Intended Audience :: Science/Research',
+ 'Topic :: Software Development :: Libraries',
+ 'Topic :: Multimedia :: Sound/Audio :: Analysis',
+ 'Topic :: Multimedia :: Sound/Audio :: Sound Synthesis',
+ 'Operating System :: POSIX',
+ 'Operating System :: MacOS :: MacOS X',
+ 'Operating System :: Microsoft :: Windows',
+ 'Programming Language :: C',
+ 'Programming Language :: Python',
+ 'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)',
+ ]
+
+distrib = setup(name='aubio',
+ version = __version__,
+ packages = ['aubio'],
+ package_dir = {'aubio':'python/lib/aubio'},
+ scripts = ['python/scripts/aubiocut'],
+ ext_modules = [aubio_extension],
+ description = 'a collection of tools for music analysis',
+ long_description = 'a collection of tools for music analysis',
+ license = 'GNU/GPL version 3',
+ author = 'Paul Brossier',
+ author_email = 'piem@aubio.org',
+ maintainer = 'Paul Brossier',
+ maintainer_email = 'piem@aubio.org',
+ url = 'https://aubio.org/',
+ platforms = 'any',
+ classifiers = classifiers,
+ install_requires = ['numpy'],
+ setup_requires = ['numpy'],
+ cmdclass = {
+ 'clean': CleanGenerated,
+ 'build_ext': build_ext,
+ },
+ test_suite = 'nose2.collector.collector',
+ extras_require = {
+ 'tests': ['numpy'],
+ },
+ )
Several examples of C programs are available in the \p examples/ and \p tests/src
directories of the source tree.
+ Some examples:
+ - @ref spectral/test-fft.c
+ - @ref spectral/test-phasevoc.c
+ - @ref onset/test-onset.c
+ - @ref pitch/test-pitch.c
+ - @ref tempo/test-tempo.c
+ - @ref test-fvec.c
+ - @ref test-cvec.c
+
\subsection unstable_api Unstable API
Several more functions are available and used within aubio, but not
\section download Download
Latest versions, further documentation, examples, wiki, and mailing lists can
- be found at http://aubio.org .
+ be found at https://aubio.org .
*/
#include "pitch/pitch.h"
#include "onset/onset.h"
#include "tempo/tempo.h"
+#include "notes/notes.h"
#include "io/source.h"
#include "io/sink.h"
#include "synth/sampler.h"
#include "synth/wavetable.h"
#include "utils/parameter.h"
+#include "utils/log.h"
#if AUBIO_UNSTABLE
#include "mathutils.h"
* This file is for inclusion from _within_ the library only.
*/
-#ifndef _AUBIO__PRIV_H
-#define _AUBIO__PRIV_H
+#ifndef AUBIO_PRIV_H
+#define AUBIO_PRIV_H
/*********************
*
*
*/
+#ifdef HAVE_CONFIG_H
#include "config.h"
+#endif
-#if HAVE_STDLIB_H
+#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
-#if HAVE_STDIO_H
+#ifdef HAVE_STDIO_H
#include <stdio.h>
#endif
#include <limits.h> // for CHAR_BIT, in C99 standard
#endif
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#endif
+
#ifdef HAVE_ACCELERATE
#define HAVE_ATLAS 1
#include <Accelerate/Accelerate.h>
-#elif HAVE_ATLAS_CBLAS_H
+#elif defined(HAVE_ATLAS_CBLAS_H)
#define HAVE_ATLAS 1
#include <atlas/cblas.h>
#else
#ifdef HAVE_ACCELERATE
#include <Accelerate/Accelerate.h>
-#if !HAVE_AUBIO_DOUBLE
+#ifndef HAVE_AUBIO_DOUBLE
#define aubio_vDSP_mmov vDSP_mmov
#define aubio_vDSP_vmul vDSP_vmul
#define aubio_vDSP_vfill vDSP_vfill
#define aubio_vDSP_maxvi vDSP_maxvi
#define aubio_vDSP_minv vDSP_minv
#define aubio_vDSP_minvi vDSP_minvi
+#define aubio_vDSP_dotpr vDSP_dotpr
#else /* HAVE_AUBIO_DOUBLE */
#define aubio_vDSP_mmov vDSP_mmovD
#define aubio_vDSP_vmul vDSP_vmulD
#define aubio_vDSP_maxvi vDSP_maxviD
#define aubio_vDSP_minv vDSP_minvD
#define aubio_vDSP_minvi vDSP_minviD
+#define aubio_vDSP_dotpr vDSP_dotprD
#endif /* HAVE_AUBIO_DOUBLE */
#endif /* HAVE_ACCELERATE */
#ifdef HAVE_ATLAS
-#if !HAVE_AUBIO_DOUBLE
+#ifndef HAVE_AUBIO_DOUBLE
#define aubio_catlas_set catlas_sset
#define aubio_cblas_copy cblas_scopy
#define aubio_cblas_swap cblas_sswap
AUBIO_FAIL = 1
} aubio_status;
+/* Logging */
+
+#include "utils/log.h"
+
+/** internal logging function, defined in utils/log.c */
+uint_t aubio_log(sint_t level, const char_t *fmt, ...);
+
#ifdef HAVE_C99_VARARGS_MACROS
-#define AUBIO_ERR(...) fprintf(stderr, "AUBIO ERROR: " __VA_ARGS__)
-#define AUBIO_MSG(...) fprintf(stdout, __VA_ARGS__)
-#define AUBIO_DBG(...) fprintf(stderr, __VA_ARGS__)
-#define AUBIO_WRN(...) fprintf(stderr, "AUBIO WARNING: " __VA_ARGS__)
+#define AUBIO_ERR(...) aubio_log(AUBIO_LOG_ERR, "AUBIO ERROR: " __VA_ARGS__)
+#define AUBIO_INF(...) aubio_log(AUBIO_LOG_INF, "AUBIO INFO: " __VA_ARGS__)
+#define AUBIO_MSG(...) aubio_log(AUBIO_LOG_MSG, __VA_ARGS__)
+#define AUBIO_DBG(...) aubio_log(AUBIO_LOG_DBG, __VA_ARGS__)
+#define AUBIO_WRN(...) aubio_log(AUBIO_LOG_WRN, "AUBIO WARNING: " __VA_ARGS__)
#else
-#define AUBIO_ERR(format, args...) fprintf(stderr, "AUBIO ERROR: " format , ##args)
-#define AUBIO_MSG(format, args...) fprintf(stdout, format , ##args)
-#define AUBIO_DBG(format, args...) fprintf(stderr, format , ##args)
-#define AUBIO_WRN(format, args...) fprintf(stderr, "AUBIO WARNING: " format, ##args)
+#define AUBIO_ERR(format, args...) aubio_log(AUBIO_LOG_ERR, "AUBIO ERROR: " format , ##args)
+#define AUBIO_INF(format, args...) aubio_log(AUBIO_LOG_INF, "AUBIO INFO: " format , ##args)
+#define AUBIO_MSG(format, args...) aubio_log(AUBIO_LOG_MSG, format , ##args)
+#define AUBIO_DBG(format, args...) aubio_log(AUBIO_LOG_DBG, format , ##args)
+#define AUBIO_WRN(format, args...) aubio_log(AUBIO_LOG_WRN, "AUBIO WARNING: " format, ##args)
#endif
#define AUBIO_ERROR AUBIO_ERR
#define AUBIO_QUIT(_s) exit(_s)
#define AUBIO_SPRINTF sprintf
+#define AUBIO_MAX_SAMPLERATE (192000*8)
+#define AUBIO_MAX_CHANNELS 1024
+
/* pi and 2*pi */
#ifndef M_PI
#define PI (3.14159265358979323846)
#endif
#define TWO_PI (PI*2.)
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
/* aliases to math.h functions */
#if !HAVE_AUBIO_DOUBLE
#define EXP expf
#define LOG logf
#define FLOOR floorf
#define CEIL ceilf
+#define ATAN atanf
#define ATAN2 atan2f
#else
#define EXP exp
#define LOG log
#define FLOOR floor
#define CEIL ceil
+#define ATAN atan
#define ATAN2 atan2
#endif
#define ROUND(x) FLOOR(x+.5)
#define IMAG cimagf
#endif
+/* avoid unresolved symbol with msvc 9 */
+#if defined(_MSC_VER) && (_MSC_VER < 1900)
+#define isnan _isnan
+#endif
+
/* handy shortcuts */
#define DB2LIN(g) (POW(10.0,(g)*0.05f))
#define LIN2DB(v) (20.0*LOG10(v))
#define UNUSED
#endif
-#endif /* _AUBIO__PRIV_H */
+/* are we using gcc -std=c99 ? */
+#if defined(__STRICT_ANSI__)
+#define strnlen(a,b) MIN(strlen(a),b)
+#if !HAVE_AUBIO_DOUBLE
+#define floorf floor
+#endif
+#endif /* __STRICT_ANSI__ */
+
+#endif /* AUBIO_PRIV_H */
#include "aubio_priv.h"
#include "cvec.h"
-cvec_t * new_cvec( uint_t length) {
+cvec_t * new_cvec(uint_t length) {
cvec_t * s;
if ((sint_t)length <= 0) {
return NULL;
return s->phas[position];
}
-smpl_t * cvec_norm_get_data (cvec_t *s) {
+smpl_t * cvec_norm_get_data (const cvec_t *s) {
return s->norm;
}
-smpl_t * cvec_phas_get_data (cvec_t *s) {
+smpl_t * cvec_phas_get_data (const cvec_t *s) {
return s->phas;
}
/* helper functions */
-void cvec_print(cvec_t *s) {
+void cvec_print(const cvec_t *s) {
uint_t j;
AUBIO_MSG("norm: ");
for (j=0; j< s->length; j++) {
AUBIO_MSG("\n");
}
-void cvec_copy(cvec_t *s, cvec_t *t) {
+void cvec_copy(const cvec_t *s, cvec_t *t) {
if (s->length != t->length) {
AUBIO_ERR("trying to copy %d elements to %d elements \n",
s->length, t->length);
return;
}
-#if HAVE_MEMCPY_HACKS
+#ifdef HAVE_MEMCPY_HACKS
memcpy(t->norm, s->norm, t->length * sizeof(smpl_t));
memcpy(t->phas, s->phas, t->length * sizeof(smpl_t));
-#else
+#else /* HAVE_MEMCPY_HACKS */
uint_t j;
for (j=0; j< t->length; j++) {
t->norm[j] = s->norm[j];
t->phas[j] = s->phas[j];
}
-#endif
+#endif /* HAVE_MEMCPY_HACKS */
}
void cvec_norm_set_all (cvec_t *s, smpl_t val) {
}
void cvec_norm_zeros(cvec_t *s) {
-#if HAVE_MEMCPY_HACKS
+#ifdef HAVE_MEMCPY_HACKS
memset(s->norm, 0, s->length * sizeof(smpl_t));
-#else
+#else /* HAVE_MEMCPY_HACKS */
cvec_norm_set_all (s, 0.);
-#endif
+#endif /* HAVE_MEMCPY_HACKS */
}
void cvec_norm_ones(cvec_t *s) {
}
void cvec_phas_zeros(cvec_t *s) {
-#if HAVE_MEMCPY_HACKS
+#ifdef HAVE_MEMCPY_HACKS
memset(s->phas, 0, s->length * sizeof(smpl_t));
#else
cvec_phas_set_all (s, 0.);
*/
-#ifndef _AUBIO__CVEC_H
-#define _AUBIO__CVEC_H
+#ifndef AUBIO_CVEC_H
+#define AUBIO_CVEC_H
#ifdef __cplusplus
extern "C" {
\param s vector to read from
*/
-smpl_t * cvec_norm_get_data (cvec_t *s);
+smpl_t * cvec_norm_get_data (const cvec_t *s);
/** read phase data from a complex buffer
\param s vector to read from
*/
-smpl_t * cvec_phas_get_data (cvec_t *s);
+smpl_t * cvec_phas_get_data (const cvec_t *s);
/** print out cvec data
\param s vector to print out
*/
-void cvec_print(cvec_t *s);
+void cvec_print(const cvec_t *s);
/** make a copy of a vector
\param t vector to copy to
*/
-void cvec_copy(cvec_t *s, cvec_t *t);
+void cvec_copy(const cvec_t *s, cvec_t *t);
/** set all norm elements to a given value
}
#endif
-#endif /* _AUBIO__CVEC_H */
+#endif /* AUBIO_CVEC_H */
s->data[channel][position] = data;
}
-smpl_t fmat_get_sample(fmat_t *s, uint_t channel, uint_t position) {
+smpl_t fmat_get_sample(const fmat_t *s, uint_t channel, uint_t position) {
return s->data[channel][position];
}
-void fmat_get_channel(fmat_t *s, uint_t channel, fvec_t *output) {
+void fmat_get_channel(const fmat_t *s, uint_t channel, fvec_t *output) {
output->data = s->data[channel];
output->length = s->length;
return;
}
-smpl_t * fmat_get_channel_data(fmat_t *s, uint_t channel) {
+smpl_t * fmat_get_channel_data(const fmat_t *s, uint_t channel) {
return s->data[channel];
}
-smpl_t ** fmat_get_data(fmat_t *s) {
+smpl_t ** fmat_get_data(const fmat_t *s) {
return s->data;
}
/* helper functions */
-void fmat_print(fmat_t *s) {
+void fmat_print(const fmat_t *s) {
uint_t i,j;
for (i=0; i< s->height; i++) {
for (j=0; j< s->length; j++) {
}
void fmat_zeros(fmat_t *s) {
-#if HAVE_MEMCPY_HACKS
+#ifdef HAVE_MEMCPY_HACKS
uint_t i;
for (i=0; i< s->height; i++) {
memset(s->data[i], 0, s->length * sizeof(smpl_t));
}
-#else
+#else /* HAVE_MEMCPY_HACKS */
fmat_set(s, 0.);
-#endif
+#endif /* HAVE_MEMCPY_HACKS */
}
void fmat_ones(fmat_t *s) {
void fmat_rev(fmat_t *s) {
uint_t i,j;
for (i=0; i< s->height; i++) {
- for (j=0; j< FLOOR(s->length/2); j++) {
+ for (j=0; j< FLOOR((smpl_t)s->length/2); j++) {
ELEM_SWAP(s->data[i][j], s->data[i][s->length-1-j]);
}
}
}
-void fmat_weight(fmat_t *s, fmat_t *weight) {
+void fmat_weight(fmat_t *s, const fmat_t *weight) {
uint_t i,j;
uint_t length = MIN(s->length, weight->length);
for (i=0; i< s->height; i++) {
}
}
-void fmat_copy(fmat_t *s, fmat_t *t) {
+void fmat_copy(const fmat_t *s, fmat_t *t) {
uint_t i;
-#if !HAVE_MEMCPY_HACKS
+#ifndef HAVE_MEMCPY_HACKS
uint_t j;
-#endif
+#endif /* HAVE_MEMCPY_HACKS */
if (s->height != t->height) {
AUBIO_ERR("trying to copy %d rows to %d rows \n",
s->height, t->height);
s->length, t->length);
return;
}
-#if HAVE_MEMCPY_HACKS
+#ifdef HAVE_MEMCPY_HACKS
for (i=0; i< s->height; i++) {
memcpy(t->data[i], s->data[i], t->length * sizeof(smpl_t));
}
-#else
+#else /* HAVE_MEMCPY_HACKS */
for (i=0; i< t->height; i++) {
for (j=0; j< t->length; j++) {
t->data[i][j] = s->data[i][j];
}
}
-#endif
+#endif /* HAVE_MEMCPY_HACKS */
}
+void fmat_vecmul(const fmat_t *s, const fvec_t *scale, fvec_t *output) {
+ uint_t k;
+#if 0
+ assert(s->height == output->length);
+ assert(s->length == scale->length);
+#endif
+#if !defined(HAVE_ACCELERATE) && !defined(HAVE_ATLAS)
+ uint_t j;
+ fvec_zeros(output);
+ for (j = 0; j < s->length; j++) {
+ for (k = 0; k < s->height; k++) {
+ output->data[k] += scale->data[j]
+ * s->data[k][j];
+ }
+ }
+#elif defined(HAVE_ATLAS)
+ for (k = 0; k < s->height; k++) {
+ output->data[k] = aubio_cblas_dot( s->length, scale->data, 1, s->data[k], 1);
+ }
+#elif defined(HAVE_ACCELERATE)
+#if 0
+ // seems slower and less precise (and dangerous?)
+ vDSP_mmul (s->data[0], 1, scale->data, 1, output->data, 1, s->height, 1, s->length);
+#else
+ for (k = 0; k < s->height; k++) {
+ aubio_vDSP_dotpr( scale->data, 1, s->data[k], 1, &(output->data[k]), s->length);
+ }
+#endif
+#endif
+}
*/
-#ifndef _AUBIO__FMAT_H
-#define _AUBIO__FMAT_H
+#ifndef AUBIO_FMAT_H
+#define AUBIO_FMAT_H
#ifdef __cplusplus
extern "C" {
\param position sample position to read from
*/
-smpl_t fmat_get_sample(fmat_t *s, uint_t channel, uint_t position);
+smpl_t fmat_get_sample(const fmat_t *s, uint_t channel, uint_t position);
/** write sample value in a buffer
\param output ::fvec_t to output to
*/
-void fmat_get_channel (fmat_t *s, uint_t channel, fvec_t *output);
+void fmat_get_channel (const fmat_t *s, uint_t channel, fvec_t *output);
/** get vector buffer from an fmat data
\param channel channel to read from
*/
-smpl_t * fmat_get_channel_data (fmat_t *s, uint_t channel);
+smpl_t * fmat_get_channel_data (const fmat_t *s, uint_t channel);
/** read data from a buffer
\param s vector to read from
*/
-smpl_t ** fmat_get_data(fmat_t *s);
+smpl_t ** fmat_get_data(const fmat_t *s);
/** print out fmat data
\param s vector to print out
*/
-void fmat_print(fmat_t *s);
+void fmat_print(const fmat_t *s);
/** set all elements to a given value
\param weight weighting coefficients
*/
-void fmat_weight(fmat_t *s, fmat_t *weight);
+void fmat_weight(fmat_t *s, const fmat_t *weight);
/** make a copy of a matrix
\param t vector to copy to
*/
-void fmat_copy(fmat_t *s, fmat_t *t);
+void fmat_copy(const fmat_t *s, fmat_t *t);
+
+/** compute the product of a matrix by a vector
+
+ \param s matrix to compute product with
+ \param scale vector to compute product with
+ \param output vector to store restults in
+
+*/
+void fmat_vecmul(const fmat_t *s, const fvec_t *scale, fvec_t *output);
#ifdef __cplusplus
}
#endif
-#endif /* _AUBIO__FMAT_H */
+#endif /* AUBIO_FMAT_H */
#include "aubio_priv.h"
#include "fvec.h"
-fvec_t * new_fvec( uint_t length) {
+fvec_t * new_fvec(uint_t length) {
fvec_t * s;
if ((sint_t)length <= 0) {
return NULL;
s->data[position] = data;
}
-smpl_t fvec_get_sample(fvec_t *s, uint_t position) {
+smpl_t fvec_get_sample(const fvec_t *s, uint_t position) {
return s->data[position];
}
-smpl_t * fvec_get_data(fvec_t *s) {
+smpl_t * fvec_get_data(const fvec_t *s) {
return s->data;
}
/* helper functions */
-void fvec_print(fvec_t *s) {
+void fvec_print(const fvec_t *s) {
uint_t j;
for (j=0; j< s->length; j++) {
AUBIO_MSG(AUBIO_SMPL_FMT " ", s->data[j]);
void fvec_rev(fvec_t *s) {
uint_t j;
- for (j=0; j< FLOOR(s->length/2); j++) {
+ for (j=0; j< FLOOR((smpl_t)s->length/2); j++) {
ELEM_SWAP(s->data[j], s->data[s->length-1-j]);
}
}
-void fvec_weight(fvec_t *s, fvec_t *weight) {
+void fvec_weight(fvec_t *s, const fvec_t *weight) {
#ifndef HAVE_ACCELERATE
uint_t j;
uint_t length = MIN(s->length, weight->length);
#endif /* HAVE_ACCELERATE */
}
-void fvec_weighted_copy(fvec_t *in, fvec_t *weight, fvec_t *out) {
+void fvec_weighted_copy(const fvec_t *in, const fvec_t *weight, fvec_t *out) {
#ifndef HAVE_ACCELERATE
uint_t j;
uint_t length = MIN(out->length, weight->length);
#endif /* HAVE_ACCELERATE */
}
-void fvec_copy(fvec_t *s, fvec_t *t) {
+void fvec_copy(const fvec_t *s, fvec_t *t) {
if (s->length != t->length) {
AUBIO_ERR("trying to copy %d elements to %d elements \n",
s->length, t->length);
return;
}
-#if HAVE_NOOPT
+#ifdef HAVE_NOOPT
uint_t j;
for (j=0; j< t->length; j++) {
t->data[j] = s->data[j];
*/
-#ifndef _AUBIO__FVEC_H
-#define _AUBIO__FVEC_H
+#ifndef AUBIO_FVEC_H
+#define AUBIO_FVEC_H
#ifdef __cplusplus
extern "C" {
\param position sample position to read from
*/
-smpl_t fvec_get_sample(fvec_t *s, uint_t position);
+smpl_t fvec_get_sample(const fvec_t *s, uint_t position);
/** write sample value in a buffer
\param s vector to read from
*/
-smpl_t * fvec_get_data(fvec_t *s);
+smpl_t * fvec_get_data(const fvec_t *s);
/** print out fvec data
\param s vector to print out
*/
-void fvec_print(fvec_t *s);
+void fvec_print(const fvec_t *s);
/** set all elements to a given value
\param weight weighting coefficients
*/
-void fvec_weight(fvec_t *s, fvec_t *weight);
+void fvec_weight(fvec_t *s, const fvec_t *weight);
/** make a copy of a vector
\param t vector to copy to
*/
-void fvec_copy(fvec_t *s, fvec_t *t);
+void fvec_copy(const fvec_t *s, fvec_t *t);
/** make a copy of a vector, applying weights to each element
\param out output vector
*/
-void fvec_weighted_copy(fvec_t *in, fvec_t *weight, fvec_t *out);
+void fvec_weighted_copy(const fvec_t *in, const fvec_t *weight, fvec_t *out);
#ifdef __cplusplus
}
#endif
-#endif /* _AUBIO__FVEC_H */
+#endif /* AUBIO_FVEC_H */
*/
-#include "config.h"
-#ifdef HAVE_AUDIO_UNIT
#include "aubio_priv.h"
+#ifdef HAVE_AUDIO_UNIT
#include "fvec.h"
#include "fmat.h"
*/
-#ifndef _AUBIO_AUDIO_UNIT_H
-#define _AUBIO_AUDIO_UNIT_H
+#ifndef AUBIO_AUDIO_UNIT_H
+#define AUBIO_AUDIO_UNIT_H
/** \file
}
#endif
-#endif /* _AUBIO_AUDIO_UNIT_H */
+#endif /* AUBIO_AUDIO_UNIT_H */
--- /dev/null
+/*
+ Copyright (C) 2016 Paul Brossier <piem@aubio.org>
+
+ This file is part of aubio.
+
+ aubio is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ aubio is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with aubio. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "aubio_priv.h"
+
+uint_t
+aubio_io_validate_samplerate(const char_t *kind, const char_t *path, uint_t samplerate)
+{
+ if ((sint_t)(samplerate) <= 0) {
+ AUBIO_ERR("%s: failed creating %s, samplerate should be positive, not %d\n",
+ kind, path, samplerate);
+ return AUBIO_FAIL;
+ }
+ if ((sint_t)samplerate > AUBIO_MAX_SAMPLERATE) {
+ AUBIO_ERR("%s: failed creating %s, samplerate %dHz is too large\n",
+ kind, path, samplerate);
+ return AUBIO_FAIL;
+ }
+ return AUBIO_OK;
+}
+
+uint_t
+aubio_io_validate_channels(const char_t *kind, const char_t *path, uint_t channels)
+{
+ if ((sint_t)(channels) <= 0) {
+ AUBIO_ERR("sink_%s: failed creating %s, channels should be positive, not %d\n",
+ kind, path, channels);
+ return AUBIO_FAIL;
+ }
+ if (channels > AUBIO_MAX_CHANNELS) {
+ AUBIO_ERR("sink_%s: failed creating %s, too many channels (%d but %d available)\n",
+ kind, path, channels, AUBIO_MAX_CHANNELS);
+ return AUBIO_FAIL;
+ }
+ return AUBIO_OK;
+}
--- /dev/null
+/*
+ Copyright (C) 2016 Paul Brossier <piem@aubio.org>
+
+ This file is part of aubio.
+
+ aubio is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ aubio is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with aubio. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef AUBIO_IOUTILS_H
+#define AUBIO_IOUTILS_H
+
+/** \file
+
+ Simple utility functions to validate input parameters.
+
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** validate samplerate
+
+ \param kind the object kind to report on
+ \param path the object properties to report on
+ \param samplerate the object properties to report on
+ \return 0 if ok, non-zero if validation failed
+
+ */
+uint_t aubio_io_validate_samplerate(const char_t *kind, const char_t *path,
+ uint_t samplerate);
+
+/** validate number of channels
+
+ \param kind the object kind to report on
+ \param path the object properties to report on
+ \param channels the object properties to report on
+ \return 0 if ok, non-zero if validation failed
+
+ */
+uint_t aubio_io_validate_channels(const char_t *kind, const char_t *path,
+ uint_t channels);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AUBIO_IOUTILS_H */
*/
-#include "config.h"
#include "aubio_priv.h"
#include "fvec.h"
#include "fmat.h"
del_aubio_sink_t s_del;
};
-aubio_sink_t * new_aubio_sink(char_t * uri, uint_t samplerate) {
+aubio_sink_t * new_aubio_sink(const char_t * uri, uint_t samplerate) {
aubio_sink_t * s = AUBIO_NEW(aubio_sink_t);
#ifdef HAVE_SINK_APPLE_AUDIO
s->sink = (void *)new_aubio_sink_apple_audio(uri, samplerate);
return s;
}
#endif /* HAVE_SINK_APPLE_AUDIO */
-#if HAVE_SNDFILE
+#ifdef HAVE_SNDFILE
s->sink = (void *)new_aubio_sink_sndfile(uri, samplerate);
if (s->sink) {
s->s_do = (aubio_sink_do_t)(aubio_sink_sndfile_do);
return s;
}
#endif /* HAVE_SNDFILE */
-#if HAVE_WAVWRITE
+#ifdef HAVE_WAVWRITE
s->sink = (void *)new_aubio_sink_wavwrite(uri, samplerate);
if (s->sink) {
s->s_do = (aubio_sink_do_t)(aubio_sink_wavwrite_do);
return s;
}
#endif /* HAVE_WAVWRITE */
- AUBIO_ERROR("sink: failed creating %s with samplerate %dHz\n",
- uri, samplerate);
+#if !defined(HAVE_WAVWRITE) && \
+ !defined(HAVE_SNDFILE) && \
+ !defined(HAVE_SINK_APPLE_AUDIO)
+ AUBIO_ERROR("sink: failed creating '%s' at %dHz (no sink built-in)\n", uri, samplerate);
+#endif
AUBIO_FREE(s);
return NULL;
}
return s->s_preset_channels((void *)s->sink, channels);
}
-uint_t aubio_sink_get_samplerate(aubio_sink_t * s) {
+uint_t aubio_sink_get_samplerate(const aubio_sink_t * s) {
return s->s_get_samplerate((void *)s->sink);
}
-uint_t aubio_sink_get_channels(aubio_sink_t * s) {
+uint_t aubio_sink_get_channels(const aubio_sink_t * s) {
return s->s_get_channels((void *)s->sink);
}
*/
-#ifndef _AUBIO_SINK_H
-#define _AUBIO_SINK_H
+#ifndef AUBIO_SINK_H
+#define AUBIO_SINK_H
/** \file
been called.
*/
-aubio_sink_t * new_aubio_sink(char_t * uri, uint_t samplerate);
+aubio_sink_t * new_aubio_sink(const char_t * uri, uint_t samplerate);
/**
\return samplerate, in Hz
*/
-uint_t aubio_sink_get_samplerate(aubio_sink_t *s);
+uint_t aubio_sink_get_samplerate(const aubio_sink_t *s);
/**
\return number of channels
*/
-uint_t aubio_sink_get_channels(aubio_sink_t *s);
+uint_t aubio_sink_get_channels(const aubio_sink_t *s);
/**
}
#endif
-#endif /* _AUBIO_SINK_H */
+#endif /* AUBIO_SINK_H */
*/
-#include "config.h"
+#include "aubio_priv.h"
#ifdef HAVE_SINK_APPLE_AUDIO
-
-#include "aubio_priv.h"
#include "fvec.h"
#include "fmat.h"
#include "io/sink_apple_audio.h"
+#include "io/ioutils.h"
// CFURLRef, CFURLCreateWithFileSystemPath, ...
#include <CoreFoundation/CoreFoundation.h>
#define MAX_SIZE 4096 // the maximum number of frames that can be written at a time
+void aubio_sink_apple_audio_write(aubio_sink_apple_audio_t *s, uint_t write);
+
struct _aubio_sink_apple_audio_t {
uint_t samplerate;
uint_t channels;
bool async;
};
-aubio_sink_apple_audio_t * new_aubio_sink_apple_audio(char_t * uri, uint_t samplerate) {
+aubio_sink_apple_audio_t * new_aubio_sink_apple_audio(const char_t * uri, uint_t samplerate) {
aubio_sink_apple_audio_t * s = AUBIO_NEW(aubio_sink_apple_audio_t);
- s->path = uri;
s->max_frames = MAX_SIZE;
- s->async = true;
+ s->async = false;
- if (uri == NULL) {
+ if ( (uri == NULL) || (strlen(uri) < 1) ) {
AUBIO_ERROR("sink_apple_audio: Aborted opening null path\n");
goto beach;
}
+ if (s->path != NULL) AUBIO_FREE(s->path);
+ s->path = AUBIO_ARRAY(char_t, strnlen(uri, PATH_MAX) + 1);
+ strncpy(s->path, uri, strnlen(uri, PATH_MAX) + 1);
s->samplerate = 0;
s->channels = 0;
- // negative samplerate given, abort
- if ((sint_t)samplerate < 0) goto beach;
// zero samplerate given. do not open yet
- if ((sint_t)samplerate == 0) return s;
+ if ((sint_t)samplerate == 0) {
+ return s;
+ }
+ // invalid samplerate given, abort
+ if (aubio_io_validate_samplerate("sink_apple_audio", s->path, samplerate)) {
+ goto beach;
+ }
s->samplerate = samplerate;
s->channels = 1;
uint_t aubio_sink_apple_audio_preset_samplerate(aubio_sink_apple_audio_t *s, uint_t samplerate)
{
- if ((sint_t)(samplerate) <= 0) return AUBIO_FAIL;
+ if (aubio_io_validate_samplerate("sink_apple_audio", s->path, samplerate)) {
+ return AUBIO_FAIL;
+ }
s->samplerate = samplerate;
// automatically open when both samplerate and channels have been set
if (s->samplerate != 0 && s->channels != 0) {
uint_t aubio_sink_apple_audio_preset_channels(aubio_sink_apple_audio_t *s, uint_t channels)
{
- if ((sint_t)(channels) <= 0) return AUBIO_FAIL;
+ if (aubio_io_validate_channels("sink_apple_audio", s->path, channels)) {
+ return AUBIO_FAIL;
+ }
s->channels = channels;
// automatically open when both samplerate and channels have been set
if (s->samplerate != 0 && s->channels != 0) {
return AUBIO_OK;
}
-uint_t aubio_sink_apple_audio_get_samplerate(aubio_sink_apple_audio_t *s)
+uint_t aubio_sink_apple_audio_get_samplerate(const aubio_sink_apple_audio_t *s)
{
return s->samplerate;
}
-uint_t aubio_sink_apple_audio_get_channels(aubio_sink_apple_audio_t *s)
+uint_t aubio_sink_apple_audio_get_channels(const aubio_sink_apple_audio_t *s)
{
return s->channels;
}
}
void aubio_sink_apple_audio_do(aubio_sink_apple_audio_t * s, fvec_t * write_data, uint_t write) {
- OSStatus err = noErr;
UInt32 c, v;
short *data = (short*)s->bufferList.mBuffers[0].mData;
if (write > s->max_frames) {
}
}
}
- if (s->async) {
- err = ExtAudioFileWriteAsync(s->audioFile, write, &s->bufferList);
-
- if (err) {
- char_t errorstr[20];
- AUBIO_ERROR("sink_apple_audio: error while writing %s "
- "in ExtAudioFileWriteAsync (%s), switching to sync\n", s->path,
- getPrintableOSStatusError(errorstr, err));
- s->async = false;
- } else {
- return;
- }
-
- } else {
- err = ExtAudioFileWrite(s->audioFile, write, &s->bufferList);
-
- if (err) {
- char_t errorstr[20];
- AUBIO_ERROR("sink_apple_audio: error while writing %s "
- "in ExtAudioFileWrite (%s)\n", s->path,
- getPrintableOSStatusError(errorstr, err));
- }
- }
- return;
+ aubio_sink_apple_audio_write(s, write);
}
void aubio_sink_apple_audio_do_multi(aubio_sink_apple_audio_t * s, fmat_t * write_data, uint_t write) {
- OSStatus err = noErr;
UInt32 c, v;
short *data = (short*)s->bufferList.mBuffers[0].mData;
if (write > s->max_frames) {
}
}
}
+ aubio_sink_apple_audio_write(s, write);
+}
+
+void aubio_sink_apple_audio_write(aubio_sink_apple_audio_t *s, uint_t write) {
+ OSStatus err = noErr;
if (s->async) {
err = ExtAudioFileWriteAsync(s->audioFile, write, &s->bufferList);
-
if (err) {
char_t errorstr[20];
+ if (err == kExtAudioFileError_AsyncWriteBufferOverflow) {
+ sprintf(errorstr,"buffer overflow");
+ } else if (err == kExtAudioFileError_AsyncWriteTooLarge) {
+ sprintf(errorstr,"write too large");
+ } else {
+ // unknown error
+ getPrintableOSStatusError(errorstr, err);
+ }
AUBIO_ERROR("sink_apple_audio: error while writing %s "
- "in ExtAudioFileWriteAsync (%s), switching to sync\n", s->path,
- getPrintableOSStatusError(errorstr, err));
- s->async = false;
- } else {
- return;
+ "in ExtAudioFileWriteAsync (%s)\n", s->path, errorstr);
}
-
} else {
err = ExtAudioFileWrite(s->audioFile, write, &s->bufferList);
-
if (err) {
char_t errorstr[20];
AUBIO_ERROR("sink_apple_audio: error while writing %s "
getPrintableOSStatusError(errorstr, err));
}
}
- return;
}
uint_t aubio_sink_apple_audio_close(aubio_sink_apple_audio_t * s) {
void del_aubio_sink_apple_audio(aubio_sink_apple_audio_t * s) {
if (s->audioFile) aubio_sink_apple_audio_close (s);
+ if (s->path) AUBIO_FREE(s->path);
freeAudioBufferList(&s->bufferList);
AUBIO_FREE(s);
return;
*/
-#ifndef _AUBIO_SINK_APPLE_AUDIO_H
-#define _AUBIO_SINK_APPLE_AUDIO_H
+#ifndef AUBIO_SINK_APPLE_AUDIO_H
+#define AUBIO_SINK_APPLE_AUDIO_H
/** \file
been called.
*/
-aubio_sink_apple_audio_t * new_aubio_sink_apple_audio(char_t * uri, uint_t samplerate);
+aubio_sink_apple_audio_t * new_aubio_sink_apple_audio(const char_t * uri, uint_t samplerate);
/**
\return samplerate, in Hz
*/
-uint_t aubio_sink_apple_audio_get_samplerate(aubio_sink_apple_audio_t *s);
+uint_t aubio_sink_apple_audio_get_samplerate(const aubio_sink_apple_audio_t *s);
/**
\return number of channels
*/
-uint_t aubio_sink_apple_audio_get_channels(aubio_sink_apple_audio_t *s);
+uint_t aubio_sink_apple_audio_get_channels(const aubio_sink_apple_audio_t *s);
/**
}
#endif
-#endif /* _AUBIO_SINK_APPLE_AUDIO_H */
+#endif /* AUBIO_SINK_APPLE_AUDIO_H */
*/
-#include "config.h"
+#include "aubio_priv.h"
#ifdef HAVE_SNDFILE
#include <sndfile.h>
-#include "aubio_priv.h"
#include "fvec.h"
#include "fmat.h"
#include "io/sink_sndfile.h"
+#include "io/ioutils.h"
-#define MAX_CHANNELS 6
#define MAX_SIZE 4096
#if !HAVE_AUBIO_DOUBLE
uint_t aubio_sink_sndfile_open(aubio_sink_sndfile_t *s);
-aubio_sink_sndfile_t * new_aubio_sink_sndfile(char_t * path, uint_t samplerate) {
+aubio_sink_sndfile_t * new_aubio_sink_sndfile(const char_t * path, uint_t samplerate) {
aubio_sink_sndfile_t * s = AUBIO_NEW(aubio_sink_sndfile_t);
s->max_size = MAX_SIZE;
- s->path = path;
if (path == NULL) {
AUBIO_ERR("sink_sndfile: Aborted opening null path\n");
return NULL;
}
+ if (s->path) AUBIO_FREE(s->path);
+ s->path = AUBIO_ARRAY(char_t, strnlen(path, PATH_MAX) + 1);
+ strncpy(s->path, path, strnlen(path, PATH_MAX) + 1);
+
s->samplerate = 0;
s->channels = 0;
- // negative samplerate given, abort
- if ((sint_t)samplerate < 0) goto beach;
// zero samplerate given. do not open yet
- if ((sint_t)samplerate == 0) return s;
+ if ((sint_t)samplerate == 0) {
+ return s;
+ }
+ // invalid samplerate given, abort
+ if (aubio_io_validate_samplerate("sink_sndfile", s->path, samplerate)) {
+ goto beach;
+ }
s->samplerate = samplerate;
s->channels = 1;
uint_t aubio_sink_sndfile_preset_samplerate(aubio_sink_sndfile_t *s, uint_t samplerate)
{
- if ((sint_t)(samplerate) <= 0) return AUBIO_FAIL;
+ if (aubio_io_validate_samplerate("sink_sndfile", s->path, samplerate)) {
+ return AUBIO_FAIL;
+ }
s->samplerate = samplerate;
// automatically open when both samplerate and channels have been set
if (s->samplerate != 0 && s->channels != 0) {
uint_t aubio_sink_sndfile_preset_channels(aubio_sink_sndfile_t *s, uint_t channels)
{
- if ((sint_t)(channels) <= 0) return AUBIO_FAIL;
+ if (aubio_io_validate_channels("sink_sndfile", s->path, channels)) {
+ return AUBIO_FAIL;
+ }
s->channels = channels;
// automatically open when both samplerate and channels have been set
if (s->samplerate != 0 && s->channels != 0) {
return AUBIO_OK;
}
-uint_t aubio_sink_sndfile_get_samplerate(aubio_sink_sndfile_t *s)
+uint_t aubio_sink_sndfile_get_samplerate(const aubio_sink_sndfile_t *s)
{
return s->samplerate;
}
-uint_t aubio_sink_sndfile_get_channels(aubio_sink_sndfile_t *s)
+uint_t aubio_sink_sndfile_get_channels(const aubio_sink_sndfile_t *s)
{
return s->channels;
}
if (s->handle == NULL) {
/* show libsndfile err msg */
- AUBIO_ERR("sink_sndfile: Failed opening %s. %s\n", s->path, sf_strerror (NULL));
+ AUBIO_ERR("sink_sndfile: Failed opening \"%s\" with %d channels, %dHz: %s\n",
+ s->path, s->channels, s->samplerate, sf_strerror (NULL));
return AUBIO_FAIL;
}
s->scratch_size = s->max_size*s->channels;
/* allocate data for de/interleaving reallocated when needed. */
- if (s->scratch_size >= MAX_SIZE * MAX_CHANNELS) {
+ if (s->scratch_size >= MAX_SIZE * AUBIO_MAX_CHANNELS) {
+ abort();
AUBIO_ERR("sink_sndfile: %d x %d exceeds maximum aubio_sink_sndfile buffer size %d\n",
- s->max_size, s->channels, MAX_CHANNELS * MAX_CHANNELS);
+ s->max_size, s->channels, MAX_SIZE * AUBIO_MAX_CHANNELS);
return AUBIO_FAIL;
}
s->scratch_data = AUBIO_ARRAY(smpl_t,s->scratch_size);
void del_aubio_sink_sndfile(aubio_sink_sndfile_t * s){
if (!s) return;
+ if (s->path) AUBIO_FREE(s->path);
aubio_sink_sndfile_close(s);
AUBIO_FREE(s->scratch_data);
AUBIO_FREE(s);
*/
-#ifndef _AUBIO_SINK_SNDFILE_H
-#define _AUBIO_SINK_SNDFILE_H
+#ifndef AUBIO_SINK_SNDFILE_H
+#define AUBIO_SINK_SNDFILE_H
/** \file
been called.
*/
-aubio_sink_sndfile_t * new_aubio_sink_sndfile(char_t * uri, uint_t samplerate);
+aubio_sink_sndfile_t * new_aubio_sink_sndfile(const char_t * uri, uint_t samplerate);
/**
\return samplerate, in Hz
*/
-uint_t aubio_sink_sndfile_get_samplerate(aubio_sink_sndfile_t *s);
+uint_t aubio_sink_sndfile_get_samplerate(const aubio_sink_sndfile_t *s);
/**
\return number of channels
*/
-uint_t aubio_sink_sndfile_get_channels(aubio_sink_sndfile_t *s);
+uint_t aubio_sink_sndfile_get_channels(const aubio_sink_sndfile_t *s);
/**
}
#endif
-#endif /* _AUBIO_SINK_SNDFILE_H */
+#endif /* AUBIO_SINK_SNDFILE_H */
*/
-#include "config.h"
+#include "aubio_priv.h"
#ifdef HAVE_WAVWRITE
-#include "aubio_priv.h"
#include "fvec.h"
#include "fmat.h"
#include "io/sink_wavwrite.h"
+#include "io/ioutils.h"
#include <errno.h>
-#define MAX_CHANNELS 6
#define MAX_SIZE 4096
#define FLOAT_TO_SHORT(x) (short)(x * 32768)
unsigned short *scratch_data;
};
-unsigned char *write_little_endian (unsigned int s, unsigned char *str, unsigned int length);
-unsigned char *write_little_endian (unsigned int s, unsigned char *str, unsigned int length) {
+static unsigned char *write_little_endian (unsigned int s, unsigned char *str,
+ unsigned int length);
+
+static unsigned char *write_little_endian (unsigned int s, unsigned char *str,
+ unsigned int length)
+{
uint_t i;
for (i = 0; i < length; i++) {
str[i] = s >> (i * 8);
return str;
}
-aubio_sink_wavwrite_t * new_aubio_sink_wavwrite(char_t * path, uint_t samplerate) {
+aubio_sink_wavwrite_t * new_aubio_sink_wavwrite(const char_t * path, uint_t samplerate) {
aubio_sink_wavwrite_t * s = AUBIO_NEW(aubio_sink_wavwrite_t);
if (path == NULL) {
goto beach;
}
- s->path = path;
+ if (s->path) AUBIO_FREE(s->path);
+ s->path = AUBIO_ARRAY(char_t, strnlen(path, PATH_MAX) + 1);
+ strncpy(s->path, path, strnlen(path, PATH_MAX) + 1);
+
s->max_size = MAX_SIZE;
s->bitspersample = 16;
s->total_frames_written = 0;
s->samplerate = 0;
s->channels = 0;
- // negative samplerate given, abort
- if ((sint_t)samplerate < 0) goto beach;
// zero samplerate given. do not open yet
- if ((sint_t)samplerate == 0) return s;
- // samplerate way too large, fail
- if ((sint_t)samplerate > 192000 * 4) goto beach;
+ if ((sint_t)samplerate == 0) {
+ return s;
+ }
+ // invalid samplerate given, abort
+ if (aubio_io_validate_samplerate("sink_wavwrite", s->path, samplerate)) {
+ goto beach;
+ }
s->samplerate = samplerate;
s->channels = 1;
uint_t aubio_sink_wavwrite_preset_samplerate(aubio_sink_wavwrite_t *s, uint_t samplerate)
{
- if ((sint_t)(samplerate) <= 0) return AUBIO_FAIL;
+ if (aubio_io_validate_samplerate("sink_wavwrite", s->path, samplerate)) {
+ return AUBIO_FAIL;
+ }
s->samplerate = samplerate;
// automatically open when both samplerate and channels have been set
if (s->samplerate != 0 && s->channels != 0) {
uint_t aubio_sink_wavwrite_preset_channels(aubio_sink_wavwrite_t *s, uint_t channels)
{
- if ((sint_t)(channels) <= 0) return AUBIO_FAIL;
+ if (aubio_io_validate_channels("sink_wavwrite", s->path, channels)) {
+ return AUBIO_FAIL;
+ }
s->channels = channels;
// automatically open when both samplerate and channels have been set
if (s->samplerate != 0 && s->channels != 0) {
return AUBIO_OK;
}
-uint_t aubio_sink_wavwrite_get_samplerate(aubio_sink_wavwrite_t *s)
+uint_t aubio_sink_wavwrite_get_samplerate(const aubio_sink_wavwrite_t *s)
{
return s->samplerate;
}
-uint_t aubio_sink_wavwrite_get_channels(aubio_sink_wavwrite_t *s)
+uint_t aubio_sink_wavwrite_get_channels(const aubio_sink_wavwrite_t *s)
{
return s->channels;
}
s->scratch_size = s->max_size * s->channels;
/* allocate data for de/interleaving reallocated when needed. */
- if (s->scratch_size >= MAX_SIZE * MAX_CHANNELS) {
+ if (s->scratch_size >= MAX_SIZE * AUBIO_MAX_CHANNELS) {
AUBIO_ERR("sink_wavwrite: %d x %d exceeds SIZE maximum buffer size %d\n",
- s->max_size, s->channels, MAX_SIZE * MAX_CHANNELS);
+ s->max_size, s->channels, MAX_SIZE * AUBIO_MAX_CHANNELS);
goto beach;
}
s->scratch_data = AUBIO_ARRAY(unsigned short,s->scratch_size);
void del_aubio_sink_wavwrite(aubio_sink_wavwrite_t * s){
if (!s) return;
aubio_sink_wavwrite_close(s);
+ if (s->path) AUBIO_FREE(s->path);
AUBIO_FREE(s->scratch_data);
AUBIO_FREE(s);
}
*/
-#ifndef _AUBIO_SINK_WAVWRITE_H
-#define _AUBIO_SINK_WAVWRITE_H
+#ifndef AUBIO_SINK_WAVWRITE_H
+#define AUBIO_SINK_WAVWRITE_H
/** \file
been called.
*/
-aubio_sink_wavwrite_t * new_aubio_sink_wavwrite(char_t * uri, uint_t samplerate);
+aubio_sink_wavwrite_t * new_aubio_sink_wavwrite(const char_t * uri, uint_t samplerate);
/**
\return samplerate, in Hz
*/
-uint_t aubio_sink_wavwrite_get_samplerate(aubio_sink_wavwrite_t *s);
+uint_t aubio_sink_wavwrite_get_samplerate(const aubio_sink_wavwrite_t *s);
/**
\return number of channels
*/
-uint_t aubio_sink_wavwrite_get_channels(aubio_sink_wavwrite_t *s);
+uint_t aubio_sink_wavwrite_get_channels(const aubio_sink_wavwrite_t *s);
/**
}
#endif
-#endif /* _AUBIO_SINK_WAVWRITE_H */
+#endif /* AUBIO_SINK_WAVWRITE_H */
*/
-#include "config.h"
#include "aubio_priv.h"
#include "fvec.h"
#include "fmat.h"
typedef void (*aubio_source_do_multi_t)(aubio_source_t * s, fmat_t * data, uint_t * read);
typedef uint_t (*aubio_source_get_samplerate_t)(aubio_source_t * s);
typedef uint_t (*aubio_source_get_channels_t)(aubio_source_t * s);
+typedef uint_t (*aubio_source_get_duration_t)(aubio_source_t * s);
typedef uint_t (*aubio_source_seek_t)(aubio_source_t * s, uint_t seek);
typedef uint_t (*aubio_source_close_t)(aubio_source_t * s);
typedef void (*del_aubio_source_t)(aubio_source_t * s);
aubio_source_do_multi_t s_do_multi;
aubio_source_get_samplerate_t s_get_samplerate;
aubio_source_get_channels_t s_get_channels;
+ aubio_source_get_duration_t s_get_duration;
aubio_source_seek_t s_seek;
aubio_source_close_t s_close;
del_aubio_source_t s_del;
};
-aubio_source_t * new_aubio_source(char_t * uri, uint_t samplerate, uint_t hop_size) {
+aubio_source_t * new_aubio_source(const char_t * uri, uint_t samplerate, uint_t hop_size) {
aubio_source_t * s = AUBIO_NEW(aubio_source_t);
-#if HAVE_LIBAV
+#ifdef HAVE_LIBAV
s->source = (void *)new_aubio_source_avcodec(uri, samplerate, hop_size);
if (s->source) {
s->s_do = (aubio_source_do_t)(aubio_source_avcodec_do);
s->s_do_multi = (aubio_source_do_multi_t)(aubio_source_avcodec_do_multi);
s->s_get_channels = (aubio_source_get_channels_t)(aubio_source_avcodec_get_channels);
s->s_get_samplerate = (aubio_source_get_samplerate_t)(aubio_source_avcodec_get_samplerate);
+ s->s_get_duration = (aubio_source_get_duration_t)(aubio_source_avcodec_get_duration);
s->s_seek = (aubio_source_seek_t)(aubio_source_avcodec_seek);
s->s_close = (aubio_source_close_t)(aubio_source_avcodec_close);
s->s_del = (del_aubio_source_t)(del_aubio_source_avcodec);
s->s_do_multi = (aubio_source_do_multi_t)(aubio_source_apple_audio_do_multi);
s->s_get_channels = (aubio_source_get_channels_t)(aubio_source_apple_audio_get_channels);
s->s_get_samplerate = (aubio_source_get_samplerate_t)(aubio_source_apple_audio_get_samplerate);
+ s->s_get_duration = (aubio_source_get_duration_t)(aubio_source_apple_audio_get_duration);
s->s_seek = (aubio_source_seek_t)(aubio_source_apple_audio_seek);
s->s_close = (aubio_source_close_t)(aubio_source_apple_audio_close);
s->s_del = (del_aubio_source_t)(del_aubio_source_apple_audio);
return s;
}
#endif /* HAVE_SOURCE_APPLE_AUDIO */
-#if HAVE_SNDFILE
+#ifdef HAVE_SNDFILE
s->source = (void *)new_aubio_source_sndfile(uri, samplerate, hop_size);
if (s->source) {
s->s_do = (aubio_source_do_t)(aubio_source_sndfile_do);
s->s_do_multi = (aubio_source_do_multi_t)(aubio_source_sndfile_do_multi);
s->s_get_channels = (aubio_source_get_channels_t)(aubio_source_sndfile_get_channels);
s->s_get_samplerate = (aubio_source_get_samplerate_t)(aubio_source_sndfile_get_samplerate);
+ s->s_get_duration = (aubio_source_get_duration_t)(aubio_source_sndfile_get_duration);
s->s_seek = (aubio_source_seek_t)(aubio_source_sndfile_seek);
s->s_close = (aubio_source_close_t)(aubio_source_sndfile_close);
s->s_del = (del_aubio_source_t)(del_aubio_source_sndfile);
return s;
}
#endif /* HAVE_SNDFILE */
-#if HAVE_WAVREAD
+#ifdef HAVE_WAVREAD
s->source = (void *)new_aubio_source_wavread(uri, samplerate, hop_size);
if (s->source) {
s->s_do = (aubio_source_do_t)(aubio_source_wavread_do);
s->s_do_multi = (aubio_source_do_multi_t)(aubio_source_wavread_do_multi);
s->s_get_channels = (aubio_source_get_channels_t)(aubio_source_wavread_get_channels);
s->s_get_samplerate = (aubio_source_get_samplerate_t)(aubio_source_wavread_get_samplerate);
+ s->s_get_duration = (aubio_source_get_duration_t)(aubio_source_wavread_get_duration);
s->s_seek = (aubio_source_seek_t)(aubio_source_wavread_seek);
s->s_close = (aubio_source_close_t)(aubio_source_wavread_close);
s->s_del = (del_aubio_source_t)(del_aubio_source_wavread);
return s;
}
#endif /* HAVE_WAVREAD */
- AUBIO_ERROR("source: failed creating aubio source with %s"
- " at samplerate %d with hop_size %d\n", uri, samplerate, hop_size);
+#if !defined(HAVE_WAVREAD) && \
+ !defined(HAVE_LIBAV) && \
+ !defined(HAVE_SOURCE_APPLE_AUDIO) && \
+ !defined(HAVE_SNDFILE)
+ AUBIO_ERROR("source: failed creating with %s at %dHz with hop size %d"
+ " (no source built-in)\n", uri, samplerate, hop_size);
+#endif
AUBIO_FREE(s);
return NULL;
}
return s->s_get_channels((void *)s->source);
}
+uint_t aubio_source_get_duration(aubio_source_t *s) {
+ return s->s_get_duration((void *)s->source);
+}
+
uint_t aubio_source_seek (aubio_source_t * s, uint_t seek ) {
return s->s_seek((void *)s->source, seek);
}
*/
-#ifndef _AUBIO_SOURCE_H
-#define _AUBIO_SOURCE_H
+#ifndef AUBIO_SOURCE_H
+#define AUBIO_SOURCE_H
/** \file
::aubio_source_get_samplerate.
*/
-aubio_source_t * new_aubio_source(char_t * uri, uint_t samplerate, uint_t hop_size);
+aubio_source_t * new_aubio_source(const char_t * uri, uint_t samplerate, uint_t hop_size);
/**
/**
+ get the duration of source object, in frames
+
+ \param s source object, created with ::new_aubio_source
+ \return number of frames in file
+
+*/
+uint_t aubio_source_get_duration (aubio_source_t * s);
+
+/**
+
close source object
\param s source object, created with ::new_aubio_source
}
#endif
-#endif /* _AUBIO_SOURCE_H */
+#endif /* AUBIO_SOURCE_H */
*/
-#include "config.h"
+#include "aubio_priv.h"
#ifdef HAVE_SOURCE_APPLE_AUDIO
-#include "aubio_priv.h"
#include "fvec.h"
#include "fmat.h"
#include "io/source_apple_audio.h"
extern CFURLRef createURLFromPath(const char * path);
char_t *getPrintableOSStatusError(char_t *str, OSStatus error);
-uint_t aubio_source_apple_audio_open (aubio_source_apple_audio_t *s, char_t * path);
+uint_t aubio_source_apple_audio_open (aubio_source_apple_audio_t *s, const char_t * path);
-aubio_source_apple_audio_t * new_aubio_source_apple_audio(char_t * path, uint_t samplerate, uint_t block_size)
+aubio_source_apple_audio_t * new_aubio_source_apple_audio(const char_t * path, uint_t samplerate, uint_t block_size)
{
aubio_source_apple_audio_t * s = AUBIO_NEW(aubio_source_apple_audio_t);
s->block_size = block_size;
s->samplerate = samplerate;
- s->path = path;
if ( aubio_source_apple_audio_open ( s, path ) ) {
goto beach;
return NULL;
}
-uint_t aubio_source_apple_audio_open (aubio_source_apple_audio_t *s, char_t * path)
+uint_t aubio_source_apple_audio_open (aubio_source_apple_audio_t *s, const char_t * path)
{
OSStatus err = noErr;
UInt32 propSize;
- s->path = path;
+
+ if (s->path) AUBIO_FREE(s->path);
+ s->path = AUBIO_ARRAY(char_t, strnlen(path, PATH_MAX) + 1);
+ strncpy(s->path, path, strnlen(path, PATH_MAX) + 1);
// open the resource url
- CFURLRef fileURL = createURLFromPath(path);
+ CFURLRef fileURL = createURLFromPath(s->path);
err = ExtAudioFileOpenURL(fileURL, &s->audioFile);
CFRelease(fileURL);
if (err == -43) {
uint_t aubio_source_apple_audio_close (aubio_source_apple_audio_t *s)
{
OSStatus err = noErr;
- if (!s->audioFile) { return AUBIO_FAIL; }
+ if (!s->audioFile) { return AUBIO_OK; }
err = ExtAudioFileDispose(s->audioFile);
s->audioFile = NULL;
if (err) {
void del_aubio_source_apple_audio(aubio_source_apple_audio_t * s){
aubio_source_apple_audio_close (s);
+ if (s->path) AUBIO_FREE(s->path);
freeAudioBufferList(&s->bufferList);
AUBIO_FREE(s);
return;
goto beach;
}
// check if we are not seeking out of the file
- SInt64 fileLengthFrames = 0;
- UInt32 propSize = sizeof(fileLengthFrames);
- ExtAudioFileGetProperty(s->audioFile,
- kExtAudioFileProperty_FileLengthFrames, &propSize, &fileLengthFrames);
+ uint_t fileLengthFrames = aubio_source_apple_audio_get_duration(s);
// compute position in the source file, before resampling
smpl_t ratio = s->source_samplerate * 1. / s->samplerate;
SInt64 resampled_pos = (SInt64)ROUND( pos * ratio );
return err;
}
-uint_t aubio_source_apple_audio_get_samplerate(aubio_source_apple_audio_t * s) {
+uint_t aubio_source_apple_audio_get_samplerate(const aubio_source_apple_audio_t * s) {
return s->samplerate;
}
-uint_t aubio_source_apple_audio_get_channels(aubio_source_apple_audio_t * s) {
+uint_t aubio_source_apple_audio_get_channels(const aubio_source_apple_audio_t * s) {
return s->channels;
}
+uint_t aubio_source_apple_audio_get_duration(const aubio_source_apple_audio_t * s) {
+ SInt64 fileLengthFrames = 0;
+ UInt32 propSize = sizeof(fileLengthFrames);
+ OSStatus err = ExtAudioFileGetProperty(s->audioFile,
+ kExtAudioFileProperty_FileLengthFrames, &propSize, &fileLengthFrames);
+ if (err) {
+ char_t errorstr[20];
+ AUBIO_ERROR("source_apple_audio: Failed getting %s duration, "
+ "error in ExtAudioFileGetProperty (%s)\n", s->path,
+ getPrintableOSStatusError(errorstr, err));
+ return err;
+ }
+ return (uint_t)fileLengthFrames;
+}
+
#endif /* HAVE_SOURCE_APPLE_AUDIO */
*/
-#ifndef _AUBIO_SOURCE_APPLE_AUDIO_H
-#define _AUBIO_SOURCE_APPLE_AUDIO_H
+#ifndef AUBIO_SOURCE_APPLE_AUDIO_H
+#define AUBIO_SOURCE_APPLE_AUDIO_H
/** \file
::aubio_source_apple_audio_get_samplerate.
*/
-aubio_source_apple_audio_t * new_aubio_source_apple_audio(char_t * uri, uint_t samplerate, uint_t hop_size);
+aubio_source_apple_audio_t * new_aubio_source_apple_audio(const char_t * uri, uint_t samplerate, uint_t hop_size);
/**
\return samplerate, in Hz
*/
-uint_t aubio_source_apple_audio_get_samplerate(aubio_source_apple_audio_t * s);
+uint_t aubio_source_apple_audio_get_samplerate(const aubio_source_apple_audio_t * s);
/**
\return number of channels
*/
-uint_t aubio_source_apple_audio_get_channels(aubio_source_apple_audio_t * s);
+uint_t aubio_source_apple_audio_get_channels(const aubio_source_apple_audio_t * s);
+
+/**
+
+ get the duration of source object, in frames
+
+ \param s source object, created with ::new_aubio_source_apple_audio
+ \return number of frames in file
+
+*/
+uint_t aubio_source_apple_audio_get_duration(const aubio_source_apple_audio_t * s);
/**
}
#endif
-#endif /* _AUBIO_SOURCE_APPLE_AUDIO_H */
+#endif /* AUBIO_SOURCE_APPLE_AUDIO_H */
*/
-
-#include "config.h"
+#include "aubio_priv.h"
#ifdef HAVE_LIBAV
-// determine whether we use libavformat from ffmpe or libav
-#define FFMPEG_LIBAVFORMAT (LIBAVFORMAT_VERSION_MICRO > 99)
-
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavresample/avresample.h>
#include <libavutil/opt.h>
#include <stdlib.h>
+// determine whether we use libavformat from ffmpeg or from libav
+#define FFMPEG_LIBAVFORMAT (LIBAVFORMAT_VERSION_MICRO > 99 )
+// max_analyze_duration2 was used from ffmpeg libavformat 55.43.100 through 57.2.100
+#define FFMPEG_LIBAVFORMAT_MAX_DUR2 FFMPEG_LIBAVFORMAT && ( \
+ (LIBAVFORMAT_VERSION_MAJOR == 55 && LIBAVFORMAT_VERSION_MINOR >= 43) \
+ || (LIBAVFORMAT_VERSION_MAJOR == 56) \
+ || (LIBAVFORMAT_VERSION_MAJOR == 57 && LIBAVFORMAT_VERSION_MINOR < 2) \
+ )
+
+// backward compatibility with libavcodec55
+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,28,1)
+#warning "libavcodec55 is deprecated"
+#define HAVE_AUBIO_LIBAVCODEC_DEPRECATED 1
+#define av_frame_alloc avcodec_alloc_frame
+#define av_frame_free avcodec_free_frame
+#define av_packet_unref av_free_packet
+#endif
+
#include "aubio_priv.h"
#include "fvec.h"
#include "fmat.h"
AVFormatContext *avFormatCtx;
AVCodecContext *avCodecCtx;
AVFrame *avFrame;
+ AVPacket avPacket;
AVAudioResampleContext *avr;
- float *output;
+ smpl_t *output;
uint_t read_samples;
uint_t read_index;
sint_t selected_stream;
void aubio_source_avcodec_reset_resampler(aubio_source_avcodec_t * s, uint_t multi);
void aubio_source_avcodec_readframe(aubio_source_avcodec_t *s, uint_t * read_samples);
-aubio_source_avcodec_t * new_aubio_source_avcodec(char_t * path, uint_t samplerate, uint_t hop_size) {
+uint_t aubio_source_avcodec_has_network_url(aubio_source_avcodec_t *s);
+
+uint_t aubio_source_avcodec_has_network_url(aubio_source_avcodec_t *s) {
+ char proto[20], authorization[256], hostname[128], uripath[256];
+ int proto_size = 20, authorization_size = 256, hostname_size = 128,
+ *port_ptr = 0, path_size = 256;
+ av_url_split(proto, proto_size, authorization, authorization_size, hostname,
+ hostname_size, port_ptr, uripath, path_size, s->path);
+ if (strlen(proto)) {
+ return 1;
+ }
+ return 0;
+}
+
+
+aubio_source_avcodec_t * new_aubio_source_avcodec(const char_t * path, uint_t samplerate, uint_t hop_size) {
aubio_source_avcodec_t * s = AUBIO_NEW(aubio_source_avcodec_t);
int err;
if (path == NULL) {
s->hop_size = hop_size;
s->channels = 1;
- s->path = path;
+
+ if (s->path) AUBIO_FREE(s->path);
+ s->path = AUBIO_ARRAY(char_t, strnlen(path, PATH_MAX) + 1);
+ strncpy(s->path, path, strnlen(path, PATH_MAX) + 1);
// register all formats and codecs
av_register_all();
- // if path[0] != '/'
- //avformat_network_init();
+ if (aubio_source_avcodec_has_network_url(s)) {
+ avformat_network_init();
+ }
// try opening the file and get some info about it
AVFormatContext *avFormatCtx = s->avFormatCtx;
}
// try to make sure max_analyze_duration is big enough for most songs
-#if FFMPEG_LIBAVFORMAT
+#if FFMPEG_LIBAVFORMAT_MAX_DUR2
avFormatCtx->max_analyze_duration2 *= 100;
#else
avFormatCtx->max_analyze_duration *= 100;
uint_t i;
sint_t selected_stream = -1;
for (i = 0; i < avFormatCtx->nb_streams; i++) {
+#if FF_API_LAVF_AVCTX
+ if (avFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
+#else
if (avFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+#endif
if (selected_stream == -1) {
selected_stream = i;
} else {
s->selected_stream = selected_stream;
AVCodecContext *avCodecCtx = s->avCodecCtx;
+#if FF_API_LAVF_AVCTX
+ AVCodecParameters *codecpar = avFormatCtx->streams[selected_stream]->codecpar;
+ if (codecpar == NULL) {
+ AUBIO_ERR("source_avcodec: Could not find decoder for %s", s->path);
+ goto beach;
+ }
+ AVCodec *codec = avcodec_find_decoder(codecpar->codec_id);
+
+ /* Allocate a codec context for the decoder */
+ avCodecCtx = avcodec_alloc_context3(codec);
+ if (!avCodecCtx) {
+ AUBIO_ERR("source_avcodec: Failed to allocate the %s codec context for path %s\n",
+ av_get_media_type_string(AVMEDIA_TYPE_AUDIO), s->path);
+ goto beach;
+ }
+#else
avCodecCtx = avFormatCtx->streams[selected_stream]->codec;
AVCodec *codec = avcodec_find_decoder(avCodecCtx->codec_id);
+#endif
if (codec == NULL) {
AUBIO_ERR("source_avcodec: Could not find decoder for %s", s->path);
goto beach;
}
+#if FF_API_LAVF_AVCTX
+ /* Copy codec parameters from input stream to output codec context */
+ if ((err = avcodec_parameters_to_context(avCodecCtx, codecpar)) < 0) {
+ AUBIO_ERR("source_avcodec: Failed to copy %s codec parameters to decoder context for %s\n",
+ av_get_media_type_string(AVMEDIA_TYPE_AUDIO), s->path);
+ goto beach;
+ }
+#endif
+
if ( ( err = avcodec_open2(avCodecCtx, codec, NULL) ) < 0) {
char errorstr[256];
av_strerror (err, errorstr, sizeof(errorstr));
//AUBIO_DBG("input_channels: %d\n", s->input_channels);
if (samplerate == 0) {
- samplerate = s->input_samplerate;
- //AUBIO_DBG("sampling rate set to 0, automagically adjusting to %d\n", samplerate);
+ s->samplerate = s->input_samplerate;
+ } else {
+ s->samplerate = samplerate;
}
- s->samplerate = samplerate;
if (s->samplerate > s->input_samplerate) {
AUBIO_WRN("source_avcodec: upsampling %s from %d to %d\n", s->path,
}
/* allocate output for avr */
- s->output = (float *)av_malloc(AUBIO_AVCODEC_MAX_BUFFER_SIZE * sizeof(float));
+ s->output = (smpl_t *)av_malloc(AUBIO_AVCODEC_MAX_BUFFER_SIZE * sizeof(smpl_t));
s->read_samples = 0;
s->read_index = 0;
}
void aubio_source_avcodec_reset_resampler(aubio_source_avcodec_t * s, uint_t multi) {
+ // create or reset resampler to/from mono/multi-channel
if ( (multi != s->multi) || (s->avr == NULL) ) {
int64_t input_layout = av_get_default_channel_layout(s->input_channels);
uint_t output_channels = multi ? s->input_channels : 1;
int64_t output_layout = av_get_default_channel_layout(output_channels);
- if (s->avr != NULL) {
- avresample_close( s->avr );
- av_free ( s->avr );
- s->avr = NULL;
- }
- AVAudioResampleContext *avr = s->avr;
- avr = avresample_alloc_context();
+ AVAudioResampleContext *avr = avresample_alloc_context();
+ AVAudioResampleContext *oldavr = s->avr;
av_opt_set_int(avr, "in_channel_layout", input_layout, 0);
av_opt_set_int(avr, "out_channel_layout", output_layout, 0);
av_opt_set_int(avr, "in_sample_rate", s->input_samplerate, 0);
av_opt_set_int(avr, "out_sample_rate", s->samplerate, 0);
av_opt_set_int(avr, "in_sample_fmt", s->avCodecCtx->sample_fmt, 0);
+#if HAVE_AUBIO_DOUBLE
+ av_opt_set_int(avr, "out_sample_fmt", AV_SAMPLE_FMT_DBL, 0);
+#else
av_opt_set_int(avr, "out_sample_fmt", AV_SAMPLE_FMT_FLT, 0);
+#endif
+ // TODO: use planar?
+ //av_opt_set_int(avr, "out_sample_fmt", AV_SAMPLE_FMT_FLTP, 0);
int err;
if ( ( err = avresample_open(avr) ) < 0) {
char errorstr[256];
return;
}
s->avr = avr;
+ if (oldavr != NULL) {
+ avresample_close( oldavr );
+ av_free ( oldavr );
+ oldavr = NULL;
+ }
s->multi = multi;
}
}
AVFormatContext *avFormatCtx = s->avFormatCtx;
AVCodecContext *avCodecCtx = s->avCodecCtx;
AVFrame *avFrame = s->avFrame;
- AVPacket avPacket;
+ AVPacket avPacket = s->avPacket;
av_init_packet (&avPacket);
AVAudioResampleContext *avr = s->avr;
- float *output = s->output;
+ smpl_t *output = s->output;
*read_samples = 0;
do
if (err != 0) {
char errorstr[256];
av_strerror (err, errorstr, sizeof(errorstr));
- AUBIO_ERR("Could not read frame in %s (%s)\n", s->path, errorstr);
+ AUBIO_ERR("source_avcodec: could not read frame in %s (%s)\n", s->path, errorstr);
goto beach;
}
} while (avPacket.stream_index != s->selected_stream);
int got_frame = 0;
+#if FF_API_LAVF_AVCTX
+ int ret = avcodec_send_packet(avCodecCtx, &avPacket);
+ if (ret < 0 && ret != AVERROR_EOF) {
+ AUBIO_ERR("source_avcodec: error when sending packet for %s\n", s->path);
+ goto beach;
+ }
+ ret = avcodec_receive_frame(avCodecCtx, avFrame);
+ if (ret >= 0) {
+ got_frame = 1;
+ }
+ if (ret < 0) {
+ if (ret == AVERROR(EAGAIN)) {
+ AUBIO_WRN("source_avcodec: output is not available right now - user must try to send new input\n");
+ } else if (ret == AVERROR_EOF) {
+ AUBIO_WRN("source_avcodec: the decoder has been fully flushed, and there will be no more output frames\n");
+ } else {
+ AUBIO_ERR("source_avcodec: decoding errors on %s\n", s->path);
+ goto beach;
+ }
+ }
+#else
int len = avcodec_decode_audio4(avCodecCtx, avFrame, &got_frame, &avPacket);
if (len < 0) {
- AUBIO_ERR("Error while decoding %s\n", s->path);
+ AUBIO_ERR("source_avcodec: error while decoding %s\n", s->path);
goto beach;
}
+#endif
if (got_frame == 0) {
- //AUBIO_ERR("Could not get frame for (%s)\n", s->path);
+ AUBIO_WRN("source_avcodec: did not get a frame when reading %s\n", s->path);
goto beach;
}
(uint8_t **)&output, out_linesize, max_out_samples,
(uint8_t **)avFrame->data, in_linesize, in_samples);
if (out_samples <= 0) {
- //AUBIO_ERR("No sample found while converting frame (%s)\n", s->path);
+ AUBIO_WRN("source_avcodec: no sample found while converting frame (%s)\n", s->path);
goto beach;
}
s->avr = avr;
s->output = output;
- av_free_packet(&avPacket);
+ av_packet_unref(&avPacket);
}
void aubio_source_avcodec_do(aubio_source_avcodec_t * s, fvec_t * read_data, uint_t * read){
- if (s->multi == 1) aubio_source_avcodec_reset_resampler(s, 0);
uint_t i;
uint_t end = 0;
uint_t total_wrote = 0;
+ // switch from multi
+ if (s->multi == 1) aubio_source_avcodec_reset_resampler(s, 0);
while (total_wrote < s->hop_size) {
end = MIN(s->read_samples - s->read_index, s->hop_size - total_wrote);
for (i = 0; i < end; i++) {
}
}
if (total_wrote < s->hop_size) {
- for (i = end; i < s->hop_size; i++) {
+ for (i = total_wrote; i < s->hop_size; i++) {
read_data->data[i] = 0.;
}
}
}
void aubio_source_avcodec_do_multi(aubio_source_avcodec_t * s, fmat_t * read_data, uint_t * read){
- if (s->multi == 0) aubio_source_avcodec_reset_resampler(s, 1);
uint_t i,j;
uint_t end = 0;
uint_t total_wrote = 0;
+ // switch from mono
+ if (s->multi == 0) aubio_source_avcodec_reset_resampler(s, 1);
while (total_wrote < s->hop_size) {
end = MIN(s->read_samples - s->read_index, s->hop_size - total_wrote);
for (j = 0; j < read_data->height; j++) {
}
if (total_wrote < s->hop_size) {
for (j = 0; j < read_data->height; j++) {
- for (i = end; i < s->hop_size; i++) {
+ for (i = total_wrote; i < s->hop_size; i++) {
read_data->data[j][i] = 0.;
}
}
*read = total_wrote;
}
-uint_t aubio_source_avcodec_get_samplerate(aubio_source_avcodec_t * s) {
+uint_t aubio_source_avcodec_get_samplerate(const aubio_source_avcodec_t * s) {
return s->samplerate;
}
-uint_t aubio_source_avcodec_get_channels(aubio_source_avcodec_t * s) {
+uint_t aubio_source_avcodec_get_channels(const aubio_source_avcodec_t * s) {
return s->input_channels;
}
int64_t min_ts = MAX(resampled_pos - 2000, 0);
int64_t max_ts = MIN(resampled_pos + 2000, INT64_MAX);
int seek_flags = AVSEEK_FLAG_FRAME | AVSEEK_FLAG_ANY;
- int ret = avformat_seek_file(s->avFormatCtx, s->selected_stream,
+ int ret = AUBIO_FAIL;
+ if (s->avFormatCtx != NULL && s->avr != NULL) {
+ ret = AUBIO_OK;
+ } else {
+ AUBIO_ERR("source_avcodec: failed seeking in %s (file not opened?)", s->path);
+ return ret;
+ }
+ if ((sint_t)pos < 0) {
+ AUBIO_ERR("source_avcodec: could not seek %s at %d (seeking position"
+ " should be >= 0)\n", s->path, pos);
+ return AUBIO_FAIL;
+ }
+ ret = avformat_seek_file(s->avFormatCtx, s->selected_stream,
min_ts, resampled_pos, max_ts, seek_flags);
if (ret < 0) {
- AUBIO_ERR("Failed seeking to %d in file %s", pos, s->path);
+ AUBIO_ERR("source_avcodec: failed seeking to %d in file %s", pos, s->path);
}
// reset read status
s->eof = 0;
return ret;
}
+uint_t aubio_source_avcodec_get_duration (aubio_source_avcodec_t * s) {
+ if (s && &(s->avFormatCtx) != NULL) {
+ int64_t duration = s->avFormatCtx->duration;
+ return s->samplerate * ((uint_t)duration / 1e6 );
+ }
+ return 0;
+}
+
uint_t aubio_source_avcodec_close(aubio_source_avcodec_t * s) {
if (s->avr != NULL) {
avresample_close( s->avr );
}
s->avCodecCtx = NULL;
if (s->avFormatCtx != NULL) {
- avformat_close_input ( &(s->avFormatCtx) );
+ avformat_close_input(&s->avFormatCtx);
+#ifndef HAVE_AUBIO_LIBAVCODEC_DEPRECATED // avoid crash on old libavcodec54
+ avformat_free_context(s->avFormatCtx);
+#endif
+ s->avFormatCtx = NULL;
}
- s->avFormatCtx = NULL;
+ av_packet_unref(&s->avPacket);
return AUBIO_OK;
}
av_frame_free( &(s->avFrame) );
}
s->avFrame = NULL;
+ if (s->path) {
+ AUBIO_FREE(s->path);
+ }
+ s->path = NULL;
AUBIO_FREE(s);
}
*/
-#ifndef _AUBIO_SOURCE_AVCODEC_H
-#define _AUBIO_SOURCE_AVCODEC_H
+#ifndef AUBIO_SOURCE_AVCODEC_H
+#define AUBIO_SOURCE_AVCODEC_H
/** \file
::aubio_source_avcodec_get_samplerate.
*/
-aubio_source_avcodec_t * new_aubio_source_avcodec(char_t * uri, uint_t samplerate, uint_t hop_size);
+aubio_source_avcodec_t * new_aubio_source_avcodec(const char_t * uri, uint_t samplerate, uint_t hop_size);
/**
\return samplerate, in Hz
*/
-uint_t aubio_source_avcodec_get_samplerate(aubio_source_avcodec_t * s);
+uint_t aubio_source_avcodec_get_samplerate(const aubio_source_avcodec_t * s);
/**
\return number of channels
*/
-uint_t aubio_source_avcodec_get_channels (aubio_source_avcodec_t * s);
+uint_t aubio_source_avcodec_get_channels (const aubio_source_avcodec_t * s);
/**
/**
+ get the duration of source object, in frames
+
+ \param s source object, created with ::new_aubio_source_avcodec
+ \return number of frames in file
+
+*/
+uint_t aubio_source_avcodec_get_duration (aubio_source_avcodec_t * s);
+
+/**
+
close source
\param s source object, created with ::new_aubio_source_avcodec
}
#endif
-#endif /* _AUBIO_SOURCE_AVCODEC_H */
+#endif /* AUBIO_SOURCE_AVCODEC_H */
*/
-
-#include "config.h"
+#include "aubio_priv.h"
#ifdef HAVE_SNDFILE
#include <sndfile.h>
-#include "aubio_priv.h"
#include "fvec.h"
#include "fmat.h"
#include "source_sndfile.h"
#include "temporal/resampler.h"
-#define MAX_CHANNELS 6
#define MAX_SIZE 4096
-#define MAX_SAMPLES MAX_CHANNELS * MAX_SIZE
+#define MAX_SAMPLES AUBIO_MAX_CHANNELS * MAX_SIZE
+
+#if !HAVE_AUBIO_DOUBLE
+#define aubio_sf_read_smpl sf_read_float
+#else /* HAVE_AUBIO_DOUBLE */
+#define aubio_sf_read_smpl sf_read_double
+#endif /* HAVE_AUBIO_DOUBLE */
struct _aubio_source_sndfile_t {
uint_t hop_size;
int input_samplerate;
int input_channels;
int input_format;
+ int duration;
// resampling stuff
smpl_t ratio;
uint_t input_hop_size;
#ifdef HAVE_SAMPLERATE
- aubio_resampler_t *resampler;
+ aubio_resampler_t **resamplers;
fvec_t *input_data;
+ fmat_t *input_mat;
#endif /* HAVE_SAMPLERATE */
// some temporary memory for sndfile to write at
uint_t scratch_size;
- float *scratch_data;
+ smpl_t *scratch_data;
};
-aubio_source_sndfile_t * new_aubio_source_sndfile(char_t * path, uint_t samplerate, uint_t hop_size) {
+aubio_source_sndfile_t * new_aubio_source_sndfile(const char_t * path, uint_t samplerate, uint_t hop_size) {
aubio_source_sndfile_t * s = AUBIO_NEW(aubio_source_sndfile_t);
SF_INFO sfinfo;
s->hop_size = hop_size;
s->channels = 1;
- s->path = path;
+
+ if (s->path) AUBIO_FREE(s->path);
+ s->path = AUBIO_ARRAY(char_t, strnlen(path, PATH_MAX) + 1);
+ strncpy(s->path, path, strnlen(path, PATH_MAX) + 1);
// try opening the file, getting the info in sfinfo
AUBIO_MEMSET(&sfinfo, 0, sizeof (sfinfo));
if (s->handle == NULL) {
/* show libsndfile err msg */
- AUBIO_ERR("source_sndfile: Failed opening %s: %s\n", s->path, sf_strerror (NULL));
+ AUBIO_ERR("source_sndfile: Failed opening %s (%s)\n", s->path,
+ sf_strerror (NULL));
goto beach;
}
s->input_samplerate = sfinfo.samplerate;
s->input_channels = sfinfo.channels;
s->input_format = sfinfo.format;
+ s->duration = sfinfo.frames;
if (samplerate == 0) {
- samplerate = s->input_samplerate;
+ s->samplerate = s->input_samplerate;
//AUBIO_DBG("sampling rate set to 0, automagically adjusting to %d\n", samplerate);
+ } else {
+ s->samplerate = samplerate;
}
- s->samplerate = samplerate;
/* compute input block size required before resampling */
- s->ratio = s->samplerate/(float)s->input_samplerate;
+ s->ratio = s->samplerate/(smpl_t)s->input_samplerate;
s->input_hop_size = (uint_t)FLOOR(s->hop_size / s->ratio + .5);
if (s->input_hop_size * s->input_channels > MAX_SAMPLES) {
}
#ifdef HAVE_SAMPLERATE
- s->resampler = NULL;
s->input_data = NULL;
+ s->input_mat = NULL;
+ s->resamplers = NULL;
if (s->ratio != 1) {
+ uint_t i;
+ s->resamplers = AUBIO_ARRAY(aubio_resampler_t*, s->input_channels);
s->input_data = new_fvec(s->input_hop_size);
- s->resampler = new_aubio_resampler(s->ratio, 4);
+ s->input_mat = new_fmat(s->input_channels, s->input_hop_size);
+ for (i = 0; i < (uint_t)s->input_channels; i++) {
+ s->resamplers[i] = new_aubio_resampler(s->ratio, 4);
+ }
if (s->ratio > 1) {
// we would need to add a ring buffer for these
- if ( (uint_t)(s->input_hop_size * s->ratio + .5) != s->hop_size ) {
+ if ( (uint_t)FLOOR(s->input_hop_size * s->ratio + .5) != s->hop_size ) {
AUBIO_ERR("source_sndfile: can not upsample %s from %d to %d\n", s->path,
s->input_samplerate, s->samplerate);
goto beach;
AUBIO_WRN("source_sndfile: upsampling %s from %d to %d\n", s->path,
s->input_samplerate, s->samplerate);
}
+ s->duration = (uint_t)FLOOR(s->duration * s->ratio);
}
#else
if (s->ratio != 1) {
/* allocate data for de/interleaving reallocated when needed. */
s->scratch_size = s->input_hop_size * s->input_channels;
- s->scratch_data = AUBIO_ARRAY(float,s->scratch_size);
+ s->scratch_data = AUBIO_ARRAY(smpl_t, s->scratch_size);
return s;
void aubio_source_sndfile_do(aubio_source_sndfile_t * s, fvec_t * read_data, uint_t * read){
uint_t i,j, input_channels = s->input_channels;
/* read from file into scratch_data */
- sf_count_t read_samples = sf_read_float (s->handle, s->scratch_data, s->scratch_size);
+ sf_count_t read_samples = aubio_sf_read_smpl (s->handle, s->scratch_data, s->scratch_size);
/* where to store de-interleaved data */
smpl_t *ptr_data;
}
#ifdef HAVE_SAMPLERATE
- if (s->resampler) {
- aubio_resampler_do(s->resampler, s->input_data, read_data);
+ if (s->resamplers) {
+ aubio_resampler_do(s->resamplers[0], s->input_data, read_data);
}
#endif /* HAVE_SAMPLERATE */
void aubio_source_sndfile_do_multi(aubio_source_sndfile_t * s, fmat_t * read_data, uint_t * read){
uint_t i,j, input_channels = s->input_channels;
/* do actual reading */
- sf_count_t read_samples = sf_read_float (s->handle, s->scratch_data, s->scratch_size);
+ sf_count_t read_samples = aubio_sf_read_smpl (s->handle, s->scratch_data, s->scratch_size);
/* where to store de-interleaved data */
smpl_t **ptr_data;
#ifdef HAVE_SAMPLERATE
if (s->ratio != 1) {
- AUBIO_ERR("source_sndfile: no multi channel resampling yet\n");
- return;
- //ptr_data = s->input_data->data;
+ ptr_data = s->input_mat->data;
} else
#endif /* HAVE_SAMPLERATE */
{
// channels of the file, de-interleaving data
for (j = 0; j < read_samples / input_channels; j++) {
for (i = 0; i < read_data->height; i++) {
- ptr_data[i][j] = (smpl_t)s->scratch_data[j * input_channels + i];
+ ptr_data[i][j] = s->scratch_data[j * input_channels + i];
}
}
} else {
// channel from the file to the destination matrix, de-interleaving data
for (j = 0; j < read_samples / input_channels; j++) {
for (i = 0; i < input_channels; i++) {
- ptr_data[i][j] = (smpl_t)s->scratch_data[j * input_channels + i];
+ ptr_data[i][j] = s->scratch_data[j * input_channels + i];
}
}
}
// of the file to each additional channels, de-interleaving data
for (j = 0; j < read_samples / input_channels; j++) {
for (i = input_channels; i < read_data->height; i++) {
- ptr_data[i][j] = (smpl_t)s->scratch_data[j * input_channels + (input_channels - 1)];
+ ptr_data[i][j] = s->scratch_data[j * input_channels + (input_channels - 1)];
}
}
}
#ifdef HAVE_SAMPLERATE
- if (s->resampler) {
- //aubio_resampler_do(s->resampler, s->input_data, read_data);
+ if (s->resamplers) {
+ for (i = 0; i < input_channels; i++) {
+ fvec_t input_chan, read_chan;
+ input_chan.data = s->input_mat->data[i];
+ input_chan.length = s->input_mat->length;
+ read_chan.data = read_data->data[i];
+ read_chan.length = read_data->length;
+ aubio_resampler_do(s->resamplers[i], &input_chan, &read_chan);
+ }
}
#endif /* HAVE_SAMPLERATE */
return s->input_channels;
}
+uint_t aubio_source_sndfile_get_duration (const aubio_source_sndfile_t * s) {
+ if (s && s->duration) {
+ return s->duration;
+ }
+ return 0;
+}
+
uint_t aubio_source_sndfile_seek (aubio_source_sndfile_t * s, uint_t pos) {
uint_t resampled_pos = (uint_t)ROUND(pos / s->ratio);
- sf_count_t sf_ret = sf_seek (s->handle, resampled_pos, SEEK_SET);
+ sf_count_t sf_ret;
+ if (s->handle == NULL) {
+ AUBIO_ERR("source_sndfile: failed seeking in %s (file not opened?)\n",
+ s->path);
+ return AUBIO_FAIL;
+ }
+ if ((sint_t)pos < 0) {
+ AUBIO_ERR("source_sndfile: could not seek %s at %d (seeking position"
+ " should be >= 0)\n", s->path, pos);
+ return AUBIO_FAIL;
+ }
+ sf_ret = sf_seek (s->handle, resampled_pos, SEEK_SET);
if (sf_ret == -1) {
AUBIO_ERR("source_sndfile: Failed seeking %s at %d: %s\n", s->path, pos, sf_strerror (NULL));
return AUBIO_FAIL;
uint_t aubio_source_sndfile_close (aubio_source_sndfile_t *s) {
if (!s->handle) {
- return AUBIO_FAIL;
+ return AUBIO_OK;
}
if(sf_close(s->handle)) {
AUBIO_ERR("source_sndfile: Error closing file %s: %s\n", s->path, sf_strerror (NULL));
return AUBIO_FAIL;
}
+ s->handle = NULL;
return AUBIO_OK;
}
if (!s) return;
aubio_source_sndfile_close(s);
#ifdef HAVE_SAMPLERATE
- if (s->resampler != NULL) {
- del_aubio_resampler(s->resampler);
+ if (s->resamplers != NULL) {
+ uint_t i = 0, input_channels = s->input_channels;
+ for (i = 0; i < input_channels; i ++) {
+ if (s->resamplers[i] != NULL) {
+ del_aubio_resampler(s->resamplers[i]);
+ }
+ }
+ AUBIO_FREE(s->resamplers);
}
if (s->input_data) {
del_fvec(s->input_data);
}
+ if (s->input_mat) {
+ del_fmat(s->input_mat);
+ }
#endif /* HAVE_SAMPLERATE */
+ if (s->path) AUBIO_FREE(s->path);
AUBIO_FREE(s->scratch_data);
AUBIO_FREE(s);
}
*/
-#ifndef _AUBIO_SOURCE_SNDFILE_H
-#define _AUBIO_SOURCE_SNDFILE_H
+#ifndef AUBIO_SOURCE_SNDFILE_H
+#define AUBIO_SOURCE_SNDFILE_H
/** \file
::aubio_source_sndfile_get_samplerate.
*/
-aubio_source_sndfile_t * new_aubio_source_sndfile(char_t * uri, uint_t samplerate, uint_t hop_size);
+aubio_source_sndfile_t * new_aubio_source_sndfile(const char_t * uri, uint_t samplerate, uint_t hop_size);
/**
/**
+ get the duration of source object, in frames
+
+ \param s source object, created with ::new_aubio_source_sndfile
+ \return number of frames in file
+
+*/
+uint_t aubio_source_sndfile_get_duration (const aubio_source_sndfile_t *s);
+
+/**
+
close source
\param s source object, created with ::new_aubio_source_sndfile
}
#endif
-#endif /* _AUBIO_SOURCE_SNDFILE_H */
+#endif /* AUBIO_SOURCE_SNDFILE_H */
*/
-#include "config.h"
+#include "aubio_priv.h"
#ifdef HAVE_WAVREAD
-#include "aubio_priv.h"
#include "fvec.h"
#include "fmat.h"
#include "source_wavread.h"
uint_t read_index;
uint_t eof;
+ uint_t duration;
+
size_t seek_start;
unsigned char *short_output;
fmat_t *output;
};
-unsigned int read_little_endian (unsigned char *buf, unsigned int length);
-unsigned int read_little_endian (unsigned char *buf, unsigned int length) {
+static unsigned int read_little_endian (unsigned char *buf,
+ unsigned int length);
+
+static unsigned int read_little_endian (unsigned char *buf,
+ unsigned int length)
+{
uint_t i, ret = 0;
for (i = 0; i < length; i++) {
ret += buf[i] << (i * 8);
return ret;
}
-aubio_source_wavread_t * new_aubio_source_wavread(char_t * path, uint_t samplerate, uint_t hop_size) {
+aubio_source_wavread_t * new_aubio_source_wavread(const char_t * path, uint_t samplerate, uint_t hop_size) {
aubio_source_wavread_t * s = AUBIO_NEW(aubio_source_wavread_t);
- size_t bytes_read = 0, bytes_expected = 44;
- unsigned char buf[5];
- unsigned int format, channels, sr, byterate, blockalign, bitspersample;//, data_size;
+ size_t bytes_read = 0, bytes_junk = 0, bytes_expected = 44;
+ unsigned char buf[5] = "\0";
+ unsigned int format, channels, sr, byterate, blockalign, duration, bitspersample;//, data_size;
if (path == NULL) {
AUBIO_ERR("source_wavread: Aborted opening null path\n");
goto beach;
}
- s->path = path;
+ if (s->path) AUBIO_FREE(s->path);
+ s->path = AUBIO_ARRAY(char_t, strnlen(path, PATH_MAX) + 1);
+ strncpy(s->path, path, strnlen(path, PATH_MAX) + 1);
+
s->samplerate = samplerate;
s->hop_size = hop_size;
bytes_read += fread(buf, 1, 4, s->fid);
buf[4] = '\0';
if ( strcmp((const char *)buf, "RIFF") != 0 ) {
- AUBIO_ERR("source_wavread: could not find RIFF header in %s\n", s->path);
+ AUBIO_ERR("source_wavread: Failed opening %s (could not find RIFF header)\n", s->path);
goto beach;
}
bytes_read += fread(buf, 1, 4, s->fid);
buf[4] = '\0';
if ( strcmp((const char *)buf, "WAVE") != 0 ) {
- AUBIO_ERR("source_wavread: wrong format in RIFF header in %s\n", s->path);
+ AUBIO_ERR("source_wavread: Failed opening %s (wrong format in RIFF header)\n", s->path);
goto beach;
}
// Subchunk1ID
bytes_read += fread(buf, 1, 4, s->fid);
buf[4] = '\0';
+
+ // check if we have a JUNK Chunk
+ if ( strcmp((const char *)buf, "JUNK") == 0 ) {
+ bytes_junk = fread(buf, 1, 4, s->fid);
+ buf[4] = '\0';
+ bytes_junk += read_little_endian(buf, 4);
+ if (fseek(s->fid, bytes_read + bytes_junk, SEEK_SET) != 0) {
+ AUBIO_ERR("source_wavread: Failed opening %s (could not seek past JUNK Chunk: %s)\n",
+ s->path, strerror(errno));
+ goto beach;
+ }
+ bytes_read += bytes_junk;
+ bytes_expected += bytes_junk + 4;
+ // now really read the fmt chunk
+ bytes_read += fread(buf, 1, 4, s->fid);
+ buf[4] = '\0';
+ }
+
+ // get the fmt chunk
if ( strcmp((const char *)buf, "fmt ") != 0 ) {
- AUBIO_ERR("source_wavread: fmt RIFF header in %s\n", s->path);
+ AUBIO_ERR("source_wavread: Failed opening %s (could not find 'fmt ' in RIFF header)\n", s->path);
goto beach;
}
format = read_little_endian(buf, 4);
if ( format != 16 ) {
// TODO accept format 18
- AUBIO_ERR("source_wavread: file %s is not encoded with PCM\n", s->path);
+ AUBIO_ERR("source_wavread: Failed opening %s (not encoded with PCM)\n", s->path);
goto beach;
}
if ( buf[1] || buf[2] | buf[3] ) {
- AUBIO_ERR("source_wavread: Subchunk1Size should be 0, in %s\n", s->path);
+ AUBIO_ERR("source_wavread: Failed opening %s (Subchunk1Size should be 0)\n", s->path);
goto beach;
}
// AudioFormat
bytes_read += fread(buf, 1, 2, s->fid);
if ( buf[0] != 1 || buf[1] != 0) {
- AUBIO_ERR("source_wavread: AudioFormat should be PCM, in %s\n", s->path);
+ AUBIO_ERR("source_wavread: Failed opening %s (AudioFormat should be PCM)\n", s->path);
goto beach;
}
#endif
if ( byterate * 8 != sr * channels * bitspersample ) {
- AUBIO_ERR("source_wavread: wrong byterate in %s\n", s->path);
+ AUBIO_ERR("source_wavread: Failed opening %s (wrong byterate)\n", s->path);
goto beach;
}
if ( blockalign * 8 != channels * bitspersample ) {
- AUBIO_ERR("source_wavread: wrong blockalign in %s\n", s->path);
+ AUBIO_ERR("source_wavread: Failed opening %s (wrong blockalign)\n", s->path);
goto beach;
}
// Subchunk2ID
bytes_read += fread(buf, 1, 4, s->fid);
buf[4] = '\0';
- if ( strcmp((const char *)buf, "data") != 0 ) {
- AUBIO_ERR("source_wavread: data RIFF header not found in %s\n", s->path);
- goto beach;
+ while ( strcmp((const char *)buf, "data") != 0 ) {
+ if (feof(s->fid) || ferror(s->fid)) {
+ AUBIO_ERR("source_wavread: no data RIFF header found in %s\n", s->path);
+ goto beach;
+ }
+ bytes_junk = fread(buf, 1, 4, s->fid);
+ buf[4] = '\0';
+ bytes_junk += read_little_endian(buf, 4);
+ if (fseek(s->fid, bytes_read + bytes_junk, SEEK_SET) != 0) {
+ AUBIO_ERR("source_wavread: could not seek past unknown chunk in %s (%s)\n",
+ s->path, strerror(errno));
+ goto beach;
+ }
+ bytes_read += bytes_junk;
+ bytes_expected += bytes_junk+ 4;
+ bytes_read += fread(buf, 1, 4, s->fid);
+ buf[4] = '\0';
}
// Subchunk2Size
bytes_read += fread(buf, 1, 4, s->fid);
+ duration = read_little_endian(buf, 4) / blockalign;
+
//data_size = buf[0] + (buf[1] << 8) + (buf[2] << 16) + (buf[3] << 24);
//AUBIO_MSG("found %d frames in %s\n", 8 * data_size / bitspersample / channels, s->path);
s->blockalign= blockalign;
s->bitspersample = bitspersample;
+ s->duration = duration;
+
s->short_output = (unsigned char *)calloc(s->blockalign, AUBIO_WAVREAD_BUFSIZE);
s->read_index = 0;
s->read_samples = 0;
uint_t i, j;
uint_t end = 0;
uint_t total_wrote = 0;
+ if (s->fid == NULL) {
+ AUBIO_ERR("source_wavread: could not read from %s (file not opened)\n",
+ s->path);
+ return;
+ }
while (total_wrote < s->hop_size) {
end = MIN(s->read_samples - s->read_index, s->hop_size - total_wrote);
for (i = 0; i < end; i++) {
uint_t i,j;
uint_t end = 0;
uint_t total_wrote = 0;
+ if (s->fid == NULL) {
+ AUBIO_ERR("source_wavread: could not read from %s (file not opened)\n",
+ s->path);
+ return;
+ }
while (total_wrote < s->hop_size) {
end = MIN(s->read_samples - s->read_index, s->hop_size - total_wrote);
for (j = 0; j < read_data->height; j++) {
uint_t aubio_source_wavread_seek (aubio_source_wavread_t * s, uint_t pos) {
uint_t ret = 0;
+ if (s->fid == NULL) {
+ AUBIO_ERR("source_wavread: could not seek %s (file not opened?)\n", s->path, pos);
+ return AUBIO_FAIL;
+ }
if ((sint_t)pos < 0) {
+ AUBIO_ERR("source_wavread: could not seek %s at %d (seeking position should be >= 0)\n", s->path, pos);
return AUBIO_FAIL;
}
ret = fseek(s->fid, s->seek_start + pos * s->blockalign, SEEK_SET);
return AUBIO_OK;
}
+uint_t aubio_source_wavread_get_duration (const aubio_source_wavread_t * s) {
+ if (s && s->duration) {
+ return s->duration;
+ }
+ return 0;
+}
+
uint_t aubio_source_wavread_close (aubio_source_wavread_t * s) {
- if (!s->fid) {
- return AUBIO_FAIL;
+ if (s->fid == NULL) {
+ return AUBIO_OK;
}
if (fclose(s->fid)) {
AUBIO_ERR("source_wavread: could not close %s (%s)\n", s->path, strerror(errno));
aubio_source_wavread_close(s);
if (s->short_output) AUBIO_FREE(s->short_output);
if (s->output) del_fmat(s->output);
+ if (s->path) AUBIO_FREE(s->path);
AUBIO_FREE(s);
}
*/
-#ifndef _AUBIO_SOURCE_WAVREAD_H
-#define _AUBIO_SOURCE_WAVREAD_H
+#ifndef AUBIO_SOURCE_WAVREAD_H
+#define AUBIO_SOURCE_WAVREAD_H
/** \file
::aubio_source_wavread_get_samplerate.
*/
-aubio_source_wavread_t * new_aubio_source_wavread(char_t * uri, uint_t samplerate, uint_t hop_size);
+aubio_source_wavread_t * new_aubio_source_wavread(const char_t * uri, uint_t samplerate, uint_t hop_size);
/**
/**
+ get the duration of source object, in frames
+
+ \param s source object, created with ::new_aubio_source_sndfile
+ \return number of frames in file
+
+*/
+uint_t aubio_source_wavread_get_duration (const aubio_source_wavread_t *s);
+
+/**
+
close source
\param s source object, created with ::new_aubio_source_wavread
}
#endif
-#endif /* _AUBIO_SOURCE_WAVREAD_H */
+#endif /* AUBIO_SOURCE_WAVREAD_H */
-#include "config.h"
+#include "aubio_priv.h"
#if defined(HAVE_SOURCE_APPLE_AUDIO) || defined(HAVE_SINK_APPLE_AUDIO)
#include <CoreFoundation/CoreFoundation.h>
// ExtAudioFileRef, AudioStreamBasicDescription, AudioBufferList, ...
#include <AudioToolbox/AudioToolbox.h>
-#include "aubio_priv.h"
int createAubioBufferList(AudioBufferList *bufferList, int channels, int segmentSize);
void freeAudioBufferList(AudioBufferList *bufferList);
#include "aubio_priv.h"
#include "lvec.h"
-lvec_t * new_lvec( uint_t length) {
+lvec_t * new_lvec(uint_t length) {
lvec_t * s;
if ((sint_t)length <= 0) {
return NULL;
return s->data[position];
}
-lsmp_t * lvec_get_data(lvec_t *s) {
+lsmp_t * lvec_get_data(const lvec_t *s) {
return s->data;
}
/* helper functions */
-void lvec_print(lvec_t *s) {
+void lvec_print(const lvec_t *s) {
uint_t j;
for (j=0; j< s->length; j++) {
AUBIO_MSG(AUBIO_LSMP_FMT " ", s->data[j]);
*/
-#ifndef _AUBIO__LVEC_H
-#define _AUBIO__LVEC_H
+#ifndef AUBIO_LVEC_H
+#define AUBIO_LVEC_H
#ifdef __cplusplus
extern "C" {
\param s vector to read from
*/
-lsmp_t * lvec_get_data(lvec_t *s);
+lsmp_t * lvec_get_data(const lvec_t *s);
/** print out lvec data
\param s vector to print out
*/
-void lvec_print(lvec_t *s);
+void lvec_print(const lvec_t *s);
/** set all elements to a given value
}
#endif
-#endif /* _AUBIO__LVEC_H */
+#endif /* AUBIO_LVEC_H */
#include "fvec.h"
#include "mathutils.h"
#include "musicutils.h"
-#include "config.h"
/** Window types */
typedef enum
void
fvec_shift (fvec_t * s)
{
+ uint_t half = s->length / 2, start = half, j;
+ // if length is odd, middle element is moved to the end
+ if (2 * half < s->length) start ++;
#ifndef HAVE_ATLAS
- uint_t j;
- for (j = 0; j < s->length / 2; j++) {
- ELEM_SWAP (s->data[j], s->data[j + s->length / 2]);
+ for (j = 0; j < half; j++) {
+ ELEM_SWAP (s->data[j], s->data[j + start]);
}
#else
- uint_t half = s->length / 2;
- aubio_cblas_swap(half, s->data, 1, s->data + half, 1);
+ aubio_cblas_swap(half, s->data, 1, s->data + start, 1);
#endif
+ if (start != half) {
+ for (j = 0; j < half; j++) {
+ ELEM_SWAP (s->data[j + start - 1], s->data[j + start]);
+ }
+ }
+}
+
+void
+fvec_ishift (fvec_t * s)
+{
+ uint_t half = s->length / 2, start = half, j;
+ // if length is odd, middle element is moved to the beginning
+ if (2 * half < s->length) start ++;
+#ifndef HAVE_ATLAS
+ for (j = 0; j < half; j++) {
+ ELEM_SWAP (s->data[j], s->data[j + start]);
+ }
+#else
+ aubio_cblas_swap(half, s->data, 1, s->data + start, 1);
+#endif
+ if (start != half) {
+ for (j = 0; j < half; j++) {
+ ELEM_SWAP (s->data[half], s->data[j]);
+ }
+ }
}
smpl_t
-aubio_level_lin (fvec_t * f)
+aubio_level_lin (const fvec_t * f)
{
smpl_t energy = 0.;
#ifndef HAVE_ATLAS
}
}
-smpl_t fvec_quadratic_peak_pos (fvec_t * x, uint_t pos) {
+smpl_t fvec_quadratic_peak_pos (const fvec_t * x, uint_t pos) {
smpl_t s0, s1, s2; uint_t x0, x2;
+ smpl_t half = .5, two = 2.;
if (pos == 0 || pos == x->length - 1) return pos;
x0 = (pos < 1) ? pos : pos - 1;
x2 = (pos + 1 < x->length) ? pos + 1 : pos;
s0 = x->data[x0];
s1 = x->data[pos];
s2 = x->data[x2];
- return pos + 0.5 * (s0 - s2 ) / (s0 - 2.* s1 + s2);
+ return pos + half * (s0 - s2 ) / (s0 - two * s1 + s2);
}
smpl_t fvec_quadratic_peak_mag (fvec_t *x, smpl_t pos) {
return x1 - .25 * (x0 - x2) * (pos - index);
}
-uint_t fvec_peakpick(fvec_t * onset, uint_t pos) {
+uint_t fvec_peakpick(const fvec_t * onset, uint_t pos) {
uint_t tmp=0;
tmp = (onset->data[pos] > onset->data[pos-1]
&& onset->data[pos] > onset->data[pos+1]
}
smpl_t
-aubio_db_spl (fvec_t * o)
+aubio_db_spl (const fvec_t * o)
{
return 10. * LOG10 (aubio_level_lin (o));
}
uint_t
-aubio_silence_detection (fvec_t * o, smpl_t threshold)
+aubio_silence_detection (const fvec_t * o, smpl_t threshold)
{
return (aubio_db_spl (o) < threshold);
}
smpl_t
-aubio_level_detection (fvec_t * o, smpl_t threshold)
+aubio_level_detection (const fvec_t * o, smpl_t threshold)
{
smpl_t db_spl = aubio_db_spl (o);
if (db_spl < threshold) {
}
void
-aubio_autocorr (fvec_t * input, fvec_t * output)
+aubio_autocorr (const fvec_t * input, fvec_t * output)
{
uint_t i, j, length = input->length;
smpl_t *data, *acf;
*/
-#ifndef _AUBIO_MATHUTILS_H
-#define _AUBIO_MATHUTILS_H
+#ifndef AUBIO_MATHUTILS_H
+#define AUBIO_MATHUTILS_H
#include "fvec.h"
#include "musicutils.h"
*/
void fvec_shift (fvec_t * v);
+/** swap the left and right halves of a vector
+
+ This function swaps the left part of the signal with the right part of the
+signal. Therefore
+
+ \f$ a[0], a[1], ..., a[\frac{N}{2}], a[\frac{N}{2}+1], ..., a[N-1], a[N] \f$
+
+ becomes
+
+ \f$ a[\frac{N}{2}+1], ..., a[N-1], a[N], a[0], a[1], ..., a[\frac{N}{2}] \f$
+
+ This operation, known as 'ifftshift' in the Matlab Signal Processing Toolbox,
+can be used after computing the inverse FFT to simplify the phase relationship
+of the resulting spectrum. See Amalia de Götzen's paper referred to above.
+
+*/
+void fvec_ishift (fvec_t * v);
+
/** compute the sum of all elements of a vector
\param v vector to compute the sum of
\return \f$ p + p_{frac} \f$ exact peak position of interpolated maximum or minimum
*/
-smpl_t fvec_quadratic_peak_pos (fvec_t * x, uint_t p);
+smpl_t fvec_quadratic_peak_pos (const fvec_t * x, uint_t p);
/** finds magnitude of peak by quadratic interpolation
\return 1 if a peak is found, 0 otherwise
*/
-uint_t fvec_peakpick (fvec_t * v, uint_t p);
+uint_t fvec_peakpick (const fvec_t * v, uint_t p);
/** return 1 if a is a power of 2, 0 otherwise */
uint_t aubio_is_power_of_two(uint_t a);
\param output vector to store autocorrelation function to
*/
-void aubio_autocorr (fvec_t * input, fvec_t * output);
+void aubio_autocorr (const fvec_t * input, fvec_t * output);
#ifdef __cplusplus
}
#endif
-#endif /* _AUBIO_MATHUTILS_H */
+#endif /* AUBIO_MATHUTILS_H */
* various functions useful in audio signal processing
*/
-#ifndef _AUBIO__MUSICUTILS_H
-#define _AUBIO__MUSICUTILS_H
+#ifndef AUBIO_MUSICUTILS_H
+#define AUBIO_MUSICUTILS_H
#ifdef __cplusplus
extern "C" {
\return level of v
*/
-smpl_t aubio_level_lin (fvec_t * v);
+smpl_t aubio_level_lin (const fvec_t * v);
/** compute sound pressure level (SPL) in dB
\return level of v in dB SPL
*/
-smpl_t aubio_db_spl (fvec_t * v);
+smpl_t aubio_db_spl (const fvec_t * v);
/** check if buffer level in dB SPL is under a given threshold
\return 0 if level is under the given threshold, 1 otherwise
*/
-uint_t aubio_silence_detection (fvec_t * v, smpl_t threshold);
+uint_t aubio_silence_detection (const fvec_t * v, smpl_t threshold);
/** get buffer level if level >= threshold, 1. otherwise
\return level in dB SPL if level >= threshold, 1. otherwise
*/
-smpl_t aubio_level_detection (fvec_t * v, smpl_t threshold);
+smpl_t aubio_level_detection (const fvec_t * v, smpl_t threshold);
#ifdef __cplusplus
}
#endif
-#endif /* _AUBIO__MUSICUTILS_H */
+#endif /* AUBIO_MUSICUTILS_H */
--- /dev/null
+/*
+ Copyright (C) 2014 Paul Brossier <piem@aubio.org>
+
+ This file is part of aubio.
+
+ aubio is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ aubio is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with aubio. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "aubio_priv.h"
+#include "fvec.h"
+#include "pitch/pitch.h"
+#include "onset/onset.h"
+#include "notes/notes.h"
+
+#define AUBIO_DEFAULT_NOTES_SILENCE -70.
+// increase to 10. for .1 cent precision
+// or to 100. for .01 cent precision
+#define AUBIO_DEFAULT_CENT_PRECISION 1.
+#define AUBIO_DEFAULT_NOTES_MINIOI_MS 30.
+
+struct _aubio_notes_t {
+
+ uint_t onset_buf_size;
+ uint_t pitch_buf_size;
+ uint_t hop_size;
+
+ uint_t samplerate;
+
+ uint_t median;
+ fvec_t *note_buffer;
+ fvec_t *note_buffer2;
+
+ aubio_pitch_t *pitch;
+ fvec_t *pitch_output;
+ smpl_t pitch_tolerance;
+
+ aubio_onset_t *onset;
+ fvec_t *onset_output;
+ smpl_t onset_threshold;
+
+ smpl_t curnote;
+ smpl_t newnote;
+
+ smpl_t silence_threshold;
+
+ uint_t isready;
+};
+
+aubio_notes_t * new_aubio_notes (const char_t * method,
+ uint_t buf_size, uint_t hop_size, uint_t samplerate) {
+ aubio_notes_t *o = AUBIO_NEW(aubio_notes_t);
+
+ const char_t * onset_method = "default";
+ const char_t * pitch_method = "default";
+
+ o->onset_buf_size = buf_size;
+ o->pitch_buf_size = buf_size * 4;
+ o->hop_size = hop_size;
+
+ o->onset_threshold = 0.;
+ o->pitch_tolerance = 0.;
+
+ o->samplerate = samplerate;
+
+ o->median = 6;
+
+ o->isready = 0;
+
+ o->onset = new_aubio_onset (onset_method, o->onset_buf_size, o->hop_size, o->samplerate);
+ if (o->onset_threshold != 0.) aubio_onset_set_threshold (o->onset, o->onset_threshold);
+ o->onset_output = new_fvec (1);
+
+ o->pitch = new_aubio_pitch (pitch_method, o->pitch_buf_size, o->hop_size, o->samplerate);
+ if (o->pitch_tolerance != 0.) aubio_pitch_set_tolerance (o->pitch, o->pitch_tolerance);
+ aubio_pitch_set_unit (o->pitch, "midi");
+ o->pitch_output = new_fvec (1);
+
+ if (strcmp(method, "default") != 0) {
+ AUBIO_ERR("notes: unknown notes detection method \"%s\"\n", method);
+ goto fail;
+ }
+ o->note_buffer = new_fvec(o->median);
+ o->note_buffer2 = new_fvec(o->median);
+
+ o->curnote = -1.;
+ o->newnote = 0.;
+
+ aubio_notes_set_silence(o, AUBIO_DEFAULT_NOTES_SILENCE);
+ aubio_notes_set_minioi_ms (o, AUBIO_DEFAULT_NOTES_MINIOI_MS);
+
+ return o;
+
+fail:
+ del_aubio_notes(o);
+ return NULL;
+}
+
+uint_t aubio_notes_set_silence(aubio_notes_t *o, smpl_t silence)
+{
+ uint_t err = AUBIO_OK;
+ if (aubio_pitch_set_silence(o->pitch, silence) != AUBIO_OK) {
+ err = AUBIO_FAIL;
+ }
+ if (aubio_onset_set_silence(o->onset, silence) != AUBIO_OK) {
+ err = AUBIO_FAIL;
+ }
+ o->silence_threshold = silence;
+ return err;
+}
+
+smpl_t aubio_notes_get_silence(const aubio_notes_t *o)
+{
+ return aubio_pitch_get_silence(o->pitch);
+}
+
+uint_t aubio_notes_set_minioi_ms (aubio_notes_t *o, smpl_t minioi_ms)
+{
+ uint_t err = AUBIO_OK;
+ if (!o->onset || (aubio_onset_set_minioi_ms(o->onset, minioi_ms) != 0)) {
+ err = AUBIO_FAIL;
+ }
+ return err;
+}
+
+smpl_t aubio_notes_get_minioi_ms(const aubio_notes_t *o)
+{
+ return aubio_onset_get_minioi_ms(o->onset);
+}
+
+/** append new note candidate to the note_buffer and return filtered value. we
+ * need to copy the input array as fvec_median destroy its input data.*/
+static void
+note_append (fvec_t * note_buffer, smpl_t curnote)
+{
+ uint_t i = 0;
+ for (i = 0; i < note_buffer->length - 1; i++) {
+ note_buffer->data[i] = note_buffer->data[i + 1];
+ }
+ //note_buffer->data[note_buffer->length - 1] = ROUND(10.*curnote)/10.;
+ note_buffer->data[note_buffer->length - 1] = ROUND(AUBIO_DEFAULT_CENT_PRECISION*curnote);
+ return;
+}
+
+static smpl_t
+aubio_notes_get_latest_note (aubio_notes_t *o)
+{
+ fvec_copy(o->note_buffer, o->note_buffer2);
+ return fvec_median (o->note_buffer2) / AUBIO_DEFAULT_CENT_PRECISION;
+}
+
+
+void aubio_notes_do (aubio_notes_t *o, const fvec_t * input, fvec_t * notes)
+{
+ smpl_t new_pitch, curlevel;
+ fvec_zeros(notes);
+ aubio_onset_do(o->onset, input, o->onset_output);
+
+ aubio_pitch_do (o->pitch, input, o->pitch_output);
+ new_pitch = o->pitch_output->data[0];
+ if(o->median){
+ note_append(o->note_buffer, new_pitch);
+ }
+
+ /* curlevel is negatif or 1 if silence */
+ curlevel = aubio_level_detection(input, o->silence_threshold);
+ if (o->onset_output->data[0] != 0) {
+ /* test for silence */
+ if (curlevel == 1.) {
+ if (o->median) o->isready = 0;
+ /* send note off */
+ //send_noteon(o->curnote,0);
+ //notes->data[0] = o->curnote;
+ //notes->data[1] = 0.;
+ notes->data[2] = o->curnote;
+ } else {
+ if (o->median) {
+ o->isready = 1;
+ } else {
+ /* kill old note */
+ //send_noteon(o->curnote,0, o->samplerate);
+ notes->data[2] = o->curnote;
+ /* get and send new one */
+ //send_noteon(new_pitch,127+(int)floor(curlevel), o->samplerate);
+ notes->data[0] = new_pitch;
+ notes->data[1] = 127 + (int)floor(curlevel);
+ o->curnote = new_pitch;
+ }
+ }
+ } else {
+ if (o->median) {
+ if (o->isready > 0)
+ o->isready++;
+ if (o->isready == o->median)
+ {
+ /* kill old note */
+ //send_noteon(curnote,0);
+ notes->data[2] = o->curnote;
+ o->newnote = aubio_notes_get_latest_note(o);
+ o->curnote = o->newnote;
+ /* get and send new one */
+ if (o->curnote>45){
+ //send_noteon(curnote,127+(int)floor(curlevel));
+ notes->data[0] = o->curnote;
+ notes->data[1] = 127 + (int) floor(curlevel);
+ }
+ }
+ } // if median
+ }
+}
+
+void del_aubio_notes (aubio_notes_t *o) {
+ if (o->note_buffer) del_fvec(o->note_buffer);
+ if (o->note_buffer2) del_fvec(o->note_buffer2);
+ if (o->pitch_output) del_fvec(o->pitch_output);
+ if (o->pitch) del_aubio_pitch(o->pitch);
+ if (o->onset_output) del_fvec(o->onset_output);
+ if (o->onset) del_aubio_onset(o->onset);
+ AUBIO_FREE(o);
+}
--- /dev/null
+/*
+ Copyright (C) 2003-2014 Paul Brossier <piem@aubio.org>
+
+ This file is part of aubio.
+
+ aubio is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ aubio is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with aubio. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+/** \file
+
+ Note detection object
+
+*/
+
+#ifndef _AUBIO_NOTES_H
+#define _AUBIO_NOTES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** notes detection object */
+typedef struct _aubio_notes_t aubio_notes_t;
+
+/** create notes detection object
+
+ \param method notes detection type as specified in specdesc.h
+ \param buf_size buffer size for phase vocoder
+ \param hop_size hop size for phase vocoder
+ \param samplerate sampling rate of the input signal
+
+ \return newly created ::aubio_notes_t
+
+*/
+aubio_notes_t * new_aubio_notes (const char_t * method,
+ uint_t buf_size, uint_t hop_size, uint_t samplerate);
+
+/** delete notes detection object
+
+ \param o notes detection object to delete
+
+*/
+void del_aubio_notes(aubio_notes_t * o);
+
+/** execute note detection on an input signal frame
+
+ \param o note detection object as returned by new_aubio_notes()
+ \param input input signal of size [hop_size]
+ \param output output notes, fvec of length 3
+
+ The notes output is a vector of length 3 containing:
+ - 0. the midi note value, or 0 if no note was found
+ - 1. the note velocity
+ - 2. the midi note to turn off
+
+*/
+void aubio_notes_do (aubio_notes_t *o, const fvec_t * input, fvec_t * output);
+
+/** set notes detection silence threshold
+
+ \param o notes detection object as returned by new_aubio_notes()
+ \param silence new silence detection threshold
+
+ \return 0 on success, non-zero otherwise
+
+*/
+uint_t aubio_notes_set_silence(aubio_notes_t * o, smpl_t silence);
+
+/** get notes detection silence threshold
+
+ \param o notes detection object as returned by new_aubio_notes()
+
+ \return current silence threshold
+
+*/
+smpl_t aubio_notes_get_silence(const aubio_notes_t * o);
+
+/** get notes detection minimum inter-onset interval, in millisecond
+
+ \param o notes detection object as returned by new_aubio_notes()
+
+ \return current minimum inter onset interval
+
+ */
+smpl_t aubio_notes_get_minioi_ms(const aubio_notes_t *o);
+
+/** set notes detection minimum inter-onset interval, in millisecond
+
+ \param o notes detection object as returned by new_aubio_notes()
+ \param minioi_ms new inter-onset interval
+
+ \return 0 on success, non-zero otherwise
+
+*/
+uint_t aubio_notes_set_minioi_ms (aubio_notes_t *o, smpl_t minioi_ms);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _AUBIO_NOTES_H */
};
/* execute onset detection function on iput buffer */
-void aubio_onset_do (aubio_onset_t *o, fvec_t * input, fvec_t * onset)
+void aubio_onset_do (aubio_onset_t *o, const fvec_t * input, fvec_t * onset)
{
smpl_t isonset = 0;
aubio_pvoc_do (o->pv,input, o->fftgrain);
return;
}
-uint_t aubio_onset_get_last (aubio_onset_t *o)
+uint_t aubio_onset_get_last (const aubio_onset_t *o)
{
return o->last_onset - o->delay;
}
-smpl_t aubio_onset_get_last_s (aubio_onset_t *o)
+smpl_t aubio_onset_get_last_s (const aubio_onset_t *o)
{
return aubio_onset_get_last (o) / (smpl_t) (o->samplerate);
}
-smpl_t aubio_onset_get_last_ms (aubio_onset_t *o)
+smpl_t aubio_onset_get_last_ms (const aubio_onset_t *o)
{
return aubio_onset_get_last_s (o) * 1000.;
}
return AUBIO_OK;
}
-smpl_t aubio_onset_get_silence(aubio_onset_t * o) {
+smpl_t aubio_onset_get_silence(const aubio_onset_t * o) {
return o->silence;
}
return AUBIO_OK;
}
-smpl_t aubio_onset_get_threshold(aubio_onset_t * o) {
+smpl_t aubio_onset_get_threshold(const aubio_onset_t * o) {
return aubio_peakpicker_get_threshold(o->pp);
}
return AUBIO_OK;
}
-uint_t aubio_onset_get_minioi(aubio_onset_t * o) {
+uint_t aubio_onset_get_minioi(const aubio_onset_t * o) {
return o->minioi;
}
uint_t aubio_onset_set_minioi_s(aubio_onset_t * o, smpl_t minioi) {
- return aubio_onset_set_minioi (o, minioi * o->samplerate);
+ return aubio_onset_set_minioi (o, (uint_t)ROUND(minioi * o->samplerate));
}
-smpl_t aubio_onset_get_minioi_s(aubio_onset_t * o) {
+smpl_t aubio_onset_get_minioi_s(const aubio_onset_t * o) {
return aubio_onset_get_minioi (o) / (smpl_t) o->samplerate;
}
return aubio_onset_set_minioi_s (o, minioi / 1000.);
}
-smpl_t aubio_onset_get_minioi_ms(aubio_onset_t * o) {
+smpl_t aubio_onset_get_minioi_ms(const aubio_onset_t * o) {
return aubio_onset_get_minioi_s (o) * 1000.;
}
return AUBIO_OK;
}
-uint_t aubio_onset_get_delay(aubio_onset_t * o) {
+uint_t aubio_onset_get_delay(const aubio_onset_t * o) {
return o->delay;
}
return aubio_onset_set_delay (o, delay * o->samplerate);
}
-smpl_t aubio_onset_get_delay_s(aubio_onset_t * o) {
+smpl_t aubio_onset_get_delay_s(const aubio_onset_t * o) {
return aubio_onset_get_delay (o) / (smpl_t) o->samplerate;
}
return aubio_onset_set_delay_s (o, delay / 1000.);
}
-smpl_t aubio_onset_get_delay_ms(aubio_onset_t * o) {
+smpl_t aubio_onset_get_delay_ms(const aubio_onset_t * o) {
return aubio_onset_get_delay_s (o) * 1000.;
}
-smpl_t aubio_onset_get_descriptor(aubio_onset_t * o) {
+smpl_t aubio_onset_get_descriptor(const aubio_onset_t * o) {
return o->desc->data[0];
}
-smpl_t aubio_onset_get_thresholded_descriptor(aubio_onset_t * o) {
+smpl_t aubio_onset_get_thresholded_descriptor(const aubio_onset_t * o) {
fvec_t * thresholded = aubio_peakpicker_get_thresholded_input(o->pp);
return thresholded->data[0];
}
/* Allocate memory for an onset detection */
-aubio_onset_t * new_aubio_onset (char_t * onset_mode,
+aubio_onset_t * new_aubio_onset (const char_t * onset_mode,
uint_t buf_size, uint_t hop_size, uint_t samplerate)
{
aubio_onset_t * o = AUBIO_NEW(aubio_onset_t);
if ((sint_t)hop_size < 1) {
AUBIO_ERR("onset: got hop_size %d, but can not be < 1\n", hop_size);
goto beach;
- } else if ((sint_t)buf_size < 1) {
- AUBIO_ERR("onset: got buffer_size %d, but can not be < 1\n", buf_size);
+ } else if ((sint_t)buf_size < 2) {
+ AUBIO_ERR("onset: got buffer_size %d, but can not be < 2\n", buf_size);
goto beach;
} else if (buf_size < hop_size) {
- AUBIO_ERR("onset: hop size (%d) is larger than win size (%d)\n", buf_size, hop_size);
+ AUBIO_ERR("onset: hop size (%d) is larger than win size (%d)\n", hop_size, buf_size);
goto beach;
} else if ((sint_t)samplerate < 1) {
AUBIO_ERR("onset: samplerate (%d) can not be < 1\n", samplerate);
o->pv = new_aubio_pvoc(buf_size, o->hop_size);
o->pp = new_aubio_peakpicker();
o->od = new_aubio_specdesc(onset_mode,buf_size);
+ if (o->od == NULL) goto beach_specdesc;
o->fftgrain = new_cvec(buf_size);
o->desc = new_fvec(1);
o->total_frames = 0;
return o;
+beach_specdesc:
+ del_aubio_peakpicker(o->pp);
+ del_aubio_pvoc(o->pv);
beach:
AUBIO_FREE(o);
return NULL;
*/
-#ifndef _AUBIO_ONSET_H
-#define _AUBIO_ONSET_H
+#ifndef AUBIO_ONSET_H
+#define AUBIO_ONSET_H
#ifdef __cplusplus
extern "C" {
\return newly created ::aubio_onset_t
*/
-aubio_onset_t * new_aubio_onset (char_t * method,
+aubio_onset_t * new_aubio_onset (const char_t * method,
uint_t buf_size, uint_t hop_size, uint_t samplerate);
/** execute onset detection
aubio_onset_get_delay().
*/
-void aubio_onset_do (aubio_onset_t *o, fvec_t * input, fvec_t * onset);
+void aubio_onset_do (aubio_onset_t *o, const fvec_t * input, fvec_t * onset);
/** get the time of the latest onset detected, in samples
\return onset detection timestamps (in samples)
*/
-uint_t aubio_onset_get_last (aubio_onset_t *o);
+uint_t aubio_onset_get_last (const aubio_onset_t *o);
/** get the time of the latest onset detected, in seconds
\return onset detection timestamps (in seconds)
*/
-smpl_t aubio_onset_get_last_s (aubio_onset_t *o);
+smpl_t aubio_onset_get_last_s (const aubio_onset_t *o);
/** get the time of the latest onset detected, in milliseconds
\return onset detection timestamps (in milliseconds)
*/
-smpl_t aubio_onset_get_last_ms (aubio_onset_t *o);
+smpl_t aubio_onset_get_last_ms (const aubio_onset_t *o);
/** set onset detection adaptive whitening
\return current silence threshold
*/
-smpl_t aubio_onset_get_silence(aubio_onset_t * o);
+smpl_t aubio_onset_get_silence(const aubio_onset_t * o);
/** get onset detection function
\return the current value of the descriptor
*/
-smpl_t aubio_onset_get_descriptor ( aubio_onset_t *o);
+smpl_t aubio_onset_get_descriptor (const aubio_onset_t *o);
/** get thresholded onset detection function
\return the value of the thresholded descriptor
*/
-smpl_t aubio_onset_get_thresholded_descriptor ( aubio_onset_t *o);
+smpl_t aubio_onset_get_thresholded_descriptor (const aubio_onset_t *o);
/** set onset detection peak picking threshold
samples)
*/
-uint_t aubio_onset_get_minioi(aubio_onset_t * o);
+uint_t aubio_onset_get_minioi(const aubio_onset_t * o);
/** get minimum inter onset interval in seconds
seconds)
*/
-smpl_t aubio_onset_get_minioi_s(aubio_onset_t * o);
+smpl_t aubio_onset_get_minioi_s(const aubio_onset_t * o);
/** get minimum inter onset interval in milliseconds
milliseconds)
*/
-smpl_t aubio_onset_get_minioi_ms(aubio_onset_t * o);
+smpl_t aubio_onset_get_minioi_ms(const aubio_onset_t * o);
/** get delay in samples
(in samples)
*/
-uint_t aubio_onset_get_delay(aubio_onset_t * o);
+uint_t aubio_onset_get_delay(const aubio_onset_t * o);
/** get delay in seconds
(in seconds)
*/
-smpl_t aubio_onset_get_delay_s(aubio_onset_t * o);
+smpl_t aubio_onset_get_delay_s(const aubio_onset_t * o);
/** get delay in milliseconds
(in milliseconds)
*/
-smpl_t aubio_onset_get_delay_ms(aubio_onset_t * o);
+smpl_t aubio_onset_get_delay_ms(const aubio_onset_t * o);
/** get onset peak picking threshold
\return current onset detection threshold
*/
-smpl_t aubio_onset_get_threshold(aubio_onset_t * o);
+smpl_t aubio_onset_get_threshold(const aubio_onset_t * o);
/** delete onset detection object
}
#endif
-#endif /* _AUBIO_ONSET_H */
+#endif /* AUBIO_ONSET_H */
generated with octave butter function: [b,a] = butter(2, 0.34);
*/
t->biquad = new_aubio_filter_biquad (0.15998789, 0.31997577, 0.15998789,
- -0.59488894, 0.23484048);
+ // FIXME: broken since c9e20ca, revert for now
+ //-0.59488894, 0.23484048);
+ 0.23484048, 0);
return t;
}
*/
-#ifndef _AUBIO_PEAKPICK_H
-#define _AUBIO_PEAKPICK_H
+#ifndef AUBIO_PEAKPICK_H
+#define AUBIO_PEAKPICK_H
#ifdef __cplusplus
extern "C" {
}
#endif
-#endif /* _AUBIO_PEAKPICK_H */
+#endif /* AUBIO_PEAKPICK_H */
} aubio_pitch_mode;
/** callback to get pitch candidate, defined below */
-typedef void (*aubio_pitch_detect_t) (aubio_pitch_t * p, fvec_t * ibuf, fvec_t * obuf);
+typedef void (*aubio_pitch_detect_t) (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf);
/** callback to convert pitch from one unit to another, defined below */
typedef smpl_t(*aubio_pitch_convert_t) (smpl_t value, uint_t samplerate, uint_t bufsize);
uint_t bufsize; /**< buffer size */
void *p_object; /**< pointer to pitch object */
aubio_filter_t *filter; /**< filter */
+ fvec_t *filtered; /**< filtered input */
aubio_pvoc_t *pv; /**< phase vocoder for mcomb */
cvec_t *fftgrain; /**< spectral frame for mcomb */
fvec_t *buf; /**< temporary buffer for yin */
};
/* callback functions for pitch detection */
-static void aubio_pitch_do_mcomb (aubio_pitch_t * p, fvec_t * ibuf, fvec_t * obuf);
-static void aubio_pitch_do_yin (aubio_pitch_t * p, fvec_t * ibuf, fvec_t * obuf);
-static void aubio_pitch_do_schmitt (aubio_pitch_t * p, fvec_t * ibuf, fvec_t * obuf);
-static void aubio_pitch_do_fcomb (aubio_pitch_t * p, fvec_t * ibuf, fvec_t * obuf);
-static void aubio_pitch_do_yinfft (aubio_pitch_t * p, fvec_t * ibuf, fvec_t * obuf);
-static void aubio_pitch_do_specacf (aubio_pitch_t * p, fvec_t * ibuf, fvec_t * obuf);
-
-/* conversion functions for frequency conversions */
-smpl_t freqconvbin (smpl_t f, uint_t samplerate, uint_t bufsize);
-smpl_t freqconvmidi (smpl_t f, uint_t samplerate, uint_t bufsize);
-smpl_t freqconvpass (smpl_t f, uint_t samplerate, uint_t bufsize);
+static void aubio_pitch_do_mcomb (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf);
+static void aubio_pitch_do_yin (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf);
+static void aubio_pitch_do_schmitt (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf);
+static void aubio_pitch_do_fcomb (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf);
+static void aubio_pitch_do_yinfft (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf);
+static void aubio_pitch_do_specacf (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf);
+
+/* internal functions for frequency conversion */
+static smpl_t freqconvbin (smpl_t f, uint_t samplerate, uint_t bufsize);
+static smpl_t freqconvmidi (smpl_t f, uint_t samplerate, uint_t bufsize);
+static smpl_t freqconvpass (smpl_t f, uint_t samplerate, uint_t bufsize);
/* adapter to stack ibuf new samples at the end of buf, and trim `buf` to `bufsize` */
-void aubio_pitch_slideblock (aubio_pitch_t * p, fvec_t * ibuf);
+void aubio_pitch_slideblock (aubio_pitch_t * p, const fvec_t * ibuf);
aubio_pitch_t *
-new_aubio_pitch (char_t * pitch_mode,
+new_aubio_pitch (const char_t * pitch_mode,
uint_t bufsize, uint_t hopsize, uint_t samplerate)
{
aubio_pitch_t *p = AUBIO_NEW (aubio_pitch_t);
aubio_pitch_type pitch_type;
+ if (pitch_mode == NULL) {
+ AUBIO_ERR ("pitch: can not use ‘NULL‘ for pitch detection method\n");
+ goto beach;
+ }
if (strcmp (pitch_mode, "mcomb") == 0)
pitch_type = aubio_pitcht_mcomb;
else if (strcmp (pitch_mode, "yinfft") == 0)
else if (strcmp (pitch_mode, "default") == 0)
pitch_type = aubio_pitcht_default;
else {
- AUBIO_ERR ("unknown pitch detection method %s, using default.\n",
- pitch_mode);
- pitch_type = aubio_pitcht_default;
+ AUBIO_ERR ("pitch: unknown pitch detection method ‘%s’\n", pitch_mode);
+ goto beach;
}
// check parameters are valid
if ((sint_t)hopsize < 1) {
- AUBIO_ERR("onset: got hopsize %d, but can not be < 1\n", hopsize);
+ AUBIO_ERR("pitch: got hopsize %d, but can not be < 1\n", hopsize);
goto beach;
} else if ((sint_t)bufsize < 1) {
- AUBIO_ERR("onset: got buffer_size %d, but can not be < 1\n", bufsize);
+ AUBIO_ERR("pitch: got buffer_size %d, but can not be < 1\n", bufsize);
goto beach;
} else if (bufsize < hopsize) {
- AUBIO_ERR("onset: hop size (%d) is larger than win size (%d)\n", bufsize, hopsize);
+ AUBIO_ERR("pitch: hop size (%d) is larger than win size (%d)\n", hopsize, bufsize);
goto beach;
} else if ((sint_t)samplerate < 1) {
- AUBIO_ERR("onset: samplerate (%d) can not be < 1\n", samplerate);
+ AUBIO_ERR("pitch: samplerate (%d) can not be < 1\n", samplerate);
goto beach;
}
case aubio_pitcht_yin:
p->buf = new_fvec (bufsize);
p->p_object = new_aubio_pitchyin (bufsize);
+ if (!p->p_object) goto beach;
p->detect_cb = aubio_pitch_do_yin;
p->conf_cb = (aubio_pitch_get_conf_t)aubio_pitchyin_get_confidence;
aubio_pitchyin_set_tolerance (p->p_object, 0.15);
break;
case aubio_pitcht_mcomb:
+ p->filtered = new_fvec (hopsize);
p->pv = new_aubio_pvoc (bufsize, hopsize);
+ if (!p->pv) goto beach;
p->fftgrain = new_cvec (bufsize);
p->p_object = new_aubio_pitchmcomb (bufsize, hopsize);
p->filter = new_aubio_filter_c_weighting (samplerate);
case aubio_pitcht_fcomb:
p->buf = new_fvec (bufsize);
p->p_object = new_aubio_pitchfcomb (bufsize, hopsize);
+ if (!p->p_object) goto beach;
p->detect_cb = aubio_pitch_do_fcomb;
break;
case aubio_pitcht_schmitt:
case aubio_pitcht_yinfft:
p->buf = new_fvec (bufsize);
p->p_object = new_aubio_pitchyinfft (samplerate, bufsize);
+ if (!p->p_object) goto beach;
p->detect_cb = aubio_pitch_do_yinfft;
p->conf_cb = (aubio_pitch_get_conf_t)aubio_pitchyinfft_get_confidence;
aubio_pitchyinfft_set_tolerance (p->p_object, 0.85);
case aubio_pitcht_specacf:
p->buf = new_fvec (bufsize);
p->p_object = new_aubio_pitchspecacf (bufsize);
+ if (!p->p_object) goto beach;
p->detect_cb = aubio_pitch_do_specacf;
p->conf_cb = (aubio_pitch_get_conf_t)aubio_pitchspecacf_get_tolerance;
aubio_pitchspecacf_set_tolerance (p->p_object, 0.85);
return p;
beach:
+ if (p->filtered) del_fvec(p->filtered);
+ if (p->buf) del_fvec(p->buf);
AUBIO_FREE(p);
return NULL;
}
del_aubio_pitchyin (p->p_object);
break;
case aubio_pitcht_mcomb:
+ del_fvec (p->filtered);
del_aubio_pvoc (p->pv);
del_cvec (p->fftgrain);
del_aubio_filter (p->filter);
}
void
-aubio_pitch_slideblock (aubio_pitch_t * p, fvec_t * ibuf)
+aubio_pitch_slideblock (aubio_pitch_t * p, const fvec_t * ibuf)
{
uint_t overlap_size = p->buf->length - ibuf->length;
#if 1 //!HAVE_MEMCPY_HACKS
}
uint_t
-aubio_pitch_set_unit (aubio_pitch_t * p, char_t * pitch_unit)
+aubio_pitch_set_unit (aubio_pitch_t * p, const char_t * pitch_unit)
{
uint_t err = AUBIO_OK;
aubio_pitch_mode pitch_mode;
else if (strcmp (pitch_unit, "default") == 0)
pitch_mode = aubio_pitchm_default;
else {
- AUBIO_ERR ("unknown pitch detection unit %s, using default\n", pitch_unit);
+ AUBIO_WRN("pitch: unknown pitch detection unit ‘%s’, using default\n",
+ pitch_unit);
pitch_mode = aubio_pitchm_default;
err = AUBIO_FAIL;
}
return AUBIO_OK;
}
+smpl_t
+aubio_pitch_get_tolerance (aubio_pitch_t * p)
+{
+ smpl_t tolerance = 1.;
+ switch (p->type) {
+ case aubio_pitcht_yin:
+ tolerance = aubio_pitchyin_get_tolerance (p->p_object);
+ break;
+ case aubio_pitcht_yinfft:
+ tolerance = aubio_pitchyinfft_get_tolerance (p->p_object);
+ break;
+ default:
+ break;
+ }
+ return tolerance;
+}
+
uint_t
aubio_pitch_set_silence (aubio_pitch_t * p, smpl_t silence)
{
p->silence = silence;
return AUBIO_OK;
} else {
- AUBIO_ERR("pitch: could not set silence to %.2f", silence);
+ AUBIO_WRN("pitch: could not set silence to %.2f\n", silence);
return AUBIO_FAIL;
}
}
/* do method, calling the detection callback, then the conversion callback */
void
-aubio_pitch_do (aubio_pitch_t * p, fvec_t * ibuf, fvec_t * obuf)
+aubio_pitch_do (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf)
{
p->detect_cb (p, ibuf, obuf);
if (aubio_silence_detection(ibuf, p->silence) == 1) {
/* do method for each algorithm */
void
-aubio_pitch_do_mcomb (aubio_pitch_t * p, fvec_t * ibuf, fvec_t * obuf)
+aubio_pitch_do_mcomb (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf)
{
- aubio_filter_do (p->filter, ibuf);
+ aubio_filter_do_outplace (p->filter, ibuf, p->filtered);
aubio_pvoc_do (p->pv, ibuf, p->fftgrain);
aubio_pitchmcomb_do (p->p_object, p->fftgrain, obuf);
obuf->data[0] = aubio_bintofreq (obuf->data[0], p->samplerate, p->bufsize);
}
void
-aubio_pitch_do_yin (aubio_pitch_t * p, fvec_t * ibuf, fvec_t * obuf)
+aubio_pitch_do_yin (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf)
{
smpl_t pitch = 0.;
aubio_pitch_slideblock (p, ibuf);
void
-aubio_pitch_do_yinfft (aubio_pitch_t * p, fvec_t * ibuf, fvec_t * obuf)
+aubio_pitch_do_yinfft (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf)
{
smpl_t pitch = 0.;
aubio_pitch_slideblock (p, ibuf);
}
void
-aubio_pitch_do_specacf (aubio_pitch_t * p, fvec_t * ibuf, fvec_t * out)
+aubio_pitch_do_specacf (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * out)
{
smpl_t pitch = 0., period;
aubio_pitch_slideblock (p, ibuf);
}
void
-aubio_pitch_do_fcomb (aubio_pitch_t * p, fvec_t * ibuf, fvec_t * out)
+aubio_pitch_do_fcomb (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * out)
{
aubio_pitch_slideblock (p, ibuf);
aubio_pitchfcomb_do (p->p_object, p->buf, out);
}
void
-aubio_pitch_do_schmitt (aubio_pitch_t * p, fvec_t * ibuf, fvec_t * out)
+aubio_pitch_do_schmitt (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * out)
{
smpl_t period, pitch = 0.;
aubio_pitch_slideblock (p, ibuf);
*/
-#ifndef _AUBIO_PITCH_H
-#define _AUBIO_PITCH_H
+#ifndef AUBIO_PITCH_H
+#define AUBIO_PITCH_H
#ifdef __cplusplus
extern "C" {
\param out output pitch candidates of size [1]
*/
-void aubio_pitch_do (aubio_pitch_t * o, fvec_t * in, fvec_t * out);
+void aubio_pitch_do (aubio_pitch_t * o, const fvec_t * in, fvec_t * out);
/** change yin or yinfft tolerance threshold
*/
uint_t aubio_pitch_set_tolerance (aubio_pitch_t * o, smpl_t tol);
+/** get yin or yinfft tolerance threshold
+
+ \param o pitch detection object as returned by new_aubio_pitch()
+ \return tolerance (default is 0.15 for yin and 0.85 for yinfft)
+
+*/
+smpl_t aubio_pitch_get_tolerance (aubio_pitch_t * o);
+
/** deletion of the pitch detection object
\param o pitch detection object as returned by new_aubio_pitch()
\return newly created ::aubio_pitch_t
*/
-aubio_pitch_t *new_aubio_pitch (char_t * method,
+aubio_pitch_t *new_aubio_pitch (const char_t * method,
uint_t buf_size, uint_t hop_size, uint_t samplerate);
/** set the output unit of the pitch detection object
\param o pitch detection object as returned by new_aubio_pitch()
\param mode set pitch units for output
+ mode can be one of "Hz", "midi", "cent", or "bin". Defaults to "Hz".
+
\return 0 if successfull, non-zero otherwise
*/
-uint_t aubio_pitch_set_unit (aubio_pitch_t * o, char_t * mode);
+uint_t aubio_pitch_set_unit (aubio_pitch_t * o, const char_t * mode);
/** set the silence threshold of the pitch detection object
}
#endif
-#endif /* _AUBIO_PITCH_H */
+#endif /* AUBIO_PITCH_H */
aubio_pitchfcomb_t *p = AUBIO_NEW (aubio_pitchfcomb_t);
p->fftSize = bufsize;
p->stepSize = hopsize;
+ p->fft = new_aubio_fft (bufsize);
+ if (!p->fft) goto beach;
p->winput = new_fvec (bufsize);
p->fftOut = new_cvec (bufsize);
p->fftLastPhase = new_fvec (bufsize);
- p->fft = new_aubio_fft (bufsize);
p->win = new_aubio_window ("hanning", bufsize);
return p;
+
+beach:
+ AUBIO_FREE(p);
+ return NULL;
}
/* input must be stepsize long */
void
-aubio_pitchfcomb_do (aubio_pitchfcomb_t * p, fvec_t * input, fvec_t * output)
+aubio_pitchfcomb_do (aubio_pitchfcomb_t * p, const fvec_t * input, fvec_t * output)
{
uint_t k, l, maxharm = 0;
smpl_t phaseDifference = TWO_PI * (smpl_t) p->stepSize / (smpl_t) p->fftSize;
*/
-#ifndef _AUBIO_PITCHFCOMB_H
-#define _AUBIO_PITCHFCOMB_H
+#ifndef AUBIO_PITCHFCOMB_H
+#define AUBIO_PITCHFCOMB_H
#ifdef __cplusplus
extern "C" {
\param output pitch candidates in bins
*/
-void aubio_pitchfcomb_do (aubio_pitchfcomb_t * p, fvec_t * input,
+void aubio_pitchfcomb_do (aubio_pitchfcomb_t * p, const fvec_t * input,
fvec_t * output);
/** creation of the pitch detection object
}
#endif
-#endif /* _AUBIO_PITCHFCOMB_H */
+#endif /* AUBIO_PITCHFCOMB_H */
uint_t aubio_pitchmcomb_get_root_peak (aubio_spectralpeak_t * peaks,
uint_t length);
uint_t aubio_pitchmcomb_quadpick (aubio_spectralpeak_t * spectral_peaks,
- fvec_t * X);
-void aubio_pitchmcomb_spectral_pp (aubio_pitchmcomb_t * p, fvec_t * oldmag);
-void aubio_pitchmcomb_combdet (aubio_pitchmcomb_t * p, fvec_t * newmag);
+ const fvec_t * X);
+void aubio_pitchmcomb_spectral_pp (aubio_pitchmcomb_t * p, const fvec_t * oldmag);
+void aubio_pitchmcomb_combdet (aubio_pitchmcomb_t * p, const fvec_t * newmag);
/* not used but useful : sort by amplitudes (or anything else)
* sort_pitchpeak(peaks, length);
*/
/** sort spectral_peak against their mag */
void aubio_pitchmcomb_sort_peak (aubio_spectralpeak_t * peaks, uint_t nbins);
/** select the best candidates */
-uint_t aubio_pitch_cands (aubio_pitchmcomb_t * p, cvec_t * fftgrain,
+uint_t aubio_pitch_cands (aubio_pitchmcomb_t * p, const cvec_t * fftgrain,
smpl_t * cands);
/** sort spectral_candidate against their comb ene */
void
-aubio_pitchmcomb_do (aubio_pitchmcomb_t * p, cvec_t * fftgrain, fvec_t * output)
+aubio_pitchmcomb_do (aubio_pitchmcomb_t * p, const cvec_t * fftgrain, fvec_t * output)
{
uint_t j;
smpl_t instfreq;
}
uint_t
-aubio_pitch_cands (aubio_pitchmcomb_t * p, cvec_t * fftgrain, smpl_t * cands)
+aubio_pitch_cands (aubio_pitchmcomb_t * p, const cvec_t * fftgrain, smpl_t * cands)
{
uint_t j;
uint_t k;
}
void
-aubio_pitchmcomb_spectral_pp (aubio_pitchmcomb_t * p, fvec_t * newmag)
+aubio_pitchmcomb_spectral_pp (aubio_pitchmcomb_t * p, const fvec_t * newmag)
{
fvec_t *mag = (fvec_t *) p->scratch;
fvec_t *tmp = (fvec_t *) p->scratch2;
}
void
-aubio_pitchmcomb_combdet (aubio_pitchmcomb_t * p, fvec_t * newmag)
+aubio_pitchmcomb_combdet (aubio_pitchmcomb_t * p, const fvec_t * newmag)
{
aubio_spectralpeak_t *peaks = (aubio_spectralpeak_t *) p->peaks;
aubio_spectralcandidate_t **candidate =
* \bug peak-picking too picky, sometimes counts too many peaks ?
*/
uint_t
-aubio_pitchmcomb_quadpick (aubio_spectralpeak_t * spectral_peaks, fvec_t * X)
+aubio_pitchmcomb_quadpick (aubio_spectralpeak_t * spectral_peaks, const fvec_t * X)
{
uint_t j, ispeak, count = 0;
for (j = 1; j < X->length - 1; j++) {
/* bug: should check if size / 8 > post+pre+1 */
uint_t i, j;
uint_t spec_size;
- p->spec_partition = 4;
+ p->spec_partition = 2;
p->ncand = 5;
p->npartials = 5;
p->cutoff = 1.;
p->goodcandidate = 0;
p->phasefreq = bufsize / hopsize / TWO_PI;
p->phasediff = TWO_PI * hopsize / bufsize;
- spec_size = bufsize / p->spec_partition;
+ spec_size = bufsize / p->spec_partition + 1;
//p->pickerfn = quadpick;
//p->biquad = new_biquad(0.1600,0.3200,0.1600, -0.5949, 0.2348);
/* allocate temp memory */
*/
-#ifndef _AUBIO_PITCHMCOMB_H
-#define _AUBIO_PITCHMCOMB_H
+#ifndef AUBIO_PITCHMCOMB_H
+#define AUBIO_PITCHMCOMB_H
#ifdef __cplusplus
extern "C" {
\param out_cands pitch candidate frequenciess, in bins
*/
-void aubio_pitchmcomb_do (aubio_pitchmcomb_t * p, cvec_t * in_fftgrain,
+void aubio_pitchmcomb_do (aubio_pitchmcomb_t * p, const cvec_t * in_fftgrain,
fvec_t * out_cands);
/** creation of the pitch detection object
}
#endif
-#endif /* _AUBIO_PITCHMCOMB_H */
+#endif /* AUBIO_PITCHMCOMB_H */
}
void
-aubio_pitchschmitt_do (aubio_pitchschmitt_t * p, fvec_t * input,
+aubio_pitchschmitt_do (aubio_pitchschmitt_t * p, const fvec_t * input,
fvec_t * output)
{
uint_t j;
*/
-#ifndef _AUBIO_PITCHSCHMITT_H
-#define _AUBIO_PITCHSCHMITT_H
+#ifndef AUBIO_PITCHSCHMITT_H
+#define AUBIO_PITCHSCHMITT_H
#ifdef __cplusplus
extern "C" {
\param cands_out pitch period estimates, in samples
*/
-void aubio_pitchschmitt_do (aubio_pitchschmitt_t * p, fvec_t * samples_in,
+void aubio_pitchschmitt_do (aubio_pitchschmitt_t * p, const fvec_t * samples_in,
fvec_t * cands_out);
/** creation of the pitch detection object
}
#endif
-#endif /* _AUBIO_PITCHSCHMITT_H */
-
+#endif /* AUBIO_PITCHSCHMITT_H */
new_aubio_pitchspecacf (uint_t bufsize)
{
aubio_pitchspecacf_t *p = AUBIO_NEW (aubio_pitchspecacf_t);
+ p->fft = new_aubio_fft (bufsize);
+ if (!p->fft) goto beach;
p->win = new_aubio_window ("hanningz", bufsize);
p->winput = new_fvec (bufsize);
- p->fft = new_aubio_fft (bufsize);
p->fftout = new_fvec (bufsize);
p->sqrmag = new_fvec (bufsize);
p->acf = new_fvec (bufsize / 2 + 1);
p->tol = 1.;
p->confidence = 0.;
return p;
+
+beach:
+ AUBIO_FREE(p);
+ return NULL;
}
void
-aubio_pitchspecacf_do (aubio_pitchspecacf_t * p, fvec_t * input, fvec_t * output)
+aubio_pitchspecacf_do (aubio_pitchspecacf_t * p, const fvec_t * input, fvec_t * output)
{
uint_t l, tau;
fvec_t *fftout = p->fftout;
}
smpl_t
-aubio_pitchspecacf_get_confidence (aubio_pitchspecacf_t * o) {
+aubio_pitchspecacf_get_confidence (const aubio_pitchspecacf_t * o) {
// no confidence for now
return o->confidence;
}
}
smpl_t
-aubio_pitchspecacf_get_tolerance (aubio_pitchspecacf_t * p)
+aubio_pitchspecacf_get_tolerance (const aubio_pitchspecacf_t * p)
{
return p->tol;
}
*/
-#ifndef _AUBIO_PITCHSPECACF_H
-#define _AUBIO_PITCHSPECACF_H
+#ifndef AUBIO_PITCHSPECACF_H
+#define AUBIO_PITCHSPECACF_H
#ifdef __cplusplus
extern "C" {
\param cands_out pitch period candidates, in samples
*/
-void aubio_pitchspecacf_do (aubio_pitchspecacf_t * o, fvec_t * samples_in, fvec_t * cands_out);
+void aubio_pitchspecacf_do (aubio_pitchspecacf_t * o, const fvec_t * samples_in, fvec_t * cands_out);
/** creation of the pitch detection object
\param buf_size size of the input buffer to analyse
\return tolerance parameter for minima selection [default 1.]
*/
-smpl_t aubio_pitchspecacf_get_tolerance (aubio_pitchspecacf_t * o);
+smpl_t aubio_pitchspecacf_get_tolerance (const aubio_pitchspecacf_t * o);
/** set tolerance parameter for `specacf` pitch detection object
\return confidence parameter
*/
-smpl_t aubio_pitchspecacf_get_confidence (aubio_pitchspecacf_t * o);
+smpl_t aubio_pitchspecacf_get_confidence (const aubio_pitchspecacf_t * o);
#ifdef __cplusplus
}
#endif
-#endif /* _AUBIO_PITCHSPECACF_H */
+#endif /* AUBIO_PITCHSPECACF_H */
};
/** compute difference function
-
- \param input input signal
+
+ \param input input signal
\param yinbuf output buffer to store difference function (half shorter than input)
*/
void aubio_pitchyin_diff (fvec_t * input, fvec_t * yinbuf);
-/** in place computation of the YIN cumulative normalised function
-
- \param yinbuf input signal (a square difference function), also used to store function
+/** in place computation of the YIN cumulative normalised function
+
+ \param yinbuf input signal (a square difference function), also used to store function
*/
void aubio_pitchyin_getcum (fvec_t * yinbuf);
/** detect pitch in a YIN function
-
+
\param yinbuf input buffer as computed by aubio_pitchyin_getcum
*/
-uint_t aubio_pitchyin_getpitch (fvec_t * yinbuf);
+uint_t aubio_pitchyin_getpitch (const fvec_t * yinbuf);
aubio_pitchyin_t *
new_aubio_pitchyin (uint_t bufsize)
}
uint_t
-aubio_pitchyin_getpitch (fvec_t * yin)
+aubio_pitchyin_getpitch (const fvec_t * yin)
{
uint_t tau = 1;
do {
return 0;
}
-
/* all the above in one */
void
-aubio_pitchyin_do (aubio_pitchyin_t * o, fvec_t * input, fvec_t * out)
+aubio_pitchyin_do (aubio_pitchyin_t * o, const fvec_t * input, fvec_t * out)
{
- smpl_t tol = o->tol;
- fvec_t *yin = o->yin;
- uint_t j, tau = 0;
+ const smpl_t tol = o->tol;
+ fvec_t* yin = o->yin;
+ const smpl_t *input_data = input->data;
+ const uint_t length = yin->length;
+ smpl_t *yin_data = yin->data;
+ uint_t j, tau;
sint_t period;
- smpl_t tmp = 0., tmp2 = 0.;
- yin->data[0] = 1.;
- for (tau = 1; tau < yin->length; tau++) {
- yin->data[tau] = 0.;
- for (j = 0; j < yin->length; j++) {
- tmp = input->data[j] - input->data[j + tau];
- yin->data[tau] += SQR (tmp);
+ smpl_t tmp, tmp2 = 0.;
+
+ yin_data[0] = 1.;
+ for (tau = 1; tau < length; tau++) {
+ yin_data[tau] = 0.;
+ for (j = 0; j < length; j++) {
+ tmp = input_data[j] - input_data[j + tau];
+ yin_data[tau] += SQR (tmp);
}
- tmp2 += yin->data[tau];
+ tmp2 += yin_data[tau];
if (tmp2 != 0) {
yin->data[tau] *= tau / tmp2;
} else {
yin->data[tau] = 1.;
}
period = tau - 3;
- if (tau > 4 && (yin->data[period] < tol) &&
- (yin->data[period] < yin->data[period + 1])) {
+ if (tau > 4 && (yin_data[period] < tol) &&
+ (yin_data[period] < yin_data[period + 1])) {
out->data[0] = fvec_quadratic_peak_pos (yin, period);
goto beach;
}
*/
-#ifndef _AUBIO_PITCHYIN_H
-#define _AUBIO_PITCHYIN_H
+#ifndef AUBIO_PITCHYIN_H
+#define AUBIO_PITCHYIN_H
#ifdef __cplusplus
extern "C" {
\param cands_out pitch period candidates, in samples
*/
-void aubio_pitchyin_do (aubio_pitchyin_t * o, fvec_t * samples_in, fvec_t * cands_out);
+void aubio_pitchyin_do (aubio_pitchyin_t * o, const fvec_t * samples_in, fvec_t * cands_out);
/** set tolerance parameter for YIN algorithm
}
#endif
-#endif /* _AUBIO_PITCHYIN_H */
+#endif /* AUBIO_PITCHYIN_H */
aubio_pitchyinfft_t *p = AUBIO_NEW (aubio_pitchyinfft_t);
p->winput = new_fvec (bufsize);
p->fft = new_aubio_fft (bufsize);
+ if (!p->fft) goto beach;
p->fftout = new_fvec (bufsize);
p->sqrmag = new_fvec (bufsize);
p->yinfft = new_fvec (bufsize / 2 + 1);
// check for octave errors above 1300 Hz
p->short_period = (uint_t)ROUND(samplerate / 1300.);
return p;
+
+beach:
+ if (p->winput) del_fvec(p->winput);
+ AUBIO_FREE(p);
+ return NULL;
}
void
-aubio_pitchyinfft_do (aubio_pitchyinfft_t * p, fvec_t * input, fvec_t * output)
+aubio_pitchyinfft_do (aubio_pitchyinfft_t * p, const fvec_t * input, fvec_t * output)
{
uint_t tau, l;
uint_t length = p->fftout->length;
*/
-#ifndef _AUBIO_PITCHYINFFT_H
-#define _AUBIO_PITCHYINFFT_H
+#ifndef AUBIO_PITCHYINFFT_H
+#define AUBIO_PITCHYINFFT_H
#ifdef __cplusplus
extern "C" {
\param cands_out pitch period candidates, in samples
*/
-void aubio_pitchyinfft_do (aubio_pitchyinfft_t * o, fvec_t * samples_in, fvec_t * cands_out);
+void aubio_pitchyinfft_do (aubio_pitchyinfft_t * o, const fvec_t * samples_in, fvec_t * cands_out);
/** creation of the pitch detection object
\param samplerate samplerate of the input signal
}
#endif
-#endif /* _AUBIO_PITCHYINFFT_H */
+#endif /* AUBIO_PITCHYINFFT_H */
#ifdef HAVE_FFTW3F
#if HAVE_AUBIO_DOUBLE
-#warning "Using aubio in double precision with fftw3 in single precision"
+#error "Using aubio in double precision with fftw3 in single precision"
#endif /* HAVE_AUBIO_DOUBLE */
#define real_t float
-#else /* HAVE_FFTW3F */
+#elif defined (HAVE_FFTW3) /* HAVE_FFTW3F */
#if !HAVE_AUBIO_DOUBLE
-#warning "Using aubio in single precision with fftw3 in double precision"
+#error "Using aubio in single precision with fftw3 in double precision"
#endif /* HAVE_AUBIO_DOUBLE */
#define real_t double
#endif /* HAVE_FFTW3F */
#else // using OOURA
// let's use ooura instead
-extern void rdft(int, int, smpl_t *, int *, smpl_t *);
+extern void aubio_ooura_rdft(int, int, smpl_t *, int *, smpl_t *);
#endif /* HAVE_ACCELERATE */
#endif /* HAVE_FFTW3 */
aubio_fft_t * new_aubio_fft (uint_t winsize) {
aubio_fft_t * s = AUBIO_NEW(aubio_fft_t);
- if ((sint_t)winsize < 1) {
- AUBIO_ERR("fft: got winsize %d, but can not be < 1\n", winsize);
+ if ((sint_t)winsize < 2) {
+ AUBIO_ERR("fft: got winsize %d, but can not be < 2\n", winsize);
goto beach;
}
#ifdef HAVE_FFTW3
s->fftSetup = aubio_vDSP_create_fftsetup(s->log2fftsize, FFT_RADIX2);
#else // using OOURA
if (aubio_is_power_of_two(winsize) != 1) {
- AUBIO_ERR("fft: can only create with sizes power of two,"
- " requested %d\n", winsize);
+ AUBIO_ERR("fft: can only create with sizes power of two, requested %d,"
+ " try recompiling aubio with --enable-fftw3\n", winsize);
goto beach;
}
s->winsize = winsize;
/* destroy data */
del_fvec(s->compspec);
#ifdef HAVE_FFTW3 // using FFTW3
+ pthread_mutex_lock(&aubio_fftw_mutex);
fftw_destroy_plan(s->pfw);
fftw_destroy_plan(s->pbw);
fftw_free(s->specdata);
+ pthread_mutex_unlock(&aubio_fftw_mutex);
#else /* HAVE_FFTW3 */
#ifdef HAVE_ACCELERATE // using ACCELERATE
AUBIO_FREE(s->spec.realp);
AUBIO_FREE(s);
}
-void aubio_fft_do(aubio_fft_t * s, fvec_t * input, cvec_t * spectrum) {
+void aubio_fft_do(aubio_fft_t * s, const fvec_t * input, cvec_t * spectrum) {
aubio_fft_do_complex(s, input, s->compspec);
aubio_fft_get_spectrum(s->compspec, spectrum);
}
-void aubio_fft_rdo(aubio_fft_t * s, cvec_t * spectrum, fvec_t * output) {
+void aubio_fft_rdo(aubio_fft_t * s, const cvec_t * spectrum, fvec_t * output) {
aubio_fft_get_realimag(spectrum, s->compspec);
aubio_fft_rdo_complex(s, s->compspec, output);
}
-void aubio_fft_do_complex(aubio_fft_t * s, fvec_t * input, fvec_t * compspec) {
+void aubio_fft_do_complex(aubio_fft_t * s, const fvec_t * input, fvec_t * compspec) {
uint_t i;
#ifndef HAVE_MEMCPY_HACKS
for (i=0; i < s->winsize; i++) {
smpl_t scale = 1./2.;
aubio_vDSP_vsmul(compspec->data, 1, &scale, compspec->data, 1, s->fft_size);
#else // using OOURA
- rdft(s->winsize, 1, s->in, s->ip, s->w);
+ aubio_ooura_rdft(s->winsize, 1, s->in, s->ip, s->w);
compspec->data[0] = s->in[0];
compspec->data[s->winsize / 2] = s->in[1];
for (i = 1; i < s->fft_size - 1; i++) {
#endif /* HAVE_FFTW3 */
}
-void aubio_fft_rdo_complex(aubio_fft_t * s, fvec_t * compspec, fvec_t * output) {
+void aubio_fft_rdo_complex(aubio_fft_t * s, const fvec_t * compspec, fvec_t * output) {
uint_t i;
#ifdef HAVE_FFTW3
const smpl_t renorm = 1./(smpl_t)s->winsize;
s->out[2 * i] = compspec->data[i];
s->out[2 * i + 1] = - compspec->data[s->winsize - i];
}
- rdft(s->winsize, -1, s->out, s->ip, s->w);
+ aubio_ooura_rdft(s->winsize, -1, s->out, s->ip, s->w);
for (i=0; i < s->winsize; i++) {
output->data[i] = s->out[i] * scale;
}
#endif /* HAVE_FFTW3 */
}
-void aubio_fft_get_spectrum(fvec_t * compspec, cvec_t * spectrum) {
+void aubio_fft_get_spectrum(const fvec_t * compspec, cvec_t * spectrum) {
aubio_fft_get_phas(compspec, spectrum);
aubio_fft_get_norm(compspec, spectrum);
}
-void aubio_fft_get_realimag(cvec_t * spectrum, fvec_t * compspec) {
+void aubio_fft_get_realimag(const cvec_t * spectrum, fvec_t * compspec) {
aubio_fft_get_imag(spectrum, compspec);
aubio_fft_get_real(spectrum, compspec);
}
-void aubio_fft_get_phas(fvec_t * compspec, cvec_t * spectrum) {
+void aubio_fft_get_phas(const fvec_t * compspec, cvec_t * spectrum) {
uint_t i;
if (compspec->data[0] < 0) {
spectrum->phas[0] = PI;
}
}
-void aubio_fft_get_norm(fvec_t * compspec, cvec_t * spectrum) {
+void aubio_fft_get_norm(const fvec_t * compspec, cvec_t * spectrum) {
uint_t i = 0;
spectrum->norm[0] = ABS(compspec->data[0]);
for (i=1; i < spectrum->length - 1; i++) {
ABS(compspec->data[compspec->length/2]);
}
-void aubio_fft_get_imag(cvec_t * spectrum, fvec_t * compspec) {
+void aubio_fft_get_imag(const cvec_t * spectrum, fvec_t * compspec) {
uint_t i;
for (i = 1; i < ( compspec->length + 1 ) / 2 /*- 1 + 1*/; i++) {
compspec->data[compspec->length - i] =
}
}
-void aubio_fft_get_real(cvec_t * spectrum, fvec_t * compspec) {
+void aubio_fft_get_real(const cvec_t * spectrum, fvec_t * compspec) {
uint_t i;
for (i = 0; i < compspec->length / 2 + 1; i++) {
compspec->data[i] =
- [FFTW3](http://www.fftw.org)
- [vDSP](https://developer.apple.com/library/mac/#documentation/Accelerate/Reference/vDSPRef/Reference/reference.html)
- \example src/spectral/test-fft.c
+ \example spectral/test-fft.c
*/
-#ifndef _AUBIO_FFT_H
-#define _AUBIO_FFT_H
+#ifndef AUBIO_FFT_H
+#define AUBIO_FFT_H
#ifdef __cplusplus
extern "C" {
\param spectrum output spectrum
*/
-void aubio_fft_do (aubio_fft_t *s, fvec_t * input, cvec_t * spectrum);
+void aubio_fft_do (aubio_fft_t *s, const fvec_t * input, cvec_t * spectrum);
/** compute backward (inverse) FFT
\param s fft object as returned by new_aubio_fft
\param output output signal
*/
-void aubio_fft_rdo (aubio_fft_t *s, cvec_t * spectrum, fvec_t * output);
+void aubio_fft_rdo (aubio_fft_t *s, const cvec_t * spectrum, fvec_t * output);
/** compute forward FFT
\param compspec complex output fft real/imag
*/
-void aubio_fft_do_complex (aubio_fft_t *s, fvec_t * input, fvec_t * compspec);
+void aubio_fft_do_complex (aubio_fft_t *s, const fvec_t * input, fvec_t * compspec);
/** compute backward (inverse) FFT from real/imag
\param s fft object as returned by new_aubio_fft
\param output real output array
*/
-void aubio_fft_rdo_complex (aubio_fft_t *s, fvec_t * compspec, fvec_t * output);
+void aubio_fft_rdo_complex (aubio_fft_t *s, const fvec_t * compspec, fvec_t * output);
/** convert real/imag spectrum to norm/phas spectrum
\param spectrum cvec norm/phas output array
*/
-void aubio_fft_get_spectrum(fvec_t * compspec, cvec_t * spectrum);
+void aubio_fft_get_spectrum(const fvec_t * compspec, cvec_t * spectrum);
/** convert real/imag spectrum to norm/phas spectrum
\param compspec real/imag input fft array
\param spectrum cvec norm/phas output array
*/
-void aubio_fft_get_realimag(cvec_t * spectrum, fvec_t * compspec);
+void aubio_fft_get_realimag(const cvec_t * spectrum, fvec_t * compspec);
/** compute phas spectrum from real/imag parts
\param spectrum cvec norm/phas output array
*/
-void aubio_fft_get_phas(fvec_t * compspec, cvec_t * spectrum);
+void aubio_fft_get_phas(const fvec_t * compspec, cvec_t * spectrum);
/** compute imaginary part from the norm/phas cvec
\param spectrum norm/phas input array
\param compspec real/imag output fft array
*/
-void aubio_fft_get_imag(cvec_t * spectrum, fvec_t * compspec);
+void aubio_fft_get_imag(const cvec_t * spectrum, fvec_t * compspec);
/** compute norm component from real/imag parts
\param spectrum cvec norm/phas output array
*/
-void aubio_fft_get_norm(fvec_t * compspec, cvec_t * spectrum);
+void aubio_fft_get_norm(const fvec_t * compspec, cvec_t * spectrum);
/** compute real part from norm/phas components
\param spectrum norm/phas input array
\param compspec real/imag output fft array
*/
-void aubio_fft_get_real(cvec_t * spectrum, fvec_t * compspec);
+void aubio_fft_get_real(const cvec_t * spectrum, fvec_t * compspec);
#ifdef __cplusplus
}
#endif
-#endif /* _AUBIO_FFT_H */
+#endif /* AUBIO_FFT_H */
}
void
-aubio_filterbank_do (aubio_filterbank_t * f, cvec_t * in, fvec_t * out)
+aubio_filterbank_do (aubio_filterbank_t * f, const cvec_t * in, fvec_t * out)
{
- uint_t j, fn;
-
/* apply filter to all input channel, provided out has enough channels */
- uint_t max_filters = MIN (f->n_filters, out->length);
- uint_t max_length = MIN (in->length, f->filters->length);
+ //uint_t max_filters = MIN (f->n_filters, out->length);
+ //uint_t max_length = MIN (in->length, f->filters->length);
- /* reset all values in output vector */
- fvec_zeros (out);
+ // view cvec->norm as fvec->data
+ fvec_t tmp;
+ tmp.length = in->length;
+ tmp.data = in->norm;
- /* for each filter */
- for (fn = 0; fn < max_filters; fn++) {
- /* for each sample */
- for (j = 0; j < max_length; j++) {
- out->data[fn] += in->norm[j] * f->filters->data[fn][j];
- }
- }
+ fmat_vecmul(f->filters, &tmp, out);
return;
}
fmat_t *
-aubio_filterbank_get_coeffs (aubio_filterbank_t * f)
+aubio_filterbank_get_coeffs (const aubio_filterbank_t * f)
{
return f->filters;
}
uint_t
-aubio_filterbank_set_coeffs (aubio_filterbank_t * f, fmat_t * filter_coeffs)
+aubio_filterbank_set_coeffs (aubio_filterbank_t * f, const fmat_t * filter_coeffs)
{
fmat_copy(filter_coeffs, f->filters);
return 0;
*/
-#ifndef _AUBIO_FILTERBANK_H
-#define _AUBIO_FILTERBANK_H
+#ifndef AUBIO_FILTERBANK_H
+#define AUBIO_FILTERBANK_H
#ifdef __cplusplus
extern "C"
\param out output vector containing the energy found in each band, `nfilt` output values
*/
-void aubio_filterbank_do (aubio_filterbank_t * f, cvec_t * in, fvec_t * out);
+void aubio_filterbank_do (aubio_filterbank_t * f, const cvec_t * in, fvec_t * out);
/** return a pointer to the matrix object containing all filter coefficients
\param f filterbank object, as returned by new_aubio_filterbank()
*/
-fmat_t *aubio_filterbank_get_coeffs (aubio_filterbank_t * f);
+fmat_t *aubio_filterbank_get_coeffs (const aubio_filterbank_t * f);
/** copy filter coefficients to the filterbank
\param filters filter bank coefficients to copy from
*/
-uint_t aubio_filterbank_set_coeffs (aubio_filterbank_t * f, fmat_t * filters);
+uint_t aubio_filterbank_set_coeffs (aubio_filterbank_t * f, const fmat_t * filters);
#ifdef __cplusplus
}
#endif
-#endif /* _AUBIO_FILTERBANK_H */
+#endif /* AUBIO_FILTERBANK_H */
uint_t
aubio_filterbank_set_triangle_bands (aubio_filterbank_t * fb,
- fvec_t * freqs, smpl_t samplerate)
+ const fvec_t * freqs, smpl_t samplerate)
{
fmat_t *filters = aubio_filterbank_get_coeffs (fb);
*/
-#ifndef _AUBIO_FILTERBANK_MEL_H
-#define _AUBIO_FILTERBANK_MEL_H
+#ifndef AUBIO_FILTERBANK_MEL_H
+#define AUBIO_FILTERBANK_MEL_H
#ifdef __cplusplus
extern "C"
*/
uint_t aubio_filterbank_set_triangle_bands (aubio_filterbank_t * fb,
- fvec_t * freqs, smpl_t samplerate);
+ const fvec_t * freqs, smpl_t samplerate);
/** filterbank initialization for Mel filters using Slaney's coefficients
}
#endif
-#endif /* _AUBIO_FILTERBANK_MEL_H */
+#endif /* AUBIO_FILTERBANK_MEL_H */
/* allocating buffers */
mfcc->in_dct = new_fvec (n_filters);
- mfcc->dct_coeffs = new_fmat (n_filters, n_coefs);
+ mfcc->dct_coeffs = new_fmat (n_coefs, n_filters);
- /* compute DCT transform dct_coeffs[i][j] as
+ /* compute DCT transform dct_coeffs[j][i] as
cos ( j * (i+.5) * PI / n_filters ) */
scaling = 1. / SQRT (n_filters / 2.);
for (i = 0; i < n_filters; i++) {
for (j = 0; j < n_coefs; j++) {
- mfcc->dct_coeffs->data[i][j] =
+ mfcc->dct_coeffs->data[j][i] =
scaling * COS (j * (i + 0.5) * PI / n_filters);
}
- mfcc->dct_coeffs->data[i][0] *= SQRT (2.) / 2.;
+ mfcc->dct_coeffs->data[0][i] *= SQRT (2.) / 2.;
}
return mfcc;
-};
+}
void
del_aubio_mfcc (aubio_mfcc_t * mf)
void
-aubio_mfcc_do (aubio_mfcc_t * mf, cvec_t * in, fvec_t * out)
+aubio_mfcc_do (aubio_mfcc_t * mf, const cvec_t * in, fvec_t * out)
{
- uint_t j, k;
-
/* compute filterbank */
aubio_filterbank_do (mf->fb, in, mf->in_dct);
/* raise power */
//fvec_pow (mf->in_dct, 3.);
- /* zeros output */
- fvec_zeros(out);
-
- /* compute discrete cosine transform */
- for (j = 0; j < mf->n_filters; j++) {
- for (k = 0; k < mf->n_coefs; k++) {
- out->data[k] += mf->in_dct->data[j]
- * mf->dct_coeffs->data[j][k];
- }
- }
+ /* compute mfccs */
+ fmat_vecmul(mf->dct_coeffs, mf->in_dct, out);
return;
}
*/
-#ifndef _AUBIO_MFCC_H
-#define _AUBIO_MFCC_H
+#ifndef AUBIO_MFCC_H
+#define AUBIO_MFCC_H
#ifdef __cplusplus
extern "C"
\param out output mel coefficients buffer (n_coeffs long)
*/
-void aubio_mfcc_do (aubio_mfcc_t * mf, cvec_t * in, fvec_t * out);
+void aubio_mfcc_do (aubio_mfcc_t * mf, const cvec_t * in, fvec_t * out);
#ifdef __cplusplus
}
#endif
-#endif /* _AUBIO_MFCC_H */
+#endif /* AUBIO_MFCC_H */
// - replace all 'double' with 'smpl_t'
// - include "aubio_priv.h" (for config.h and types.h)
// - add missing prototypes
-// - use COS and SIN macros
+// - use COS, SIN, and ATAN macros
+// - add cast to (smpl_t) to avoid float conversion warnings
+// - declare initialization as static
+// - prefix public function with aubio_ooura_
#include "aubio_priv.h"
-void cdft(int n, int isgn, smpl_t *a, int *ip, smpl_t *w);
-void rdft(int n, int isgn, smpl_t *a, int *ip, smpl_t *w);
-void ddct(int n, int isgn, smpl_t *a, int *ip, smpl_t *w);
-void ddst(int n, int isgn, smpl_t *a, int *ip, smpl_t *w);
-void dfct(int n, smpl_t *a, smpl_t *t, int *ip, smpl_t *w);
-void dfst(int n, smpl_t *a, smpl_t *t, int *ip, smpl_t *w);
-void makewt(int nw, int *ip, smpl_t *w);
-void makect(int nc, int *ip, smpl_t *c);
-void bitrv2(int n, int *ip, smpl_t *a);
-void bitrv2conj(int n, int *ip, smpl_t *a);
-void cftfsub(int n, smpl_t *a, smpl_t *w);
-void cftbsub(int n, smpl_t *a, smpl_t *w);
-void cft1st(int n, smpl_t *a, smpl_t *w);
-void cftmdl(int n, int l, smpl_t *a, smpl_t *w);
-void rftfsub(int n, smpl_t *a, int nc, smpl_t *c);
-void rftbsub(int n, smpl_t *a, int nc, smpl_t *c);
-void dctsub(int n, smpl_t *a, int nc, smpl_t *c);
-void dstsub(int n, smpl_t *a, int nc, smpl_t *c);
+void aubio_ooura_cdft(int n, int isgn, smpl_t *a, int *ip, smpl_t *w);
+void aubio_ooura_rdft(int n, int isgn, smpl_t *a, int *ip, smpl_t *w);
+void aubio_ooura_ddct(int n, int isgn, smpl_t *a, int *ip, smpl_t *w);
+void aubio_ooura_ddst(int n, int isgn, smpl_t *a, int *ip, smpl_t *w);
+void aubio_ooura_dfct(int n, smpl_t *a, smpl_t *t, int *ip, smpl_t *w);
+void aubio_ooura_dfst(int n, smpl_t *a, smpl_t *t, int *ip, smpl_t *w);
+static void makewt(int nw, int *ip, smpl_t *w);
+static void makect(int nc, int *ip, smpl_t *c);
+static void bitrv2(int n, int *ip, smpl_t *a);
+static void bitrv2conj(int n, int *ip, smpl_t *a);
+static void cftfsub(int n, smpl_t *a, smpl_t *w);
+static void cftbsub(int n, smpl_t *a, smpl_t *w);
+static void cft1st(int n, smpl_t *a, smpl_t *w);
+static void cftmdl(int n, int l, smpl_t *a, smpl_t *w);
+static void rftfsub(int n, smpl_t *a, int nc, smpl_t *c);
+static void rftbsub(int n, smpl_t *a, int nc, smpl_t *c);
+static void dctsub(int n, smpl_t *a, int nc, smpl_t *c);
+static void dstsub(int n, smpl_t *a, int nc, smpl_t *c);
/*
Fast Fourier/Cosine/Sine Transform
*/
-void cdft(int n, int isgn, smpl_t *a, int *ip, smpl_t *w)
+void aubio_ooura_cdft(int n, int isgn, smpl_t *a, int *ip, smpl_t *w)
{
void makewt(int nw, int *ip, smpl_t *w);
void bitrv2(int n, int *ip, smpl_t *a);
}
-void rdft(int n, int isgn, smpl_t *a, int *ip, smpl_t *w)
+void aubio_ooura_rdft(int n, int isgn, smpl_t *a, int *ip, smpl_t *w)
{
void makewt(int nw, int *ip, smpl_t *w);
void makect(int nc, int *ip, smpl_t *c);
a[0] += a[1];
a[1] = xi;
} else {
- a[1] = 0.5 * (a[0] - a[1]);
+ a[1] = (smpl_t)0.5 * (a[0] - a[1]);
a[0] -= a[1];
if (n > 4) {
rftbsub(n, a, nc, w + nw);
}
-void ddct(int n, int isgn, smpl_t *a, int *ip, smpl_t *w)
+void aubio_ooura_ddct(int n, int isgn, smpl_t *a, int *ip, smpl_t *w)
{
void makewt(int nw, int *ip, smpl_t *w);
void makect(int nc, int *ip, smpl_t *c);
}
-void ddst(int n, int isgn, smpl_t *a, int *ip, smpl_t *w)
+void aubio_ooura_ddst(int n, int isgn, smpl_t *a, int *ip, smpl_t *w)
{
void makewt(int nw, int *ip, smpl_t *w);
void makect(int nc, int *ip, smpl_t *c);
}
-void dfct(int n, smpl_t *a, smpl_t *t, int *ip, smpl_t *w)
+void aubio_ooura_dfct(int n, smpl_t *a, smpl_t *t, int *ip, smpl_t *w)
{
void makewt(int nw, int *ip, smpl_t *w);
void makect(int nc, int *ip, smpl_t *c);
}
-void dfst(int n, smpl_t *a, smpl_t *t, int *ip, smpl_t *w)
+void aubio_ooura_dfst(int n, smpl_t *a, smpl_t *t, int *ip, smpl_t *w)
{
void makewt(int nw, int *ip, smpl_t *w);
void makect(int nc, int *ip, smpl_t *c);
ip[1] = 1;
if (nw > 2) {
nwh = nw >> 1;
- delta = atan(1.0) / nwh;
+ delta = ATAN(1.0) / nwh;
w[0] = 1;
w[1] = 0;
w[nwh] = COS(delta * nwh);
ip[1] = nc;
if (nc > 1) {
nch = nc >> 1;
- delta = atan(1.0) / nch;
- c[0] = cos(delta * nch);
- c[nch] = 0.5 * c[0];
+ delta = ATAN(1.0) / nch;
+ c[0] = COS(delta * nch);
+ c[nch] = (smpl_t)0.5 * c[0];
for (j = 1; j < nch; j++) {
- c[j] = 0.5 * cos(delta * j);
- c[nc - j] = 0.5 * sin(delta * j);
+ c[j] = (smpl_t)0.5 * COS(delta * j);
+ c[nc - j] = (smpl_t)0.5 * SIN(delta * j);
}
}
}
for (j = 2; j < m; j += 2) {
k = n - j;
kk += ks;
- wkr = 0.5 - c[nc - kk];
+ wkr = (smpl_t)0.5 - c[nc - kk];
wki = c[kk];
xr = a[j] - a[k];
xi = a[j + 1] + a[k + 1];
for (j = 2; j < m; j += 2) {
k = n - j;
kk += ks;
- wkr = 0.5 - c[nc - kk];
+ wkr = (smpl_t)0.5 - c[nc - kk];
wki = c[kk];
xr = a[j] - a[k];
xi = a[j + 1] + a[k + 1];
/** returns data and dataold slided by hop_s */
-static void aubio_pvoc_swapbuffers(aubio_pvoc_t *pv, fvec_t *new);
+static void aubio_pvoc_swapbuffers(aubio_pvoc_t *pv, const fvec_t *new);
/** do additive synthesis from 'old' and 'cur' */
static void aubio_pvoc_addsynth(aubio_pvoc_t *pv, fvec_t * synthnew);
-void aubio_pvoc_do(aubio_pvoc_t *pv, fvec_t * datanew, cvec_t *fftgrain) {
+void aubio_pvoc_do(aubio_pvoc_t *pv, const fvec_t * datanew, cvec_t *fftgrain) {
/* slide */
aubio_pvoc_swapbuffers(pv, datanew);
/* windowing */
/* calculate rfft */
aubio_fft_rdo(pv->fft,fftgrain,pv->synth);
/* unshift */
- fvec_shift(pv->synth);
+ fvec_ishift(pv->synth);
+ /* windowing */
+ // if overlap = 50%, do not apply window (identity)
+ if (pv->hop_s * 2 < pv->win_s) {
+ fvec_weight(pv->synth, pv->w);
+ }
/* additive synthesis */
aubio_pvoc_addsynth(pv, synthnew);
}
if ((sint_t)hop_s < 1) {
AUBIO_ERR("pvoc: got hop_size %d, but can not be < 1\n", hop_s);
goto beach;
- } else if ((sint_t)win_s < 1) {
- AUBIO_ERR("pvoc: got buffer_size %d, but can not be < 1\n", win_s);
+ } else if ((sint_t)win_s < 2) {
+ AUBIO_ERR("pvoc: got buffer_size %d, but can not be < 2\n", win_s);
goto beach;
} else if (win_s < hop_s) {
- AUBIO_ERR("pvoc: hop size (%d) is larger than win size (%d)\n", win_s, hop_s);
+ AUBIO_ERR("pvoc: hop size (%d) is larger than win size (%d)\n", hop_s, win_s);
goto beach;
}
pv->fft = new_aubio_fft (win_s);
+ if (pv->fft == NULL) {
+ goto beach;
+ }
/* remember old */
pv->data = new_fvec (win_s);
pv->end_datasize = pv->end * sizeof(smpl_t);
pv->hop_datasize = pv->hop_s * sizeof(smpl_t);
- pv->scale = pv->hop_s * 2. / pv->win_s;
+ // for reconstruction with 75% overlap
+ if (win_s == hop_s * 4) {
+ pv->scale = 2./3.;
+ } else if (win_s == hop_s * 8) {
+ pv->scale = 1./3.;
+ } else if (win_s == hop_s * 2) {
+ pv->scale = 1.;
+ } else {
+ pv->scale = .5;
+ }
return pv;
AUBIO_FREE(pv);
}
-static void aubio_pvoc_swapbuffers(aubio_pvoc_t *pv, fvec_t *new)
+static void aubio_pvoc_swapbuffers(aubio_pvoc_t *pv, const fvec_t *new)
{
/* some convenience pointers */
smpl_t * data = pv->data->data;
smpl_t * dataold = pv->dataold->data;
smpl_t * datanew = new->data;
-#if !HAVE_MEMCPY_HACKS
+#ifndef HAVE_MEMCPY_HACKS
uint_t i;
for (i = 0; i < pv->end; i++)
data[i] = dataold[i];
*/
-#ifndef _AUBIO_PHASEVOC_H
-#define _AUBIO_PHASEVOC_H
+#ifndef AUBIO_PHASEVOC_H
+#define AUBIO_PHASEVOC_H
#ifdef __cplusplus
extern "C" {
\param fftgrain output spectral frame
*/
-void aubio_pvoc_do(aubio_pvoc_t *pv, fvec_t *in, cvec_t * fftgrain);
+void aubio_pvoc_do(aubio_pvoc_t *pv, const fvec_t *in, cvec_t * fftgrain);
/** compute signal from spectral frame
This function takes an input spectral frame fftgrain of size
}
#endif
-#endif /* _AUBIO_PHASEVOC_H */
+#endif /* AUBIO_PHASEVOC_H */
#include "mathutils.h"
#include "utils/hist.h"
-void aubio_specdesc_energy(aubio_specdesc_t *o, cvec_t * fftgrain, fvec_t * onset);
-void aubio_specdesc_hfc(aubio_specdesc_t *o, cvec_t * fftgrain, fvec_t * onset);
-void aubio_specdesc_complex(aubio_specdesc_t *o, cvec_t * fftgrain, fvec_t * onset);
-void aubio_specdesc_phase(aubio_specdesc_t *o, cvec_t * fftgrain, fvec_t * onset);
-void aubio_specdesc_specdiff(aubio_specdesc_t *o, cvec_t * fftgrain, fvec_t * onset);
-void aubio_specdesc_kl(aubio_specdesc_t *o, cvec_t * fftgrain, fvec_t * onset);
-void aubio_specdesc_mkl(aubio_specdesc_t *o, cvec_t * fftgrain, fvec_t * onset);
-void aubio_specdesc_specflux(aubio_specdesc_t *o, cvec_t * fftgrain, fvec_t * onset);
+void aubio_specdesc_energy(aubio_specdesc_t *o, const cvec_t * fftgrain, fvec_t * onset);
+void aubio_specdesc_hfc(aubio_specdesc_t *o, const cvec_t * fftgrain, fvec_t * onset);
+void aubio_specdesc_complex(aubio_specdesc_t *o, const cvec_t * fftgrain, fvec_t * onset);
+void aubio_specdesc_phase(aubio_specdesc_t *o, const cvec_t * fftgrain, fvec_t * onset);
+void aubio_specdesc_specdiff(aubio_specdesc_t *o, const cvec_t * fftgrain, fvec_t * onset);
+void aubio_specdesc_kl(aubio_specdesc_t *o, const cvec_t * fftgrain, fvec_t * onset);
+void aubio_specdesc_mkl(aubio_specdesc_t *o, const cvec_t * fftgrain, fvec_t * onset);
+void aubio_specdesc_specflux(aubio_specdesc_t *o, const cvec_t * fftgrain, fvec_t * onset);
-extern void aubio_specdesc_centroid (aubio_specdesc_t * o, cvec_t * spec,
+extern void aubio_specdesc_centroid (aubio_specdesc_t * o, const cvec_t * spec,
fvec_t * desc);
-extern void aubio_specdesc_spread (aubio_specdesc_t * o, cvec_t * spec,
+extern void aubio_specdesc_spread (aubio_specdesc_t * o, const cvec_t * spec,
fvec_t * desc);
-extern void aubio_specdesc_skewness (aubio_specdesc_t * o, cvec_t * spec,
+extern void aubio_specdesc_skewness (aubio_specdesc_t * o, const cvec_t * spec,
fvec_t * desc);
-extern void aubio_specdesc_kurtosis (aubio_specdesc_t * o, cvec_t * spec,
+extern void aubio_specdesc_kurtosis (aubio_specdesc_t * o, const cvec_t * spec,
fvec_t * desc);
-extern void aubio_specdesc_slope (aubio_specdesc_t * o, cvec_t * spec,
+extern void aubio_specdesc_slope (aubio_specdesc_t * o, const cvec_t * spec,
fvec_t * desc);
-extern void aubio_specdesc_decrease (aubio_specdesc_t * o, cvec_t * spec,
+extern void aubio_specdesc_decrease (aubio_specdesc_t * o, const cvec_t * spec,
fvec_t * desc);
-extern void aubio_specdesc_rolloff (aubio_specdesc_t * o, cvec_t * spec,
+extern void aubio_specdesc_rolloff (aubio_specdesc_t * o, const cvec_t * spec,
fvec_t * desc);
/** onsetdetection types */
aubio_specdesc_type onset_type; /**< onset detection type */
/** Pointer to aubio_specdesc_<type> function */
void (*funcpointer)(aubio_specdesc_t *o,
- cvec_t * fftgrain, fvec_t * onset);
+ const cvec_t * fftgrain, fvec_t * onset);
smpl_t threshold; /**< minimum norm threshold for phase and specdiff */
fvec_t *oldmag; /**< previous norm vector */
fvec_t *dev1 ; /**< current onset detection measure vector */
/* Energy based onset detection function */
void aubio_specdesc_energy (aubio_specdesc_t *o UNUSED,
- cvec_t * fftgrain, fvec_t * onset) {
+ const cvec_t * fftgrain, fvec_t * onset) {
uint_t j;
onset->data[0] = 0.;
for (j=0;j<fftgrain->length;j++) {
/* High Frequency Content onset detection function */
void aubio_specdesc_hfc(aubio_specdesc_t *o UNUSED,
- cvec_t * fftgrain, fvec_t * onset){
+ const cvec_t * fftgrain, fvec_t * onset){
uint_t j;
onset->data[0] = 0.;
for (j=0;j<fftgrain->length;j++) {
/* Complex Domain Method onset detection function */
-void aubio_specdesc_complex (aubio_specdesc_t *o, cvec_t * fftgrain, fvec_t * onset) {
+void aubio_specdesc_complex (aubio_specdesc_t *o, const cvec_t * fftgrain, fvec_t * onset) {
uint_t j;
uint_t nbins = fftgrain->length;
onset->data[0] = 0.;
/* Phase Based Method onset detection function */
void aubio_specdesc_phase(aubio_specdesc_t *o,
- cvec_t * fftgrain, fvec_t * onset){
+ const cvec_t * fftgrain, fvec_t * onset){
uint_t j;
uint_t nbins = fftgrain->length;
onset->data[0] = 0.0;
/* Spectral difference method onset detection function */
void aubio_specdesc_specdiff(aubio_specdesc_t *o,
- cvec_t * fftgrain, fvec_t * onset){
+ const cvec_t * fftgrain, fvec_t * onset){
uint_t j;
uint_t nbins = fftgrain->length;
onset->data[0] = 0.0;
/* Kullback Liebler onset detection function
* note we use ln(1+Xn/(Xn-1+0.0001)) to avoid
* negative (1.+) and infinite values (+1.e-10) */
-void aubio_specdesc_kl(aubio_specdesc_t *o, cvec_t * fftgrain, fvec_t * onset){
+void aubio_specdesc_kl(aubio_specdesc_t *o, const cvec_t * fftgrain, fvec_t * onset){
uint_t j;
onset->data[0] = 0.;
for (j=0;j<fftgrain->length;j++) {
/* Modified Kullback Liebler onset detection function
* note we use ln(1+Xn/(Xn-1+0.0001)) to avoid
* negative (1.+) and infinite values (+1.e-10) */
-void aubio_specdesc_mkl(aubio_specdesc_t *o, cvec_t * fftgrain, fvec_t * onset){
+void aubio_specdesc_mkl(aubio_specdesc_t *o, const cvec_t * fftgrain, fvec_t * onset){
uint_t j;
onset->data[0] = 0.;
for (j=0;j<fftgrain->length;j++) {
}
/* Spectral flux */
-void aubio_specdesc_specflux(aubio_specdesc_t *o, cvec_t * fftgrain, fvec_t * onset){
+void aubio_specdesc_specflux(aubio_specdesc_t *o, const cvec_t * fftgrain, fvec_t * onset){
uint_t j;
onset->data[0] = 0.;
for (j=0;j<fftgrain->length;j++) {
/* Generic function pointing to the choosen one */
void
-aubio_specdesc_do (aubio_specdesc_t *o, cvec_t * fftgrain,
+aubio_specdesc_do (aubio_specdesc_t *o, const cvec_t * fftgrain,
fvec_t * onset) {
o->funcpointer(o,fftgrain,onset);
}
* depending on the choosen type, allocate memory as needed
*/
aubio_specdesc_t *
-new_aubio_specdesc (char_t * onset_mode, uint_t size){
+new_aubio_specdesc (const char_t * onset_mode, uint_t size){
aubio_specdesc_t * o = AUBIO_NEW(aubio_specdesc_t);
uint_t rsize = size/2+1;
aubio_specdesc_type onset_type;
else if (strcmp (onset_mode, "default") == 0)
onset_type = aubio_onset_default;
else {
- AUBIO_ERR("unknown spectral descriptor type %s, using default.\n", onset_mode);
- onset_type = aubio_onset_default;
+ AUBIO_ERR("unknown spectral descriptor type %s\n", onset_mode);
+ AUBIO_FREE(o);
+ return NULL;
}
switch(onset_type) {
/* for both energy and hfc, only fftgrain->norm is required */
- case aubio_onset_energy:
+ case aubio_onset_energy:
break;
case aubio_onset_hfc:
break;
void del_aubio_specdesc (aubio_specdesc_t *o){
switch(o->onset_type) {
- case aubio_onset_energy:
+ case aubio_onset_energy:
break;
case aubio_onset_hfc:
break;
*/
-#ifndef _AUBIO_SPECDESC_H
-#define _AUBIO_SPECDESC_H
+#ifndef AUBIO_SPECDESC_H
+#define AUBIO_SPECDESC_H
#ifdef __cplusplus
extern "C" {
\param desc output vector (one sample long, to send to the peak picking)
*/
-void aubio_specdesc_do (aubio_specdesc_t * o, cvec_t * fftgrain,
+void aubio_specdesc_do (aubio_specdesc_t * o, const cvec_t * fftgrain,
fvec_t * desc);
/** creation of a spectral description object
- `centroid`, `spread`, `skewness`, `kurtosis`, `slope`, `decrease`, `rolloff`
*/
-aubio_specdesc_t *new_aubio_specdesc (char_t * method, uint_t buf_size);
+aubio_specdesc_t *new_aubio_specdesc (const char_t * method, uint_t buf_size);
/** deletion of a spectral descriptor
}
#endif
-#endif /* _AUBIO_SPECDESC_H */
+#endif /* AUBIO_SPECDESC_H */
#include "cvec.h"
#include "spectral/specdesc.h"
-void aubio_specdesc_centroid (aubio_specdesc_t * o, cvec_t * spec,
+void aubio_specdesc_centroid (aubio_specdesc_t * o, const cvec_t * spec,
fvec_t * desc);
-void aubio_specdesc_spread (aubio_specdesc_t * o, cvec_t * spec,
+void aubio_specdesc_spread (aubio_specdesc_t * o, const cvec_t * spec,
fvec_t * desc);
-void aubio_specdesc_skewness (aubio_specdesc_t * o, cvec_t * spec,
+void aubio_specdesc_skewness (aubio_specdesc_t * o, const cvec_t * spec,
fvec_t * desc);
-void aubio_specdesc_kurtosis (aubio_specdesc_t * o, cvec_t * spec,
+void aubio_specdesc_kurtosis (aubio_specdesc_t * o, const cvec_t * spec,
fvec_t * desc);
-void aubio_specdesc_slope (aubio_specdesc_t * o, cvec_t * spec,
+void aubio_specdesc_slope (aubio_specdesc_t * o, const cvec_t * spec,
fvec_t * desc);
-void aubio_specdesc_decrease (aubio_specdesc_t * o, cvec_t * spec,
+void aubio_specdesc_decrease (aubio_specdesc_t * o, const cvec_t * spec,
fvec_t * desc);
-void aubio_specdesc_rolloff (aubio_specdesc_t * o, cvec_t * spec,
+void aubio_specdesc_rolloff (aubio_specdesc_t * o, const cvec_t * spec,
fvec_t * desc);
-smpl_t cvec_sum (cvec_t * s);
-smpl_t cvec_mean (cvec_t * s);
-smpl_t cvec_centroid (cvec_t * s);
-smpl_t cvec_moment (cvec_t * s, uint_t moment);
+smpl_t cvec_sum (const cvec_t * s);
+smpl_t cvec_mean (const cvec_t * s);
+smpl_t cvec_centroid (const cvec_t * s);
+smpl_t cvec_moment (const cvec_t * s, uint_t moment);
smpl_t
-cvec_sum (cvec_t * s)
+cvec_sum (const cvec_t * s)
{
uint_t j;
smpl_t tmp = 0.0;
}
smpl_t
-cvec_mean (cvec_t * s)
+cvec_mean (const cvec_t * s)
{
return cvec_sum (s) / (smpl_t) (s->length);
}
smpl_t
-cvec_centroid (cvec_t * spec)
+cvec_centroid (const cvec_t * spec)
{
smpl_t sum = 0., sc = 0.;
uint_t j;
}
smpl_t
-cvec_moment (cvec_t * spec, uint_t order)
+cvec_moment (const cvec_t * spec, uint_t order)
{
smpl_t sum = 0., centroid = 0., sc = 0.;
uint_t j;
}
void
-aubio_specdesc_centroid (aubio_specdesc_t * o UNUSED, cvec_t * spec,
+aubio_specdesc_centroid (aubio_specdesc_t * o UNUSED, const cvec_t * spec,
fvec_t * desc)
{
desc->data[0] = cvec_centroid (spec);
}
void
-aubio_specdesc_spread (aubio_specdesc_t * o UNUSED, cvec_t * spec,
+aubio_specdesc_spread (aubio_specdesc_t * o UNUSED, const cvec_t * spec,
fvec_t * desc)
{
desc->data[0] = cvec_moment (spec, 2);
}
void
-aubio_specdesc_skewness (aubio_specdesc_t * o UNUSED, cvec_t * spec,
+aubio_specdesc_skewness (aubio_specdesc_t * o UNUSED, const cvec_t * spec,
fvec_t * desc)
{
smpl_t spread;
}
void
-aubio_specdesc_kurtosis (aubio_specdesc_t * o UNUSED, cvec_t * spec,
+aubio_specdesc_kurtosis (aubio_specdesc_t * o UNUSED, const cvec_t * spec,
fvec_t * desc)
{
smpl_t spread;
}
void
-aubio_specdesc_slope (aubio_specdesc_t * o UNUSED, cvec_t * spec,
+aubio_specdesc_slope (aubio_specdesc_t * o UNUSED, const cvec_t * spec,
fvec_t * desc)
{
uint_t j;
}
void
-aubio_specdesc_decrease (aubio_specdesc_t *o UNUSED, cvec_t * spec,
+aubio_specdesc_decrease (aubio_specdesc_t *o UNUSED, const cvec_t * spec,
fvec_t * desc)
{
uint_t j; smpl_t sum;
}
void
-aubio_specdesc_rolloff (aubio_specdesc_t *o UNUSED, cvec_t * spec,
+aubio_specdesc_rolloff (aubio_specdesc_t *o UNUSED, const cvec_t * spec,
fvec_t *desc)
{
uint_t j; smpl_t cumsum, rollsum;
fvec_t *dev;
};
-void aubio_tss_do(aubio_tss_t *o, cvec_t * input,
+void aubio_tss_do(aubio_tss_t *o, const cvec_t * input,
cvec_t * trans, cvec_t * stead)
{
uint_t j;
*/
-#ifndef _AUBIO_TSS_H
-#define _AUBIO_TSS_H
+#ifndef AUBIO_TSS_H
+#define AUBIO_TSS_H
#ifdef __cplusplus
extern "C" {
\param stead output steady state components
*/
-void aubio_tss_do (aubio_tss_t * o, cvec_t * input, cvec_t * trans,
+void aubio_tss_do (aubio_tss_t * o, const cvec_t * input, cvec_t * trans,
cvec_t * stead);
/** set transient / steady state separation threshold
}
#endif
-#endif /* _AUBIO_TSS_H */
+#endif /* AUBIO_TSS_H */
*/
-#include "config.h"
#include "aubio_priv.h"
#include "fvec.h"
#include "fmat.h"
return NULL;
}
-uint_t aubio_sampler_load( aubio_sampler_t * o, char_t * uri )
+uint_t aubio_sampler_load( aubio_sampler_t * o, const char_t * uri )
{
if (o->source) del_aubio_source(o->source);
- o->uri = uri;
+
+ if (o->uri) AUBIO_FREE(o->uri);
+ o->uri = AUBIO_ARRAY(char_t, strnlen(uri, PATH_MAX));
+ strncpy(o->uri, uri, strnlen(uri, PATH_MAX));
+
o->source = new_aubio_source(uri, o->samplerate, o->blocksize);
if (o->source) return 0;
AUBIO_ERR("sampler: failed loading %s", uri);
return 1;
}
-void aubio_sampler_do ( aubio_sampler_t * o, fvec_t * input, fvec_t * output)
+void aubio_sampler_do ( aubio_sampler_t * o, const fvec_t * input, fvec_t * output)
{
uint_t read = 0, i;
if (o->playing) {
}
}
-void aubio_sampler_do_multi ( aubio_sampler_t * o, fmat_t * input, fmat_t * output)
+void aubio_sampler_do_multi ( aubio_sampler_t * o, const fmat_t * input, fmat_t * output)
{
uint_t read = 0, i, j;
if (o->playing) {
}
}
-uint_t aubio_sampler_get_playing ( aubio_sampler_t * o )
+uint_t aubio_sampler_get_playing ( const aubio_sampler_t * o )
{
return o->playing;
}
if (o->source) {
del_aubio_source(o->source);
}
+ if (o->uri) AUBIO_FREE(o->uri);
del_fvec(o->source_output);
del_fmat(o->source_output_multi);
AUBIO_FREE(o);
*/
-#ifndef _AUBIO_SAMPLER_H
-#define _AUBIO_SAMPLER_H
+#ifndef AUBIO_SAMPLER_H
+#define AUBIO_SAMPLER_H
/** \file
\return 0 if successful, non-zero otherwise
*/
-uint_t aubio_sampler_load( aubio_sampler_t * o, char_t * uri );
+uint_t aubio_sampler_load( aubio_sampler_t * o, const char_t * uri );
/** process sampler function
are added to the output.
*/
-void aubio_sampler_do ( aubio_sampler_t * o, fvec_t * input, fvec_t * output);
+void aubio_sampler_do ( aubio_sampler_t * o, const fvec_t * input, fvec_t * output);
/** process sampler function, multiple channels
are added to the output.
*/
-void aubio_sampler_do_multi ( aubio_sampler_t * o, fmat_t * input, fmat_t * output);
+void aubio_sampler_do_multi ( aubio_sampler_t * o, const fmat_t * input, fmat_t * output);
/** get current playing state
\return 0 if not playing, 1 if playing
*/
-uint_t aubio_sampler_get_playing ( aubio_sampler_t * o );
+uint_t aubio_sampler_get_playing ( const aubio_sampler_t * o );
/** set current playing state
}
#endif
-#endif /* _AUBIO_SAMPLER_H */
+#endif /* AUBIO_SAMPLER_H */
*/
-#include "config.h"
#include "aubio_priv.h"
#include "fvec.h"
#include "fmat.h"
return NULL;
}
-static smpl_t interp_2(fvec_t *input, smpl_t pos) {
+static smpl_t interp_2(const fvec_t *input, smpl_t pos) {
uint_t idx = (uint_t)FLOOR(pos);
smpl_t frac = pos - (smpl_t)idx;
smpl_t a = input->data[idx];
return a + frac * ( b - a );
}
-void aubio_wavetable_do ( aubio_wavetable_t * s, fvec_t * input, fvec_t * output)
+void aubio_wavetable_do ( aubio_wavetable_t * s, const fvec_t * input, fvec_t * output)
{
uint_t i;
if (s->playing) {
}
}
-void aubio_wavetable_do_multi ( aubio_wavetable_t * s, fmat_t * input, fmat_t * output)
+void aubio_wavetable_do_multi ( aubio_wavetable_t * s, const fmat_t * input, fmat_t * output)
{
uint_t i, j;
if (s->playing) {
}
}
-uint_t aubio_wavetable_get_playing ( aubio_wavetable_t * s )
+uint_t aubio_wavetable_get_playing ( const aubio_wavetable_t * s )
{
return s->playing;
}
return aubio_parameter_set_target_value ( s->freq, freq );
}
-smpl_t aubio_wavetable_get_freq ( aubio_wavetable_t * s) {
+smpl_t aubio_wavetable_get_freq ( const aubio_wavetable_t * s) {
return aubio_parameter_get_current_value ( s->freq);
}
return aubio_parameter_set_target_value ( s->amp, amp );
}
-smpl_t aubio_wavetable_get_amp ( aubio_wavetable_t * s) {
+smpl_t aubio_wavetable_get_amp ( const aubio_wavetable_t * s) {
return aubio_parameter_get_current_value ( s->amp );
}
*/
-#ifndef _AUBIO_WAVETABLE_H
-#define _AUBIO_WAVETABLE_H
+#ifndef AUBIO_WAVETABLE_H
+#define AUBIO_WAVETABLE_H
/** \file
\return 0 if successful, non-zero otherwise
*/
-uint_t aubio_wavetable_load( aubio_wavetable_t * o, char_t * uri );
+uint_t aubio_wavetable_load( aubio_wavetable_t * o, const char_t * uri );
/** process wavetable function
are added to the output.
*/
-void aubio_wavetable_do ( aubio_wavetable_t * o, fvec_t * input, fvec_t * output);
+void aubio_wavetable_do ( aubio_wavetable_t * o, const fvec_t * input, fvec_t * output);
/** process wavetable function, multiple channels
are added to the output.
*/
-void aubio_wavetable_do_multi ( aubio_wavetable_t * o, fmat_t * input, fmat_t * output);
+void aubio_wavetable_do_multi ( aubio_wavetable_t * o, const fmat_t * input, fmat_t * output);
/** get current playing state
\return 0 if not playing, 1 if playing
*/
-uint_t aubio_wavetable_get_playing ( aubio_wavetable_t * o );
+uint_t aubio_wavetable_get_playing ( const aubio_wavetable_t * o );
/** set current playing state
\return current frequency, in Hz
*/
-smpl_t aubio_wavetable_get_freq ( aubio_wavetable_t * o);
+smpl_t aubio_wavetable_get_freq ( const aubio_wavetable_t * o);
/** set wavetable amplitude
\return current amplitude
*/
-smpl_t aubio_wavetable_get_amp ( aubio_wavetable_t * o);
+smpl_t aubio_wavetable_get_amp ( const aubio_wavetable_t * o);
/** destroy aubio_wavetable_t object
}
#endif
-#endif /* _AUBIO_WAVETABLE_H */
+#endif /* AUBIO_WAVETABLE_H */
void
-aubio_beattracking_do (aubio_beattracking_t * bt, fvec_t * dfframe,
+aubio_beattracking_do (aubio_beattracking_t * bt, const fvec_t * dfframe,
fvec_t * output)
{
}
smpl_t
-aubio_beattracking_get_period (aubio_beattracking_t * bt)
+aubio_beattracking_get_period (const aubio_beattracking_t * bt)
{
return bt->hop_size * bt->bp;
}
smpl_t
-aubio_beattracking_get_period_s (aubio_beattracking_t * bt)
+aubio_beattracking_get_period_s (const aubio_beattracking_t * bt)
{
return aubio_beattracking_get_period(bt) / (smpl_t) bt->samplerate;
}
smpl_t
-aubio_beattracking_get_bpm (aubio_beattracking_t * bt)
+aubio_beattracking_get_bpm (const aubio_beattracking_t * bt)
{
if (bt->bp != 0) {
return 60. / aubio_beattracking_get_period_s(bt);
}
smpl_t
-aubio_beattracking_get_confidence (aubio_beattracking_t * bt)
+aubio_beattracking_get_confidence (const aubio_beattracking_t * bt)
{
if (bt->gp) {
smpl_t acf_sum = fvec_sum(bt->acfout);
\example tempo/test-beattracking.c
*/
-#ifndef _AUBIO_BEATTRACKING_H
-#define _AUBIO_BEATTRACKING_H
+#ifndef AUBIO_BEATTRACKING_H
+#define AUBIO_BEATTRACKING_H
#ifdef __cplusplus
extern "C" {
\param out stored detected beat locations
*/
-void aubio_beattracking_do (aubio_beattracking_t * bt, fvec_t * dfframes,
+void aubio_beattracking_do (aubio_beattracking_t * bt, const fvec_t * dfframes,
fvec_t * out);
/** get current beat period in samples
value is found.
*/
-smpl_t aubio_beattracking_get_period (aubio_beattracking_t * bt);
+smpl_t aubio_beattracking_get_period (const aubio_beattracking_t * bt);
/** get current beat period in seconds
value is found.
*/
-smpl_t aubio_beattracking_get_period_s (aubio_beattracking_t * bt);
+smpl_t aubio_beattracking_get_period_s (const aubio_beattracking_t * bt);
/** get current tempo in bpm
consistent value is found.
*/
-smpl_t aubio_beattracking_get_bpm(aubio_beattracking_t * bt);
+smpl_t aubio_beattracking_get_bpm(const aubio_beattracking_t * bt);
/** get current tempo confidence
consistent value is found.
*/
-smpl_t aubio_beattracking_get_confidence(aubio_beattracking_t * bt);
+smpl_t aubio_beattracking_get_confidence(const aubio_beattracking_t * bt);
/** delete beat tracking object
}
#endif
-#endif /* _AUBIO_BEATTRACKING_H */
+#endif /* AUBIO_BEATTRACKING_H */
#include "mathutils.h"
#include "tempo/tempo.h"
-// TODO implement get/set_delay
-
-/** set current delay
-
- \param o beat tracking object
-
- \return current delay, in samples
-
- */
-uint_t aubio_tempo_get_delay(aubio_tempo_t * o);
-
-/** set current delay
-
- \param o beat tracking object
- \param delay delay to set tempo to, in samples
-
- \return `0` if successful, non-zero otherwise
-
- */
-uint_t aubio_tempo_set_delay(aubio_tempo_t * o, uint_t delay);
-
/* structure to store object state */
struct _aubio_tempo_t {
aubio_specdesc_t * od; /** onset detection */
uint_t hop_size; /** get hop_size */
uint_t total_frames; /** total frames since beginning */
uint_t last_beat; /** time of latest detected beat, in samples */
- uint_t delay; /** delay to remove to last beat, in samples */
+ sint_t delay; /** delay to remove to last beat, in samples */
uint_t last_tatum; /** time of latest detected tatum, in samples */
uint_t tatum_signature; /** number of tatum between each beats */
};
/* execute tempo detection function on iput buffer */
-void aubio_tempo_do(aubio_tempo_t *o, fvec_t * input, fvec_t * tempo)
+void aubio_tempo_do(aubio_tempo_t *o, const fvec_t * input, fvec_t * tempo)
{
uint_t i;
uint_t winlen = o->winlen;
}
o->blockpos++;
aubio_peakpicker_do (o->pp, o->of, o->onset);
- tempo->data[1] = o->onset->data[0];
+ // store onset detection function in second sample of vector
+ //tempo->data[1] = o->onset->data[0];
thresholded = aubio_peakpicker_get_thresholded_input(o->pp);
o->dfframe->data[winlen - step + o->blockpos] = thresholded->data[0];
/* end of second level loop */
uint_t aubio_tempo_get_last (aubio_tempo_t *o)
{
- return o->last_beat - o->delay;
+ return o->last_beat + o->delay;
}
smpl_t aubio_tempo_get_last_s (aubio_tempo_t *o)
return aubio_tempo_get_last_s (o) * 1000.;
}
-uint_t aubio_tempo_set_delay(aubio_tempo_t * o, uint_t delay) {
+uint_t aubio_tempo_set_delay(aubio_tempo_t * o, sint_t delay) {
o->delay = delay;
return AUBIO_OK;
}
+uint_t aubio_tempo_set_delay_s(aubio_tempo_t * o, smpl_t delay) {
+ o->delay = delay * o->samplerate;
+ return AUBIO_OK;
+}
+
+uint_t aubio_tempo_set_delay_ms(aubio_tempo_t * o, smpl_t delay) {
+ o->delay = 1000. * delay * o->samplerate;
+ return AUBIO_OK;
+}
+
uint_t aubio_tempo_get_delay(aubio_tempo_t * o) {
return o->delay;
}
+smpl_t aubio_tempo_get_delay_s(aubio_tempo_t * o) {
+ return o->delay / (smpl_t)(o->samplerate);
+}
+
+smpl_t aubio_tempo_get_delay_ms(aubio_tempo_t * o) {
+ return o->delay / (smpl_t)(o->samplerate) / 1000.;
+}
+
uint_t aubio_tempo_set_silence(aubio_tempo_t * o, smpl_t silence) {
o->silence = silence;
return AUBIO_OK;
}
/* Allocate memory for an tempo detection */
-aubio_tempo_t * new_aubio_tempo (char_t * tempo_mode,
+aubio_tempo_t * new_aubio_tempo (const char_t * tempo_mode,
uint_t buf_size, uint_t hop_size, uint_t samplerate)
{
aubio_tempo_t * o = AUBIO_NEW(aubio_tempo_t);
if ((sint_t)hop_size < 1) {
AUBIO_ERR("tempo: got hop size %d, but can not be < 1\n", hop_size);
goto beach;
- } else if ((sint_t)buf_size < 1) {
- AUBIO_ERR("tempo: got window size %d, but can not be < 1\n", buf_size);
+ } else if ((sint_t)buf_size < 2) {
+ AUBIO_ERR("tempo: got window size %d, but can not be < 2\n", buf_size);
goto beach;
} else if (buf_size < hop_size) {
AUBIO_ERR("tempo: hop size (%d) is larger than window size (%d)\n", buf_size, hop_size);
*/
-#ifndef _AUBIO_TEMPO_H
-#define _AUBIO_TEMPO_H
+#ifndef AUBIO_TEMPO_H
+#define AUBIO_TEMPO_H
#ifdef __cplusplus
extern "C" {
\return newly created ::aubio_tempo_t if successful, `NULL` otherwise
*/
-aubio_tempo_t * new_aubio_tempo (char_t * method,
+aubio_tempo_t * new_aubio_tempo (const char_t * method,
uint_t buf_size, uint_t hop_size, uint_t samplerate);
/** execute tempo detection
\param tempo output beats
*/
-void aubio_tempo_do (aubio_tempo_t *o, fvec_t * input, fvec_t * tempo);
+void aubio_tempo_do (aubio_tempo_t *o, const fvec_t * input, fvec_t * tempo);
/** get the time of the latest beat detected, in samples
\param o beat tracking object
- \return confidence with which the tempo has been observed, `0` if no
- consistent value is found.
+ \return confidence with which the tempo has been observed, the higher the
+ more confidence, `0` if no consistent value is found.
*/
smpl_t aubio_tempo_get_confidence(aubio_tempo_t * o);
-/* set number of tatum per beat
+/** set number of tatum per beat
\param o beat tracking object
\param signature number of tatum per beat (between 1 and 64)
*/
uint_t aubio_tempo_set_tatum_signature(aubio_tempo_t *o, uint_t signature);
-/* check whether a tatum was detected in the current frame
+/** check whether a tatum was detected in the current frame
\param o beat tracking object
*/
uint_t aubio_tempo_was_tatum(aubio_tempo_t *o);
-/* get position of last_tatum, in samples
+/** get position of last_tatum, in samples
\param o beat tracking object
*/
smpl_t aubio_tempo_get_last_tatum(aubio_tempo_t *o);
+/** get current delay
+
+ \param o beat tracking object
+
+ \return current delay, in samples
+
+ */
+uint_t aubio_tempo_get_delay(aubio_tempo_t * o);
+
+/** get current delay in seconds
+
+ \param o beat tracking object
+
+ \return current delay, in seconds
+
+ */
+smpl_t aubio_tempo_get_delay_s(aubio_tempo_t * o);
+
+/** get current delay in ms
+
+ \param o beat tracking object
+
+ \return current delay, in milliseconds
+
+ */
+smpl_t aubio_tempo_get_delay_ms(aubio_tempo_t * o);
+
+/** set current delay
+
+ \param o beat tracking object
+ \param delay delay to set tempo to, in samples
+
+ \return `0` if successful, non-zero otherwise
+
+ */
+uint_t aubio_tempo_set_delay(aubio_tempo_t * o, sint_t delay);
+
+/** set current delay in seconds
+
+ \param o beat tracking object
+ \param delay delay to set tempo to, in seconds
+
+ \return `0` if successful, non-zero otherwise
+
+ */
+uint_t aubio_tempo_set_delay_s(aubio_tempo_t * o, smpl_t delay);
+
+/** set current delay
+
+ \param o beat tracking object
+ \param delay delay to set tempo to, in samples
+
+ \return `0` if successful, non-zero otherwise
+
+ */
+uint_t aubio_tempo_set_delay_ms(aubio_tempo_t * o, smpl_t delay);
+
/** delete tempo detection object
\param o beat tracking object
}
#endif
-#endif /* _AUBIO_TEMPO_H */
+#endif /* AUBIO_TEMPO_H */
aubio_filter_set_a_weighting (aubio_filter_t * f, uint_t samplerate)
{
uint_t order; lsmp_t *a, *b; lvec_t *as, *bs;
- aubio_filter_set_samplerate (f, samplerate);
- bs = aubio_filter_get_feedforward (f);
- as = aubio_filter_get_feedback (f);
- b = bs->data, a = as->data;
- order = aubio_filter_get_order (f);
+ if ((sint_t)samplerate <= 0) {
+ AUBIO_ERROR("aubio_filter: failed setting A-weighting with samplerate %d\n", samplerate);
+ return AUBIO_FAIL;
+ }
+ if (f == NULL) {
+ AUBIO_ERROR("aubio_filter: failed setting A-weighting with filter NULL\n");
+ return AUBIO_FAIL;
+ }
+
+ order = aubio_filter_get_order (f);
if (order != 7) {
- AUBIO_ERROR ("order of A-weighting filter must be 7, not %d\n", order);
+ AUBIO_ERROR ("aubio_filter: order of A-weighting filter must be 7, not %d\n", order);
return 1;
}
+ aubio_filter_set_samplerate (f, samplerate);
+ bs = aubio_filter_get_feedforward (f);
+ as = aubio_filter_get_feedback (f);
+ b = bs->data, a = as->data;
+
/* select coefficients according to sampling frequency */
switch (samplerate) {
new_aubio_filter_a_weighting (uint_t samplerate)
{
aubio_filter_t *f = new_aubio_filter (7);
- aubio_filter_set_a_weighting (f, samplerate);
+ if (aubio_filter_set_a_weighting(f,samplerate) != AUBIO_OK) {
+ del_aubio_filter(f);
+ return NULL;
+ }
return f;
}
*/
-#ifndef _AUBIO_FILTER_A_DESIGN_H
-#define _AUBIO_FILTER_A_DESIGN_H
+#ifndef AUBIO_FILTER_A_DESIGN_H
+#define AUBIO_FILTER_A_DESIGN_H
/** \file
}
#endif
-#endif /* _AUBIO_FILTER_A_DESIGN_H */
+#endif /* AUBIO_FILTER_A_DESIGN_H */
bs->data[2] = b2;
as->data[0] = 1.;
as->data[1] = a1;
- as->data[1] = a2;
+ as->data[2] = a2;
return AUBIO_OK;
}
*/
-#ifndef _AUBIO_FILTER_BIQUAD_H
-#define _AUBIO_FILTER_BIQUAD_H
+#ifndef AUBIO_FILTER_BIQUAD_H
+#define AUBIO_FILTER_BIQUAD_H
/** \file
}
#endif
-#endif /* _AUBIO_FILTER_BIQUAD_H */
+#endif /* AUBIO_FILTER_BIQUAD_H */
aubio_filter_set_c_weighting (aubio_filter_t * f, uint_t samplerate)
{
uint_t order; lsmp_t *a, *b; lvec_t *as, *bs;
- aubio_filter_set_samplerate (f, samplerate);
- bs = aubio_filter_get_feedforward (f);
- as = aubio_filter_get_feedback (f);
- b = bs->data, a = as->data;
- order = aubio_filter_get_order (f);
+ if ((sint_t)samplerate <= 0) {
+ AUBIO_ERROR("aubio_filter: failed setting C-weighting with samplerate %d\n", samplerate);
+ return AUBIO_FAIL;
+ }
+ if (f == NULL) {
+ AUBIO_ERROR("aubio_filter: failed setting C-weighting with filter NULL\n");
+ return AUBIO_FAIL;
+ }
+
+ order = aubio_filter_get_order (f);
if ( order != 5 ) {
- AUBIO_ERROR ("order of C-weighting filter must be 5, not %d\n", order);
+ AUBIO_ERROR ("aubio_filter: order of C-weighting filter must be 5, not %d\n", order);
return 1;
}
+ aubio_filter_set_samplerate (f, samplerate);
+ bs = aubio_filter_get_feedforward (f);
+ as = aubio_filter_get_feedback (f);
+ b = bs->data, a = as->data;
+
/* select coefficients according to sampling frequency */
switch (samplerate) {
aubio_filter_t * new_aubio_filter_c_weighting (uint_t samplerate) {
aubio_filter_t * f = new_aubio_filter(5);
- aubio_filter_set_c_weighting (f, samplerate);
+ if (aubio_filter_set_c_weighting(f,samplerate) != AUBIO_OK) {
+ del_aubio_filter(f);
+ return NULL;
+ }
return f;
}
-
*/
-#ifndef _AUBIO_FILTER_C_DESIGN_H
-#define _AUBIO_FILTER_C_DESIGN_H
+#ifndef AUBIO_FILTER_C_DESIGN_H
+#define AUBIO_FILTER_C_DESIGN_H
/** \file
}
#endif
-#endif /* _AUBIO_FILTER_C_DESIGN_H */
+#endif /* AUBIO_FILTER_C_DESIGN_H */
};
void
-aubio_filter_do_outplace (aubio_filter_t * f, fvec_t * in, fvec_t * out)
+aubio_filter_do_outplace (aubio_filter_t * f, const fvec_t * in, fvec_t * out)
{
fvec_copy (in, out);
aubio_filter_do (f, out);
}
lvec_t *
-aubio_filter_get_feedback (aubio_filter_t * f)
+aubio_filter_get_feedback (const aubio_filter_t * f)
{
return f->a;
}
lvec_t *
-aubio_filter_get_feedforward (aubio_filter_t * f)
+aubio_filter_get_feedforward (const aubio_filter_t * f)
{
return f->b;
}
uint_t
-aubio_filter_get_order (aubio_filter_t * f)
+aubio_filter_get_order (const aubio_filter_t * f)
{
return f->order;
}
uint_t
-aubio_filter_get_samplerate (aubio_filter_t * f)
+aubio_filter_get_samplerate (const aubio_filter_t * f)
{
return f->samplerate;
}
new_aubio_filter (uint_t order)
{
aubio_filter_t *f = AUBIO_NEW (aubio_filter_t);
+ if ((sint_t)order < 1) {
+ AUBIO_FREE(f);
+ return NULL;
+ }
f->x = new_lvec (order);
f->y = new_lvec (order);
f->a = new_lvec (order);
f->samplerate = 0;
f->order = order;
/* set default to identity */
- f->a->data[1] = 1.;
+ f->a->data[0] = 1.;
+ f->b->data[0] = 1.;
return f;
}
*/
-#ifndef _AUBIO_FILTER_H
-#define _AUBIO_FILTER_H
+#ifndef AUBIO_FILTER_H
+#define AUBIO_FILTER_H
/** \file
\param out output vector to store filtered input
*/
-void aubio_filter_do_outplace (aubio_filter_t * f, fvec_t * in, fvec_t * out);
+void aubio_filter_do_outplace (aubio_filter_t * f, const fvec_t * in, fvec_t * out);
/** filter input vector forward and backward
\return a pointer to the \f$ a_0 ... a_i ... a_P \f$ coefficients
*/
-lvec_t *aubio_filter_get_feedback (aubio_filter_t * f);
+lvec_t *aubio_filter_get_feedback (const aubio_filter_t * f);
/** returns a pointer to feedforward coefficients \f$ b_i \f$
\return a pointer to the \f$ b_0 ... b_i ... b_P \f$ coefficients
*/
-lvec_t *aubio_filter_get_feedforward (aubio_filter_t * f);
+lvec_t *aubio_filter_get_feedforward (const aubio_filter_t * f);
/** get order of the filter
\return the order of the filter
*/
-uint_t aubio_filter_get_order (aubio_filter_t * f);
+uint_t aubio_filter_get_order (const aubio_filter_t * f);
/** get sampling rate of the filter
\return the sampling rate of the filter, in Hz
*/
-uint_t aubio_filter_get_samplerate (aubio_filter_t * f);
+uint_t aubio_filter_get_samplerate (const aubio_filter_t * f);
/** get sampling rate of the filter
}
#endif
-#endif /* _AUBIO_FILTER_H */
+#endif /* AUBIO_FILTER_H */
*/
-#include "config.h"
-
#include "aubio_priv.h"
#include "fvec.h"
#include "temporal/resampler.h"
-#if HAVE_SAMPLERATE
+#ifdef HAVE_SAMPLERATE
+
+#if HAVE_AUBIO_DOUBLE
+#error "Should not use libsamplerate with aubio in double precision"
+#endif
#include <samplerate.h> /* from libsamplerate */
}
void
-aubio_resampler_do (aubio_resampler_t * s, fvec_t * input, fvec_t * output)
+aubio_resampler_do (aubio_resampler_t * s, const fvec_t * input, fvec_t * output)
{
s->proc->input_frames = input->length;
s->proc->output_frames = output->length;
}
void
-aubio_resampler_do (aubio_resampler_t * s UNUSED, fvec_t * input UNUSED, fvec_t * output UNUSED)
+aubio_resampler_do (aubio_resampler_t * s UNUSED, const fvec_t * input UNUSED, fvec_t * output UNUSED)
{
}
#endif /* HAVE_SAMPLERATE */
*/
-#ifndef _AUBIO_RESAMPLER_H
-#define _AUBIO_RESAMPLER_H
+#ifndef AUBIO_RESAMPLER_H
+#define AUBIO_RESAMPLER_H
/** \file
\param output output buffer of size N*ratio
*/
-void aubio_resampler_do (aubio_resampler_t * s, fvec_t * input,
+void aubio_resampler_do (aubio_resampler_t * s, const fvec_t * input,
fvec_t * output);
#ifdef __cplusplus
}
#endif
-#endif /* _AUBIO_RESAMPLER_H */
+#endif /* AUBIO_RESAMPLER_H */
*/
-#ifndef _AUBIO__TYPES_H
-#define _AUBIO__TYPES_H
+#ifndef AUBIO_TYPES_H
+#define AUBIO_TYPES_H
/** \file
}
#endif
-#endif /* _AUBIO__TYPES_H */
+#endif /* AUBIO_TYPES_H */
}
}
-smpl_t aubio_hist_mean (aubio_hist_t *s) {
+smpl_t aubio_hist_mean (const aubio_hist_t *s) {
uint_t j;
smpl_t tmp = 0.0;
for (j=0; j < s->nelems; j++)
* Big hacks to implement an histogram
*/
-#ifndef _AUBIO_HIST_H
-#define _AUBIO_HIST_H
+#ifndef AUBIO_HIST_H
+#define AUBIO_HIST_H
#ifdef __cplusplus
extern "C" {
/** compute the histogram ignoring null elements */
void aubio_hist_do_notnull(aubio_hist_t *s, fvec_t * input);
/** compute the mean of the histogram */
-smpl_t aubio_hist_mean(aubio_hist_t *s);
+smpl_t aubio_hist_mean(const aubio_hist_t *s);
/** weight the histogram */
void aubio_hist_weight(aubio_hist_t *s);
/** compute dynamic histogram for non-null elements */
}
#endif
-#endif /* _AUBIO_HIST_H */
+#endif /* AUBIO_HIST_H */
--- /dev/null
+/*
+ Copyright (C) 2016 Paul Brossier <piem@aubio.org>
+
+ This file is part of aubio.
+
+ aubio is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ aubio is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with aubio. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "aubio_priv.h"
+#include "log.h"
+
+/** array of pointers to logging functions, one per level */
+static aubio_log_function_t aubio_log_function[AUBIO_LOG_LAST_LEVEL];
+/** array of pointers to closure passed to logging functions, one per level */
+static void* aubio_log_user_data[AUBIO_LOG_LAST_LEVEL];
+/** buffer for logging messages */
+static char aubio_log_buffer[512];
+
+/** private function used by default by logging functions */
+void
+aubio_default_log(sint_t level, const char_t *message, void * data UNUSED)
+{
+ FILE *out;
+ out = stdout;
+ if (level == AUBIO_LOG_ERR || level == AUBIO_LOG_DBG || level == AUBIO_LOG_WRN) {
+ out = stderr;
+ }
+ fprintf(out, "%s", message);
+ //fflush(out);
+}
+
+uint_t
+aubio_log(sint_t level, const char_t *fmt, ...)
+{
+ aubio_log_function_t fun = NULL;
+
+ va_list args;
+ va_start(args, fmt);
+ vsnprintf(aubio_log_buffer, sizeof(aubio_log_buffer), fmt, args);
+ va_end(args);
+
+ if ((level >= 0) && (level < AUBIO_LOG_LAST_LEVEL)) {
+ fun = aubio_log_function[level];
+ if (fun != NULL) {
+ (*fun)(level, aubio_log_buffer, aubio_log_user_data[level]);
+ } else {
+ aubio_default_log(level, aubio_log_buffer, NULL);
+ }
+ }
+ return AUBIO_FAIL;
+}
+
+void
+aubio_log_reset(void)
+{
+ uint_t i = 0;
+ for (i = 0; i < AUBIO_LOG_LAST_LEVEL; i++) {
+ aubio_log_set_level_function(i, aubio_default_log, NULL);
+ }
+}
+
+aubio_log_function_t
+aubio_log_set_level_function(sint_t level, aubio_log_function_t fun, void * data)
+{
+ aubio_log_function_t old = NULL;
+ if ((level >= 0) && (level < AUBIO_LOG_LAST_LEVEL)) {
+ old = aubio_log_function[level];
+ aubio_log_function[level] = fun;
+ aubio_log_user_data[level] = data;
+ }
+ return old;
+}
+
+void
+aubio_log_set_function(aubio_log_function_t fun, void * data) {
+ uint_t i = 0;
+ for (i = 0; i < AUBIO_LOG_LAST_LEVEL; i++) {
+ aubio_log_set_level_function(i, fun, data);
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2016 Paul Brossier <piem@aubio.org>
+
+ This file is part of aubio.
+
+ aubio is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ aubio is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with aubio. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef AUBIO_LOG_H
+#define AUBIO_LOG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** \file
+
+ Logging features
+
+ This file specifies ::aubio_log_set_function and
+ ::aubio_log_set_level_function, which let you define one or several custom
+ logging functions to redirect warnings and errors from aubio to your
+ application. The custom function should have the prototype defined in
+ ::aubio_log_function_t.
+
+ After a call to ::aubio_log_set_level_function, ::aubio_log_reset can be used
+ to reset each logging functions to the default ones.
+
+ \example utils/test-log.c
+
+*/
+
+/** list of logging levels */
+enum aubio_log_level {
+ AUBIO_LOG_ERR, /**< critical errors */
+ AUBIO_LOG_INF, /**< infos */
+ AUBIO_LOG_MSG, /**< general messages */
+ AUBIO_LOG_DBG, /**< debug messages */
+ AUBIO_LOG_WRN, /**< warnings */
+ AUBIO_LOG_LAST_LEVEL, /**< number of valid levels */
+};
+
+/** Logging function prototype, to be passed to ::aubio_log_set_function
+
+ \param level log level
+ \param message text to log
+ \param data optional closure used by the callback
+
+ See @ref utils/test-log.c for an example of logging function.
+
+ */
+typedef void (*aubio_log_function_t)(sint_t level, const char_t *message, void
+ *data);
+
+/** Set logging function for all levels
+
+ \param fun the function to be used to log, of type ::aubio_log_function_t
+ \param data optional closure to be passed to the function (can be NULL if
+ nothing to pass)
+
+ */
+void aubio_log_set_function(aubio_log_function_t fun, void* data);
+
+/** Set logging function for a given level
+
+ \param level the level for which to set the logging function
+ \param fun the function to be used to log, of type ::aubio_log_function_t
+ \param data optional closure to be passed to the function (can be NULL if
+ nothing to pass)
+
+*/
+aubio_log_function_t aubio_log_set_level_function(sint_t level,
+ aubio_log_function_t fun, void* data);
+
+/** Reset all logging functions to the default one
+
+ After calling this function, the default logging function will be used to
+ print error, warning, normal, and debug messages to `stdout` or `stderr`.
+
+ */
+void aubio_log_reset(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AUBIO_LOG_H */
*/
-#include "config.h"
#include "aubio_priv.h"
#include "parameter.h"
return err;
}
-smpl_t aubio_parameter_get_current_value ( aubio_parameter_t * s )
+smpl_t aubio_parameter_get_current_value ( const aubio_parameter_t * s )
{
return s->current_value;
}
return AUBIO_OK;
}
-uint_t aubio_parameter_get_steps ( aubio_parameter_t * param )
+uint_t aubio_parameter_get_steps ( const aubio_parameter_t * param )
{
return param->steps;
}
return AUBIO_OK;
}
-smpl_t aubio_parameter_get_min_value ( aubio_parameter_t * param )
+smpl_t aubio_parameter_get_min_value ( const aubio_parameter_t * param )
{
return param->min_value;
}
return AUBIO_OK;
}
-smpl_t aubio_parameter_get_max_value ( aubio_parameter_t * param )
+smpl_t aubio_parameter_get_max_value ( const aubio_parameter_t * param )
{
return param->max_value;
}
*/
-#ifndef _AUBIO_PARAMETER_H
-#define _AUBIO_PARAMETER_H
+#ifndef AUBIO_PARAMETER_H
+#define AUBIO_PARAMETER_H
/** \file
\return current value
*/
-smpl_t aubio_parameter_get_current_value ( aubio_parameter_t * param );
+smpl_t aubio_parameter_get_current_value ( const aubio_parameter_t * param );
/** set current parameter value, skipping interpolation
\return number of steps
*/
-uint_t aubio_parameter_get_steps ( aubio_parameter_t * param);
+uint_t aubio_parameter_get_steps ( const aubio_parameter_t * param);
/** set minimum value of this parameter
\return minimum value
*/
-smpl_t aubio_parameter_get_min_value ( aubio_parameter_t * param );
+smpl_t aubio_parameter_get_min_value ( const aubio_parameter_t * param );
/** set maximum value of this parameter
\return maximum value
*/
-smpl_t aubio_parameter_get_max_value ( aubio_parameter_t * param );
+smpl_t aubio_parameter_get_max_value ( const aubio_parameter_t * param );
/** destroy ::aubio_parameter_t object
}
#endif
-#endif /* _AUBIO_PARAMETER_H */
+#endif /* AUBIO_PARAMETER_H */
*/
};
-aubio_scale_t * new_aubio_scale (smpl_t ilow, smpl_t ihig,
+aubio_scale_t * new_aubio_scale (smpl_t ilow, smpl_t ihig,
smpl_t olow, smpl_t ohig) {
aubio_scale_t * s = AUBIO_NEW(aubio_scale_t);
aubio_scale_set_limits (s, ilow, ihig, olow, ohig);
\f$ y = (x - ilow)*(ohig-olow)/(ihig-ilow) + olow \f$
*/
-#ifndef _AUBIO_SCALE_H
-#define _AUBIO_SCALE_H
+#ifndef AUBIO_SCALE_H
+#define AUBIO_SCALE_H
#ifdef __cplusplus
extern "C" {
}
#endif
-#endif /* _AUBIO_SCALE_H */
+#endif /* AUBIO_SCALE_H */
--- /dev/null
+/*
+ Copyright (C) 2016 Paul Brossier <piem@aubio.org>
+
+ This file is part of aubio.
+
+ aubio is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ aubio is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with aubio. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+/** @file
+
+ Windows dll entry point.
+
+*/
+
+#include "aubio_priv.h"
+
+#ifdef HAVE_WIN_HACKS
+
+#ifndef __GNUC__ // do not include msvc headers when using gcc/mingw32
+
+// latest version
+#include <SDKDDKVer.h>
+// for earlier versions, include WinSDKVer.h and set _WIN32_WINNT macro
+
+#endif /* __GNUC__ */
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#include "aubio.h"
+
+BOOL APIENTRY DllMain( HMODULE hModule,
+ DWORD ul_reason_for_call,
+ LPVOID lpReserved )
+{
+ switch (ul_reason_for_call)
+ {
+ case DLL_PROCESS_ATTACH:
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+ return TRUE;
+}
+
+#endif
-#include "config.h"
#include "aubio_priv.h"
#include "types.h"
#include "fvec.h"
*/
-#ifndef _AUBIO__VECUTILS_H
-#define _AUBIO__VECUTILS_H
+#ifndef AUBIO_VECUTILS_H
+#define AUBIO_VECUTILS_H
#ifdef __cplusplus
extern "C" {
}
#endif
-#endif /* _AUBIO__VECUTILS_H */
+#endif /* AUBIO_VECUTILS_H */
# vim:set syntax=python:
uselib = []
+uselib += ['M']
uselib += ['FFTW3', 'FFTW3F']
uselib += ['SAMPLERATE']
uselib += ['SNDFILE']
uselib += ['AVUTIL']
uselib += ['BLAS']
-# build each source files
source = ctx.path.ant_glob('*.c **/*.c')
+
ctx(features = 'c',
source = source,
includes = ['.'],
- uselib = uselib,
- lib = 'm',
+ use = uselib,
target = 'lib_objects')
# build libaubio.so (cshlib) and/or libaubio.a (cstlib)
if ctx.env['DEST_OS'] in ['ios', 'iosimulator']:
build_features = ['cstlib', 'cshlib']
elif ctx.env['DEST_OS'] in ['win32', 'win64']:
- build_features = ['cshlib']
-else: #linux, darwin, android, mingw, ...
- build_features = ['cshlib', 'cstlib']
+ build_features = ['cstlib', 'cshlib']
+elif ctx.env['DEST_OS'] in ['emscripten']:
+ build_features = ['cstlib']
+elif '--static' in ctx.env['LDFLAGS'] or '--static' in ctx.env['LINKFLAGS']:
+ # static in cflags, ...
+ build_features = ['cstlib']
+else:
+ # linux, darwin, android, mingw, ...
+ build_features = ['cstlib', 'cshlib']
+
+# also install static lib
+from waflib.Tools.c import cstlib
+from waflib.Tools.fc import fcstlib
+fcstlib.inst_to = cstlib.inst_to = '${LIBDIR}'
for target in build_features:
ctx(features = 'c ' + target,
- use = ['lib_objects'],
- uselib = uselib,
- lib = 'm',
+ use = uselib + ['lib_objects'],
target = 'aubio',
vnum = ctx.env['LIB_VERSION'])
# install headers, except _priv.h ones
-ctx.install_files('${PREFIX}/include/aubio/',
+ctx.install_files('${INCLUDEDIR}/aubio/',
ctx.path.ant_glob('**/*.h', excl = ['**_priv.h', 'config.h']),
relative_trick=True)
#define AUBIO_UNSTABLE 1
#include <aubio.h>
-#include "config.h"
#include "utils_tests.h"
// this file uses the unstable aubio api, please use aubio_sink instead
#define AUBIO_UNSTABLE 1
#include <aubio.h>
-#include "config.h"
#include "utils_tests.h"
// this file uses the unstable aubio api, please use aubio_sink instead
if (!s) { err = 1; goto beach; }
fvec_t *vec = new_fvec(hop_size);
+ uint_t n_frames_expected = aubio_source_get_duration(s);
+
samplerate = aubio_source_get_samplerate(s);
do {
n_frames += read;
} while ( read == hop_size );
- PRINT_MSG("read %d frames at %dHz (%d blocks) from %s\n", n_frames, samplerate,
- n_frames / hop_size, source_path);
+ PRINT_MSG("read %d frames (expected %d) at %dHz (%d blocks) from %s\n",
+ n_frames, n_frames_expected, samplerate, n_frames / hop_size,
+ source_path);
// close the file (optional)
aubio_source_close(s);
if (!s) { err = 1; goto beach; }
fvec_t *vec = new_fvec(hop_size);
+ uint_t n_frames_expected = aubio_source_apple_audio_get_duration(s);
+
samplerate = aubio_source_apple_audio_get_samplerate(s);
do {
n_frames += read;
} while ( read == hop_size );
- PRINT_MSG("read %d frames at %dHz (%d blocks) from %s\n", n_frames, samplerate,
- n_frames / hop_size, source_path);
+ PRINT_MSG("read %d frames (expected %d) at %dHz (%d blocks) from %s\n",
+ n_frames, n_frames_expected, samplerate, n_frames / hop_size,
+ source_path);
del_fvec (vec);
del_aubio_source_apple_audio (s);
if (!s) { err = 1; goto beach; }
fvec_t *vec = new_fvec(hop_size);
+ uint_t n_frames_expected = aubio_source_avcodec_get_duration(s);
+
samplerate = aubio_source_avcodec_get_samplerate(s);
do {
n_frames += read;
} while ( read == hop_size );
- PRINT_MSG("read %d frames at %dHz (%d blocks) from %s\n", n_frames, samplerate,
- n_frames / hop_size, source_path);
+ PRINT_MSG("read %d frames (expected %d) at %dHz (%d blocks) from %s\n",
+ n_frames, n_frames_expected, samplerate, n_frames / hop_size,
+ source_path);
del_fvec (vec);
del_aubio_source_avcodec (s);
if (!s) { err = 1; goto beach; }
fvec_t *vec = new_fvec(hop_size);
+ uint_t n_frames_expected = aubio_source_sndfile_get_duration(s);
+
samplerate = aubio_source_sndfile_get_samplerate(s);
do {
n_frames += read;
} while ( read == hop_size );
- PRINT_MSG("read %d frames at %dHz (%d blocks) from %s\n", n_frames, samplerate,
- n_frames / hop_size, source_path);
+ PRINT_MSG("read %d frames (expected %d) at %dHz (%d blocks) from %s\n",
+ n_frames, n_frames_expected, samplerate, n_frames / hop_size,
+ source_path);
del_fvec (vec);
del_aubio_source_sndfile (s);
aubio_source_wavread_t * s =
new_aubio_source_wavread(source_path, samplerate, hop_size);
+
if (!s) { err = 1; goto beach; }
fvec_t *vec = new_fvec(hop_size);
+ uint_t n_frames_expected = aubio_source_wavread_get_duration(s);
+
samplerate = aubio_source_wavread_get_samplerate(s);
do {
n_frames += read;
} while ( read == hop_size );
- PRINT_MSG("read %d frames at %dHz (%d blocks) from %s\n", n_frames, samplerate,
- n_frames / hop_size, source_path);
+ PRINT_MSG("read %d frames (expected %d) at %dHz (%d blocks) from %s\n",
+ n_frames, n_frames_expected, samplerate, n_frames / hop_size,
+ source_path);
del_fvec (vec);
del_aubio_source_wavread (s);
{
int return_code = 0;
uint_t i, n_iters = 100; // number of iterations
- uint_t win_s = 500; // window size
+ uint_t win_s = 512; // window size
fvec_t * in = new_fvec (win_s); // input buffer
cvec_t * fftgrain = new_cvec (win_s); // fft norm and phase
fvec_t * out = new_fvec (win_s); // output buffer
// ...
cvec_print (fftgrain);
- // optionnaly rebuild the signa
+ // optionally rebuild the signal
aubio_pvoc_rdo(pv,fftgrain,out);
// and do something with the result
// create some vectors
fvec_t * in = new_fvec (hop_size); // input audio buffer
- fvec_t * out = new_fvec (2); // output position
+ fvec_t * out = new_fvec (1); // output position
// create tempo object
aubio_tempo_t * o = new_aubio_tempo("default", win_size, hop_size, samplerate);
// samplerate unknown
f = new_aubio_filter_a_weighting (4200);
- del_aubio_filter (f);
+ if (!f) {
+ //PRINT_MSG ("failed creating A-weighting filter with samplerate=4200Hz\n");
+ }
// order to small
f = new_aubio_filter (2);
- aubio_filter_set_a_weighting (f, samplerate);
+ if (aubio_filter_set_a_weighting (f, samplerate) != 0) {
+ //PRINT_MSG ("failed setting filter to A-weighting\n");
+ }
del_aubio_filter (f);
// order to big
f = new_aubio_filter (12);
- aubio_filter_set_a_weighting (f, samplerate);
+ if (aubio_filter_set_a_weighting (f, samplerate) != 0) {
+ //PRINT_MSG ("failed setting filter to A-weighting\n");
+ }
del_aubio_filter (f);
return 0;
// samplerate unknown
f = new_aubio_filter_c_weighting (4200);
- del_aubio_filter (f);
+ if (!f) {
+ //PRINT_WRN ("failed creating C-weighting filter with samplerate=4200Hz");
+ }
// order to small
f = new_aubio_filter (2);
- aubio_filter_set_c_weighting (f, samplerate);
+ if (aubio_filter_set_c_weighting (f, samplerate) != 0) {
+ //PRINT_WRN ("failed setting filter to C-weighting");
+ }
del_aubio_filter (f);
// order to big
f = new_aubio_filter (12);
- aubio_filter_set_c_weighting (f, samplerate);
+ if (aubio_filter_set_c_weighting (f, samplerate) != 0) {
+ //PRINT_WRN ("failed setting filter to C-weighting");
+ }
del_aubio_filter (f);
return 0;
uint_t win_s = 32; // window size
lvec_t * sp = new_lvec (win_s); // input buffer
lvec_set_sample (sp, 2./3., 0);
- PRINT_MSG("%lf\n", lvec_get_sample (sp, 0));
+ PRINT_MSG(AUBIO_LSMP_FMT "\n", lvec_get_sample (sp, 0));
lvec_print (sp);
lvec_ones (sp);
lvec_print (sp);
--- /dev/null
+#include <aubio.h>
+#include <stdio.h>
+#include "aubio_priv.h"
+
+const char_t *hdr = "CUSTOM HEADER: ";
+const char_t *hdr2 = "OTHER HEADER: ";
+
+/* an example of logging function that adds a custom header and prints
+ * aubio debug messages on stdout instead of stderr */
+void logging(int level, const char_t *message, void *data) {
+ FILE *out;
+ //fprintf(stdout, "using custom logging function\n");
+ if (level == AUBIO_LOG_ERR) {
+ out = stderr;
+ } else {
+ out = stdout;
+ }
+ if ((level >= 0) && (data != NULL)) {
+ fprintf(out, "%s", (const char_t *)data);
+ }
+ fprintf(out, "%s", message);
+}
+
+int main (void)
+{
+ fprintf(stdout, "### testing normal logging\n");
+ AUBIO_ERR("testing normal AUBIO_LOG_ERR\n");
+ AUBIO_INF("testing normal AUBIO_LOG_INF\n");
+ AUBIO_WRN("testing normal AUBIO_LOG_WRN\n");
+ AUBIO_MSG("testing normal AUBIO_LOG_MSG\n");
+ AUBIO_DBG("testing normal AUBIO_LOG_DBG\n");
+
+ fprintf(stdout, "### testing with one custom function\n");
+ aubio_log_set_function(logging, (void *)hdr);
+ AUBIO_ERR("testing custom set_function AUBIO_LOG_ERR\n");
+ AUBIO_INF("testing custom set_function AUBIO_LOG_INF\n");
+ AUBIO_WRN("testing custom set_function AUBIO_LOG_WRN\n");
+ AUBIO_MSG("testing custom set_function AUBIO_LOG_MSG\n");
+ AUBIO_DBG("testing custom set_function AUBIO_LOG_DBG\n");
+
+ fprintf(stdout, "### testing resetted logging\n");
+ aubio_log_reset();
+ AUBIO_ERR("testing again normal AUBIO_LOG_ERR\n");
+ AUBIO_INF("testing again normal AUBIO_LOG_INF\n");
+ AUBIO_WRN("testing again normal AUBIO_LOG_WRN\n");
+ AUBIO_MSG("testing again normal AUBIO_LOG_MSG\n");
+ AUBIO_DBG("testing again normal AUBIO_LOG_DBG\n");
+
+ fprintf(stdout, "### testing per level customization\n");
+ aubio_log_set_level_function(AUBIO_LOG_ERR, logging, (void *)hdr2);
+ aubio_log_set_level_function(AUBIO_LOG_WRN, logging, NULL);
+ aubio_log_set_level_function(AUBIO_LOG_MSG, logging, (void *)hdr);
+ AUBIO_ERR("testing custom set_level_function AUBIO_LOG_ERR\n");
+ AUBIO_INF("testing again normal AUBIO_LOG_INF\n");
+ AUBIO_WRN("testing custom set_level_function AUBIO_LOG_WRN with data=NULL\n");
+ AUBIO_MSG("testing custom set_level_function AUBIO_LOG_MSG\n");
+ AUBIO_DBG("testing again normal AUBIO_LOG_DBG\n");
+
+ return 0;
+}
#include <assert.h>
#include "config.h"
+#ifdef HAVE_C99_VARARGS_MACROS
+#define PRINT_ERR(...) fprintf(stderr, "AUBIO-TESTS ERROR: " __VA_ARGS__)
+#define PRINT_MSG(...) fprintf(stdout, __VA_ARGS__)
+#define PRINT_DBG(...) fprintf(stderr, __VA_ARGS__)
+#define PRINT_WRN(...) fprintf(stderr, "AUBIO-TESTS WARNING: " __VA_ARGS__)
+#else
#define PRINT_ERR(format, args...) fprintf(stderr, "AUBIO-TESTS ERROR: " format , ##args)
#define PRINT_MSG(format, args...) fprintf(stdout, format , ##args)
#define PRINT_DBG(format, args...) fprintf(stderr, format , ##args)
#define PRINT_WRN(format, args...) fprintf(stderr, "AUBIO-TESTS WARNING: " format, ##args)
+#endif
+
+#ifndef M_PI
+#define M_PI (3.14159265358979323846)
+#endif
+
+#ifndef RAND_MAX
+#define RAND_MAX 32767
+#endif
-#ifdef HAVE_WIN_HACKS
+// are we on windows ? or are we using -std=c99 ?
+#if defined(HAVE_WIN_HACKS) || defined(__STRICT_ANSI__)
// http://en.wikipedia.org/wiki/Linear_congruential_generator
// no srandom/random on win32
# vim:set syntax=python:
-for target_name in ctx.path.ant_glob('src/**/*.c'):
- uselib = []
- uselib += ['FFTW3', 'FFTW3F']
- uselib += ['SAMPLERATE']
- uselib += ['SNDFILE']
- uselib += ['AVCODEC']
- uselib += ['AVFORMAT']
- uselib += ['AVRESAMPLE']
- uselib += ['AVUTIL']
- uselib += ['JACK']
- uselib += ['BLAS']
- includes = ['../src', '.']
- extra_source = []
+import os.path
+uselib = ['aubio']
+
+includes = ['../src', '.']
+programs_sources = ctx.path.ant_glob('src/**/*.c')
+
+for source_file in programs_sources:
+ target = os.path.basename(os.path.splitext(str(source_file))[0])
bld(features = 'c cprogram test',
- lib = 'm',
- uselib = uselib,
- source = [target_name] + extra_source,
- target = str(target_name).split('.')[0],
+ source = source_file,
+ target = target,
includes = includes,
+ use = uselib,
install_path = None,
defines = 'AUBIO_UNSTABLE_API=1',
- cflags = ['-g'],
- use = 'aubio')
+ )
# have Python installed, you do *not* need to install anything to build aubio.
# For more info about waf, see http://code.google.com/p/waf/ .
+import sys
+
APPNAME = 'aubio'
# source VERSION
help = help_disable_str )
def options(ctx):
+ ctx.add_option('--build-type', action = 'store',
+ default = "release",
+ choices = ('debug', 'release'),
+ dest = 'build_type',
+ help = 'whether to compile with (--build-type=release) or without (--build-type=debug) '\
+ ' compiler opimizations [default: release]')
add_option_enable_disable(ctx, 'fftw3f', default = False,
help_str = 'compile with fftw3f instead of ooura (recommended)',
help_disable_str = 'do not compile with fftw3f')
add_option_enable_disable(ctx, 'apple-audio', default = None,
help_str = 'use CoreFoundation (darwin only) (auto)',
help_disable_str = 'do not use CoreFoundation framework')
- add_option_enable_disable(ctx, 'atlas', default = None,
- help_str = 'use Atlas library (auto)',
+ add_option_enable_disable(ctx, 'atlas', default = False,
+ help_str = 'use Atlas library (no)',
help_disable_str = 'do not use Atlas library')
+ add_option_enable_disable(ctx, 'wavread', default = True,
+ help_str = 'compile with source_wavread (default)',
+ help_disable_str = 'do not compile source_wavread')
+ add_option_enable_disable(ctx, 'wavwrite', default = True,
+ help_str = 'compile with source_wavwrite (default)',
+ help_disable_str = 'do not compile source_wavwrite')
+
+ add_option_enable_disable(ctx, 'docs', default = None,
+ help_str = 'build documentation (auto)',
+ help_disable_str = 'do not build documentation')
ctx.add_option('--with-target-platform', type='string',
help='set target platform for cross-compilation', dest='target_platform')
ctx.load('waf_unit_test')
ctx.load('gnu_dirs')
- target_platform = Options.platform
+ # check for common headers
+ ctx.check(header_name='stdlib.h')
+ ctx.check(header_name='stdio.h')
+ ctx.check(header_name='math.h')
+ ctx.check(header_name='string.h')
+ ctx.check(header_name='limits.h')
+ ctx.check(header_name='stdarg.h')
+ ctx.check(header_name='getopt.h', mandatory = False)
+ ctx.check(header_name='unistd.h', mandatory = False)
+
+ target_platform = sys.platform
if ctx.options.target_platform:
target_platform = ctx.options.target_platform
ctx.env['DEST_OS'] = target_platform
- if 'CL.exe' not in ctx.env.CC[0]:
- ctx.env.CFLAGS += ['-g', '-Wall', '-Wextra']
+ if ctx.options.build_type == "debug":
+ ctx.define('DEBUG', 1)
+ else:
+ ctx.define('NDEBUG', 1)
+
+ if ctx.env.CC_NAME != 'msvc':
+ if ctx.options.build_type == "debug":
+ # no optimization in debug mode
+ ctx.env.prepend_value('CFLAGS', ['-O0'])
+ else:
+ # default to -O2 in release mode
+ ctx.env.prepend_value('CFLAGS', ['-O2'])
+ # enable debug symbols and configure warnings
+ ctx.env.prepend_value('CFLAGS', ['-g', '-Wall', '-Wextra'])
else:
- ctx.env.CFLAGS += ['-Wall']
+ # enable debug symbols
+ ctx.env.CFLAGS += ['/Z7', '/FS']
+ ctx.env.LINKFLAGS += ['/DEBUG', '/INCREMENTAL:NO']
+ # configure warnings
+ ctx.env.CFLAGS += ['/W4', '/D_CRT_SECURE_NO_WARNINGS']
+ # set optimization level and runtime libs
+ if (ctx.options.build_type == "release"):
+ ctx.env.CFLAGS += ['/Ox']
+ ctx.env.CFLAGS += ['/MD']
+ else:
+ assert(ctx.options.build_type == "debug")
+ ctx.env.CFLAGS += ['/MDd']
+
+ ctx.check_cc(lib='m', uselib_store='M', mandatory=False)
if target_platform not in ['win32', 'win64']:
ctx.env.CFLAGS += ['-fPIC']
if target_platform == 'darwin' and ctx.options.enable_fat:
ctx.env.CFLAGS += ['-arch', 'i386', '-arch', 'x86_64']
ctx.env.LINKFLAGS += ['-arch', 'i386', '-arch', 'x86_64']
+ MINSDKVER="10.4"
+ ctx.env.CFLAGS += [ '-mmacosx-version-min=' + MINSDKVER ]
+ ctx.env.LINKFLAGS += [ '-mmacosx-version-min=' + MINSDKVER ]
if target_platform in [ 'darwin', 'ios', 'iosimulator']:
if (ctx.options.enable_apple_audio != False):
ctx.env.FRAMEWORK += ['CoreFoundation', 'AudioToolbox']
ctx.define('HAVE_SOURCE_APPLE_AUDIO', 1)
ctx.define('HAVE_SINK_APPLE_AUDIO', 1)
+ ctx.msg('Checking for AudioToolbox.framework', 'yes')
+ else:
+ ctx.msg('Checking for AudioToolbox.framework', 'no (disabled)', color = 'YELLOW')
if (ctx.options.enable_accelerate != False):
ctx.define('HAVE_ACCELERATE', 1)
ctx.env.FRAMEWORK += ['Accelerate']
+ ctx.msg('Checking for Accelerate framework', 'yes')
+ else:
+ ctx.msg('Checking for Accelerate framework', 'no (disabled)', color = 'YELLOW')
if target_platform in [ 'ios', 'iosimulator' ]:
MINSDKVER="6.1"
ctx.env.CFLAGS += [ '-isysroot' , SDKROOT]
ctx.env.LINKFLAGS += [ '-isysroot' , SDKROOT]
- # check for required headers
- ctx.check(header_name='stdlib.h')
- ctx.check(header_name='stdio.h')
- ctx.check(header_name='math.h')
- ctx.check(header_name='string.h')
- ctx.check(header_name='limits.h')
+ if target_platform == 'emscripten':
+ import os.path
+ ctx.env.CFLAGS += [ '-I' + os.path.join(os.environ['EMSCRIPTEN'], 'system', 'include') ]
+ ctx.env.CFLAGS += ['-Oz']
+ ctx.env.cprogram_PATTERN = "%s.js"
+ if (ctx.options.enable_atlas != True):
+ ctx.options.enable_atlas = False
# check support for C99 __VA_ARGS__ macros
check_c99_varargs = '''
mandatory = False):
ctx.define('HAVE_C99_VARARGS_MACROS', 1)
- # double precision mode
+ # show a message about enable_double status
if (ctx.options.enable_double == True):
- ctx.define('HAVE_AUBIO_DOUBLE', 1)
+ ctx.msg('Checking for size of smpl_t', 'double')
+ ctx.msg('Checking for size of lsmp_t', 'long double')
else:
- ctx.define('HAVE_AUBIO_DOUBLE', 0)
+ ctx.msg('Checking for size of smpl_t', 'float')
+ ctx.msg('Checking for size of lsmp_t', 'double')
# optionally use complex.h
if (ctx.options.enable_complex == True):
ctx.check(header_name='complex.h')
+ else:
+ ctx.msg('Checking if complex.h is enabled', 'no')
# check for fftw3
if (ctx.options.enable_fftw3 != False or ctx.options.enable_fftw3f != False):
mandatory = ctx.options.enable_sndfile)
# check for libsamplerate
+ if (ctx.options.enable_double):
+ if (ctx.options.enable_samplerate):
+ ctx.fatal("Could not compile aubio in double precision mode with libsamplerate")
+ else:
+ ctx.options.enable_samplerate = False
+ ctx.msg('Checking if using samplerate', 'no (disabled in double precision mode)',
+ color = 'YELLOW')
if (ctx.options.enable_samplerate != False):
ctx.check_cfg(package = 'samplerate', atleast_version = '0.0.15',
args = '--cflags --libs',
else:
ctx.msg('Checking for all libav libraries', 'not found', color = 'YELLOW')
- ctx.define('HAVE_WAVREAD', 1)
- ctx.define('HAVE_WAVWRITE', 1)
+ if (ctx.options.enable_wavread != False):
+ ctx.define('HAVE_WAVREAD', 1)
+ ctx.msg('Checking if using source_wavread', ctx.options.enable_wavread and 'yes' or 'no')
+ if (ctx.options.enable_wavwrite!= False):
+ ctx.define('HAVE_WAVWRITE', 1)
+ ctx.msg('Checking if using sink_wavwrite', ctx.options.enable_wavwrite and 'yes' or 'no')
# use ATLAS
if (ctx.options.enable_atlas != False):
# use memcpy hacks
if (ctx.options.enable_memcpy == True):
ctx.define('HAVE_MEMCPY_HACKS', 1)
- else:
- ctx.define('HAVE_MEMCPY_HACKS', 0)
# write configuration header
ctx.write_config_header('src/config.h')
+ # the following defines will be passed as arguments to the compiler
+ # instead of being written to src/config.h
+ ctx.define('HAVE_CONFIG_H', 1)
+
# add some defines used in examples
ctx.define('AUBIO_PREFIX', ctx.env['PREFIX'])
ctx.define('PACKAGE', APPNAME)
- # check if txt2man is installed, optional
- try:
- ctx.find_program('txt2man', var='TXT2MAN')
- except ctx.errors.ConfigurationError:
- ctx.to_log('txt2man was not found (ignoring)')
+ # double precision mode
+ if (ctx.options.enable_double == True):
+ ctx.define('HAVE_AUBIO_DOUBLE', 1)
- # check if doxygen is installed, optional
- try:
- ctx.find_program('doxygen', var='DOXYGEN')
- except ctx.errors.ConfigurationError:
- ctx.to_log('doxygen was not found (ignoring)')
+ if (ctx.options.enable_docs != False):
+ # check if txt2man is installed, optional
+ try:
+ ctx.find_program('txt2man', var='TXT2MAN')
+ except ctx.errors.ConfigurationError:
+ ctx.to_log('txt2man was not found (ignoring)')
+
+ # check if doxygen is installed, optional
+ try:
+ ctx.find_program('doxygen', var='DOXYGEN')
+ except ctx.errors.ConfigurationError:
+ ctx.to_log('doxygen was not found (ignoring)')
+
+ # check if sphinx-build is installed, optional
+ try:
+ ctx.find_program('sphinx-build', var='SPHINX')
+ except ctx.errors.ConfigurationError:
+ ctx.to_log('sphinx-build was not found (ignoring)')
def build(bld):
bld.env['VERSION'] = VERSION
bld.env['LIB_VERSION'] = LIB_VERSION
- # add sub directories
+ # main source
bld.recurse('src')
- if bld.env['DEST_OS'] not in ['ios', 'iosimulator']:
- pass
+
+ # add sub directories
if bld.env['DEST_OS'] not in ['ios', 'iosimulator', 'android']:
bld.recurse('examples')
bld.recurse('tests')
+ # pkg-config template
bld( source = 'aubio.pc.in' )
+ # documentation
+ txt2man(bld)
+ doxygen(bld)
+ sphinx(bld)
+
+def txt2man(bld):
# build manpages from txt files using txt2man
if bld.env['TXT2MAN']:
from waflib import TaskGen
if 'MANDIR' not in bld.env:
- bld.env['MANDIR'] = bld.env['PREFIX'] + '/share/man'
+ bld.env['MANDIR'] = bld.env['DATAROOTDIR'] + '/man'
+ bld.env.VERSION = VERSION
rule_str = '${TXT2MAN} -t `basename ${TGT} | cut -f 1 -d . | tr a-z A-Z`'
rule_str += ' -r ${PACKAGE}\\ ${VERSION} -P ${PACKAGE}'
rule_str += ' -v ${PACKAGE}\\ User\\\'s\\ manual'
)
bld( source = bld.path.ant_glob('doc/*.txt') )
+def doxygen(bld):
# build documentation from source files using doxygen
if bld.env['DOXYGEN']:
bld( name = 'doxygen', rule = 'doxygen ${SRC} > /dev/null',
source = 'doc/web.cfg',
+ target = '../doc/web/html/index.html',
cwd = 'doc')
- bld.install_files( '${PREFIX}' + '/share/doc/libaubio-doc',
+ bld.install_files( '${DATAROOTDIR}' + '/doc/libaubio-doc',
bld.path.ant_glob('doc/web/html/**'),
cwd = bld.path.find_dir ('doc/web'),
relative_trick = True)
+def sphinx(bld):
+ # build documentation from source files using sphinx-build
+ # note: build in ../doc/_build/html, otherwise waf wont install unsigned files
+ if bld.env['SPHINX']:
+ bld.env.VERSION = VERSION
+ bld( name = 'sphinx',
+ rule = '${SPHINX} -b html -D release=${VERSION} -D version=${VERSION} -a -q `dirname ${SRC}` `dirname ${TGT}`',
+ source = 'doc/conf.py',
+ target = '../doc/_build/html/index.html')
+ bld.install_files( '${DATAROOTDIR}' + '/doc/libaubio-doc/sphinx',
+ bld.path.ant_glob('doc/_build/html/**'),
+ cwd = bld.path.find_dir('doc/_build/html'),
+ relative_trick = True)
+
+# register the previous rules as build rules
+from waflib.Build import BuildContext
+
+class build_txt2man(BuildContext):
+ cmd = 'txt2man'
+ fun = 'txt2man'
+
+class build_manpages(BuildContext):
+ cmd = 'manpages'
+ fun = 'txt2man'
+
+class build_sphinx(BuildContext):
+ cmd = 'sphinx'
+ fun = 'sphinx'
+
+class build_doxygen(BuildContext):
+ cmd = 'doxygen'
+ fun = 'doxygen'
+
def shutdown(bld):
from waflib import Logs
if bld.options.target_platform in ['ios', 'iosimulator']:
Logs.pprint('RED', msg)
def dist(ctx):
- ctx.excl = ' **/.waf-1* **/*~ **/*.pyc **/*.swp **/.lock-w* **/.git*'
+ ctx.excl = ' **/.waf* **/*~ **/*.pyc **/*.swp **/*.swo **/*.swn **/.lock-w* **/.git*'
ctx.excl += ' **/build/*'
+ ctx.excl += ' doc/_build'
+ ctx.excl += ' python/demos_*'
ctx.excl += ' **/python/gen **/python/build **/python/dist'
+ ctx.excl += ' **/python/ext/config.h'
+ ctx.excl += ' **/python/lib/aubio/_aubio.so'
+ ctx.excl += ' **.egg-info'
ctx.excl += ' **/**.zip **/**.tar.bz2'
+ ctx.excl += ' **.tar.bz2'
ctx.excl += ' **/doc/full/* **/doc/web/*'
+ ctx.excl += ' **/doc/full.cfg'
ctx.excl += ' **/python/*.db'
ctx.excl += ' **/python.old/*'
+ ctx.excl += ' **/python/*/*.old'
ctx.excl += ' **/python/tests/sounds'
ctx.excl += ' **/**.asc'
+ ctx.excl += ' **/dist*'
+ ctx.excl += ' **/.DS_Store'
+ ctx.excl += ' **/.travis.yml'
+ ctx.excl += ' **/.landscape.yml'
+ ctx.excl += ' **/.appveyor.yml'