Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 240 lines (204 sloc) 5.702 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
cf3bb79 @yaxu working and broken again
yaxu authored
12 pthread_mutex_t queue_waiting_lock;
f4296e1 @yaxu foo
yaxu authored
13
14 t_queue *waiting = NULL;
15 t_queue *playing = NULL;
16
82f4f04 @yaxu works better
yaxu authored
17 double epochOffset = 0;
f4296e1 @yaxu foo
yaxu authored
18
19 jack_client_t *client = NULL;
20
21 extern void audio_init(void) {
22 int samplerate;
23
cf3bb79 @yaxu working and broken again
yaxu authored
24 pthread_mutex_init(&queue_waiting_lock, NULL);
f4296e1 @yaxu foo
yaxu authored
25 client = jack_start(audio_callback);
26 samplerate = jack_get_sample_rate(client);
27 file_set_samplerate(samplerate);
28 }
29
cf3bb79 @yaxu working and broken again
yaxu authored
30 int queue_size(t_queue *queue) {
31 int result = 0;
32 while (queue != NULL) {
33 result++;
34 queue = queue->next;
35 if (result > 1024) {
36 printf("whoops, big queue\n");
37 break;
38 }
39 }
40 return(result);
41 }
42
43 void queue_add(t_queue **queue, t_queue *new) {
44 //printf("queuing %s @ %lld\n", new->sound->samplename, new->start);
45 int s = queue_size(*queue);
46 int added = 0;
47 if (*queue == NULL) {
48 *queue = new;
49 assert(s == (queue_size(*queue) - 1));
50 added++;
f4296e1 @yaxu foo
yaxu authored
51 }
52 else {
cf3bb79 @yaxu working and broken again
yaxu authored
53 t_queue *tmp = *queue;
54 assert(tmp->prev == NULL);
f4296e1 @yaxu foo
yaxu authored
55
cf3bb79 @yaxu working and broken again
yaxu authored
56 int i =0;
57 while (1) {
82f4f04 @yaxu works better
yaxu authored
58 if (tmp->startFrame > new->startFrame) {
cf3bb79 @yaxu working and broken again
yaxu authored
59 // insert in front of later event
f4296e1 @yaxu foo
yaxu authored
60 new->next = tmp;
cf3bb79 @yaxu working and broken again
yaxu authored
61 new->prev = tmp->prev;
62 if (new->prev != NULL) {
63 new->prev->next = new;
64 }
65 else {
66 *queue = new;
f4296e1 @yaxu foo
yaxu authored
67 }
cf3bb79 @yaxu working and broken again
yaxu authored
68 tmp->prev = new;
f4296e1 @yaxu foo
yaxu authored
69
cf3bb79 @yaxu working and broken again
yaxu authored
70 if (s != (queue_size(*queue) - 1)) {
71 assert(s == (queue_size(*queue) - 1));
f4296e1 @yaxu foo
yaxu authored
72 }
cf3bb79 @yaxu working and broken again
yaxu authored
73 added++;
f4296e1 @yaxu foo
yaxu authored
74 break;
75 }
76
cf3bb79 @yaxu working and broken again
yaxu authored
77 if (tmp->next == NULL) {
78 // add to end of queue
79 tmp->next = new;
80 new->prev = tmp;
81 added++;
82 assert(s == (queue_size(*queue) - 1));
83 break;
84 }
85 ++i;
f4296e1 @yaxu foo
yaxu authored
86 tmp = tmp->next;
87 }
88 }
89
cf3bb79 @yaxu working and broken again
yaxu authored
90 if (s != (queue_size(*queue) - added)) {
91 assert(s == (queue_size(*queue) - added));
f4296e1 @yaxu foo
yaxu authored
92 }
cf3bb79 @yaxu working and broken again
yaxu authored
93 assert(added == 1);
94 }
95
96
97 void queue_remove(t_queue **queue, t_queue *old) {
98 int s = queue_size(*queue);
99 if (old->prev == NULL) {
100 *queue = old->next;
101 if (*queue != NULL) {
102 (*queue)->prev = NULL;
103 }
f4296e1 @yaxu foo
yaxu authored
104 }
cf3bb79 @yaxu working and broken again
yaxu authored
105 else {
106 old->prev->next = old->next;
107
108 if (old->next) {
109 old->next->prev = old->prev;
110 }
f4296e1 @yaxu foo
yaxu authored
111 }
cf3bb79 @yaxu working and broken again
yaxu authored
112 assert(s == (queue_size(*queue) + 1));
113 //free(old);
f4296e1 @yaxu foo
yaxu authored
114 }
115
82f4f04 @yaxu works better
yaxu authored
116 extern int audio_play(double when, char *samplename, float offset, float duration, float speed) {
f4296e1 @yaxu foo
yaxu authored
117 int result = 0;
118 t_sound *sound;
119 t_sample *sample = file_get(samplename);
cf3bb79 @yaxu working and broken again
yaxu authored
120 //printf("samplename: %s when: %f\n", samplename, when);
f4296e1 @yaxu foo
yaxu authored
121 if (sample != NULL) {
cf3bb79 @yaxu working and broken again
yaxu authored
122 //printf("got\n");
f4296e1 @yaxu foo
yaxu authored
123 t_queue *new;
124
cf3bb79 @yaxu working and broken again
yaxu authored
125 sound = (t_sound *) calloc(1, sizeof(t_sound));
f4296e1 @yaxu foo
yaxu authored
126 strncpy(sound->samplename, samplename, MAXPATHSIZE);
127 sound->sample = sample;
128
cf3bb79 @yaxu working and broken again
yaxu authored
129 new = (t_queue *) calloc(1, sizeof(t_queue));
82f4f04 @yaxu works better
yaxu authored
130 new->startFrame = jack_time_to_frames(client, ((when-epochOffset) * 1000000));
cf3bb79 @yaxu working and broken again
yaxu authored
131 //printf("start: %lld\n", new->start);
f4296e1 @yaxu foo
yaxu authored
132 new->sound = sound;
133 new->next = NULL;
cf3bb79 @yaxu working and broken again
yaxu authored
134 new->prev = NULL;
f4296e1 @yaxu foo
yaxu authored
135 new->position = 0;
136 new->speed = 1;
137
cf3bb79 @yaxu working and broken again
yaxu authored
138 pthread_mutex_lock(&queue_waiting_lock);
139 queue_add(&waiting, new);
140 //printf("added: %d\n", waiting != NULL);
141 pthread_mutex_unlock(&queue_waiting_lock);
f4296e1 @yaxu foo
yaxu authored
142
143 result = 1;
144 }
145 return(result);
146 }
147
cf3bb79 @yaxu working and broken again
yaxu authored
148 t_queue *queue_next(t_queue **queue, jack_nframes_t now) {
f4296e1 @yaxu foo
yaxu authored
149 t_queue *result = NULL;
82f4f04 @yaxu works better
yaxu authored
150 if (*queue != NULL && (*queue)->startFrame <= now) {
cf3bb79 @yaxu working and broken again
yaxu authored
151 result = *queue;
152 *queue = (*queue)->next;
153 if ((*queue) != NULL) {
154 (*queue)->prev = NULL;
155 }
f4296e1 @yaxu foo
yaxu authored
156 }
cf3bb79 @yaxu working and broken again
yaxu authored
157
f4296e1 @yaxu foo
yaxu authored
158 return(result);
159 }
160
cf3bb79 @yaxu working and broken again
yaxu authored
161 void dequeue(jack_nframes_t now) {
f4296e1 @yaxu foo
yaxu authored
162 t_queue *p;
cf3bb79 @yaxu working and broken again
yaxu authored
163 pthread_mutex_lock(&queue_waiting_lock);
164 while ((p = queue_next(&waiting, now)) != NULL) {
165 int s = queue_size(playing);
82f4f04 @yaxu works better
yaxu authored
166 //printf("dequeuing %s @ %d\n", p->sound->samplename, p->startFrame);
cf3bb79 @yaxu working and broken again
yaxu authored
167 p->prev = NULL;
f4296e1 @yaxu foo
yaxu authored
168 p->next = playing;
169 if (playing != NULL) {
cf3bb79 @yaxu working and broken again
yaxu authored
170 playing->prev = p;
f4296e1 @yaxu foo
yaxu authored
171 }
172 playing = p;
cf3bb79 @yaxu working and broken again
yaxu authored
173 assert(s == (queue_size(playing) - 1));
174
175 //printf("done.\n");
f4296e1 @yaxu foo
yaxu authored
176 }
cf3bb79 @yaxu working and broken again
yaxu authored
177 pthread_mutex_unlock(&queue_waiting_lock);
f4296e1 @yaxu foo
yaxu authored
178 }
179
cf3bb79 @yaxu working and broken again
yaxu authored
180
181 inline void playback(float **buffers, int frame, jack_nframes_t frametime) {
182 int channel;
183 t_queue *p = playing;
184
185 for (channel = 0; channel < CHANNELS; ++channel) {
186 buffers[channel][frame] = 0;
187 }
188 //printf("ah\n");
189 while (p != NULL) {
190 int channels;
191 t_queue *tmp;
82f4f04 @yaxu works better
yaxu authored
192 //printf("compare start %d with frametime %d\n", p->startFrame, frametime);
193 if (p->startFrame > frametime) {
cf3bb79 @yaxu working and broken again
yaxu authored
194 p = p->next;
195 continue;
196 }
197 //printf("playing %s\n", p->sound->samplename);
198 channels = p->sound->sample->info->channels;
199 //printf("channels: %d\n", channels);
200 for (channel = 0; channel < channels; ++channel) {
201 /* todo tween */
202 buffers[channel][frame] +=
e46d783 @yaxu works more again
yaxu authored
203 p->sound->sample->items[(channels * ((int) p->position)) + channel];
cf3bb79 @yaxu working and broken again
yaxu authored
204 }
205
206 p->position += p->speed;
207 //printf("position: %d of %d\n", p->position, playing->sound->sample->info->frames);
208
209 /* remove dead sounds */
210 tmp = p;
211 p = p->next;
212 if (tmp->position >= tmp->sound->sample->info->frames) {
213 //printf("remove %s\n", tmp->sound->samplename);
214 queue_remove(&playing, tmp);
215 }
216 }
217 }
218
219 extern int audio_callback(int frames, float **buffers) {
ab0fe60 @yaxu there
yaxu authored
220 int i;
cf3bb79 @yaxu working and broken again
yaxu authored
221 jack_nframes_t now;
222
82f4f04 @yaxu works better
yaxu authored
223 if (epochOffset == 0) {
f4296e1 @yaxu foo
yaxu authored
224 struct timeval tv;
225 gettimeofday(&tv, NULL);
82f4f04 @yaxu works better
yaxu authored
226 epochOffset = ((double) tv.tv_sec + ((double) tv.tv_usec / 1000000.0))
cf3bb79 @yaxu working and broken again
yaxu authored
227 - ((double) jack_get_time() / 1000000.0);
82f4f04 @yaxu works better
yaxu authored
228 //printf("jack time: %d tv_sec %d epochOffset: %f\n", jack_get_time(), tv.tv_sec, epochOffset);
f4296e1 @yaxu foo
yaxu authored
229 }
cf3bb79 @yaxu working and broken again
yaxu authored
230
231 now = jack_last_frame_time(client);
232
f4296e1 @yaxu foo
yaxu authored
233 for (i=0; i < frames; ++i) {
cf3bb79 @yaxu working and broken again
yaxu authored
234 dequeue(now + frames);
235
236 playback(buffers, i, now + i);
ab0fe60 @yaxu there
yaxu authored
237 }
238 return(0);
239 }
Something went wrong with that request. Please try again.