shithub: aubio

Download patch

ref: 4cb2d5418ce1306edbb3f0f81932a6cdec728ca0
parent: 00c9444330525961aeeba7daafca0b8da5740ea3
parent: 1c565c030cd8675306a2647622b17ef529e3045d
author: Paul Brossier <piem@piem.org>
date: Fri Dec 21 15:06:39 EST 2018

Merge branch 'feature/sink_flac' into feature/autosink

--- a/.travis.yml
+++ b/.travis.yml
@@ -2,24 +2,24 @@
 
 matrix:
   include:
-    - python: 3.5
+    - python: 3.6
       os: linux
       compiler: gcc
-    - python: 3.4
+    - python: 3.5
       os: linux
       compiler: gcc
     - python: 2.7
       os: linux
       compiler: gcc
-    - python: "pypy"
+    - python: "pypy3.5"
       os: linux
       compiler: gcc
       env: CFLAGS="-Os" WAFOPTS="--disable-avcodec"
-    - python: 3.5
+    - python: 3.6
       os: linux
       compiler: gcc
       env: CFLAGS="-Os" WAFOPTS="--disable-samplerate"
-    - python: 3.4
+    - python: 3.5
       os: linux
       compiler: gcc
       env: HAVE_AUBIO_DOUBLE=1 CFLAGS="-O3" WAFOPTS="--enable-fftw3"
--- a/examples/utils.c
+++ b/examples/utils.c
@@ -184,7 +184,8 @@
         total_read, blocks, hop_size, source_uri, samplerate);
 
     del_aubio_source (this_source);
-    del_aubio_sink   (this_sink);
+    if (this_sink)
+      del_aubio_sink   (this_sink);
 
   }
 }
--- a/python/ext/py-filter.c
+++ b/python/ext/py-filter.c
@@ -109,7 +109,8 @@
 Py_filter_del (Py_filter * self)
 {
   Py_XDECREF(self->out);
-  del_aubio_filter (self->o);
+  if (self->o)
+    del_aubio_filter (self->o);
   Py_TYPE(self)->tp_free ((PyObject *) self);
 }
 
