shithub: aubio

Download patch

ref: bfbfafa5cb3c42aa2eb201a5db3656a5232554ff
parent: 7b7a58e087d43e0586b52412034bc6fd87e60f71
parent: 25db68c4eefe354f18c58a47eeb5643fc534eb81
author: Paul Brossier <piem@piem.org>
date: Tue Oct 3 18:31:12 EDT 2017

Merge branch 'master' into dct

--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -7,27 +7,27 @@
 
     # pre-installed python version, see:
     # http://www.appveyor.com/docs/installed-software#python
-    - PYTHON: "C:\\Python27"
+    - PYTHONDIR: "C:\\Python27"
       PYTHON_VERSION: "2.7.x"
       PYTHON_ARCH: "32"
 
-    - PYTHON: "C:\\Python27-x64"
+    - PYTHONDIR: "C:\\Python27-x64"
       PYTHON_VERSION: "2.7.x"
       PYTHON_ARCH: "64"
 
-    - PYTHON: "C:\\Python34"
+    - PYTHONDIR: "C:\\Python34"
       PYTHON_VERSION: "3.4.x"
       PYTHON_ARCH: "32"
 
-    - PYTHON: "C:\\Python34-x64"
+    - PYTHONDIR: "C:\\Python34-x64"
       PYTHON_VERSION: "3.4.x"
       PYTHON_ARCH: "64"
 
-    - PYTHON: "C:\\Python35"
+    - PYTHONDIR: "C:\\Python35"
       PYTHON_VERSION: "3.5.x"
       PYTHON_ARCH: "32"
 
-    - PYTHON: "C:\\Python35-x64"
+    - PYTHONDIR: "C:\\Python35-x64"
       PYTHON_VERSION: "3.5.x"
       PYTHON_ARCH: "64"
       # add path required to run preprocessor step
@@ -39,20 +39,19 @@
   - 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)\""
+  - "%PYTHONDIR%\\python.exe --version"
+  - "%PYTHONDIR%\\python.exe -c \"import struct; print(struct.calcsize('P') * 8)\""
 
   # We need wheel installed to build wheels
-  - "%PYTHON%\\python.exe -m pip install wheel"
+  - "%PYTHONDIR%\\python.exe -m pip install wheel"
 
-  - "SET PATH=%PATH_EXTRAS%;%PYTHON%;%PYTHON%\\Scripts;%PATH%"
+  - "SET PATH=%PATH_EXTRAS%;%PYTHONDIR%;%PYTHONDIR%\\Scripts;%PATH%"
 
   - "pip install --disable-pip-version-check --user --upgrade pip"
   - "pip install --upgrade setuptools"
 
 before_build:
-  - curl -fsS -o waf https://waf.io/waf-1.8.22
-  - curl -fsS -o waf.bat https://raw.githubusercontent.com/waf-project/waf/master/utils/waf.bat
+  - "bash scripts/get_waf.sh"
 
 build_script:
   # build python module without using libaubio
@@ -62,8 +61,6 @@
   - "python python\\demos\\demo_create_test_sounds.py"
   - "nose2 --verbose"
   # clean up
-  - waf distclean
+  - "python waf distclean"
   # build libaubio
-  - waf configure build --verbose
-  # build python module using libaubio dll
-  - "python setup.py build"
+  - python waf configure build --verbose --msvc_version="msvc 14.0"
--- /dev/null
+++ b/.coveragerc
@@ -1,0 +1,3 @@
+[run]
+branch = True
+source = aubio
--- a/.travis.yml
+++ b/.travis.yml
@@ -81,6 +81,7 @@
     - libasound2-dev
     - libfftw3-dev
     - sox
+    - lcov
 
 before_install:
    - |
@@ -89,6 +90,7 @@
        brew install sox
        brew install ffmpeg
        brew install libsndfile
+       brew install lcov
        export PATH="$HOME/Library/Python/2.7/bin/:$PATH"
      fi;
 
@@ -97,6 +99,8 @@
   - travis_retry make getwaf expandwaf deps_python
   - which pip
   - pip --version
+  - pip install python-coveralls
+  - gem install coveralls-lcov
 
 script:
   - make create_test_sounds
@@ -103,10 +107,21 @@
   - |
     if [[ -z "$AUBIO_NOTESTS" ]]; then
       make test_lib_python_clean
-      make test_python_only_clean
+      make coverage
     else
       make test_lib_only_clean
     fi;
