Skip to content
Newer
Older
100644 432 lines (370 sloc) 11.1 KB
f4296e1 @yaxu foo
yaxu authored
1 #include <pthread.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <sys/time.h>
5 #include <jack/jack.h>
cf3bb79 @yaxu working and broken again
yaxu authored
6 #include <math.h>
7 #include <assert.h>
ab0fe60 @yaxu there
yaxu authored
8
fb7aa5b @yaxu foo
yaxu authored
9 #include "config.h"
f4296e1 @yaxu foo
yaxu authored
10 #include "jack.h"
11 #include "audio.h"
12
fb689a4 @yaxu panning and sample interpellation
yaxu authored
13 #define HALF_PI 1.5707963267948966
14
cf3bb79 @yaxu working and broken again
yaxu authored
15 pthread_mutex_t queue_waiting_lock;
f4296e1 @yaxu foo
yaxu authored
16
1afd593 @yaxu twiddles
yaxu authored
17 t_sound *waiting = NULL;
18 t_sound *playing = NULL;
f4296e1 @yaxu foo
yaxu authored
19
fb7aa5b @yaxu foo
yaxu authored
20 #ifdef FEEDBACK
5898624 @yaxu audio input
yaxu authored
21 t_loop *loop = NULL;
fb7aa5b @yaxu foo
yaxu authored
22 #endif
5898624 @yaxu audio input
yaxu authored
23
82f4f04 @yaxu works better
yaxu authored
24 double epochOffset = 0;
f4296e1 @yaxu foo
yaxu authored
25
26 jack_client_t *client = NULL;
5898624 @yaxu audio input
yaxu authored
27 static int samplerate = 0;
f4296e1 @yaxu foo
yaxu authored
28
29 extern void audio_init(void) {
cf3bb79 @yaxu working and broken again
yaxu authored
30 pthread_mutex_init(&queue_waiting_lock, NULL);
f4296e1 @yaxu foo
yaxu authored
31 client = jack_start(audio_callback);
32 samplerate = jack_get_sample_rate(client);
33 file_set_samplerate(samplerate);
fb7aa5b @yaxu foo
yaxu authored
34 #ifdef FEEDBACK
5898624 @yaxu audio input
yaxu authored
35 loop = new_loop(8);
fb7aa5b @yaxu foo
yaxu authored
36 #endif
f4296e1 @yaxu foo
yaxu authored
37 }
38
1afd593 @yaxu twiddles
yaxu authored
39 int queue_size(t_sound *queue) {
cf3bb79 @yaxu working and broken again
yaxu authored
40 int result = 0;
41 while (queue != NULL) {
42 result++;
43 queue = queue->next;
749ecaa @yaxu foo
yaxu authored
44 if (result > 4096) {
cf3bb79 @yaxu working and broken again
yaxu authored
45 printf("whoops, big queue\n");
46 break;
47 }
48 }
49 return(result);
50 }
51
1afd593 @yaxu twiddles
yaxu authored
52 void queue_add(t_sound **queue, t_sound *new) {
53 //printf("queuing %s @ %lld\n", new->samplename, new->start);
cf3bb79 @yaxu working and broken again
yaxu authored
54 int s = queue_size(*queue);
55 int added = 0;
56 if (*queue == NULL) {
57 *queue = new;
58 assert(s == (queue_size(*queue) - 1));
59 added++;
f4296e1 @yaxu foo
yaxu authored
60 }
61 else {
1afd593 @yaxu twiddles
yaxu authored
62 t_sound *tmp = *queue;
cf3bb79 @yaxu working and broken again
yaxu authored
63 assert(tmp->prev == NULL);
f4296e1 @yaxu foo
yaxu authored
64
cf3bb79 @yaxu working and broken again
yaxu authored
65 int i =0;
66 while (1) {
82f4f04 @yaxu works better
yaxu authored
67 if (tmp->startFrame > new->startFrame) {
cf3bb79 @yaxu working and broken again
yaxu authored
68 // insert in front of later event
f4296e1 @yaxu foo
yaxu authored
69 new->next = tmp;
cf3bb79 @yaxu working and broken again
yaxu authored
70 new->prev = tmp->prev;
71 if (new->prev != NULL) {
72 new->prev->next = new;
73 }
74 else {
75 *queue = new;
f4296e1 @yaxu foo
yaxu authored
76 }
cf3bb79 @yaxu working and broken again
yaxu authored
77 tmp->prev = new;
f4296e1 @yaxu foo
yaxu authored
78
cf3bb79 @yaxu working and broken again
yaxu authored
79 if (s != (queue_size(*queue) - 1)) {
80 assert(s == (queue_size(*queue) - 1));
f4296e1 @yaxu foo
yaxu authored
81 }
cf3bb79 @yaxu working and broken again
yaxu authored
82 added++;
f4296e1 @yaxu foo
yaxu authored
83 break;
84 }
85
cf3bb79 @yaxu working and broken again
yaxu authored
86 if (tmp->next == NULL) {
87 // add to end of queue
88 tmp->next = new;
89 new->prev = tmp;
90 added++;
91 assert(s == (queue_size(*queue) - 1));
92 break;
93 }
94 ++i;
f4296e1 @yaxu foo
yaxu authored
95 tmp = tmp->next;
96 }
97 }
98
cf3bb79 @yaxu working and broken again
yaxu authored
99 if (s != (queue_size(*queue) - added)) {
100 assert(s == (queue_size(*queue) - added));
f4296e1 @yaxu foo
yaxu authored
101 }
cf3bb79 @yaxu working and broken again
yaxu authored
102 assert(added == 1);
103 }
104
105
1afd593 @yaxu twiddles
yaxu authored
106 void queue_remove(t_sound **queue, t_sound *old) {
cf3bb79 @yaxu working and broken again
yaxu authored
107 int s = queue_size(*queue);
108 if (old->prev == NULL) {
109 *queue = old->next;
110 if (*queue != NULL) {
111 (*queue)->prev = NULL;
112 }
f4296e1 @yaxu foo
yaxu authored
113 }
cf3bb79 @yaxu working and broken again
yaxu authored
114 else {
115 old->prev->next = old->next;
116
117 if (old->next) {
118 old->next->prev = old->prev;
119 }
f4296e1 @yaxu foo
yaxu authored
120 }
cf3bb79 @yaxu working and broken again
yaxu authored
121 assert(s == (queue_size(*queue) + 1));
1afd593 @yaxu twiddles
yaxu authored
122 free(old);
f4296e1 @yaxu foo
yaxu authored
123 }
124
4441b0f @yaxu aha
yaxu authored
125 const double coeff[5][11]= {
126 { 3.11044e-06,
127 8.943665402, -36.83889529, 92.01697887, -154.337906, 181.6233289,
128 -151.8651235, 89.09614114, -35.10298511, 8.388101016, -0.923313471
129 },
130 {4.36215e-06,
131 8.90438318, -36.55179099, 91.05750846, -152.422234, 179.1170248,
132 -149.6496211,87.78352223, -34.60687431, 8.282228154, -0.914150747
133 },
134 { 3.33819e-06,
135 8.893102966, -36.49532826, 90.96543286, -152.4545478, 179.4835618,
136 -150.315433, 88.43409371, -34.98612086, 8.407803364, -0.932568035
137 },
138 {1.13572e-06,
139 8.994734087, -37.2084849, 93.22900521, -156.6929844, 184.596544,
140 -154.3755513, 90.49663749, -35.58964535, 8.478996281, -0.929252233
141 },
142 {4.09431e-07,
143 8.997322763, -37.20218544, 93.11385476, -156.2530937, 183.7080141,
144 -153.2631681, 89.59539726, -35.12454591, 8.338655623, -0.910251753
145 }
146 };
147
148 float formant_filter(float in, t_sound *sound, int channel) {
149 float res =
150 (float) ( coeff[sound->formant_vowelnum][0] * in +
151 coeff[sound->formant_vowelnum][1] * sound->formant_history[channel][0] +
152 coeff[sound->formant_vowelnum][2] * sound->formant_history[channel][1] +
153 coeff[sound->formant_vowelnum][3] * sound->formant_history[channel][2] +
154 coeff[sound->formant_vowelnum][4] * sound->formant_history[channel][3] +
155 coeff[sound->formant_vowelnum][5] * sound->formant_history[channel][4] +
156 coeff[sound->formant_vowelnum][6] * sound->formant_history[channel][5] +
157 coeff[sound->formant_vowelnum][7] * sound->formant_history[channel][6] +
158 coeff[sound->formant_vowelnum][8] * sound->formant_history[channel][7] +
159 coeff[sound->formant_vowelnum][9] * sound->formant_history[channel][8] +
160 coeff[sound->formant_vowelnum][10] * sound->formant_history[channel][9]
161 );
162
163 sound->formant_history[channel][9] = sound->formant_history[channel][8];
164 sound->formant_history[channel][8] = sound->formant_history[channel][7];
165 sound->formant_history[channel][7] = sound->formant_history[channel][6];
166 sound->formant_history[channel][6] = sound->formant_history[channel][5];
167 sound->formant_history[channel][5] = sound->formant_history[channel][4];
168 sound->formant_history[channel][4] = sound->formant_history[channel][3];
169 sound->formant_history[channel][3] = sound->formant_history[channel][2];
170 sound->formant_history[channel][2] = sound->formant_history[channel][1];
171 sound->formant_history[channel][1] = sound->formant_history[channel][0];
172 sound->formant_history[channel][0] = (double) res;
173 return res;
174 }
175
749ecaa @yaxu foo
yaxu authored
176 extern int audio_play(double when, char *samplename, float offset, float start, float end, float speed, float pan, float velocity, int vowelnum) {
4441b0f @yaxu aha
yaxu authored
177 struct timeval tv;
fb7aa5b @yaxu foo
yaxu authored
178 #ifdef FEEDBACK
5898624 @yaxu audio input
yaxu authored
179 int is_loop = 0;
fb7aa5b @yaxu foo
yaxu authored
180 #endif
5898624 @yaxu audio input
yaxu authored
181 t_sample *sample = NULL;
182 t_sound *new;
183
4441b0f @yaxu aha
yaxu authored
184 gettimeofday(&tv, NULL);
1afd593 @yaxu twiddles
yaxu authored
185
4441b0f @yaxu aha
yaxu authored
186
fb7aa5b @yaxu foo
yaxu authored
187 #ifdef FEEDBACK
5898624 @yaxu audio input
yaxu authored
188 if (strcmp(samplename, "loop") == 0) {
189 is_loop = 1;
190 }
191 else {
fb7aa5b @yaxu foo
yaxu authored
192 #endif
5898624 @yaxu audio input
yaxu authored
193 sample = file_get(samplename);
194 if (sample == NULL) {
195 return(0);
196 }
fb7aa5b @yaxu foo
yaxu authored
197 #ifdef FEEDBACK
5898624 @yaxu audio input
yaxu authored
198 }
fb7aa5b @yaxu foo
yaxu authored
199 #endif
5898624 @yaxu audio input
yaxu authored
200
201 new = (t_sound *) calloc(1, sizeof(t_sound));
202 printf("samplename: %s when: %f\n", samplename, when - (float) tv.tv_sec);
203 strncpy(new->samplename, samplename, MAXPATHSIZE);
204
fb7aa5b @yaxu foo
yaxu authored
205 #ifdef FEEDBACK
5898624 @yaxu audio input
yaxu authored
206 if (is_loop) {
207 new->loop = loop;
208 new->frames = loop->frames;
209 new->items = loop->items;
210 new->channels = 1;
211 new->loop_start = (loop->now + (loop->frames / 2)) % loop->frames;
212 }
213 else {
fb7aa5b @yaxu foo
yaxu authored
214 #endif
5898624 @yaxu audio input
yaxu authored
215 new->sample = sample;
216 new->frames = sample->info->frames;
217 new->items = sample->items;
218 new->channels = sample->info->channels;
fb7aa5b @yaxu foo
yaxu authored
219 #ifdef FEEDBACK
5898624 @yaxu audio input
yaxu authored
220 }
221 new->is_loop = is_loop;
fb7aa5b @yaxu foo
yaxu authored
222 #endif
4441b0f @yaxu aha
yaxu authored
223
5898624 @yaxu audio input
yaxu authored
224 new->startFrame =
225 jack_time_to_frames(client, ((when-epochOffset) * 1000000));
226
227 new->next = NULL;
228 new->prev = NULL;
229 new->startframe = 0;
230 new->speed = speed;
231 new->pan = pan;
232 new->velocity = velocity;
233
234 new->offset = offset;
f4296e1 @yaxu foo
yaxu authored
235
5898624 @yaxu audio input
yaxu authored
236 printf("frames: %f\n", new->frames);
237 if (start > 0 && start <= 1) {
238 new->startframe = start * new->frames;
f4296e1 @yaxu foo
yaxu authored
239 }
5898624 @yaxu audio input
yaxu authored
240
241 if (end > 0 && end < 1) {
242 new->frames *= end;
243 }
244
245 if (new->speed == 0) {
246 new->speed = 1;
247 }
248
249 if (new->speed < 0) {
250 new->startframe = new->frames - new->startframe;
251 }
252
253 new->position = new->startframe;
254 new->formant_vowelnum = vowelnum;
255
256 pthread_mutex_lock(&queue_waiting_lock);
257 queue_add(&waiting, new);
258 //printf("added: %d\n", waiting != NULL);
259 pthread_mutex_unlock(&queue_waiting_lock);
260
261 return(1);
f4296e1 @yaxu foo
yaxu authored
262 }
263
1afd593 @yaxu twiddles
yaxu authored
264 t_sound *queue_next(t_sound **queue, jack_nframes_t now) {
265 t_sound *result = NULL;
82f4f04 @yaxu works better
yaxu authored
266 if (*queue != NULL && (*queue)->startFrame <= now) {
cf3bb79 @yaxu working and broken again
yaxu authored
267 result = *queue;
268 *queue = (*queue)->next;
269 if ((*queue) != NULL) {
270 (*queue)->prev = NULL;
271 }
f4296e1 @yaxu foo
yaxu authored
272 }
cf3bb79 @yaxu working and broken again
yaxu authored
273
f4296e1 @yaxu foo
yaxu authored
274 return(result);
275 }
276
cf3bb79 @yaxu working and broken again
yaxu authored
277 void dequeue(jack_nframes_t now) {
1afd593 @yaxu twiddles
yaxu authored
278 t_sound *p;
cf3bb79 @yaxu working and broken again
yaxu authored
279 pthread_mutex_lock(&queue_waiting_lock);
280 while ((p = queue_next(&waiting, now)) != NULL) {
281 int s = queue_size(playing);
1afd593 @yaxu twiddles
yaxu authored
282 //printf("dequeuing %s @ %d\n", p->samplename, p->startFrame);
cf3bb79 @yaxu working and broken again
yaxu authored
283 p->prev = NULL;
f4296e1 @yaxu foo
yaxu authored
284 p->next = playing;
285 if (playing != NULL) {
cf3bb79 @yaxu working and broken again
yaxu authored
286 playing->prev = p;
f4296e1 @yaxu foo
yaxu authored
287 }
288 playing = p;
cf3bb79 @yaxu working and broken again
yaxu authored
289 assert(s == (queue_size(playing) - 1));
290
291 //printf("done.\n");
f4296e1 @yaxu foo
yaxu authored
292 }
cf3bb79 @yaxu working and broken again
yaxu authored
293 pthread_mutex_unlock(&queue_waiting_lock);
f4296e1 @yaxu foo
yaxu authored
294 }
295
cf3bb79 @yaxu working and broken again
yaxu authored
296
297 inline void playback(float **buffers, int frame, jack_nframes_t frametime) {
298 int channel;
1afd593 @yaxu twiddles
yaxu authored
299 t_sound *p = playing;
cf3bb79 @yaxu working and broken again
yaxu authored
300
301 for (channel = 0; channel < CHANNELS; ++channel) {
302 buffers[channel][frame] = 0;
303 }
fb689a4 @yaxu panning and sample interpellation
yaxu authored
304
cf3bb79 @yaxu working and broken again
yaxu authored
305 while (p != NULL) {
306 int channels;
1afd593 @yaxu twiddles
yaxu authored
307 t_sound *tmp;
fb689a4 @yaxu panning and sample interpellation
yaxu authored
308
82f4f04 @yaxu works better
yaxu authored
309 //printf("compare start %d with frametime %d\n", p->startFrame, frametime);
310 if (p->startFrame > frametime) {
cf3bb79 @yaxu working and broken again
yaxu authored
311 p = p->next;
312 continue;
313 }
1afd593 @yaxu twiddles
yaxu authored
314 //printf("playing %s\n", p->samplename);
5898624 @yaxu audio input
yaxu authored
315 channels = p->channels;
cf3bb79 @yaxu working and broken again
yaxu authored
316 //printf("channels: %d\n", channels);
317 for (channel = 0; channel < channels; ++channel) {
4441b0f @yaxu aha
yaxu authored
318 float roundoff = 1;
5898624 @yaxu audio input
yaxu authored
319 float value;
320
fb7aa5b @yaxu foo
yaxu authored
321 #ifdef FEEDBACK
5898624 @yaxu audio input
yaxu authored
322 if (p->is_loop) {
323 // only one channel, but relative to 'now'
324 unsigned int i = (p->loop_start + ((int) p->position)) % p->loop->frames;
325 value = p->items[i];
326 }
327 else {
fb7aa5b @yaxu foo
yaxu authored
328 #endif
5898624 @yaxu audio input
yaxu authored
329 value = p->items[(channels * ((int) p->position)) + channel];
fb7aa5b @yaxu foo
yaxu authored
330 #ifdef FEEDBACK
5898624 @yaxu audio input
yaxu authored
331 }
fb7aa5b @yaxu foo
yaxu authored
332 #endif
5898624 @yaxu audio input
yaxu authored
333
4441b0f @yaxu aha
yaxu authored
334 int pos = ((int) p->position) + 1;
fb7aa5b @yaxu foo
yaxu authored
335 #ifdef FEEDBACK
5898624 @yaxu audio input
yaxu authored
336 if ((!p->is_loop) && pos < p->frames) {
fb7aa5b @yaxu foo
yaxu authored
337 #else
338 if (pos < p->frames) {
339 #endif
340 float next =
5898624 @yaxu audio input
yaxu authored
341 p->items[(channels * pos)
342 + channel
343 ];
fb689a4 @yaxu panning and sample interpellation
yaxu authored
344 float tween_amount = (p->position - (int) p->position);
4441b0f @yaxu aha
yaxu authored
345
346
fb689a4 @yaxu panning and sample interpellation
yaxu authored
347 /* linear interpolation */
348 value += (next - value) * tween_amount;
349 }
350
4441b0f @yaxu aha
yaxu authored
351 if (p->formant_vowelnum >= 0) {
352 value = formant_filter(value, p, 0);
353 }
354
355 if ((p->frames - p->position) < ROUNDOFF) {
356 // TODO what frames < ROUNDOFF?)
357 //printf("roundoff: %f\n", (p->frames - pos) / (float) ROUNDOFF);
358 roundoff = (p->frames - pos) / (float) ROUNDOFF;
359 }
030581c @yaxu ramp up
yaxu authored
360 else {
361 if ((pos - p->startframe) < ROUNDOFF) {
362 roundoff = (pos - p->startframe) / (float) ROUNDOFF;
363 }
364 }
4441b0f @yaxu aha
yaxu authored
365 value *= roundoff;
366
fb689a4 @yaxu panning and sample interpellation
yaxu authored
367 float c = (float) channel + p->pan;
368 float d = c - floor(c);
369 int channel_a = ((int) c) % CHANNELS;
370 int channel_b = ((int) c + 1) % CHANNELS;
371
372 if (channel_a < 0) {
373 channel_a += CHANNELS;
374 }
375 if (channel_b < 0) {
376 channel_b += CHANNELS;
377 }
378
4441b0f @yaxu aha
yaxu authored
379 // equal power panning
462f67d @yaxu bugfix panning
yaxu authored
380 buffers[channel_a][frame] += value * cos(HALF_PI * d);
381 buffers[channel_b][frame] += value * sin(HALF_PI * d);
cf3bb79 @yaxu working and broken again
yaxu authored
382 }
383
384 p->position += p->speed;
6356ffd @yaxu more
yaxu authored
385 //printf("position: %d of %d\n", p->position, playing->frames);
cf3bb79 @yaxu working and broken again
yaxu authored
386
387 /* remove dead sounds */
388 tmp = p;
389 p = p->next;
4441b0f @yaxu aha
yaxu authored
390 if (tmp->speed > 0) {
391 if (tmp->position >= tmp->frames) {
392 //printf("remove %s\n", tmp->samplename);
393 queue_remove(&playing, tmp);
394 }
395 }
396 else {
397 if (tmp->position <= 0) {
398 //printf("remove %s\n", tmp->samplename);
399 queue_remove(&playing, tmp);
400 }
cf3bb79 @yaxu working and broken again
yaxu authored
401 }
402 }
403 }
404
5898624 @yaxu audio input
yaxu authored
405 extern int audio_callback(int frames, float *input, float **outputs) {
ab0fe60 @yaxu there
yaxu authored
406 int i;
cf3bb79 @yaxu working and broken again
yaxu authored
407 jack_nframes_t now;
408
82f4f04 @yaxu works better
yaxu authored
409 if (epochOffset == 0) {
f4296e1 @yaxu foo
yaxu authored
410 struct timeval tv;
411 gettimeofday(&tv, NULL);
82f4f04 @yaxu works better
yaxu authored
412 epochOffset = ((double) tv.tv_sec + ((double) tv.tv_usec / 1000000.0))
cf3bb79 @yaxu working and broken again
yaxu authored
413 - ((double) jack_get_time() / 1000000.0);
82f4f04 @yaxu works better
yaxu authored
414 //printf("jack time: %d tv_sec %d epochOffset: %f\n", jack_get_time(), tv.tv_sec, epochOffset);
f4296e1 @yaxu foo
yaxu authored
415 }
cf3bb79 @yaxu working and broken again
yaxu authored
416 now = jack_last_frame_time(client);
417
f4296e1 @yaxu foo
yaxu authored
418 for (i=0; i < frames; ++i) {
fb7aa5b @yaxu foo
yaxu authored
419 #ifdef FEEDBACK
5898624 @yaxu audio input
yaxu authored
420 loop->items[loop->now++] = input[i];
fb7aa5b @yaxu foo
yaxu authored
421
5898624 @yaxu audio input
yaxu authored
422 if (loop->now >= loop->frames) {
423 loop->now = 0;
424 }
fb7aa5b @yaxu foo
yaxu authored
425 #endif
cf3bb79 @yaxu working and broken again
yaxu authored
426 dequeue(now + frames);
427
5898624 @yaxu audio input
yaxu authored
428 playback(outputs, i, now + i);
ab0fe60 @yaxu there
yaxu authored
429 }
430 return(0);
431 }
Something went wrong with that request. Please try again.