void AL_Update(void) { int i; channel_t *ch; vec_t orientation[6]; if (!s_active) { return; } paintedtime = cl.time; // set listener parameters qalListener3f(AL_POSITION, AL_UnpackVector(listener_origin)); AL_CopyVector(listener_forward, orientation); AL_CopyVector(listener_up, orientation + 3); qalListenerfv(AL_ORIENTATION, orientation); qalListenerf(AL_GAIN, s_volume->value); qalDistanceModel(AL_LINEAR_DISTANCE_CLAMPED); // update spatialization for dynamic sounds ch = channels; for (i = 0; i < s_numchannels; i++, ch++) { if (!ch->sfx) continue; if (ch->autosound) { // autosounds are regenerated fresh each frame if (ch->autoframe != s_framecount) { AL_StopChannel(ch); continue; } } else { ALenum state; qalGetError(); qalGetSourcei(ch->srcnum, AL_SOURCE_STATE, &state); if (qalGetError() != AL_NO_ERROR || state == AL_STOPPED) { AL_StopChannel(ch); continue; } } #ifdef _DEBUG if (s_show->integer) { Com_Printf("%.1f %s\n", ch->master_vol, ch->sfx->name); // total++; } #endif AL_Spatialize(ch); // respatialize channel } s_framecount++; // add loopsounds AL_AddLoopSounds(); AL_IssuePlaysounds(); }
/* * Main update function. Called every frame, * performes all necessary calculations. */ void AL_Update ( void ) { q_int32_t i; channel_t *ch; vec_t orientation[6]; paintedtime = cl.time; /* set listener (player) parameters */ AL_CopyVector ( listener_forward, orientation ); AL_CopyVector ( listener_up, orientation + 3 ); qalListenerf ( AL_GAIN, s_volume->value ); qalListenerf ( AL_MAX_GAIN, s_openal_maxgain->value ); qalDistanceModel ( AL_LINEAR_DISTANCE_CLAMPED ); qalListener3f ( AL_POSITION, AL_UnpackVector ( listener_origin ) ); qalListenerfv ( AL_ORIENTATION, orientation ); /* update spatialization for dynamic sounds */ ch = channels; for ( i = 0; i < s_numchannels; i++, ch++ ) { if ( !ch->sfx ) { continue; } if ( ch->autosound ) { /* autosounds are regenerated fresh each frame */ if ( ch->autoframe != s_framecount ) { AL_StopChannel ( ch ); continue; } } else { ALenum state; qalGetError(); qalGetSourcei ( ch->srcnum, AL_SOURCE_STATE, &state ); if ( ( qalGetError() != AL_NO_ERROR ) || ( state == AL_STOPPED ) ) { AL_StopChannel ( ch ); continue; } } if ( s_show->value ) { Com_Printf ( "%3i %s\n", ch->master_vol, ch->sfx->name ); } /* respatialize channel */ AL_Spatialize ( ch ); } s_framecount++; /* add loopsounds */ AL_AddLoopSounds(); /* add music */ #ifdef HT_WITH_OGG OGG_Stream(); #endif AL_StreamUpdate(); AL_IssuePlaysounds(); }
/* * S_SetAttenuationModel */ void S_SetAttenuationModel( int model, float maxdistance, float refdistance ) { s_attenuation_model = model; s_attenuation_maxdistance = maxdistance; s_attenuation_refdistance = refdistance; switch( model ) { case 0: qalDistanceModel( AL_LINEAR_DISTANCE ); break; case 1: default: qalDistanceModel( AL_LINEAR_DISTANCE_CLAMPED ); break; case 2: qalDistanceModel( AL_INVERSE_DISTANCE ); break; case 3: qalDistanceModel( AL_INVERSE_DISTANCE_CLAMPED ); break; case 4: qalDistanceModel( AL_EXPONENT_DISTANCE ); break; case 5: qalDistanceModel( AL_EXPONENT_DISTANCE_CLAMPED ); break; } }
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_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 }