shithub: aubio

Download patch

ref: 1cf031a3a5b869368562b1251419fd45191eaa53
parent: bcc53876548334b4c5f1ebd47a5bd5f151974e8b
parent: ef0a430fdb65d2f8eaf3b92e47eaece4255497d8
author: Paul Brossier <piem@piem.org>
date: Mon Nov 26 06:34:45 EST 2018

Merge branch 'fix/bufoverflow_tempo' (thanks to @niugx)

--- /dev/null
+++ b/python/tests/test_tempo.py
@@ -1,0 +1,91 @@
+#! /usr/bin/env python
+
+from unittest import main
+from numpy.testing import TestCase, assert_equal, assert_almost_equal
+import aubio
+
+class aubio_tempo_default(TestCase):
+
+    def test_members(self):
+        o = aubio.tempo()
+        assert_equal ([o.buf_size, o.hop_size, o.method, o.samplerate],
+            [1024,512,'default',44100])
+
+class aubio_tempo_params(TestCase):
+
+    samplerate = 44100
+
+    def setUp(self):
+        self.o = aubio.tempo(samplerate = self.samplerate)
+
+    def test_get_delay(self):
+        self.assertEqual(self.o.get_delay(), 0)
+
+    def test_set_delay(self):
+        val = 256
+        self.o.set_delay(val)
+        assert_equal (self.o.get_delay(), val)
+
+    def test_get_delay_s(self):
+        self.assertEqual(self.o.get_delay_s(), 0.)
+
+    def test_set_delay_s(self):
+        val = .05
+        self.o.set_delay_s(val)
+        assert_almost_equal (self.o.get_delay_s(), val)
+
+    def test_get_delay_ms(self):
+        self.assertEqual(self.o.get_delay_ms(), 0.)
+
+    def test_set_delay_ms(self):
+        val = 50.
+        self.o.set_delay_ms(val)
+        assert_almost_equal (self.o.get_delay_ms(), val)
+
+    def test_get_threshold(self):
+        assert_almost_equal(self.o.get_threshold(), 0.3)
+
+    def test_set_threshold(self):
+        val = .1
+        self.o.set_threshold(val)
+        assert_almost_equal (self.o.get_threshold(), val)
+
+    def test_get_silence(self):
+        self.assertEqual(self.o.get_silence(), -90.)
+
+    def test_set_silence(self):
+        val = -50.
+        self.o.set_silence(val)
+        assert_almost_equal (self.o.get_silence(), val)
+
+    def test_get_last(self):
+        self.assertEqual(self.o.get_last(), 0.)
+
+    def test_get_last_s(self):
+        self.assertEqual(self.o.get_last_s(), 0.)
+
+    def test_get_last_ms(self):
+        self.assertEqual(self.o.get_last_ms(), 0.)
+
+    def test_get_period(self):
+        self.assertEqual(self.o.get_period(), 0.)
+
+    def test_get_period_s(self):
+        self.assertEqual(self.o.get_period_s(), 0.)
+
+    def test_get_last_tatum(self):
+        self.assertEqual(self.o.get_last_tatum(), 0.)
+
+    def test_set_tatum_signature(self):
+        self.o.set_tatum_signature(8)
+        self.o.set_tatum_signature(64)
+        self.o.set_tatum_signature(1)
+
+    def test_set_wrong_tatum_signature(self):
+        with self.assertRaises(ValueError):
+            self.o.set_tatum_signature(101)
+        with self.assertRaises(ValueError):
+            self.o.set_tatum_signature(0)
+
+if __name__ == '__main__':
+    main()
--- a/src/tempo/tempo.c
+++ b/src/tempo/tempo.c
@@ -128,8 +128,7 @@
 }
 
 uint_t aubio_tempo_set_delay_ms(aubio_tempo_t * o, smpl_t delay) {
-  o->delay = 1000. * delay * o->samplerate;
-  return AUBIO_OK;
+  return aubio_tempo_set_delay_s(o, delay / 1000.);
 }
 
 uint_t aubio_tempo_get_delay(aubio_tempo_t * o) {
@@ -141,7 +140,7 @@
 }
 
 smpl_t aubio_tempo_get_delay_ms(aubio_tempo_t * o) {
-  return o->delay / (smpl_t)(o->samplerate) / 1000.;
+  return aubio_tempo_get_delay_s(o) * 1000.;
 }
 
 uint_t aubio_tempo_set_silence(aubio_tempo_t * o, smpl_t silence) {
@@ -168,7 +167,7 @@
     uint_t buf_size, uint_t hop_size, uint_t samplerate)
 {
   aubio_tempo_t * o = AUBIO_NEW(aubio_tempo_t);
-  char_t specdesc_func[20];
+  char_t specdesc_func[PATH_MAX];
   o->samplerate = samplerate;
   // check parameters are valid
   if ((sint_t)hop_size < 1) {
@@ -203,9 +202,10 @@
   o->pp       = new_aubio_peakpicker();
   aubio_peakpicker_set_threshold (o->pp, o->threshold);
   if ( strcmp(tempo_mode, "default") == 0 ) {
-    strcpy(specdesc_func, "specflux");
+    strncpy(specdesc_func, "specflux", PATH_MAX - 1);
   } else {
-    strcpy(specdesc_func, tempo_mode);
+    strncpy(specdesc_func, tempo_mode, PATH_MAX - 1);
+    specdesc_func[PATH_MAX - 1] = '\0';
   }
   o->od       = new_aubio_specdesc(specdesc_func,buf_size);
   o->of       = new_fvec(1);
@@ -215,12 +215,17 @@
     o2 = new_aubio_specdesc(type_onset2,buffer_size);
     onset2 = new_fvec(1);
   }*/
+  if (!o->dfframe || !o->fftgrain || !o->out || !o->pv ||
+      !o->pp || !o->od || !o->of || !o->bt || !o->onset) {
+    AUBIO_ERR("tempo: failed creating tempo object\n");
+    goto beach;
+  }
   o->last_tatum = 0;
   o->tatum_signature = 4;
   return o;
 
 beach:
-  AUBIO_FREE(o);
+  del_aubio_tempo(o);
   return NULL;
 }
 