--- a/python/ext/py-sink.c
+++ b/python/ext/py-sink.c
@@ -150,8 +150,10 @@
 static void
 Py_sink_del (Py_sink *self, PyObject *unused)
 {
-  del_aubio_sink(self->o);
-  free(self->mwrite_data.data);
+  if (self->o) {
+    del_aubio_sink(self->o);
+    free(self->mwrite_data.data);
+  }
   if (self->uri) {
     free(self->uri);
   }
--- a/python/ext/py-source.c
+++ b/python/ext/py-source.c
@@ -436,6 +436,10 @@
   /* compute _do function */
   aubio_source_do (self->o, &(self->c_read_to), &read);
 
+  if (PyErr_Occurred() != NULL) {
+    return NULL;
+  }
+
   outputs = PyTuple_New(2);
   PyTuple_SetItem( outputs, 0, self->read_to );
   PyTuple_SetItem( outputs, 1, (PyObject *)PyLong_FromLong(read));
@@ -457,6 +461,10 @@
   /* compute _do function */
   aubio_source_do_multi (self->o, &(self->c_mread_to), &read);
 
+  if (PyErr_Occurred() != NULL) {
+    return NULL;
+  }
+
   outputs = PyTuple_New(2);
   PyTuple_SetItem( outputs, 0, self->mread_to);
   PyTuple_SetItem( outputs, 1, (PyObject *)PyLong_FromLong(read));
@@ -573,9 +581,7 @@
       return vec;
     } else if (PyLong_AsLong(size) > 0) {
       // short read, return a shorter array
-      PyArrayObject *shortread = (PyArrayObject*)
-        PyArray_FROM_OTF(PyTuple_GetItem(done, 0), NPY_NOTYPE,
-            NPY_ARRAY_ENSURECOPY);
+      PyArrayObject *shortread = (PyArrayObject*)PyTuple_GetItem(done, 0);
       PyArray_Dims newdims;
       PyObject *reshaped;
       newdims.len = PyArray_NDIM(shortread);
--- a/python/tests/test_source.py
+++ b/python/tests/test_source.py
@@ -23,22 +23,36 @@
 
 _debug = False
 
-class Test_aubio_source_test_case(object):
+class Test_aubio_source_test_case(TestCase):
 
-    @parametrize('filename', list_of_sounds)
-    def test_close_file(self, filename):
+    def setUp(self):
+        if not default_test_sound:
+            skipTest(no_sounds_msg)
+
+    def test_close_file(self):
         samplerate = 0 # use native samplerate
         hop_size = 256
-        f = source(filename, samplerate, hop_size)
+        f = source(default_test_sound, samplerate, hop_size)
         f.close()
 
-    @parametrize('filename', list_of_sounds)
-    def test_close_file_twice(self, filename):
+    def test_close_file_twice(self):
         samplerate = 0 # use native samplerate
         hop_size = 256
-        f = source(filename, samplerate, hop_size)
+        f = source(default_test_sound, samplerate, hop_size)
         f.close()
         f.close()
+
+    def test_read_after_close(self):
+        samplerate = 0 # use native samplerate
+        hop_size = 256
+        f = source(default_test_sound, samplerate, hop_size)
+        read, frames = f()
+        f.close()
+        with assert_raises(RuntimeError):
+            read, frames = f()
+        with assert_raises(RuntimeError):
+            read, frames = f.do_multi()
+
 
 class Test_aubio_source_read(object):
 
--- a/scripts/build_apple_frameworks
+++ b/scripts/build_apple_frameworks
@@ -13,7 +13,7 @@
 # add git abbreviated commit hash
 #VERSION+=+$(git log --pretty=format:"%h" -1)
 
-CFLAGS="-Werror -Ofast"
+CFLAGS="-Werror -Os"
 WAFCONF="--disable-sndfile --disable-avcodec --disable-samplerate --enable-fat" # --disable-memcpy --disable-accelerate"
 
 export VERSION
--- a/src/io/sink.c
+++ b/src/io/sink.c
@@ -216,7 +216,7 @@
 
 void del_aubio_sink(aubio_sink_t * s) {
   AUBIO_ASSERT(s);
-  if (s->s_del && s->sink)
+  if (s && s->s_del && s->sink)
     s->s_del((void *)s->sink);
   AUBIO_FREE(s);
 }
--- a/src/io/source.c
+++ b/src/io/source.c
@@ -139,7 +139,7 @@
 
 void del_aubio_source(aubio_source_t * s) {
   AUBIO_ASSERT(s);
-  if (s->s_del && s->source)
+  if (s && s->s_del && s->source)
     s->s_del((void *)s->source);
   AUBIO_FREE(s);
 }
--- a/src/io/source_apple_audio.c
+++ b/src/io/source_apple_audio.c
@@ -344,7 +344,7 @@
     AUBIO_ERROR("source_apple_audio: Failed getting %s duration, "
         "error in ExtAudioFileGetProperty (%s)\n", s->path,
         getPrintableOSStatusError(errorstr, err));
-    return err;
+    return 0;
   }
   return (uint_t)fileLengthFrames;
 }
--- a/src/io/source_avcodec.c
+++ b/src/io/source_avcodec.c
@@ -491,6 +491,12 @@
   uint_t total_wrote = 0;
   uint_t length = aubio_source_validate_input_length("source_avcodec", s->path,
       s->hop_size, read_data->length);
