shithub: aubio

Download patch

ref: adc6e02ecf2d72a827822e7d09b519434e66376a
parent: bbfa9a42e9ea4786c187774437f2553f34c019bb
parent: bde4f641feff4cabff716064342ce600d762ce4d
author: Paul Brossier <[email protected]>
date: Sat Dec 1 05:57:07 EST 2018

Merge branch 'master' into feature/pytest

--- a/Makefile
+++ b/Makefile
@@ -259,22 +259,20 @@
 	lcov $(LCOVOPTS) -a build/coverage_python.info -a build/coverage_lib.info \
 		--output-file build/coverage.info
 	# remove tests
-	lcov $(LCOVOPTS) --remove build/coverage.info '*/tests/*' '*/ooura_fft8g*' \
+	lcov $(LCOVOPTS) --remove build/coverage.info '*/ooura_fft8g*' \
 		--output-file build/coverage_lib.info
 
 # make sure we don't build the doc, which builds a temporary python module
 coverage_report: export WAFOPTS += --disable-docs
 coverage_report: coverage
-	# create coverage report dir
-	mkdir -p build/coverage/
 	# generate report with lcov's genhtml
-	genhtml build/coverage_lib.info --output-directory build/coverage/lcov \
+	genhtml build/coverage_lib.info --output-directory build/coverage_c \
 		--branch-coverage --highlight --legend
 	# generate python report with coverage python package
 	coverage report
-	coverage html -d build/coverage/coverage
+	coverage html -d build/coverage_python
 	# show links to generated reports
-	for i in $$(ls build/coverage/*/index.html); do echo file://$(PWD)/$$i; done
+	for i in $$(ls build/coverage_*/index.html); do echo file://$(PWD)/$$i; done
 
 sphinx: configure
 	$(WAFCMD) sphinx $(WAFOPTS)
--- a/python/ext/py-phasevoc.c
+++ b/python/ext/py-phasevoc.c
@@ -90,10 +90,6 @@
   self->win_s = Py_default_vector_length;
   self->hop_s = Py_default_vector_length/2;
 
-  if (self == NULL) {
-    return NULL;
-  }
-
   if (win_s > 0) {
     self->win_s = win_s;
   } else if (win_s < 0) {
--- a/src/notes/notes.c
+++ b/src/notes/notes.c
@@ -83,6 +83,7 @@
   o->isready = 0;
 
   o->onset = new_aubio_onset (onset_method, o->onset_buf_size, o->hop_size, o->samplerate);
+  if (o->onset == NULL) goto fail;
   if (o->onset_threshold != 0.) aubio_onset_set_threshold (o->onset, o->onset_threshold);
   o->onset_output = new_fvec (1);
 
@@ -98,6 +99,9 @@
   }
   o->note_buffer = new_fvec(o->median);
   o->note_buffer2 = new_fvec(o->median);
+
+  if (!o->onset_output || !o->pitch_output ||
+      !o->note_buffer || !o->note_buffer2) goto fail;
 
   o->curnote = -1.;
   o->newnote = 0.;
--- a/src/pitch/pitchmcomb.c
+++ b/src/pitch/pitchmcomb.c
@@ -37,6 +37,7 @@
 /* not used but useful : sort by amplitudes (or anything else)
  * sort_pitchpeak(peaks, length);
  */
+#if 0
 /** spectral_peak comparison function (must return signed int) */
 static sint_t aubio_pitchmcomb_sort_peak_comp (const void *x, const void *y);
 /** sort spectral_peak against their mag */
@@ -44,13 +45,16 @@
 /** select the best candidates */
 uint_t aubio_pitch_cands (aubio_pitchmcomb_t * p, const cvec_t * fftgrain,
     smpl_t * cands);
+#endif
 
 /** sort spectral_candidate against their comb ene */
 void aubio_pitchmcomb_sort_cand_ene (aubio_spectralcandidate_t ** candidates,
     uint_t nbins);
+#if 0
 /** sort spectral_candidate against their frequency */
 void aubio_pitchmcomb_sort_cand_freq (aubio_spectralcandidate_t ** candidates,
     uint_t nbins);
+#endif
 
 struct _aubio_pitchmcomb_t
 {
@@ -133,6 +137,7 @@
      } */
 }
 
+#if 0
 uint_t
 aubio_pitch_cands (aubio_pitchmcomb_t * p, const cvec_t * fftgrain, smpl_t * cands)
 {
@@ -163,6 +168,7 @@
     return 0;
   }
 }
+#endif
 
 void
 aubio_pitchmcomb_spectral_pp (aubio_pitchmcomb_t * p, const fvec_t * newmag)
@@ -313,6 +319,7 @@
   return pos;
 }
 
+#if 0
 void
 aubio_pitchmcomb_sort_peak (aubio_spectralpeak_t * peaks, uint_t nbins)
 {
@@ -342,7 +349,6 @@
   }
 }
 
-
 void
 aubio_pitchmcomb_sort_cand_freq (aubio_spectralcandidate_t ** candidates,
     uint_t nbins)
@@ -356,6 +362,7 @@
     }
   }
 }
+#endif
 
 aubio_pitchmcomb_t *
 new_aubio_pitchmcomb (uint_t bufsize, uint_t hopsize)
--- a/src/pitch/pitchyin.c
+++ b/src/pitch/pitchyin.c
@@ -39,6 +39,7 @@
   uint_t peak_pos;
 };
 
