/* ================= S_AL_SoundInfo ================= */ static void S_AL_SoundInfo( void ) { Com_Printf( "OpenAL info:\n" ); Com_Printf( " Vendor: %s\n", qalGetString( AL_VENDOR ) ); Com_Printf( " Version: %s\n", qalGetString( AL_VERSION ) ); Com_Printf( " Renderer: %s\n", qalGetString( AL_RENDERER ) ); Com_Printf( " AL Extensions: %s\n", qalGetString( AL_EXTENSIONS ) ); Com_Printf( " ALC Extensions: %s\n", qalcGetString( alDevice, ALC_EXTENSIONS ) ); if(qalcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT")) { Com_Printf(" Device: %s\n", qalcGetString(alDevice, ALC_DEVICE_SPECIFIER)); Com_Printf("Available Devices:\n%s", s_alAvailableDevices->string); } }
/* * S_ListDevices_f */ static void S_ListDevices_f( void ) { char *device, *defaultDevice, *curDevice; Com_Printf( "Available OpenAL devices:\n" ); defaultDevice = ( char * )qalcGetString( NULL, ALC_DEFAULT_DEVICE_SPECIFIER ); curDevice = ( char * )qalcGetString( alDevice, ALC_DEVICE_SPECIFIER ); device = ( char * )qalcGetString( NULL, ALC_DEVICE_SPECIFIER ); for( ; *device; device += strlen( device ) + 1 ) { if( defaultDevice && !strcmp( device, defaultDevice ) ) Com_Printf( "(def) : " ); else if( curDevice && !strcmp( device, curDevice ) ) Com_Printf( "(cur) : " ); else Com_Printf( " : " ); Com_Printf( "%s\n", device ); } }
void SndAl_InitCapture( qboolean usingAL ) { const char *inputdevice = NULL; #ifdef USE_OPENAL_DLOPEN // Load QAL if we are called from the base sound driver if ( !usingAL ) { s_alDriver = si.Cvar_Get( "s_alDriver", ALDRIVER_DEFAULT, CVAR_ARCHIVE | CVAR_LATCH ); if ( !QAL_Init( s_alDriver->string ) ) { si.Printf( PRINT_ALL, "Failed to load library: \"%s\".\n", s_alDriver->string ); return; } } #endif // !!! FIXME: some of these alcCaptureOpenDevice() values should be cvars. // !!! FIXME: add support for capture device enumeration. // !!! FIXME: add some better error reporting. s_alCapture = si.Cvar_Get( "s_alCapture", "1", CVAR_ARCHIVE | CVAR_LATCH ); if ( !s_alCapture->integer ) { si.Printf( PRINT_ALL, "OpenAL capture support disabled by user ('+set s_alCapture 1' to enable)\n" ); } else { if ( !qalcIsExtensionPresent( NULL, "ALC_EXT_capture" ) ) { si.Printf( PRINT_ALL, "No ALC_EXT_CAPTURE support, can't record audio.\n" ); } else { char inputdevicenames[ 16384 ] = ""; const char *inputdevicelist; const char *defaultinputdevice; int curlen; capture_ext = qtrue; // get all available input devices + the default input device name. inputdevicelist = qalcGetString( NULL, ALC_CAPTURE_DEVICE_SPECIFIER ); defaultinputdevice = qalcGetString( NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER ); // dump a list of available devices to a cvar for the user to see. #ifndef MACOS_X while ( ( curlen = strlen( inputdevicelist ) ) ) { si.strcat( inputdevicenames, sizeof( inputdevicenames ), inputdevicelist ); si.strcat( inputdevicenames, sizeof( inputdevicenames ), "\n" ); inputdevicelist += curlen + 1; } #endif s_alAvailableInputDevices = si.Cvar_Get( "s_alAvailableInputDevices", inputdevicenames, CVAR_ROM | CVAR_NORESTART ); // !!! FIXME: 8000Hz is what Speex narrowband mode needs, but we // !!! FIXME: should probably open the capture device after // !!! FIXME: initializing Speex so we can change to wideband // !!! FIXME: if we like. si.Printf( PRINT_ALL, "OpenAL default capture device is '%s'\n", defaultinputdevice ); alCaptureDevice = qalcCaptureOpenDevice( inputdevice, 8000, AL_FORMAT_MONO16, 4096 ); if ( !alCaptureDevice && inputdevice ) { si.Printf( PRINT_ALL, "Failed to open OpenAL Input device '%s', trying default.\n", inputdevice ); alCaptureDevice = qalcCaptureOpenDevice( NULL, 8000, AL_FORMAT_MONO16, 4096 ); } si.Printf( PRINT_ALL, "OpenAL capture device %s.\n", ( alCaptureDevice == NULL ) ? "failed to open" : "opened" ); } } }
qboolean SndAl_Init( void ) { const char *device = NULL; // Original console variables s_volume = si.Cvar_Get( "s_volume", "0.8", CVAR_ARCHIVE ); s_musicVolume = si.Cvar_Get( "s_musicvolume", "0.25", CVAR_ARCHIVE ); s_doppler = si.Cvar_Get( "s_doppler", "1", CVAR_ARCHIVE ); // New console variables s_precache = si.Cvar_Get( "al_precache", "1", CVAR_ARCHIVE ); s_gain = si.Cvar_Get( "al_gain", "0.4", CVAR_ARCHIVE ); s_sources = si.Cvar_Get( "al_sources", "64", CVAR_ARCHIVE ); s_dopplerFactor = si.Cvar_Get( "al_dopplerfactor", "1.0", CVAR_ARCHIVE ); s_dopplerSpeed = si.Cvar_Get( "al_dopplerspeed", "2200", CVAR_ARCHIVE ); s_minDistance = si.Cvar_Get( "al_mindistance", "80", CVAR_ARCHIVE ); s_rolloff = si.Cvar_Get( "al_rolloff", "0.25", CVAR_ARCHIVE ); s_alDevice = si.Cvar_Get( "al_device", "", CVAR_ARCHIVE | CVAR_LATCH ); #ifdef USE_OPENAL_DLOPEN s_alDriver = si.Cvar_Get( "al_driver", ALDRIVER_DEFAULT, CVAR_ARCHIVE ); #endif // USE_OPENAL_DLOPEN #ifdef USE_OPENAL_DLOPEN // Load QAL if ( !QAL_Init( s_alDriver->string ) ) { si.Printf( PRINT_ALL, "not initializing.\n" ); return qfalse; } #endif // USE_OPENAL_DLOPEN // Open default device device = s_alDevice->string; if ( device && !*device ) { device = NULL; } if ( qalcIsExtensionPresent( NULL, "ALC_ENUMERATION_EXT" ) ) { char devicenames[ 1024 ] = ""; const char *devicelist; #ifdef _WIN32 const char *defaultdevice; #endif int curlen; // get all available devices + the default device name. devicelist = qalcGetString( NULL, ALC_DEVICE_SPECIFIER ); #ifdef _WIN32 defaultdevice = qalcGetString( NULL, ALC_DEFAULT_DEVICE_SPECIFIER ); // check whether the default device is generic hardware. If it is, change to // Generic Software as that one works more reliably with various sound systems. // If it's not, use OpenAL's default selection as we don't want to ignore // native hardware acceleration. if ( !device && !strcmp( defaultdevice, "Generic Hardware" ) ) { device = "Generic Software"; } #endif // dump a list of available devices to a cvar for the user to see. #ifndef MACOS_X while ( ( curlen = strlen( devicelist ) ) ) { strcat( devicenames, devicelist ); strcat( devicenames, "\n" ); devicelist += curlen + 1; } #endif s_alAvailableDevices = si.Cvar_Get( "al_AvailableDevices", devicenames, CVAR_ROM | CVAR_NORESTART ); } alDevice = qalcOpenDevice( device ); if ( !alDevice && device ) { si.Printf( PRINT_ALL, "Failed to open OpenAL device '%s', trying default.\n", device ); alDevice = qalcOpenDevice( NULL ); } if ( !alDevice ) { #ifdef USE_OPENAL_DLOPEN QAL_Shutdown(); #endif si.Printf( PRINT_ALL, "Failed to open OpenAL device.\n" ); return qfalse; } // Create OpenAL context alContext = qalcCreateContext( alDevice, NULL ); if ( !alContext ) { #ifdef USE_OPENAL_DLOPEN QAL_Shutdown(); #endif qalcCloseDevice( alDevice ); si.Printf( PRINT_ALL, "Failed to create context\n" ); return qfalse; } qalcMakeContextCurrent( alContext ); qalcProcessContext( alContext ); // Print OpenAL information si.Printf( PRINT_ALL, "OpenAL initialised\n" ); si.Printf( PRINT_ALL, " Vendor: %s\n", qalGetString( AL_VENDOR ) ); si.Printf( PRINT_ALL, " Version: %s\n", qalGetString( AL_VERSION ) ); si.Printf( PRINT_ALL, " Renderer: %s\n", qalGetString( AL_RENDERER ) ); si.Printf( PRINT_ALL, " AL Extensions: %s\n", qalGetString( AL_EXTENSIONS ) ); si.Printf( PRINT_ALL, " ALC Extensions: %s\n", qalcGetString( alDevice, ALC_EXTENSIONS ) ); if ( qalcIsExtensionPresent( NULL, "ALC_ENUMERATION_EXT" ) ) { si.Printf( PRINT_ALL, " Device: %s\n", qalcGetString( alDevice, ALC_DEVICE_SPECIFIER ) ); si.Printf( PRINT_ALL, "Available Devices:\n%s", s_alAvailableDevices->string ); } // Check for Linux shutdown race condition if ( !strcmp( qalGetString( AL_VENDOR ), "J. Valenzuela" ) ) { snd_shutdown_bug = qtrue; } // Initialize sources, buffers, music al_buf_init(); al_src_init(); // Set up OpenAL parameters (doppler, etc) qalDistanceModel( AL_INVERSE_DISTANCE_CLAMPED ); qalDopplerFactor( s_dopplerFactor->value ); qalDopplerVelocity( s_dopplerSpeed->value );; // Add commands si.Cmd_AddCommand( "play", S_Play_f ); si.Cmd_AddCommand( "music", S_Music_f ); #ifdef USE_VOIP SndAl_InitCapture( qtrue ); #endif // Init successful si.Printf( PRINT_ALL, "initialization successful\n" ); return qtrue; }
/* ================= S_AL_Init ================= */ qboolean S_AL_Init( soundInterface_t *si ) { #if USE_OPENAL qboolean enumsupport, founddev = qfalse; if( !si ) { return qfalse; } // New console variables s_alPrecache = Cvar_Get( "s_alPrecache", "1", CVAR_ARCHIVE ); s_alGain = Cvar_Get( "s_alGain", "0.4", CVAR_ARCHIVE ); s_alSources = Cvar_Get( "s_alSources", "96", CVAR_ARCHIVE ); s_alDopplerFactor = Cvar_Get( "s_alDopplerFactor", "1.0", CVAR_ARCHIVE ); s_alDopplerSpeed = Cvar_Get( "s_alDopplerSpeed", "2200", CVAR_ARCHIVE ); s_alMinDistance = Cvar_Get( "s_alMinDistance", "120", CVAR_CHEAT ); s_alMaxDistance = Cvar_Get("s_alMaxDistance", "1024", CVAR_CHEAT); s_alRolloff = Cvar_Get( "s_alRolloff", "2", CVAR_CHEAT); s_alGraceDistance = Cvar_Get("s_alGraceDistance", "512", CVAR_CHEAT); s_alDriver = Cvar_Get( "s_alDriver", ALDRIVER_DEFAULT, CVAR_ARCHIVE ); // Load QAL if( !QAL_Init( s_alDriver->string ) ) { Com_Printf( "Failed to load library: \"%s\".\n", s_alDriver->string ); return qfalse; } // Device enumeration support (extension is implemented reasonably only on Windows right now). if((enumsupport = qalcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT"))) { char devicenames[1024] = ""; const char *devicelist; const char *defaultdevice; int curlen; // get all available devices + the default device name. devicelist = qalcGetString(NULL, ALC_DEVICE_SPECIFIER); defaultdevice = qalcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER); #ifdef _WIN32 // check whether the default device is generic hardware. If it is, change to // Generic Software as that one works more reliably with various sound systems. // If it's not, use OpenAL's default selection as we don't want to ignore // native hardware acceleration. if(!strcmp(defaultdevice, "Generic Hardware")) s_alDevice = Cvar_Get("s_alDevice", ALDEVICE_DEFAULT, CVAR_ARCHIVE | CVAR_LATCH); else #endif s_alDevice = Cvar_Get("s_alDevice", defaultdevice, CVAR_ARCHIVE | CVAR_LATCH); // dump a list of available devices to a cvar for the user to see. while((curlen = strlen(devicelist))) { Q_strcat(devicenames, sizeof(devicenames), devicelist); Q_strcat(devicenames, sizeof(devicenames), "\n"); // check whether the device we want to load is available at all. if(!strcmp(s_alDevice->string, devicelist)) founddev = qtrue; devicelist += curlen + 1; } s_alAvailableDevices = Cvar_Get("s_alAvailableDevices", devicenames, CVAR_ROM | CVAR_NORESTART); if(!founddev) { Cvar_ForceReset("s_alDevice"); founddev = 1; } } if(founddev) alDevice = qalcOpenDevice(s_alDevice->string); else alDevice = qalcOpenDevice(NULL); if( !alDevice ) { QAL_Shutdown( ); Com_Printf( "Failed to open OpenAL device.\n" ); return qfalse; } if(enumsupport) Cvar_Set("s_alDevice", qalcGetString(alDevice, ALC_DEVICE_SPECIFIER)); // Create OpenAL context alContext = qalcCreateContext( alDevice, NULL ); if( !alContext ) { QAL_Shutdown( ); qalcCloseDevice( alDevice ); Com_Printf( "Failed to create OpenAL context.\n" ); return qfalse; } qalcMakeContextCurrent( alContext ); // Initialize sources, buffers, music S_AL_BufferInit( ); S_AL_SrcInit( ); // Set up OpenAL parameters (doppler, etc) qalDistanceModel(AL_INVERSE_DISTANCE_CLAMPED); qalDopplerFactor( s_alDopplerFactor->value ); qalDopplerVelocity( s_alDopplerSpeed->value ); si->Shutdown = S_AL_Shutdown; si->StartSound = S_AL_StartSound; si->StartLocalSound = S_AL_StartLocalSound; si->StartBackgroundTrack = S_AL_StartBackgroundTrack; si->StopBackgroundTrack = S_AL_StopBackgroundTrack; si->RawSamples = S_AL_RawSamples; si->StopAllSounds = S_AL_StopAllSounds; si->ClearLoopingSounds = S_AL_ClearLoopingSounds; si->AddLoopingSound = S_AL_AddLoopingSound; si->AddRealLoopingSound = S_AL_AddRealLoopingSound; si->StopLoopingSound = S_AL_StopLoopingSound; si->Respatialize = S_AL_Respatialize; si->UpdateEntityPosition = S_AL_UpdateEntityPosition; si->Update = S_AL_Update; si->DisableSounds = S_AL_DisableSounds; si->BeginRegistration = S_AL_BeginRegistration; si->RegisterSound = S_AL_RegisterSound; si->ClearSoundBuffer = S_AL_ClearSoundBuffer; si->SoundInfo = S_AL_SoundInfo; si->SoundList = S_AL_SoundList; return qtrue; #else return qfalse; #endif }
/* * S_Init */ static qboolean S_Init( void *hwnd, int maxEntities, qboolean verbose ) { int numDevices; int userDeviceNum = -1; char *devices, *defaultDevice; cvar_t *s_openAL_device; alDevice = NULL; alContext = NULL; // get system default device identifier defaultDevice = ( char * )qalcGetString( NULL, ALC_DEFAULT_DEVICE_SPECIFIER ); if( !defaultDevice ) { Com_Printf( "Failed to get openAL default device\n" ); return qfalse; } s_openAL_device = trap_Cvar_Get( "s_openAL_device", ALDEVICE_DEFAULT ? ALDEVICE_DEFAULT : defaultDevice, CVAR_ARCHIVE|CVAR_LATCH_SOUND ); devices = ( char * )qalcGetString( NULL, ALC_DEVICE_SPECIFIER ); for( numDevices = 0; *devices; devices += strlen( devices ) + 1, numDevices++ ) { if( !Q_stricmp( s_openAL_device->string, devices ) ) { userDeviceNum = numDevices; // force case sensitive if( strcmp( s_openAL_device->string, devices ) ) trap_Cvar_ForceSet( "s_openAL_device", devices ); } } if( !numDevices ) { Com_Printf( "Failed to get openAL devices\n" ); return qfalse; } // the device assigned by the user is not available if( userDeviceNum == -1 ) { Com_Printf( "'s_openAL_device': incorrect device name, reseting to default\n" ); trap_Cvar_ForceSet( "s_openAL_device", ALDEVICE_DEFAULT ? ALDEVICE_DEFAULT : defaultDevice ); devices = ( char * )qalcGetString( NULL, ALC_DEVICE_SPECIFIER ); for( numDevices = 0; *devices; devices += strlen( devices ) + 1, numDevices++ ) { if( !Q_stricmp( s_openAL_device->string, devices ) ) userDeviceNum = numDevices; } if( userDeviceNum == -1 ) trap_Cvar_ForceSet( "s_openAL_device", defaultDevice ); } alDevice = qalcOpenDevice( (const ALchar *)s_openAL_device->string ); if( !alDevice ) { Com_Printf( "Failed to open device\n" ); return qfalse; } // Create context alContext = qalcCreateContext( alDevice, NULL ); if( !alContext ) { Com_Printf( "Failed to create context\n" ); return qfalse; } qalcMakeContextCurrent( alContext ); if( verbose ) { Com_Printf( "OpenAL initialized\n" ); if( numDevices ) { int i; Com_Printf( " Devices: " ); devices = ( char * )qalcGetString( NULL, ALC_DEVICE_SPECIFIER ); for( i = 0; *devices; devices += strlen( devices ) + 1, i++ ) Com_Printf( "%s%s", devices, ( i < numDevices - 1 ) ? ", " : "" ); Com_Printf( "\n" ); if( defaultDevice && *defaultDevice ) Com_Printf( " Default system device: %s\n", defaultDevice ); Com_Printf( "\n" ); } Com_Printf( " Device: %s\n", qalcGetString( alDevice, ALC_DEVICE_SPECIFIER ) ); Com_Printf( " Vendor: %s\n", qalGetString( AL_VENDOR ) ); Com_Printf( " Version: %s\n", qalGetString( AL_VERSION ) ); Com_Printf( " Renderer: %s\n", qalGetString( AL_RENDERER ) ); Com_Printf( " Extensions: %s\n", qalGetString( AL_EXTENSIONS ) ); } // Check for Linux shutdown race condition if( !Q_stricmp( qalGetString( AL_VENDOR ), "J. Valenzuela" ) ) snd_shutdown_bug = qtrue; qalDopplerFactor( s_doppler->value ); qalDopplerVelocity( s_sound_velocity->value > 0.0f ? s_sound_velocity->value : 0.0f ); if( qalSpeedOfSound ) // opelAL 1.1 only. alDopplerVelocity being deprecated qalSpeedOfSound( s_sound_velocity->value > 0.0f ? s_sound_velocity->value : 0.0f ); s_doppler->modified = qfalse; S_SetAttenuationModel( S_DEFAULT_ATTENUATION_MODEL, S_DEFAULT_ATTENUATION_MAXDISTANCE, S_DEFAULT_ATTENUATION_REFDISTANCE ); S_LockBackgroundTrack( qfalse ); if( !S_InitDecoders( verbose ) ) { Com_Printf( "Failed to init decoders\n" ); return qfalse; } if( !S_InitSources( maxEntities, verbose ) ) { Com_Printf( "Failed to init sources\n" ); return qfalse; } return qtrue; }
/* ================= S_AL_Init ================= */ qboolean S_AL_Init( soundInterface_t *si ) { #ifdef USE_OPENAL qboolean enumsupport, founddev = qfalse; int i; if( !si ) { return qfalse; } for (i = 0; i < MAX_RAW_STREAMS; i++) { streamSourceHandles[i] = -1; streamPlaying[i] = qfalse; streamSources[i] = 0; } // New console variables s_alPrecache = Cvar_Get( "s_alPrecache", "1", CVAR_ARCHIVE ); s_alGain = Cvar_Get( "s_alGain", "1.0", CVAR_ARCHIVE ); s_alSources = Cvar_Get( "s_alSources", "96", CVAR_ARCHIVE ); s_alDopplerFactor = Cvar_Get( "s_alDopplerFactor", "1.0", CVAR_ARCHIVE ); s_alDopplerSpeed = Cvar_Get( "s_alDopplerSpeed", "2200", CVAR_ARCHIVE ); s_alMinDistance = Cvar_Get( "s_alMinDistance", "120", CVAR_CHEAT ); s_alMaxDistance = Cvar_Get("s_alMaxDistance", "1024", CVAR_CHEAT); s_alRolloff = Cvar_Get( "s_alRolloff", "2", CVAR_CHEAT); s_alGraceDistance = Cvar_Get("s_alGraceDistance", "512", CVAR_CHEAT); s_alDriver = Cvar_Get( "s_alDriver", ALDRIVER_DEFAULT, CVAR_ARCHIVE ); // Load QAL if( !QAL_Init( s_alDriver->string ) ) { Com_Printf( "Failed to load library: \"%s\".\n", s_alDriver->string ); return qfalse; } // Device enumeration support (extension is implemented reasonably only on Windows right now). if((enumsupport = qalcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT"))) { char devicenames[1024] = ""; const char *devicelist; const char *defaultdevice; int curlen; // get all available devices + the default device name. devicelist = qalcGetString(NULL, ALC_DEVICE_SPECIFIER); defaultdevice = qalcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER); #ifdef _WIN32 // check whether the default device is generic hardware. If it is, change to // Generic Software as that one works more reliably with various sound systems. // If it's not, use OpenAL's default selection as we don't want to ignore // native hardware acceleration. if(!strcmp(defaultdevice, "Generic Hardware")) s_alDevice = Cvar_Get("s_alDevice", ALDEVICE_DEFAULT, CVAR_ARCHIVE | CVAR_LATCH); else #endif s_alDevice = Cvar_Get("s_alDevice", defaultdevice, CVAR_ARCHIVE | CVAR_LATCH); // dump a list of available devices to a cvar for the user to see. while((curlen = strlen(devicelist))) { Q_strcat(devicenames, sizeof(devicenames), devicelist); Q_strcat(devicenames, sizeof(devicenames), "\n"); // check whether the device we want to load is available at all. if(!strcmp(s_alDevice->string, devicelist)) founddev = qtrue; devicelist += curlen + 1; } s_alAvailableDevices = Cvar_Get("s_alAvailableDevices", devicenames, CVAR_ROM | CVAR_NORESTART); if(!founddev) { Cvar_ForceReset("s_alDevice"); founddev = 1; } } if(founddev) alDevice = qalcOpenDevice(s_alDevice->string); else alDevice = qalcOpenDevice(NULL); if( !alDevice ) { QAL_Shutdown( ); Com_Printf( "Failed to open OpenAL device.\n" ); return qfalse; } if(enumsupport) Cvar_Set("s_alDevice", qalcGetString(alDevice, ALC_DEVICE_SPECIFIER)); // Create OpenAL context alContext = qalcCreateContext( alDevice, NULL ); if( !alContext ) { QAL_Shutdown( ); qalcCloseDevice( alDevice ); Com_Printf( "Failed to create OpenAL context.\n" ); return qfalse; } qalcMakeContextCurrent( alContext ); // Initialize sources, buffers, music S_AL_BufferInit( ); S_AL_SrcInit( ); // Set up OpenAL parameters (doppler, etc) qalDistanceModel(AL_INVERSE_DISTANCE_CLAMPED); qalDopplerFactor( s_alDopplerFactor->value ); qalDopplerVelocity( s_alDopplerSpeed->value ); #ifdef USE_VOIP // !!! FIXME: some of these alcCaptureOpenDevice() values should be cvars. // !!! FIXME: add support for capture device enumeration. // !!! FIXME: add some better error reporting. s_alCapture = Cvar_Get( "s_alCapture", "1", CVAR_ARCHIVE | CVAR_LATCH ); if (!s_alCapture->integer) { Com_Printf("OpenAL capture support disabled by user ('+set s_alCapture 1' to enable)\n"); } #if USE_MUMBLE else if (cl_useMumble->integer) { Com_Printf("OpenAL capture support disabled for Mumble support\n"); } #endif else { #ifdef MACOS_X // !!! FIXME: Apple has a 1.1-compliant OpenAL, which includes // !!! FIXME: capture support, but they don't list it in the // !!! FIXME: extension string. We need to check the version string, // !!! FIXME: then the extension string, but that's too much trouble, // !!! FIXME: so we'll just check the function pointer for now. if (qalcCaptureOpenDevice == NULL) #else if (!qalcIsExtensionPresent(NULL, "ALC_EXT_capture")) #endif { Com_Printf("No ALC_EXT_capture support, can't record audio.\n"); } else { // !!! FIXME: 8000Hz is what Speex narrowband mode needs, but we // !!! FIXME: should probably open the capture device after // !!! FIXME: initializing Speex so we can change to wideband // !!! FIXME: if we like. Com_Printf("OpenAL default capture device is '%s'\n", qalcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER)); alCaptureDevice = qalcCaptureOpenDevice(NULL, 8000, AL_FORMAT_MONO16, 4096); Com_Printf( "OpenAL capture device %s.\n", (alCaptureDevice == NULL) ? "failed to open" : "opened"); } } #endif si->Shutdown = S_AL_Shutdown; si->StartSound = S_AL_StartSound; si->StartLocalSound = S_AL_StartLocalSound; si->StartBackgroundTrack = S_AL_StartBackgroundTrack; si->StopBackgroundTrack = S_AL_StopBackgroundTrack; si->RawSamples = S_AL_RawSamples; si->StopAllSounds = S_AL_StopAllSounds; si->ClearLoopingSounds = S_AL_ClearLoopingSounds; si->AddLoopingSound = S_AL_AddLoopingSound; si->AddRealLoopingSound = S_AL_AddRealLoopingSound; si->StopLoopingSound = S_AL_StopLoopingSound; si->Respatialize = S_AL_Respatialize; si->UpdateEntityPosition = S_AL_UpdateEntityPosition; si->Update = S_AL_Update; si->DisableSounds = S_AL_DisableSounds; si->BeginRegistration = S_AL_BeginRegistration; si->RegisterSound = S_AL_RegisterSound; si->SoundDuration = S_AL_SoundDuration; si->ClearSoundBuffer = S_AL_ClearSoundBuffer; si->SoundInfo = S_AL_SoundInfo; si->SoundList = S_AL_SoundList; #ifdef USE_VOIP si->StartCapture = S_AL_StartCapture; si->AvailableCaptureSamples = S_AL_AvailableCaptureSamples; si->Capture = S_AL_Capture; si->StopCapture = S_AL_StopCapture; si->MasterGain = S_AL_MasterGain; #endif return qtrue; #else return qfalse; #endif }
void QAL_Info(void) { Com_Printf("AL_VENDOR: %s\n", qalGetString(AL_VENDOR)); Com_Printf("AL_RENDERER: %s\n", qalGetString(AL_RENDERER)); Com_Printf("AL_VERSION: %s\n", qalGetString(AL_VERSION)); Com_DPrintf("AL_EXTENSIONS: %s\n", qalGetString(AL_EXTENSIONS)); // print out available devices if (qalcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT")) { const char *devs = qalcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER); Com_Printf("\nAvailable OpenAL devices:\n"); if (devs == NULL) { // no devices, might be an old OpenAL 1.0 or prior system... Com_Printf(S_COLOR_RED "- No devices found. Depending on your\n"); Com_Printf(S_COLOR_RED " platform this may be expected and\n"); Com_Printf(S_COLOR_RED " doesn't indicate a problem!\n"); } else { while (devs && *devs) { Com_Printf("- %s\n", devs); devs += strlen(devs) + 1; } } } // print out current device if (qalcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT")) { const char *devs = qalcGetString(device, ALC_DEVICE_SPECIFIER); Com_Printf("\nCurrent OpenAL device:\n"); if (devs == NULL) Com_Printf("- No OpenAL device in use\n"); else Com_Printf("- %s\n", devs); } // grab frequency for device { ALCint attr_size; ALCint * attributes; int i = 0; qalcGetIntegerv(device, ALC_ATTRIBUTES_SIZE, sizeof(attr_size), &attr_size); attributes = (ALCint *)Z_TagMalloc(attr_size * sizeof(ALCint), 0); qalcGetIntegerv(device, ALC_ALL_ATTRIBUTES, attr_size, attributes); for (i = 0; i < attr_size; i += 2) { if (attributes[i] == ALC_FREQUENCY) Com_Printf("ALC_FREQUENCY: %i\n", attributes[i + 1]); } Z_Free(attributes); } // check for hrtf support if (qalcIsExtensionPresent(device, "ALC_SOFT_HRTF")) { alcGetIntegerv(device, ALC_HRTF_SOFT, 1, &hrtf_state); if (!hrtf_state) { Com_Printf(S_COLOR_RED "HRTF not enabled!\n"); } else { const ALchar *name = alcGetString(device, ALC_HRTF_SPECIFIER_SOFT); Com_Printf(S_COLOR_GREEN "HRTF enabled, using %s\n", name); } } }
qboolean QAL_Init (void) { #ifdef _WIN32 char *libraries[] = { "soft_oal.dll", "openal32.dll", 0 }; #elif defined(__APPLE__) char *libraries[] = { "libopenal.dylib", "OpenAL-Soft.framework/OpenAL-Soft", "/System/Library/Frameworks/OpenAL.framework/OpenAL", 0 }; #else char *libraries[] = { "libopenal.so", "libopenal.so.0", "libopenal.so.1", 0 }; #endif char name[256]; // init cvars al_device = Cvar_Get ("al_device", "", CVAR_ARCHIVE); al_driver = Cvar_Get ("al_driver", "", CVAR_ARCHIVE); // prevent the user from screwing themselves by setting an invalid library strncpy(name, al_driver->string, sizeof(name)); Com_DPrintf("LoadLibrary (%s)\n", name); Sys_LoadLibrary(name, NULL, &handle); for (int i = 0; !handle && libraries[i] != NULL; i++) { Com_DPrintf("LoadLibrary (%s)\n", libraries[i]); Sys_LoadLibrary(libraries[i], NULL, &handle); if (handle) { // hey we got one! Cvar_Set("al_driver", libraries[i]); } } if (!handle) { Com_Printf(S_COLOR_RED "Loading %s failed! Disabling OpenAL.\n", al_driver->string); return false; } #define QAL(type,func) q##func = Sys_GetProcAddress (handle, #func); QALC_IMP QAL_IMP #undef QAL // open the OpenAL device Com_DPrintf("...opening OpenAL device: "); // get list of OpenAL devices { char* devices = (char*)qalcGetString(NULL, ALC_DEVICE_SPECIFIER); while (!device && devices && *devices != 0) { Com_DPrintf(S_COLOR_GREEN "...found OpenAL device: %s\n",devices); devices += strlen(devices) + 1; // on to the next device } } // try and open what the user has set as the device { const char *dev = al_device->string[0] ? al_device->string : qalcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER); Com_DPrintf("...attempting to open OpenAL device '%s': ", dev); device = qalcOpenDevice(dev); } // ugh, no device still, so open the default if (!device) { Com_DPrintf(S_COLOR_RED "failed!\n...attempting to open default OpenAL device: "); device = qalcOpenDevice(qalcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER)); } if (!device) goto fail; Com_DPrintf (S_COLOR_GREEN "ok\n"); // create OpenAL context Com_DPrintf ("...creating OpenAL context: "); context = qalcCreateContext (device, NULL); if (!context) goto fail; Com_DPrintf (S_COLOR_GREEN "ok\n"); // make OpenAL context current Com_DPrintf ("...making context current: "); if (!qalcMakeContextCurrent(context)) goto fail; Com_DPrintf (S_COLOR_GREEN "ok\n"); // enumerate available HRTFs, and reset the device using one if (qalcIsExtensionPresent(device, "ALC_SOFT_HRTF")) { ALCint num_hrtf; qalcGetIntegerv(device, ALC_NUM_HRTF_SPECIFIERS_SOFT, 1, &num_hrtf); if (!num_hrtf) { Com_DPrintf(S_COLOR_RED "...no HRTFs found\n"); } else { const char *hrtfname = "hrtf\\default-44100"; // default 44hz HRTF ALCint attr[5]; ALCint index = -1; ALCint i; Com_DPrintf("...available HRTFs:\n"); for (i = 0; i < num_hrtf; i++) { const ALCchar *name = qalcGetStringiSOFT(device, ALC_HRTF_SPECIFIER_SOFT, i); Com_DPrintf(" %d: %s\n", i, name); // Check if this is the HRTF the user requested if (hrtfname && strcmp(name, hrtfname) == 0) index = i; } i = 0; attr[i++] = ALC_HRTF_SOFT; attr[i++] = ALC_TRUE; if (index == -1) { if (hrtfname) Com_DPrintf(S_COLOR_RED "HRTF \"%s\" not found\n", hrtfname); Com_DPrintf(S_COLOR_GREEN "Using default HRTF...\n"); } else { Com_DPrintf(S_COLOR_GREEN "Selecting HRTF %d...\n", index); attr[i++] = ALC_HRTF_ID_SOFT; attr[i++] = index; } attr[i] = 0; if (!qalcResetDeviceSOFT(device, attr)) goto fail; } } return true; fail: Com_DPrintf (S_COLOR_RED "failed\n"); QAL_Shutdown (); return false; }
/* * S_Init */ qboolean S_Init( void *hwnd, int maxEntities, qboolean verbose ) { int numDevices; int userDeviceNum = -1; char *devices, *defaultDevice; soundpool = S_MemAllocPool( "OpenAL sound module" ); alDevice = NULL; alContext = NULL; #ifdef OPENAL_RUNTIME if( !QAL_Init( ALDRIVER, verbose ) ) { #ifdef ALDRIVER_ALT if( !QAL_Init( ALDRIVER_ALT, verbose ) ) #endif { Com_Printf( "Failed to load OpenAL library: %s\n", ALDRIVER ); goto fail_no_device; } } #endif // get system default device identifier defaultDevice = ( char * )qalcGetString( NULL, ALC_DEFAULT_DEVICE_SPECIFIER ); if( !defaultDevice ) { Com_Printf( "Failed to get openAL default device\n" ); goto fail_no_device; } s_openAL_device = trap_Cvar_Get( "s_openAL_device", ALDEVICE_DEFAULT ? ALDEVICE_DEFAULT : defaultDevice, CVAR_ARCHIVE|CVAR_LATCH_SOUND ); devices = ( char * )qalcGetString( NULL, ALC_DEVICE_SPECIFIER ); for( numDevices = 0; *devices; devices += strlen( devices ) + 1, numDevices++ ) { if( !Q_stricmp( s_openAL_device->string, devices ) ) { userDeviceNum = numDevices; // force case sensitive if( strcmp( s_openAL_device->string, devices ) ) trap_Cvar_ForceSet( "s_openAL_device", devices ); } } if( !numDevices ) { Com_Printf( "Failed to get openAL devices\n" ); goto fail_no_device; } // the device assigned by the user is not available if( userDeviceNum == -1 ) { Com_Printf( "'s_openAL_device': incorrect device name, reseting to default\n" ); trap_Cvar_ForceSet( "s_openAL_device", ALDEVICE_DEFAULT ? ALDEVICE_DEFAULT : defaultDevice ); devices = ( char * )qalcGetString( NULL, ALC_DEVICE_SPECIFIER ); for( numDevices = 0; *devices; devices += strlen( devices ) + 1, numDevices++ ) { if( !Q_stricmp( s_openAL_device->string, devices ) ) userDeviceNum = numDevices; } if( userDeviceNum == -1 ) trap_Cvar_ForceSet( "s_openAL_device", defaultDevice ); } alDevice = qalcOpenDevice( (const ALchar *)s_openAL_device->string ); if( !alDevice ) { Com_Printf( "Failed to open device\n" ); goto fail_no_device; } // Create context alContext = qalcCreateContext( alDevice, NULL ); if( !alContext ) { Com_Printf( "Failed to create context\n" ); goto fail; } qalcMakeContextCurrent( alContext ); if( verbose ) { Com_Printf( "OpenAL initialized\n" ); if( numDevices ) { int i; Com_Printf( " Devices: " ); devices = ( char * )qalcGetString( NULL, ALC_DEVICE_SPECIFIER ); for( i = 0; *devices; devices += strlen( devices ) + 1, i++ ) Com_Printf( "%s%s", devices, ( i < numDevices - 1 ) ? ", " : "" ); Com_Printf( "\n" ); if( defaultDevice && *defaultDevice ) Com_Printf( " Default system device: %s\n", defaultDevice ); Com_Printf( "\n" ); } Com_Printf( " Device: %s\n", qalcGetString( alDevice, ALC_DEVICE_SPECIFIER ) ); Com_Printf( " Vendor: %s\n", qalGetString( AL_VENDOR ) ); Com_Printf( " Version: %s\n", qalGetString( AL_VERSION ) ); Com_Printf( " Renderer: %s\n", qalGetString( AL_RENDERER ) ); Com_Printf( " Extensions: %s\n", qalGetString( AL_EXTENSIONS ) ); } // Check for Linux shutdown race condition if( !Q_stricmp( qalGetString( AL_VENDOR ), "J. Valenzuela" ) ) snd_shutdown_bug = qtrue; s_volume = trap_Cvar_Get( "s_volume", "0.8", CVAR_ARCHIVE ); s_musicvolume = trap_Cvar_Get( "s_musicvolume", "0.5", CVAR_ARCHIVE ); s_doppler = trap_Cvar_Get( "s_doppler", "1.0", CVAR_ARCHIVE ); s_sound_velocity = trap_Cvar_Get( "s_sound_velocity", "10976", CVAR_DEVELOPER ); s_stereo2mono = trap_Cvar_Get ( "s_stereo2mono", "0", CVAR_ARCHIVE ); qalDopplerFactor( s_doppler->value ); qalDopplerVelocity( s_sound_velocity->value > 0.0f ? s_sound_velocity->value : 0.0f ); if( qalSpeedOfSound ) // opelAL 1.1 only. alDopplerVelocity being deprecated qalSpeedOfSound( s_sound_velocity->value > 0.0f ? s_sound_velocity->value : 0.0f ); s_doppler->modified = qfalse; S_SetAttenuationModel( S_DEFAULT_ATTENUATION_MODEL, S_DEFAULT_ATTENUATION_MAXDISTANCE, S_DEFAULT_ATTENUATION_REFDISTANCE ); S_LockBackgroundTrack( qfalse ); if( !S_InitDecoders( verbose ) ) { Com_Printf( "Failed to init decoders\n" ); goto fail; } if( !S_InitBuffers() ) { Com_Printf( "Failed to init buffers\n" ); goto fail; } if( !S_InitSources( maxEntities, verbose ) ) { Com_Printf( "Failed to init sources\n" ); goto fail; } #ifdef ENABLE_PLAY trap_Cmd_AddCommand( "play", S_Play ); #endif trap_Cmd_AddCommand( "music", S_Music ); trap_Cmd_AddCommand( "stopmusic", S_StopMusic ); trap_Cmd_AddCommand( "prevmusic", S_PrevMusic ); trap_Cmd_AddCommand( "nextmusic", S_NextMusic ); trap_Cmd_AddCommand( "pausemusic", S_PauseMusic ); trap_Cmd_AddCommand( "soundlist", S_SoundList ); trap_Cmd_AddCommand( "s_devices", S_ListDevices ); return qtrue; fail: if( alContext ) { if( !snd_shutdown_bug ) qalcMakeContextCurrent( NULL ); qalcDestroyContext( alContext ); alContext = NULL; } if( alDevice ) { qalcCloseDevice( alDevice ); alDevice = NULL; } fail_no_device: S_MemFreePool( &soundpool ); return qfalse; }