source: src/synth/wavetable.c @ dd15573

feature/autosinkfeature/cnnfeature/cnn_orgfeature/constantqfeature/crepefeature/crepe_orgfeature/pitchshiftfeature/pydocstringsfeature/timestretchfix/ffmpeg5pitchshiftsamplertimestretchyinfft+
Last change on this file since dd15573 was dd15573, checked in by Paul Brossier <piem@piem.org>, 11 years ago

added first version of wavetable

  • Property mode set to 100644
File size: 5.4 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 (s->freq != s->target_freq)
89        s->freq += s->inc_freq;
90      smpl_t inc = s->freq * (smpl_t)(s->wavetable_length) / (smpl_t) (s->samplerate);
91      pos += inc;
92      while (pos > s->wavetable_length) {
93        pos -= s->wavetable_length;
94      }
95      if ( ABS(s->amp - s->target_amp) > ABS(s->inc_amp) )
96        s->amp += s->inc_amp;
97      else
98        s->amp = s->target_amp;
99      output->data[i] = s->amp * interp_2(s->wavetable, pos);
100    }
101    s->last_pos = pos;
102  } else {
103    fvec_set(output, 0.);
104  }
105  // add input to output if needed
106  if (input && input != output) {
107    for (i = 0; i < output->length; i++) {
108      output->data[i] += input->data[i];
109    }
110  }
111}
112
113void aubio_wavetable_do_multi ( aubio_wavetable_t * s, fmat_t * input, fmat_t * output)
114{
115  uint_t i, j;
116  if (s->playing) {
117    smpl_t pos = s->last_pos;
118    for (j = 0; j < output->length; j++) {
119      if (s->freq != s->target_freq)
120        s->freq += s->inc_freq;
121      smpl_t inc = s->freq * (smpl_t)(s->wavetable_length) / (smpl_t) (s->samplerate);
122      pos += inc;
123      while (pos > s->wavetable_length) {
124        pos -= s->wavetable_length;
125      }
126      for (i = 0; i < output->height; i++) {
127        output->data[i][j] = interp_2(s->wavetable, pos);
128      }
129    }
130    s->last_pos = pos;
131  } else {
132    for (j = 0; j < output->length; j++) {
133      if (s->freq != s->target_freq)
134        s->freq += s->inc_freq;
135    }
136    fmat_set(output, 0.);
137  }
138  // add output to input if needed
139  if (input && input != output) {
140    for (i = 0; i < output->height; i++) {
141      for (j = 0; j < output->length; j++) {
142        output->data[i][j] += input->data[i][j];
143      }
144    }
145  }
146}
147
148uint_t aubio_wavetable_get_playing ( aubio_wavetable_t * s )
149{
150  return s->playing;
151}
152
153uint_t aubio_wavetable_set_playing ( aubio_wavetable_t * s, uint_t playing )
154{
155  s->playing = (playing == 1) ? 1 : 0;
156  return 0;
157}
158
159uint_t aubio_wavetable_play ( aubio_wavetable_t * s )
160{
161  aubio_wavetable_set_amp (s, 0.7);
162  return aubio_wavetable_set_playing (s, 1);
163}
164
165uint_t aubio_wavetable_stop ( aubio_wavetable_t * s )
166{
167  //aubio_wavetable_set_freq (s, 0.);
168  aubio_wavetable_set_amp (s, 0.);
169  //s->last_pos = 0;
170  return aubio_wavetable_set_playing (s, 1);
171}
172
173uint_t aubio_wavetable_set_freq ( aubio_wavetable_t * s, smpl_t freq )
174{
175  if (freq >= 0 && freq < s->samplerate / 2.) {
176    uint_t steps = 10;
177    s->inc_freq = (freq - s->freq) / steps; 
178    s->target_freq = freq;
179    return 0;
180  } else {
181    return 1;
182  }
183}
184
185smpl_t aubio_wavetable_get_freq ( aubio_wavetable_t * s) {
186  return s->freq;
187}
188
189uint_t aubio_wavetable_set_amp ( aubio_wavetable_t * s, smpl_t amp )
190{
191  AUBIO_MSG("amp: %f, s->amp: %f, target_amp: %f, inc_amp: %f\n",
192      amp, s->amp, s->target_amp, s->inc_amp);
193  if (amp >= 0. && amp < 1.) {
194    uint_t steps = 100;
195    s->inc_amp = (amp - s->amp) / steps; 
196    s->target_amp = amp;
197    AUBIO_ERR("amp: %f, s->amp: %f, target_amp: %f, inc_amp: %f\n",
198        amp, s->amp, s->target_amp, s->inc_amp);
199    return 0;
200  } else {
201    return 1;
202  }
203}
204
205smpl_t aubio_wavetable_get_amp ( aubio_wavetable_t * s) {
206  return s->amp;
207}
208
209void del_aubio_wavetable( aubio_wavetable_t * s )
210{
211  del_fvec(s->wavetable);
212  AUBIO_FREE(s);
213}
Note: See TracBrowser for help on using the repository browser.