@@ -277,15 +282,23 @@
 
 void del_aubio_tempo (aubio_tempo_t *o)
 {
-  del_aubio_specdesc(o->od);
-  del_aubio_beattracking(o->bt);
-  del_aubio_peakpicker(o->pp);
-  del_aubio_pvoc(o->pv);
-  del_fvec(o->out);
-  del_fvec(o->of);
-  del_cvec(o->fftgrain);
-  del_fvec(o->dfframe);
-  del_fvec(o->onset);
+  if (o->od)
+    del_aubio_specdesc(o->od);
+  if (o->bt)
+    del_aubio_beattracking(o->bt);
+  if (o->pp)
+    del_aubio_peakpicker(o->pp);
+  if (o->pv)
+    del_aubio_pvoc(o->pv);
+  if (o->out)
+    del_fvec(o->out);
+  if (o->of)
+    del_fvec(o->of);
+  if (o->fftgrain)
+    del_cvec(o->fftgrain);
+  if (o->dfframe)
+    del_fvec(o->dfframe);
+  if (o->onset)
+    del_fvec(o->onset);
   AUBIO_FREE(o);
-  return;
 }
--- a/tests/src/tempo/test-tempo.c
+++ b/tests/src/tempo/test-tempo.c
@@ -1,14 +1,22 @@
 #include <aubio.h>
 #include "utils_tests.h"
 
