ref: f264b173a447448e0e124df2ac309b5e482e02c9
parent: 60fc05b3fadd7da5957eb8c531bfa882d35e6568
parent: 6769586029891c240afe04dec96f7c554e3803bd
author: Paul Brossier <piem@piem.org>
date: Wed Jun 22 09:00:10 EDT 2016
Merge branch 'master' into notes
--- a/.gitignore
+++ b/.gitignore
@@ -39,3 +39,7 @@
aubio-*.tar.bz2
aubio-*.zip
+
+# test sounds
+python/tests/sounds
+aubio.egg-info
--- /dev/null
+++ b/.landscape.yml
@@ -1,0 +1,5 @@
+strictness: medium
+test-warnings: true
+python-targets:
+ - 2
+ - 3
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,15 +1,64 @@
-language: c
+language: python
-sudo: false
+matrix:
+ include:
+ - python: 2.7
+ os: linux
+ compiler: gcc
+ env: ARCH=x86_64
+ - python: 2.7
+ os: linux
+ compiler: gcc
+ env: ARCH=i386
+ - python: 3.4
+ os: linux
+ compiler: gcc
+ env: ARCH=x86_64
+ - python: 3.4
+ os: linux
+ compiler: gcc
+ env: ARCH=i386 WAFOPTS=--enable-fftw3f
+ - language: C
+ os: osx
+ compiler: clang
+ env: ARCH=x86_64
+ - language: C
+ os: osx
+ compiler: clang
+ env: ARCH=i386
+ - python: 2.7
+ os: linux
+ compiler: gcc
+ env: ARCH=x86_64 HAVE_DOUBLE=1 WAFOPTS=--enable-fftw3
+ - python: 2.7
+ os: linux
+ compiler: gcc
+ env: ARCH=i386 HAVE_DOUBLE=1
+ - python: 3.4
+ os: linux
+ compiler: gcc
+ env: ARCH=x86_64 HAVE_DOUBLE=1
+ - python: 3.4
+ os: linux
+ compiler: gcc
+ env: ARCH=i386 HAVE_DOUBLE=1
+ - language: C
+ os: osx
+ compiler: clang
+ env: ARCH=x86_64 HAVE_DOUBLE=1
+ - language: C
+ os: osx
+ compiler: clang
+ env: ARCH=i386 HAVE_DOUBLE=1
+ - language: C
+ os: osx
+ compiler: clang
+ env: ARCH=x86_64 WAFOPTS=--enable-fat
+ - language: C
+ os: osx
+ compiler: clang
+ env: ARCH=i386 WAFOPTS=--enable-fat
-compiler:
- - gcc
- - clang
-
-env:
- - ARCH=i386
- - ARCH=x86_64
-
addons:
apt:
packages:
@@ -19,12 +68,34 @@
- libjack-dev
- libasound2-dev
- libfftw3-dev
- - python-dev
- - python-numpy
+ - sox
+before_install:
+ - |
+ if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
+ brew update
+ brew install sox
+ export PATH="$HOME/Library/Python/2.7/bin/:$PATH"
+ fi;
+
+
+install:
+ - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then travis_retry pip install nose2; fi
+ - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then travis_retry pip install --user nose2; fi
+
script:
+ - make create_test_sounds
- make build
- make build_python
+ - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then make test_python; fi
+ - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then make test_python_osx; fi
- make clean_python
- make clean
- make distcheck
+ - make test_pure_python
+
+notifications:
+ irc:
+ channels:
+ - "irc.freenode.org#aubio"
+ use_notice: true
--- /dev/null
+++ b/MANIFEST.in
@@ -1,0 +1,25 @@
+include AUTHORS COPYING README.md VERSION ChangeLog
+include python/README
+include Makefile wscript */wscript_build
+include waf
+include aubio.pc.in
+include nose2.cfg
+include requirements.txt
+include src/*.h
+include 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/demos/*.py
+include python/tests/*.expected
+include doc/*.txt doc/*.rst doc/*.cfg doc/Makefile doc/make.bat doc/conf.py
+include scripts/* scripts/apple/Info.plist scripts/apple/Modules/module.modulemap
+exclude python/gen/*
+exclude python/ext/config.h
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,10 @@
+WAFCMD=python waf
+
+SOX=sox
+
+ENABLE_DOUBLE := $(shell [ -z $(HAVE_DOUBLE) ] || echo --enable-double )
+TESTSOUNDS := python/tests/sounds
+
all: build
checkwaf:
@@ -4,28 +11,86 @@
@[ -f waf ] || make getwaf
getwaf:
- curl https://waf.io/waf-1.8.12 > waf
+ curl https://waf.io/waf-1.8.20 > waf
+ @chmod +x waf
+
+expandwaf:
@[ -d wafilb ] || rm -fr waflib
- @chmod +x waf && ./waf --help > /dev/null
- @mv .waf*/waflib . && rm -fr .waf-*
+ @$(WAFCMD) --help > /dev/null
+ @mv .waf*/waflib . && rm -fr .waf*
@sed '/^#==>$$/,$$d' waf > waf2 && mv waf2 waf
@chmod +x waf
-build: checkwaf
- ./waf configure
- ./waf build
+configure: checkwaf
+ $(WAFCMD) configure $(WAFOPTS) $(ENABLE_DOUBLE)
+build: configure
+ $(WAFCMD) build $(WAFOPTS)
+
build_python:
- cd python && ./setup.py build
+ python ./setup.py generate $(ENABLE_DOUBLE) build
+test_python: export LD_LIBRARY_PATH=$(PWD)/build/src
+test_python:
+ pip install -v -r requirements.txt
+ pip install -v .
+ nose2 --verbose
+ pip uninstall -y -v aubio
+
+test_python_osx:
+ # create links from ~/lib/lib* to build/src/lib*
+ [ -f build/src/libaubio.[0-9].dylib ] && ( mkdir -p ~/lib && cp -prv build/src/libaubio.4.dylib ~/lib ) || true
+ # then run the tests
+ pip install --user -v -r requirements.txt
+ pip install --user -v .
+ nose2 --verbose
+ pip uninstall -y -v aubio
+
clean_python:
- cd python && ./setup.py clean
+ ./setup.py clean
+test_pure_python:
+ -pip uninstall -v -y aubio
+ -rm -rf build/ python/gen/
+ -rm -f dist/*.egg
+ -pip install -v -r requirements.txt
+ CFLAGS=-Os python setup.py bdist_egg
+ [ "$(TRAVIS_OS_NAME)" == "osx" ] && easy_install --user dist/*.egg || \
+ easy_install dist/*.egg
+ nose2 -N 4
+ pip uninstall -v -y aubio
+
+test_pure_python_wheel:
+ -pip uninstall -v -y aubio
+ -rm -rf build/ python/gen/
+ -rm -f dist/*.whl
+ -pip install -v -r requirements.txt
+ -pip install -v wheel
+ CFLAGS=-Os python setup.py bdist_wheel --universal
+ wheel install dist/*.whl
+ nose2 -N 4
+ pip uninstall -v -y aubio
+
+build_python3:
+ python3 ./setup.py generate $(ENABLE_DOUBLE) build
+
+clean_python3:
+ python3 ./setup.py clean
+
clean:
- ./waf clean
+ $(WAFCMD) clean
-distcheck: build
- ./waf distcheck
+distcheck: checkwaf
+ $(WAFCMD) distcheck $(WAFOPTS) $(ENABLE_DOUBLE)
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" synth 1s silence 0
+ -$(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" synth 30 silence 0 vol 0.9
+ -$(SOX) -r 48000 -b 32 -n "$(TESTSOUNDS)/48000Hz_60s_sweep.wav" synth 60 sine 100-20000 vol 0.9
--- a/README.md
+++ b/README.md
@@ -68,20 +68,19 @@
The latest version of the documentation can be found at:
- http://aubio.org/documentation
+ 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
-page](http://aubio.org/download).
+page](https://aubio.org/download).
aubio uses [waf](https://waf.io/) to configure, compile, and test the source:
./waf configure
./waf build
- sudo ./waf install
If waf is not found in the directory, you can download and install it with:
@@ -89,6 +88,35 @@
aubio compiles on Linux, Mac OS X, 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
------------------------
@@ -107,7 +135,7 @@
in:
- Paul Brossier, _[Automatic annotation of musical audio for interactive
- systems](http://aubio.org/phd)_, PhD thesis, Centre for Digital music,
+ systems](https://aubio.org/phd)_, PhD thesis, Centre for Digital music,
Queen Mary University of London, London, UK, 2006.
Additional results obtained with this software were discussed in the following
@@ -114,12 +142,12 @@
papers:
- P. M. Brossier and J. P. Bello and M. D. Plumbley, [Real-time temporal
- segmentation of note objects in music signals](http://aubio.org/articles/brossier04fastnotes.pdf),
+ segmentation of note objects in music signals](https://aubio.org/articles/brossier04fastnotes.pdf),
in _Proceedings of the International Computer Music Conference_, 2004, Miami,
Florida, ICMA
- P. M. Brossier and J. P. Bello and M. D. Plumbley, [Fast labelling of note
- objects in music signals] (http://aubio.org/articles/brossier04fastnotes.pdf),
+ objects in music signals] (https://aubio.org/articles/brossier04fastnotes.pdf),
in _Proceedings of the International Symposium on Music Information Retrieval_,
2004, Barcelona, Spain
@@ -127,7 +155,7 @@
Contact Info and Mailing List
-----------------------------
-The home page of this project can be found at: http://aubio.org/
+The home page of this project can be found at: https://aubio.org/
Questions, comments, suggestions, and contributions are welcome. Use the
mailing list: <aubio-user@aubio.org>.
--- /dev/null
+++ b/appveyor.yml
@@ -1,0 +1,67 @@
+# 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"
+
+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=%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.20
+ - 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"
+ # clean up
+ - waf distclean
+ # build libaubio
+ - waf configure build --verbose
+ # build python module using libaubio dll
+ - "python setup.py build"
--- a/examples/aubiotrack.c
+++ b/examples/aubiotrack.c
@@ -20,6 +20,7 @@
#include "utils.h"
#define PROG_HAS_TEMPO 1
+#define PROG_HAS_ONSET 1
#define PROG_HAS_OUTPUT 1
#define PROG_HAS_JACK 1
#include "parse_args.h"
--- a/examples/jackio.c
+++ b/examples/jackio.c
@@ -21,7 +21,7 @@
#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"
--- a/examples/parse_args.h
+++ b/examples/parse_args.h
@@ -18,6 +18,12 @@
*/
+#include "config.h"
+
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+
extern int verbose;
// input / output
extern int usejack;
@@ -63,6 +69,7 @@
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"
@@ -106,6 +113,10 @@
" -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);
}
@@ -112,6 +123,7 @@
int
parse_args (int argc, char **argv)
{
+#ifdef HAVE_GETOPT_H
const char *options = "hv"
"i:r:B:H:"
#ifdef PROG_HAS_JACK
@@ -157,11 +169,13 @@
{"force-overwrite", 0, NULL, 'f'},
{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) {
@@ -235,6 +249,9 @@
}
}
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 ) {
--- a/examples/utils.c
+++ b/examples/utils.c
@@ -72,7 +72,7 @@
#if HAVE_JACK
aubio_jack_t *jack_setup;
-#endif
+#endif /* HAVE_JACK */
void examples_common_init (int argc, char **argv);
void examples_common_del (void);
@@ -114,7 +114,7 @@
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);
@@ -137,16 +137,16 @@
uint_t read = 0;
if (usejack) {
-#if HAVE_JACK
+#ifdef HAVE_JACK
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 {
@@ -181,7 +181,7 @@
send_noteon (int pitch, int velo)
{
smpl_t mpitch = floor (aubio_freqtomidi (pitch) + .5);
-#if HAVE_JACK
+#ifdef HAVE_JACK
jack_midi_event_t ev;
ev.size = 3;
ev.buffer = malloc (3 * sizeof (jack_midi_data_t)); // FIXME
--- a/examples/utils.h
+++ b/examples/utils.h
@@ -18,15 +18,29 @@
*/
-#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
--- a/examples/wscript_build
+++ b/examples/wscript_build
@@ -1,15 +1,9 @@
# vim:set syntax=python:
-uselib = []
-uselib += ['FFTW3', 'FFTW3F']
-uselib += ['SAMPLERATE']
-uselib += ['SNDFILE']
-uselib += ['AVCODEC']
-uselib += ['AVFORMAT']
-uselib += ['AVRESAMPLE']
-uselib += ['AVUTIL']
+uselib = ['aubio']
uselib += ['JACK']
+includes = ['../src']
utils_source = ['utils.c', 'jackio.c']
programs_source = ctx.path.ant_glob('*.c', excl = utils_source)
@@ -16,17 +10,15 @@
# 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:
bld(features = 'c cprogram',
- includes = '../src',
- lib = 'm',
- use = ['aubio', 'utilsio'],
- uselib = uselib,
source = source_file,
- target = str(source_file).split('.')[0]
- )
+ target = str(source_file).split('.')[0],
+ includes = includes,
+ use = uselib + ['utilsio'],
+ )
--- /dev/null
+++ b/nose2.cfg
@@ -1,0 +1,6 @@
+[unittest]
+start-dir = python/tests/
+plugins = nose2.plugins.mp
+
+[multiprocess]
+always-on = false
--- a/python/MANIFEST.in
+++ /dev/null
@@ -1,8 +1,0 @@
-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
--- a/python/README
+++ b/python/README
@@ -45,15 +45,6 @@
$ 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
-------------------------
--- a/python/VERSION
+++ /dev/null
@@ -1,7 +1,0 @@
-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
--- a/python/demos/demo_a_weighting.py
+++ /dev/null
@@ -1,27 +1,0 @@
-#! /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)
--- a/python/demos/demo_bpm_extract.py
+++ b/python/demos/demo_bpm_extract.py
@@ -3,16 +3,18 @@
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
@@ -43,8 +45,14 @@
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__':
@@ -51,4 +59,4 @@
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
+++ b/python/demos/demo_create_test_sounds.py
@@ -1,0 +1,50 @@
+#! /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
+++ b/python/demos/demo_filter.py
@@ -1,0 +1,36 @@
+#! /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)
--- a/python/demos/demo_filterbank.py
+++ b/python/demos/demo_filterbank.py
@@ -1,7 +1,7 @@
#! /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
@@ -19,7 +19,7 @@
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])
--- a/python/demos/demo_filterbank_slaney.py
+++ b/python/demos/demo_filterbank_slaney.py
@@ -1,7 +1,7 @@
#! /usr/bin/env python
from aubio import filterbank
-from numpy import array, arange, vstack
+from numpy import arange, vstack
win_s = 8192
samplerate = 16000
@@ -11,7 +11,7 @@
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])
--- a/python/demos/demo_filterbank_triangle_bands.py
+++ b/python/demos/demo_filterbank_triangle_bands.py
@@ -16,7 +16,7 @@
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])
@@ -37,7 +37,7 @@
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])
--- a/python/demos/demo_keyboard.py
+++ b/python/demos/demo_keyboard.py
@@ -25,7 +25,6 @@
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
--- a/python/demos/demo_mel-energy.py
+++ b/python/demos/demo_mel-energy.py
@@ -1,14 +1,14 @@
#! /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]
@@ -34,14 +34,14 @@
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
--- a/python/demos/demo_mfcc.py
+++ b/python/demos/demo_mfcc.py
@@ -2,16 +2,16 @@
import sys
from aubio import source, pvoc, mfcc
-from numpy import array, vstack, zeros
+from numpy import vstack, zeros
win_s = 512 # fft size
-hop_s = win_s / 4 # hop 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>" % sys.argv[0])
sys.exit(1)
source_filename = sys.argv[1]
--- a/python/demos/demo_onset.py
+++ b/python/demos/demo_onset.py
@@ -4,10 +4,10 @@
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]
@@ -28,7 +28,7 @@
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
--- a/python/demos/demo_onset_plot.py
+++ b/python/demos/demo_onset_plot.py
@@ -2,13 +2,13 @@
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]
@@ -34,10 +34,10 @@
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())
@@ -46,7 +46,6 @@
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)) ]
@@ -62,9 +61,10 @@
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')
--- a/python/demos/demo_pitch.py
+++ b/python/demos/demo_pitch.py
@@ -1,20 +1,20 @@
#! /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
@@ -36,7 +36,7 @@
#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
@@ -45,6 +45,7 @@
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
@@ -63,14 +64,11 @@
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)
--- a/python/demos/demo_pitch_sinusoid.py
+++ b/python/demos/demo_pitch_sinusoid.py
@@ -1,20 +1,17 @@
#! /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']
@@ -23,9 +20,9 @@
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
@@ -40,29 +37,35 @@
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()
--- a/python/demos/demo_pysoundcard_play.py
+++ b/python/demos/demo_pysoundcard_play.py
@@ -10,7 +10,7 @@
f = source(source_path, hop_size = hop_size)
samplerate = f.samplerate
- s = Stream(sample_rate = samplerate, block_length = hop_size)
+ s = Stream(samplerate = samplerate, blocksize = hop_size)
s.start()
read = 0
while 1:
--- a/python/demos/demo_pysoundcard_record.py
+++ b/python/demos/demo_pysoundcard_record.py
@@ -8,17 +8,21 @@
hop_size = 256
duration = 5 # in seconds
- s = Stream(block_length = hop_size)
- g = sink(sink_path, samplerate = s.sample_rate)
+ s = Stream(blocksize = hop_size, channels = 1)
+ g = sink(sink_path, samplerate = int(s.samplerate))
s.start()
total_frames = 0
- while total_frames < duration * s.sample_rate:
- vec = s.read(hop_size)
- # mix down to mono
- mono_vec = vec.sum(-1) / float(s.input_channels)
- g(mono_vec, hop_size)
- total_frames += hop_size
+ try:
+ while total_frames < duration * s.samplerate:
+ vec = s.read(hop_size)
+ # mix down to mono
+ mono_vec = vec.sum(-1) / float(s.channels[0])
+ g(mono_vec, hop_size)
+ total_frames += hop_size
+ except KeyboardInterrupt:
+ duration = total_frames / float(s.samplerate)
+ print("stopped after %.2f seconds" % duration)
s.stop()
if __name__ == '__main__':
--- /dev/null
+++ b/python/demos/demo_reading_speed.py
@@ -1,0 +1,139 @@
+#! /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)
+
+ 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)
--- a/python/demos/demo_simple_robot_voice.py
+++ b/python/demos/demo_simple_robot_voice.py
@@ -4,27 +4,26 @@
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))
--- a/python/demos/demo_simple_spectral_weighting.py
+++ b/python/demos/demo_simple_spectral_weighting.py
@@ -13,7 +13,7 @@
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])
@@ -22,7 +22,7 @@
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
@@ -30,7 +30,7 @@
.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:
@@ -52,4 +52,5 @@
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))
--- a/python/demos/demo_sink.py
+++ b/python/demos/demo_sink.py
@@ -5,7 +5,7 @@
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])
@@ -22,8 +22,10 @@
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)
--- a/python/demos/demo_sink_create_woodblock.py
+++ b/python/demos/demo_sink_create_woodblock.py
@@ -2,11 +2,11 @@
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
@@ -25,9 +25,9 @@
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):
@@ -39,7 +39,7 @@
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 ) )
--- a/python/demos/demo_sink_multi.py
+++ b/python/demos/demo_sink_multi.py
@@ -5,7 +5,7 @@
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])
@@ -22,10 +22,11 @@
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)
--- a/python/demos/demo_slicing.py
+++ b/python/demos/demo_slicing.py
@@ -6,7 +6,7 @@
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])
@@ -44,7 +44,8 @@
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
--- a/python/demos/demo_source.py
+++ b/python/demos/demo_source.py
@@ -5,7 +5,7 @@
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
@@ -20,7 +20,9 @@
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)
--- a/python/demos/demo_specdesc.py
+++ b/python/demos/demo_specdesc.py
@@ -1,14 +1,14 @@
#! /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]
@@ -30,7 +30,7 @@
for method in methods:
cands = []
- all_descs[method] = fvec(0)
+ all_descs[method] = np.array([])
o[method] = specdesc(method, win_s)
total_frames = 0
@@ -39,17 +39,17 @@
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,
+ 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
--- a/python/demos/demo_spectrogram.py
+++ b/python/demos/demo_spectrogram.py
@@ -1,63 +1,77 @@
#! /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
+ 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
- # 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)')
-
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()
--- a/python/demos/demo_tempo.py
+++ b/python/demos/demo_tempo.py
@@ -4,10 +4,10 @@
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]
@@ -33,7 +33,7 @@
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
--- a/python/demos/demo_tempo_plot.py
+++ b/python/demos/demo_tempo_plot.py
@@ -4,10 +4,10 @@
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]
@@ -39,11 +39,11 @@
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')
@@ -75,5 +75,5 @@
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
+++ b/python/demos/demo_timestretch.py
@@ -1,0 +1,110 @@
+#! /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, mfcc, 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
+++ b/python/demos/demo_timestretch_online.py
@@ -1,0 +1,110 @@
+#! /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, mfcc, 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)
+
+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)
+
+ block_read += 1
+ if read < hop_s: break
+
+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))
--- a/python/demos/demo_tss.py
+++ b/python/demos/demo_tss.py
@@ -4,44 +4,44 @@
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)
+ 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
+ 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)
+ 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
+ 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)
+ t.set_threshold(threshold)
- read = hop_s
+ 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
+ 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
+ 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()
+ 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()
--- a/python/demos/demo_waveform_plot.py
+++ b/python/demos/demo_waveform_plot.py
@@ -1,7 +1,7 @@
#! /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):
@@ -21,7 +21,7 @@
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
@@ -48,7 +48,7 @@
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)
--- a/python/ext/aubio-types.h
+++ b/python/ext/aubio-types.h
@@ -1,6 +1,8 @@
#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
@@ -33,31 +35,38 @@
#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
-// special python type for cvec
-typedef struct
-{
- PyObject_HEAD
- cvec_t * o;
- uint_t length;
- uint_t channels;
-} Py_cvec;
+// compat with Python < 2.6
+#ifndef Py_TYPE
+#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
+#endif
+
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;
--- a/python/ext/aubiomodule.c
+++ b/python/ext/aubiomodule.c
@@ -1,6 +1,5 @@
#define PY_AUBIO_MODULE_MAIN
#include "aubio-types.h"
-#include "aubio-generated.h"
#include "py-musicutils.h"
static char aubio_module_doc[] = "Python module for the aubio library";
@@ -83,11 +82,11 @@
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;
}
@@ -95,14 +94,12 @@
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;
}
@@ -116,7 +113,7 @@
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;
}
@@ -131,7 +128,7 @@
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;
}
@@ -146,7 +143,7 @@
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;
}
@@ -161,7 +158,7 @@
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;
}
@@ -174,7 +171,7 @@
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)) {
@@ -185,14 +182,12 @@
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;
}
@@ -204,7 +199,7 @@
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;
@@ -214,19 +209,17 @@
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;
@@ -245,13 +238,28 @@
{"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
+
+static PyObject *
+initaubio (void)
{
- PyObject *m;
+ PyObject *m = NULL;
int err;
// fvec is defined in __init__.py
@@ -265,13 +273,17 @@
// 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 ();
@@ -295,9 +307,27 @@
Py_INCREF (&Py_sinkType);
PyModule_AddObject (m, "sink", (PyObject *) & Py_sinkType);
+ PyModule_AddStringConstant(m, "float_type", AUBIO_NPY_SMPL_STR);
+
// add generated objects
add_generated_objects(m);
// add ufunc
add_ufuncs(m);
+
+ 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
--- a/python/ext/aubioproxy.c
+++ b/python/ext/aubioproxy.c
@@ -1,12 +1,30 @@
#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)) {
@@ -14,74 +32,47 @@
// 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);
-}
+int
+PyAubio_ArrayToCFvec (PyObject *input, fvec_t *out) {
-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;
-}
-
-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 *
@@ -101,14 +92,13 @@
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)) {
@@ -116,56 +106,53 @@
// 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;
+ return 0;
}
- 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);
- }
} 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;
}
-
--- a/python/ext/aubiowraphell.h
+++ /dev/null
@@ -1,90 +1,0 @@
-#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;
--- a/python/ext/py-cvec.c
+++ b/python/ext/py-cvec.c
@@ -1,17 +1,51 @@
#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)
{
@@ -24,7 +58,6 @@
return NULL;
}
-
self = (Py_cvec *) type->tp_alloc (type, 0);
self->length = Py_default_vector_length / 2 + 1;
@@ -47,11 +80,9 @@
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;
}
@@ -58,8 +89,9 @@
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 *
@@ -69,7 +101,7 @@
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;
}
@@ -78,9 +110,9 @@
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);
@@ -90,152 +122,61 @@
}
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 %ld, 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 %ld, 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[] = {
@@ -260,8 +201,7 @@
};
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 */
@@ -272,7 +212,7 @@
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 */
@@ -299,4 +239,13 @@
(initproc) Py_cvec_init, /* tp_init */
0, /* tp_alloc */
Py_cvec_new, /* tp_new */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
};
--- a/python/ext/py-fft.c
+++ b/python/ext/py-fft.c
@@ -1,10 +1,20 @@
-#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)
{
@@ -36,62 +46,100 @@
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,
+ "error creating fft with win_s=%d "
+ "(should be a power of 2 greater than 1; "
+ "try recompiling aubio with --enable-fftw3)",
+ self->win_s);
+ return -1;
+ }
-AUBIO_INIT(fft, self->win_s)
+ self->doout = new_py_cvec(self->win_s);
+ self->rdoout = new_py_fvec(self->win_s);
-AUBIO_DEL(fft)
+ return 0;
+}
-static PyObject *
-Py_fft_do(PyObject * self, PyObject * args)
+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(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 (!PyAubio_ArrayToCFvec(input, &(self->vecin))) {
+ return NULL;
+ }
- if (vec == NULL) {
+ 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;
}
- output = new_cvec(((Py_fft *) self)->win_s);
-
+ 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 (!PyAubio_PyCvecToCCvec (input, &(self->cvecin)) ) {
+ return NULL;
+ }
- if (vec == NULL) {
+ 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;
}
- output = new_fvec(self->win_s);
-
+ 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[] = {
@@ -100,4 +148,52 @@
{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,
+};
--- a/python/ext/py-filter.c
+++ b/python/ext/py-filter.c
@@ -5,6 +5,9 @@
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";
@@ -47,7 +50,7 @@
if (self->o == NULL) {
return -1;
}
-
+ self->out = NULL;
return 0;
}
@@ -54,15 +57,15 @@
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;
@@ -72,19 +75,25 @@
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;
@@ -102,7 +111,7 @@
Py_RETURN_NONE;
}
-static PyObject *
+static PyObject *
Py_filter_set_a_weighting (Py_filter * self, PyObject *args)
{
uint_t err = 0;
@@ -156,8 +165,7 @@
};
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 */
@@ -195,4 +203,13 @@
(initproc) Py_filter_init, /* tp_init */
0, /* tp_alloc */
Py_filter_new, /* tp_new */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
};
--- a/python/ext/py-filterbank.c
+++ b/python/ext/py-filterbank.c
@@ -1,10 +1,20 @@
-#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)
{
@@ -44,41 +54,67 @@
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 (!PyAubio_PyCvecToCCvec(input, &(self->vec) )) {
+ return NULL;
+ }
- if (vec == NULL) {
+ 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;
}
- out = new_fvec (self->n_filters);
-
+ 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)
@@ -87,7 +123,6 @@
PyObject *input;
uint_t samplerate;
- fvec_t *freqs;
if (!PyArg_ParseTuple (args, "OI", &input, &samplerate)) {
return NULL;
}
@@ -96,14 +131,12 @@
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");
@@ -137,21 +170,15 @@
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,
@@ -180,4 +207,52 @@
{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,
+};
--- a/python/ext/py-musicutils.c
+++ b/python/ext/py-musicutils.c
@@ -8,7 +8,6 @@
fvec_t *window = NULL;
if (!PyArg_ParseTuple (args, "|sI", &wintype, &winlen)) {
- PyErr_SetString (PyExc_ValueError, "failed parsing arguments");
return NULL;
}
@@ -25,11 +24,10 @@
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;
}
@@ -37,12 +35,11 @@
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;
@@ -55,11 +52,10 @@
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;
}
@@ -67,12 +63,11 @@
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;
@@ -85,12 +80,11 @@
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;
}
@@ -98,12 +92,11 @@
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;
@@ -116,12 +109,11 @@
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;
}
@@ -129,12 +121,11 @@
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;
--- a/python/ext/py-musicutils.h
+++ b/python/ext/py-musicutils.h
@@ -1,5 +1,5 @@
-#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"
@@ -71,4 +71,4 @@
PyObject * Py_aubio_level_detection(PyObject *self, PyObject *args);
-#endif /* _PY_AUBIO_MUSICUTILS_H_ */
+#endif /* PY_AUBIO_MUSICUTILS_H */
--- a/python/ext/py-phasevoc.c
+++ b/python/ext/py-phasevoc.c
@@ -1,10 +1,22 @@
-#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)
{
@@ -49,64 +61,99 @@
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,
+ "failed creating pvoc with win_s=%d, hop_s=%d",
+ self->win_s, self->hop_s);
+ 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);
-AUBIO_DEL(pvoc)
+ return 0;
+}
-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 (!PyAubio_ArrayToCFvec (input, &(self->vecin) )) {
+ return NULL;
+ }
- if (vec == NULL) {
+ 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;
}
- output = new_cvec(self->win_s);
-
+ 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 (!PyAubio_PyCvecToCCvec (input, &(self->cvecin) )) {
+ return NULL;
+ }
- if (vec == NULL) {
+ 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;
}
- output = new_fvec(self->hop_s);
-
+ 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[] = {
@@ -115,4 +162,52 @@
{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,
+};
--- a/python/ext/py-sink.c
+++ b/python/ext/py-sink.c
@@ -1,4 +1,4 @@
-#include "aubiowraphell.h"
+#include "aubio-types.h"
typedef struct
{
@@ -7,6 +7,8 @@
char_t* uri;
uint_t samplerate;
uint_t channels;
+ fvec_t write_data;
+ fmat_t mwrite_data;
} Py_sink;
static char Py_sink_doc[] = ""
@@ -115,7 +117,7 @@
aubio_sink_preset_samplerate ( self->o, self->samplerate );
}
if (self->o == NULL) {
- PyErr_SetString (PyExc_StandardError, "error creating sink with this uri");
+ PyErr_SetString (PyExc_RuntimeError, "error creating sink with this uri");
return -1;
}
self->samplerate = aubio_sink_get_samplerate ( self->o );
@@ -124,7 +126,13 @@
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);
+ Py_TYPE(self)->tp_free((PyObject *) self);
+}
/* function Py_sink_do */
static PyObject *
@@ -134,7 +142,6 @@
PyObject * write_data_obj;
/* input vectors prototypes */
- fvec_t* write_data;
uint_t write;
@@ -142,20 +149,14 @@
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;
}
@@ -168,7 +169,6 @@
PyObject * write_data_obj;
/* input vectors prototypes */
- fmat_t * write_data;
uint_t write;
@@ -178,22 +178,16 @@
/* 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,
@@ -200,7 +194,8 @@
"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)
@@ -216,4 +211,52 @@
{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,
+};
--- a/python/ext/py-source.c
+++ b/python/ext/py-source.c
@@ -1,4 +1,4 @@
-#include "aubiowraphell.h"
+#include "aubio-types.h"
typedef struct
{
@@ -8,6 +8,11 @@
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[] = ""
@@ -135,9 +140,8 @@
{
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, "error creating source with \"%s\"",
+ self->uri);
return -1;
}
self->samplerate = aubio_source_get_samplerate ( self->o );
@@ -144,39 +148,45 @@
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);
+ }
+ 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;
}
@@ -184,33 +194,24 @@
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,
@@ -219,14 +220,16 @@
"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 *
@@ -233,7 +236,7 @@
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 *
@@ -248,11 +251,18 @@
{
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,
@@ -278,4 +288,52 @@
{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,
+ 0,
+ 0,
+ 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,
+};
--- a/python/ext/ufuncs.c
+++ b/python/ext/ufuncs.c
@@ -84,6 +84,7 @@
void add_ufuncs ( PyObject *m )
{
int err = 0;
+ PyObject *dict, *f, *g, *h;
err = _import_umath ();
if (err != 0) {
@@ -91,7 +92,6 @@
"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,
@@ -99,7 +99,6 @@
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);
@@ -106,7 +105,6 @@
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);
--- a/python/lib/aubio/__init__.py
+++ b/python/lib/aubio/__init__.py
@@ -1,14 +1,18 @@
#! /usr/bin/env python
import numpy
-from _aubio import *
-from midiconv import *
-from slicing import *
+from ._aubio import *
+from ._aubio import float_type
+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)
--- a/python/lib/aubio/midiconv.py
+++ b/python/lib/aubio/midiconv.py
@@ -1,14 +1,28 @@
# -*- 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 = {None: 0, u'♮': 0, '#': +1, u'♯': +1, u'\udd2a': +2,
+ 'b': -1, u'♭': -1, u'\ufffd': -2}
_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:
@@ -26,27 +40,27 @@
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)))
--- a/python/lib/aubio/slicing.py
+++ b/python/lib/aubio/slicing.py
@@ -1,43 +1,45 @@
-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 = []
@@ -44,7 +46,7 @@
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
@@ -53,9 +55,9 @@
# 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)
@@ -62,7 +64,7 @@
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
@@ -72,12 +74,13 @@
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
+++ b/python/lib/gen_code.py
@@ -1,0 +1,533 @@
+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',
+ 'wavetable': 'self->hop_size',
+ 'sampler': 'self->hop_size',
+ 'mfcc': 'self->n_coeffs',
+ 'specdesc': '1',
+ 'tempo': '1',
+ 'filterbank': 'self->n_filters',
+ 'tss': 'self->hop_size',
+ }
+
+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_Exception, "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 += """
+ {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
+ 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']])
+ 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});
+
+ return {outputs};
+}}
+""".format(
+ do_fn = do_fn,
+ inputs = inputs, outputs = outputs, c_outputs = c_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
+++ b/python/lib/gen_external.py
@@ -1,0 +1,249 @@
+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',
+ #'resampler',
+ # 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',
+
+ 'tss',
+ ]
+
+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):
+ cpp_cmd = get_preprocessor()
+
+ macros = [('AUBIO_UNSTABLE', 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 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 glob.glob(os.path.join(output_path, '*.c'))
+ sources_list = []
+ cpp_output, cpp_objects = get_cpp_objects(header)
+ 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)
+
+ """
+ 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} {:d}".format(o, family, len(lib[o][family]) ) )
+ """
+
+ 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 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)
--- a/python/lib/gen_pyobject.py
+++ /dev/null
@@ -1,529 +1,0 @@
-#! /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
--- a/python/lib/generator.py
+++ /dev/null
@@ -1,226 +1,0 @@
-#! /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
+++ b/python/lib/moresetuptools.py
@@ -1,0 +1,141 @@
+""" 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
+
+# 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:
+ 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):
+ """ build aubio inside python module instead of linking against libaubio """
+ print("Warning: libaubio was not built with waf, adding src/")
+ # create an empty header, macros will be passed on the command line
+ fake_config_header = os.path.join('python', 'ext', 'config.h')
+ distutils.file_util.write_file(fake_config_header, "")
+ aubio_sources = glob.glob(os.path.join('src', '**.c'))
+ aubio_sources += glob.glob(os.path.join('src', '*', '**.c'))
+ ext.sources += aubio_sources
+ # 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_MEMCPY_HACKS']:
+ ext.define_macros += [(define_macro, 1)]
+
+ # loof for additional packages
+ print("Info: looking for *optional* additional packages")
+ packages = ['libavcodec', 'libavformat', 'libavutil', 'libavresample',
+ 'jack',
+ 'sndfile', 'samplerate',
+ #'fftw3f',
+ ]
+ 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
+ add_packages(['aubio'], ext)
+ if 'aubio' not in ext.libraries:
+ print("Error: libaubio not found")
+
+class CleanGenerated(distutils.command.clean.clean):
+ def run(self):
+ distutils.dir_util.remove_tree(output_path)
+ distutils.command.clean.clean.run(self)
+
+class GenerateCommand(distutils.cmd.Command):
+ description = 'generate gen/gen-*.c files from ../src/aubio.h'
+ user_options = [
+ # The format is (long option, short option, description).
+ ('enable-double', None, 'use HAVE_AUBIO_DOUBLE=1 (default: 0)'),
+ ]
+
+ def initialize_options(self):
+ self.enable_double = False
+
+ def 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 run(self):
+ self.announce( 'Generating code', level=distutils.log.INFO)
+ generated_object_files = generate_external(header, output_path, usedouble=self.enable_double)
--- a/python/scripts/aubiocut
+++ b/python/scripts/aubiocut
@@ -134,7 +134,7 @@
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
@@ -171,7 +171,7 @@
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
@@ -188,7 +188,7 @@
from aubio.slicing import slice_source_at_stamps
timestamps_end = None
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 ]
--- a/python/setup.py
+++ /dev/null
@@ -1,99 +1,0 @@
-#! /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'],
- )
--- a/python/tests/run_all_tests
+++ b/python/tests/run_all_tests
@@ -1,24 +1,5 @@
#! /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()
--- a/python/tests/test_aubio.py
+++ b/python/tests/test_aubio.py
@@ -1,14 +1,14 @@
#! /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
if __name__ == '__main__':
- from unittest import main
- main()
+ main()
--- a/python/tests/test_cvec.py
+++ b/python/tests/test_cvec.py
@@ -1,17 +1,19 @@
#! /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)
+ _ = a.norm[0]
assert_equal(a.norm, 0.)
assert_equal(a.phas, 0.)
@@ -41,11 +43,103 @@
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()
--- a/python/tests/test_fft.py
+++ b/python/tests/test_fft.py
@@ -1,10 +1,12 @@
#! /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):
@@ -20,8 +22,9 @@
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 """
@@ -34,10 +37,8 @@
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)
@@ -49,27 +50,26 @@
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 )
@@ -95,7 +95,6 @@
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 )
@@ -106,7 +105,84 @@
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()
-
--- a/python/tests/test_filter.py
+++ b/python/tests/test_filter.py
@@ -1,74 +1,87 @@
#! /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
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()
--- a/python/tests/test_filterbank.py
+++ b/python/tests/test_filterbank.py
@@ -1,68 +1,84 @@
#! /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
+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_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_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[:] = pi
- assert_equal( f(c), 0);
+ 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_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_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):
- 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_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[:] = 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[:] = 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() )
+ 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() )
-if __name__ == '__main__':
- from unittest import main
- main()
+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()
--- a/python/tests/test_filterbank_mel.py
+++ b/python/tests/test_filterbank_mel.py
@@ -1,51 +1,49 @@
#! /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_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_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 = 'float32')
- f.set_triangle_bands(freqs, 48000)
- f.get_coeffs().T
- assert_equal ( f(cvec(1024)), 0)
+ 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 = '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_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()
--- a/python/tests/test_fvec.py
+++ b/python/tests/test_fvec.py
@@ -1,10 +1,13 @@
#! /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
class aubio_fvec_test_case(TestCase):
@@ -11,15 +14,15 @@
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)
@@ -34,104 +37,107 @@
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.)
+ self.assertRaises(IndexError, a.__getitem__, 3)
+ self.assertRaises(IndexError, a.__getitem__, 2)
- def test_alpha_norm_of_none(self):
- self.assertRaises (ValueError, alpha_norm, None, 1)
+class aubio_wrong_fvec_input(TestCase):
+ """ uses min_removal to test PyAubio_IsValidVector """
- 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_no_input(self):
+ self.assertRaises(TypeError, min_removal)
- 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_none(self):
+ self.assertRaises(ValueError, min_removal, None)
- def test_alpha_norm_of_array_of_string (self):
- a = "hello"
- self.assertRaises (ValueError, alpha_norm, a, 1)
+ 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 = 5)
+
+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 )
+ a = np.array([0, 1, -1], dtype=float_type)
+ assert_almost_equal(zero_crossing_rate(a), 1./3.)
- 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)
+ 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')
+ 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)
- a[0] = 0
- assert_equal (a, b)
+ assert_equal(b, [19, 0, 18])
- def test_fvec_min_removal_of_array_float64(self):
- a = array([20,1,19], dtype='float64')
- self.assertRaises (ValueError, min_removal, a)
+class aubio_fvec_test_memory(TestCase):
- def test_fvec_min_removal_of_fvec(self):
- a = fvec(3)
- 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)
+ 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()
--- a/python/tests/test_mathutils.py
+++ b/python/tests/test_mathutils.py
@@ -1,5 +1,6 @@
#! /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
@@ -12,7 +13,7 @@
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"))
@@ -23,13 +24,12 @@
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)
@@ -53,7 +53,7 @@
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 )
@@ -61,7 +61,7 @@
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 )
@@ -69,8 +69,8 @@
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 )
@@ -77,7 +77,7 @@
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 )
@@ -85,7 +85,7 @@
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 )
@@ -93,7 +93,7 @@
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 )
@@ -101,5 +101,4 @@
assert_equal ( array(b) < 0, False )
if __name__ == '__main__':
- from unittest import main
main()
--- /dev/null
+++ b/python/tests/test_mfcc.py
@@ -1,0 +1,109 @@
+#! /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)
+
+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()
--- a/python/tests/test_midi2note.py
+++ b/python/tests/test_midi2note.py
@@ -27,7 +27,7 @@
" 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)
--- a/python/tests/test_musicutils.py
+++ b/python/tests/test_musicutils.py
@@ -1,14 +1,12 @@
#! /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, float_type
-from aubio import fvec
-
class aubio_window(TestCase):
def test_accept_name_and_size(self):
@@ -15,25 +13,17 @@
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):
@@ -41,19 +31,14 @@
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):
@@ -60,20 +45,14 @@
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):
@@ -80,20 +59,15 @@
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):
@@ -100,21 +74,15 @@
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()
--- a/python/tests/test_note2midi.py
+++ b/python/tests/test_note2midi.py
@@ -1,7 +1,9 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
-from aubio import note2midi
+from __future__ import unicode_literals
+
+from aubio import note2midi, freq2note
import unittest
list_of_known_notes = (
@@ -14,13 +16,13 @@
( 'A4', 69 ),
( 'A#4', 70 ),
( 'Bb4', 70 ),
- ( u'B♭4', 70 ),
+ ( 'B♭4', 70 ),
( 'G8', 115 ),
- ( u'G♯8', 116 ),
+ ( 'G♯8', 116 ),
( 'G9', 127 ),
- ( u'G\udd2a2', 45 ),
- ( u'B\ufffd2', 45 ),
- ( u'A♮2', 45 ),
+ ( 'G\udd2a2', 45 ),
+ ( 'B\ufffd2', 45 ),
+ ( 'A♮2', 45 ),
)
class note2midi_good_values(unittest.TestCase):
@@ -49,12 +51,27 @@
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)
+
+
+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()
--- a/python/tests/test_onset.py
+++ b/python/tests/test_onset.py
@@ -1,7 +1,7 @@
#! /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):
@@ -84,5 +84,4 @@
samplerate = 8000
if __name__ == '__main__':
- from unittest import main
main()
--- a/python/tests/test_phasevoc.py
+++ b/python/tests/test_phasevoc.py
@@ -1,12 +1,23 @@
#! /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 """
@@ -30,53 +41,147 @@
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)
+ assert_equal ( 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
+ @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()
--- a/python/tests/test_pitch.py
+++ b/python/tests/test_pitch.py
@@ -1,10 +1,9 @@
#! /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):
@@ -24,7 +23,7 @@
" 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 "
@@ -31,7 +30,7 @@
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):
@@ -50,10 +49,9 @@
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:
@@ -63,7 +61,7 @@
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%
@@ -124,5 +122,4 @@
setattr (aubio_pitch_Sinusoid, test_method.__name__, test_method)
if __name__ == '__main__':
- from unittest import main
main()
--- a/python/tests/test_sink.py
+++ b/python/tests/test_sink.py
@@ -1,17 +1,31 @@
#! /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
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_many_sinks(self):
from tempfile import mkdtemp
import os.path
@@ -23,87 +37,47 @@
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 = []
+ @params(*all_params)
+ def test_read_and_write(self, hop_size, samplerate, path):
+
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)
+ 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)
- def test_read_and_write(self):
+ @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)
- 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\'')
-
- 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)
-
def test_close_file(self):
samplerate = 44100
sink_path = get_tmp_sink_path()
@@ -120,5 +94,4 @@
del_tmp_sink_path(sink_path)
if __name__ == '__main__':
- from unittest import main
main()
--- a/python/tests/test_slicing.py
+++ b/python/tests/test_slicing.py
@@ -1,10 +1,10 @@
#! /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
@@ -146,5 +146,4 @@
shutil.rmtree(self.output_dir)
if __name__ == '__main__':
- from unittest import main
main()
--- a/python/tests/test_source.py
+++ b/python/tests/test_source.py
@@ -1,17 +1,29 @@
#! /usr/bin/env python
-from numpy.testing import TestCase, assert_equal, assert_almost_equal
-from aubio import fvec, source
-from numpy import array
+from nose2 import main
+from nose2.tools import params
+from numpy.testing import TestCase
+from aubio import source
from utils import list_all_sounds
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\'')
+ self.default_test_sound = list_of_sounds[0]
class aubio_source_test_case(aubio_source_test_case_base):
@@ -35,86 +47,111 @@
def read_from_source(self, f):
total_frames = 0
while True:
- vec, read = f()
+ _ , 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
+ #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)
+ @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
+ 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)
+ @params(*list_of_sounds)
+ def test_samplerate_none(self, p):
+ 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(*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')
+ with self.assertRaises(ValueError):
+ source(self.default_test_sound, 0, -1)
- 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_wrong_channels(self):
+ with self.assertRaises(ValueError):
+ source(self.default_test_sound, 0, 0, -1)
- 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
+ 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()
+ _, 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
+ #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
if __name__ == '__main__':
- from unittest import main
main()
--- a/python/tests/test_specdesc.py
+++ b/python/tests/test_specdesc.py
@@ -1,9 +1,9 @@
#! /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",
@@ -29,38 +29,25 @@
o = specdesc()
for method in methods:
- o = specdesc(method, buf_size)
- assert_equal ([o.buf_size, o.method], [buf_size, method])
+ 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.)
+ 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_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)))
-
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.)
@@ -70,7 +57,7 @@
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.)
@@ -79,7 +66,7 @@
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))
@@ -88,7 +75,7 @@
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
@@ -101,7 +88,7 @@
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)
@@ -109,7 +96,7 @@
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)
@@ -117,11 +104,11 @@
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):
@@ -129,7 +116,7 @@
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)
@@ -140,7 +127,7 @@
def test_spread(self):
o = specdesc("spread")
c = cvec(2048)
- ramp = arange(c.length, dtype='float32')
+ ramp = arange(c.length, dtype=float_type)
assert_equal( 0., o(c))
a = ramp
@@ -153,7 +140,7 @@
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)
@@ -167,7 +154,7 @@
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)
@@ -178,8 +165,8 @@
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)
@@ -186,7 +173,7 @@
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)
@@ -193,7 +180,7 @@
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)
@@ -201,18 +188,18 @@
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)
@@ -221,18 +208,27 @@
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):
+ # FIXME should fail?
+ with self.assertRaises(ValueError):
+ specdesc("unknown", 512)
+ self.skipTest('todo: new_specdesc should fail on wrong method')
+
if __name__ == '__main__':
- from unittest import main
main()
--- a/python/tests/test_zero_crossing_rate.py
+++ b/python/tests/test_zero_crossing_rate.py
@@ -1,7 +1,7 @@
#! /usr/bin/env python
+from unittest import main
from numpy.testing import TestCase
-
from aubio import fvec, zero_crossing_rate
buf_size = 2048
@@ -22,26 +22,25 @@
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()
--- a/python/tests/utils.py
+++ b/python/tests/utils.py
@@ -1,14 +1,18 @@
#! /usr/bin/env python
+import os
+import glob
+import numpy as np
+from tempfile import mkstemp
+
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,'*.*'))
@@ -20,15 +24,21 @@
return all_sounds[0]
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
@@ -43,13 +53,12 @@
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]):
@@ -60,7 +69,6 @@
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
+++ b/requirements.txt
@@ -1,0 +1,2 @@
+numpy
+nose2
--- /dev/null
+++ b/scripts/apple/Info.plist
@@ -1,0 +1,28 @@
+<?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
+++ b/scripts/apple/Modules/module.modulemap
@@ -1,0 +1,6 @@
+framework module aubio {
+ umbrella header "aubio.h"
+
+ export *
+ module * { export * }
+}
--- /dev/null
+++ b/scripts/build_apple_frameworks
@@ -1,0 +1,100 @@
+#! /bin/sh
+
+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
+++ b/scripts/build_emscripten
@@ -1,0 +1,21 @@
+#! /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
+++ b/scripts/build_mingw
@@ -1,0 +1,28 @@
+#! /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
+++ b/scripts/setenv_local.sh
@@ -1,0 +1,32 @@
+#! /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/python/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
+++ b/setup.py
@@ -1,0 +1,111 @@
+#! /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
+
+# read from VERSION
+for l in open('VERSION').readlines(): exec (l.strip())
+
+if AUBIO_MAJOR_VERSION is None or AUBIO_MINOR_VERSION is None \
+ or AUBIO_PATCH_VERSION is None:
+ raise SystemError("Failed parsing VERSION file.")
+
+__version__ = '.'.join(map(str, [AUBIO_MAJOR_VERSION,
+ AUBIO_MINOR_VERSION,
+ AUBIO_PATCH_VERSION]))
+if AUBIO_VERSION_STATUS is not None:
+ if AUBIO_VERSION_STATUS.startswith('~'):
+ AUBIO_VERSION_STATUS = AUBIO_VERSION_STATUS[1:]
+ __version__ += AUBIO_VERSION_STATUS
+
+include_dirs = []
+library_dirs = []
+define_macros = []
+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 = 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 aubio headers are found in this directory
+ add_local_aubio_header(aubio_extension)
+ # was waf used to build the shared lib?
+ if os.path.isdir(os.path.join('build','src')):
+ # link against build/src/libaubio, built with waf
+ add_local_aubio_lib(aubio_extension)
+ else:
+ # add libaubio sources and look for optional deps with pkg-config
+ add_local_aubio_sources(aubio_extension)
+ __version__ += '_libaubio'
+else:
+ # look for aubio headers and lib using pkg-config
+ add_system_aubio(aubio_extension)
+
+
+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+)',
+ ]
+
+from distutils.command.build_ext import build_ext as _build_ext
+class build_ext(_build_ext):
+
+ def build_extension(self, extension):
+ # generate files python/gen/*.c, python/gen/aubio-generated.h
+ extension.sources += generate_external(header, output_path, overwrite = False)
+ return _build_ext.build_extension(self, extension)
+
+distrib = setup(name='aubio',
+ version = __version__,
+ packages = ['aubio'],
+ package_dir = {'aubio':'python/lib/aubio'},
+ scripts = ['python/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'],
+ cmdclass = {
+ 'clean': CleanGenerated,
+ 'generate': GenerateCommand,
+ 'build_ext': build_ext,
+ },
+ test_suite = 'nose2.collector.collector',
+ )
--- a/src/aubio_priv.h
+++ b/src/aubio_priv.h
@@ -24,8 +24,8 @@
* 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
/*********************
*
@@ -35,11 +35,11 @@
#include "config.h"
-#if HAVE_STDLIB_H
+#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
-#if HAVE_STDIO_H
+#ifdef HAVE_STDIO_H
#include <stdio.h>
#endif
@@ -64,6 +64,63 @@
#include <limits.h> // for CHAR_BIT, in C99 standard
#endif
+#ifdef HAVE_ACCELERATE
+#define HAVE_ATLAS 1
+#include <Accelerate/Accelerate.h>
+#elif defined(HAVE_ATLAS_CBLAS_H)
+#define HAVE_ATLAS 1
+#include <atlas/cblas.h>
+#else
+#undef HAVE_ATLAS
+#endif
+
+#ifdef HAVE_ACCELERATE
+#include <Accelerate/Accelerate.h>
+#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_meanv vDSP_meanv
+#define aubio_vDSP_sve vDSP_sve
+#define aubio_vDSP_maxv vDSP_maxv
+#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_vfill vDSP_vfillD
+#define aubio_vDSP_meanv vDSP_meanvD
+#define aubio_vDSP_sve vDSP_sveD
+#define aubio_vDSP_maxv vDSP_maxvD
+#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
+#ifndef HAVE_AUBIO_DOUBLE
+#define aubio_catlas_set catlas_sset
+#define aubio_cblas_copy cblas_scopy
+#define aubio_cblas_swap cblas_sswap
+#define aubio_cblas_dot cblas_sdot
+#else /* HAVE_AUBIO_DOUBLE */
+#define aubio_catlas_set catlas_dset
+#define aubio_cblas_copy cblas_dcopy
+#define aubio_cblas_swap cblas_dswap
+#define aubio_cblas_dot cblas_ddot
+#endif /* HAVE_AUBIO_DOUBLE */
+#endif /* HAVE_ATLAS */
+
+#if !defined(HAVE_MEMCPY_HACKS) && !defined(HAVE_ACCELERATE) && !defined(HAVE_ATLAS)
+#define HAVE_NOOPT 1
+#else
+#undef HAVE_NOOPT
+#endif
+
#include "types.h"
#define AUBIO_UNSTABLE 1
@@ -136,6 +193,10 @@
#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
@@ -193,6 +254,11 @@
#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))
@@ -228,4 +294,12 @@
#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 */
--- a/src/cvec.c
+++ b/src/cvec.c
@@ -21,7 +21,7 @@
#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;
@@ -55,17 +55,17 @@
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++) {
@@ -79,22 +79,22 @@
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) {
@@ -105,11 +105,11 @@
}
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) {
@@ -124,7 +124,7 @@
}
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.);
--- a/src/cvec.h
+++ b/src/cvec.h
@@ -18,8 +18,8 @@
*/
-#ifndef _AUBIO__CVEC_H
-#define _AUBIO__CVEC_H
+#ifndef AUBIO_CVEC_H
+#define AUBIO_CVEC_H
#ifdef __cplusplus
extern "C" {
@@ -150,7 +150,7 @@
\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
@@ -162,7 +162,7 @@
\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
@@ -169,7 +169,7 @@
\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
@@ -177,7 +177,7 @@
\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
@@ -234,4 +234,4 @@
}
#endif
-#endif /* _AUBIO__CVEC_H */
+#endif /* AUBIO_CVEC_H */
--- a/src/fmat.c
+++ b/src/fmat.c
@@ -53,27 +53,27 @@
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++) {
@@ -93,14 +93,14 @@
}
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) {
@@ -116,7 +116,7 @@
}
}
-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++) {
@@ -126,11 +126,11 @@
}
}
-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);
@@ -141,16 +141,46 @@
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
+}
--- a/src/fmat.h
+++ b/src/fmat.h
@@ -18,8 +18,8 @@
*/
-#ifndef _AUBIO__FMAT_H
-#define _AUBIO__FMAT_H
+#ifndef AUBIO_FMAT_H
+#define AUBIO_FMAT_H
#ifdef __cplusplus
extern "C" {
@@ -65,7 +65,7 @@
\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
@@ -84,7 +84,7 @@
\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
@@ -92,7 +92,7 @@
\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
@@ -99,7 +99,7 @@
\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
@@ -106,7 +106,7 @@
\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
@@ -146,7 +146,7 @@
\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
@@ -154,10 +154,19 @@
\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 */
--- a/src/fvec.c
+++ b/src/fvec.c
@@ -21,20 +21,7 @@
#include "aubio_priv.h"
#include "fvec.h"
-#ifdef HAVE_ACCELERATE
-#include <Accelerate/Accelerate.h>
-#if !HAVE_AUBIO_DOUBLE
-#define aubio_vDSP_mmov vDSP_mmov
-#define aubio_vDSP_vmul vDSP_vmul
-#define aubio_vDSP_vfill vDSP_vfill
-#else /* HAVE_AUBIO_DOUBLE */
-#define aubio_vDSP_mmov vDSP_mmovD
-#define aubio_vDSP_vmul vDSP_vmulD
-#define aubio_vDSP_vfill vDSP_vfillD
-#endif /* HAVE_AUBIO_DOUBLE */
-#endif
-
-fvec_t * new_fvec( uint_t length) {
+fvec_t * new_fvec(uint_t length) {
fvec_t * s;
if ((sint_t)length <= 0) {
return NULL;
@@ -54,17 +41,17 @@
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]);
@@ -73,12 +60,14 @@
}
void fvec_set_all (fvec_t *s, smpl_t val) {
-#ifndef HAVE_ACCELERATE
+#if !defined(HAVE_ACCELERATE) && !defined(HAVE_ATLAS)
uint_t j;
for (j=0; j< s->length; j++) {
s->data[j] = val;
}
-#else
+#elif defined(HAVE_ATLAS)
+ aubio_catlas_set(s->length, val, s->data, 1);
+#elif defined(HAVE_ACCELERATE)
aubio_vDSP_vfill(&val, s->data, 1, s->length);
#endif
}
@@ -106,7 +95,7 @@
}
}
-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);
@@ -118,22 +107,34 @@
#endif /* HAVE_ACCELERATE */
}
-void fvec_copy(fvec_t *s, fvec_t *t) {
+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);
+ for (j=0; j< length; j++) {
+ out->data[j] = in->data[j] * weight->data[j];
+ }
+#else
+ aubio_vDSP_vmul(in->data, 1, weight->data, 1, out->data, 1, out->length);
+#endif /* HAVE_ACCELERATE */
+}
+
+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 !defined(HAVE_MEMCPY_HACKS) && !defined(HAVE_ACCELERATE)
+#ifdef HAVE_NOOPT
uint_t j;
for (j=0; j< t->length; j++) {
t->data[j] = s->data[j];
}
-#else
-#if defined(HAVE_MEMCPY_HACKS)
+#elif defined(HAVE_MEMCPY_HACKS)
memcpy(t->data, s->data, t->length * sizeof(smpl_t));
-#else
+#elif defined(HAVE_ATLAS)
+ aubio_cblas_copy(s->length, s->data, 1, t->data, 1);
+#elif defined(HAVE_ACCELERATE)
aubio_vDSP_mmov(s->data, t->data, 1, s->length, 1, 1);
-#endif
#endif
}
--- a/src/fvec.h
+++ b/src/fvec.h
@@ -18,8 +18,8 @@
*/
-#ifndef _AUBIO__FVEC_H
-#define _AUBIO__FVEC_H
+#ifndef AUBIO_FVEC_H
+#define AUBIO_FVEC_H
#ifdef __cplusplus
extern "C" {
@@ -89,7 +89,7 @@
\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
@@ -105,7 +105,7 @@
\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
@@ -112,7 +112,7 @@
\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
@@ -152,7 +152,7 @@
\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
@@ -160,10 +160,19 @@
\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 in input vector
+ \param weight weights vector
+ \param out output vector
+
+*/
+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 */
--- a/src/io/audio_unit.h
+++ b/src/io/audio_unit.h
@@ -18,8 +18,8 @@
*/
-#ifndef _AUBIO_AUDIO_UNIT_H
-#define _AUBIO_AUDIO_UNIT_H
+#ifndef AUBIO_AUDIO_UNIT_H
+#define AUBIO_AUDIO_UNIT_H
/** \file
@@ -58,4 +58,4 @@
}
#endif
-#endif /* _AUBIO_AUDIO_UNIT_H */
+#endif /* AUBIO_AUDIO_UNIT_H */
--- a/src/io/sink.c
+++ b/src/io/sink.c
@@ -54,7 +54,7 @@
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);
@@ -70,7 +70,7 @@
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);
@@ -84,7 +84,7 @@
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);
@@ -120,11 +120,11 @@
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);
}
--- a/src/io/sink.h
+++ b/src/io/sink.h
@@ -18,8 +18,8 @@
*/
-#ifndef _AUBIO_SINK_H
-#define _AUBIO_SINK_H
+#ifndef AUBIO_SINK_H
+#define AUBIO_SINK_H
/** \file
@@ -76,7 +76,7 @@
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);
/**
@@ -120,7 +120,7 @@
\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);
/**
@@ -130,7 +130,7 @@
\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);
/**
@@ -178,4 +178,4 @@
}
#endif
-#endif /* _AUBIO_SINK_H */
+#endif /* AUBIO_SINK_H */
--- a/src/io/sink_apple_audio.c
+++ b/src/io/sink_apple_audio.c
@@ -36,7 +36,7 @@
extern int createAubioBufferList(AudioBufferList *bufferList, int channels, int segmentSize);
extern void freeAudioBufferList(AudioBufferList *bufferList);
-extern CFURLRef getURLFromPath(const char * path);
+extern CFURLRef createURLFromPath(const char * path);
char_t *getPrintableOSStatusError(char_t *str, OSStatus error);
uint_t aubio_sink_apple_audio_open(aubio_sink_apple_audio_t *s);
@@ -43,6 +43,8 @@
#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;
@@ -55,16 +57,18 @@
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) {
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;
@@ -110,12 +114,12 @@
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;
}
@@ -137,11 +141,12 @@
clientFormat.mReserved = 0;
AudioFileTypeID fileType = kAudioFileWAVEType;
- CFURLRef fileURL = getURLFromPath(s->path);
+ CFURLRef fileURL = createURLFromPath(s->path);
bool overwrite = true;
OSStatus err = noErr;
err = ExtAudioFileCreateWithURL(fileURL, fileType, &clientFormat, NULL,
overwrite ? kAudioFileFlags_EraseFile : 0, &s->audioFile);
+ CFRelease(fileURL);
if (err) {
char_t errorstr[20];
AUBIO_ERR("sink_apple_audio: error when trying to create %s with "
@@ -161,7 +166,6 @@
}
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) {
@@ -178,34 +182,10 @@
}
}
}
- 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) {
@@ -222,22 +202,28 @@
}
}
}
+ 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 "
@@ -245,7 +231,6 @@
getPrintableOSStatusError(errorstr, err));
}
}
- return;
}
uint_t aubio_sink_apple_audio_close(aubio_sink_apple_audio_t * s) {
@@ -266,6 +251,7 @@
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;
--- a/src/io/sink_apple_audio.h
+++ b/src/io/sink_apple_audio.h
@@ -18,8 +18,8 @@
*/
-#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
@@ -58,7 +58,7 @@
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);
/**
@@ -102,7 +102,7 @@
\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);
/**
@@ -112,7 +112,7 @@
\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);
/**
@@ -160,4 +160,4 @@
}
#endif
-#endif /* _AUBIO_SINK_APPLE_AUDIO_H */
+#endif /* AUBIO_SINK_APPLE_AUDIO_H */
--- a/src/io/sink_sndfile.c
+++ b/src/io/sink_sndfile.c
@@ -53,10 +53,9 @@
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");
@@ -63,6 +62,10 @@
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;
@@ -106,12 +109,12 @@
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;
}
@@ -219,6 +222,7 @@
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);
--- a/src/io/sink_sndfile.h
+++ b/src/io/sink_sndfile.h
@@ -18,8 +18,8 @@
*/
-#ifndef _AUBIO_SINK_SNDFILE_H
-#define _AUBIO_SINK_SNDFILE_H
+#ifndef AUBIO_SINK_SNDFILE_H
+#define AUBIO_SINK_SNDFILE_H
/** \file
@@ -57,7 +57,7 @@
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);
/**
@@ -101,7 +101,7 @@
\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);
/**
@@ -111,7 +111,7 @@
\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);
/**
@@ -159,4 +159,4 @@
}
#endif
-#endif /* _AUBIO_SINK_SNDFILE_H */
+#endif /* AUBIO_SINK_SNDFILE_H */
--- a/src/io/sink_wavwrite.c
+++ b/src/io/sink_wavwrite.c
@@ -77,7 +77,7 @@
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) {
@@ -89,7 +89,10 @@
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;
@@ -142,12 +145,12 @@
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;
}
@@ -287,6 +290,7 @@
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);
}
--- a/src/io/sink_wavwrite.h
+++ b/src/io/sink_wavwrite.h
@@ -18,8 +18,8 @@
*/
-#ifndef _AUBIO_SINK_WAVWRITE_H
-#define _AUBIO_SINK_WAVWRITE_H
+#ifndef AUBIO_SINK_WAVWRITE_H
+#define AUBIO_SINK_WAVWRITE_H
/** \file
@@ -57,7 +57,7 @@
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);
/**
@@ -101,7 +101,7 @@
\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);
/**
@@ -111,7 +111,7 @@
\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);
/**
@@ -159,4 +159,4 @@
}
#endif
-#endif /* _AUBIO_SINK_WAVWRITE_H */
+#endif /* AUBIO_SINK_WAVWRITE_H */
--- a/src/io/source.c
+++ b/src/io/source.c
@@ -40,6 +40,7 @@
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);
@@ -50,14 +51,15 @@
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);
@@ -64,6 +66,7 @@
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);
@@ -77,6 +80,7 @@
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);
@@ -83,7 +87,7 @@
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);
@@ -90,6 +94,7 @@
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);
@@ -96,7 +101,7 @@
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);
@@ -103,6 +108,7 @@
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);
@@ -139,6 +145,10 @@
uint_t aubio_source_get_channels(aubio_source_t * s) {
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 ) {
--- a/src/io/source.h
+++ b/src/io/source.h
@@ -18,8 +18,8 @@
*/
-#ifndef _AUBIO_SOURCE_H
-#define _AUBIO_SOURCE_H
+#ifndef AUBIO_SOURCE_H
+#define AUBIO_SOURCE_H
/** \file
@@ -85,7 +85,7 @@
::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);
/**
@@ -149,6 +149,16 @@
/**
+ 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
@@ -171,4 +181,4 @@
}
#endif
-#endif /* _AUBIO_SOURCE_H */
+#endif /* AUBIO_SOURCE_H */
--- a/src/io/source_apple_audio.c
+++ b/src/io/source_apple_audio.c
@@ -51,12 +51,12 @@
extern int createAubioBufferList(AudioBufferList *bufferList, int channels, int max_source_samples);
extern void freeAudioBufferList(AudioBufferList *bufferList);
-extern CFURLRef getURLFromPath(const char * path);
+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);
@@ -79,7 +79,6 @@
s->block_size = block_size;
s->samplerate = samplerate;
- s->path = path;
if ( aubio_source_apple_audio_open ( s, path ) ) {
goto beach;
@@ -91,15 +90,19 @@
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 = getURLFromPath(path);
+ CFURLRef fileURL = createURLFromPath(s->path);
err = ExtAudioFileOpenURL(fileURL, &s->audioFile);
+ CFRelease(fileURL);
if (err == -43) {
AUBIO_ERR("source_apple_audio: Failed opening %s, "
"file not found, or no read access\n", s->path);
@@ -292,6 +295,7 @@
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;
@@ -307,10 +311,7 @@
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 );
@@ -351,12 +352,27 @@
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 */
--- a/src/io/source_apple_audio.h
+++ b/src/io/source_apple_audio.h
@@ -18,8 +18,8 @@
*/
-#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
@@ -57,7 +57,7 @@
::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);
/**
@@ -95,7 +95,7 @@
\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);
/**
@@ -105,10 +105,20 @@
\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);
+
+/**
+
seek source object
\param s source object, created with ::new_aubio_source
@@ -143,4 +153,4 @@
}
#endif
-#endif /* _AUBIO_SOURCE_APPLE_AUDIO_H */
+#endif /* AUBIO_SOURCE_APPLE_AUDIO_H */
--- a/src/io/source_avcodec.c
+++ b/src/io/source_avcodec.c
@@ -23,8 +23,14 @@
#ifdef HAVE_LIBAV
-// determine whether we use libavformat from ffmpe or libav
-#define FFMPEG_LIBAVFORMAT (LIBAVFORMAT_VERSION_MICRO > 99)
+// 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) \
+ )
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
@@ -66,7 +72,22 @@
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) {
@@ -84,13 +105,17 @@
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;
@@ -103,7 +128,7 @@
}
// 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;
@@ -163,10 +188,10 @@
//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,
@@ -299,7 +324,7 @@
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){
@@ -369,11 +394,11 @@
*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;
}
@@ -397,6 +422,14 @@
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 );
@@ -424,6 +457,7 @@
if (s->avFrame != NULL) {
av_frame_free( &(s->avFrame) );
}
+ if (s->path) AUBIO_FREE(s->path);
s->avFrame = NULL;
AUBIO_FREE(s);
}
--- a/src/io/source_avcodec.h
+++ b/src/io/source_avcodec.h
@@ -18,8 +18,8 @@
*/
-#ifndef _AUBIO_SOURCE_AVCODEC_H
-#define _AUBIO_SOURCE_AVCODEC_H
+#ifndef AUBIO_SOURCE_AVCODEC_H
+#define AUBIO_SOURCE_AVCODEC_H
/** \file
@@ -56,7 +56,7 @@
::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);
/**
@@ -94,7 +94,7 @@
\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);
/**
@@ -104,7 +104,7 @@
\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);
/**
@@ -120,6 +120,16 @@
/**
+ 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
@@ -142,4 +152,4 @@
}
#endif
-#endif /* _AUBIO_SOURCE_AVCODEC_H */
+#endif /* AUBIO_SOURCE_AVCODEC_H */
--- a/src/io/source_sndfile.c
+++ b/src/io/source_sndfile.c
@@ -36,6 +36,12 @@
#define MAX_SIZE 4096
#define MAX_SAMPLES 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;
uint_t samplerate;
@@ -47,6 +53,7 @@
int input_samplerate;
int input_channels;
int input_format;
+ int duration;
// resampling stuff
smpl_t ratio;
@@ -58,10 +65,10 @@
// 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;
@@ -80,8 +87,11 @@
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));
s->handle = sf_open (s->path, SFM_READ, &sfinfo);
@@ -96,14 +106,16 @@
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) {
@@ -128,6 +140,7 @@
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) {
@@ -138,7 +151,7 @@
/* 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;
@@ -152,7 +165,7 @@
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;
@@ -193,7 +206,7 @@
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;
@@ -213,7 +226,7 @@
// 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 {
@@ -221,7 +234,7 @@
// 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];
}
}
}
@@ -231,7 +244,7 @@
// 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)];
}
}
}
@@ -262,6 +275,13 @@
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);
@@ -299,6 +319,7 @@
del_fvec(s->input_data);
}
#endif /* HAVE_SAMPLERATE */
+ if (s->path) AUBIO_FREE(s->path);
AUBIO_FREE(s->scratch_data);
AUBIO_FREE(s);
}
--- a/src/io/source_sndfile.h
+++ b/src/io/source_sndfile.h
@@ -18,8 +18,8 @@
*/
-#ifndef _AUBIO_SOURCE_SNDFILE_H
-#define _AUBIO_SOURCE_SNDFILE_H
+#ifndef AUBIO_SOURCE_SNDFILE_H
+#define AUBIO_SOURCE_SNDFILE_H
/** \file
@@ -56,7 +56,7 @@
::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);
/**
@@ -120,6 +120,16 @@
/**
+ 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
@@ -142,4 +152,4 @@
}
#endif
-#endif /* _AUBIO_SOURCE_SNDFILE_H */
+#endif /* AUBIO_SOURCE_SNDFILE_H */
--- a/src/io/source_wavread.c
+++ b/src/io/source_wavread.c
@@ -52,6 +52,8 @@
uint_t read_index;
uint_t eof;
+ uint_t duration;
+
size_t seek_start;
unsigned char *short_output;
@@ -67,11 +69,11 @@
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;
+ unsigned int format, channels, sr, byterate, blockalign, duration, bitspersample;//, data_size;
if (path == NULL) {
AUBIO_ERR("source_wavread: Aborted opening null path\n");
@@ -86,7 +88,10 @@
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;
@@ -212,6 +217,8 @@
// 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);
@@ -232,6 +239,8 @@
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;
@@ -371,6 +380,13 @@
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;
@@ -388,6 +404,7 @@
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);
}
--- a/src/io/source_wavread.h
+++ b/src/io/source_wavread.h
@@ -18,8 +18,8 @@
*/
-#ifndef _AUBIO_SOURCE_WAVREAD_H
-#define _AUBIO_SOURCE_WAVREAD_H
+#ifndef AUBIO_SOURCE_WAVREAD_H
+#define AUBIO_SOURCE_WAVREAD_H
/** \file
@@ -61,7 +61,7 @@
::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);
/**
@@ -125,6 +125,16 @@
/**
+ 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
@@ -147,4 +157,4 @@
}
#endif
-#endif /* _AUBIO_SOURCE_WAVREAD_H */
+#endif /* AUBIO_SOURCE_WAVREAD_H */
--- a/src/io/utils_apple_audio.c
+++ b/src/io/utils_apple_audio.c
@@ -33,12 +33,14 @@
bufferList = NULL;
}
-CFURLRef getURLFromPath(const char * path) {
+CFURLRef createURLFromPath(const char * path) {
CFStringRef cfTotalPath = CFStringCreateWithCString (kCFAllocatorDefault,
path, kCFStringEncodingUTF8);
- return CFURLCreateWithFileSystemPath(kCFAllocatorDefault, cfTotalPath,
+ CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, cfTotalPath,
kCFURLPOSIXPathStyle, false);
+ CFRelease(cfTotalPath);
+ return url;
}
char_t *getPrintableOSStatusError(char_t *str, OSStatus error)
--- a/src/lvec.c
+++ b/src/lvec.c
@@ -21,7 +21,7 @@
#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;
@@ -45,13 +45,13 @@
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]);
--- a/src/lvec.h
+++ b/src/lvec.h
@@ -18,8 +18,8 @@
*/
-#ifndef _AUBIO__LVEC_H
-#define _AUBIO__LVEC_H
+#ifndef AUBIO_LVEC_H
+#define AUBIO_LVEC_H
#ifdef __cplusplus
extern "C" {
@@ -80,7 +80,7 @@
\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
@@ -87,7 +87,7 @@
\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
@@ -115,4 +115,4 @@
}
#endif
-#endif /* _AUBIO__LVEC_H */
+#endif /* AUBIO_LVEC_H */
--- a/src/mathutils.c
+++ b/src/mathutils.c
@@ -26,10 +26,6 @@
#include "musicutils.h"
#include "config.h"
-#ifdef HAVE_ACCELERATE
-#include <Accelerate/Accelerate.h>
-#endif
-
/** Window types */
typedef enum
{
@@ -166,11 +162,7 @@
}
return tmp / (smpl_t) (s->length);
#else
-#if !HAVE_AUBIO_DOUBLE
- vDSP_meanv(s->data, 1, &tmp, s->length);
-#else /* HAVE_AUBIO_DOUBLE */
- vDSP_meanvD(s->data, 1, &tmp, s->length);
-#endif /* HAVE_AUBIO_DOUBLE */
+ aubio_vDSP_meanv(s->data, 1, &tmp, s->length);
return tmp;
#endif /* HAVE_ACCELERATE */
}
@@ -185,11 +177,7 @@
tmp += s->data[j];
}
#else
-#if !HAVE_AUBIO_DOUBLE
- vDSP_sve(s->data, 1, &tmp, s->length);
-#else /* HAVE_AUBIO_DOUBLE */
- vDSP_sveD(s->data, 1, &tmp, s->length);
-#endif /* HAVE_AUBIO_DOUBLE */
+ aubio_vDSP_sve(s->data, 1, &tmp, s->length);
#endif /* HAVE_ACCELERATE */
return tmp;
}
@@ -205,12 +193,8 @@
}
#else
smpl_t tmp = 0.;
-#if !HAVE_AUBIO_DOUBLE
- vDSP_maxv(s->data, 1, &tmp, s->length);
-#else
- vDSP_maxvD(s->data, 1, &tmp, s->length);
+ aubio_vDSP_maxv(s->data, 1, &tmp, s->length);
#endif
-#endif
return tmp;
}
@@ -225,12 +209,8 @@
}
#else
smpl_t tmp = 0.;
-#if !HAVE_AUBIO_DOUBLE
- vDSP_minv(s->data, 1, &tmp, s->length);
-#else
- vDSP_minvD(s->data, 1, &tmp, s->length);
+ aubio_vDSP_minv(s->data, 1, &tmp, s->length);
#endif
-#endif
return tmp;
}
@@ -247,12 +227,8 @@
#else
smpl_t tmp = 0.;
uint_t pos = 0.;
-#if !HAVE_AUBIO_DOUBLE
- vDSP_minvi(s->data, 1, &tmp, (vDSP_Length *)&pos, s->length);
-#else
- vDSP_minviD(s->data, 1, &tmp, (vDSP_Length *)&pos, s->length);
+ aubio_vDSP_minvi(s->data, 1, &tmp, (vDSP_Length *)&pos, s->length);
#endif
-#endif
return pos;
}
@@ -269,12 +245,8 @@
#else
smpl_t tmp = 0.;
uint_t pos = 0.;
-#if !HAVE_AUBIO_DOUBLE
- vDSP_maxvi(s->data, 1, &tmp, (vDSP_Length *)&pos, s->length);
-#else
- vDSP_maxviD(s->data, 1, &tmp, (vDSP_Length *)&pos, s->length);
+ aubio_vDSP_maxvi(s->data, 1, &tmp, (vDSP_Length *)&pos, s->length);
#endif
-#endif
return pos;
}
@@ -281,20 +253,55 @@
void
fvec_shift (fvec_t * s)
{
- uint_t j;
- for (j = 0; j < s->length / 2; j++) {
- ELEM_SWAP (s->data[j], s->data[j + s->length / 2]);
+ 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
+ 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[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
uint_t j;
for (j = 0; j < f->length; j++) {
energy += SQR (f->data[j]);
}
+#else
+ energy = aubio_cblas_dot(f->length, f->data, 1, f->data, 1);
+#endif
return energy / f->length;
}
@@ -433,8 +440,9 @@
}
}
-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;
@@ -443,7 +451,7 @@
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) {
@@ -457,7 +465,7 @@
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]
@@ -544,13 +552,13 @@
}
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);
}
@@ -590,7 +598,7 @@
}
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;
--- a/src/mathutils.h
+++ b/src/mathutils.h
@@ -27,8 +27,8 @@
*/
-#ifndef _AUBIO_MATHUTILS_H
-#define _AUBIO_MATHUTILS_H
+#ifndef AUBIO_MATHUTILS_H
+#define AUBIO_MATHUTILS_H
#include "fvec.h"
#include "musicutils.h"
@@ -99,6 +99,24 @@
*/
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
@@ -232,7 +250,7 @@
\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
@@ -275,7 +293,7 @@
\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);
@@ -289,10 +307,10 @@
\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 */
--- a/src/musicutils.h
+++ b/src/musicutils.h
@@ -22,8 +22,8 @@
* 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" {
@@ -56,8 +56,8 @@
implementations of a phase vocoder: the tricks of the trade. In Proceedings of
the International Conference on Digital Audio Effects (DAFx-00), pages 37–44,
Uni- versity of Verona, Italy, 2000.
- (<a href="http://profs.sci.univr.it/%7Edafx/Final-Papers/ps/Bernardini.ps.gz">
- ps.gz</a>)
+ (<a href="http://www.cs.princeton.edu/courses/archive/spr09/cos325/Bernardini.pdf">
+ pdf</a>)
*/
uint_t fvec_set_window (fvec_t * window, char_t * window_type);
@@ -121,7 +121,7 @@
\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
@@ -134,7 +134,7 @@
\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
@@ -144,7 +144,7 @@
\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
@@ -160,4 +160,4 @@
}
#endif
-#endif /* _AUBIO__MUSICUTILS_H */
+#endif /* AUBIO_MUSICUTILS_H */
--- a/src/onset/onset.c
+++ b/src/onset/onset.c
@@ -45,7 +45,7 @@
};
/* 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);
@@ -84,17 +84,17 @@
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.;
}
@@ -104,7 +104,7 @@
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;
}
@@ -113,7 +113,7 @@
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);
}
@@ -122,15 +122,15 @@
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;
}
@@ -138,7 +138,7 @@
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.;
}
@@ -147,7 +147,7 @@
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;
}
@@ -155,7 +155,7 @@
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;
}
@@ -163,21 +163,21 @@
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);
@@ -186,8 +186,8 @@
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);
--- a/src/onset/onset.h
+++ b/src/onset/onset.h
@@ -39,8 +39,8 @@
*/
-#ifndef _AUBIO_ONSET_H
-#define _AUBIO_ONSET_H
+#ifndef AUBIO_ONSET_H
+#define AUBIO_ONSET_H
#ifdef __cplusplus
extern "C" {
@@ -59,7 +59,7 @@
\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
@@ -88,7 +88,7 @@
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
@@ -97,7 +97,7 @@
\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
@@ -106,7 +106,7 @@
\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
@@ -115,7 +115,7 @@
\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 silence threshold
@@ -132,7 +132,7 @@
\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
@@ -140,7 +140,7 @@
\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
@@ -148,7 +148,7 @@
\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
@@ -219,7 +219,7 @@
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
@@ -228,7 +228,7 @@
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
@@ -237,7 +237,7 @@
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
@@ -246,7 +246,7 @@
(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
@@ -255,7 +255,7 @@
(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
@@ -264,7 +264,7 @@
(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
@@ -272,7 +272,7 @@
\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
@@ -285,4 +285,4 @@
}
#endif
-#endif /* _AUBIO_ONSET_H */
+#endif /* AUBIO_ONSET_H */
--- a/src/onset/peakpicker.h
+++ b/src/onset/peakpicker.h
@@ -26,8 +26,8 @@
*/
-#ifndef _AUBIO_PEAKPICK_H
-#define _AUBIO_PEAKPICK_H
+#ifndef AUBIO_PEAKPICK_H
+#define AUBIO_PEAKPICK_H
#ifdef __cplusplus
extern "C" {
@@ -54,4 +54,4 @@
}
#endif
-#endif /* _AUBIO_PEAKPICK_H */
+#endif /* AUBIO_PEAKPICK_H */
--- a/src/pitch/pitch.c
+++ b/src/pitch/pitch.c
@@ -61,7 +61,7 @@
} 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);
@@ -78,6 +78,7 @@
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 */
@@ -88,12 +89,12 @@
};
/* 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);
+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);
/* conversion functions for frequency conversions */
smpl_t freqconvbin (smpl_t f, uint_t samplerate, uint_t bufsize);
@@ -101,11 +102,11 @@
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);
@@ -132,16 +133,16 @@
// 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", bufsize, hopsize);
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;
}
@@ -160,6 +161,7 @@
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);
p->fftgrain = new_cvec (bufsize);
p->p_object = new_aubio_pitchmcomb (bufsize, hopsize);
@@ -209,6 +211,7 @@
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);
@@ -237,10 +240,11 @@
}
void
-aubio_pitch_slideblock (aubio_pitch_t * p, fvec_t * ibuf)
+aubio_pitch_slideblock (aubio_pitch_t * p, const fvec_t * ibuf)
{
- uint_t j = 0, overlap_size = 0;
- overlap_size = p->buf->length - ibuf->length;
+ uint_t overlap_size = p->buf->length - ibuf->length;
+#if 1 //!HAVE_MEMCPY_HACKS
+ uint_t j;
for (j = 0; j < overlap_size; j++) {
p->buf->data[j] = p->buf->data[j + ibuf->length];
}
@@ -247,10 +251,16 @@
for (j = 0; j < ibuf->length; j++) {
p->buf->data[j + overlap_size] = ibuf->data[j];
}
+#else
+ smpl_t *data = p->buf->data;
+ smpl_t *newdata = ibuf->data;
+ memmove(data, data + ibuf->length, overlap_size);
+ memcpy(data + overlap_size, newdata, ibuf->length);
+#endif
}
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;
@@ -335,7 +345,7 @@
/* 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) {
@@ -346,9 +356,9 @@
/* 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);
@@ -355,7 +365,7 @@
}
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);
@@ -371,7 +381,7 @@
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);
@@ -386,7 +396,7 @@
}
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);
@@ -402,7 +412,7 @@
}
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);
@@ -410,7 +420,7 @@
}
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);
--- a/src/pitch/pitch.h
+++ b/src/pitch/pitch.h
@@ -18,8 +18,8 @@
*/
-#ifndef _AUBIO_PITCH_H
-#define _AUBIO_PITCH_H
+#ifndef AUBIO_PITCH_H
+#define AUBIO_PITCH_H
#ifdef __cplusplus
extern "C" {
@@ -107,7 +107,7 @@
\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
@@ -134,7 +134,7 @@
\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
@@ -145,7 +145,7 @@
\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
@@ -179,4 +179,4 @@
}
#endif
-#endif /* _AUBIO_PITCH_H */
+#endif /* AUBIO_PITCH_H */
--- a/src/pitch/pitchfcomb.c
+++ b/src/pitch/pitchfcomb.c
@@ -63,7 +63,7 @@
/* 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;
--- a/src/pitch/pitchfcomb.h
+++ b/src/pitch/pitchfcomb.h
@@ -34,8 +34,8 @@
*/
-#ifndef _AUBIO_PITCHFCOMB_H
-#define _AUBIO_PITCHFCOMB_H
+#ifndef AUBIO_PITCHFCOMB_H
+#define AUBIO_PITCHFCOMB_H
#ifdef __cplusplus
extern "C" {
@@ -51,7 +51,7 @@
\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
@@ -73,4 +73,4 @@
}
#endif
-#endif /* _AUBIO_PITCHFCOMB_H */
+#endif /* AUBIO_PITCHFCOMB_H */
--- a/src/pitch/pitchmcomb.c
+++ b/src/pitch/pitchmcomb.c
@@ -31,9 +31,9 @@
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);
*/
@@ -42,7 +42,7 @@
/** 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 */
@@ -101,7 +101,7 @@
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;
@@ -134,7 +134,7 @@
}
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;
@@ -165,7 +165,7 @@
}
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;
@@ -197,7 +197,7 @@
}
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 =
@@ -285,7 +285,7 @@
* \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++) {
@@ -335,8 +335,7 @@
uint_t cur = 0;
uint_t run = 0;
for (cur = 0; cur < nbins; cur++) {
- run = cur + 1;
- for (run = cur; run < nbins; run++) {
+ for (run = cur + 1; run < nbins; run++) {
if (candidates[run]->ene > candidates[cur]->ene)
CAND_SWAP (candidates[run], candidates[cur]);
}
@@ -351,8 +350,7 @@
uint_t cur = 0;
uint_t run = 0;
for (cur = 0; cur < nbins; cur++) {
- run = cur + 1;
- for (run = cur; run < nbins; run++) {
+ for (run = cur + 1; run < nbins; run++) {
if (candidates[run]->ebin < candidates[cur]->ebin)
CAND_SWAP (candidates[run], candidates[cur]);
}
@@ -366,7 +364,7 @@
/* 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.;
@@ -378,7 +376,7 @@
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 */
--- a/src/pitch/pitchmcomb.h
+++ b/src/pitch/pitchmcomb.h
@@ -35,8 +35,8 @@
*/
-#ifndef _AUBIO_PITCHMCOMB_H
-#define _AUBIO_PITCHMCOMB_H
+#ifndef AUBIO_PITCHMCOMB_H
+#define AUBIO_PITCHMCOMB_H
#ifdef __cplusplus
extern "C" {
@@ -52,7 +52,7 @@
\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
@@ -74,4 +74,4 @@
}
#endif
-#endif /* _AUBIO_PITCHMCOMB_H */
+#endif /* AUBIO_PITCHMCOMB_H */
--- a/src/pitch/pitchschmitt.c
+++ b/src/pitch/pitchschmitt.c
@@ -47,7 +47,7 @@
}
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;
--- a/src/pitch/pitchschmitt.h
+++ b/src/pitch/pitchschmitt.h
@@ -34,8 +34,8 @@
*/
-#ifndef _AUBIO_PITCHSCHMITT_H
-#define _AUBIO_PITCHSCHMITT_H
+#ifndef AUBIO_PITCHSCHMITT_H
+#define AUBIO_PITCHSCHMITT_H
#ifdef __cplusplus
extern "C" {
@@ -51,7 +51,7 @@
\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
@@ -72,5 +72,4 @@
}
#endif
-#endif /* _AUBIO_PITCHSCHMITT_H */
-
+#endif /* AUBIO_PITCHSCHMITT_H */
--- a/src/pitch/pitchspecacf.c
+++ b/src/pitch/pitchspecacf.c
@@ -54,7 +54,7 @@
}
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;
@@ -91,7 +91,7 @@
}
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;
}
@@ -104,7 +104,7 @@
}
smpl_t
-aubio_pitchspecacf_get_tolerance (aubio_pitchspecacf_t * p)
+aubio_pitchspecacf_get_tolerance (const aubio_pitchspecacf_t * p)
{
return p->tol;
}
--- a/src/pitch/pitchspecacf.h
+++ b/src/pitch/pitchspecacf.h
@@ -38,8 +38,8 @@
*/
-#ifndef _AUBIO_PITCHSPECACF_H
-#define _AUBIO_PITCHSPECACF_H
+#ifndef AUBIO_PITCHSPECACF_H
+#define AUBIO_PITCHSPECACF_H
#ifdef __cplusplus
extern "C" {
@@ -55,7 +55,7 @@
\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
@@ -76,7 +76,7 @@
\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
@@ -94,10 +94,10 @@
\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 */
--- a/src/pitch/pitchyin.c
+++ b/src/pitch/pitchyin.c
@@ -40,26 +40,26 @@
};
/** 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)
@@ -111,7 +111,7 @@
}
uint_t
-aubio_pitchyin_getpitch (fvec_t * yin)
+aubio_pitchyin_getpitch (const fvec_t * yin)
{
uint_t tau = 1;
do {
@@ -130,7 +130,7 @@
/* 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;
--- a/src/pitch/pitchyin.h
+++ b/src/pitch/pitchyin.h
@@ -35,8 +35,8 @@
*/
-#ifndef _AUBIO_PITCHYIN_H
-#define _AUBIO_PITCHYIN_H
+#ifndef AUBIO_PITCHYIN_H
+#define AUBIO_PITCHYIN_H
#ifdef __cplusplus
extern "C" {
@@ -66,7 +66,7 @@
\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
@@ -97,4 +97,4 @@
}
#endif
-#endif /* _AUBIO_PITCHYIN_H */
+#endif /* AUBIO_PITCHYIN_H */
--- a/src/pitch/pitchyinfft.c
+++ b/src/pitch/pitchyinfft.c
@@ -98,7 +98,7 @@
}
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;
@@ -107,9 +107,7 @@
fvec_t *yin = p->yinfft;
smpl_t tmp = 0., sum = 0.;
// window the input
- for (l = 0; l < input->length; l++) {
- p->winput->data[l] = p->win->data[l] * input->data[l];
- }
+ fvec_weighted_copy(input, p->win, p->winput);
// get the real / imag parts of its fft
aubio_fft_do_complex (p->fft, p->winput, fftout);
// get the squared magnitude spectrum, applying some weight
--- a/src/pitch/pitchyinfft.h
+++ b/src/pitch/pitchyinfft.h
@@ -35,8 +35,8 @@
*/
-#ifndef _AUBIO_PITCHYINFFT_H
-#define _AUBIO_PITCHYINFFT_H
+#ifndef AUBIO_PITCHYINFFT_H
+#define AUBIO_PITCHYINFFT_H
#ifdef __cplusplus
extern "C" {
@@ -52,7 +52,7 @@
\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
@@ -96,4 +96,4 @@
}
#endif
-#endif /* _AUBIO_PITCHYINFFT_H */
+#endif /* AUBIO_PITCHYINFFT_H */
--- a/src/spectral/fft.c
+++ b/src/spectral/fft.c
@@ -64,12 +64,12 @@
#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 */
@@ -143,8 +143,8 @@
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
@@ -230,17 +230,17 @@
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++) {
@@ -291,7 +291,7 @@
#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;
@@ -346,17 +346,17 @@
#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;
@@ -374,7 +374,7 @@
}
}
-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++) {
@@ -385,7 +385,7 @@
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] =
@@ -393,7 +393,7 @@
}
}
-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] =
--- a/src/spectral/fft.h
+++ b/src/spectral/fft.h
@@ -31,8 +31,8 @@
*/
-#ifndef _AUBIO_FFT_H
-#define _AUBIO_FFT_H
+#ifndef AUBIO_FFT_H
+#define AUBIO_FFT_H
#ifdef __cplusplus
extern "C" {
@@ -65,7 +65,7 @@
\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
@@ -73,7 +73,7 @@
\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
@@ -82,7 +82,7 @@
\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
@@ -90,7 +90,7 @@
\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
@@ -98,7 +98,7 @@
\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
@@ -105,7 +105,7 @@
\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
@@ -113,7 +113,7 @@
\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
@@ -120,7 +120,7 @@
\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
@@ -128,7 +128,7 @@
\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
@@ -135,10 +135,10 @@
\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 */
--- a/src/spectral/filterbank.c
+++ b/src/spectral/filterbank.c
@@ -56,36 +56,30 @@
}
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;
--- a/src/spectral/filterbank.h
+++ b/src/spectral/filterbank.h
@@ -29,8 +29,8 @@
*/
-#ifndef _AUBIO_FILTERBANK_H
-#define _AUBIO_FILTERBANK_H
+#ifndef AUBIO_FILTERBANK_H
+#define AUBIO_FILTERBANK_H
#ifdef __cplusplus
extern "C"
@@ -66,7 +66,7 @@
\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
@@ -73,7 +73,7 @@
\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
@@ -81,10 +81,10 @@
\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 */
--- a/src/spectral/filterbank_mel.c
+++ b/src/spectral/filterbank_mel.c
@@ -29,7 +29,7 @@
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);
--- a/src/spectral/filterbank_mel.h
+++ b/src/spectral/filterbank_mel.h
@@ -31,8 +31,8 @@
*/
-#ifndef _AUBIO_FILTERBANK_MEL_H
-#define _AUBIO_FILTERBANK_MEL_H
+#ifndef AUBIO_FILTERBANK_MEL_H
+#define AUBIO_FILTERBANK_MEL_H
#ifdef __cplusplus
extern "C"
@@ -50,7 +50,7 @@
*/
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
@@ -69,4 +69,4 @@
}
#endif
-#endif /* _AUBIO_FILTERBANK_MEL_H */
+#endif /* AUBIO_FILTERBANK_MEL_H */
--- a/src/spectral/mfcc.c
+++ b/src/spectral/mfcc.c
@@ -67,21 +67,21 @@
/* 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)
@@ -100,10 +100,8 @@
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);
@@ -113,16 +111,8 @@
/* 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;
}
--- a/src/spectral/mfcc.h
+++ b/src/spectral/mfcc.h
@@ -34,8 +34,8 @@
*/
-#ifndef _AUBIO_MFCC_H
-#define _AUBIO_MFCC_H
+#ifndef AUBIO_MFCC_H
+#define AUBIO_MFCC_H
#ifdef __cplusplus
extern "C"
@@ -70,10 +70,10 @@
\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 */
--- a/src/spectral/phasevoc.c
+++ b/src/spectral/phasevoc.c
@@ -44,12 +44,12 @@
/** 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 */
@@ -64,7 +64,12 @@
/* 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);
}
@@ -79,8 +84,8 @@
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);
@@ -88,6 +93,9 @@
}
pv->fft = new_aubio_fft (win_s);
+ if (pv->fft == NULL) {
+ goto beach;
+ }
/* remember old */
pv->data = new_fvec (win_s);
@@ -117,7 +125,16 @@
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;
@@ -136,13 +153,13 @@
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];
--- a/src/spectral/phasevoc.h
+++ b/src/spectral/phasevoc.h
@@ -31,8 +31,8 @@
*/
-#ifndef _AUBIO_PHASEVOC_H
-#define _AUBIO_PHASEVOC_H
+#ifndef AUBIO_PHASEVOC_H
+#define AUBIO_PHASEVOC_H
#ifdef __cplusplus
extern "C" {
@@ -67,7 +67,7 @@
\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
@@ -99,4 +99,4 @@
}
#endif
-#endif /* _AUBIO_PHASEVOC_H */
+#endif /* AUBIO_PHASEVOC_H */
--- a/src/spectral/specdesc.c
+++ b/src/spectral/specdesc.c
@@ -26,28 +26,28 @@
#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 */
@@ -75,7 +75,7 @@
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 */
@@ -87,7 +87,7 @@
/* 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++) {
@@ -97,7 +97,7 @@
/* 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++) {
@@ -107,7 +107,7 @@
/* 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.;
@@ -131,7 +131,7 @@
/* 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;
@@ -161,7 +161,7 @@
/* 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;
@@ -188,7 +188,7 @@
/* 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++) {
@@ -202,7 +202,7 @@
/* 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++) {
@@ -213,7 +213,7 @@
}
/* 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++) {
@@ -225,7 +225,7 @@
/* 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);
}
@@ -234,7 +234,7 @@
* 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;
--- a/src/spectral/specdesc.h
+++ b/src/spectral/specdesc.h
@@ -145,8 +145,8 @@
*/
-#ifndef _AUBIO_SPECDESC_H
-#define _AUBIO_SPECDESC_H
+#ifndef AUBIO_SPECDESC_H
+#define AUBIO_SPECDESC_H
#ifdef __cplusplus
extern "C" {
@@ -164,7 +164,7 @@
\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
@@ -178,7 +178,7 @@
- `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
@@ -191,4 +191,4 @@
}
#endif
-#endif /* _AUBIO_SPECDESC_H */
+#endif /* AUBIO_SPECDESC_H */
--- a/src/spectral/statistics.c
+++ b/src/spectral/statistics.c
@@ -22,29 +22,29 @@
#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;
@@ -55,13 +55,13 @@
}
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;
@@ -77,7 +77,7 @@
}
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;
@@ -94,7 +94,7 @@
}
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);
@@ -101,7 +101,7 @@
}
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);
@@ -108,7 +108,7 @@
}
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;
@@ -122,7 +122,7 @@
}
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;
@@ -136,7 +136,7 @@
}
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;
@@ -164,7 +164,7 @@
}
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;
@@ -182,7 +182,7 @@
}
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;
--- a/src/spectral/tss.c
+++ b/src/spectral/tss.c
@@ -40,7 +40,7 @@
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;
--- a/src/spectral/tss.h
+++ b/src/spectral/tss.h
@@ -36,8 +36,8 @@
*/
-#ifndef _AUBIO_TSS_H
-#define _AUBIO_TSS_H
+#ifndef AUBIO_TSS_H
+#define AUBIO_TSS_H
#ifdef __cplusplus
extern "C" {
@@ -69,7 +69,7 @@
\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
@@ -100,4 +100,4 @@
}
#endif
-#endif /* _AUBIO_TSS_H */
+#endif /* AUBIO_TSS_H */
--- a/src/synth/sampler.c
+++ b/src/synth/sampler.c
@@ -55,10 +55,14 @@
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);
@@ -65,7 +69,7 @@
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) {
@@ -82,7 +86,7 @@
}
}
-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) {
@@ -103,7 +107,7 @@
}
}
-uint_t aubio_sampler_get_playing ( aubio_sampler_t * o )
+uint_t aubio_sampler_get_playing ( const aubio_sampler_t * o )
{
return o->playing;
}
@@ -130,6 +134,7 @@
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);
--- a/src/synth/sampler.h
+++ b/src/synth/sampler.h
@@ -18,8 +18,8 @@
*/
-#ifndef _AUBIO_SAMPLER_H
-#define _AUBIO_SAMPLER_H
+#ifndef AUBIO_SAMPLER_H
+#define AUBIO_SAMPLER_H
/** \file
@@ -59,7 +59,7 @@
\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
@@ -73,7 +73,7 @@
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
@@ -87,7 +87,7 @@
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
@@ -96,7 +96,7 @@
\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
@@ -137,4 +137,4 @@
}
#endif
-#endif /* _AUBIO_SAMPLER_H */
+#endif /* AUBIO_SAMPLER_H */
--- a/src/synth/wavetable.c
+++ b/src/synth/wavetable.c
@@ -68,7 +68,7 @@
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];
@@ -76,7 +76,7 @@
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) {
@@ -107,7 +107,7 @@
}
}
-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) {
@@ -142,7 +142,7 @@
}
}
-uint_t aubio_wavetable_get_playing ( aubio_wavetable_t * s )
+uint_t aubio_wavetable_get_playing ( const aubio_wavetable_t * s )
{
return s->playing;
}
@@ -172,7 +172,7 @@
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);
}
@@ -181,7 +181,7 @@
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 );
}
--- a/src/synth/wavetable.h
+++ b/src/synth/wavetable.h
@@ -18,8 +18,8 @@
*/
-#ifndef _AUBIO_WAVETABLE_H
-#define _AUBIO_WAVETABLE_H
+#ifndef AUBIO_WAVETABLE_H
+#define AUBIO_WAVETABLE_H
/** \file
@@ -59,7 +59,7 @@
\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
@@ -73,7 +73,7 @@
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
@@ -87,7 +87,7 @@
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
@@ -96,7 +96,7 @@
\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
@@ -143,7 +143,7 @@
\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
@@ -162,7 +162,7 @@
\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
@@ -175,4 +175,4 @@
}
#endif
-#endif /* _AUBIO_WAVETABLE_H */
+#endif /* AUBIO_WAVETABLE_H */
--- a/src/tempo/beattracking.c
+++ b/src/tempo/beattracking.c
@@ -123,7 +123,7 @@
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)
{
@@ -409,10 +409,22 @@
}
smpl_t
-aubio_beattracking_get_bpm (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 (const aubio_beattracking_t * bt)
+{
+ return aubio_beattracking_get_period(bt) / (smpl_t) bt->samplerate;
+}
+
+smpl_t
+aubio_beattracking_get_bpm (const aubio_beattracking_t * bt)
+{
if (bt->bp != 0) {
- return 60. * bt->samplerate/ bt->bp / bt->hop_size;
+ return 60. / aubio_beattracking_get_period_s(bt);
} else {
return 0.;
}
@@ -419,7 +431,7 @@
}
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);
--- a/src/tempo/beattracking.h
+++ b/src/tempo/beattracking.h
@@ -36,8 +36,8 @@
\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" {
@@ -64,9 +64,29 @@
\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
+
+ \param bt beat tracking object
+
+ Returns the currently observed period, in samples, or 0 if no consistent
+ value is found.
+
+*/
+smpl_t aubio_beattracking_get_period (const aubio_beattracking_t * bt);
+
+/** get current beat period in seconds
+
+ \param bt beat tracking object
+
+ Returns the currently observed period, in seconds, or 0 if no consistent
+ value is found.
+
+*/
+smpl_t aubio_beattracking_get_period_s (const aubio_beattracking_t * bt);
+
/** get current tempo in bpm
\param bt beat tracking object
@@ -75,7 +95,7 @@
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
@@ -85,7 +105,7 @@
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
@@ -98,4 +118,4 @@
}
#endif
-#endif /* _AUBIO_BEATTRACKING_H */
+#endif /* AUBIO_BEATTRACKING_H */
--- a/src/tempo/tempo.c
+++ b/src/tempo/tempo.c
@@ -28,27 +28,6 @@
#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 */
@@ -64,16 +43,18 @@
smpl_t threshold; /** peak picking threshold */
sint_t blockpos; /** current position in dfframe */
uint_t winlen; /** dfframe bufsize */
- uint_t step; /** dfframe hopsize */
- uint_t samplerate; /** sampling rate of the signal */
+ uint_t step; /** dfframe hopsize */
+ uint_t samplerate; /** sampling rate of the signal */
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;
@@ -90,20 +71,21 @@
/* check dfframe */
aubio_beattracking_do(o->bt,o->dfframe,o->out);
/* rotate dfframe */
- for (i = 0 ; i < winlen - step; i++ )
+ for (i = 0 ; i < winlen - step; i++ )
o->dfframe->data[i] = o->dfframe->data[i+step];
- for (i = winlen - step ; i < winlen; i++ )
+ for (i = winlen - step ; i < winlen; i++ )
o->dfframe->data[i] = 0.;
o->blockpos = -1;
}
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 */
tempo->data[0] = 0; /* reset tactus */
- i=0;
+ //i=0;
for (i = 1; i < o->out->data[0]; i++ ) {
/* if current frame is a predicted tactus */
if (o->blockpos == FLOOR(o->out->data[i])) {
@@ -113,6 +95,7 @@
tempo->data[0] = 0; // unset beat if silent
}
o->last_beat = o->total_frames + (uint_t)ROUND(tempo->data[0] * o->hop_size);
+ o->last_tatum = o->last_beat;
}
}
o->total_frames += o->hop_size;
@@ -121,7 +104,7 @@
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)
@@ -134,15 +117,33 @@
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;
@@ -163,7 +164,7 @@
}
/* 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);
@@ -173,8 +174,8 @@
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);
@@ -214,6 +215,8 @@
o2 = new_aubio_specdesc(type_onset2,buffer_size);
onset2 = new_fvec(1);
}*/
+ o->last_tatum = 0;
+ o->tatum_signature = 4;
return o;
beach:
@@ -225,8 +228,51 @@
return aubio_beattracking_get_bpm(o->bt);
}
+smpl_t aubio_tempo_get_period (aubio_tempo_t *o)
+{
+ return aubio_beattracking_get_period (o->bt);
+}
+
+smpl_t aubio_tempo_get_period_s (aubio_tempo_t *o)
+{
+ return aubio_beattracking_get_period_s (o->bt);
+}
+
smpl_t aubio_tempo_get_confidence(aubio_tempo_t *o) {
return aubio_beattracking_get_confidence(o->bt);
+}
+
+uint_t aubio_tempo_was_tatum (aubio_tempo_t *o)
+{
+ uint_t last_tatum_distance = o->total_frames - o->last_tatum;
+ smpl_t beat_period = aubio_tempo_get_period(o);
+ smpl_t tatum_period = beat_period / o->tatum_signature;
+ if (last_tatum_distance < o->hop_size) {
+ o->last_tatum = o->last_beat;
+ return 2;
+ }
+ else if (last_tatum_distance > tatum_period) {
+ if ( last_tatum_distance + o->hop_size > beat_period ) {
+ // next beat is too close, pass
+ return 0;
+ }
+ o->last_tatum = o->total_frames;
+ return 1;
+ }
+ return 0;
+}
+
+smpl_t aubio_tempo_get_last_tatum (aubio_tempo_t *o) {
+ return (smpl_t)o->last_tatum - o->delay;
+}
+
+uint_t aubio_tempo_set_tatum_signature (aubio_tempo_t *o, uint_t signature) {
+ if (signature < 1 || signature > 64) {
+ return AUBIO_FAIL;
+ } else {
+ o->tatum_signature = signature;
+ return AUBIO_OK;
+ }
}
void del_aubio_tempo (aubio_tempo_t *o)
--- a/src/tempo/tempo.h
+++ b/src/tempo/tempo.h
@@ -30,8 +30,8 @@
*/
-#ifndef _AUBIO_TEMPO_H
-#define _AUBIO_TEMPO_H
+#ifndef AUBIO_TEMPO_H
+#define AUBIO_TEMPO_H
#ifdef __cplusplus
extern "C" {
@@ -50,7 +50,7 @@
\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
@@ -60,7 +60,7 @@
\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
@@ -121,6 +121,26 @@
*/
smpl_t aubio_tempo_get_threshold(aubio_tempo_t * o);
+/** get current beat period in samples
+
+ \param bt beat tracking object
+
+ Returns the currently observed period, in samples, or 0 if no consistent
+ value is found.
+
+*/
+smpl_t aubio_tempo_get_period (aubio_tempo_t * bt);
+
+/** get current beat period in seconds
+
+ \param bt beat tracking object
+
+ Returns the currently observed period, in seconds, or 0 if no consistent
+ value is found.
+
+*/
+smpl_t aubio_tempo_get_period_s (aubio_tempo_t * bt);
+
/** get current tempo
\param o beat tracking object
@@ -140,6 +160,87 @@
*/
smpl_t aubio_tempo_get_confidence(aubio_tempo_t * o);
+/* 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
+
+ \param o beat tracking object
+
+ \return 2 if a beat was detected, 1 if a tatum was detected, 0 otherwise
+
+*/
+uint_t aubio_tempo_was_tatum(aubio_tempo_t *o);
+
+/* 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
@@ -151,4 +252,4 @@
}
#endif
-#endif /* _AUBIO_TEMPO_H */
+#endif /* AUBIO_TEMPO_H */
--- a/src/temporal/a_weighting.c
+++ b/src/temporal/a_weighting.c
@@ -29,17 +29,27 @@
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) {
@@ -244,6 +254,9 @@
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;
}
--- a/src/temporal/a_weighting.h
+++ b/src/temporal/a_weighting.h
@@ -18,8 +18,8 @@
*/
-#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
@@ -85,4 +85,4 @@
}
#endif
-#endif /* _AUBIO_FILTER_A_DESIGN_H */
+#endif /* AUBIO_FILTER_A_DESIGN_H */
--- a/src/temporal/biquad.h
+++ b/src/temporal/biquad.h
@@ -18,8 +18,8 @@
*/
-#ifndef _AUBIO_FILTER_BIQUAD_H
-#define _AUBIO_FILTER_BIQUAD_H
+#ifndef AUBIO_FILTER_BIQUAD_H
+#define AUBIO_FILTER_BIQUAD_H
/** \file
@@ -72,4 +72,4 @@
}
#endif
-#endif /* _AUBIO_FILTER_BIQUAD_H */
+#endif /* AUBIO_FILTER_BIQUAD_H */
--- a/src/temporal/c_weighting.c
+++ b/src/temporal/c_weighting.c
@@ -29,17 +29,27 @@
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) {
@@ -199,7 +209,9 @@
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;
}
-
--- a/src/temporal/c_weighting.h
+++ b/src/temporal/c_weighting.h
@@ -18,8 +18,8 @@
*/
-#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
@@ -85,4 +85,4 @@
}
#endif
-#endif /* _AUBIO_FILTER_C_DESIGN_H */
+#endif /* AUBIO_FILTER_C_DESIGN_H */
--- a/src/temporal/filter.c
+++ b/src/temporal/filter.c
@@ -39,7 +39,7 @@
};
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);
@@ -93,25 +93,25 @@
}
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;
}
@@ -134,6 +134,10 @@
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);
@@ -142,7 +146,8 @@
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;
}
--- a/src/temporal/filter.h
+++ b/src/temporal/filter.h
@@ -18,8 +18,8 @@
*/
-#ifndef _AUBIO_FILTER_H
-#define _AUBIO_FILTER_H
+#ifndef AUBIO_FILTER_H
+#define AUBIO_FILTER_H
/** \file
@@ -86,7 +86,7 @@
\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
@@ -104,7 +104,7 @@
\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$
@@ -113,7 +113,7 @@
\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
@@ -122,7 +122,7 @@
\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
@@ -131,7 +131,7 @@
\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
@@ -173,4 +173,4 @@
}
#endif
-#endif /* _AUBIO_FILTER_H */
+#endif /* AUBIO_FILTER_H */
--- a/src/temporal/resampler.c
+++ b/src/temporal/resampler.c
@@ -24,7 +24,7 @@
#include "fvec.h"
#include "temporal/resampler.h"
-#if HAVE_SAMPLERATE
+#ifdef HAVE_SAMPLERATE
#include <samplerate.h> /* from libsamplerate */
@@ -61,7 +61,7 @@
}
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;
@@ -92,7 +92,7 @@
}
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 */
--- a/src/temporal/resampler.h
+++ b/src/temporal/resampler.h
@@ -18,8 +18,8 @@
*/
-#ifndef _AUBIO_RESAMPLER_H
-#define _AUBIO_RESAMPLER_H
+#ifndef AUBIO_RESAMPLER_H
+#define AUBIO_RESAMPLER_H
/** \file
@@ -55,7 +55,7 @@
\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
@@ -62,4 +62,4 @@
}
#endif
-#endif /* _AUBIO_RESAMPLER_H */
+#endif /* AUBIO_RESAMPLER_H */
--- a/src/types.h
+++ b/src/types.h
@@ -18,8 +18,8 @@
*/
-#ifndef _AUBIO__TYPES_H
-#define _AUBIO__TYPES_H
+#ifndef AUBIO_TYPES_H
+#define AUBIO_TYPES_H
/** \file
@@ -67,4 +67,4 @@
}
#endif
-#endif /* _AUBIO__TYPES_H */
+#endif /* AUBIO_TYPES_H */
--- a/src/utils/hist.c
+++ b/src/utils/hist.c
@@ -137,7 +137,7 @@
}
}
-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++)
--- a/src/utils/hist.h
+++ b/src/utils/hist.h
@@ -25,8 +25,8 @@
* 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" {
@@ -50,7 +50,7 @@
/** 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 */
@@ -60,4 +60,4 @@
}
#endif
-#endif /* _AUBIO_HIST_H */
+#endif /* AUBIO_HIST_H */
--- a/src/utils/parameter.c
+++ b/src/utils/parameter.c
@@ -84,7 +84,7 @@
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;
}
@@ -109,7 +109,7 @@
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;
}
@@ -120,7 +120,7 @@
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;
}
@@ -131,7 +131,7 @@
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;
}
--- a/src/utils/parameter.h
+++ b/src/utils/parameter.h
@@ -18,8 +18,8 @@
*/
-#ifndef _AUBIO_PARAMETER_H
-#define _AUBIO_PARAMETER_H
+#ifndef AUBIO_PARAMETER_H
+#define AUBIO_PARAMETER_H
/** \file
@@ -76,7 +76,7 @@
\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
@@ -105,7 +105,7 @@
\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
@@ -124,7 +124,7 @@
\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
@@ -143,7 +143,7 @@
\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
@@ -156,4 +156,4 @@
}
#endif
-#endif /* _AUBIO_PARAMETER_H */
+#endif /* AUBIO_PARAMETER_H */
--- a/src/utils/scale.c
+++ b/src/utils/scale.c
@@ -37,7 +37,7 @@
*/
};
-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);
--- a/src/utils/scale.h
+++ b/src/utils/scale.h
@@ -28,8 +28,8 @@
\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" {
@@ -77,4 +77,4 @@
}
#endif
-#endif /* _AUBIO_SCALE_H */
+#endif /* AUBIO_SCALE_H */
--- /dev/null
+++ b/src/utils/windll.c
@@ -1,0 +1,59 @@
+/*
+ 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 "config.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
--- a/src/vecutils.h
+++ b/src/vecutils.h
@@ -24,8 +24,8 @@
*/
-#ifndef _AUBIO__VECUTILS_H
-#define _AUBIO__VECUTILS_H
+#ifndef AUBIO_VECUTILS_H
+#define AUBIO_VECUTILS_H
#ifdef __cplusplus
extern "C" {
@@ -113,4 +113,4 @@
}
#endif
-#endif /* _AUBIO__VECUTILS_H */
+#endif /* AUBIO_VECUTILS_H */
--- a/src/wscript_build
+++ b/src/wscript_build
@@ -1,6 +1,7 @@
# vim:set syntax=python:
uselib = []
+uselib += ['M']
uselib += ['FFTW3', 'FFTW3F']
uselib += ['SAMPLERATE']
uselib += ['SNDFILE']
@@ -8,14 +9,14 @@
uselib += ['AVFORMAT']
uselib += ['AVRESAMPLE']
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)
@@ -22,15 +23,15 @@
if ctx.env['DEST_OS'] in ['ios', 'iosimulator']:
build_features = ['cstlib', 'cshlib']
elif ctx.env['DEST_OS'] in ['win32', 'win64']:
- build_features = ['cshlib']
+ build_features = ['cstlib', 'cshlib']
+elif ctx.env['DEST_OS'] in ['emscripten']:
+ build_features = ['cstlib']
else: #linux, darwin, android, mingw, ...
- build_features = ['cshlib', 'cstlib']
+ build_features = ['cstlib', 'cshlib']
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'])
--- a/tests/src/io/test-source.c
+++ b/tests/src/io/test-source.c
@@ -33,6 +33,8 @@
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 {
@@ -41,8 +43,9 @@
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);
--- a/tests/src/io/test-source_apple_audio.c
+++ b/tests/src/io/test-source_apple_audio.c
@@ -38,6 +38,8 @@
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 {
@@ -46,8 +48,9 @@
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);
--- a/tests/src/io/test-source_avcodec.c
+++ b/tests/src/io/test-source_avcodec.c
@@ -38,6 +38,8 @@
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 {
@@ -46,8 +48,9 @@
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);
--- a/tests/src/io/test-source_sndfile.c
+++ b/tests/src/io/test-source_sndfile.c
@@ -38,6 +38,8 @@
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 {
@@ -46,8 +48,9 @@
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);
--- a/tests/src/io/test-source_wavread.c
+++ b/tests/src/io/test-source_wavread.c
@@ -35,9 +35,12 @@
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 {
@@ -46,8 +49,9 @@
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);
--- a/tests/src/tempo/test-tempo.c
+++ b/tests/src/tempo/test-tempo.c
@@ -27,7 +27,7 @@
// 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);
--- a/tests/src/temporal/test-a_weighting.c
+++ b/tests/src/temporal/test-a_weighting.c
@@ -20,16 +20,22 @@
// 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;
--- a/tests/src/temporal/test-c_weighting.c
+++ b/tests/src/temporal/test-c_weighting.c
@@ -19,16 +19,22 @@
// 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;
--- a/tests/src/test-lvec.c
+++ b/tests/src/test-lvec.c
@@ -6,7 +6,7 @@
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);
--- a/tests/utils_tests.h
+++ b/tests/utils_tests.h
@@ -5,12 +5,28 @@
#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
-#ifdef HAVE_WIN_HACKS
+#ifndef M_PI
+#define M_PI (3.14159265358979323846)
+#endif
+
+#ifndef RAND_MAX
+#define RAND_MAX 32767
+#endif
+
+// 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
--- a/tests/wscript_build
+++ b/tests/wscript_build
@@ -1,25 +1,16 @@
# 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']
- includes = ['../src', '.']
- extra_source = []
+uselib = ['aubio']
+includes = ['../src', '.']
+programs_sources = ctx.path.ant_glob('src/**/*.c')
+
+for source_file in programs_sources:
bld(features = 'c cprogram test',
- lib = 'm',
- uselib = uselib,
- source = [target_name] + extra_source,
- target = str(target_name).split('.')[0],
+ source = source_file,
+ target = str(source_file).split('.')[0],
includes = includes,
+ use = uselib,
install_path = None,
defines = 'AUBIO_UNSTABLE_API=1',
- cflags = ['-g'],
- use = 'aubio')
+ )
--- a/wscript
+++ b/wscript
@@ -81,7 +81,14 @@
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)',
+ help_disable_str = 'do not use Atlas library')
+ 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')
@@ -95,16 +102,28 @@
ctx.load('waf_unit_test')
ctx.load('gnu_dirs')
+ # 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='getopt.h', mandatory = False)
+ ctx.check(header_name='unistd.h', mandatory = False)
+
target_platform = Options.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]:
+ if ctx.env.CC_NAME != 'msvc':
ctx.env.CFLAGS += ['-g', '-Wall', '-Wextra']
else:
- ctx.env.CFLAGS += ['-Wall']
+ ctx.env.CFLAGS += ['/W4', '/MD']
+ ctx.env.CFLAGS += ['/D_CRT_SECURE_NO_WARNINGS']
+ ctx.check_cc(lib='m', uselib_store='M', mandatory=False)
+
if target_platform not in ['win32', 'win64']:
ctx.env.CFLAGS += ['-fPIC']
else:
@@ -114,6 +133,9 @@
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):
@@ -127,7 +149,7 @@
if target_platform in [ 'ios', 'iosimulator' ]:
MINSDKVER="6.1"
ctx.env.CFLAGS += ['-std=c99']
- if (ctx.options.enable_audio_unit != False):
+ if (ctx.options.enable_apple_audio != False):
ctx.define('HAVE_AUDIO_UNIT', 1)
#ctx.env.FRAMEWORK += ['CoreFoundation', 'AudioToolbox']
if target_platform == 'ios':
@@ -134,6 +156,7 @@
DEVROOT = "/Applications/Xcode.app/Contents"
DEVROOT += "/Developer/Platforms/iPhoneOS.platform/Developer"
SDKROOT = "%(DEVROOT)s/SDKs/iPhoneOS.sdk" % locals()
+ ctx.env.CFLAGS += [ '-fembed-bitcode' ]
ctx.env.CFLAGS += [ '-arch', 'arm64' ]
ctx.env.CFLAGS += [ '-arch', 'armv7' ]
ctx.env.CFLAGS += [ '-arch', 'armv7s' ]
@@ -155,12 +178,13 @@
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 = '''
@@ -174,15 +198,19 @@
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):
@@ -259,31 +287,43 @@
ctx.define('HAVE_WAVREAD', 1)
ctx.define('HAVE_WAVWRITE', 1)
+ # use ATLAS
+ if (ctx.options.enable_atlas != False):
+ ctx.check(header_name = 'atlas/cblas.h', mandatory = ctx.options.enable_atlas)
+ #ctx.check(lib = 'lapack', uselib_store = 'LAPACK', mandatory = ctx.options.enable_atlas)
+ ctx.check(lib = 'cblas', uselib_store = 'BLAS', mandatory = ctx.options.enable_atlas)
+
# 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
+
# 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)')
+
def build(bld):
bld.env['VERSION'] = VERSION
bld.env['LIB_VERSION'] = LIB_VERSION
@@ -290,8 +330,6 @@
# add sub directories
bld.recurse('src')
- if bld.env['DEST_OS'] not in ['ios', 'iosimulator']:
- pass
if bld.env['DEST_OS'] not in ['ios', 'iosimulator', 'android']:
bld.recurse('examples')
bld.recurse('tests')
@@ -339,9 +377,15 @@
ctx.excl = ' **/.waf-1* **/*~ **/*.pyc **/*.swp **/.lock-w* **/.git*'
ctx.excl += ' **/build/*'
ctx.excl += ' **/python/gen **/python/build **/python/dist'
+ ctx.excl += ' **/python/ext/config.h'
ctx.excl += ' **/**.zip **/**.tar.bz2'
ctx.excl += ' **/doc/full/* **/doc/web/*'
ctx.excl += ' **/python/*.db'
ctx.excl += ' **/python.old/*'
+ ctx.excl += ' **/python/*/*.old'
ctx.excl += ' **/python/tests/sounds'
ctx.excl += ' **/**.asc'
+ ctx.excl += ' **/.DS_Store'
+ ctx.excl += ' **/.travis.yml'
+ ctx.excl += ' **/dist*'
+ ctx.excl += ' **/appveyor.yml'