source: src/synth/wavetable.c @ 81fe7d30

feature/constantq
Last change on this file since 81fe7d30 was b669066, checked in by Paul Brossier <piem@piem.org>, 8 years ago

src/synth/wavetable.c: always clamp 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 "aubio_priv.h"
23#include "fvec.h"
24#include "fmat.h"
25#include "utils/parameter.h"
26#include "synth/wavetable.h"
27
28#define WAVETABLE_LEN 4096
29
30struct _aubio_wavetable_t {
31  uint_t samplerate;
32  uint_t blocksize;
33  uint_t wavetable_length;
34  fvec_t *wavetable;
35  uint_t playing;
36  smpl_t last_pos;
37
38  aubio_parameter_t *freq;
39  aubio_parameter_t *amp;
40};
41
42aubio_wavetable_t *new_aubio_wavetable(uint_t samplerate, uint_t blocksize)
43{
44  uint_t i = 0;
45  aubio_wavetable_t *s = AUBIO_NEW(aubio_wavetable_t);
46  if ((sint_t)samplerate <= 0) {
47    AUBIO_ERR("Can not create wavetable with samplerate %d\n", samplerate);
48    goto beach;
49  }
50  s->samplerate = samplerate;
51  s->blocksize = blocksize;
52  s->wavetable_length = WAVETABLE_LEN;
53  s->wavetable = new_fvec(s->wavetable_length + 3);
54  for (i = 0; i < s->wavetable_length; i++) {
55    s->wavetable->data[i] = SIN(TWO_PI * i / (smpl_t) s->wavetable_length );
56  }
57  s->wavetable->data[s->wavetable_length] = s->wavetable->data[0];
58  s->wavetable->data[s->wavetable_length + 1] = s->wavetable->data[1];
59  s->wavetable->data[s->wavetable_length + 2] = s->wavetable->data[2];
60  s->playing = 0;
61  s->last_pos = 0.;
62  s->freq = new_aubio_parameter( 0., s->samplerate / 2., 10 );
63  s->amp = new_aubio_parameter( 0., 1., 100 );
64  return s;
65beach:
66  AUBIO_FREE(s);
67  return NULL;
68}
69
70static smpl_t interp_2(const fvec_t *input, smpl_t pos) {
71  uint_t idx = (uint_t)FLOOR(pos);
72  smpl_t frac = pos - (smpl_t)idx;
73  smpl_t a = input->data[idx];
74  smpl_t b = input->data[idx + 1];
75  return a + frac * ( b - a );
76}
77
78void aubio_wavetable_do ( aubio_wavetable_t * s, const fvec_t * input, fvec_t * output)
79{
80  uint_t i;
81  if (s->playing) {
82    smpl_t pos = s->last_pos;
83    for (i = 0; i < output->length; i++) {
84      smpl_t inc = aubio_parameter_get_next_value( s->freq );
85      inc *= (smpl_t)(s->wavetable_length) / (smpl_t) (s->samplerate);
86      pos += inc;
87      while (pos > s->wavetable_length) {
88        pos -= s->wavetable_length;
89      }
90      output->data[i] = aubio_parameter_get_next_value ( s->amp );
91      output->data[i] *= interp_2(s->wavetable, pos);
92    }
93    s->last_pos = pos;
94  } else {
95    for (i = 0; i < output->length; i++) {
96      aubio_parameter_get_next_value ( s->freq );
97      aubio_parameter_get_next_value ( s->amp );
98    }
99    fvec_zeros (output);
100  }
101  // add input to output if needed
102  if (input && input != output) {
103    for (i = 0; i < output->length; i++) {
104      output->data[i] += input->data[i];
105    }
106    fvec_clamp(output, 1.);
107  }
108}
109
110void aubio_wavetable_do_multi ( aubio_wavetable_t * s, const fmat_t * input, fmat_t * output)
111{
112  uint_t i, j;
113  if (s->playing) {
114    smpl_t pos = s->last_pos;
115    for (j = 0; j < output->length; j++) {
116      smpl_t inc = aubio_parameter_get_next_value( s->freq );
117      smpl_t amp = aubio_parameter_get_next_value ( s->amp );
118      inc *= (smpl_t)(s->wavetable_length) / (smpl_t) (s->samplerate);
119      pos += inc;
120      while (pos > s->wavetable_length) {
121        pos -= s->wavetable_length;
122      }
123      for (i = 0; i < output->height; i++) {
124        output->data[i][j] = amp * interp_2(s->wavetable, pos);
125      }
126    }
127    s->last_pos = pos;
128  } else {
129    for (j = 0; j < output->length; j++) {
130      aubio_parameter_get_next_value ( s->freq );
131      aubio_parameter_get_next_value ( s->amp );
132    }
133    fmat_zeros (output);
134  }
135  // add output to input if needed
136  if (input && input != output) {
137    for (i = 0; i < output->height; i++) {
138      for (j = 0; j < output->length; j++) {
139        output->data[i][j] += input->data[i][j];
140      }
141    }
142  }
143}
144
145uint_t aubio_wavetable_get_playing ( const aubio_wavetable_t * s )
146{
147  return s->playing;
148}
149
150uint_t aubio_wavetable_set_playing ( aubio_wavetable_t * s, uint_t playing )
151{
152  s->playing = (playing == 1) ? 1 : 0;
153  return 0;
154}
155
156uint_t aubio_wavetable_play ( aubio_wavetable_t * s )
157{
158  aubio_wavetable_set_amp (s, 0.7);
159  return aubio_wavetable_set_playing (s, 1);
160}
161
162uint_t aubio_wavetable_stop ( aubio_wavetable_t * s )
163{
164  //aubio_wavetable_set_freq (s, 0.);
165  aubio_wavetable_set_amp (s, 0.);
166  //s->last_pos = 0;
167  return aubio_wavetable_set_playing (s, 1);
168}
169
170uint_t aubio_wavetable_set_freq ( aubio_wavetable_t * s, smpl_t freq )
171{
172  return aubio_parameter_set_target_value ( s->freq, freq );
173}
174
175smpl_t aubio_wavetable_get_freq ( const aubio_wavetable_t * s) {
176  return aubio_parameter_get_current_value ( s->freq);
177}
178
179uint_t aubio_wavetable_set_amp ( aubio_wavetable_t * s, smpl_t amp )
180{
181  return aubio_parameter_set_target_value ( s->amp, amp );
182}
183
184smpl_t aubio_wavetable_get_amp ( const aubio_wavetable_t * s) {
185  return aubio_parameter_get_current_value ( s->amp );
186}
187
188void del_aubio_wavetable( aubio_wavetable_t * s )
189{
190  del_aubio_parameter(s->freq);
191  del_aubio_parameter(s->amp);
192  del_fvec(s->wavetable);
193  AUBIO_FREE(s);
194}
Note: See TracBrowser for help on using the repository browser.