+
+after_success:
+  - |
+    if [[ -z "$AUBIO_NOTESTS" ]]; then
+      # upload lcov coverage to coveralls.io
+      coveralls-lcov build/coverage.info
+      # upload python coverage
+      #coveralls
+      # upload to codecov
+      bash <(curl -s https://codecov.io/bash)
+    fi
 
 notifications:
     irc:
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,70 @@
+2017-10-02 Paul Brossier <piem@aubio.org>
+
+	[ Overview ]
+
+	* VERSION: bump to 0.4.6
+	* src/spectral/fft.c, src/*.c: add support for Intel IPP (many thanks to
+	Eduard Mueller)
+	* wscript: add support for emscripten (thanks to Martin Hermant)
+	* src/pitch/pitchyinfast.h: new fast method to compute YIN algorithm
+	* src/pitch/pitchyin*.c: improve confidence measure, making sure its value
+	corresponds to the selected period (thanks to Eduard Mueller)
+	* python/lib/aubio/cmd.py: add `quiet`, `cut`, and `help` subcommands
+
+	[ Library ]
+
+	* src/aubio_priv.h: add missing aubio_vDSP_vclr (Eduard Mueller)
+	* src/io/source_avcodec.c: improve error message, prevent un-opened bracket,
+	no declaration after statements for older compilers, avoid unused variable
+	* src/mathutils.c: prevent segfault with Accelerate.framework (closes #58,
+	closes #102)
+	* src/spectral/phasevoc.h: add aubio_pvoc_set_window to change the windowing
+	function
+	* src/mathutils.c: add window type `ones` (no windowing)
+
+	[ Python ]
+
+	* python/demos/demo_tapthebeat.py: add a real-time example to play beats
+	using pyaudio
+	* python/lib/gen_external.py: improve parsing and syntax, use results in
+	emscripten build (Martin Hermant)
+	* python/lib/aubio/cmd.py: add option `-u` to `aubio pitch`, improve error
+	messages, add `quiet` subcommand (closes #124), improve syntax, add some
+	documentation, add `cut` and `help` subcommand, add silence and time format
+	options
+	* python/lib/aubio/cut.py: upgrade to argparse, set samplerate as needed
+	* python/demos/demo_yin_compare.py: add comparison of yin implementations
+	* python/demos/demo_wav2midi.py: add an example to create a midi from a
+	sound file using mido (closes: #134)
+	* python/demos/demo_bpm_extract.py: use argparse, use beats_to_bpm function
+	* python/ext/py-cvec.c: fix support for pypy by changing setters to return a
+	negative value on error (closes #17)
+
+	[ Documentation ]
+
+	* src/tempo/beattracking.h: fix typo (thanks to Hannes Fritz)
+	* doc/requirements.rst: fix broken link (thanks to @ssj71, closes #99)
+	* doc/aubiomfcc.txt: fix typo in 'coefficients'
+
+	[ Tests ]
+
+	* python/tests/tests_aubio_{cmd,cut}.py: add basic tests
+	* python/tests/test_filterbank*.py: ignore UserWarnings, clean-up,
+	improve get_coeff tests
+
+	[ Build system ]
+
+	* wscript: add support for emscripten, see scripts/build_emscripten
+	* scripts/get_waf.sh: update waf to 2.0.1, build waf from source tarball
+	* scripts/build_emscripten: update to build aubio.js
+	* Makefile: add coverage and coverage_report targets, run tests once
+
+	[ Continuous integration ]
+
+	* .travis.yml: add coverage report on osx
+	* .appveyor.yml: use msvc 14.0 (VS 2015) and scripts/get_waf.sh
+	* .coveragerc: add minimal python coverage configuration
+
 2017-04-10 Paul Brossier <piem@aubio.org>
 
 	[Overview]
--- a/Makefile
+++ b/Makefile
@@ -35,6 +35,9 @@
 DATAROOTDIR?=$(PREFIX)/share
 MANDIR?=$(DATAROOTDIR)/man
 
+# default nose2 command
+NOSE2?=nose2 -N 4 --verbose
+
 SOX=sox
 
 TESTSOUNDS := python/tests/sounds
@@ -135,9 +138,9 @@
 test_python: export PYTHONPATH=$(PYDESTDIR)/$(LIBDIR)
 test_python: local_dylib
 	# run test with installed package
-	./python/tests/run_all_tests --verbose
-	# also run with nose, multiple processes
-	nose2 -N 4
+	# ./python/tests/run_all_tests --verbose
+	# run with nose2, multiple processes
+	$(NOSE2)
 
 clean_python:
 	./setup.py clean
@@ -230,6 +233,27 @@
 test_python_only_clean: test_python_only \
 	uninstall_python \
 	check_clean_python
+
+coverage: export CFLAGS=--coverage
+coverage: export LDFLAGS=--coverage
+coverage: export PYTHONPATH=$(PWD)/python/lib
+coverage: export LD_LIBRARY_PATH=$(PWD)/build/src
+coverage: force_uninstall_python deps_python \
+	clean_python clean distclean build local_dylib
+	lcov --capture --no-external --directory . --output-file build/coverage_lib.info
+	pip install -v -e .
+	coverage run `which nose2`
+	lcov --capture --no-external --directory . --output-file build/coverage_python.info
+	lcov -a build/coverage_python.info -a build/coverage_lib.info -o build/coverage.info
+
+coverage_report: coverage
+	genhtml build/coverage.info --output-directory lcov_html
+	mkdir -p gcovr_html/
+	gcovr -r . --html --html-details \
+		--output gcovr_html/index.html \
+		--exclude ".*tests/.*" --exclude ".*examples/.*"
+	coverage report
+	coverage html
 
 sphinx: configure
 	$(WAFCMD) sphinx $(WAFOPTS)
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
 [![Travis build status](https://travis-ci.org/aubio/aubio.svg?branch=master)](https://travis-ci.org/aubio/aubio "Travis build status")
 [![Appveyor build status](https://img.shields.io/appveyor/ci/piem/aubio/master.svg)](https://ci.appveyor.com/project/piem/aubio "Appveyor build status")
 [![Landscape code health](https://landscape.io/github/aubio/aubio/master/landscape.svg?style=flat)](https://landscape.io/github/aubio/aubio/master "Landscape code health")
-[![Commits since last release](https://img.shields.io/github/commits-since/aubio/aubio/0.4.5.svg)](https://github.com/aubio/aubio "Commits since last release")
+[![Commits since last release](https://img.shields.io/github/commits-since/aubio/aubio/0.4.6.svg)](https://github.com/aubio/aubio "Commits since last release")
 
 [![Documentation](https://readthedocs.org/projects/aubio/badge/?version=latest)](http://aubio.readthedocs.io/en/latest/?badge=latest "Latest documentation")
 [![DOI](https://zenodo.org/badge/396389.svg)](https://zenodo.org/badge/latestdoi/396389)
--- a/VERSION
+++ b/VERSION
@@ -1,7 +1,7 @@
 AUBIO_MAJOR_VERSION=0
 AUBIO_MINOR_VERSION=4
-AUBIO_PATCH_VERSION=6
+AUBIO_PATCH_VERSION=7
 AUBIO_VERSION_STATUS='~alpha'
 LIBAUBIO_LT_CUR=5
-LIBAUBIO_LT_REV=2
-LIBAUBIO_LT_AGE=6
+LIBAUBIO_LT_REV=3
+LIBAUBIO_LT_AGE=7
--- a/doc/statuslinks.rst
+++ b/doc/statuslinks.rst
@@ -17,7 +17,7 @@
    :target: https://aubio.readthedocs.io/en/latest/?badge=latest
    :alt: Documentation status
 
-.. image:: https://img.shields.io/github/commits-since/aubio/aubio/0.4.5.svg?maxAge=2592000
+.. image:: https://img.shields.io/github/commits-since/aubio/aubio/0.4.6.svg?maxAge=2592000
    :target: https://github.com/aubio/aubio
    :alt: Commits since last release
 
--- a/python/ext/py-cvec.c
+++ b/python/ext/py-cvec.c
@@ -142,7 +142,7 @@
 {
   npy_intp length;
   if (!PyAubio_IsValidVector(input)) {
-    return 1;
+    return -1;
   }
   length = PyArray_SIZE ((PyArrayObject *)input);
   if (length != vec->length) {
@@ -149,7 +149,7 @@
     PyErr_Format (PyExc_ValueError,
         "input array has length %" NPY_INTP_FMT ", but cvec has length %d", length,
         vec->length);
-    return 1;
+    return -1;
   }
 
   Py_XDECREF(vec->norm);
@@ -163,7 +163,7 @@
 {
   npy_intp length;
   if (!PyAubio_IsValidVector(input)) {
-    return 1;
+    return -1;
   }
   length = PyArray_SIZE ((PyArrayObject *)input);
   if (length != vec->length) {
@@ -170,7 +170,7 @@
     PyErr_Format (PyExc_ValueError,
         "input array has length %" NPY_INTP_FMT ", but cvec has length %d", length,
         vec->length);
-    return 1;
+    return -1;
   }
 
   Py_XDECREF(vec->phas);
--- a/python/tests/test_aubio_cmd.py
+++ b/python/tests/test_aubio_cmd.py
@@ -10,7 +10,11 @@
         self.a_parser = aubio.cmd.aubio_parser()
 
     def test_default_creation(self):
-        assert self.a_parser.parse_args(['-V']).show_version
+        try:
+            assert self.a_parser.parse_args(['-V']).show_version
+        except SystemExit:
+            url = 'https://bugs.python.org/issue9253'
+            self.skipTest('subcommand became optional in py3, see %s' % url)
 
 class aubio_cmd_utils(TestCase):
 
--- a/scripts/build_emscripten
+++ b/scripts/build_emscripten
@@ -1,4 +1,4 @@
-#! /bin/sh
+#! /bin/bash
 
 function checkprog() {
   type $1 >/dev/null 2>&1 || { echo >&2 "$1 required but not found, aborting."; exit 1; }
@@ -9,13 +9,10 @@
 checkprog emmake
 
 # clean
-emmake ./waf distclean
+./waf distclean
 
 # configure
-emconfigure ./waf configure --prefix=$EMSCRIPTEN/system/local/ --with-target-platform emscripten
+emconfigure ./waf configure --with-target-platform emscripten $*
 
 # build
-emmake ./waf --testcmd="node %s"
-
-# intall
-#emmake ./waf install
+emmake ./waf build
--- a/scripts/build_mingw
+++ b/scripts/build_mingw
@@ -14,7 +14,7 @@
 VERSION=`python $PWD/this_version.py -v`
 
 FFMPEG_BUILDS_URL="https://ffmpeg.zeranoe.com/builds"
-FFMPEG_DEFAULT="20170404-1229007"
+FFMPEG_DEFAULT="3.3.3"
 
 # define some default CFLAGS
 DEF_CFLAGS="-Os -I/usr/share/mingw-w64"
@@ -80,10 +80,7 @@
     ./waf distclean configure build install $WAFOPTS_TGT --testcmd='echo %s'
   # fix dll location (see https://github.com/waf-project/waf/issues/1860)
   mv $DESTDIR/lib/libaubio-5.dll $DESTDIR/bin
-  # generate def file (see https://github.com/aubio/aubio/issues/97)
-  ( echo -e "EXPORTS"; $NM $DESTDIR/bin/libaubio-5.dll | grep T\  | \
-    egrep "(aubio|fvec|cvec|lvec|fmat)" | sed 's/^.* T _\?//' ) \
-    > $DESTDIR/bin/libaubio-5.def
+  mv $DESTDIR/lib/libaubio-5.def $DESTDIR/bin
   zip -r $DESTDIR.zip `basename $DESTDIR`
   rm -rf $DESTDIR
   sha256sum $DESTDIR.zip > $DESTDIR.zip.sha256
--- a/scripts/get_waf.sh
+++ b/scripts/get_waf.sh
@@ -1,10 +1,37 @@
-#! /bin/sh
+#! /bin/bash
 
 set -e
 set -x
 
-WAFURL=https://waf.io/waf-1.9.12
+WAFVERSION=2.0.1
+WAFTARBALL=waf-$WAFVERSION.tar.bz2
+WAFURL=https://waf.io/$WAFTARBALL
 
-( which wget > /dev/null && wget -qO waf $WAFURL ) || ( which curl > /dev/null && curl $WAFURL > waf )
+WAFBUILDDIR=`mktemp -d`
 
-chmod +x waf
+function cleanup () {
+  rm -rf $WAFBUILDDIR
+}
+
+trap cleanup SIGINT SIGTERM
+
+function buildwaf () {
+  pushd $WAFBUILDDIR
+
+  ( which wget > /dev/null && wget -qO $WAFTARBALL $WAFURL ) || ( which curl > /dev/null && curl $WAFURL > $WAFTARBALL )
+
+  tar xf $WAFTARBALL
+  pushd waf-$WAFVERSION
+  NOCLIMB=1 python waf-light --tools=c_emscripten $*
+
+  popd
+  popd
+
+  cp -prv $WAFBUILDDIR/waf-$WAFVERSION/waf $PWD
+
+  chmod +x waf
+}
+
+buildwaf
+
+cleanup
--- a/src/aubio_priv.h
+++ b/src/aubio_priv.h
@@ -93,6 +93,7 @@
 #define aubio_vDSP_minv       vDSP_minv
 #define aubio_vDSP_minvi      vDSP_minvi
 #define aubio_vDSP_dotpr      vDSP_dotpr
+#define aubio_vDSP_vclr       vDSP_vclr
 #else /* HAVE_AUBIO_DOUBLE */
 #define aubio_vDSP_mmov       vDSP_mmovD
 #define aubio_vDSP_vmul       vDSP_vmulD
@@ -104,6 +105,7 @@
 #define aubio_vDSP_minv       vDSP_minvD
 #define aubio_vDSP_minvi      vDSP_minviD
 #define aubio_vDSP_dotpr      vDSP_dotprD
+#define aubio_vDSP_vclr       vDSP_vclrD
 #endif /* HAVE_AUBIO_DOUBLE */
 #endif /* HAVE_ACCELERATE */
 
@@ -121,7 +123,38 @@
 #endif /* HAVE_AUBIO_DOUBLE */
 #endif /* HAVE_ATLAS */
 
-#if !defined(HAVE_MEMCPY_HACKS) && !defined(HAVE_ACCELERATE) && !defined(HAVE_ATLAS)
+#if defined HAVE_INTEL_IPP
+#include <ippcore.h>
+#include <ippvm.h>
+#include <ipps.h>
+#ifndef HAVE_AUBIO_DOUBLE
+#define aubio_ippsSet         ippsSet_32f
+#define aubio_ippsZero        ippsZero_32f
+#define aubio_ippsCopy        ippsCopy_32f
+#define aubio_ippsMul         ippsMul_32f
+#define aubio_ippsMulC        ippsMulC_32f
+#define aubio_ippsAddC        ippsAddC_32f
+#define aubio_ippsLn          ippsLn_32f_A21
+#define aubio_ippsMean(a,b,c) ippsMean_32f(a, b, c, ippAlgHintFast)
+#define aubio_ippsSum(a,b,c)  ippsSum_32f(a, b, c, ippAlgHintFast)
+#define aubio_ippsMax         ippsMax_32f
+#define aubio_ippsMin         ippsMin_32f
+#else /* HAVE_AUBIO_DOUBLE */
+#define aubio_ippsSet         ippsSet_64f
+#define aubio_ippsZero        ippsZero_64f
+#define aubio_ippsCopy        ippsCopy_64f
+#define aubio_ippsMul         ippsMul_64f
+#define aubio_ippsMulC        ippsMulC_64f
+#define aubio_ippsAddC        ippsAddC_64f
+#define aubio_ippsLn          ippsLn_64f_A26
+#define aubio_ippsMean        ippsMean_64f
+#define aubio_ippsSum         ippsSum_64f
+#define aubio_ippsMax         ippsMax_64f
+#define aubio_ippsMin         ippsMin_64f
+#endif /* HAVE_AUBIO_DOUBLE */
+#endif
+
+#if !defined(HAVE_MEMCPY_HACKS) && !defined(HAVE_ACCELERATE) && !defined(HAVE_ATLAS) && !defined(HAVE_INTEL_IPP)
 #define HAVE_NOOPT 1
 #else
 #undef HAVE_NOOPT
--- a/src/cvec.c
+++ b/src/cvec.c
@@ -85,31 +85,40 @@
         s->length, t->length);
     return;
   }
