commit 1c0cbbccf4781bcde83335c522c414766fc5f6bb parent 88b5f39d6e0812e49814ef7b64c3c973b9e40d9a Author: Michael Savage <mikejsavage@gmail.com> Date: Sun Aug 28 06:29:06 +0100 Use dlload instead of linking with asound Diffstat:
audio.cc | | | 2 | ++ |
linux_audio.h | | | 76 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------- |
os.mk | | | 2 | +- |
platform_audio.h | | | 6 | +++--- |
diff --git a/audio.cc b/audio.cc @@ -6,6 +6,8 @@ #include "mixer.h" #include "wave.h" #include "assets.h" +#define PLATFORM_AUDIO_IMPLEMENTATION 1 +#include "platform_audio.h" static SoundData make_sin_wave( u32 sample_rate, u32 frequency ) { const u32 num_samples = sample_rate * ( 1.0f / frequency ); diff --git a/linux_audio.h b/linux_audio.h @@ -3,6 +3,7 @@ #include <stdio.h> #include <stdarg.h> +#include <dlfcn.h> #include <alsa/asoundlib.h> @@ -13,7 +14,24 @@ struct AudioOutputDevice { snd_pcm_t * pcm; }; -static inline void audio_error_handler( const char * file, int line, const char * function, int err, const char * fmt, ... ) { +void audio_output_open( AudioOutputDevice * device ); +void audio_output_close( AudioOutputDevice * device ); +void audio_output_write( AudioOutputDevice * device, s16 * samples, size_t num_samples ); + +#endif // _LINUX_AUDIO_H_ + +#ifdef PLATFORM_AUDIO_IMPLEMENTATION + +// copied from alsa headers +static int ( *_snd_lib_error_set_handler )( snd_lib_error_handler_t handler ) = NULL; +static const char * ( *_snd_strerror )( int errnum ) = NULL; +static int ( *_snd_pcm_open )( snd_pcm_t ** pcm, const char * name, snd_pcm_stream_t stream, int mode ) = NULL; +static int ( *_snd_pcm_set_params )( snd_pcm_t * pcm, snd_pcm_format_t format, snd_pcm_access_t access, unsigned int channels, unsigned int rate, int soft_resample, unsigned int latency ) = NULL; +static snd_pcm_sframes_t ( *_snd_pcm_writen )( snd_pcm_t * pcm, void ** bufs, snd_pcm_uframes_t size ) = NULL; +static int ( *_snd_pcm_recover )( snd_pcm_t * pcm, int err, int silent ) = NULL; +static int ( *_snd_pcm_close )( snd_pcm_t * pcm ) = NULL; + +static void audio_error_handler( const char * file, int line, const char * function, int err, const char * fmt, ... ) { printf( "error in %s at %s:%d\n", file, function, line ); va_list args; @@ -23,45 +41,75 @@ static inline void audio_error_handler( const char * file, int line, const char printf( "\n" ); } -inline void audio_output_open( AudioOutputDevice * device ) { +void audio_output_open( AudioOutputDevice * device ) { // TODO: make an audio_output_init_lib function to do this + dlload - snd_lib_error_set_handler( audio_error_handler ); + static bool audio_inited = false; + if( !audio_inited ) { + void * alsa_lib = dlopen( "libasound.so", RTLD_NOW ); + if( alsa_lib == NULL ) { + ERROR( "Couldn't open libasound.so: %s", dlerror() ); + } + + _snd_lib_error_set_handler = ( int ( * )( snd_lib_error_handler_t ) ) dlsym( alsa_lib, "snd_lib_error_set_handler" ); + _snd_strerror = ( const char * ( * )( int ) ) dlsym( alsa_lib, "snd_strerror" ); + _snd_pcm_open = ( int ( * ) ( snd_pcm_t **, const char *, snd_pcm_stream_t, int ) ) dlsym( alsa_lib, "snd_pcm_open" ); + _snd_pcm_set_params = ( int ( * ) ( snd_pcm_t *, snd_pcm_format_t, snd_pcm_access_t, unsigned int, unsigned int, int, unsigned int ) ) dlsym( alsa_lib, "snd_pcm_set_params" ); + _snd_pcm_writen = ( snd_pcm_sframes_t ( * ) ( snd_pcm_t *, void **, snd_pcm_uframes_t ) ) dlsym( alsa_lib, "snd_pcm_writen" ); + _snd_pcm_recover = ( int ( * )( snd_pcm_t *, int, int ) ) dlsym( alsa_lib, "snd_pcm_recover" ); + _snd_pcm_close = ( int ( * ) ( snd_pcm_t * ) ) dlsym( alsa_lib, "snd_pcm_close" ); + + if( + _snd_lib_error_set_handler == NULL + || _snd_strerror == NULL + || _snd_pcm_open == NULL + || _snd_pcm_set_params == NULL + || _snd_pcm_writen == NULL + || _snd_pcm_recover == NULL + || _snd_pcm_close == NULL + ) { + ERROR( "Couldn't load ALSA functions" ); + } + + _snd_lib_error_set_handler( audio_error_handler ); + + audio_inited = true; + } const int channels = 2; const int sample_rate = 44100; const int ms = 1000; const int latency = 10 * ms; - int err_open = snd_pcm_open( &device->pcm, "default", SND_PCM_STREAM_PLAYBACK, 0 ); + 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 - ERROR( "Couldn't open sound output: %s", snd_strerror( err_open ) ); + ERROR( "Couldn't open sound output: %s", _snd_strerror( err_open ) ); } - int err_params = snd_pcm_set_params( device->pcm, + int err_params = _snd_pcm_set_params( device->pcm, 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 - ERROR( "Couldn't configure sound output: %s", snd_strerror( err_params ) ); + ERROR( "Couldn't configure sound output: %s", _snd_strerror( err_params ) ); } } -inline void audio_output_close( AudioOutputDevice * device ) { - int err = snd_pcm_close( device->pcm ); +void audio_output_close( AudioOutputDevice * device ) { + int err = _snd_pcm_close( device->pcm ); if( err != 0 ) { // TODO: maybe don't kill the program - ERROR( "Couldn't close sound output: %s", snd_strerror( err ) ); + ERROR( "Couldn't close sound output: %s", _snd_strerror( err ) ); } } -inline void audio_output_write( AudioOutputDevice * device, s16 * samples, size_t num_samples ) { +void audio_output_write( AudioOutputDevice * device, s16 * samples, size_t num_samples ) { for( u32 i = 0; 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 ); + 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 ); + _snd_pcm_recover( device->pcm, written, 1 ); } else { i += written; @@ -69,4 +117,4 @@ inline void audio_output_write( AudioOutputDevice * device, s16 * samples, size_ } } -#endif // _LINUX_AUDIO_H_ +#endif diff --git a/os.mk b/os.mk @@ -1,7 +1,7 @@ # Makefile OS detection ifneq ($(shell uname -s),Darwin) CXXFLAGS += -fPIC - LDFLAGS += -lGL -lglfw -ldl -lasound + LDFLAGS += -lGL -lglfw -ldl else LDFLAGS += -framework OpenGL -lglfw3 endif diff --git a/platform_audio.h b/platform_audio.h @@ -1,5 +1,5 @@ -#ifndef _PLATFORM_AUDIO_H_ -#define _PLATFORM_AUDIO_H_ +// #ifndef _PLATFORM_AUDIO_H_ +// #define _PLATFORM_AUDIO_H_ #if defined( __linux__ ) #include "linux_audio.h" @@ -7,4 +7,4 @@ #error new platform #endif -#endif // _PLATFORM_AUDIO_H_ +// #endif // _PLATFORM_AUDIO_H_