source: src/synth/wavetable.c @ 8247249

feature/autosinkfeature/constantqfeature/pitchshiftfeature/pydocstringsfeature/timestretchpitchshiftsamplertimestretchyinfft+
Last change on this file since 8247249 was 8247249, checked in by Paul Brossier <piem@piem.org>, 6 years ago

src/synth/wavetable.c: fix frequency interpolation, add amp to do_multi

  • Property mode set to 100644
File size: 5.7 KB
Line 
1/*
2  Copyright (C) 2003-2013 Paul Brossier <piem@aubio.org>
3
4  This file is part of aubio.
5
6  aubio is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10
11  aubio is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  GNU General Public License for more details.
15
16  You should have received a copy of the GNU General Public License
17  along with aubio.  If not, see <http://www.gnu.org/licenses/>.
18
19*/
20
21
22#include "config.h"
23#include "aubio_priv.h"
24#include "fvec.h"
25#include "fmat.h"
26#include "io/source.h"
27#include "synth/wavetable.h"
28
29#define WAVETABLE_LEN 4096
30
31struct _aubio_wavetable_t {
32  uint_t samplerate;
33  uint_t blocksize;
34  uint_t wavetable_length;
35  fvec_t *wavetable;
36  uint_t playing;
37  smpl_t last_pos;
38
39  smpl_t target_freq;
40  smpl_t freq;
41  smpl_t inc_freq;
42
43  smpl_t target_amp;
44  smpl_t amp;
45  smpl_t inc_amp;
46};
47
48aubio_wavetable_t *new_aubio_wavetable(uint_t samplerate, uint_t blocksize)
49{
50  aubio_wavetable_t *s = AUBIO_NEW(aubio_wavetable_t);
51  uint_t i = 0;
52  s->samplerate = samplerate;
53  s->blocksize = blocksize;
54  s->wavetable_length = WAVETABLE_LEN;
55  s->wavetable = new_fvec(s->wavetable_length + 3);
56  for (i = 0; i < s->wavetable_length; i++) {
57    s->wavetable->data[i] = SIN(TWO_PI * i / (smpl_t) s->wavetable_length );
58  }
59  s->wavetable->data[s->wavetable_length] = s->wavetable->data[0];
60  s->wavetable->data[s->wavetable_length + 1] = s->wavetable->data[1];
61  s->wavetable->data[s->wavetable_length + 2] = s->wavetable->data[2];
62  s->playing = 0;
63  s->last_pos = 0.;
64  s->freq = 0.;
65  s->target_freq = 0.;
66  s->inc_freq = 0.;
67
68  s->amp = 0.;
69  s->target_amp = 0.;
70  s->inc_amp = 0.;
71  return s;
72}
73
74static smpl_t interp_2(fvec_t *input, smpl_t pos) {
75  uint_t idx = (uint_t)FLOOR(pos);
76  smpl_t frac = pos - (smpl_t)idx;
77  smpl_t a = input->data[idx];
78  smpl_t b = input->data[idx + 1];
79  return a + frac * ( b - a );
80}
81
82void aubio_wavetable_do ( aubio_wavetable_t * s, fvec_t * input, fvec_t * output)
83{
84  uint_t i;
85  if (s->playing) {
86    smpl_t pos = s->last_pos;
87    for (i = 0; i < output->length; i++) {
88      if ( ABS(s->freq - s->target_freq) > ABS(s->inc_freq) )
89        s->freq += s->inc_freq;
90      else
91        s->freq = s->target_freq;
92      smpl_t inc = s->freq * (smpl_t)(s->wavetable_length) / (smpl_t) (s->samplerate);
93      pos += inc;
94      while (pos > s->wavetable_length) {
95        pos -= s->wavetable_length;
96      }
97      if ( ABS(s->amp - s->target_amp) > ABS(s->inc_amp) )
98        s->amp += s->inc_amp;
99      else
100        s->amp = s->target_amp;
101      output->data[i] = s->amp * interp_2(s->wavetable, pos);
102    }
103    s->last_pos = pos;
104  } else {
105    fvec_set(output, 0.);
106  }
107  // add input to output if needed
108  if (input && input != output) {
109    for (i = 0; i < output->length; i++) {
110      output->data[i] += input->data[i];
111    }
112  }
113}
114
115void aubio_wavetable_do_multi ( aubio_wavetable_t * s, fmat_t * input, fmat_t * output)
116{
117  uint_t i, j;
118  if (s->playing) {
119    smpl_t pos = s->last_pos;
120    for (j = 0; j < output->length; j++) {
121      if ( ABS(s->freq - s->target_freq) > ABS(s->inc_freq) )
122        s->freq += s->inc_freq;
123      else
124        s->freq = s->target_freq;
125      smpl_t inc = s->freq * (smpl_t)(s->wavetable_length) / (smpl_t) (s->samplerate);
126      pos += inc;
127      while (pos > s->wavetable_length) {
128        pos -= s->wavetable_length;
129      }
130      if ( ABS(s->amp - s->target_amp) > ABS(s->inc_amp) )
131        s->amp += s->inc_amp;
132      else
133        s->amp = s->target_amp;
134      for (i = 0; i < output->height; i++) {
135        output->data[i][j] = s->amp * interp_2(s->wavetable, pos);
136      }
137    }
138    s->last_pos = pos;
139  } else {
140    for (j = 0; j < output->length; j++) {
141      if (s->freq != s->target_freq)
142        s->freq += s->inc_freq;
143    }
144    fmat_set(output, 0.);
145  }
146  // add output to input if needed
147  if (input && input != output) {
148    for (i = 0; i < output->height; i++) {
149      for (j = 0; j < output->length; j++) {
150        output->data[i][j] += input->data[i][j];
151      }
152    }
153  }
154}
155
156uint_t aubio_wavetable_get_playing ( aubio_wavetable_t * s )
157{
158  return s->playing;
159}
160
161uint_t aubio_wavetable_set_playing ( aubio_wavetable_t * s, uint_t playing )
162{
163  s->playing = (playing == 1) ? 1 : 0;
164  return 0;
165}
166
167uint_t aubio_wavetable_play ( aubio_wavetable_t * s )
168{
169  aubio_wavetable_set_amp (s, 0.7);
170  return aubio_wavetable_set_playing (s, 1);
171}
172
173uint_t aubio_wavetable_stop ( aubio_wavetable_t * s )
174{
175  //aubio_wavetable_set_freq (s, 0.);
176  aubio_wavetable_set_amp (s, 0.);
177  //s->last_pos = 0;
178  return aubio_wavetable_set_playing (s, 1);
179}
180
181uint_t aubio_wavetable_set_freq ( aubio_wavetable_t * s, smpl_t freq )
182{
183  if (freq >= 0 && freq < s->samplerate / 2.) {
184    uint_t steps = 10;
185    s->inc_freq = (freq - s->freq) / steps; 
186    s->target_freq = freq;
187    return 0;
188  } else {
189    return 1;
190  }
191}
192
193smpl_t aubio_wavetable_get_freq ( aubio_wavetable_t * s) {
194  return s->freq;
195}
196
197uint_t aubio_wavetable_set_amp ( aubio_wavetable_t * s, smpl_t amp )
198{
199  AUBIO_MSG("amp: %f, s->amp: %f, target_amp: %f, inc_amp: %f\n",
200      amp, s->amp, s->target_amp, s->inc_amp);
201  if (amp >= 0. && amp < 1.) {
202    uint_t steps = 100;
203    s->inc_amp = (amp - s->amp) / steps; 
204    s->target_amp = amp;
205    AUBIO_ERR("amp: %f, s->amp: %f, target_amp: %f, inc_amp: %f\n",
206        amp, s->amp, s->target_amp, s->inc_amp);
207    return 0;
208  } else {
209    return 1;
210  }
211}
212
213smpl_t aubio_wavetable_get_amp ( aubio_wavetable_t * s) {
214  return s->amp;
215}
216
217void del_aubio_wavetable( aubio_wavetable_t * s )
218{
219  del_fvec(s->wavetable);
220  AUBIO_FREE(s);
221}
Note: See TracBrowser for help on using the repository browser.