-#ifdef HAVE_MEMCPY_HACKS
+#if defined(HAVE_INTEL_IPP)
+  aubio_ippsCopy(s->phas, t->phas, (int)s->length);
+  aubio_ippsCopy(s->norm, t->norm, (int)s->length);
+#elif defined(HAVE_MEMCPY_HACKS)
   memcpy(t->norm, s->norm, t->length * sizeof(smpl_t));
   memcpy(t->phas, s->phas, t->length * sizeof(smpl_t));
-#else /* HAVE_MEMCPY_HACKS */
+#else
   uint_t j;
   for (j=0; j< t->length; j++) {
     t->norm[j] = s->norm[j];
     t->phas[j] = s->phas[j];
   }
-#endif /* HAVE_MEMCPY_HACKS */
+#endif
 }
 
-void cvec_norm_set_all (cvec_t *s, smpl_t val) {
+void cvec_norm_set_all(cvec_t *s, smpl_t val) {
+#if defined(HAVE_INTEL_IPP)
+  aubio_ippsSet(val, s->norm, (int)s->length);
+#else
   uint_t j;
   for (j=0; j< s->length; j++) {
     s->norm[j] = val;
   }
+#endif
 }
 
 void cvec_norm_zeros(cvec_t *s) {
-#ifdef HAVE_MEMCPY_HACKS
+#if defined(HAVE_INTEL_IPP)
+  aubio_ippsZero(s->norm, (int)s->length);
+#elif defined(HAVE_MEMCPY_HACKS)
   memset(s->norm, 0, s->length * sizeof(smpl_t));
-#else /* HAVE_MEMCPY_HACKS */
+#else
   cvec_norm_set_all (s, 0.);
-#endif /* HAVE_MEMCPY_HACKS */
+#endif
 }
 
 void cvec_norm_ones(cvec_t *s) {
@@ -117,14 +126,20 @@
 }
 
 void cvec_phas_set_all (cvec_t *s, smpl_t val) {
+#if defined(HAVE_INTEL_IPP)
+  aubio_ippsSet(val, s->phas, (int)s->length);
+#else
   uint_t j;
   for (j=0; j< s->length; j++) {
     s->phas[j] = val;
   }
+#endif
 }
 
 void cvec_phas_zeros(cvec_t *s) {
-#ifdef HAVE_MEMCPY_HACKS
+#if defined(HAVE_INTEL_IPP)
+  aubio_ippsZero(s->phas, (int)s->length);
+#elif defined(HAVE_MEMCPY_HACKS)
   memset(s->phas, 0, s->length * sizeof(smpl_t));
 #else
   cvec_phas_set_all (s, 0.);
@@ -141,8 +156,14 @@
 }
 
 void cvec_logmag(cvec_t *s, smpl_t lambda) {
+#if defined(HAVE_INTEL_IPP)
+  aubio_ippsMulC(s->norm, lambda, s->norm, (int)s->length);
+  aubio_ippsAddC(s->norm, 1.0, s->norm, (int)s->length);
+  aubio_ippsLn(s->norm, s->norm, (int)s->length);
+#else
   uint_t j;
   for (j=0; j< s->length; j++) {
     s->norm[j] = LOG(lambda * s->norm[j] + 1);
   }
+#endif
 }
--- a/src/fvec.c
+++ b/src/fvec.c
@@ -60,28 +60,31 @@
 }
 
 void fvec_set_all (fvec_t *s, smpl_t val) {
-#if !defined(HAVE_ACCELERATE) && !defined(HAVE_ATLAS)
-  uint_t j;
-  for (j=0; j< s->length; j++) {
-    s->data[j] = val;
-  }
+#if defined(HAVE_INTEL_IPP)
+  aubio_ippsSet(val, s->data, (int)s->length);
 #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);
+#else
+  uint_t j;
+  for ( j = 0; j< s->length; j++ )
+  {
+    s->data[j] = val;
+  }
 #endif
 }
 
 void fvec_zeros(fvec_t *s) {
-#if !defined(HAVE_MEMCPY_HACKS) && !defined(HAVE_ACCELERATE)
-  fvec_set_all (s, 0.);
-#else
-#if defined(HAVE_MEMCPY_HACKS)
+#if defined(HAVE_INTEL_IPP)
+  aubio_ippsZero(s->data, (int)s->length);
+#elif defined(HAVE_ACCELERATE)
+  aubio_vDSP_vclr(s->data, 1, s->length);
+#elif defined(HAVE_MEMCPY_HACKS)
   memset(s->data, 0, s->length * sizeof(smpl_t));
 #else
-  aubio_vDSP_vclr(s->data, 1, s->length);
+  fvec_set_all(s, 0.);
 #endif
-#endif
 }
 
 void fvec_ones(fvec_t *s) {
@@ -96,27 +99,31 @@
 }
 
 void fvec_weight(fvec_t *s, const fvec_t *weight) {
-#ifndef HAVE_ACCELERATE
-  uint_t j;
   uint_t length = MIN(s->length, weight->length);
-  for (j=0; j< length; j++) {
+#if defined(HAVE_INTEL_IPP)
+  aubio_ippsMul(s->data, weight->data, s->data, (int)length);
+#elif defined(HAVE_ACCELERATE)
+  aubio_vDSP_vmul( s->data, 1, weight->data, 1, s->data, 1, length );
+#else
+  uint_t j;
+  for (j = 0; j < length; j++) {
     s->data[j] *= weight->data[j];
   }
-#else
-  aubio_vDSP_vmul(s->data, 1, weight->data, 1, s->data, 1, s->length);
 #endif /* HAVE_ACCELERATE */
 }
 
 void fvec_weighted_copy(const fvec_t *in, const fvec_t *weight, fvec_t *out) {
-#ifndef HAVE_ACCELERATE
+  uint_t length = MIN(in->length, MIN(out->length, weight->length));
+#if defined(HAVE_INTEL_IPP)
+  aubio_ippsMul(in->data, weight->data, out->data, (int)length);
+#elif defined(HAVE_ACCELERATE)
+  aubio_vDSP_vmul(in->data, 1, weight->data, 1, out->data, 1, length);
+#else
   uint_t j;
-  uint_t length = MIN(out->length, weight->length);
-  for (j=0; j< length; j++) {
+  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 */
+#endif
 }
 
 void fvec_copy(const fvec_t *s, fvec_t *t) {
@@ -125,16 +132,18 @@
         s->length, t->length);
     return;
   }
-#ifdef HAVE_NOOPT
-  uint_t j;
-  for (j=0; j< t->length; j++) {
-    t->data[j] = s->data[j];
-  }
-#elif defined(HAVE_MEMCPY_HACKS)
-  memcpy(t->data, s->data, t->length * sizeof(smpl_t));
+#if defined(HAVE_INTEL_IPP)
+  aubio_ippsCopy(s->data, t->data, (int)s->length);
 #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);
+#elif defined(HAVE_MEMCPY_HACKS)
+  memcpy(t->data, s->data, t->length * sizeof(smpl_t));
+#else
+  uint_t j;
+  for (j = 0; j < t->length; j++) {
+    t->data[j] = s->data[j];
+  }
 #endif
 }
