src/synth/wavetable.c: make sure samplerate is valid
[aubio.git] / src / synth / wavetable.c
index b89af1e..86497ae 100644 (file)
@@ -23,7 +23,7 @@
 #include "aubio_priv.h"
 #include "fvec.h"
 #include "fmat.h"
-#include "io/source.h"
+#include "utils/parameter.h"
 #include "synth/wavetable.h"
 
 #define WAVETABLE_LEN 4096
@@ -36,18 +36,17 @@ struct _aubio_wavetable_t {
   uint_t playing;
   smpl_t last_pos;
 
-  smpl_t target_freq;
-  smpl_t freq;
-  smpl_t inc_freq;
-
-  smpl_t target_amp;
-  smpl_t amp;
-  smpl_t inc_amp;
+  aubio_parameter_t *freq;
+  aubio_parameter_t *amp;
 };
 
 aubio_wavetable_t *new_aubio_wavetable(uint_t samplerate, uint_t blocksize)
 {
   aubio_wavetable_t *s = AUBIO_NEW(aubio_wavetable_t);
+  if ((sint_t)samplerate <= 0) {
+    AUBIO_ERR("Can not create wavetable with samplerate %d\n", samplerate);
+    goto beach;
+  }
   uint_t i = 0;
   s->samplerate = samplerate;
   s->blocksize = blocksize;
@@ -61,14 +60,12 @@ aubio_wavetable_t *new_aubio_wavetable(uint_t samplerate, uint_t blocksize)
   s->wavetable->data[s->wavetable_length + 2] = s->wavetable->data[2];
   s->playing = 0;
   s->last_pos = 0.;
-  s->freq = 0.;
-  s->target_freq = 0.;
-  s->inc_freq = 0.;
-
-  s->amp = 0.;
-  s->target_amp = 0.;
-  s->inc_amp = 0.;
+  s->freq = new_aubio_parameter( 0., s->samplerate / 2., 10 );
+  s->amp = new_aubio_parameter( 0., 1., 100 );
   return s;
+beach:
+  AUBIO_FREE(s);
+  return NULL;
 }
 
 static smpl_t interp_2(fvec_t *input, smpl_t pos) {
@@ -85,21 +82,21 @@ void aubio_wavetable_do ( aubio_wavetable_t * s, fvec_t * input, fvec_t * output
   if (s->playing) {
     smpl_t pos = s->last_pos;
     for (i = 0; i < output->length; i++) {
-      if (s->freq != s->target_freq)
-        s->freq += s->inc_freq;
-      smpl_t inc = s->freq * (smpl_t)(s->wavetable_length) / (smpl_t) (s->samplerate);
+      smpl_t inc = aubio_parameter_get_next_value( s->freq );
+      inc *= (smpl_t)(s->wavetable_length) / (smpl_t) (s->samplerate);
       pos += inc;
       while (pos > s->wavetable_length) {
         pos -= s->wavetable_length;
       }
-      if ( ABS(s->amp - s->target_amp) > ABS(s->inc_amp) )
-        s->amp += s->inc_amp;
-      else
-        s->amp = s->target_amp;
-      output->data[i] = s->amp * interp_2(s->wavetable, pos);
+      output->data[i] = aubio_parameter_get_next_value ( s->amp );
+      output->data[i] *= interp_2(s->wavetable, pos);
     }
     s->last_pos = pos;
   } else {
+    for (i = 0; i < output->length; i++) {
+      aubio_parameter_get_next_value ( s->freq );
+      aubio_parameter_get_next_value ( s->amp );
+    }
     fvec_set(output, 0.);
   }
   // add input to output if needed
@@ -116,22 +113,22 @@ void aubio_wavetable_do_multi ( aubio_wavetable_t * s, fmat_t * input, fmat_t *
   if (s->playing) {
     smpl_t pos = s->last_pos;
     for (j = 0; j < output->length; j++) {
-      if (s->freq != s->target_freq)
-        s->freq += s->inc_freq;
-      smpl_t inc = s->freq * (smpl_t)(s->wavetable_length) / (smpl_t) (s->samplerate);
+      smpl_t inc = aubio_parameter_get_next_value( s->freq );
+      inc *= (smpl_t)(s->wavetable_length) / (smpl_t) (s->samplerate);
       pos += inc;
       while (pos > s->wavetable_length) {
         pos -= s->wavetable_length;
       }
+      smpl_t amp = aubio_parameter_get_next_value ( s->amp );
       for (i = 0; i < output->height; i++) {
-        output->data[i][j] = interp_2(s->wavetable, pos);
+        output->data[i][j] = amp * interp_2(s->wavetable, pos);
       }
     }
     s->last_pos = pos;
   } else {
     for (j = 0; j < output->length; j++) {
-      if (s->freq != s->target_freq)
-        s->freq += s->inc_freq;
+      aubio_parameter_get_next_value ( s->freq );
+      aubio_parameter_get_next_value ( s->amp );
     }
     fmat_set(output, 0.);
   }
@@ -172,42 +169,26 @@ uint_t aubio_wavetable_stop ( aubio_wavetable_t * s )
 
 uint_t aubio_wavetable_set_freq ( aubio_wavetable_t * s, smpl_t freq )
 {
-  if (freq >= 0 && freq < s->samplerate / 2.) {
-    uint_t steps = 10;
-    s->inc_freq = (freq - s->freq) / steps; 
-    s->target_freq = freq;
-    return 0;
-  } else {
-    return 1;
-  }
+  return aubio_parameter_set_target_value ( s->freq, freq );
 }
 
 smpl_t aubio_wavetable_get_freq ( aubio_wavetable_t * s) {
-  return s->freq;
+  return aubio_parameter_get_current_value ( s->freq);
 }
 
 uint_t aubio_wavetable_set_amp ( aubio_wavetable_t * s, smpl_t amp )
 {
-  AUBIO_MSG("amp: %f, s->amp: %f, target_amp: %f, inc_amp: %f\n",
-      amp, s->amp, s->target_amp, s->inc_amp);
-  if (amp >= 0. && amp < 1.) {
-    uint_t steps = 100;
-    s->inc_amp = (amp - s->amp) / steps; 
-    s->target_amp = amp;
-    AUBIO_ERR("amp: %f, s->amp: %f, target_amp: %f, inc_amp: %f\n",
-        amp, s->amp, s->target_amp, s->inc_amp);
-    return 0;
-  } else {
-    return 1;
-  }
+  return aubio_parameter_set_target_value ( s->amp, amp );
 }
 
 smpl_t aubio_wavetable_get_amp ( aubio_wavetable_t * s) {
-  return s->amp;
+  return aubio_parameter_get_current_value ( s->amp );
 }
 
 void del_aubio_wavetable( aubio_wavetable_t * s )
 {
+  del_aubio_parameter(s->freq);
+  del_aubio_parameter(s->amp);
   del_fvec(s->wavetable);
   AUBIO_FREE(s);
 }