41#include "physfsrwops.h"
55#define SOUND_FADEOUT 100
60#define SOUND_SUFFIX_WAV ".wav"
61#define SOUND_SUFFIX_OGG ".ogg"
63#define voiceLock() SDL_LockMutex( voice_mutex )
64#define voiceUnlock() SDL_UnlockMutex( voice_mutex )
71typedef struct alSound_ {
84typedef enum voice_state_ {
98typedef struct alVoice_ {
113typedef struct alGroup_s {
221 ALfloat vx, ALfloat vy, ALint relative );
222static int al_load(
alSound *snd, SDL_RWops *rw,
const char *name );
223static int al_loadWav( ALuint *buf, SDL_RWops *rw );
224static int al_loadOgg( ALuint *buf, OggVorbis_File *vf );
228static void al_pausev( ALint n, ALuint *s );
248static size_t ovpack_read(
void *ptr,
size_t size,
size_t nmemb,
251 SDL_RWops *rw = datasource;
252 return (
size_t)SDL_RWread( rw, ptr, size, nmemb );
254static int ovpack_seek(
void *datasource, ogg_int64_t offset,
int whence )
256 SDL_RWops *rw = datasource;
257 return SDL_RWseek( rw, offset, whence );
259static int ovpack_close(
void *datasource )
261 SDL_RWops *rw = datasource;
262 return SDL_RWclose( rw );
264static int ovpack_closeFake(
void *datasource )
269static long ovpack_tell(
void *datasource )
271 SDL_RWops *rw = datasource;
272 return SDL_RWseek( rw, 0, SEEK_CUR );
275 .read_func = ovpack_read,
276 .seek_func = ovpack_seek,
277 .close_func = ovpack_close,
278 .tell_func = ovpack_tell };
280 .seek_func = ovpack_seek,
281 .close_func = ovpack_closeFake,
293 int ret, nattribs = 0;
295 ALint attribs[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
307 WARN( _(
"Unable to open default sound device" ) );
313 attribs[0] = ALC_MONO_SOURCES;
315 attribs[2] = ALC_STEREO_SOURCES;
322 if (
al_info.efx == AL_TRUE ) {
323 attribs[nattribs + 0] = ALC_MAX_AUXILIARY_SENDS;
324 attribs[nattribs + 1] = 4;
332 alcIsExtensionPresent(
al_device,
"ALC_SOFT_output_limiter" );
333 if (
al_info.output_limiter ) {
334 attribs[nattribs + 0] = ALC_OUTPUT_LIMITER_SOFT;
335 attribs[nattribs + 1] = ALC_TRUE;
342 WARN( _(
"Unable to create OpenAL context" ) );
348 if ( alcMakeContextCurrent(
al_context ) == AL_FALSE ) {
349 WARN( _(
"Failure to set default context" ) );
358 if (
al_info.output_limiter ) {
360 alcGetIntegerv(
al_device, ALC_OUTPUT_LIMITER_SOFT, 1, &limiter );
361 if ( limiter != ALC_TRUE )
362 WARN( _(
"Failed to set ALC_OUTPUT_LIMITER_SOFT" ) );
371 if (
al_info.efx == AL_TRUE ) {
386 alGenSources( 1, &s );
422 alSourcef( s, AL_REFERENCE_DISTANCE,
423 SOUND_REFERENCE_DISTANCE );
425 alSourcef( s, AL_MAX_DISTANCE,
426 SOUND_MAX_DISTANCE );
428 alSourcef( s, AL_ROLLOFF_FACTOR, 1. );
436 if ( alGetError() == AL_NO_ERROR )
443 WARN( _(
"OpenAL failed to initialize sources" ) );
464 AL_INVERSE_DISTANCE_CLAMPED );
475 DEBUG( _(
"OpenAL started: %d Hz" ),
al_info.freq );
476 DEBUG( _(
"Renderer: %s" ), alGetString( AL_RENDERER ) );
478 DEBUG( _(
"Version: %s with EFX %d.%d" ), alGetString( AL_VERSION ),
481 DEBUG( _(
"Version: %s without EFX" ), alGetString( AL_VERSION ) );
511 if ( strcmp( alGetString( AL_VERSION ),
"1.1 ALSOFT 1.19.1" ) == 0 ) {
512 DEBUG( _(
"Crashing ALSOFT version detected, disabling EFX" ) );
518 alcGetIntegerv(
al_device, ALC_MAX_AUXILIARY_SENDS, 1,
524 nalGenAuxiliaryEffectSlots = alGetProcAddress(
"alGenAuxiliaryEffectSlots" );
525 nalDeleteAuxiliaryEffectSlots =
526 alGetProcAddress(
"alDeleteAuxiliaryEffectSlots" );
527 nalIsAuxiliaryEffectSlot = alGetProcAddress(
"alIsAuxiliaryEffectSlot" );
528 nalAuxiliaryEffectSloti = alGetProcAddress(
"alAuxiliaryEffectSloti" );
529 nalAuxiliaryEffectSlotiv = alGetProcAddress(
"alAuxiliaryEffectSlotiv" );
530 nalAuxiliaryEffectSlotf = alGetProcAddress(
"alAuxiliaryEffectSlotf" );
531 nalAuxiliaryEffectSlotfv = alGetProcAddress(
"alAuxiliaryEffectSlotfv" );
532 nalGetAuxiliaryEffectSloti = alGetProcAddress(
"alGetAuxiliaryEffectSloti" );
533 nalGetAuxiliaryEffectSlotiv =
534 alGetProcAddress(
"alGetAuxiliaryEffectSlotiv" );
535 nalGetAuxiliaryEffectSlotf = alGetProcAddress(
"alGetAuxiliaryEffectSlotf" );
536 nalGetAuxiliaryEffectSlotfv =
537 alGetProcAddress(
"alGetAuxiliaryEffectSlotfv" );
538 nalGenFilters = alGetProcAddress(
"alGenFilters" );
539 nalDeleteFilters = alGetProcAddress(
"alDeleteFilters" );
540 nalFilteri = alGetProcAddress(
"alFilteri" );
541 nalFilteriv = alGetProcAddress(
"alFilteriv" );
542 nalFilterf = alGetProcAddress(
"alFilterf" );
543 nalFilterfv = alGetProcAddress(
"alFilterfv" );
544 nalGenEffects = alGetProcAddress(
"alGenEffects" );
545 nalDeleteEffects = alGetProcAddress(
"alDeleteEffects" );
546 nalEffecti = alGetProcAddress(
"alEffecti" );
547 nalEffectiv = alGetProcAddress(
"alEffectiv" );
548 nalEffectf = alGetProcAddress(
"alEffectf" );
549 nalEffectfv = alGetProcAddress(
"alEffectfv" );
550 if ( !nalGenAuxiliaryEffectSlots || !nalDeleteAuxiliaryEffectSlots ||
551 !nalIsAuxiliaryEffectSlot || !nalAuxiliaryEffectSloti ||
552 !nalAuxiliaryEffectSlotiv || !nalAuxiliaryEffectSlotf ||
553 !nalAuxiliaryEffectSlotfv || !nalGetAuxiliaryEffectSloti ||
554 !nalGetAuxiliaryEffectSlotiv || !nalGetAuxiliaryEffectSlotf ||
555 !nalGetAuxiliaryEffectSlotfv || !nalGenFilters || !nalDeleteFilters ||
556 !nalFilteri || !nalFilteriv || !nalFilterf || !nalFilterfv ||
557 !nalGenEffects || !nalDeleteEffects || !nalEffecti || !nalEffectiv ||
558 !nalEffectf || !nalEffectfv ) {
559 DEBUG( _(
"OpenAL EFX functions not found, disabling EFX." ) );
569 nalEffecti(
efx_reverb, AL_EFFECT_TYPE, AL_EFFECT_REVERB );
570 if ( alGetError() != AL_NO_ERROR ) {
571 DEBUG( _(
"OpenAL Reverb not found, disabling." ) );
583 nalEffecti(
efx_echo, AL_EFFECT_TYPE, AL_EFFECT_ECHO );
584 if ( alGetError() != AL_NO_ERROR ) {
585 DEBUG( _(
"OpenAL Echo not found, disabling." ) );
592 nalEffectf(
efx_echo, AL_ECHO_DELAY, 0.207 );
596 alListenerf( AL_METERS_PER_UNIT, 5. );
614 if ( conf.nosound ) {
628 WARN( _(
"Sound disabled." ) );
635 WARN( _(
"Unable to create voice mutex." ) );
641 if ( ( conf.sound > 1. ) || ( conf.sound < 0. ) ) {
642 WARN( _(
"Sound has invalid value, clamping to [0:1]." ) );
643 conf.sound =
CLAMP( 0., 1., conf.sound );
654 WARN( _(
"Music disabled." ) );
731 if (
al_info.efx == AL_TRUE ) {
733 if (
al_info.efx_reverb == AL_TRUE )
735 if (
al_info.efx_echo == AL_TRUE )
741 alcMakeContextCurrent( NULL );
767 if ( strcmp( name,
sound_list[i].name ) == 0 )
770 WARN( _(
"Sound '%s' not found in sound list" ), name );
850 if ( target && ( p != NULL ) ) {
858 dist =
pow2( px - cx ) +
pow2( py - cy );
916 unsigned int t = SDL_GetTicks();
933 f = t - g->fade_timer;
934 if ( f < SOUND_FADEOUT ) {
936 d = 1. - (ALfloat)f / (ALfloat)SOUND_FADEOUT;
941 for (
int j = 0; j < g->nsources; j++ )
942 alSourcef( g->sources[j], AL_GAIN, v );
954 for (
int j = 0; j < g->nsources; j++ ) {
955 alSourceStop( g->sources[j] );
956 alSourcei( g->sources[j], AL_BUFFER, AL_NONE );
957 alSourcef( g->sources[j], AL_GAIN, v );
989 if ( tv->
next != NULL )
997 if ( v->next != NULL )
1062 if ( v->source != 0 ) {
1066 alSourceStop( v->source );
1094 if ( v->source != 0 ) {
1096 alSourceStop( v->source );
1118 ALfloat ori[6], pos[3], vel[3];
1135 alListenerfv( AL_ORIENTATION, ori );
1139 alListenerfv( AL_POSITION, pos );
1143 alListenerfv( AL_VELOCITY, vel );
1168 v =
CLAMP( 0, 1., ( s - 2 ) / 10. );
1179 }
else if ( playing ) {
1197 for (
int j = 0; j < g->nsources; j++ )
1198 alSourcef( g->sources[j], AL_PITCH, s * g->pitch );
1217 files = PHYSFS_enumerateFiles( SOUND_PATH );
1224 for (
size_t i = 0; files[i] != NULL; i++ ) {
1228 int flen = strlen( files[i] );
1231 if ( flen < suflen )
1242 snprintf( path,
sizeof( path ), SOUND_PATH
"%s", files[i] );
1243 rw = PHYSFSRWOPS_openRead( path );
1246 len = flen - suflen;
1247 files[i][len] =
'\0';
1257 PHYSFS_freeList( files );
1276 svolume = (ALfloat)1. / pow( 2., ( 1. - vol ) * 8. );
1326 alDeleteBuffers( 1, &snd->
buf );
1361 g->sources = calloc( size,
sizeof( ALuint ) );
1365 for (
int i = 0; i < size; i++ ) {
1375 if (
al_info.efx_reverb == AL_TRUE ) {
1376 alSourcef( g->sources[i], AL_AIR_ABSORPTION_FACTOR, 0. );
1377 alSource3i( g->sources[i], AL_AUXILIARY_SEND_FILTER,
1378 AL_EFFECTSLOT_NULL, 0, AL_FILTER_NULL );
1431 for (
int j = 0; j < g->nsources; j++ ) {
1434 alGetSourcei( g->sources[j], AL_SOURCE_STATE, &state );
1437 if ( j == g->nsources - 1 ) {
1438 if ( state != AL_STOPPED )
1439 alSourceStop( g->sources[j] );
1442 else if ( ( state == AL_PLAYING ) || ( state == AL_PAUSED ) )
1446 alSourcei( g->sources[j], AL_BUFFER, s->
buf );
1449 alSourcei( g->sources[j], AL_SOURCE_RELATIVE, AL_TRUE );
1452 alSourcei( g->sources[j], AL_LOOPING, ( once ) ? AL_FALSE : AL_TRUE );
1458 alSourcef( g->sources[j], AL_GAIN, v );
1461 alSourcePlay( g->sources[j] );
1473 WARN( _(
"Group '%d' has no free sounds." ), group );
1477 WARN( _(
"Group '%d' not found." ), group );
1498 g->fade_timer = SDL_GetTicks();
1545static void groupSpeedReset(
alGroup_t *g )
1547 for (
int i = 0; i < g->nsources; i++ ) {
1549 alSourcef( g->sources[i], AL_PITCH,
sound_speed * g->pitch );
1551 alSourcef( g->sources[i], AL_PITCH, 1. );
1573 groupSpeedReset( g );
1602 for (
int j = 0; j < g->nsources; j++ )
1603 alSourcef( g->sources[j], AL_GAIN, v );
1627 groupSpeedReset( g );
1632void sound_setAbsorption(
double value )
1645 alSourcef( s, AL_AIR_ABSORPTION_FACTOR, value );
1666 switch ( env_type ) {
1667 case SOUND_ENV_NORMAL:
1669 alSpeedOfSound( 3433. );
1670 alDopplerFactor( 0.3 );
1672 if (
al_info.efx == AL_TRUE ) {
1678 sound_setAbsorption( 0. );
1682 case SOUND_ENV_NEBULA:
1686 alSpeedOfSound( 3433. / ( 1. + f * 2. ) );
1687 alDopplerFactor( 1.0 );
1689 if (
al_info.efx == AL_TRUE ) {
1690 if (
al_info.efx_reverb == AL_TRUE ) {
1692 nalEffectf(
efx_reverb, AL_REVERB_DECAY_TIME, 10. );
1693 nalEffectf(
efx_reverb, AL_REVERB_DECAY_HFRATIO, 0.5 );
1701 sound_setAbsorption( 3. * f );
1725 v = calloc( 1,
sizeof(
alVoice ) );
1747 if ( v->prev != NULL ) {
1750 if ( tv->
next != NULL )
1751 tv->
next->prev = tv;
1804 memset( &snd, 0,
sizeof(
alSound ) );
1805 ret =
al_load( &snd, rw, name );
1810 memcpy( sndl, &snd,
sizeof(
alSound ) );
1811 sndl->
name = strdup( name );
1821 SDL_RWops *rw = PHYSFSRWOPS_openRead( filename );
1832 for (
int i = 0; i < n; i++ ) {
1834 alGetSourcei( s[i], AL_SOURCE_STATE, &state );
1835 if ( state == AL_PLAYING )
1836 alSourcePause( s[i] );
1845 for (
int i = 0; i < n; i++ ) {
1847 alGetSourcei( s[i], AL_SOURCE_STATE, &state );
1848 if ( state == AL_PAUSED )
1849 alSourcePlay( s[i] );
1863 WARN( _(
"Group '%d' not found." ), group );
1877 SDL_AudioSpec wav_spec;
1882 SDL_RWseek( rw, 0, SEEK_SET );
1885 if ( SDL_LoadWAV_RW( rw, 0, &wav_spec, &wav_buffer, &wav_length ) == NULL ) {
1886 WARN( _(
"SDL_LoadWav_RW failed: %s" ), SDL_GetError() );
1891 switch ( wav_spec.format ) {
1894 format = ( wav_spec.channels == 1 ) ? AL_FORMAT_MONO8 : AL_FORMAT_STEREO8;
1899 ( wav_spec.channels == 1 ) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
1903 WARN( _(
"Big endian WAVs unsupported!" ) );
1906 WARN( _(
"Invalid WAV format!" ) );
1913 alGenBuffers( 1, buf );
1915 alBufferData( *buf, format, wav_buffer, wav_length, wav_spec.freq );
1920 SDL_FreeWAV( wav_buffer );
1931 return _(
"A read from media returned an error." );
1934 "Internal logic fault; indicates a bug or heap/stack corruption." );
1936 return _(
"Feature not implemented." );
1938 return _(
"Either an invalid argument, or incompletely initialized "
1939 "argument passed to libvorbisfile call" );
1941 return _(
"Bitstream is not Vorbis data." );
1943 return _(
"Invalid Vorbis bitstream header." );
1945 return _(
"Vorbis version mismatch." );
1947 return _(
"The given link exists in the Vorbis data stream, but is not "
1948 "decipherable due to garbage or corruption." );
1950 return _(
"The given stream is not seekable." );
1953 return _(
"Unknown vorbisfile error." );
1965void rg_filter(
float **pcm,
long channels,
long samples,
void *filter_param )
1968 float scale_factor = param->rg_scale_factor;
1969 float max_scale = param->rg_max_scale;
1972 if ( scale_factor > max_scale ) {
1973 for (
int i = 0; i < channels; i++ )
1974 for (
int j = 0; j < samples; j++ ) {
1975 float cur_sample = pcm[i][j] * scale_factor;
1981 if ( cur_sample < -0.5 )
1983 tanh( ( cur_sample + 0.5 ) / ( 1 - 0.5 ) ) * ( 1 - 0.5 ) -
1985 else if ( cur_sample > 0.5 )
1987 tanh( ( cur_sample - 0.5 ) / ( 1 - 0.5 ) ) * ( 1 - 0.5 ) +
1989 pcm[i][j] = cur_sample;
1991 }
else if ( scale_factor > 0.0 )
1992 for (
int i = 0; i < channels; i++ )
1993 for (
int j = 0; j < samples; j++ )
1994 pcm[i][j] *= scale_factor;
2014 ALfloat track_gain_db, track_peak;
2019 ret = ov_test_open( vf );
2021 WARN( _(
"Failed to finish loading Ogg file: %s" ),
2027 info = ov_info( vf, -1 );
2028 format = ( info->channels == 1 ) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
2029 len = ov_pcm_total( vf, -1 ) * info->channels *
sizeof( short );
2032 vc = ov_comment( vf, -1 );
2035 if ( ( tag = vorbis_comment_query( vc,
"replaygain_track_gain", 0 ) ) )
2036 track_gain_db = atof( tag );
2037 if ( ( tag = vorbis_comment_query( vc,
"replaygain_track_peak", 0 ) ) )
2038 track_peak = atof( tag );
2039 param.rg_scale_factor = pow( 10.0, ( track_gain_db + RG_PREAMP_DB ) / 20.0 );
2040 param.rg_max_scale = 1.0 / track_peak;
2043 data = malloc( len );
2048 while ( bytes_read > 0 ) {
2050 bytes_read = ov_read_filter( vf, &data[i], 4096,
2051 ( SDL_BYTEORDER == SDL_BIG_ENDIAN ), 2, 1,
2053 if ( bytes_read == OV_HOLE || bytes_read == OV_EBADLINK ||
2054 bytes_read == OV_EINVAL ) {
2055 WARN( _(
"Error reading from OGG file!" ) );
2063 alGenBuffers( 1, buf );
2065 alBufferData( *buf, format, data, len, info->rate );
2103 WARN( _(
"Failed to load sound file '%s'." ), name );
2126 ALint freq, bits, channels, size;
2129 WARN( _(
"Failed to load sound file '%s'." ), name );
2136 alGetBufferi( snd->
buf, AL_FREQUENCY, &freq );
2137 alGetBufferi( snd->
buf, AL_BITS, &bits );
2138 alGetBufferi( snd->
buf, AL_CHANNELS, &channels );
2139 alGetBufferi( snd->
buf, AL_SIZE, &size );
2140 if ( ( freq == 0 ) || ( bits == 0 ) || ( channels == 0 ) ) {
2141 WARN( _(
"Something went wrong when loading sound file '%s'." ), name );
2144 snd->
length = (double)size / (
double)( freq * ( bits / 8 ) * channels );
2167 double v =
svolume * g->volume;
2170 for (
int j = 0; j < g->nsources; j++ )
2171 alSourcef( g->sources[j], AL_GAIN, v );
2184 ALfloat vx, ALfloat vy, ALint relative )
2199 if ( v->source == 0 )
2206 alSourcei( v->source, AL_BUFFER, v->buffer );
2209 alSourcei( v->source, AL_SOURCE_RELATIVE, relative );
2212 if ( ( relative == AL_FALSE ) && ( s->
channels > 1 ) )
2213 WARN( _(
"Sound '%s' has %d channels but is being played as positional. "
2214 "It should be mono!" ),
2228 alSourcefv( v->source, AL_POSITION, v->pos );
2229 alSourcefv( v->source, AL_VELOCITY, v->vel );
2232 alSourcei( v->source, AL_LOOPING, AL_FALSE );
2235 alSourcePlay( v->source );
2267 if ( v->source == 0 ) {
2275 alGetSourcei( v->source, AL_SOURCE_STATE, &state );
2276 if ( state == AL_STOPPED ) {
2279 alSourcei( v->source, AL_BUFFER, AL_NONE );
2298 alSourcefv( v->source, AL_POSITION, v->pos );
2299 alSourcefv( v->source, AL_VELOCITY, v->vel );
Provides macros to work with dynamic arrays.
#define array_free(ptr_array)
Frees memory allocated and sets array to NULL.
static ALWAYS_INLINE int array_size(const void *array)
Returns number of elements in the array.
#define array_grow(ptr_array)
Increases the number of elements by one and returns the last element.
#define array_create(basic_type)
Creates a new dynamic array of ‘basic_type’.
void cam_getPos(double *x, double *y)
Gets the camera position.
int cam_getTarget(void)
Returns the camera's current target.
void music_update(double dt)
Updates the music.
int music_init(void)
Initializes the music subsystem.
Header file with generic functions and naev-specifics.
void spfxL_setSpeedVolume(double v)
Sets the speed volume due to autonav and the likes.
Pilot * pilot_get(unsigned int id)
Pulls a pilot out of the pilot_stack based on ID.
double pilot_sensorRange(void)
Returns the default sensor range for the current system.
int pilot_inRange(const Pilot *p, double x, double y)
Check to see if a position is in range of the pilot.
static int al_load(alSound *snd, SDL_RWops *rw, const char *name)
Loads the sound.
int sound_createGroup(int size)
Creates a sound group.
static alGroup_t * al_groups
static void al_resumev(ALint n, ALuint *s)
Acts like alSourcePlayv but with proper checks to just resume.
double sound_getVolumeLog(void)
Gets the current sound volume (logarithmic).
int sound_al_buffer(ALuint *buf, SDL_RWops *rw, const char *name)
Loads the sound.
double sound_getLength(int sound)
Gets the length of the sound buffer.
static int al_loadOgg(ALuint *buf, OggVorbis_File *vf)
Loads an ogg file from a tested format if possible.
static void al_updateVoice(alVoice *v)
Updates the voice.
static double snd_compression_gain
void sound_pitchGroup(int group, double pitch)
Sets the pitch of a group.
void sound_resume(void)
Resumes all the sounds.
static void sound_free(alSound *snd)
Frees the sound.
static ALCcontext * al_context
void rg_filter(float **pcm, long channels, long samples, void *filter_param)
This is the filter function for the decoded Ogg Vorbis stream.
void sound_resumeGroup(int group)
Resumes all the sounds in a group.
double sound_getVolume(void)
Gets the current sound volume (linear).
static int snd_compression
void sound_speedGroup(int group, int enable)
Sets whether or not the speed affects a group.
static ALfloat svolume_speed
static int al_loadWav(ALuint *buf, SDL_RWops *rw)
Loads a wav file from the rw if possible.
int source_newRW(SDL_RWops *rw, const char *name, unsigned int flags)
Loads a new sound source from a RWops.
static int sound_makeList(void)
Makes the list of available sounds.
static ALuint * source_total
static alVoice * voice_new(void)
Gets a new voice ready to be used.
static const char * vorbis_getErr(int err)
Gets the vorbisfile error in human readable form..
static alVoice * voice_pool
static alGroup_t * al_getGroup(int group)
Gets a group by ID.
static alVoice * voice_active
int sound_updateListener(double dir, double px, double py, double vx, double vy)
Updates the sound listener.
int sound_playPos(int sound, double px, double py, double vx, double vy)
Plays a sound based on position.
int sound_playGroup(int group, int sound, int once)
Plays a sound in a group.
static double sound_speed
void sound_exit(void)
Cleans up after the sound subsytem.
static ALuint * source_stack
void sound_stopGroup(int group)
Stops all the sounds in a group.
int sound_update(double dt)
Updates the sounds removing obsolete ones and such.
void sound_stopAll(void)
Stops all the playing voices.
int source_new(const char *filename, unsigned int flags)
Loads a new source from a file.
static int al_enableEFX(void)
Enables the OpenAL EFX extension.
static ALfloat svolume_lin
ov_callbacks sound_al_ovcall_noclose
static ALCdevice * al_device
int sound_init(void)
Initializes the sound subsystem.
void sound_pause(void)
Pauses all the sounds.
voice_state_t
The state of a voice.
int sound_get(const char *name)
Gets the buffer to sound of name.
static SDL_mutex * voice_mutex
int sound_env(SoundEnv_t env_type, double param)
Sets up the sound environment.
void sound_pauseGroup(int group)
Pauses all the sounds in a group.
static void al_volumeUpdate(void)
Internal volume update function.
ALuint sound_efx_directSlot
static alVoice * voice_get(int id)
Gets a voice by identifier.
static int sound_initialized
void sound_stop(int voice)
Stops a voice from playing.
ov_callbacks sound_al_ovcall
int sound_updatePos(int voice, double px, double py, double vx, double vy)
Updates the position of a voice.
int sound_al_updatePos(alVoice *v, double px, double py, double vx, double vy)
Updates the position of the sound.
static int voice_add(alVoice *v)
Adds a voice to the active voice stack.
int sound_play(int sound)
Plays the sound in the first available channel.
static alSound * sound_list
static ALuint * source_all
int sound_volume(const double vol)
Sets the volume.
static void al_pausev(ALint n, ALuint *s)
Acts like alSourcePausev but with proper checks.
static int sound_al_init(void)
Initializes the sound subsystem.
void sound_volumeGroup(int group, double volume)
Sets the volume of a group.
void sound_setSpeed(double s)
Sets the speed to play the sound at.
static int snd_compressionG
static int al_playVoice(alVoice *v, alSound *s, ALfloat px, ALfloat py, ALfloat vx, ALfloat vy, ALint relative)
Plays a voice.
The representation of an in-game pilot.
Represents a voice in the game.