--- a/src/mathutils.c
+++ b/src/mathutils.c
@@ -159,16 +159,19 @@
 fvec_mean (fvec_t * s)
 {
   smpl_t tmp = 0.0;
-#ifndef HAVE_ACCELERATE
+#if defined(HAVE_INTEL_IPP)
+  aubio_ippsMean(s->data, (int)s->length, &tmp);
+  return tmp;
+#elif defined(HAVE_ACCELERATE)
+  aubio_vDSP_meanv(s->data, 1, &tmp, s->length);
+  return tmp;
+#else
   uint_t j;
   for (j = 0; j < s->length; j++) {
     tmp += s->data[j];
   }
-  return tmp / (smpl_t) (s->length);
-#else
-  aubio_vDSP_meanv(s->data, 1, &tmp, s->length);
-  return tmp;
-#endif /* HAVE_ACCELERATE */
+  return tmp / (smpl_t)(s->length);
+#endif
 }
 
 smpl_t
@@ -175,14 +178,16 @@
 fvec_sum (fvec_t * s)
 {
   smpl_t tmp = 0.0;
-#ifndef HAVE_ACCELERATE
+#if defined(HAVE_INTEL_IPP)
+  aubio_ippsSum(s->data, (int)s->length, &tmp);
+#elif defined(HAVE_ACCELERATE)
+  aubio_vDSP_sve(s->data, 1, &tmp, s->length);
+#else
   uint_t j;
   for (j = 0; j < s->length; j++) {
     tmp += s->data[j];
   }
-#else
-  aubio_vDSP_sve(s->data, 1, &tmp, s->length);
-#endif /* HAVE_ACCELERATE */
+#endif
   return tmp;
 }
 
@@ -189,15 +194,18 @@
 smpl_t
 fvec_max (fvec_t * s)
 {
-#ifndef HAVE_ACCELERATE
+#if defined(HAVE_INTEL_IPP)
+  smpl_t tmp = 0.;
+  aubio_ippsMax( s->data, (int)s->length, &tmp);
+#elif defined(HAVE_ACCELERATE)
+  smpl_t tmp = 0.;
+  aubio_vDSP_maxv( s->data, 1, &tmp, s->length );
+#else
   uint_t j;
-  smpl_t tmp = 0.0;
-  for (j = 0; j < s->length; j++) {
+  smpl_t tmp = s->data[0];
+  for (j = 1; j < s->length; j++) {
     tmp = (tmp > s->data[j]) ? tmp : s->data[j];
   }
-#else
-  smpl_t tmp = 0.;
-  aubio_vDSP_maxv(s->data, 1, &tmp, s->length);
 #endif
   return tmp;
 }
@@ -205,15 +213,18 @@
 smpl_t
 fvec_min (fvec_t * s)
 {
-#ifndef HAVE_ACCELERATE
+#if defined(HAVE_INTEL_IPP)
+  smpl_t tmp = 0.;
+  aubio_ippsMin(s->data, (int)s->length, &tmp);
+#elif defined(HAVE_ACCELERATE)
+  smpl_t tmp = 0.;
+  aubio_vDSP_minv(s->data, 1, &tmp, s->length);
+#else
   uint_t j;
   smpl_t tmp = s->data[0];
-  for (j = 0; j < s->length; j++) {
+  for (j = 1; j < s->length; j++) {
     tmp = (tmp < s->data[j]) ? tmp : s->data[j];
   }
-#else
-  smpl_t tmp = 0.;
-  aubio_vDSP_minv(s->data, 1, &tmp, s->length);
 #endif
   return tmp;
 }
@@ -572,6 +583,17 @@
   uint_t i = 1;
   while (i < a) i <<= 1;
   return i;
+}
+
+uint_t
+aubio_power_of_two_order (uint_t a)
+{
+  int order = 0;
+  int temp = aubio_next_power_of_two(a);
+  while (temp >>= 1) {
+    ++order;
+  }
+  return order;
 }
 
 smpl_t
--- a/src/mathutils.h
+++ b/src/mathutils.h
@@ -312,6 +312,9 @@
 /** return the next power of power of 2 greater than a */
 uint_t aubio_next_power_of_two(uint_t a);
 
+/** return the log2 factor of the given power of 2 value a */
+uint_t aubio_power_of_two_order(uint_t a);
+
 /** compute normalised autocorrelation function
 
   \param input vector to compute autocorrelation from
--- a/src/pitch/pitchyin.c
+++ b/src/pitch/pitchyin.c
@@ -36,7 +36,7 @@
 {
   fvec_t *yin;
   smpl_t tol;
-  smpl_t confidence;
+  uint_t peak_pos;
 };
 
 /** compute difference function
@@ -67,6 +67,7 @@
   aubio_pitchyin_t *o = AUBIO_NEW (aubio_pitchyin_t);
   o->yin = new_fvec (bufsize / 2);
   o->tol = 0.15;
+  o->peak_pos = 0;
   return o;
 }
 
@@ -156,19 +157,18 @@
     period = tau - 3;
     if (tau > 4 && (yin_data[period] < tol) &&
         (yin_data[period] < yin_data[period + 1])) {
-      out->data[0] = fvec_quadratic_peak_pos (yin, period);
-      goto beach;
+      o->peak_pos = (uint_t)period;
+      out->data[0] = fvec_quadratic_peak_pos (yin, o->peak_pos);
+      return;
     }
   }
-  out->data[0] = fvec_quadratic_peak_pos (yin, fvec_min_elem (yin));
-beach:
-  return;
+  o->peak_pos = (uint_t)fvec_min_elem (yin);
+  out->data[0] = fvec_quadratic_peak_pos (yin, o->peak_pos);
 }
 
 smpl_t
 aubio_pitchyin_get_confidence (aubio_pitchyin_t * o) {
-  o->confidence = 1. - fvec_min (o->yin);
-  return o->confidence;
+  return 1. - o->yin->data[o->peak_pos];
 }
 
 uint_t
--- a/src/pitch/pitchyinfast.c
+++ b/src/pitch/pitchyinfast.c
@@ -38,7 +38,7 @@
 {
   fvec_t *yin;
   smpl_t tol;
-  smpl_t confidence;
+  uint_t peak_pos;
   fvec_t *tmpdata;
   fvec_t *sqdiff;
   fvec_t *kernel;
@@ -59,6 +59,7 @@
   o->kernel_fft = new_fvec (bufsize);
   o->fft = new_aubio_fft (bufsize);
   o->tol = 0.15;
+  o->peak_pos = 0;
   return o;
 }
 
@@ -85,7 +86,6 @@
   uint_t B = o->tmpdata->length;
   uint_t W = o->yin->length; // B / 2
   fvec_t tmp_slice, kernel_ptr;
-  smpl_t *yin_data = yin->data;
   uint_t tau;
   sint_t period;
   smpl_t tmp2 = 0.;
@@ -142,15 +142,15 @@
     aubio_fft_rdo_complex(o->fft, compmul, rt_of_tau);
     // compute square difference r_t(tau) = sqdiff - 2 * r_t_tau[W-1:-1]
     for (tau = 0; tau < W; tau++) {
-      yin_data[tau] = o->sqdiff->data[tau] - 2. * rt_of_tau->data[tau+W];
+      yin->data[tau] = o->sqdiff->data[tau] - 2. * rt_of_tau->data[tau+W];
     }
   }
 
   // now build yin and look for first minimum
-  fvec_set_all(out, 0.);
-  yin_data[0] = 1.;
+  fvec_zeros(out);
+  yin->data[0] = 1.;
   for (tau = 1; tau < length; tau++) {
-    tmp2 += yin_data[tau];
+    tmp2 += yin->data[tau];
     if (tmp2 != 0) {
       yin->data[tau] *= tau / tmp2;
     } else {
@@ -157,21 +157,21 @@
       yin->data[tau] = 1.;
     }
     period = tau - 3;
-    if (tau > 4 && (yin_data[period] < tol) &&
-        (yin_data[period] < yin_data[period + 1])) {
-      out->data[0] = fvec_quadratic_peak_pos (yin, period);
-      goto beach;
+    if (tau > 4 && (yin->data[period] < tol) &&
+        (yin->data[period] < yin->data[period + 1])) {
+      o->peak_pos = (uint_t)period;
+      out->data[0] = fvec_quadratic_peak_pos (yin, o->peak_pos);
+      return;
     }
   }
-  out->data[0] = fvec_quadratic_peak_pos (yin, fvec_min_elem (yin) );
-beach:
-  return;
+  // use global minimum 
+  o->peak_pos = (uint_t)fvec_min_elem (yin);
+  out->data[0] = fvec_quadratic_peak_pos (yin, o->peak_pos);
 }
 
 smpl_t
 aubio_pitchyinfast_get_confidence (aubio_pitchyinfast_t * o) {
-  o->confidence = 1. - fvec_min (o->yin);
-  return o->confidence;
+  return 1. - o->yin->data[o->peak_pos];
 }
 
 uint_t
--- a/src/pitch/pitchyinfft.c
+++ b/src/pitch/pitchyinfft.c
@@ -36,7 +36,7 @@
   aubio_fft_t *fft;   /**< fft object to compute square difference function */
   fvec_t *yinfft;     /**< Yin function */
   smpl_t tol;         /**< Yin tolerance */
-  smpl_t confidence;  /**< confidence */
+  uint_t peak_pos;    /**< currently selected peak pos*/
   uint_t short_period; /** shortest period under which to check for octave error */
 };
 
