medfall

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit bc33c9af17cabb6d9a7c069beb77ce62c783dcf6
parent f3f4af7dfc5051e894a96326a639491dea64a6e3
Author: Michael Savage <mikejsavage@gmail.com>
Date:   Mon Oct 24 21:49:32 +0300

Make AudioOutputDevice own the mixer thread (because the OSX audio system insists on creating a thread for you)

Diffstat:
audio.cc | 9++++++---
linux_audio_output.cc | 53++++++++++++++++++++++++++++++++++-------------------
linux_audio_output.h | 9+++++++--
mixer.cc | 63+++++++++++++++++++++++----------------------------------------
mixer.h | 6+++---
5 files changed, 73 insertions(+), 67 deletions(-)
diff --git a/audio.cc b/audio.cc @@ -32,10 +32,10 @@ int main( int argc, char ** argv ) { memarena_init( &arena, memory, sizeof( memory ) ); audio_output_init(); + mixer_init(); AudioOutputDevice output_device; - audio_output_open( &output_device ); - mixer_init( &output_device ); + audio_output_open( &output_device, mixer_mix ); u8 * wave = file_get_contents( "02 - Unbreakable.wav" ); SoundData sound; @@ -83,9 +83,12 @@ int main( int argc, char ** argv ) { } playing = !playing; } + else if( strcmp( line, "q\n" ) == 0 ) { + break; + } } - mixer_term(); + audio_output_close( &output_device ); return 0; } diff --git a/linux_audio_output.cc b/linux_audio_output.cc @@ -72,7 +72,34 @@ void audio_output_term() { library_close( alsa_lib ); } -void audio_output_open( AudioOutputDevice * device ) { +static void audio_output_write( snd_pcm_t * pcm, s16 * samples, s32 num_samples ) { + s32 i = 0; + while( i < num_samples ) { + s16 * channels[ 2 ] = { samples + i, samples + i }; + + snd_pcm_sframes_t written = _snd_pcm_writen( pcm, ( void ** ) channels, num_samples - i ); + if( written <= 0 ) { + _snd_pcm_recover( pcm, written, 1 ); + } + else { + i += written; + } + } +} + +static THREAD( audio_output_thread ) { + AudioOutputDevice * device = ( AudioOutputDevice * ) data; + + s16 samples[ 1024 ]; + for( ;; ) { + device->callback( samples, ARRAY_COUNT( samples ) ); + audio_output_write( device->pcm, samples, ARRAY_COUNT( samples ) ); + } + + THREAD_END; +} + +void audio_output_open( AudioOutputDevice * device, AudioOutputCallback callback ) { const int channels = 2; const int sample_rate = 44100; const int ms = 1000; @@ -80,7 +107,6 @@ void audio_output_open( AudioOutputDevice * device ) { int err_open = _snd_pcm_open( &device->pcm, "default", SND_PCM_STREAM_PLAYBACK, 0 ); if( err_open != 0 ) { - // TODO: maybe don't kill the program FATAL( "Couldn't open sound output: %s", _snd_strerror( err_open ) ); } @@ -88,30 +114,19 @@ void audio_output_open( AudioOutputDevice * device ) { SND_PCM_FORMAT_S16_LE, SND_PCM_ACCESS_RW_NONINTERLEAVED, channels, sample_rate, 1, latency ); if( err_params != 0 ) { - // TODO: maybe don't kill the program FATAL( "Couldn't configure sound output: %s", _snd_strerror( err_params ) ); } + + device->callback = callback; + thread_init( &device->thread, audio_output_thread, device ); } void audio_output_close( AudioOutputDevice * device ) { + thread_cancel( &device->thread ); + thread_join( &device->thread ); + int err = _snd_pcm_close( device->pcm ); if( err != 0 ) { - // TODO: maybe don't kill the program FATAL( "Couldn't close sound output: %s", _snd_strerror( err ) ); } } - -void audio_output_write( AudioOutputDevice * device, s16 * samples, size_t num_samples ) { - u32 i = 0; - while( i < num_samples ) { - s16 * channels[ 2 ] = { samples + i, samples + i }; - - snd_pcm_sframes_t written = _snd_pcm_writen( device->pcm, ( void ** ) channels, num_samples - i ); - if( written <= 0 ) { - _snd_pcm_recover( device->pcm, written, 1 ); - } - else { - i += written; - } - } -} diff --git a/linux_audio_output.h b/linux_audio_output.h @@ -4,16 +4,21 @@ #include <alsa/asoundlib.h> #include "intrinsics.h" +#include "platform_thread.h" + +#define AUDIO_OUTPUT_CALLBACK( f ) void f( s16 * output_samples, s32 num_output_samples ) +typedef AUDIO_OUTPUT_CALLBACK( AudioOutputCallback ); struct AudioOutputDevice { snd_pcm_t * pcm; + Thread thread; + AudioOutputCallback * callback; }; void audio_output_init(); void audio_output_term(); -void audio_output_open( AudioOutputDevice * device ); +void audio_output_open( AudioOutputDevice * device, AudioOutputCallback callback ); void audio_output_close( AudioOutputDevice * device ); -void audio_output_write( AudioOutputDevice * device, s16 * samples, size_t num_samples ); #endif // _LINUX_AUDIO_H_ diff --git a/mixer.cc b/mixer.cc @@ -1,7 +1,6 @@ #include "intrinsics.h" #include "int_conversions.h" #include "mixer.h" -#include "platform_audio_output.h" #include "nonblocking_fixed_spsc_queue.h" struct PlayingSound { @@ -39,7 +38,6 @@ static PlayingSound playing_sounds[ MAX_CONCURRENT_SOUNDS ]; static PlayingSoundID ids[ MAX_CONCURRENT_SOUNDS ]; static u16 first_free_sound; static NonblockingFixedSPSCQueue< MixerCommand, COMMAND_QUEUE_SIZE > command_queue; -static Thread mixer_thread; static PlayingSoundID sound_counter; static bool mixer_sound_id_to_slot( PlayingSoundID sound_id, size_t * slot ) { @@ -141,50 +139,35 @@ static void mixer_mix_sound( PlayingSound * ps, float * samples, size_t num_samp } } -static THREAD( mixer_thread_proc ) { - AudioOutputDevice * output_device = ( AudioOutputDevice * ) data; - - for( ;; ) { - for( size_t i = 0; i < COMMAND_QUEUE_SIZE; i++ ) { - MixerCommand cmd; - if( !command_queue.dequeue( &cmd ) ) break; - mixer_process_command( cmd ); - } +void mixer_init() { + mixer_stop_all_impl(); +} - // TODO: channels - float samples[ 2048 ]; - for( size_t i = 0; i < ARRAY_COUNT( samples ); i++ ) { - samples[ i ] = 0.0f; - } +AUDIO_OUTPUT_CALLBACK( mixer_mix ) { + for( size_t i = 0; i < COMMAND_QUEUE_SIZE; i++ ) { + MixerCommand cmd; + if( !command_queue.dequeue( &cmd ) ) break; + mixer_process_command( cmd ); + } - for( size_t i = 0; i < ARRAY_COUNT( playing_sounds ); i++ ) { - PlayingSound & ps = playing_sounds[ i ]; - if( ps.playing ) { - mixer_mix_sound( &ps, samples, ARRAY_COUNT( samples ) ); - } - } + // TODO: channels + const s32 MAX_OUTPUT_SAMPLES = 4096; + float samples[ MAX_OUTPUT_SAMPLES ]; + ASSERT( num_output_samples <= MAX_OUTPUT_SAMPLES ); + for( s32 i = 0; i < num_output_samples; i++ ) { + samples[ i ] = 0.0f; + } - s16 finalised_samples[ 2048 ]; - for( size_t i = 0; i < ARRAY_COUNT( samples ); i++ ) { - finalised_samples[ i ] = quantize11s( clamp11( samples[ i ] ), 16 ); + for( size_t i = 0; i < ARRAY_COUNT( playing_sounds ); i++ ) { + PlayingSound & ps = playing_sounds[ i ]; + if( ps.playing ) { + mixer_mix_sound( &ps, samples, num_output_samples ); } - - audio_output_write( output_device, finalised_samples, ARRAY_COUNT( finalised_samples ) ); } - THREAD_END; -} - -void mixer_init( AudioOutputDevice * output_device ) { - mixer_stop_all_impl(); - sound_counter = RESET_SOUND_COUNTER; - thread_init( &mixer_thread, mixer_thread_proc, output_device ); -} - -void mixer_term() { - thread_cancel( &mixer_thread ); - thread_join( &mixer_thread ); - command_queue.clear(); + for( s32 i = 0; i < num_output_samples; i++ ) { + output_samples[ i ] = quantize11s( clamp11( samples[ i ] ), 16 ); + } } PlayingSoundID mixer_play( SoundData sound, MixerLoopBool loop, s32 start_pos ) { diff --git a/mixer.h b/mixer.h @@ -16,9 +16,9 @@ enum MixerLoopBool { MIXER_LOOP, }; -// TODO: maybe make this take a QueueReader -void mixer_init( AudioOutputDevice * output_device ); -void mixer_term(); +void mixer_init(); + +AUDIO_OUTPUT_CALLBACK( mixer_mix ); // TODO: maybe make these take a QueueWriter PlayingSoundID mixer_play( SoundData sound, MixerLoopBool loop = MIXER_DONTLOOP, s32 start_pos = 0 );