+#if 0
 /** compute difference function
 
   \param input input signal
@@ -60,6 +61,7 @@
 
 */
 uint_t aubio_pitchyin_getpitch (const fvec_t * yinbuf);
+#endif
 
 aubio_pitchyin_t *
 new_aubio_pitchyin (uint_t bufsize)
@@ -78,6 +80,7 @@
   AUBIO_FREE (o);
 }
 
+#if 0
 /* outputs the difference function */
 void
 aubio_pitchyin_diff (fvec_t * input, fvec_t * yin)
@@ -127,6 +130,7 @@
   //AUBIO_DBG("No pitch found");
   return 0;
 }
+#endif
 
 /* all the above in one */
 void
--- a/src/pitch/pitchyinfast.c
+++ b/src/pitch/pitchyinfast.c
@@ -58,6 +58,12 @@
   o->samples_fft = new_fvec (bufsize);
   o->kernel_fft = new_fvec (bufsize);
   o->fft = new_aubio_fft (bufsize);
+  if (!o->yin || !o->tmpdata || !o->tmpdata || !o->sqdiff
+      || !o->kernel || !o->samples_fft || !o->kernel || !o->fft)
+  {
+    del_aubio_pitchyinfast(o);
+    return NULL;
+  }
   o->tol = 0.15;
   o->peak_pos = 0;
   return o;
@@ -66,13 +72,20 @@
 void
 del_aubio_pitchyinfast (aubio_pitchyinfast_t * o)
 {
-  del_fvec (o->yin);
-  del_fvec (o->tmpdata);
-  del_fvec (o->sqdiff);
-  del_fvec (o->kernel);
-  del_fvec (o->samples_fft);
-  del_fvec (o->kernel_fft);
-  del_aubio_fft (o->fft);
+  if (o->yin)
+    del_fvec (o->yin);
+  if (o->tmpdata)
+    del_fvec (o->tmpdata);
+  if (o->sqdiff)
+    del_fvec (o->sqdiff);
+  if (o->kernel)
+    del_fvec (o->kernel);
+  if (o->samples_fft)
+    del_fvec (o->samples_fft);
+  if (o->kernel_fft)
+    del_fvec (o->kernel_fft);
+  if (o->fft)
+    del_aubio_fft (o->fft);
   AUBIO_FREE (o);
 }
 
--- a/src/utils/hist.c
+++ b/src/utils/hist.c
@@ -43,6 +43,9 @@
   smpl_t step = (fhig-flow)/(smpl_t)(nelems);
   smpl_t accum = step;
   uint_t i;
+  if ((sint_t)nelems <= 0) {
+    return NULL;
+  }
   s->nelems = nelems;
   s->hist = new_fvec(nelems);
   s->cent = new_fvec(nelems);
--- /dev/null
+++ b/tests/create_tests_source.py
@@ -1,0 +1,42 @@
+#! /usr/bin/env python
+
+""" Create a simple stereo file containing a sine tone at 441 Hz, using only
+python's built-in modules. """
+
+import wave
+import math
+import struct
+
+
+def create_sine_wave(freq, samplerate, nframes, nchannels):
+    """ create a pure tone (without numpy) """
+    _x = [0.7 * math.sin(2. * math.pi * freq * t / float(samplerate))
+          for t in range(nframes)]
+    _x = [int(a * 32767) for a in _x]
+    _x = b''.join([b''.join([struct.pack('h', v)
+                             for _ in range(nchannels)])
+                   for v in _x])
+    return _x
+
+
+def create_test_sound(pathname, freq=441, duration=None,
+                      framerate=44100, nchannels=2):
+    """ create a sound file at pathname, overwriting exiting file """
+    sampwidth = 2
+    nframes = duration or framerate  # defaults to 1 second duration
+    fid = wave.open(pathname, 'w')
+    fid.setnchannels(nchannels)
+    fid.setsampwidth(sampwidth)
+    fid.setframerate(framerate)
+    fid.setnframes(nframes)
+    frames = create_sine_wave(freq, framerate, nframes, nchannels)
+    fid.writeframes(frames)
+    fid.close()
+    return 0
+
+
+if __name__ == '__main__':
+    import sys
+    if len(sys.argv) < 2:
+        sys.exit(2)
+    sys.exit(create_test_sound(sys.argv[1]))
--- a/tests/src/io/test-sink-multi.c
+++ b/tests/src/io/test-sink-multi.c
@@ -9,8 +9,8 @@
   sint_t err = 0;
 
   if (argc < 3) {
-    err = 2;
-    PRINT_ERR("not enough arguments\n");
+    PRINT_ERR("not enough arguments, running tests\n");
+    err = run_on_default_source_and_sink(main);
     PRINT_MSG("usage: %s <input_path> <output_path> [samplerate] [channels] [hop_size]\n", argv[0]);
     return err;
   }
--- a/tests/src/io/test-sink.c
+++ b/tests/src/io/test-sink.c
@@ -6,8 +6,8 @@
   sint_t err = 0;
 
   if (argc < 3) {
-    err = 2;
-    PRINT_ERR("not enough arguments\n");
+    PRINT_ERR("not enough arguments, running tests\n");
+    err = run_on_default_source_and_sink(main);
     PRINT_MSG("usage: %s <input_path> <output_path> [samplerate] [hop_size]\n", argv[0]);
     return err;
   }
