Skip to content

HTTPS clone URL

Subversion checkout URL

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