/** * @brief Initializes the sound subsystem. * * @return 0 on success. */ int sound_al_init (void) { int ret; const ALchar* dev; ALuint s; ALint freq; ALint attribs[4] = { 0, 0, 0, 0 }; /* Default values. */ ret = 0; /* we'll need a mutex */ sound_lock = SDL_CreateMutex(); soundLock(); /* Get the sound device. */ dev = alcGetString( NULL, ALC_DEFAULT_DEVICE_SPECIFIER ); /* opening the default device */ al_device = alcOpenDevice(NULL); if (al_device == NULL) { WARN("Unable to open default sound device"); ret = -1; goto snderr_dev; } /* Query EFX extension. */ if (conf.al_efx) { al_info.efx = alcIsExtensionPresent( al_device, "ALC_EXT_EFX" ); if (al_info.efx == AL_TRUE) { attribs[0] = ALC_MAX_AUXILIARY_SENDS; attribs[1] = 4; } } else al_info.efx = AL_FALSE; /* Create the OpenAL context */ al_context = alcCreateContext( al_device, attribs ); if (sound_lock == NULL) { WARN("Unable to create OpenAL context"); ret = -2; goto snderr_ctx; } /* Clear the errors */ alGetError(); /* Set active context */ if (alcMakeContextCurrent( al_context )==AL_FALSE) { WARN("Failure to set default context"); ret = -4; goto snderr_act; } /* Get context information. */ alcGetIntegerv( al_device, ALC_FREQUENCY, sizeof(freq), &freq ); /* Try to enable EFX. */ if (al_info.efx == AL_TRUE) al_enableEFX(); else { al_info.efx_reverb = AL_FALSE; al_info.efx_echo = AL_FALSE; } /* Allocate source for music. */ alGenSources( 1, &music_source ); /* Check for errors. */ al_checkErr(); /* Start allocating the sources - music has already taken his */ source_nstack = 0; source_mstack = 0; while (source_nstack < SOUND_MAX_SOURCES) { if (source_mstack < source_nstack+1) { /* allocate more memory */ source_mstack += 32; source_stack = realloc( source_stack, sizeof(ALuint) * source_mstack ); } alGenSources( 1, &s ); source_stack[source_nstack] = s; /* Distance model defaults. */ alSourcef( s, AL_MAX_DISTANCE, 5000. ); alSourcef( s, AL_ROLLOFF_FACTOR, 1. ); alSourcef( s, AL_REFERENCE_DISTANCE, 500. ); /* Set the filter. */ if (al_info.efx == AL_TRUE) alSource3i( s, AL_AUXILIARY_SEND_FILTER, efx_directSlot, 0, AL_FILTER_NULL ); /* Check for error. */ if (alGetError() == AL_NO_ERROR) source_nstack++; else break; } /* Reduce ram usage. */ source_mstack = source_nstack; source_stack = realloc( source_stack, sizeof(ALuint) * source_mstack ); /* Copy allocated sources to total stack. */ source_ntotal = source_mstack; source_total = malloc( sizeof(ALuint) * source_mstack ); memcpy( source_total, source_stack, sizeof(ALuint) * source_mstack ); /* Copy allocated sources to all stack. */ source_nall = source_mstack; source_all = malloc( sizeof(ALuint) * source_mstack ); memcpy( source_all, source_stack, sizeof(ALuint) * source_mstack ); /* Set up how sound works. */ alDistanceModel( AL_INVERSE_DISTANCE_CLAMPED ); alDopplerFactor( 1. ); sound_al_env( SOUND_ENV_NORMAL, 0. ); /* Check for errors. */ al_checkErr(); /* we can unlock now */ soundUnlock(); /* debug magic */ DEBUG("OpenAL started: %d Hz", freq); DEBUG("Renderer: %s", alGetString(AL_RENDERER)); if (al_info.efx == AL_FALSE) DEBUG("Version: %s without EFX", alGetString(AL_VERSION)); else DEBUG("Version: %s with EFX %d.%d", alGetString(AL_VERSION), al_info.efx_major, al_info.efx_minor); DEBUG(); return 0; /* * error handling */ snderr_act: alcDestroyContext( al_context ); snderr_ctx: al_context = NULL; alcCloseDevice( al_device ); snderr_dev: al_device = NULL; soundUnlock(); SDL_DestroyMutex( sound_lock ); sound_lock = NULL; return ret; }
/** * @brief Initializes the sound subsystem. * * @return 0 on success. */ int sound_al_init (void) { int ret; ALuint s; ALint freq; ALint attribs[4] = { 0, 0, 0, 0 }; /* Default values. */ ret = 0; /* we'll need a mutex */ sound_lock = SDL_CreateMutex(); soundLock(); /* opening the default device */ al_device = alcOpenDevice(NULL); if (al_device == NULL) { WARN(_("Unable to open default sound device")); ret = -1; goto snderr_dev; } /* Query EFX extension. */ if (conf.al_efx) { al_info.efx = alcIsExtensionPresent( al_device, "ALC_EXT_EFX" ); if (al_info.efx == AL_TRUE) { attribs[0] = ALC_MAX_AUXILIARY_SENDS; attribs[1] = 4; } } else al_info.efx = AL_FALSE; /* Create the OpenAL context */ al_context = alcCreateContext( al_device, attribs ); if (al_context == NULL) { WARN(_("Unable to create OpenAL context")); ret = -2; goto snderr_ctx; } /* Clear the errors */ alGetError(); /* Set active context */ if (alcMakeContextCurrent( al_context )==AL_FALSE) { WARN(_("Failure to set default context")); ret = -4; goto snderr_act; } /* Get context information. */ alcGetIntegerv( al_device, ALC_FREQUENCY, sizeof(freq), &freq ); /* Try to enable EFX. */ if (al_info.efx == AL_TRUE) al_enableEFX(); else { al_info.efx_reverb = AL_FALSE; al_info.efx_echo = AL_FALSE; } /* Allocate source for music. */ alGenSources( 1, &music_source ); /* Check for errors. */ al_checkErr(); /* Start allocating the sources - music has already taken his */ source_nstack = 0; source_mstack = 0; while (source_nstack < conf.snd_voices) { if (source_mstack < source_nstack+1) { /* allocate more memory */ if (source_mstack == 0) source_mstack = conf.snd_voices; else source_mstack *= 2; source_stack = realloc( source_stack, sizeof(ALuint) * source_mstack ); } alGenSources( 1, &s ); source_stack[source_nstack] = s; /* How OpenAL distance model works: * * Clamped: * gain = distance_function( CLAMP( AL_REFERENCE_DISTANCE, AL_MAX_DISTANCE, distance ) ); * * Distance functions: * AL_REFERENCE_DISTANCE * * Inverse = ------------------------------------------------------------------------------ * AL_REFERENCE_DISTANCE + AL_ROLLOFF_FACTOR ( distance - AL_REFERENCE_DISTANCE ) * * 1 - AL_ROLLOFF_FACTOR ( distance - AL_REFERENCE_DISTANCE ) * * Linear = ---------------------------------------------------------- * AL_MAX_DISTANCE - AL_REFERENCE_DISTANCE * * / distance \ -AL_ROLLOFF_FACTOR * * Exponential = | --------------------- | * \ AL_REFERENCE_DISTANCE / * * * Some values: * * model falloff reference 100 1000 5000 10000 * linear 1 500 1.000 0.947 0.526 0.000 * inverse 1 500 1.000 0.500 0.100 0.050 * exponent 1 500 1.000 0.500 0.100 0.050 * inverse 0.5 500 1.000 0.667 0.182 0.095 * exponent 0.5 500 1.000 0.707 0.316 0.223 * inverse 2 500 1.000 0.333 0.052 0.026 * exponent 2 500 1.000 0.250 0.010 0.003 */ alSourcef( s, AL_REFERENCE_DISTANCE, 500. ); /* Close distance to clamp at (doesn't get louder). */ alSourcef( s, AL_MAX_DISTANCE, 25000. ); /* Max distance to clamp at (doesn't get quieter). */ alSourcef( s, AL_ROLLOFF_FACTOR, 1. ); /* Determines how it drops off. */ /* Set the filter. */ if (al_info.efx == AL_TRUE) alSource3i( s, AL_AUXILIARY_SEND_FILTER, efx_directSlot, 0, AL_FILTER_NULL ); /* Check for error. */ if (alGetError() == AL_NO_ERROR) source_nstack++; else break; } /* Reduce ram usage. */ source_mstack = source_nstack; source_stack = realloc( source_stack, sizeof(ALuint) * source_mstack ); /* Copy allocated sources to total stack. */ source_ntotal = source_mstack; source_total = malloc( sizeof(ALuint) * source_mstack ); memcpy( source_total, source_stack, sizeof(ALuint) * source_mstack ); /* Copy allocated sources to all stack. */ source_nall = source_mstack; source_all = malloc( sizeof(ALuint) * source_mstack ); memcpy( source_all, source_stack, sizeof(ALuint) * source_mstack ); /* Set up how sound works. */ alDistanceModel( AL_INVERSE_DISTANCE_CLAMPED ); /* Clamping is fundamental so it doesn't sound like crap. */ alDopplerFactor( 1. ); sound_al_env( SOUND_ENV_NORMAL, 0. ); /* Check for errors. */ al_checkErr(); /* we can unlock now */ soundUnlock(); /* debug magic */ DEBUG(_("OpenAL started: %d Hz"), freq); DEBUG(_("Renderer: %s"), alGetString(AL_RENDERER)); if (al_info.efx == AL_FALSE) DEBUG(_("Version: %s without EFX"), alGetString(AL_VERSION)); else DEBUG(_("Version: %s with EFX %d.%d"), alGetString(AL_VERSION), al_info.efx_major, al_info.efx_minor); DEBUG(""); return ret; /* * error handling */ snderr_act: alcDestroyContext( al_context ); snderr_ctx: al_context = NULL; alcCloseDevice( al_device ); snderr_dev: al_device = NULL; soundUnlock(); SDL_DestroyMutex( sound_lock ); sound_lock = NULL; return ret; }