@@ -67,6 +67,7 @@
   p->sqrmag = new_fvec (bufsize);
   p->yinfft = new_fvec (bufsize / 2 + 1);
   p->tol = 0.85;
+  p->peak_pos = 0;
   p->win = new_aubio_window ("hanningz", bufsize);
   p->weight = new_fvec (bufsize / 2 + 1);
   for (i = 0; i < p->weight->length; i++) {
@@ -161,11 +162,13 @@
       /* should compare the minimum value of each interpolated peaks */
       halfperiod = FLOOR (tau / 2 + .5);
       if (yin->data[halfperiod] < p->tol)
-        output->data[0] = fvec_quadratic_peak_pos (yin, halfperiod);
+        p->peak_pos = halfperiod;
       else
-        output->data[0] = fvec_quadratic_peak_pos (yin, tau);
+        p->peak_pos = tau;
+      output->data[0] = fvec_quadratic_peak_pos (yin, p->peak_pos);
     }
   } else {
+    p->peak_pos = 0;
     output->data[0] = 0.;
   }
 }
@@ -185,8 +188,7 @@
 
 smpl_t
 aubio_pitchyinfft_get_confidence (aubio_pitchyinfft_t * o) {
-  o->confidence = 1. - fvec_min (o->yinfft);
-  return o->confidence;
+  return 1. - o->yinfft->data[o->peak_pos];
 }
 
 uint_t
--- a/src/spectral/fft.c
+++ b/src/spectral/fft.c
@@ -77,8 +77,7 @@
 // a global mutex for FFTW thread safety
 pthread_mutex_t aubio_fftw_mutex = PTHREAD_MUTEX_INITIALIZER;
 
-#else
-#ifdef HAVE_ACCELERATE        // using ACCELERATE
+#elif defined HAVE_ACCELERATE        // using ACCELERATE
 // https://developer.apple.com/library/mac/#documentation/Accelerate/Reference/vDSPRef/Reference/reference.html
 #include <Accelerate/Accelerate.h>
 
@@ -112,32 +111,65 @@
 #define aubio_vvsqrt                   vvsqrt
 #endif /* HAVE_AUBIO_DOUBLE */
 
-#else                         // using OOURA
+#elif defined HAVE_INTEL_IPP // using INTEL IPP
+
+#if !HAVE_AUBIO_DOUBLE
+#define aubio_IppFloat                 Ipp32f
+#define aubio_IppComplex               Ipp32fc
+#define aubio_FFTSpec                  FFTSpec_R_32f
+#define aubio_ippsMalloc_complex       ippsMalloc_32fc
+#define aubio_ippsFFTInit_R            ippsFFTInit_R_32f
+#define aubio_ippsFFTGetSize_R         ippsFFTGetSize_R_32f
+#define aubio_ippsFFTInv_CCSToR        ippsFFTInv_CCSToR_32f
+#define aubio_ippsFFTFwd_RToCCS        ippsFFTFwd_RToCCS_32f
+#define aubio_ippsAtan2                ippsAtan2_32f_A21
+#else /* HAVE_AUBIO_DOUBLE */
+#define aubio_IppFloat                 Ipp64f
+#define aubio_IppComplex               Ipp64fc
+#define aubio_FFTSpec                  FFTSpec_R_64f
+#define aubio_ippsMalloc_complex       ippsMalloc_64fc
+#define aubio_ippsFFTInit_R            ippsFFTInit_R_64f
+#define aubio_ippsFFTGetSize_R         ippsFFTGetSize_R_64f
+#define aubio_ippsFFTInv_CCSToR        ippsFFTInv_CCSToR_64f
+#define aubio_ippsFFTFwd_RToCCS        ippsFFTFwd_RToCCS_64f
+#define aubio_ippsAtan2                ippsAtan2_64f_A50
+#endif
+
+
+#else // using OOURA
 // let's use ooura instead
 extern void aubio_ooura_rdft(int, int, smpl_t *, int *, smpl_t *);
 