+  if (!s->avr || !s->avFormatCtx || !s->avCodecCtx) {
+    AUBIO_ERR("source_avcodec: could not read from %s (file was closed)\n",
+        s->path);
+    *read= 0;
+    return;
+  }
   while (total_wrote < length) {
     end = MIN(s->read_samples - s->read_index, length - total_wrote);
     for (i = 0; i < end; i++) {
@@ -529,6 +535,12 @@
       s->hop_size, read_data->length);
   uint_t channels = aubio_source_validate_input_channels("source_avcodec",
       s->path, s->input_channels, read_data->height);
+  if (!s->avr || !s->avFormatCtx || !s->avCodecCtx) {
+    AUBIO_ERR("source_avcodec: could not read from %s (file was closed)\n",
+        s->path);
+    *read= 0;
+    return;
+  }
   while (total_wrote < length) {
     end = MIN(s->read_samples - s->read_index, length - total_wrote);
     for (j = 0; j < channels; j++) {
--- a/src/io/source_sndfile.c
+++ b/src/io/source_sndfile.c
@@ -174,6 +174,12 @@
       s->hop_size, read_data->length);
   sf_count_t read_samples = aubio_sf_read_smpl (s->handle, s->scratch_data,
       s->scratch_size);
+  if (!s->handle) {
+    AUBIO_ERR("source_sndfile: could not read from %s (file was closed)\n",
+        s->path);
+    *read = 0;
+    return;
+  }
 
   uint_t read_length = read_samples / s->input_channels;
 
@@ -219,6 +225,12 @@
       s->path, s->input_channels, read_data->height);
   sf_count_t read_samples = aubio_sf_read_smpl (s->handle, s->scratch_data,
       s->scratch_size);
+  if (!s->handle) {
+    AUBIO_ERR("source_sndfile: could not read from %s (file was closed)\n",
+        s->path);
+    *read = 0;
+    return;
+  }
 
   uint_t read_length = read_samples / s->input_channels;
 
--- a/tests/src/io/base-sink_custom.h
+++ b/tests/src/io/base-sink_custom.h
@@ -151,6 +151,9 @@
   // delete temp file
   close_temp_sink(sink_path, fd);
 
+  // shouldn't crash on null (bypassed, only check del_aubio_sink)
+  // del_aubio_sink_custom(NULL);
+
   return run_on_default_source_and_sink(base_main);
 }
 
--- a/tests/src/io/base-source_custom.h
+++ b/tests/src/io/base-source_custom.h
@@ -141,9 +141,20 @@
   // test closing the file a second time
   aubio_source_custom_close(s);
 
+  // reading after close fails
+  del_fvec(vec);
+  vec = new_fvec(hop_size);
+  aubio_source_custom_do(s, vec, &read);
+  del_fmat(mat);
+  mat = new_fmat(channels, hop_size);
+  aubio_source_custom_do_multi(s, mat, &read);
+
   del_aubio_source_custom(s);
   del_fmat(mat);
   del_fvec(vec);
+
+  // shouldn't crash on null (bypassed, only check del_aubio_source)
+  // del_aubio_source_custom(NULL);
 
   return run_on_default_source(base_main);
 }
--- a/tests/src/io/test-sink.c
+++ b/tests/src/io/test-sink.c
@@ -147,5 +147,8 @@
   // delete temp file
   close_temp_sink(sink_path, fd);
 
+  // shouldn't crash on null
+  del_aubio_sink(NULL);
+
   return run_on_default_source_and_sink(main);
 }
--- a/tests/src/io/test-source.c
+++ b/tests/src/io/test-source.c
@@ -137,9 +137,20 @@
   // test closing the file a second time
   aubio_source_close(s);
 
+  // reading after close fails
+  del_fvec(vec);
+  vec = new_fvec(hop_size);
+  aubio_source_do(s, vec, &read);
+  del_fmat(mat);
+  mat = new_fmat(channels, hop_size);
+  aubio_source_do_multi(s, mat, &read);
+
   del_aubio_source(s);
   del_fmat(mat);
   del_fvec(vec);
+
+  // shouldn't crash on null
+  del_aubio_source(NULL);
 
   return run_on_default_source(main);
 }
