1 /**
2  * Originally digi.c from allegro wiki
3  * Original authors: KC/Milan
4  *
5  * Converted to allegro5 by Ryan Dickie
6  */
7 
8 /* Title: Stream functions
9  */
10 
11 #include <stdio.h>
12 
13 #include "allegro5/allegro_audio.h"
14 #include "allegro5/internal/aintern_audio.h"
15 #include "allegro5/internal/aintern_audio_cfg.h"
16 
17 ALLEGRO_DEBUG_CHANNEL("audio")
18 
19 /*
20  * The highest quality interpolator is a cubic interpolator requiring
21  * four sample points.  In the streaming case we lag the true sample
22  * position by three.
23  */
24 #define MAX_LAG   (3)
25 
26 
27 /*
28  * To avoid deadlocks, unlock the mutex returned by this function, rather than
29  * whatever you passed as the argument.
30  */
maybe_lock_mutex(ALLEGRO_MUTEX * mutex)31 static ALLEGRO_MUTEX *maybe_lock_mutex(ALLEGRO_MUTEX *mutex)
32 {
33    if (mutex) {
34       al_lock_mutex(mutex);
35    }
36    return mutex;
37 }
38 
39 
maybe_unlock_mutex(ALLEGRO_MUTEX * mutex)40 static void maybe_unlock_mutex(ALLEGRO_MUTEX *mutex)
41 {
42    if (mutex) {
43       al_unlock_mutex(mutex);
44    }
45 }
46 
47 /* Function: al_create_audio_stream
48  */
al_create_audio_stream(size_t fragment_count,unsigned int frag_samples,unsigned int freq,ALLEGRO_AUDIO_DEPTH depth,ALLEGRO_CHANNEL_CONF chan_conf)49 ALLEGRO_AUDIO_STREAM *al_create_audio_stream(size_t fragment_count,
50    unsigned int frag_samples, unsigned int freq, ALLEGRO_AUDIO_DEPTH depth,
51    ALLEGRO_CHANNEL_CONF chan_conf)
52 {
53    ALLEGRO_AUDIO_STREAM *stream;
54    unsigned long bytes_per_sample;
55    unsigned long bytes_per_frag_buf;
56    size_t i;
57 
58    if (!fragment_count) {
59       _al_set_error(ALLEGRO_INVALID_PARAM,
60          "Attempted to create stream with no buffers");
61       return NULL;
62    }
63    if (!frag_samples) {
64       _al_set_error(ALLEGRO_INVALID_PARAM,
65           "Attempted to create stream with no buffer size");
66       return NULL;
67    }
68    if (!freq) {
69       _al_set_error(ALLEGRO_INVALID_PARAM,
70          "Attempted to create stream with no frequency");
71       return NULL;
72    }
73 
74    bytes_per_sample = al_get_channel_count(chan_conf) *
75          al_get_audio_depth_size(depth);
76    bytes_per_frag_buf = frag_samples * bytes_per_sample;
77 
78    stream = al_calloc(1, sizeof(*stream));
79    if (!stream) {
80       _al_set_error(ALLEGRO_GENERIC_ERROR,
81          "Out of memory allocating stream object");
82       return NULL;
83    }
84 
85    stream->spl.is_playing = true;
86    stream->is_draining = false;
87 
88    stream->spl.loop      = _ALLEGRO_PLAYMODE_STREAM_ONCE;
89    stream->spl.spl_data.depth     = depth;
90    stream->spl.spl_data.chan_conf = chan_conf;
91    stream->spl.spl_data.frequency = freq;
92    stream->spl.speed     = 1.0f;
93    stream->spl.gain      = 1.0f;
94    stream->spl.pan       = 0.0f;
95 
96    stream->spl.step = 0;
97    stream->spl.pos  = frag_samples;
98    stream->spl.spl_data.len  = stream->spl.pos;
99 
100    stream->buf_count = fragment_count;
101 
102    stream->used_bufs = al_calloc(1, fragment_count * sizeof(void *) * 2);
103    if (!stream->used_bufs) {
104       al_free(stream->used_bufs);
105       al_free(stream);
106       _al_set_error(ALLEGRO_GENERIC_ERROR,
107          "Out of memory allocating stream buffer pointers");
108       return NULL;
109    }
110    stream->pending_bufs = stream->used_bufs + fragment_count;
111 
112    /* The main_buffer holds all the buffer fragments in contiguous memory.
113     * To support interpolation across buffer fragments, we allocate extra
114     * MAX_LAG samples at the start of each buffer fragment, to hold the
115     * last few sample values which came before that fragment.
116     */
117    stream->main_buffer = al_calloc(1,
118       (MAX_LAG * bytes_per_sample + bytes_per_frag_buf) * fragment_count);
119    if (!stream->main_buffer) {
120       al_free(stream->used_bufs);
121       al_free(stream);
122       _al_set_error(ALLEGRO_GENERIC_ERROR,
123          "Out of memory allocating stream buffer");
124       return NULL;
125    }
126 
127    for (i = 0; i < fragment_count; i++) {
128       char *buffer = (char *)stream->main_buffer
129          + i * (MAX_LAG * bytes_per_sample + bytes_per_frag_buf);
130       al_fill_silence(buffer, MAX_LAG, depth, chan_conf);
131       stream->used_bufs[i] = buffer + MAX_LAG * bytes_per_sample;
132    }
133 
134    al_init_user_event_source(&stream->spl.es);
135 
136    /* This can lead to deadlocks on shutdown, hence we don't do it. */
137    /* stream->dtor_item = _al_kcm_register_destructor(stream, (void (*)(void *)) al_destroy_audio_stream); */
138 
139    return stream;
140 }
141 
142 
143 /* Function: al_destroy_audio_stream
144  */
al_destroy_audio_stream(ALLEGRO_AUDIO_STREAM * stream)145 void al_destroy_audio_stream(ALLEGRO_AUDIO_STREAM *stream)
146 {
147    if (stream) {
148       if (stream->feed_thread) {
149          stream->unload_feeder(stream);
150       }
151       /* See commented out call to _al_kcm_register_destructor. */
152       /* _al_kcm_unregister_destructor(stream->dtor_item); */
153       _al_kcm_detach_from_parent(&stream->spl);
154 
155       al_destroy_user_event_source(&stream->spl.es);
156       al_free(stream->main_buffer);
157       al_free(stream->used_bufs);
158       al_free(stream);
159    }
160 }
161 
162 
163 /* Function: al_drain_audio_stream
164  */
al_drain_audio_stream(ALLEGRO_AUDIO_STREAM * stream)165 void al_drain_audio_stream(ALLEGRO_AUDIO_STREAM *stream)
166 {
167    bool playing;
168 
169    if (!al_get_audio_stream_attached(stream)) {
170       al_set_audio_stream_playing(stream, false);
171       return;
172    }
173 
174    stream->is_draining = true;
175    do {
176       al_rest(0.01);
177       playing = al_get_audio_stream_playing(stream);
178    } while (playing);
179    stream->is_draining = false;
180 }
181 
182 
183 /* Function: al_get_audio_stream_frequency
184  */
al_get_audio_stream_frequency(const ALLEGRO_AUDIO_STREAM * stream)185 unsigned int al_get_audio_stream_frequency(const ALLEGRO_AUDIO_STREAM *stream)
186 {
187    ASSERT(stream);
188 
189    return stream->spl.spl_data.frequency;
190 }
191 
192 
193 /* Function: al_get_audio_stream_length
194  */
al_get_audio_stream_length(const ALLEGRO_AUDIO_STREAM * stream)195 unsigned int al_get_audio_stream_length(const ALLEGRO_AUDIO_STREAM *stream)
196 {
197    ASSERT(stream);
198 
199    return stream->spl.spl_data.len;
200 }
201 
202 
203 /* Function: al_get_audio_stream_fragments
204  */
al_get_audio_stream_fragments(const ALLEGRO_AUDIO_STREAM * stream)205 unsigned int al_get_audio_stream_fragments(const ALLEGRO_AUDIO_STREAM *stream)
206 {
207    ASSERT(stream);
208 
209    return stream->buf_count;
210 }
211 
212 
213 /* Function: al_get_available_audio_stream_fragments
214  */
al_get_available_audio_stream_fragments(const ALLEGRO_AUDIO_STREAM * stream)215 unsigned int al_get_available_audio_stream_fragments(
216    const ALLEGRO_AUDIO_STREAM *stream)
217 {
218    unsigned int i;
219    ASSERT(stream);
220 
221    for (i = 0; i < stream->buf_count && stream->used_bufs[i]; i++)
222       ;
223    return i;
224 }
225 
226 
227 /* Function: al_get_audio_stream_speed
228  */
al_get_audio_stream_speed(const ALLEGRO_AUDIO_STREAM * stream)229 float al_get_audio_stream_speed(const ALLEGRO_AUDIO_STREAM *stream)
230 {
231    ASSERT(stream);
232 
233    return stream->spl.speed;
234 }
235 
236 
237 /* Function: al_get_audio_stream_gain
238  */
al_get_audio_stream_gain(const ALLEGRO_AUDIO_STREAM * stream)239 float al_get_audio_stream_gain(const ALLEGRO_AUDIO_STREAM *stream)
240 {
241    ASSERT(stream);
242 
243    return stream->spl.gain;
244 }
245 
246 
247 /* Function: al_get_audio_stream_pan
248  */
al_get_audio_stream_pan(const ALLEGRO_AUDIO_STREAM * stream)249 float al_get_audio_stream_pan(const ALLEGRO_AUDIO_STREAM *stream)
250 {
251    ASSERT(stream);
252 
253    return stream->spl.pan;
254 }
255 
256 
257 /* Function: al_get_audio_stream_channels
258  */
al_get_audio_stream_channels(const ALLEGRO_AUDIO_STREAM * stream)259 ALLEGRO_CHANNEL_CONF al_get_audio_stream_channels(
260    const ALLEGRO_AUDIO_STREAM *stream)
261 {
262    ASSERT(stream);
263 
264    return stream->spl.spl_data.chan_conf;
265 }
266 
267 
268 /* Function: al_get_audio_stream_depth
269  */
al_get_audio_stream_depth(const ALLEGRO_AUDIO_STREAM * stream)270 ALLEGRO_AUDIO_DEPTH al_get_audio_stream_depth(
271    const ALLEGRO_AUDIO_STREAM *stream)
272 {
273    ASSERT(stream);
274 
275    return stream->spl.spl_data.depth;
276 }
277 
278 
279 /* Function: al_get_audio_stream_playmode
280  */
al_get_audio_stream_playmode(const ALLEGRO_AUDIO_STREAM * stream)281 ALLEGRO_PLAYMODE al_get_audio_stream_playmode(
282    const ALLEGRO_AUDIO_STREAM *stream)
283 {
284    ASSERT(stream);
285 
286    return stream->spl.loop;
287 }
288 
289 
290 /* Function: al_get_audio_stream_playing
291 */
al_get_audio_stream_playing(const ALLEGRO_AUDIO_STREAM * stream)292 bool al_get_audio_stream_playing(const ALLEGRO_AUDIO_STREAM *stream)
293 {
294    ASSERT(stream);
295 
296    return stream->spl.is_playing;
297 }
298 
299 
300 /* Function: al_get_audio_stream_attached
301 */
al_get_audio_stream_attached(const ALLEGRO_AUDIO_STREAM * stream)302 bool al_get_audio_stream_attached(const ALLEGRO_AUDIO_STREAM *stream)
303 {
304    ASSERT(stream);
305 
306    return (stream->spl.parent.u.ptr != NULL);
307 }
308 
309 /* Function: al_get_audio_stream_played_samples
310 */
al_get_audio_stream_played_samples(const ALLEGRO_AUDIO_STREAM * stream)311 uint64_t al_get_audio_stream_played_samples(const ALLEGRO_AUDIO_STREAM *stream)
312 {
313    uint64_t result;
314    ALLEGRO_MUTEX *stream_mutex;
315    ASSERT(stream);
316 
317    stream_mutex = maybe_lock_mutex(stream->spl.mutex);
318    if (stream->spl.spl_data.buffer.ptr) {
319       result = stream->consumed_fragments * stream->spl.spl_data.len +
320          stream->spl.pos;
321    }
322    else {
323       result = 0;
324    }
325    maybe_unlock_mutex(stream_mutex);
326 
327    return result;
328 }
329 
330 /* Function: al_get_audio_stream_fragment
331 */
al_get_audio_stream_fragment(const ALLEGRO_AUDIO_STREAM * stream)332 void *al_get_audio_stream_fragment(const ALLEGRO_AUDIO_STREAM *stream)
333 {
334    size_t i;
335    void *fragment;
336    ALLEGRO_MUTEX *stream_mutex;
337    ASSERT(stream);
338 
339    stream_mutex = maybe_lock_mutex(stream->spl.mutex);
340 
341    if (!stream->used_bufs[0]) {
342       /* No free fragments are available. */
343       fragment = NULL;
344    }
345    else {
346       fragment = stream->used_bufs[0];
347       for (i = 0; i < stream->buf_count-1 && stream->used_bufs[i]; i++) {
348          stream->used_bufs[i] = stream->used_bufs[i+1];
349       }
350       stream->used_bufs[i] = NULL;
351    }
352 
353    maybe_unlock_mutex(stream_mutex);
354 
355    return fragment;
356 }
357 
358 
359 /* Function: al_set_audio_stream_speed
360  */
al_set_audio_stream_speed(ALLEGRO_AUDIO_STREAM * stream,float val)361 bool al_set_audio_stream_speed(ALLEGRO_AUDIO_STREAM *stream, float val)
362 {
363    ASSERT(stream);
364 
365    if (val <= 0.0f) {
366       _al_set_error(ALLEGRO_INVALID_PARAM,
367          "Attempted to set stream speed to a zero or negative value");
368       return false;
369    }
370 
371    if (stream->spl.parent.u.ptr && stream->spl.parent.is_voice) {
372       _al_set_error(ALLEGRO_GENERIC_ERROR,
373          "Could not set voice playback speed");
374       return false;
375    }
376 
377    stream->spl.speed = val;
378    if (stream->spl.parent.u.mixer) {
379       ALLEGRO_MIXER *mixer = stream->spl.parent.u.mixer;
380       ALLEGRO_MUTEX *stream_mutex = maybe_lock_mutex(stream->spl.mutex);
381 
382       stream->spl.step = (stream->spl.spl_data.frequency) * stream->spl.speed;
383       stream->spl.step_denom = mixer->ss.spl_data.frequency;
384       /* Don't wanna be trapped with a step value of 0 */
385       if (stream->spl.step == 0) {
386          stream->spl.step = 1;
387       }
388 
389       maybe_unlock_mutex(stream_mutex);
390    }
391 
392    return true;
393 }
394 
395 
396 /* Function: al_set_audio_stream_gain
397  */
al_set_audio_stream_gain(ALLEGRO_AUDIO_STREAM * stream,float val)398 bool al_set_audio_stream_gain(ALLEGRO_AUDIO_STREAM *stream, float val)
399 {
400    ASSERT(stream);
401 
402    if (stream->spl.parent.u.ptr && stream->spl.parent.is_voice) {
403       _al_set_error(ALLEGRO_GENERIC_ERROR,
404          "Could not set gain of stream attached to voice");
405       return false;
406    }
407 
408    if (stream->spl.gain != val) {
409       stream->spl.gain = val;
410 
411       /* If attached to a mixer already, need to recompute the sample
412        * matrix to take into account the gain.
413        */
414       if (stream->spl.parent.u.mixer) {
415          ALLEGRO_MIXER *mixer = stream->spl.parent.u.mixer;
416          ALLEGRO_MUTEX *stream_mutex = maybe_lock_mutex(stream->spl.mutex);
417          _al_kcm_mixer_rejig_sample_matrix(mixer, &stream->spl);
418          maybe_unlock_mutex(stream_mutex);
419       }
420    }
421 
422    return true;
423 }
424 
425 
426 /* Function: al_set_audio_stream_pan
427  */
al_set_audio_stream_pan(ALLEGRO_AUDIO_STREAM * stream,float val)428 bool al_set_audio_stream_pan(ALLEGRO_AUDIO_STREAM *stream, float val)
429 {
430    ASSERT(stream);
431 
432    if (stream->spl.parent.u.ptr && stream->spl.parent.is_voice) {
433       _al_set_error(ALLEGRO_GENERIC_ERROR,
434          "Could not set gain of stream attached to voice");
435       return false;
436    }
437    if (val != ALLEGRO_AUDIO_PAN_NONE && (val < -1.0 || val > 1.0)) {
438       _al_set_error(ALLEGRO_GENERIC_ERROR, "Invalid pan value");
439       return false;
440    }
441 
442    if (stream->spl.pan != val) {
443       stream->spl.pan = val;
444 
445       /* If attached to a mixer already, need to recompute the sample
446        * matrix to take into account the panning.
447        */
448       if (stream->spl.parent.u.mixer) {
449          ALLEGRO_MIXER *mixer = stream->spl.parent.u.mixer;
450          ALLEGRO_MUTEX *stream_mutex = maybe_lock_mutex(stream->spl.mutex);
451          _al_kcm_mixer_rejig_sample_matrix(mixer, &stream->spl);
452          maybe_unlock_mutex(stream_mutex);
453       }
454    }
455 
456    return true;
457 }
458 
459 
460 /* Function: al_set_audio_stream_playmode
461  */
al_set_audio_stream_playmode(ALLEGRO_AUDIO_STREAM * stream,ALLEGRO_PLAYMODE val)462 bool al_set_audio_stream_playmode(ALLEGRO_AUDIO_STREAM *stream,
463    ALLEGRO_PLAYMODE val)
464 {
465    ASSERT(stream);
466 
467    if (val == ALLEGRO_PLAYMODE_ONCE) {
468       stream->spl.loop = _ALLEGRO_PLAYMODE_STREAM_ONCE;
469       return true;
470    }
471    else if (val == ALLEGRO_PLAYMODE_LOOP) {
472       /* Only streams creating by al_load_audio_stream() support
473        * looping. */
474       if (!stream->feeder)
475          return false;
476 
477       stream->spl.loop = _ALLEGRO_PLAYMODE_STREAM_ONEDIR;
478       return true;
479    }
480 
481    // XXX _al_set_error
482    return false;
483 }
484 
485 
reset_stopped_stream(ALLEGRO_AUDIO_STREAM * stream)486 static void reset_stopped_stream(ALLEGRO_AUDIO_STREAM *stream)
487 {
488    const int bytes_per_sample =
489       al_get_channel_count(stream->spl.spl_data.chan_conf) *
490       al_get_audio_depth_size(stream->spl.spl_data.depth);
491    const int fragment_buffer_size =
492       bytes_per_sample * (stream->spl.spl_data.len + MAX_LAG);
493    size_t i, n;
494 
495    /* Write silence to the "invisible" part in between fragment buffers to
496     * avoid interpolation artifacts.  It's tempting to zero the complete
497     * memory block in one go but some of the buffers might be getting
498     * refilled.  So they are currently "owned" by the library user and
499     * should not be overwritten.  But zeroing the parts not visible to the
500     * user should be OK.
501     */
502    for (i = 0; i < stream->buf_count; ++i) {
503       al_fill_silence((char *)stream->main_buffer + i * fragment_buffer_size,
504          MAX_LAG, stream->spl.spl_data.depth, stream->spl.spl_data.chan_conf);
505    }
506 
507    /* Get the current number of entries in the used_buf list. */
508    for (n = 0; n < stream->buf_count && stream->used_bufs[n]; n++)
509       ;
510 
511    /* Move everything from pending_bufs to used_bufs. */
512    i = 0;
513    while (i < stream->buf_count &&
514          n < stream->buf_count &&
515          stream->pending_bufs[i])
516    {
517       stream->used_bufs[n] = stream->pending_bufs[i];
518       stream->pending_bufs[i] = NULL;
519       n++;
520       i++;
521    }
522 
523    /* No fragment buffer is currently playing. */
524    stream->spl.spl_data.buffer.ptr = NULL;
525    stream->spl.pos = stream->spl.spl_data.len;
526    stream->spl.pos_bresenham_error = 0;
527    stream->consumed_fragments = 0;
528 }
529 
530 
531 /* Function: al_set_audio_stream_playing
532  */
al_set_audio_stream_playing(ALLEGRO_AUDIO_STREAM * stream,bool val)533 bool al_set_audio_stream_playing(ALLEGRO_AUDIO_STREAM *stream, bool val)
534 {
535    bool rc = true;
536    ALLEGRO_MUTEX *stream_mutex;
537    ASSERT(stream);
538 
539    if (stream->spl.parent.u.ptr && stream->spl.parent.is_voice) {
540       ALLEGRO_VOICE *voice = stream->spl.parent.u.voice;
541       if (val != stream->spl.is_playing) {
542          rc = _al_kcm_set_voice_playing(voice, voice->mutex, val);
543       }
544    }
545 
546    stream_mutex = maybe_lock_mutex(stream->spl.mutex);
547 
548    stream->spl.is_playing = rc && val;
549 
550    if (stream->spl.is_playing) {
551       /* We usually emit fragment events when a fragment is used up, but if the
552        * stream has zero pending fragments to begin with then no events would
553        * ever be emitted.
554        */
555       _al_kcm_emit_stream_events(stream);
556    }
557    else if (!val) {
558       reset_stopped_stream(stream);
559    }
560 
561    maybe_unlock_mutex(stream_mutex);
562 
563    return rc;
564 }
565 
566 
567 /* Function: al_detach_audio_stream
568  */
al_detach_audio_stream(ALLEGRO_AUDIO_STREAM * stream)569 bool al_detach_audio_stream(ALLEGRO_AUDIO_STREAM *stream)
570 {
571    ASSERT(stream);
572 
573    _al_kcm_detach_from_parent(&stream->spl);
574    ASSERT(stream->spl.spl_read == NULL);
575    return !al_get_audio_stream_attached(stream);
576 }
577 
578 
579 /* Function: al_set_audio_stream_fragment
580  */
al_set_audio_stream_fragment(ALLEGRO_AUDIO_STREAM * stream,void * val)581 bool al_set_audio_stream_fragment(ALLEGRO_AUDIO_STREAM *stream, void *val)
582 {
583    size_t i;
584    bool ret;
585    ALLEGRO_MUTEX *stream_mutex;
586    ASSERT(stream);
587 
588    stream_mutex = maybe_lock_mutex(stream->spl.mutex);
589 
590    for (i = 0; i < stream->buf_count && stream->pending_bufs[i] ; i++)
591       ;
592    if (i < stream->buf_count) {
593       stream->pending_bufs[i] = val;
594       ret = true;
595    }
596    else {
597       _al_set_error(ALLEGRO_INVALID_OBJECT,
598          "Attempted to set a stream buffer with a full pending list");
599       ret = false;
600    }
601 
602    maybe_unlock_mutex(stream_mutex);
603 
604    return ret;
605 }
606 
607 
608 /* _al_kcm_refill_stream:
609  *  Called by the mixer when the current buffer has been used up.  It should
610  *  point to the next pending buffer and adjust the sample position to reflect
611  *  the buffer being updated. It may be necessary to call this function multiple
612  *  times if the sample position is so far ahead that multiple buffers need to
613  *  be consumed.
614  *  Returns true if the next buffer is available and set up.
615  *  Otherwise returns false.
616  */
_al_kcm_refill_stream(ALLEGRO_AUDIO_STREAM * stream)617 bool _al_kcm_refill_stream(ALLEGRO_AUDIO_STREAM *stream)
618 {
619    ALLEGRO_SAMPLE_INSTANCE *spl = &stream->spl;
620    void *old_buf = spl->spl_data.buffer.ptr;
621    void *new_buf;
622    size_t i;
623    int new_pos = spl->pos - spl->spl_data.len;
624 
625    if (old_buf) {
626       /* Slide the buffers down one position and put the
627        * completed buffer into the used array to be refilled.
628        */
629       for (i = 0;
630             i < stream->buf_count-1 && stream->pending_bufs[i];
631             i++) {
632          stream->pending_bufs[i] = stream->pending_bufs[i+1];
633       }
634       stream->pending_bufs[i] = NULL;
635 
636       for (i = 0; stream->used_bufs[i]; i++)
637          ;
638       stream->used_bufs[i] = old_buf;
639    }
640 
641    new_buf = stream->pending_bufs[0];
642    stream->spl.spl_data.buffer.ptr = new_buf;
643    if (!new_buf) {
644       ALLEGRO_WARN("Out of buffers\n");
645       return false;
646    }
647 
648    /* Copy the last MAX_LAG sample values to the front of the new buffer
649     * for interpolation.
650     */
651    if (old_buf) {
652       const int bytes_per_sample =
653          al_get_channel_count(spl->spl_data.chan_conf) *
654          al_get_audio_depth_size(spl->spl_data.depth);
655 
656       memcpy(
657          (char *) new_buf - bytes_per_sample * MAX_LAG,
658          (char *) old_buf + bytes_per_sample * (spl->pos-MAX_LAG-new_pos),
659          bytes_per_sample * MAX_LAG);
660 
661       stream->consumed_fragments++;
662    }
663 
664    stream->spl.pos = new_pos;
665 
666    return true;
667 }
668 
669 
670 /* _al_kcm_feed_stream:
671  * A routine running in another thread that feeds the stream buffers as
672  * necessary, usually getting data from some file reader backend.
673  */
_al_kcm_feed_stream(ALLEGRO_THREAD * self,void * vstream)674 void *_al_kcm_feed_stream(ALLEGRO_THREAD *self, void *vstream)
675 {
676    ALLEGRO_AUDIO_STREAM *stream = vstream;
677    ALLEGRO_EVENT_QUEUE *queue;
678    bool finished_event_sent = false;
679    (void)self;
680 
681    ALLEGRO_DEBUG("Stream feeder thread started.\n");
682 
683    queue = al_create_event_queue();
684    al_register_event_source(queue, &stream->spl.es);
685 
686    al_lock_mutex(stream->feed_thread_started_mutex);
687    stream->feed_thread_started = true;
688    al_broadcast_cond(stream->feed_thread_started_cond);
689    al_unlock_mutex(stream->feed_thread_started_mutex);
690 
691    stream->quit_feed_thread = false;
692 
693    while (!stream->quit_feed_thread) {
694       char *fragment;
695       ALLEGRO_EVENT event;
696 
697       al_wait_for_event(queue, &event);
698 
699       if (event.type == ALLEGRO_EVENT_AUDIO_STREAM_FRAGMENT
700           && !stream->is_draining) {
701          unsigned long bytes;
702          unsigned long bytes_written;
703          ALLEGRO_MUTEX *stream_mutex;
704 
705          fragment = al_get_audio_stream_fragment(stream);
706          if (!fragment) {
707             /* This is not an error. */
708             continue;
709          }
710 
711          bytes = (stream->spl.spl_data.len) *
712                al_get_channel_count(stream->spl.spl_data.chan_conf) *
713                al_get_audio_depth_size(stream->spl.spl_data.depth);
714 
715          stream_mutex = maybe_lock_mutex(stream->spl.mutex);
716          bytes_written = stream->feeder(stream, fragment, bytes);
717          maybe_unlock_mutex(stream_mutex);
718 
719          if (stream->spl.loop == _ALLEGRO_PLAYMODE_STREAM_ONEDIR) {
720             /* Keep rewinding until the fragment is filled. */
721             while (bytes_written < bytes &&
722                      stream->spl.loop == _ALLEGRO_PLAYMODE_STREAM_ONEDIR) {
723                size_t bw;
724                al_rewind_audio_stream(stream);
725                stream_mutex = maybe_lock_mutex(stream->spl.mutex);
726                bw = stream->feeder(stream, fragment + bytes_written,
727                   bytes - bytes_written);
728                bytes_written += bw;
729                maybe_unlock_mutex(stream_mutex);
730             }
731          }
732          else if (bytes_written < bytes) {
733             /* Fill the rest of the fragment with silence. */
734             int silence_samples = (bytes - bytes_written) /
735                (al_get_channel_count(stream->spl.spl_data.chan_conf) *
736                 al_get_audio_depth_size(stream->spl.spl_data.depth));
737             al_fill_silence(fragment + bytes_written, silence_samples,
738                             stream->spl.spl_data.depth, stream->spl.spl_data.chan_conf);
739          }
740 
741          if (!al_set_audio_stream_fragment(stream, fragment)) {
742             ALLEGRO_ERROR("Error setting stream buffer.\n");
743             continue;
744          }
745 
746          /* The streaming source doesn't feed any more, so drain buffers.
747           * Don't quit in case the user decides to seek and then restart the
748           * stream. */
749          if (bytes_written != bytes &&
750             stream->spl.loop == _ALLEGRO_PLAYMODE_STREAM_ONCE) {
751             al_drain_audio_stream(stream);
752 
753             if (!finished_event_sent) {
754                ALLEGRO_EVENT fin_event;
755                fin_event.user.type = ALLEGRO_EVENT_AUDIO_STREAM_FINISHED;
756                fin_event.user.timestamp = al_get_time();
757                al_emit_user_event(&stream->spl.es, &fin_event, NULL);
758                finished_event_sent = true;
759             }
760          } else {
761             finished_event_sent = false;
762          }
763       }
764       else if (event.type == _KCM_STREAM_FEEDER_QUIT_EVENT_TYPE) {
765          ALLEGRO_EVENT fin_event;
766          stream->quit_feed_thread = true;
767 
768          fin_event.user.type = ALLEGRO_EVENT_AUDIO_STREAM_FINISHED;
769          fin_event.user.timestamp = al_get_time();
770          al_emit_user_event(&stream->spl.es, &fin_event, NULL);
771       }
772    }
773 
774    al_destroy_event_queue(queue);
775 
776    ALLEGRO_DEBUG("Stream feeder thread finished.\n");
777 
778    return NULL;
779 }
780 
781 
_al_kcm_emit_stream_events(ALLEGRO_AUDIO_STREAM * stream)782 void _al_kcm_emit_stream_events(ALLEGRO_AUDIO_STREAM *stream)
783 {
784    /* Emit one event for each stream fragment available right now.
785     *
786     * There may already be an event corresponding to an available fragment in
787     * some event queue, but there's nothing we can do about that.  Streams may
788     * be added and removed from queues, events may be lost by the user, etc.
789     * so it would be dangerous to assume that each fragment event would be
790     * responded to, once and exactly once.
791     *
792     * Having said that, event queues are empty in the steady state so it is
793     * relatively rare that this situation occurs.
794     */
795    int count = al_get_available_audio_stream_fragments(stream);
796 
797    while (count--) {
798       ALLEGRO_EVENT event;
799       event.user.type = ALLEGRO_EVENT_AUDIO_STREAM_FRAGMENT;
800       event.user.timestamp = al_get_time();
801       al_emit_user_event(&stream->spl.es, &event, NULL);
802    }
803 }
804 
805 
806 /* Function: al_rewind_audio_stream
807  */
al_rewind_audio_stream(ALLEGRO_AUDIO_STREAM * stream)808 bool al_rewind_audio_stream(ALLEGRO_AUDIO_STREAM *stream)
809 {
810    bool ret;
811 
812    if (stream->rewind_feeder) {
813       ALLEGRO_MUTEX *stream_mutex = maybe_lock_mutex(stream->spl.mutex);
814       ret = stream->rewind_feeder(stream);
815       maybe_unlock_mutex(stream_mutex);
816       return ret;
817    }
818 
819    return false;
820 }
821 
822 
823 /* Function: al_seek_audio_stream_secs
824  */
al_seek_audio_stream_secs(ALLEGRO_AUDIO_STREAM * stream,double time)825 bool al_seek_audio_stream_secs(ALLEGRO_AUDIO_STREAM *stream, double time)
826 {
827    bool ret;
828 
829    if (stream->seek_feeder) {
830       ALLEGRO_MUTEX *stream_mutex = maybe_lock_mutex(stream->spl.mutex);
831       ret = stream->seek_feeder(stream, time);
832       maybe_unlock_mutex(stream_mutex);
833       return ret;
834    }
835 
836    return false;
837 }
838 
839 
840 /* Function: al_get_audio_stream_position_secs
841  */
al_get_audio_stream_position_secs(ALLEGRO_AUDIO_STREAM * stream)842 double al_get_audio_stream_position_secs(ALLEGRO_AUDIO_STREAM *stream)
843 {
844    double ret;
845 
846    if (stream->get_feeder_position) {
847       ALLEGRO_MUTEX *stream_mutex = maybe_lock_mutex(stream->spl.mutex);
848       ret = stream->get_feeder_position(stream);
849       maybe_unlock_mutex(stream_mutex);
850       return ret;
851    }
852 
853    return 0.0;
854 }
855 
856 
857 /* Function: al_get_audio_stream_length_secs
858  */
al_get_audio_stream_length_secs(ALLEGRO_AUDIO_STREAM * stream)859 double al_get_audio_stream_length_secs(ALLEGRO_AUDIO_STREAM *stream)
860 {
861    double ret;
862 
863    if (stream->get_feeder_length) {
864       ALLEGRO_MUTEX *stream_mutex = maybe_lock_mutex(stream->spl.mutex);
865       ret = stream->get_feeder_length(stream);
866       maybe_unlock_mutex(stream_mutex);
867       return ret;
868    }
869 
870    return 0.0;
871 }
872 
873 
874 /* Function: al_set_audio_stream_loop_secs
875  */
al_set_audio_stream_loop_secs(ALLEGRO_AUDIO_STREAM * stream,double start,double end)876 bool al_set_audio_stream_loop_secs(ALLEGRO_AUDIO_STREAM *stream,
877    double start, double end)
878 {
879    bool ret;
880 
881    if (start >= end)
882       return false;
883 
884    if (stream->set_feeder_loop) {
885       ALLEGRO_MUTEX *stream_mutex = maybe_lock_mutex(stream->spl.mutex);
886       ret = stream->set_feeder_loop(stream, start, end);
887       maybe_unlock_mutex(stream_mutex);
888       return ret;
889    }
890 
891    return false;
892 }
893 
894 
895 /* Function: al_get_audio_stream_event_source
896  */
al_get_audio_stream_event_source(ALLEGRO_AUDIO_STREAM * stream)897 ALLEGRO_EVENT_SOURCE *al_get_audio_stream_event_source(
898    ALLEGRO_AUDIO_STREAM *stream)
899 {
900    return &stream->spl.es;
901 }
902 
al_set_audio_stream_channel_matrix(ALLEGRO_AUDIO_STREAM * stream,const float * matrix)903 bool al_set_audio_stream_channel_matrix(ALLEGRO_AUDIO_STREAM *stream, const float *matrix)
904 {
905    ASSERT(stream);
906 
907    if (stream->spl.parent.u.ptr && stream->spl.parent.is_voice) {
908       _al_set_error(ALLEGRO_GENERIC_ERROR,
909          "Could not set channel matrix of stream attached to voice");
910       return false;
911    }
912 
913    return al_set_sample_instance_channel_matrix(&stream->spl, matrix);
914 }
915 
916 /* vim: set sts=3 sw=3 et: */
917