-#endif /* HAVE_ACCELERATE */
-#endif /* HAVE_FFTW3 */
+#endif
 
 struct _aubio_fft_t {
   uint_t winsize;
   uint_t fft_size;
+
 #ifdef HAVE_FFTW3             // using FFTW3
   real_t *in, *out;
   fftw_plan pfw, pbw;
-  fft_data_t * specdata;      /* complex spectral data */
-#else
-#ifdef HAVE_ACCELERATE        // using ACCELERATE
+  fft_data_t * specdata; /* complex spectral data */
+
+#elif defined HAVE_ACCELERATE  // using ACCELERATE
   int log2fftsize;
   aubio_FFTSetup fftSetup;
   aubio_DSPSplitComplex spec;
   smpl_t *in, *out;
+
+#elif defined HAVE_INTEL_IPP  // using Intel IPP
+  smpl_t *in, *out;
+  Ipp8u* memSpec;
+  Ipp8u* memInit;
+  Ipp8u* memBuffer;
+  struct aubio_FFTSpec* fftSpec;
+  aubio_IppComplex* complexOut;
 #else                         // using OOURA
   smpl_t *in, *out;
   smpl_t *w;
   int *ip;
-#endif /* HAVE_ACCELERATE */
-#endif /* HAVE_FFTW3 */
+#endif /* using OOURA */
+
   fvec_t * compspec;
 };
 
@@ -147,6 +179,7 @@
     AUBIO_ERR("fft: got winsize %d, but can not be < 2\n", winsize);
     goto beach;
   }
+
 #ifdef HAVE_FFTW3
   uint_t i;
   s->winsize  = winsize;
@@ -175,17 +208,55 @@
   for (i = 0; i < s->fft_size; i++) {
     s->specdata[i] = 0.;
   }
-#else
-#ifdef HAVE_ACCELERATE        // using ACCELERATE
+
+#elif defined HAVE_ACCELERATE  // using ACCELERATE
   s->winsize = winsize;
   s->fft_size = winsize;
   s->compspec = new_fvec(winsize);
-  s->log2fftsize = (uint_t)log2f(s->fft_size);
+  s->log2fftsize = aubio_power_of_two_order(s->fft_size);
   s->in = AUBIO_ARRAY(smpl_t, s->fft_size);
   s->out = AUBIO_ARRAY(smpl_t, s->fft_size);
   s->spec.realp = AUBIO_ARRAY(smpl_t, s->fft_size/2);
   s->spec.imagp = AUBIO_ARRAY(smpl_t, s->fft_size/2);
   s->fftSetup = aubio_vDSP_create_fftsetup(s->log2fftsize, FFT_RADIX2);
+
+#elif defined HAVE_INTEL_IPP  // using Intel IPP
+  const IppHintAlgorithm qualityHint = ippAlgHintAccurate; // OR ippAlgHintFast;
+  const int flags = IPP_FFT_NODIV_BY_ANY; // we're scaling manually afterwards
+  int order = aubio_power_of_two_order(winsize);
+  int sizeSpec, sizeInit, sizeBuffer;
+  IppStatus status;
+
+  if (winsize <= 4 || aubio_is_power_of_two(winsize) != 1)
+  {
+    AUBIO_ERR("intel IPP fft: can only create with sizes > 4 and power of two, requested %d,"
+      " try recompiling aubio with --enable-fftw3\n", winsize);
+    goto beach;
+  }
+
+  status = aubio_ippsFFTGetSize_R(order, flags, qualityHint,
+      &sizeSpec, &sizeInit, &sizeBuffer);
+  if (status != ippStsNoErr) {
+    AUBIO_ERR("fft: failed to initialize fft. IPP error: %d\n", status);
+    goto beach;
+  }
+  s->fft_size = s->winsize = winsize;
+  s->compspec = new_fvec(winsize);
+  s->in = AUBIO_ARRAY(smpl_t, s->winsize);
+  s->out = AUBIO_ARRAY(smpl_t, s->winsize);
+  s->memSpec = ippsMalloc_8u(sizeSpec);
+  s->memBuffer = ippsMalloc_8u(sizeBuffer);
+  if (sizeInit > 0 ) {
+    s->memInit = ippsMalloc_8u(sizeInit);
+  }
+  s->complexOut = aubio_ippsMalloc_complex(s->fft_size / 2 + 1);
+  status = aubio_ippsFFTInit_R(
+    &s->fftSpec, order, flags, qualityHint, s->memSpec, s->memInit);
+  if (status != ippStsNoErr) {
+    AUBIO_ERR("fft: failed to initialize. IPP error: %d\n", status);
+    goto beach;
+  }
+
 #else                         // using OOURA
   if (aubio_is_power_of_two(winsize) != 1) {
     AUBIO_ERR("fft: can only create with sizes power of two, requested %d,"
@@ -200,9 +271,10 @@
   s->ip    = AUBIO_ARRAY(int   , s->fft_size);
   s->w     = AUBIO_ARRAY(smpl_t, s->fft_size);
   s->ip[0] = 0;
-#endif /* HAVE_ACCELERATE */
-#endif /* HAVE_FFTW3 */
+#endif /* using OOURA */
+
   return s;
+
 beach:
   AUBIO_FREE(s);
   return NULL;
@@ -210,7 +282,6 @@
 
 void del_aubio_fft(aubio_fft_t * s) {
   /* destroy data */
-  del_fvec(s->compspec);
 #ifdef HAVE_FFTW3             // using FFTW3
   pthread_mutex_lock(&aubio_fftw_mutex);
   fftw_destroy_plan(s->pfw);
@@ -217,18 +288,26 @@
   fftw_destroy_plan(s->pbw);
   fftw_free(s->specdata);
   pthread_mutex_unlock(&aubio_fftw_mutex);
-#else /* HAVE_FFTW3 */
-#ifdef HAVE_ACCELERATE        // using ACCELERATE
+
+#elif defined HAVE_ACCELERATE // using ACCELERATE
   AUBIO_FREE(s->spec.realp);
   AUBIO_FREE(s->spec.imagp);
   aubio_vDSP_destroy_fftsetup(s->fftSetup);
+
+#elif defined HAVE_INTEL_IPP  // using Intel IPP
+  ippFree(s->memSpec);
+  ippFree(s->memInit);
+  ippFree(s->memBuffer);
+  ippFree(s->complexOut);
+
 #else                         // using OOURA
   AUBIO_FREE(s->w);
   AUBIO_FREE(s->ip);
-#endif /* HAVE_ACCELERATE */
-#endif /* HAVE_FFTW3 */
-  AUBIO_FREE(s->out);
+#endif
+
+  del_fvec(s->compspec);
   AUBIO_FREE(s->in);
+  AUBIO_FREE(s->out);
   AUBIO_FREE(s);
 }
 
@@ -251,6 +330,7 @@
 #else
   memcpy(s->in, input->data, s->winsize * sizeof(smpl_t));
 #endif /* HAVE_MEMCPY_HACKS */
+
 #ifdef HAVE_FFTW3             // using FFTW3
   fftw_execute(s->pfw);
 #ifdef HAVE_COMPLEX_H
@@ -265,8 +345,8 @@
     compspec->data[i] = s->specdata[i];
   }
 #endif /* HAVE_COMPLEX_H */
-#else /* HAVE_FFTW3 */
-#ifdef HAVE_ACCELERATE        // using ACCELERATE
+
+#elif defined HAVE_ACCELERATE // using ACCELERATE
   // convert real data to even/odd format used in vDSP
   aubio_vDSP_ctoz((aubio_DSPComplex*)s->in, 2, &s->spec, 1, s->fft_size/2);
   // compute the FFT
@@ -281,6 +361,19 @@
   // apply scaling
   smpl_t scale = 1./2.;
   aubio_vDSP_vsmul(compspec->data, 1, &scale, compspec->data, 1, s->fft_size);
+
+#elif defined HAVE_INTEL_IPP  // using Intel IPP
+
+  // apply fft
+  aubio_ippsFFTFwd_RToCCS(s->in, (aubio_IppFloat*)s->complexOut, s->fftSpec, s->memBuffer);
+  // convert complex buffer to [ r0, r1, ..., rN, iN-1, .., i2, i1]
+  compspec->data[0] = s->complexOut[0].re;
+  compspec->data[s->fft_size / 2] = s->complexOut[s->fft_size / 2].re;
+  for (i = 1; i < s->fft_size / 2; i++) {
+    compspec->data[i] = s->complexOut[i].re;
+    compspec->data[s->fft_size - i] = s->complexOut[i].im;
+  }
+
 #else                         // using OOURA
   aubio_ooura_rdft(s->winsize, 1, s->in, s->ip, s->w);
   compspec->data[0] = s->in[0];
@@ -289,8 +382,7 @@
     compspec->data[i] = s->in[2 * i];
     compspec->data[s->winsize - i] = - s->in[2 * i + 1];
   }