--- a/tests/src/test-cvec.c
+++ b/tests/src/test-cvec.c
@@ -3,46 +3,75 @@
 
 int main (void)
 {
-  uint_t i, window_size = 16; // window size
-  cvec_t * complex_vector = new_cvec (window_size); // input buffer
-  uint_t rand_times = 4;
+  uint_t i, window_size = 16;
+  cvec_t * complex_vector = new_cvec(window_size);
+  cvec_t * other_cvector = new_cvec(window_size);
 
-  utils_init_random();
+  assert(cvec_norm_get_data(complex_vector) == complex_vector->norm);
+  assert(cvec_phas_get_data(complex_vector) == complex_vector->phas);
+  assert(complex_vector->length == window_size / 2 + 1);
 
-  while (rand_times -- ) {
-    // fill with random phas and norm
-    for ( i = 0; i < complex_vector->length; i++ ) {
-      complex_vector->norm[i] = ( 2. / RAND_MAX * random() - 1. );
-      complex_vector->phas[i] = ( 2. / RAND_MAX * random() - 1. ) * M_PI;
-    }
-    // print the vector
-    cvec_print(complex_vector);
+  // all elements are initialized to 0
+  for ( i = 0; i < complex_vector->length; i++ ) {
+    assert( complex_vector->norm[i] == 0. );
+    assert( complex_vector->phas[i] == 0. );
   }
 
-  // set all vector elements to `0`
-  cvec_norm_zeros(complex_vector);
+  cvec_norm_set_sample(complex_vector, 2., 1);
+  assert(cvec_norm_get_sample(complex_vector, 1));
+
+  cvec_phas_set_sample(complex_vector, 2., 1);
+  assert(cvec_phas_get_sample(complex_vector, 1));
+
+  cvec_print(complex_vector);
+
+  // set all norm and phas elements to 0
+  cvec_zeros(complex_vector);
   for ( i = 0; i < complex_vector->length; i++ ) {
     assert( complex_vector->norm[i] == 0. );
-    // assert( complex_vector->phas[i] == 0 );
+    assert( complex_vector->phas[i] == 0. );
   }
-  cvec_print(complex_vector);
 
-  // set all vector elements to `1`
+  // set all norm elements to 1
   cvec_norm_ones(complex_vector);
   for ( i = 0; i < complex_vector->length; i++ ) {
     assert( complex_vector->norm[i] == 1. );
-    // assert( complex_vector->phas[i] == 0 );
   }
-  cvec_print(complex_vector);
 
-  cvec_zeros(complex_vector);
-  cvec_phas_zeros(complex_vector);
+  // set all norm elements to 0
   cvec_norm_zeros(complex_vector);
-  cvec_norm_ones(complex_vector);
+  for ( i = 0; i < complex_vector->length; i++ ) {
+    assert( complex_vector->norm[i] == 0. );
+  }
+
+  // set all phas elements to 1
   cvec_phas_ones(complex_vector);
+  for ( i = 0; i < complex_vector->length; i++ ) {
+    assert( complex_vector->phas[i] == 1. );
+  }
+
+  // set all phas elements to 0
+  cvec_phas_zeros(complex_vector);
+  for ( i = 0; i < complex_vector->length; i++ ) {
+    assert( complex_vector->phas[i] == 0. );
+  }
+
+  cvec_copy(complex_vector, other_cvector);
+  // copy to self
   cvec_copy(complex_vector, complex_vector);
+  // copy to a different size fails
+  del_cvec(other_cvector);
+  other_cvector = new_cvec(window_size + 2);
+  cvec_copy(complex_vector, other_cvector);
 
-  // destroy it
-  del_cvec(complex_vector);
+  if (complex_vector)
+    del_cvec(complex_vector);
+  if (other_cvector)
+    del_cvec(other_cvector);
+
+  // wrong parameters
+  assert(new_cvec(-1) == NULL);
+  assert(new_cvec(0) == NULL);
+
   return 0;
 }
--- a/tests/src/test-fmat.c
+++ b/tests/src/test-fmat.c
@@ -4,27 +4,93 @@
 // create a new matrix and fill it with i * 1. + j * .1, where i is the row,
 // and j the column.
 
-int main (void)
+void assert_fmat_all_equal(fmat_t *mat, smpl_t scalar)
 {
-  uint_t height = 3, length = 9, i, j;
-  // create fmat_t object
-  fmat_t * mat = new_fmat (height, length);
+  uint_t i, j;
   for ( i = 0; i < mat->height; i++ ) {
     for ( j = 0; j < mat->length; j++ ) {
+      assert(mat->data[i][j] == scalar);
+    }
+  }
+}
+
+int main (void)
+{
+  uint_t i, j;
+  uint_t height = 3, length = 9;
+
+  // create fmat_t object
+  fmat_t * mat = new_fmat(height, length);
+  fmat_t * other_mat = new_fmat(height, length);
+
+  assert(mat);
+  assert(other_mat);
+
+  assert(mat->length == length);
+  assert(mat->height == height);
+
+  for (i = 0; i < mat->height; i++) {
+    for (j = 0; j < mat->length; j++) {
       // all elements are already initialized to 0.
       assert(mat->data[i][j] == 0);
       // setting element of row i, column j
-      mat->data[i][j] = i * 1. + j *.1;
+      mat->data[i][j] = i * 10. + j;
     }
   }
+
+  // print out matrix
+  fmat_print(mat);
+
+  // helpers
+  fmat_rev(mat);
+  fmat_print(mat);
+  for (i = 0; i < mat->height; i++) {
+    for (j = 0; j < mat->length; j++) {
+      assert(mat->data[i][j] == i * 10. + mat->length - 1. - j);
+    }
+  }
+
+  fmat_set_sample(mat, 3, 1, 1);
+  assert(fmat_get_sample(mat, 1, 1) == 3.);
+
+  fmat_ones(mat);
+  assert_fmat_all_equal(mat, 1.);
+
+  fmat_set(other_mat, .5);
+  assert_fmat_all_equal(other_mat, .5);
+
+  fmat_weight(mat, other_mat);
+  assert_fmat_all_equal(mat, .5);
+
   fvec_t channel_onstack;
   fvec_t *channel = &channel_onstack;
   fmat_get_channel(mat, 1, channel);
-  fvec_print (channel);
-  // print out matrix
-  fmat_print(mat);
-  // destroy it
-  del_fmat(mat);
+  assert(channel->data == mat->data[1]);
+
+  // copy of the same size
+  fmat_copy(mat, other_mat);
+  del_fmat(other_mat);
+
+  // copy to undersized
+  other_mat = new_fmat(height - 1, length);
+  fmat_copy(mat, other_mat);
+  del_fmat(other_mat);
+
+  // copy from undersized
+  other_mat = new_fmat(height, length + 1);
+  fmat_copy(mat, other_mat);
+
+  // wrong parameters
+  assert(new_fmat(-1, length) == NULL);
+  assert(new_fmat(height, -1) == NULL);
+
+  // methods for wrappers with opaque structure
+  assert (fmat_get_channel_data(mat, 0) == mat->data[0]);
+  assert (fmat_get_data(mat) == mat->data);
+
+  if (mat)
+    del_fmat(mat);
+  if (other_mat)
+    del_fmat(other_mat);
   return 0;
 }
-
--- a/tests/src/test-fvec.c
+++ b/tests/src/test-fvec.c
@@ -1,13 +1,27 @@
 #include "aubio.h"
 #include "utils_tests.h"
 
+void assert_fvec_all_equal(fvec_t *vec, smpl_t scalar)
+{
+  uint_t i;
+  for (i = 0; i < vec->length; i++) {
+    assert(vec->data[i] == scalar);
+  }
+}
+
 int main (void)
 {
-  uint_t vec_size = 10, i;
-  fvec_t * vec = new_fvec (vec_size);
+  uint_t length = 10;
+  uint_t i;
 
+  fvec_t * vec = new_fvec (length);
+  fvec_t * other_vec = new_fvec (length);
+
+  assert (vec);
+  assert (other_vec);
+
   // vec->length matches requested size
-  assert(vec->length == vec_size);
+  assert(vec->length == length);
 
   // all elements are initialized to `0.`
   for ( i = 0; i < vec->length; i++ ) {
@@ -14,20 +28,14 @@
     assert(vec->data[i] == 0.);
   }
 
-  // all elements can be set to `0.`
-  fvec_zeros(vec);
-  for ( i = 0; i < vec->length; i++ ) {
-    assert(vec->data[i] == 0.);
-  }
-  fvec_print(vec);
-
   // all elements can be set to `1.`
   fvec_ones(vec);
-  for ( i = 0; i < vec->length; i++ ) {
-    assert(vec->data[i] == 1.);
-  }
-  fvec_print(vec);
+  assert_fvec_all_equal(vec, 1.);
 
+  // all elements can be set to `0.`
+  fvec_zeros(vec);
+  assert_fvec_all_equal(vec, 0.);
+
   // each element can be accessed directly
   for ( i = 0; i < vec->length; i++ ) {
     vec->data[i] = i;
@@ -35,9 +43,31 @@
   }
   fvec_print(vec);
 
-  // now destroys the vector
-  del_fvec(vec);
+  fvec_set_sample(vec, 3, 2);
+  assert(fvec_get_sample(vec, 2) == 3);
 
+  assert(fvec_get_data(vec) == vec->data);
+
+  // wrong parameters
+  assert(new_fvec(-1) == NULL);
+
+  // copy to an identical size works
+  fvec_copy(vec, other_vec);
+  del_fvec(other_vec);
+
+  // copy to a different size fail
+  other_vec = new_fvec(length + 1);
+  fvec_copy(vec, other_vec);
+  del_fvec(other_vec);
+
+  // copy to a different size fail
+  other_vec = new_fvec(length - 1);
+  fvec_copy(vec, other_vec);
+
+  // now destroys the vector
+  if (vec)
+    del_fvec(vec);
+  if (other_vec)
+    del_fvec(other_vec);
   return 0;
 }
-
--- a/tests/src/test-lvec.c
+++ b/tests/src/test-lvec.c
@@ -1,18 +1,47 @@
 #include "aubio.h"
 #include "utils_tests.h"
 
+void assert_lvec_all_equal(lvec_t *vec, lsmp_t scalar)
+{
+  uint_t i;
+  for (i = 0; i < vec->length; i++) {
+    assert(vec->data[i] == scalar);
+  }
+}
+
 int main (void)
 {
-  uint_t win_s = 32; // window size
-  lvec_t * sp = new_lvec (win_s); // input buffer
-  lvec_set_sample (sp, 2./3., 0);
-  PRINT_MSG(AUBIO_LSMP_FMT "\n", lvec_get_sample (sp, 0));
-  lvec_print (sp);
-  lvec_ones (sp);
-  lvec_print (sp);
-  lvec_set_all (sp, 3./5.);
-  lvec_print (sp);
-  del_lvec(sp);
+  uint_t length = 32; // window size
+
+  lvec_t * vec = new_lvec (length); // input buffer
+
+  assert(vec);
+
+  assert(vec->length == length);
+
+  lvec_set_sample (vec, 3., 0);
+  assert(lvec_get_sample(vec, 0) == 3.);
+
+  assert(lvec_get_data(vec) == vec->data);
+
+  lvec_print (vec);
+  // note AUBIO_LSMP_FMT can be used to print lsmp_t
+  PRINT_MSG(AUBIO_LSMP_FMT "\n", lvec_get_sample (vec, 0));
+
+  lvec_set_all (vec, 2.);
+  assert_lvec_all_equal(vec, 2.);
+
+  lvec_ones (vec);
+  assert_lvec_all_equal(vec, 1.);
+
+  lvec_zeros (vec);
+  assert_lvec_all_equal(vec, 0.);
+
+  del_lvec(vec);
+
+  // wrong parameters
+  assert(new_lvec(0) == NULL);
+  assert(new_lvec(-1) == NULL);
+
   return 0;
 }
-
--- a/tests/src/test-mathutils-window.c
+++ b/tests/src/test-mathutils-window.c
@@ -7,8 +7,8 @@
   uint_t n_length = 4, n_types = 10, i, t;
   uint_t lengths[4] = { 8, 10, 15, 16 };
   char *method = "default";
-  char *window_types[10] = { "default",
-    "rectangle", "hamming", "hanning", "hanningz",
+  char *window_types[11] = { "default",
+    "ones", "rectangle", "hamming", "hanning", "hanningz",
     "blackman", "blackman_harris", "gaussian", "welch", "parzen"};
 
   for ( t = 0; t < n_types; t ++ ) {
@@ -26,6 +26,10 @@
       del_fvec(window);
     }
   }
+
+  assert (new_aubio_window("parzen", -1) == NULL);
+  assert (new_aubio_window(NULL, length) == NULL);
+  assert (new_aubio_window("\0", length) == NULL);
   return 0;
 }
 
