diff --git a/addons/audio/kcm_stream.c b/addons/audio/kcm_stream.c index b17a6670a..8d784fa9a 100644 --- a/addons/audio/kcm_stream.c +++ b/addons/audio/kcm_stream.c @@ -684,6 +684,7 @@ void *_al_kcm_feed_stream(ALLEGRO_THREAD *self, void *vstream) ALLEGRO_AUDIO_STREAM *stream = vstream; ALLEGRO_EVENT_QUEUE *queue; bool finished_event_sent = false; + bool prefill = true; (void)self; ALLEGRO_DEBUG("Stream feeder thread started.\n"); @@ -702,10 +703,12 @@ void *_al_kcm_feed_stream(ALLEGRO_THREAD *self, void *vstream) char *fragment; ALLEGRO_EVENT event; - al_wait_for_event(queue, &event); + if (!prefill) + al_wait_for_event(queue, &event); - if (event.type == ALLEGRO_EVENT_AUDIO_STREAM_FRAGMENT + if ((prefill || event.type == ALLEGRO_EVENT_AUDIO_STREAM_FRAGMENT) && !stream->is_draining) { + prefill = false; unsigned long bytes; unsigned long bytes_written; ALLEGRO_MUTEX *stream_mutex; diff --git a/docs/src/refman/audio.txt b/docs/src/refman/audio.txt index 2667ffb02..a3cd1c50f 100644 --- a/docs/src/refman/audio.txt +++ b/docs/src/refman/audio.txt @@ -735,6 +735,21 @@ If you're late with supplying new data, the stream will be silent until new data is provided. You must call [al_drain_audio_stream] when you're finished with supplying data to the stream. +It is often a good idea to prefill the audio stream with data before +[ALLEGRO_EVENT_AUDIO_STREAM_FRAGMENT] events arrive. Here is a snippet that will +fill the stream buffers with silence: + +~~~~c +ALLEGRO_AUDIO_STREAM *stream = al_create_audio_stream(8, SAMPLES_PER_BUFFER, 22050, + ALLEGRO_AUDIO_DEPTH_UINT8, ALLEGRO_CHANNEL_CONF_1); +void *buf; +while ((buf = al_get_audio_stream_fragment(stream))) { + al_fill_silence(buf, SAMPLES_PER_BUFFER, ALLEGRO_AUDIO_DEPTH_UINT8, + ALLEGRO_CHANNEL_CONF_1); + al_set_audio_stream_fragment(stream, buf); +} +~~~~ + If the stream is created by [al_load_audio_stream] or [al_play_audio_stream] then it will also generate an [ALLEGRO_EVENT_AUDIO_STREAM_FINISHED] event if it reaches the end of the file and is not set to loop. diff --git a/examples/ex_saw.c b/examples/ex_saw.c index b35700e81..1a2d21b49 100644 --- a/examples/ex_saw.c +++ b/examples/ex_saw.c @@ -83,6 +83,7 @@ static void saw(ALLEGRO_AUDIO_STREAM *stream) int main(int argc, char **argv) { ALLEGRO_AUDIO_STREAM *stream; + void *buf; (void)argc; (void)argv; @@ -98,6 +99,12 @@ int main(int argc, char **argv) stream = al_create_audio_stream(8, SAMPLES_PER_BUFFER, 22050, ALLEGRO_AUDIO_DEPTH_UINT8, ALLEGRO_CHANNEL_CONF_1); + while ((buf = al_get_audio_stream_fragment(stream))) { + al_fill_silence(buf, SAMPLES_PER_BUFFER, ALLEGRO_AUDIO_DEPTH_UINT8, + ALLEGRO_CHANNEL_CONF_1); + al_set_audio_stream_fragment(stream, buf); + } + if (!stream) { abort_example("Could not create stream.\n"); } diff --git a/examples/ex_synth.cpp b/examples/ex_synth.cpp index 3ada24d4a..c058442c3 100644 --- a/examples/ex_synth.cpp +++ b/examples/ex_synth.cpp @@ -48,11 +48,7 @@ static void sawtooth(float *buf, size_t samples, double t, /* globals */ ALLEGRO_FONT *font_gui; -ALLEGRO_AUDIO_STREAM *stream1; -ALLEGRO_AUDIO_STREAM *stream2; -ALLEGRO_AUDIO_STREAM *stream3; -ALLEGRO_AUDIO_STREAM *stream4; -ALLEGRO_AUDIO_STREAM *stream5; +ALLEGRO_AUDIO_STREAM *streams[5]; bool saving = false; ALLEGRO_FILE *save_fp = NULL; @@ -358,11 +354,8 @@ void Prog::run() { d.prepare(); - d.register_event_source(al_get_audio_stream_event_source(stream1)); - d.register_event_source(al_get_audio_stream_event_source(stream2)); - d.register_event_source(al_get_audio_stream_event_source(stream3)); - d.register_event_source(al_get_audio_stream_event_source(stream4)); - d.register_event_source(al_get_audio_stream_event_source(stream5)); + for (int i = 0; i < 5; i++) + d.register_event_source(al_get_audio_stream_event_source(streams[i])); d.set_event_handler(this); while (!d.is_quit_requested()) { @@ -399,15 +392,15 @@ void Prog::handle_event(const ALLEGRO_EVENT & event) return; } - if (stream == stream1) + if (stream == streams[0]) group = &group1; - else if (stream == stream2) + else if (stream == streams[1]) group = &group2; - else if (stream == stream3) + else if (stream == streams[2]) group = &group3; - else if (stream == stream4) + else if (stream == streams[3]) group = &group4; - else if (stream == stream5) + else if (stream == streams[4]) group = &group5; else group = NULL; @@ -474,27 +467,24 @@ int main(int argc, char *argv[]) size_t buffers = 8; unsigned samples = SAMPLES_PER_BUFFER; unsigned freq = STREAM_FREQUENCY; + void *buf; ALLEGRO_AUDIO_DEPTH depth = ALLEGRO_AUDIO_DEPTH_FLOAT32; ALLEGRO_CHANNEL_CONF ch = ALLEGRO_CHANNEL_CONF_1; + ALLEGRO_MIXER *mixer = al_get_default_mixer(); - stream1 = al_create_audio_stream(buffers, samples, freq, depth, ch); - stream2 = al_create_audio_stream(buffers, samples, freq, depth, ch); - stream3 = al_create_audio_stream(buffers, samples, freq, depth, ch); - stream4 = al_create_audio_stream(buffers, samples, freq, depth, ch); - stream5 = al_create_audio_stream(buffers, samples, freq, depth, ch); - if (!stream1 || !stream2 || !stream3 || !stream4 || !stream5) { - abort_example("Could not create stream.\n"); - } + for (int i = 0; i < 5; i++) { + streams[i] = al_create_audio_stream(buffers, samples, freq, depth, ch); + if (!streams[i]) { + abort_example("Could not create stream.\n"); + } + while ((buf = al_get_audio_stream_fragment(streams[i]))) { + al_fill_silence(buf, samples, depth, ch); + al_set_audio_stream_fragment(streams[i], buf); + } - ALLEGRO_MIXER *mixer = al_get_default_mixer(); - if ( - !al_attach_audio_stream_to_mixer(stream1, mixer) || - !al_attach_audio_stream_to_mixer(stream2, mixer) || - !al_attach_audio_stream_to_mixer(stream3, mixer) || - !al_attach_audio_stream_to_mixer(stream4, mixer) || - !al_attach_audio_stream_to_mixer(stream5, mixer) - ) { - abort_example("Could not attach stream to mixer.\n"); + if (!al_attach_audio_stream_to_mixer(streams[i], mixer)) { + abort_example("Could not attach stream to mixer.\n"); + } } al_set_mixer_postprocess_callback(mixer, mixer_pp_callback, mixer); @@ -506,11 +496,9 @@ int main(int argc, char *argv[]) prog.run(); } - al_destroy_audio_stream(stream1); - al_destroy_audio_stream(stream2); - al_destroy_audio_stream(stream3); - al_destroy_audio_stream(stream4); - al_destroy_audio_stream(stream5); + for (int i = 0; i < 5; i++) { + al_destroy_audio_stream(streams[i]); + } al_uninstall_audio(); al_destroy_font(font_gui);