-#endif /* HAVE_ACCELERATE */
-#endif /* HAVE_FFTW3 */
+#endif /* using OOURA */
 }
 
 void aubio_fft_rdo_complex(aubio_fft_t * s, const fvec_t * compspec, fvec_t * output) {
@@ -313,8 +405,8 @@
   for (i = 0; i < output->length; i++) {
     output->data[i] = s->out[i]*renorm;
   }
-#else /* HAVE_FFTW3 */
-#ifdef HAVE_ACCELERATE        // using ACCELERATE
+
+#elif defined HAVE_ACCELERATE // using ACCELERATE
   // convert from real imag  [ r0, r1, ..., rN, iN-1, .., i2, i1]
   // to vDSP packed format   [ r0, rN, r1, i1, ..., rN-1, iN-1 ]
   s->out[0] = compspec->data[0];
@@ -332,6 +424,23 @@
   // apply scaling
   smpl_t scale = 1.0 / s->winsize;
   aubio_vDSP_vsmul(output->data, 1, &scale, output->data, 1, s->fft_size);
+
+#elif defined HAVE_INTEL_IPP  // using Intel IPP
+
+  // convert from real imag  [ r0, 0, ..., rN, iN-1, .., i2, i1, iN-1] to complex format
+  s->complexOut[0].re = compspec->data[0];
+  s->complexOut[0].im = 0;
+  s->complexOut[s->fft_size / 2].re = compspec->data[s->fft_size / 2];
+  s->complexOut[s->fft_size / 2].im = 0.0;
+  for (i = 1; i < s->fft_size / 2; i++) {
+    s->complexOut[i].re = compspec->data[i];
+    s->complexOut[i].im = compspec->data[s->fft_size - i];
+  }
+  // apply fft
+  aubio_ippsFFTInv_CCSToR((const aubio_IppFloat *)s->complexOut, output->data, s->fftSpec, s->memBuffer);
+  // apply scaling
+  aubio_ippsMulC(output->data, 1.0 / s->winsize, output->data, s->fft_size);
+
 #else                         // using OOURA
   smpl_t scale = 2.0 / s->winsize;
   s->out[0] = compspec->data[0];
@@ -344,8 +453,7 @@
   for (i=0; i < s->winsize; i++) {
     output->data[i] = s->out[i] * scale;
   }
-#endif /* HAVE_ACCELERATE */
-#endif /* HAVE_FFTW3 */
+#endif
 }
 
 void aubio_fft_get_spectrum(const fvec_t * compspec, cvec_t * spectrum) {
@@ -365,10 +473,26 @@
   } else {
     spectrum->phas[0] = 0.;
   }
+#if defined(HAVE_INTEL_IPP)
+  // convert from real imag  [ r0, r1, ..., rN, iN-1, ..., i2, i1, i0]
+  //                     to  [ r0, r1, ..., rN, i0, i1, i2, ..., iN-1]
+  for (i = 1; i < spectrum->length / 2; i++) {
+    ELEM_SWAP(compspec->data[compspec->length - i],
+        compspec->data[spectrum->length + i - 1]);
+  }
+  aubio_ippsAtan2(compspec->data + spectrum->length,
+      compspec->data + 1, spectrum->phas + 1, spectrum->length - 1);
+  // revert the imaginary part back again
+  for (i = 1; i < spectrum->length / 2; i++) {
+    ELEM_SWAP(compspec->data[spectrum->length + i - 1],
+        compspec->data[compspec->length - i]);
+  }
+#else
   for (i=1; i < spectrum->length - 1; i++) {
     spectrum->phas[i] = ATAN2(compspec->data[compspec->length-i],
         compspec->data[i]);
   }