--- /dev/null
+++ b/tests/src/test-vecutils.c
@@ -1,0 +1,65 @@
+#include "aubio.h"
+#include "utils_tests.h"
+
+void assert_fvec_all_almost_equal(fvec_t *vec, smpl_t scalar, smpl_t err)
+{
+  uint_t i;
+  for (i = 0; i < vec->length; i++) {
+    assert( fabs(vec->data[i] - scalar) < (smpl_t)err );
+  }
+}
+
+int main (void)
+{
+  uint_t length = 10;
+
+  fvec_t * vec = new_fvec(length);
+
+  fvec_set_all(vec, 2);
+  fvec_exp(vec);
+  assert_fvec_all_almost_equal(vec, exp(2), 1e-10);
+
+  fvec_set_all(vec, 0);
+  fvec_cos(vec);
+  assert_fvec_all_almost_equal(vec, 1., 1e-10);
+
+  fvec_set_all(vec, 0);
+  fvec_sin(vec);
+  assert_fvec_all_almost_equal(vec, 0., 1e-10);
+
+  fvec_set_all(vec, -1);
+  fvec_abs(vec);
+  assert_fvec_all_almost_equal(vec, 1., 1e-10);
+
+  fvec_set_all(vec, 4);
+  fvec_sqrt(vec);
+  assert_fvec_all_almost_equal(vec, 2., 1e-10);
+
+  fvec_set_all(vec, 10.);
+  fvec_log10(vec);
+  assert_fvec_all_almost_equal(vec, 1., 1e-10);
+
+  fvec_set_all(vec, 1.);
+  fvec_log(vec);
+  assert_fvec_all_almost_equal(vec, 0., 1e-10);
+
+  fvec_set_all(vec, 1.6);
+  fvec_floor(vec);
+  assert_fvec_all_almost_equal(vec, 1., 1e-10);
+
+  fvec_set_all(vec, 1.6);
+  fvec_ceil(vec);
+  assert_fvec_all_almost_equal(vec, 2., 1e-10);
+
+  fvec_set_all(vec, 1.6);
+  fvec_round(vec);
+  assert_fvec_all_almost_equal(vec, 2., 1e-10);
+
+  fvec_set_all(vec, 2);
+  fvec_pow(vec, 3);
+  assert_fvec_all_almost_equal(vec, 8., 1e-10);
+
+  if (vec)
+    del_fvec(vec);
+  return 0;
+}
--- a/wscript
+++ b/wscript
@@ -437,7 +437,7 @@
 
     # check for vorbisenc
     if (ctx.options.enable_vorbis != False):
-        ctx.check_cfg(package = 'vorbisenc',
+        ctx.check_cfg(package = 'vorbisenc vorbis ogg',
                 args = '--cflags --libs',
                 uselib_store = 'VORBISENC',
                 mandatory = ctx.options.enable_vorbis)