+int test_wrong_params(void);
+
 int main (int argc, char **argv)
 {
   uint_t err = 0;
   if (argc < 2) {
     err = 2;
-    PRINT_ERR("not enough arguments\n");
-    PRINT_MSG("read a wave file as a mono vector\n");
-    PRINT_MSG("usage: %s <source_path> [samplerate] [win_size] [hop_size]\n", argv[0]);
+    PRINT_WRN("no arguments, running tests\n");
+    if (test_wrong_params() != 0) {
+      PRINT_ERR("tests failed!\n");
+      err = 1;
+    } else {
+      err = 0;
+    }
+    PRINT_MSG("usage: %s <source_path> [samplerate] [win_size] [hop_size]\n",
+        argv[0]);
     return err;
   }
   uint_t samplerate = 0;
@@ -20,7 +28,8 @@
   uint_t n_frames = 0, read = 0;
 
   char_t *source_path = argv[1];
-  aubio_source_t * source = new_aubio_source(source_path, samplerate, hop_size);
+  aubio_source_t * source = new_aubio_source(source_path, samplerate,
+      hop_size);
   if (!source) { err = 1; goto beach; }
 
   if (samplerate == 0 ) samplerate = aubio_source_get_samplerate(source);
@@ -30,8 +39,11 @@
   fvec_t * out = new_fvec (1); // output position
 
   // create tempo object
-  aubio_tempo_t * o = new_aubio_tempo("default", win_size, hop_size, samplerate);
+  aubio_tempo_t * o = new_aubio_tempo("default", win_size, hop_size,
+      samplerate);
 
+  if (!o) { err = 1; goto beach_tempo; }
+
   do {
     // put some fresh data in input vector
     aubio_source_do(source, in, &read);
@@ -39,9 +51,11 @@
     aubio_tempo_do(o,in,out);
     // do something with the beats
     if (out->data[0] != 0) {
-      PRINT_MSG("beat at %.3fms, %.3fs, frame %d, %.2fbpm with confidence %.2f\n",
+      PRINT_MSG("beat at %.3fms, %.3fs, frame %d, %.2f bpm "
+          "with confidence %.2f\n",
           aubio_tempo_get_last_ms(o), aubio_tempo_get_last_s(o),
-          aubio_tempo_get_last(o), aubio_tempo_get_bpm(o), aubio_tempo_get_confidence(o));
+          aubio_tempo_get_last(o), aubio_tempo_get_bpm(o),
+          aubio_tempo_get_confidence(o));
     }
     n_frames += read;
   } while ( read == hop_size );
@@ -53,6 +67,7 @@
 
   // clean up memory
   del_aubio_tempo(o);
+beach_tempo:
   del_fvec(in);
   del_fvec(out);
   del_aubio_source(source);
@@ -60,4 +75,65 @@
   aubio_cleanup();
 
   return err;
+}
+
+int test_wrong_params(void)
+{
+  uint_t win_size = 1024;
+  uint_t hop_size = 256;
+  uint_t samplerate = 44100;
+  aubio_tempo_t *t;
+  fvec_t* in, *out;
+  uint_t i;
+
+  // test wrong method fails
+  if (new_aubio_tempo("unexisting_method", win_size, hop_size, samplerate))
+    return 1;
+
+  // test hop > win fails
+  if (new_aubio_tempo("default", hop_size, win_size, samplerate))
+    return 1;
+
+  // test null hop_size fails
+  if (new_aubio_tempo("default", win_size, 0, samplerate))
+    return 1;
+
+  // test 1 buf_size fails
+  if (new_aubio_tempo("default", 1, 1, samplerate))
+    return 1;
+
+  // test null samplerate fails
+  if (new_aubio_tempo("default", win_size, hop_size, 0))
+    return 1;
+
+  // test short sizes workaround
+  t = new_aubio_tempo("default", 2048, 2048, 500);
+  if (!t)
+    return 1;
+
+  del_aubio_tempo(t);
+
+  t = new_aubio_tempo("default", win_size, hop_size, samplerate);
+  if (!t)
+    return 1;
+
+  in = new_fvec(hop_size);
+  out = new_fvec(1);
+
+  // up to step = (next_power_of_two(5.8 * samplerate / hop_size ) / 4 )
+  for (i = 0; i < 256 + 1; i++)
+  {
+    aubio_tempo_do(t,in,out);
+    PRINT_MSG("beat at %.3fms, %.3fs, frame %d, %.2f bpm "
+        "with confidence %.2f, was tatum %d\n",
+        aubio_tempo_get_last_ms(t), aubio_tempo_get_last_s(t),
+        aubio_tempo_get_last(t), aubio_tempo_get_bpm(t),
+        aubio_tempo_get_confidence(t), aubio_tempo_was_tatum(t));
+  }
+
+  del_aubio_tempo(t);
+  del_fvec(in);
+  del_fvec(out);
+
+  return 0;
 }