+#endif
   if (compspec->data[compspec->length/2] < 0) {
     spectrum->phas[spectrum->length - 1] = PI;
   } else {
--- a/src/wscript_build
+++ b/src/wscript_build
@@ -3,6 +3,7 @@
 uselib = []
 uselib += ['M']
 uselib += ['FFTW3', 'FFTW3F']
+uselib += ['INTEL_IPP']
 uselib += ['SAMPLERATE']
 uselib += ['SNDFILE']
 uselib += ['AVCODEC']
@@ -24,7 +25,7 @@
 if ctx.env['DEST_OS'] in ['ios', 'iosimulator']:
     build_features = ['cstlib', 'cshlib']
 elif ctx.env['DEST_OS'] in ['win32', 'win64']:
-    build_features = ['cstlib', 'cshlib']
+    build_features = ['cstlib', 'cshlib gensyms']
 elif ctx.env['DEST_OS'] in ['emscripten']:
     build_features = ['cstlib','cshlib']
 elif '--static' in ctx.env['LDFLAGS'] or '--static' in ctx.env['LINKFLAGS']:
@@ -36,13 +37,13 @@
 
 # also install static lib
 from waflib.Tools.c import cstlib
-from waflib.Tools.fc import fcstlib
-fcstlib.inst_to = cstlib.inst_to = '${LIBDIR}'
+cstlib.inst_to = '${LIBDIR}'
 
 for target in build_features:
     ctx(features = 'c ' + target,
             use = uselib + ['lib_objects'],
             target = 'aubio',
+            export_symbols_regex=r'(?:.*aubio|fvec|lvec|cvec|fmat|new|del)_.*',
             vnum = ctx.env['LIB_VERSION'])
 
 # install headers, except _priv.h ones
--- a/tests/src/io/test-sink-multi.c
+++ b/tests/src/io/test-sink-multi.c
@@ -1,9 +1,8 @@
-#define AUBIO_UNSTABLE 1
 #include <aubio.h>
 #include "utils_tests.h"
 
-// this file uses the unstable aubio api, please use aubio_sink instead
-// see src/io/sink.h and tests/src/sink/test-sink.c
+// same as test-sink.c, but uses aubio_source_do_multi to read multiple
+// channels
 
 int main (int argc, char **argv)
 {
--- a/tests/src/io/test-sink_apple_audio-multi.c
+++ b/tests/src/io/test-sink_apple_audio-multi.c
@@ -2,8 +2,8 @@
 #include <aubio.h>
 #include "utils_tests.h"
 
-// this file uses the unstable aubio api, please use aubio_sink instead
-// see src/io/sink.h and tests/src/sink/test-sink.c
+// this file uses the unstable aubio api to test aubio_sink_apple_audio, please
+// use aubio_sink instead see src/io/sink.h and tests/src/sink/test-sink.c
 
 int main (int argc, char **argv)
 {
--- a/tests/src/io/test-sink_sndfile-multi.c
+++ b/tests/src/io/test-sink_sndfile-multi.c
@@ -2,8 +2,8 @@
 #include <aubio.h>
 #include "utils_tests.h"
 
-// this file uses the unstable aubio api, please use aubio_sink instead
-// see src/io/sink.h and tests/src/sink/test-sink.c
+// this file uses the unstable aubio api to test aubio_sink_sndfile, please
+// use aubio_sink instead see src/io/sink.h and tests/src/sink/test-sink.c
 
 int main (int argc, char **argv)
 {
--- a/tests/src/io/test-sink_wavwrite-multi.c
+++ b/tests/src/io/test-sink_wavwrite-multi.c
@@ -2,8 +2,8 @@
 #include <aubio.h>
 #include "utils_tests.h"
 
-// this file uses the unstable aubio api, please use aubio_sink instead
-// see src/io/sink.h and tests/src/sink/test-sink.c
+// this file uses the unstable aubio api to test aubio_sink_wavwrite, please
+// use aubio_sink instead see src/io/sink.h and tests/src/sink/test-sink.c
 
 int main (int argc, char **argv)
 {
--- /dev/null
+++ b/waf_gensyms.py
@@ -1,0 +1,40 @@
+import re
+import os.path
+from waflib import TaskGen, Task
+from waflib.Context import STDOUT
+from waflib.Utils import O644
+
+class gen_sym_file(Task.Task):
+    color = 'BLUE'
+    inst_to = '${LIBDIR}'
+    def run(self):
+        syms = {}
+        reg = getattr(self.generator, 'export_symbols_regex','.+?')
+        if 'msvc' in self.env.CC_NAME:
+            outputs = [x.abspath() for x in self.generator.link_task.outputs]
+            binary_path = list(filter(lambda x: x.endswith('lib'), outputs))[0]
+            reg_compiled = re.compile(r'External\s+\|\s+(?P<symbol>%s)\b' % reg)
+            cmd =(self.env.LINK_CC) + ['/dump', '/symbols', binary_path]
+        else: # using gcc? assume we have nm
+            outputs = [x.abspath() for x in self.generator.link_task.outputs]
+            binary_path = list(filter(lambda x: x.endswith('dll'), outputs))[0]
+            reg_compiled = re.compile(r'(T|D)\s+_(?P<symbol>%s)\b'%reg)
+            cmd = (self.env.NM or ['nm']) + ['-g', binary_path]
+        dump_output = self.generator.bld.cmd_and_log(cmd, quiet=STDOUT)
+        syms = set([])
+        for m in reg_compiled.finditer(dump_output):
+            syms.add(m.group('symbol'))
+        syms = list(syms)
+        syms.sort()
+        self.outputs[0].write('EXPORTS\n'+'\n'.join(syms))
+
+@TaskGen.feature('gensyms')
+@TaskGen.after_method('process_source','process_use','apply_link','process_uselib_local','propagate_uselib_vars')
+def gen_symbols(self):
+    #sym_file = self.path.find_or_declare(self.target + '.def')
+    sym_file_name = os.path.splitext(self.link_task.outputs[0].abspath())[0] + '.def'
+    sym_file = self.path.find_or_declare(sym_file_name)
+    symtask = self.create_task('gen_sym_file', self.link_task.outputs, sym_file)
+    self.add_install_files(install_to=self.link_task.inst_to, install_from=sym_file,
+        chmod=O644, task=self.link_task)
+
--- a/wscript
+++ b/wscript
@@ -50,6 +50,9 @@
     add_option_enable_disable(ctx, 'fftw3', default = False,
             help_str = 'compile with fftw3 instead of ooura',
             help_disable_str = 'do not compile with fftw3')
+    add_option_enable_disable(ctx, 'intelipp', default = False,
+            help_str = 'use Intel IPP libraries (auto)',
+            help_disable_str = 'do not use Intel IPP libraries')
     add_option_enable_disable(ctx, 'complex', default = False,
             help_str ='compile with C99 complex',
             help_disable_str = 'do not use C99 complex (default)' )
@@ -100,25 +103,24 @@
     ctx.load('compiler_c')
     ctx.load('waf_unit_test')
     ctx.load('gnu_dirs')
+    ctx.load('waf_gensyms', tooldir='.')
 
 def configure(ctx):
-    from waflib import Options
-    ctx.load('compiler_c')
-    ctx.load('waf_unit_test')
-    ctx.load('gnu_dirs')
-
     target_platform = sys.platform
     if ctx.options.target_platform:
         target_platform = ctx.options.target_platform
 
+    from waflib import Options
 
     if target_platform=='emscripten':
-        # need to force spaces between flag -o and path 
-        # inspired from :
-        # https://github.com/waf-project/waf/blob/master/waflib/extras/c_emscripten.py (#1885)
-        # (OSX /emscripten 1.37.9)
-        ctx.env.CC_TGT_F            = ['-c', '-o', '']
-        ctx.env.CCLNK_TGT_F         = ['-o', '']
+        ctx.load('c_emscripten')
+    else:
+        ctx.load('compiler_c')
+
+    ctx.load('waf_unit_test')
+    ctx.load('gnu_dirs')
+    ctx.load('waf_gensyms', tooldir='.')
+
     # check for common headers
     ctx.check(header_name='stdlib.h')
     ctx.check(header_name='stdio.h')
@@ -151,10 +153,17 @@
         ctx.env.prepend_value('CFLAGS', ['-g', '-Wall', '-Wextra'])
     else:
         # enable debug symbols
-        ctx.env.CFLAGS += ['/Z7', '/FS']
+        ctx.env.CFLAGS += ['/Z7']
+        # /FS flag available in msvc >= 12 (2013)
+        if 'MSVC_VERSION' in ctx.env and ctx.env.MSVC_VERSION >= 12:
+            ctx.env.CFLAGS += ['/FS']
         ctx.env.LINKFLAGS += ['/DEBUG', '/INCREMENTAL:NO']
         # configure warnings
         ctx.env.CFLAGS += ['/W4', '/D_CRT_SECURE_NO_WARNINGS']
+        # ignore "possible loss of data" warnings
+        ctx.env.CFLAGS += ['/wd4305', '/wd4244', '/wd4245', '/wd4267']
+        # ignore "unreferenced formal parameter" warnings
+        ctx.env.CFLAGS += ['/wd4100']
         # set optimization level and runtime libs
         if (ctx.options.build_type == "release"):
             ctx.env.CFLAGS += ['/Ox']
@@ -226,9 +235,6 @@
         ctx.env.LINKFLAGS += [ '-isysroot' , SDKROOT]
 
     if target_platform == 'emscripten':
-        import os.path
-        ctx.env.CFLAGS += [ '-I' + os.path.join(os.environ['EMSCRIPTEN'], 'system', 'include') ]
-        
         if ctx.options.build_type == "debug":
             ctx.env.cshlib_PATTERN = '%s.js'
             ctx.env.LINKFLAGS += ['-s','ASSERTIONS=2']
@@ -247,9 +253,11 @@
         ctx.env.cstlib_PATTERN = '%s.a'
 
         # tell emscripten functions we want to expose
-        from python.lib.gen_external import get_c_declarations, get_cpp_objects_from_c_declarations, get_all_func_names_from_lib, generate_lib_from_c_declarations
+        from python.lib.gen_external import get_c_declarations, \
+                get_cpp_objects_from_c_declarations, get_all_func_names_from_lib, \
+                generate_lib_from_c_declarations
         c_decls = get_c_declarations(usedouble=False)  # emscripten can't use double
-        objects = get_cpp_objects_from_c_declarations(c_decls)
+        objects = list(get_cpp_objects_from_c_declarations(c_decls))
         # ensure that aubio structs are exported
         objects += ['fvec_t', 'cvec_t', 'fmat_t']
         lib = generate_lib_from_c_declarations(objects, c_decls)
@@ -286,6 +294,21 @@
     else:
         ctx.msg('Checking if complex.h is enabled', 'no')
 
+    # check for Intel IPP
+    if (ctx.options.enable_intelipp != False):
+        has_ipp_headers = ctx.check(header_name=['ippcore.h', 'ippvm.h', 'ipps.h'],
+                mandatory = False)
+        has_ipp_libs = ctx.check(lib=['ippcore', 'ippvm', 'ipps'],
+                uselib_store='INTEL_IPP', mandatory = False)
+        if (has_ipp_headers and has_ipp_libs):
+            ctx.msg('Checking if Intel IPP is available', 'yes')
+            ctx.define('HAVE_INTEL_IPP', 1)
+            if ctx.env.CC_NAME == 'msvc':
+                # force linking multi-threaded static IPP libraries on Windows with msvc
+                ctx.define('_IPP_SEQUENTIAL_STATIC', 1)
+        else:
+            ctx.msg('Checking if Intel IPP is available', 'no')
+
     # check for fftw3
     if (ctx.options.enable_fftw3 != False or ctx.options.enable_fftw3f != False):
         # one of fftwf or fftw3f
@@ -309,7 +332,7 @@
                         mandatory = ctx.options.enable_fftw3)
         ctx.define('HAVE_FFTW3', 1)
 
-    # fftw not enabled, use vDSP or ooura
+    # fftw not enabled, use vDSP, intelIPP or ooura
     if 'HAVE_FFTW3F' in ctx.env.define_key:
         ctx.msg('Checking for FFT implementation', 'fftw3f')
     elif 'HAVE_FFTW3' in ctx.env.define_key:
@@ -316,6 +339,8 @@
         ctx.msg('Checking for FFT implementation', 'fftw3')
     elif 'HAVE_ACCELERATE' in ctx.env.define_key:
         ctx.msg('Checking for FFT implementation', 'vDSP')
+    elif 'HAVE_INTEL_IPP' in ctx.env.define_key:
+        ctx.msg('Checking for FFT implementation', 'Intel IPP')
     else:
         ctx.msg('Checking for FFT implementation', 'ooura')
 
@@ -446,6 +471,8 @@
 
     # add sub directories
     if bld.env['DEST_OS'] not in ['ios', 'iosimulator', 'android']:
+        if bld.env['DEST_OS']=='emscripten' and not bld.options.testcmd:
+            bld.options.testcmd = 'node %s'
         bld.recurse('examples')
         bld.recurse('tests')
 
@@ -557,3 +584,4 @@
     ctx.excl += ' **/.travis.yml'
     ctx.excl += ' **/.landscape.yml'
     ctx.excl += ' **/.appveyor.yml'
+    ctx.excl += ' **/circlei.yml'