--- a/tests/src/io/test-sink_apple_audio-multi.c
+++ b/tests/src/io/test-sink_apple_audio-multi.c
@@ -10,8 +10,8 @@
   sint_t err = 0;
 
   if (argc < 3) {
-    err = 2;
-    PRINT_ERR("not enough arguments\n");
+    PRINT_ERR("not enough arguments, running tests\n");
+    err = run_on_default_source_and_sink(main);
     PRINT_MSG("usage: %s <input_path> <output_path> [samplerate] [channels] [hop_size]\n", argv[0]);
     return err;
   }
@@ -71,7 +71,7 @@
   del_aubio_source(i);
 beach_source:
 #else /* HAVE_SINK_APPLE_AUDIO */
-  err = 3;
+  err = 0;
   PRINT_ERR("aubio was not compiled with aubio_sink_apple_audio\n");
 #endif /* HAVE_SINK_APPLE_AUDIO */
   return err;
--- a/tests/src/io/test-sink_apple_audio.c
+++ b/tests/src/io/test-sink_apple_audio.c
@@ -10,8 +10,8 @@
   sint_t err = 0;
 
   if (argc < 3) {
-    err = 2;
-    PRINT_ERR("not enough arguments\n");
+    PRINT_ERR("not enough arguments, running tests\n");
+    err = run_on_default_source_and_sink(main);
     PRINT_MSG("usage: %s <input_path> <output_path> [samplerate] [hop_size]\n", argv[0]);
     return err;
   }
@@ -60,7 +60,7 @@
   del_fvec(vec);
 beach_fvec:
 #else /* HAVE_SINK_APPLE_AUDIO */
-  err = 3;
+  err = 0;
   PRINT_ERR("aubio was not compiled with aubio_source_apple_audio\n");
 #endif /* HAVE_SINK_APPLE_AUDIO */
   return err;
--- a/tests/src/io/test-sink_sndfile-multi.c
+++ b/tests/src/io/test-sink_sndfile-multi.c
@@ -10,8 +10,8 @@
   sint_t err = 0;
 
   if (argc < 3) {
-    err = 2;
-    PRINT_ERR("not enough arguments\n");
+    PRINT_ERR("not enough arguments, running tests\n");
+    err = run_on_default_source_and_sink(main);
     PRINT_MSG("usage: %s <input_path> <output_path> [samplerate] [channels] [hop_size]\n", argv[0]);
     return err;
   }
@@ -71,7 +71,7 @@
   del_aubio_source(i);
 beach_source:
 #else
-  err = 3;
+  err = 0;
   PRINT_ERR("aubio was not compiled with aubio_sink_sndfile\n");
 #endif /* HAVE_SNDFILE */
   return err;
--- a/tests/src/io/test-sink_sndfile.c
+++ b/tests/src/io/test-sink_sndfile.c
@@ -10,8 +10,8 @@
   sint_t err = 0;
 
   if (argc < 3) {
-    err = 2;
-    PRINT_ERR("not enough arguments\n");
+    PRINT_ERR("not enough arguments, running tests\n");
+    err = run_on_default_source_and_sink(main);
     PRINT_MSG("usage: %s <input_path> <output_path> [samplerate] [hop_size]\n", argv[0]);
     return err;
   }
@@ -60,7 +60,7 @@
   del_fvec(vec);
 beach_fvec:
 #else
-  err = 3;
+  err = 0;
   PRINT_ERR("aubio was not compiled with aubio_source_sndfile\n");
 #endif /* HAVE_SNDFILE */
   return err;
--- a/tests/src/io/test-sink_wavwrite-multi.c
+++ b/tests/src/io/test-sink_wavwrite-multi.c
@@ -10,8 +10,8 @@
   sint_t err = 0;
 
   if (argc < 3) {
-    err = 2;
-    PRINT_ERR("not enough arguments\n");
+    PRINT_ERR("not enough arguments, running tests\n");
+    err = run_on_default_source_and_sink(main);
     PRINT_MSG("usage: %s <input_path> <output_path> [samplerate] [channels] [hop_size]\n", argv[0]);
     return err;
   }
@@ -71,7 +71,7 @@
   del_aubio_source(i);
 beach_source:
 #else
-  err = 3;
+  err = 0;
   PRINT_ERR("aubio was not compiled with aubio_sink_wavwrite\n");
 #endif /* HAVE_WAVWRITE */
   return err;
--- a/tests/src/io/test-sink_wavwrite.c
+++ b/tests/src/io/test-sink_wavwrite.c
@@ -10,8 +10,8 @@
   sint_t err = 0;
 
   if (argc < 3) {
-    err = 2;
-    PRINT_ERR("not enough arguments\n");
+    PRINT_ERR("not enough arguments, running tests\n");
+    err = run_on_default_source_and_sink(main);
     PRINT_MSG("usage: %s <input_path> <output_path> [samplerate] [hop_size]\n", argv[0]);
     return err;
   }
@@ -60,7 +60,7 @@
   del_fvec(vec);
 beach_fvec:
 #else
-  err = 3;
+  err = 0;
   PRINT_ERR("aubio was not compiled with aubio_sink_wavwrite\n");
 #endif /* HAVE_WAVWRITE */
   return err;
--- a/tests/src/io/test-source.c
+++ b/tests/src/io/test-source.c
@@ -5,8 +5,8 @@
 {
   uint_t err = 0;
   if (argc < 2) {
-    err = 2;
-    PRINT_ERR("not enough arguments\n");
+    PRINT_ERR("not enough arguments, running tests\n");
+    err = run_on_default_source(main);
     PRINT_MSG("read a wave file as a mono vector\n");
     PRINT_MSG("usage: %s <source_path> [samplerate] [hop_size]\n", argv[0]);
     PRINT_MSG("examples:\n");
@@ -22,8 +22,8 @@
   uint_t samplerate = 0;
   uint_t hop_size = 256;
   uint_t n_frames = 0, read = 0;
-  if ( argc == 3 ) samplerate = atoi(argv[2]);
-  if ( argc == 4 ) hop_size = atoi(argv[3]);
+  if ( argc >= 3 ) samplerate = atoi(argv[2]);
+  if ( argc >= 4 ) hop_size = atoi(argv[3]);
 
   char_t *source_path = argv[1];
 
--- a/tests/src/io/test-source_apple_audio.c
+++ b/tests/src/io/test-source_apple_audio.c
@@ -9,8 +9,8 @@
 {
   uint_t err = 0;
   if (argc < 2) {
-    err = 2;
-    PRINT_ERR("not enough arguments\n");
+    PRINT_ERR("not enough arguments, running tests\n");
+    err = run_on_default_source(main);
     PRINT_MSG("read a wave file as a mono vector\n");
     PRINT_MSG("usage: %s <source_path> [samplerate] [hop_size]\n", argv[0]);
     PRINT_MSG("examples:\n");
@@ -27,8 +27,8 @@
   uint_t samplerate = 0;
   uint_t hop_size = 256;
   uint_t n_frames = 0, read = 0;
-  if ( argc == 3 ) samplerate = atoi(argv[2]);
-  if ( argc == 4 ) hop_size = atoi(argv[3]);
+  if ( argc >= 3 ) samplerate = atoi(argv[2]);
+  if ( argc >= 4 ) hop_size = atoi(argv[3]);
 
   char_t *source_path = argv[1];
 
@@ -56,7 +56,7 @@
   del_aubio_source_apple_audio (s);
 beach:
 #else /* HAVE_SOURCE_APPLE_AUDIO */
-  err = 3;
+  err = 0;
   PRINT_ERR("aubio was not compiled with aubio_source_apple_audio\n");
 #endif /* HAVE_SOURCE_APPLE_AUDIO */
   return err;
--- a/tests/src/io/test-source_avcodec.c
+++ b/tests/src/io/test-source_avcodec.c
@@ -9,8 +9,8 @@
 {
   uint_t err = 0;
   if (argc < 2) {
-    err = 2;
-    PRINT_ERR("not enough arguments\n");
+    PRINT_ERR("not enough arguments, running tests\n");
+    err = run_on_default_source(main);
     PRINT_MSG("read a wave file as a mono vector\n");
     PRINT_MSG("usage: %s <source_path> [samplerate] [hop_size]\n", argv[0]);
     PRINT_MSG("examples:\n");
@@ -27,8 +27,8 @@
   uint_t samplerate = 0;
   uint_t hop_size = 256;
   uint_t n_frames = 0, read = 0;
-  if ( argc == 3 ) samplerate = atoi(argv[2]);
-  if ( argc == 4 ) hop_size = atoi(argv[3]);
+  if ( argc >= 3 ) samplerate = atoi(argv[2]);
+  if ( argc >= 4 ) hop_size = atoi(argv[3]);
 
   char_t *source_path = argv[1];
 
@@ -56,7 +56,7 @@
   del_aubio_source_avcodec (s);
 beach:
 #else /* HAVE_LIBAV */
-  err = 3;
+  err = 0;
   PRINT_ERR("aubio was not compiled with aubio_source_avcodec\n");
 #endif /* HAVE_LIBAV */
   return err;
--- a/tests/src/io/test-source_multi.c
+++ b/tests/src/io/test-source_multi.c
@@ -5,8 +5,8 @@
 {
   sint_t err = 0;
   if (argc < 2) {
-    err = -2;
-    PRINT_ERR("not enough arguments\n");
+    PRINT_ERR("not enough arguments, running tests\n");
+    err = run_on_default_source(main);
     PRINT_MSG("read a wave file as a mono vector\n");
     PRINT_MSG("usage: %s <source_path> [samplerate] [hop_size]\n", argv[0]);
     PRINT_MSG("examples:\n");
--- a/tests/src/io/test-source_seek.c
+++ b/tests/src/io/test-source_seek.c
@@ -5,8 +5,8 @@
 {
   uint_t err = 0;
   if (argc < 2) {
-    err = 2;
-    PRINT_ERR("not enough arguments\n");
+    PRINT_ERR("not enough arguments, running tests\n");
+    err = run_on_default_source(main);
     PRINT_MSG("read a wave file as a mono vector\n");
     PRINT_MSG("usage: %s <source_path> [samplerate] [hop_size]\n", argv[0]);
     PRINT_MSG("examples:\n");
@@ -23,8 +23,8 @@
   uint_t hop_size = 256;
   uint_t n_frames = 0, read = 0;
   uint_t old_n_frames_1 = 0, old_n_frames_2 = 0, old_n_frames_3 = 0;
-  if ( argc == 3 ) samplerate = atoi(argv[2]);
-  if ( argc == 4 ) hop_size = atoi(argv[3]);
+  if ( argc >= 3 ) samplerate = atoi(argv[2]);
+  if ( argc >= 4 ) hop_size = atoi(argv[3]);
 
   char_t *source_path = argv[1];
 
--- a/tests/src/io/test-source_sndfile.c
+++ b/tests/src/io/test-source_sndfile.c
@@ -9,8 +9,8 @@
 {
   uint_t err = 0;
   if (argc < 2) {
-    err = 2;
-    PRINT_ERR("not enough arguments\n");
+    PRINT_ERR("not enough arguments, running tests\n");
+    err = run_on_default_source(main);
     PRINT_MSG("read a wave file as a mono vector\n");
     PRINT_MSG("usage: %s <source_path> [samplerate] [hop_size]\n", argv[0]);
     PRINT_MSG("examples:\n");
@@ -27,8 +27,8 @@
   uint_t samplerate = 0;
   uint_t hop_size = 256;
   uint_t n_frames = 0, read = 0;
-  if ( argc == 3 ) samplerate = atoi(argv[2]);
-  if ( argc == 4 ) hop_size = atoi(argv[3]);
+  if ( argc >= 3 ) samplerate = atoi(argv[2]);
+  if ( argc >= 4 ) hop_size = atoi(argv[3]);
 
   char_t *source_path = argv[1];
 
@@ -56,7 +56,7 @@
   del_aubio_source_sndfile (s);
 beach:
 #else
-  err = 3;
+  err = 0;
   PRINT_ERR("aubio was not compiled with aubio_source_sndfile\n");
 #endif /* HAVE_SNDFILE */
   return err;
--- a/tests/src/io/test-source_wavread.c
+++ b/tests/src/io/test-source_wavread.c
@@ -9,8 +9,8 @@
 {
   uint_t err = 0;
   if (argc < 2) {
-    err = 2;
-    PRINT_ERR("not enough arguments\n");
+    PRINT_ERR("not enough arguments, running tests\n");
+    err = run_on_default_source(main);
     PRINT_MSG("read a wave file as a mono vector\n");
     PRINT_MSG("usage: %s <source_path> [samplerate] [hop_size]\n", argv[0]);
     PRINT_MSG("examples:\n");
@@ -27,8 +27,8 @@
   uint_t samplerate = 0;
   uint_t hop_size = 256;
   uint_t n_frames = 0, read = 0;
-  if ( argc == 3 ) samplerate = atoi(argv[2]);
-  if ( argc == 4 ) hop_size = atoi(argv[3]);
+  if ( argc >= 3 ) samplerate = atoi(argv[2]);
+  if ( argc >= 4 ) hop_size = atoi(argv[3]);
 
   char_t *source_path = argv[1];
 
@@ -35,7 +35,6 @@
 
   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);
 
@@ -57,7 +56,7 @@
   del_aubio_source_wavread (s);
 beach:
 #else
-  err = 3;
+  err = 0;
   PRINT_ERR("aubio was not compiled with aubio_source_wavread\n");
 #endif /* HAVE_WAVREAD */
   return err;
--- /dev/null
+++ b/tests/src/notes/test-notes.c
@@ -1,0 +1,24 @@
+#include <aubio.h>
+
+int main (void)
+{
+  uint_t buf_size = 2048;
+  uint_t hop_size = 512;
+  uint_t samplerate = 44100;
+  smpl_t silence, minioi_ms, release_drop;
+  aubio_notes_t *o = new_aubio_notes("default",
+      buf_size, hop_size, samplerate);
+  silence = aubio_notes_get_silence(o);
+  minioi_ms = aubio_notes_get_minioi_ms(o);
+  release_drop = aubio_notes_get_release_drop(o);
+  if (aubio_notes_set_silence(o, silence)) return 1;
+  if (aubio_notes_set_minioi_ms(o, minioi_ms)) return 1;
+  if (aubio_notes_set_release_drop(o, release_drop)) return 1;
+  del_aubio_notes(o);
+  // test wrong arguments
+  if (new_aubio_notes("unknown", buf_size, hop_size, samplerate)) return 1;
+  if (new_aubio_notes("default",        0, hop_size, samplerate)) return 1;
+  if (new_aubio_notes("default", buf_size,        0, samplerate)) return 1;
+  if (new_aubio_notes("default", buf_size, hop_size,          0)) return 1;
+  return 0;
+}
--- a/tests/src/onset/test-onset.c
+++ b/tests/src/onset/test-onset.c
@@ -9,12 +9,7 @@
   if (argc < 2) {
     err = 2;
     PRINT_WRN("no arguments, running tests\n");
-    if (test_wrong_params() != 0) {
-      PRINT_ERR("tests failed!\n");
-      err = 1;
-    } else {
-      err = 0;
-    }
+    err = test_wrong_params();
     PRINT_MSG("usage: %s <source_path> [samplerate] [hop_size]\n", argv[0]);
     return err;
   }
@@ -22,8 +17,8 @@
   uint_t win_s = 1024; // window size
   uint_t hop_size = win_s / 4;
   uint_t n_frames = 0, read = 0;
-  if ( argc == 3 ) samplerate = atoi(argv[2]);
-  if ( argc == 4 ) hop_size = atoi(argv[3]);
+  if ( argc >= 3 ) samplerate = atoi(argv[2]);
+  if ( argc >= 4 ) hop_size = atoi(argv[3]);
 
   char_t *source_path = argv[1];
   aubio_source_t * source = new_aubio_source(source_path, samplerate, hop_size);
@@ -89,15 +84,17 @@
   // specdesc creation failed
   if (new_aubio_onset("abcd", win_size, win_size/2, samplerate))
     return 1;
-  // pv creation failed
-  if (new_aubio_onset("default", 5, 2, samplerate))
-    return 1;
 
   aubio_onset_t *o;
+
+  // pv creation might fail
+  o = new_aubio_onset("default", 5, 2, samplerate);
+  if (o) del_aubio_onset(o);
+
   o = new_aubio_onset("default", win_size, hop_size, samplerate);
   if (!aubio_onset_set_default_parameters(o, "wrong_type"))
     return 1;
   del_aubio_onset(o);
 
-  return 0;
+  return run_on_default_source(main);
 }
--- a/tests/src/pitch/test-pitch.c
+++ b/tests/src/pitch/test-pitch.c
@@ -30,5 +30,42 @@
   del_fvec (input);
   aubio_cleanup ();
 
+  if (new_aubio_pitch(0, win_s, hop_s, samplerate)) return 1;
+  if (new_aubio_pitch("unknown", win_s, hop_s, samplerate)) return 1;
+  if (new_aubio_pitch("default", win_s,     0, samplerate)) return 1;
+  if (new_aubio_pitch("default",     0, hop_s, samplerate)) return 1;
+  if (new_aubio_pitch("default", hop_s, win_s, samplerate)) return 1;
+  if (new_aubio_pitch("default", win_s, hop_s,          0)) return 1;
+
+  o = new_aubio_pitch("default", win_s, hop_s, samplerate);
+
+  if (aubio_pitch_set_unit(o, "freq")) return 1;
+  if (aubio_pitch_set_unit(o, "hertz")) return 1;
+  if (aubio_pitch_set_unit(o, "Hertz")) return 1;
+  if (aubio_pitch_set_unit(o, "Hz")) return 1;
+  if (aubio_pitch_set_unit(o, "f0")) return 1;
+  if (aubio_pitch_set_unit(o, "midi")) return 1;
+  if (aubio_pitch_set_unit(o, "cent")) return 1;
+  if (aubio_pitch_set_unit(o, "bin")) return 1;
+  if (!aubio_pitch_set_unit(o, "unknown")) return 1;
+
+  if (aubio_pitch_set_tolerance(o, 0.3)) return 1;
+  if (aubio_pitch_set_silence(o, 0)) return 1;
+  if (aubio_pitch_set_silence(o, -200)) return 1;
+  if (!aubio_pitch_set_silence(o, -300)) return 1;
+  del_aubio_pitch(o);
+
+  // fft based might fail with non power of 2
+  o = new_aubio_pitch("yinfft", win_s + 1, hop_s, samplerate);
+  if (o) del_aubio_pitch(o);
+  o = new_aubio_pitch("yinfast", win_s + 1, hop_s, samplerate);
+  if (o) del_aubio_pitch(o);
+  o = new_aubio_pitch("fcomb", win_s + 1, hop_s, samplerate);
+  if (o) del_aubio_pitch(o);
+  o = new_aubio_pitch("mcomb", win_s + 1, hop_s, samplerate);
+  if (o) del_aubio_pitch(o);
+  o = new_aubio_pitch("specacf", win_s + 1, hop_s, samplerate);
+  if (o) del_aubio_pitch(o);
+
   return 0;
 }
--- a/tests/src/spectral/test-awhitening.c
+++ b/tests/src/spectral/test-awhitening.c
@@ -10,12 +10,7 @@
   if (argc < 3) {
     err = 2;
     PRINT_WRN("no arguments, running tests\n");
-    if (test_wrong_params() != 0) {
-      PRINT_ERR("tests failed!\n");
-      err = 1;
-    } else {
-      err = 0;
-    }
+    err = test_wrong_params();
     PRINT_MSG("usage: %s <input_path> <output_path> [samplerate] [hop_size]\n", argv[0]);
     return err;
   }
@@ -30,11 +25,6 @@
 
   if ( argc >= 4 ) samplerate = atoi(argv[3]);
   if ( argc >= 5 ) hop_size = atoi(argv[4]);
-  if ( argc >= 6 ) {
-    err = 2;
-    PRINT_ERR("too many arguments\n");
-    return err;
-  }
 
   fvec_t *vec = new_fvec(hop_size);
   fvec_t *out = new_fvec(hop_size); // output buffer
@@ -108,5 +98,5 @@
 
   del_aubio_spectral_whitening(o);
 
-  return 0;
+  return run_on_default_source_and_sink(main);
 }
--- a/tests/src/spectral/test-dct.c
+++ b/tests/src/spectral/test-dct.c
@@ -32,9 +32,7 @@
     aubio_dct_do (dct, in, dctout);
     aubio_dct_rdo (dct, dctout, out);
     for (j = 0; j < in->length; j++) {
-      if (fabsf(in->data[j] - out->data[j]) > 10.e-4) {
-        fprintf(stderr, "dct reconstruction failed\n");
-      }
+      return_code += (fabsf(in->data[j] - out->data[j]) > 10.e-4);
     }
   }
 
--- a/tests/src/synth/test-sampler.c
+++ b/tests/src/synth/test-sampler.c
@@ -1,3 +1,5 @@
+#include <string.h> // strncpy
+#include <limits.h> // PATH_MAX
 #include <aubio.h>
 #include "utils_tests.h"
 
@@ -5,9 +7,9 @@
 {
   sint_t err = 0;
 
-  if (argc < 4) {
-    err = 2;
-    PRINT_ERR("not enough arguments\n");
+  if (argc < 3) {
+    PRINT_ERR("not enough arguments, running tests\n");
+    err = run_on_default_source_and_sink(main);
     PRINT_MSG("usage: %s <input_path> <output_path> <sample_path> [samplerate]\n", argv[0]);
     return err;
   }
@@ -18,8 +20,15 @@
 
   char_t *source_path = argv[1];
   char_t *sink_path = argv[2];
-  char_t *sample_path = argv[3];
-  if ( argc == 5 ) samplerate = atoi(argv[4]);
+  char_t sample_path[PATH_MAX];
+  if ( argc >= 4 ) {
+    strncpy(sample_path, argv[3], PATH_MAX - 1);
+  } else {
+    // use input_path as sample
+    strncpy(sample_path, source_path, PATH_MAX - 1);
+  }
+  sample_path[PATH_MAX - 1] = '\0';
+  if ( argc >= 5 ) samplerate = atoi(argv[4]);
 
   fvec_t *vec = new_fvec(hop_size);
   aubio_source_t *source = new_aubio_source(source_path, samplerate, hop_size);
--- a/tests/src/synth/test-wavetable.c
+++ b/tests/src/synth/test-wavetable.c
@@ -6,8 +6,8 @@
   sint_t err = 0;
 
   if (argc < 2) {
-    err = 2;
-    PRINT_ERR("not enough arguments\n");
+    PRINT_ERR("not enough arguments, running tests\n");
+    err = run_on_default_sink(main);
     PRINT_MSG("usage: %s <output_path> [freq] [samplerate]\n", argv[0]);
     return err;
   }
@@ -17,8 +17,8 @@
   smpl_t freq = 440.;
 
   char_t *sink_path = argv[1];
-  if ( argc == 4 ) samplerate = atoi(argv[3]);
-  if ( argc == 3 ) freq = atof(argv[2]);
+  if ( argc >= 4 ) samplerate = atoi(argv[3]);
+  if ( argc >= 3 ) freq = atof(argv[2]);
 
   fvec_t *vec = new_fvec(hop_size);
   aubio_sink_t *sink = new_aubio_sink(sink_path, samplerate);
--- a/tests/src/tempo/test-tempo.c
+++ b/tests/src/tempo/test-tempo.c
@@ -7,14 +7,8 @@
 {
   uint_t err = 0;
   if (argc < 2) {
-    err = 2;
     PRINT_WRN("no arguments, running tests\n");
-    if (test_wrong_params() != 0) {
-      PRINT_ERR("tests failed!\n");
-      err = 1;
-    } else {
-      err = 0;
-    }
+    err = test_wrong_params();
     PRINT_MSG("usage: %s <source_path> [samplerate] [win_size] [hop_size]\n",
         argv[0]);
     return err;
@@ -135,5 +129,5 @@
   del_fvec(in);
   del_fvec(out);
 
-  return 0;
+  return run_on_default_source(main);
 }
--- a/tests/src/test-mathutils.c
+++ b/tests/src/test-mathutils.c
@@ -102,7 +102,7 @@
   fvec_print(window);
 
   window_size /= 2.;
-  window = new_aubio_window("triangle", window_size);
+  window = new_aubio_window("parzen", window_size);
   fvec_print(window);
   del_fvec(window);
 
@@ -116,5 +116,6 @@
   test_next_power_of_two();
   test_miditofreq();
   test_freqtomidi();
+  test_aubio_window();
   return 0;
 }
--- a/tests/src/utils/test-hist.c
+++ b/tests/src/utils/test-hist.c
@@ -25,6 +25,7 @@
     del_aubio_hist(o);
     del_fvec(t);
   }
+  if (new_aubio_hist(0, 1, 0)) return 1;
   return 0;
 }
 
--- a/tests/utils_tests.h
+++ b/tests/utils_tests.h
@@ -5,6 +5,36 @@
 #include <assert.h>
 #include "config.h"
 
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h> // unlink, close
+#endif
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h> // PATH_MAX
+#endif /* HAVE_LIMITS_H */
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+#if defined(HAVE_WIN_HACKS) && !defined(__GNUC__)
+#include <io.h> // _access
+#endif
+
+// This macro is used to pass a string to msvc compiler: since msvc's -D flag
+// strips the quotes, we define the string without quotes and re-add them with
+// this macro.
+
+#define REDEFINESTRING(x) #x
+#define DEFINEDSTRING(x) REDEFINESTRING(x)
+
+#ifndef AUBIO_TESTS_SOURCE
+#error "AUBIO_TESTS_SOURCE is not defined"
+#endif
+
 #ifdef HAVE_C99_VARARGS_MACROS
 #define PRINT_ERR(...)   fprintf(stderr, "AUBIO-TESTS ERROR: " __VA_ARGS__)
 #define PRINT_MSG(...)   fprintf(stdout, __VA_ARGS__)
@@ -47,7 +77,113 @@
 void utils_init_random (void) {
   time_t now = time(0);
   struct tm *tm_struct = localtime(&now);
-  int seed = tm_struct->tm_sec;
+  size_t **tm_address = (void*)&tm_struct;
+  int seed = tm_struct->tm_sec + (size_t)tm_address;
   //PRINT_WRN("current seed: %d\n", seed);
-  srandom (seed);
+  srandom ((unsigned int)seed);
+}
+
+// create_temp_sink / close_temp_sink
+#if defined(__GNUC__) // mkstemp
+
+int check_source(char *source_path)
+{
+  return access(source_path, R_OK);
+}
+
+int create_temp_sink(char *sink_path)
+{
+  return mkstemp(sink_path);
+}
+
+int close_temp_sink(char *sink_path, int sink_fildes)
+{
+  int err;
+  if ((err = close(sink_fildes)) != 0) return err;
+  if ((err = unlink(sink_path)) != 0) return err;
+  return err;
+}
+
+#elif defined(HAVE_WIN_HACKS) //&& !defined(__GNUC__)
+// windows workaround, where mkstemp does not exist...
+
+int check_source(char *source_path)
+{
+  return _access(source_path, 04);
+}
+
+int create_temp_sink(char *templ)
+{
+  int i = 0;
+  static const char letters[] = "abcdefg0123456789";
+  int letters_len = strlen(letters);
+  int templ_len = strlen(templ);
+  if (templ_len == 0) return 0;
+  utils_init_random();
+  for (i = 0; i < 6; i++)
+  {
+    templ[templ_len - i] = letters[rand() % letters_len];
+  }
+  return 1;
+}
+
+int close_temp_sink(char* sink_path, int sink_fildes) {
+  // the file should be closed when not using mkstemp, no need to open it
+  if (sink_fildes == 0) return 1;
+  return _unlink(sink_path);
+}
+
+#else // windows workaround
+// otherwise, we don't really know what to do yet
+#error "mkstemp undefined, but not on windows. additional workaround required."
+#endif
+
+// pass progname / default
+int run_on_default_source( int main(int, char**) )
+{
+  const int argc = 2;
+  int err = 0;
+  char** argv = (char**)calloc(argc, sizeof(char*));
+  argv[0] = __FILE__;
+  argv[1] = DEFINEDSTRING(AUBIO_TESTS_SOURCE);
+  // check if the file can be read
+  if ( check_source(argv[1]) ) return 1;
+  err = main(argc, argv);
+  if (argv) free(argv);
+  return err;
+}
+
+int run_on_default_sink( int main(int, char**) )
+{
+  const int argc = 2;
+  int err = 0;
+  char** argv = (char**)calloc(argc, sizeof(char*));
+  char sink_path[PATH_MAX] = "tmp_aubio_XXXXXX";
+  int fd = create_temp_sink(sink_path);
+  if (!fd) return 1;
+  argv[0] = __FILE__;
+  argv[1] = sink_path;
+  err = main(argc, argv);
+  close_temp_sink(sink_path, fd);
+  if (argv) free(argv);
+  return err;
+}
+
+int run_on_default_source_and_sink( int main(int, char**) )
+{
+  const int argc = 3;
+  int err = 0;
+  char** argv = (char**)calloc(argc, sizeof(char*));
+  char sink_path[PATH_MAX] = "tmp_aubio_XXXXXX";
+  int fd = create_temp_sink(sink_path);
+  if (!fd) return 1;
+  argv[0] = __FILE__;
+  argv[1] = DEFINEDSTRING(AUBIO_TESTS_SOURCE);
+  argv[2] = sink_path;
+  // check if the file can be read
+  if ( check_source(argv[1]) ) return 1;
+  err = main(argc, argv);
+  close_temp_sink(sink_path, fd);
+  if (argv) free(argv);
+  return err;
 }
--- a/tests/wscript_build
+++ b/tests/wscript_build
@@ -7,13 +7,30 @@
 includes = ['../src', '.']
 programs_sources = ctx.path.ant_glob('src/**/*.c')
 
+test_sound_target = '44100Hz_44100f_sine441_stereo.wav'
+test_sound_abspath = bld.path.get_bld().make_node(test_sound_target)
+# workaround to double escape backslash characters on windows
+test_sound_abspath = str(test_sound_abspath).replace('\\', '\\\\')
+
+b = bld(name='create_tests_source',
+    rule='python ${SRC} ${TGT}',
+    source='create_tests_source.py',
+    target=test_sound_target)
+# use post() to create the task, keep a reference to it
+b.post()
+create_tests_source = b.tasks[0]
+
 for source_file in programs_sources:
     target = os.path.basename(os.path.splitext(str(source_file))[0])
-    bld(features = 'c cprogram test',
+    a = bld(features = 'c cprogram test',
             source = source_file,
             target = target,
             includes = includes,
             use = uselib,
             install_path = None,
-            defines = 'AUBIO_UNSTABLE_API=1',
+            defines = ['AUBIO_UNSTABLE_API=1',
+                        'AUBIO_TESTS_SOURCE={}'.format(test_sound_abspath)]
        )
+    a.post()
+    # make sure the unit_test task runs *after* the source is created
+    a.tasks[-1].set_run_after(create_tests_source)
--- a/wscript
+++ b/wscript
@@ -517,6 +517,10 @@
     doxygen(bld)
     sphinx(bld)
 
+    from waflib.Tools import waf_unit_test
+    bld.add_post_fun(waf_unit_test.summary)
+    bld.add_post_fun(waf_unit_test.set_exit_code)
+
 def txt2man(bld):
     # build manpages from txt files using txt2man
     if bld.env['TXT2MAN']: