2024-01-07 19:47:58 +01:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Copyright ( C ) 2024 the OpenMoHAA team
This file is part of OpenMoHAA source code .
OpenMoHAA source code is free software ; you can redistribute it
and / or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation ; either version 2 of the License ,
or ( at your option ) any later version .
OpenMoHAA source code is distributed in the hope that it will be
useful , but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code ; if not , write to the Free Software
Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
# if USE_SOUND_NEW
# include "snd_local.h"
# include "snd_openal_new.h"
2024-01-12 00:04:36 +01:00
# include "client.h"
# include ".. / server / server.h"
# include <sys / stat.h>
2024-01-07 19:47:58 +01:00
typedef struct {
char * funcname ;
void * * funcptr ;
bool required ;
} extensions_table_t ;
# define MAX_MUSIC_SONGS 16
static int s_iNextLoopingWarning = 0 ;
static int s_iReverbType = 0 ;
static float s_fReverbLevel = 0 ;
static bool s_bReverbChanged = false ;
static bool s_bFading = false ;
static float s_fFadeVolume = 1.f ;
cvar_t * s_milesdriver ;
cvar_t * s_openaldevice ;
cvar_t * s_reverb ;
cvar_t * s_show_cpu ;
cvar_t * s_show_num_active_sounds ;
cvar_t * s_show_sounds ;
cvar_t * s_speaker_type ;
cvar_t * s_obstruction_cal_time ;
cvar_t * s_lastSoundTime ;
static float reverb_table [ ] = {
0.5f , 0.25f , 0.417f , 0.653f , 0.208f , 0.5f , 0.403f , 0.5f , 0.5f ,
0.361f , 0.5f , 0.153f , 0.361f , 0.44400001f , 0.25f , 0.111f , 0.111f , 0.19400001f ,
1.0f , 0.097000003f , 0.208f , 0.65200001f , 1.0f , 0.875f , 0.139f , 0.486f ,
} ;
static vec3_t vec_zero = { 0 , 0 , 0 } ;
int s_iNumMilesAudioProviders = 0 ;
bool s_bProvidersEmunerated = false ;
static bool al_initialized = false ;
static bool al_use_reverb = false ;
static float al_current_volume = 0 ;
static unsigned int al_frequency = 22050 ;
2024-01-12 00:04:36 +01:00
static ALCcontext * al_context_id = NULL ;
2024-01-07 19:47:58 +01:00
static ALCdevice * al_device = NULL ;
static ALboolean ( * _alutLoadMP3_LOKI ) ( unsigned int buffer , const byte * data , int length ) ;
static void ( * _alReverbScale_LOKI ) ( ) ;
static void ( * _alReverbDelay_LOKI ) ( ) ;
static qboolean music_active = qfalse ;
int music_current_mood = 0 ;
int music_fallback_mood = 0 ;
float old_music_volume = 1.f ;
float music_volume = 1.f ;
float new_music_volume = 1.f ;
float music_volume_fade_time = 0 ;
long int music_volume_start_time = 0 ;
int music_volume_direction = 0 ;
int music_volume_changed = 0 ;
int music_loaded = 0 ;
int music_numsongs = 0 ;
int music_currentsong = 0 ;
song_t music_songs [ MAX_MUSIC_SONGS ] ;
openal_internal_t openal ;
static float s_fFadeStartTime ;
static float s_fFadeStopTime ;
static char current_soundtrack [ 128 ] ;
2024-01-12 00:04:36 +01:00
static void S_OPENAL_PlayMP3 ( ) ;
static void S_OPENAL_StopMP3 ( ) ;
static void S_OPENAL_Pitch ( ) ;
static void S_OPENAL_reverb ( int iChannel , int iReverbType , float fReverbLevel ) ;
# define alDieIfError() __alDieIfError(__FILE__, __LINE__)
static void __alDieIfError ( const char * file , int line )
2024-01-07 19:47:58 +01:00
{
2024-01-12 00:04:36 +01:00
ALint alErr = qalGetError ( ) ;
if ( alErr ) {
Com_DPrintf ( " OpenAL error, %s, line %i: [%s]. \n " , file , line , qalGetString ( alErr ) ) ;
}
2024-01-07 19:47:58 +01:00
}
static void S_OPENAL_NukeSource ( ALuint * srcptr )
{
2024-01-12 00:04:36 +01:00
ALuint source ;
source = * srcptr ;
if ( ! * srcptr ) {
return ;
}
if ( ! qalIsSource ( * srcptr ) ) {
return ;
}
alDieIfError ( ) ;
qalSourceStop ( source ) ;
alDieIfError ( ) ;
qalSourcei ( source , AL_BUFFER , 0 ) ;
alDieIfError ( ) ;
qalDeleteSources ( 1 , srcptr ) ;
alDieIfError ( ) ;
* srcptr = 0 ;
2024-01-07 19:47:58 +01:00
}
static void S_OPENAL_NukeBuffer ( ALuint * bufptr )
{
2024-01-12 00:04:36 +01:00
if ( ! * bufptr ) {
return ;
}
if ( ! qalIsBuffer ( * bufptr ) ) {
return ;
}
alDieIfError ( ) ;
qalDeleteBuffers ( 1 , bufptr ) ;
alDieIfError ( ) ;
* bufptr = 0 ;
2024-01-07 19:47:58 +01:00
// FIXME: unimplemented
}
static void S_OPENAL_NukeChannel ( openal_channel * channel )
{
2024-01-12 00:04:36 +01:00
if ( ! channel ) {
return ;
}
S_OPENAL_NukeSource ( & channel - > source ) ;
S_OPENAL_NukeBuffer ( & channel - > buffer ) ;
if ( channel - > bufferdata ) {
delete [ ] channel - > bufferdata ;
}
2024-01-07 19:47:58 +01:00
}
static void S_OPENAL_NukeContext ( )
{
2024-01-12 00:04:36 +01:00
int i ;
Com_Printf ( " OpenAL: Destroying channels... \n " ) ;
for ( i = 0 ; i < MAX_OPENAL_CHANNELS ; + + i ) {
S_OPENAL_NukeChannel ( openal . channel [ i ] ) ;
}
Com_Printf ( " OpenAL: Channels destroyed successfully. \n " ) ;
for ( i = 0 ; i < s_numSfx ; i + + ) {
S_OPENAL_NukeBuffer ( & s_knownSfx [ i ] . buffer ) ;
}
S_OPENAL_NukeBuffer ( & openal . movieSFX . buffer ) ;
if ( al_context_id ) {
Com_Printf ( " OpenAL: Destroying context... \n " ) ;
qalcSuspendContext ( al_context_id ) ;
qalcMakeContextCurrent ( NULL ) ;
qalcDestroyContext ( al_context_id ) ;
al_context_id = NULL ;
Com_Printf ( " OpenAL: Context destroyed successfully. \n " ) ;
}
if ( al_device ) {
Com_Printf ( " OpenAL: Closing device... \n " ) ;
qalcCloseDevice ( al_device ) ;
al_device = NULL ;
Com_Printf ( " OpenAL: Device closed successfully. \n " ) ;
}
2024-01-07 19:47:58 +01:00
}
static bool S_OPENAL_InitContext ( )
{
2024-01-12 00:04:36 +01:00
const char * dev ;
int attrlist [ 6 ] ;
dev = 0 ;
if ( s_openaldevice ) {
dev = s_openaldevice - > string ;
}
if ( dev & & ! * dev ) {
dev = NULL ;
}
Com_Printf ( " OpenAL: Opening device %s... \n " , dev ? dev : " {default} " ) ;
al_device = qalcOpenDevice ( dev ) ;
if ( ! al_device ) {
Com_Printf ( " OpenAL: Could not open device \n " ) ;
S_OPENAL_NukeContext ( ) ;
return false ;
}
Com_Printf ( " OpenAL: Device opened successfully. \n " ) ;
al_frequency = 22050 ;
if ( s_khz - > integer = = 11 ) {
al_frequency = 11025 ;
} else if ( s_khz - > integer = = 44 ) {
al_frequency = 44100 ;
}
attrlist [ 0 ] = 256 ;
attrlist [ 1 ] = al_frequency ;
attrlist [ 2 ] = 258 ;
attrlist [ 3 ] = 0 ;
attrlist [ 4 ] = 0 ;
attrlist [ 5 ] = 0 ;
Com_Printf ( " OpenAL: Creating AL context... \n " ) ;
al_context_id = qalcCreateContext ( al_device , attrlist ) ;
if ( ! al_context_id ) {
Com_Printf ( " OpenAL: Could not create context \n " ) ;
S_OPENAL_NukeContext ( ) ;
return false ;
}
Com_Printf ( " OpenAL: Context created successfully. \n " ) ;
qalcMakeContextCurrent ( al_context_id ) ;
alDieIfError ( ) ;
Com_Printf ( " AL_VENDOR: %s \n " , qalGetString ( AL_VENDOR ) ) ;
alDieIfError ( ) ;
Com_Printf ( " AL_VERSION: %s \n " , qalGetString ( AL_VERSION ) ) ;
alDieIfError ( ) ;
Com_Printf ( " AL_RENDERER: %s \n " , qalGetString ( AL_RENDERER ) ) ;
alDieIfError ( ) ;
Com_Printf ( " AL_EXTENSIONS: %s \n " , qalGetString ( AL_EXTENSIONS ) ) ;
alDieIfError ( ) ;
qalDistanceModel ( AL_INVERSE_DISTANCE_CLAMPED ) ;
alDieIfError ( ) ;
qalcProcessContext ( al_context_id ) ;
alDieIfError ( ) ;
return true ;
2024-01-07 19:47:58 +01:00
}
static bool S_OPENAL_InitExtensions ( )
{
2024-01-12 00:04:36 +01:00
extensions_table_t extensions_table [ 4 ] = {
" alutLoadMP3_LOKI " ,
( void * * ) _alutLoadMP3_LOKI ,
true ,
" alReverbScale_LOKI " ,
( void * * ) _alReverbScale_LOKI ,
true ,
" alReverbDelay_LOKI " ,
( void * * ) _alReverbDelay_LOKI ,
true
} ;
extensions_table_t * i ;
for ( i = extensions_table ; i - > funcname ; + + i ) {
* i - > funcptr = NULL ;
}
for ( i = extensions_table ; i - > funcname ; + + i ) {
Com_Printf ( " AL extension: Looking up %ssymbol \" %s \" ... " , i - > required ? " required " : " " , i - > funcname ) ;
* i - > funcptr = qalGetProcAddress ( i - > funcname ) ;
if ( ! * i - > funcptr ) {
Com_Printf ( " ...not found! [%s] \n " , qalGetError ( ) ) ;
if ( i - > required ) {
S_OPENAL_NukeContext ( ) ;
return false ;
}
continue ;
}
Com_Printf ( " ...found. \n " ) ;
}
qalGetError ( ) ;
return true ;
2024-01-07 19:47:58 +01:00
}
static bool S_OPENAL_InitChannel ( int idx , openal_channel * chan )
{
2024-01-12 00:04:36 +01:00
openal . channel [ idx ] = chan ;
chan - > vOrigin [ 2 ] = 0.0 ;
chan - > vOrigin [ 1 ] = 0.0 ;
chan - > vOrigin [ 0 ] = 0.0 ;
chan - > fVolume = 1.0 ;
chan - > fNewPitchMult = 0.0 ;
chan - > fMinDist = 0.0 ;
chan - > fMaxDist = 0.0 ;
chan - > pSfx = 0 ;
chan - > iEntNum = 0 ;
chan - > iEntChannel = 0 ;
chan - > iBaseRate = 0 ;
chan - > iStartTime = 0 ;
chan - > iTime = 0 ;
chan - > iEndTime = 0 ;
chan - > iFlags = 0 ;
chan - > iPausedOffset = 0 ;
chan - > source = 0 ;
chan - > buffer = 0 ;
chan - > bufferdata = 0 ;
chan - > fading = FADE_NONE ;
chan - > fade_time = 0 ;
chan - > fade_start_time = 0 ;
chan - > song_number = 0 ;
qalGenSources ( 1 , & chan - > source ) ;
alDieIfError ( ) ;
qalSourcei ( chan - > source , 514 , 1 ) ;
alDieIfError ( ) ;
return true ;
2024-01-07 19:47:58 +01:00
}
qboolean S_OPENAL_Init ( )
{
2024-01-12 00:04:36 +01:00
int i ;
if ( al_initialized ) {
Com_DPrintf ( " S_OPENAL_Init(): Called when sound is already initialized! \n " ) ;
return qtrue ;
}
for ( i = 0 ; i < MAX_OPENAL_CHANNELS ; i + + ) {
openal . channel [ i ] = NULL ;
}
for ( i = 0 ; i < MAX_OPENAL_LOOP_SOUNDS ; i + + ) {
openal . loop_sounds [ i ] = { } ;
}
s_milesdriver = Cvar_Get ( " s_milesdriver " , " auto " , CVAR_SOUND_LATCH | CVAR_ARCHIVE ) ;
s_openaldevice = Cvar_Get ( " s_openaldevice " , " " , CVAR_SOUND_LATCH | CVAR_ARCHIVE ) ;
s_reverb = Cvar_Get ( " s_reverb " , " 0 " , CVAR_SOUND_LATCH | CVAR_ARCHIVE ) ;
s_show_cpu = Cvar_Get ( " s_show_cpu " , " 0 " , 0 ) ;
s_show_num_active_sounds = Cvar_Get ( " s_show_num_active_sounds " , " 0 " , 0 ) ;
s_show_sounds = Cvar_Get ( " s_show_sounds " , " 0 " , 0 ) ;
s_speaker_type = Cvar_Get ( " s_speaker_type " , " 0 " , CVAR_ARCHIVE ) ;
s_obstruction_cal_time = Cvar_Get ( " s_obstruction_cal_time " , " 500 " , CVAR_ARCHIVE ) ;
if ( ! Cvar_Get ( " s_initsound " , " 1 " , 0 ) - > integer ) {
Com_Printf ( " OpenAL: s_initsound set to zero...disabling audio. \n " ) ;
return true ;
}
if ( ! S_OPENAL_InitContext ( ) ) {
Com_Printf ( " OpenAL: initialization failed. No audio will play. \n " ) ;
return false ;
}
if ( ! S_OPENAL_InitExtensions ( ) ) {
Com_Printf ( " OpenAL: A required extension is missing. No audio will play. \n " ) ;
return false ;
}
al_use_reverb = false ;
if ( s_reverb - > integer ) {
STUB_DESC ( " reenable reverb support later. " ) ;
if ( al_use_reverb ) {
S_OPENAL_SetReverb ( s_iReverbType , s_fReverbLevel ) ;
} else {
Com_Printf ( " OpenAL: No reverb support. Reverb is disabled. \n " ) ;
}
}
al_current_volume = s_volume - > value * s_volume - > value ;
qalListenerf ( AL_GAIN , al_current_volume ) ;
alDieIfError ( ) ;
for ( i = 0 ; i < MAX_OPENAL_CHANNELS_3D ; i + + ) {
if ( ! S_OPENAL_InitChannel ( i , & openal . chan_3D [ i ] ) ) {
return false ;
}
}
for ( i = 0 ; i < MAX_OPENAL_CHANNELS_2D ; i + + ) {
if ( ! S_OPENAL_InitChannel ( i , & openal . chan_2D [ i ] ) ) {
return false ;
}
}
for ( i = 0 ; i < MAX_OPENAL_CHANNELS_2D_STREAM ; i + + ) {
if ( ! S_OPENAL_InitChannel ( i , & openal . chan_2D_stream [ i ] ) ) {
return false ;
}
}
for ( i = 0 ; i < MAX_OPENAL_SONGS ; i + + ) {
if ( ! S_OPENAL_InitChannel ( i , & openal . chan_song [ i ] ) ) {
return false ;
}
}
if ( ! S_OPENAL_InitChannel ( OPENAL_CHANNEL_MP3_ID , & openal . chan_mp3 ) ) {
return false ;
}
if ( ! S_OPENAL_InitChannel ( OPENAL_CHANNEL_TRIGGER_MUSIC_ID , & openal . chan_mp3 ) ) {
return false ;
}
if ( ! S_OPENAL_InitChannel ( OPENAL_CHANNEL_MOVIE_ID , & openal . chan_mp3 ) ) {
return false ;
}
Cmd_AddCommand ( " playmp3 " , S_OPENAL_PlayMP3 ) ;
Cmd_AddCommand ( " stopmp3 " , S_OPENAL_StopMP3 ) ;
Cmd_AddCommand ( " loadsoundtrack " , S_loadsoundtrack ) ;
Cmd_AddCommand ( " playsong " , S_PlaySong ) ;
Cmd_AddCommand ( " pitch " , S_OPENAL_Pitch ) ;
Cmd_AddCommand ( " tmstart " , S_TriggeredMusic_Start ) ;
Cmd_AddCommand ( " tmstartloop " , S_TriggeredMusic_StartLoop ) ;
Cmd_AddCommand ( " tmstop " , S_TriggeredMusic_Stop ) ;
S_OPENAL_ClearLoopingSounds ( ) ;
load_sfx_info ( ) ;
s_bProvidersEmunerated = true ;
al_initialized = true ;
return true ;
2024-01-07 19:47:58 +01:00
}
void S_OPENAL_Shutdown ( )
{
2024-01-12 00:04:36 +01:00
if ( ! al_initialized ) {
Com_DPrintf ( " S_OPENAL_Shutdown(): Called when sound is NOT initialized! \n " ) ;
return ;
}
S_OPENAL_StopAllSounds ( true ) ;
Cmd_RemoveCommand ( " playmp3 " ) ;
Cmd_RemoveCommand ( " stopmp3 " ) ;
Cmd_RemoveCommand ( " loadsoundtrack " ) ;
Cmd_RemoveCommand ( " playsong " ) ;
Cmd_RemoveCommand ( " pitch " ) ;
Cmd_RemoveCommand ( " tmstart " ) ;
Cmd_RemoveCommand ( " tmstartloop " ) ;
Cmd_RemoveCommand ( " tmstop " ) ;
S_OPENAL_NukeContext ( ) ;
s_bProvidersEmunerated = false ;
al_initialized = false ;
2024-01-07 19:47:58 +01:00
}
void S_FadeSound ( float fTime )
{
2024-01-12 00:04:36 +01:00
Com_Printf ( " Called FadeSound with: %f \n " , fTime ) ;
if ( fTime > 0 ) {
s_bFading = true ;
s_fFadeStartTime = cls . realtime ;
s_fFadeVolume = 1 ;
s_fFadeStopTime = cls . realtime + fTime ;
} else {
s_fFadeVolume = 1 ;
s_bFading = false ;
}
2024-01-07 19:47:58 +01:00
}
float S_GetBaseVolume ( )
{
2024-01-12 00:04:36 +01:00
return s_volume - > value * s_fFadeVolume ;
2024-01-07 19:47:58 +01:00
}
qboolean S_NeedFullRestart ( )
{
2024-01-12 00:04:36 +01:00
return Cvar_Get ( " s_initsound " , " 1 " , 0 ) - > integer ! = s_bLastInitSound ;
2024-01-07 19:47:58 +01:00
}
void S_PrintInfo ( )
{
2024-01-12 00:04:36 +01:00
const char * dev ;
Com_Printf ( " ----- Sound Info ----- \n " ) ;
if ( s_bSoundStarted ) {
dev = NULL ;
if ( s_openaldevice ) {
dev = s_openaldevice - > string ;
}
if ( ! dev | | ! * dev ) {
dev = " {default} " ;
}
Com_Printf ( " device - %s \n " , dev ) ;
if ( al_use_reverb ) {
Com_Printf ( " reverb - ON \n " ) ;
} else {
Com_Printf ( " reverb - OFF \n " ) ;
}
Com_Printf ( " samplebits - 16 \n " ) ;
Com_Printf ( " speed - %d \n " , al_frequency ) ;
if ( s_loadas8bit - > integer ) {
Com_Printf ( " Can NOT force all sounds to 8 bit in OpenAL, I think. \n " ) ;
}
} else {
Com_Printf ( " sound system not started \n " ) ;
}
Com_Printf ( " ---------------------- \n " ) ;
2024-01-07 19:47:58 +01:00
}
static void S_DumpStatus ( const char * pszChanName , int iChanNum , openal_channel * channel )
{
2024-01-12 00:04:36 +01:00
sfx_t * sfx ;
ALint status ;
sfx = channel - > pSfx ;
qalGetSourceiv ( channel - > source , AL_SOURCE_STATE , & status ) ;
alDieIfError ( ) ;
if ( status = = AL_PLAYING | | status = = AL_PAUSED ) {
const char * pszMode = status = = AL_PLAYING ? " playing " : " paused " ;
if ( sfx ) {
if ( sfx ! = ( sfx_t * ) - 16 & & sfx - > name [ 0 ] ) {
Com_Printf ( " %s channel %i - %s sfx %s \n " , pszChanName , iChanNum , pszMode , sfx - > name ) ;
} else {
Com_Printf ( " %s channel %i - %s with nameless sfx \n " , pszChanName , iChanNum , pszMode ) ;
}
} else {
Com_Printf ( " %s channel %i - %s with NULL sfx \n " , pszChanName , iChanNum , pszMode ) ;
}
}
2024-01-07 19:47:58 +01:00
}
void S_DumpInfo ( )
{
2024-01-12 00:04:36 +01:00
int i ;
for ( i = 0 ; i < MAX_OPENAL_CHANNELS_3D ; i + + ) {
S_DumpStatus ( " 3D " , i , openal . channel [ i ] ) ;
}
for ( i = 0 ; i < MAX_OPENAL_CHANNELS_2D ; i + + ) {
S_DumpStatus ( " 2D " , i , openal . channel [ MAX_OPENAL_CHANNELS_3D + i ] ) ;
}
for ( i = 0 ; i < MAX_OPENAL_CHANNELS_2D_STREAM ; i + + ) {
S_DumpStatus ( " 2D stream " , i , openal . channel [ MAX_OPENAL_CHANNELS_3D + MAX_OPENAL_CHANNELS_2D + i ] ) ;
}
for ( i = 0 ; i < MAX_OPENAL_MISC_CHANNELS ; i + + ) {
S_DumpStatus (
" Misc " ,
i ,
openal . channel [ MAX_OPENAL_CHANNELS_3D + MAX_OPENAL_CHANNELS_2D + MAX_OPENAL_CHANNELS_2D_STREAM + i ]
) ;
}
2024-01-07 19:47:58 +01:00
}
static void S_OPENAL_Pitch ( )
{
2024-01-12 00:04:36 +01:00
Com_Printf ( " S_OPENAL_Pitch() needs to be implemented! \n " ) ;
2024-01-07 19:47:58 +01:00
}
static bool S_OPENAL_LoadMP3 ( const char * _path , openal_channel * chan )
{
2024-01-12 00:04:36 +01:00
char path [ MAX_QPATH ] ;
FILE * in ;
size_t len ;
size_t rc ;
bool failed ;
chan - > stop ( ) ;
qalSourcei ( chan - > source , AL_BUFFER , 0 ) ;
alDieIfError ( ) ;
S_OPENAL_NukeBuffer ( & chan - > buffer ) ;
alDieIfError ( ) ;
Q_strncpyz ( path , _path , sizeof ( path ) ) ;
path [ MAX_QPATH - 1 ] = 0 ;
FS_CorrectCase ( path ) ;
in = fopen ( path , " rb " ) ;
if ( ! in ) {
Com_DPrintf ( " Failed to open MP3 \" %s \" for playback \n " , path ) ;
return false ;
}
fseek ( in , 0 , SEEK_END ) ;
len = ftell ( in ) ;
fseek ( in , 0 , SEEK_SET ) ;
chan - > bufferdata = new ALubyte [ len ] ;
rc = fread ( chan - > bufferdata , 1 , len , in ) ;
fclose ( in ) ;
if ( rc ! = len ) {
delete [ ] chan - > bufferdata ;
chan - > bufferdata = NULL ;
Com_DPrintf ( " Failed to read MP3 \" %s \" from disk \n " , path ) ;
return false ;
}
qalGenBuffers ( 1 , & chan - > buffer ) ;
alDieIfError ( ) ;
failed = ! _alutLoadMP3_LOKI ( chan - > buffer , chan - > bufferdata , rc ) ;
alDieIfError ( ) ;
delete [ ] chan - > bufferdata ;
chan - > bufferdata = NULL ;
if ( failed ) {
Com_DPrintf ( " Failed to decode MP3 file \" %s \" \n " , path ) ;
return false ;
}
qalSourcei ( chan - > source , AL_BUFFER , chan - > buffer ) ;
alDieIfError ( ) ;
chan - > set_no_3d ( ) ;
return true ;
2024-01-07 19:47:58 +01:00
}
static void S_OPENAL_PlayMP3 ( )
{
2024-01-12 00:04:36 +01:00
const char * path ;
if ( Cmd_Argc ( ) ! = 2 ) {
Com_Printf ( " playmp3 <mp3 file> \n " ) ;
return ;
}
path = Cmd_Argv ( 1 ) ;
if ( ! S_OPENAL_LoadMP3 ( path , & openal . chan_mp3 ) ) {
Com_Printf ( " Failed to play mp3 - %s \n " , path ) ;
return ;
}
openal . chan_mp3 . play ( ) ;
Com_Printf ( " Playing mp3 - %s \n " , path ) ;
2024-01-07 19:47:58 +01:00
}
static void S_OPENAL_StopMP3 ( )
{
2024-01-12 00:04:36 +01:00
S_OPENAL_NukeChannel ( & openal . chan_mp3 ) ;
2024-01-07 19:47:58 +01:00
}
void MUSIC_Pause ( )
{
2024-01-12 00:04:36 +01:00
int i ;
for ( i = 0 ; i < MAX_OPENAL_SONGS ; i + + ) {
openal . chan_song [ i ] . pause ( ) ;
}
2024-01-07 19:47:58 +01:00
}
void MUSIC_Unpause ( )
{
2024-01-12 00:04:36 +01:00
int i ;
for ( i = 0 ; i < MAX_OPENAL_SONGS ; i + + ) {
if ( openal . chan_song [ i ] . is_paused ( ) ) {
openal . chan_song [ i ] . play ( ) ;
}
}
2024-01-07 19:47:58 +01:00
}
void S_PauseSound ( )
{
2024-01-12 00:04:36 +01:00
int i ;
if ( ! s_bSoundStarted ) {
return ;
}
s_bSoundPaused = true ;
for ( i = 0 ; i < MAX_OPENAL_POSITION_CHANNELS ; i + + ) {
openal_channel * pChannel = openal . channel [ i ] ;
if ( ! pChannel ) {
continue ;
}
if ( pChannel - > iEntChannel = = CHAN_MENU ) {
continue ;
}
if ( ! pChannel - > is_playing ( ) ) {
continue ;
}
pChannel - > pause ( ) ;
}
if ( openal . chan_mp3 . is_playing ( ) ) {
openal . chan_mp3 . pause ( ) ;
}
MUSIC_Pause ( ) ;
S_TriggeredMusic_Pause ( ) ;
2024-01-07 19:47:58 +01:00
}
void S_UnpauseSound ( )
{
2024-01-12 00:04:36 +01:00
int i ;
if ( ! s_bSoundStarted ) {
return ;
}
s_bSoundPaused = true ;
for ( i = 0 ; i < MAX_OPENAL_POSITION_CHANNELS ; i + + ) {
openal_channel * pChannel = openal . channel [ i ] ;
if ( ! pChannel ) {
continue ;
}
if ( ! pChannel - > is_paused ( ) ) {
continue ;
}
pChannel - > play ( ) ;
}
if ( openal . chan_mp3 . is_paused ( ) ) {
openal . chan_mp3 . play ( ) ;
}
MUSIC_Unpause ( ) ;
S_TriggeredMusic_Unpause ( ) ;
s_bSoundPaused = false ;
2024-01-07 19:47:58 +01:00
}
static qboolean S_OPENAL_ShouldPlay ( sfx_t * pSfx )
{
2024-01-12 00:04:36 +01:00
if ( sfx_infos [ pSfx - > sfx_info_index ] . max_number_playing < = 0 ) {
return qtrue ;
}
int iRemainingTimesToPlay ;
int i ;
iRemainingTimesToPlay = sfx_infos [ pSfx - > sfx_info_index ] . max_number_playing ;
for ( i = 0 ; i < MAX_OPENAL_POSITION_CHANNELS ; i + + ) {
openal_channel * pChannel = openal . channel [ i ] ;
if ( ! pChannel ) {
continue ;
}
if ( pChannel - > pSfx = = pSfx & & pChannel - > is_playing ( ) ) {
iRemainingTimesToPlay - - ;
if ( ! iRemainingTimesToPlay ) {
return qfalse ;
}
}
}
return qtrue ;
2024-01-07 19:47:58 +01:00
}
2024-01-07 23:36:32 +01:00
static qboolean S_OPENAL_ShouldStart ( const vec3_t vOrigin , float fMinDist , float fMaxDist )
2024-01-07 19:47:58 +01:00
{
2024-01-12 00:04:36 +01:00
vec3_t vDir ;
vec3_t vListenerOrigin ;
vec3_t alvec ;
if ( ! al_initialized ) {
return false ;
}
qalGetListenerfv ( AL_POSITION , alvec ) ;
VectorScale ( alvec , 52.49f , vListenerOrigin ) ;
VectorSubtract ( vOrigin , vListenerOrigin , vDir ) ;
return Square ( fMaxDist ) > VectorLengthSquared ( vDir ) ;
2024-01-07 19:47:58 +01:00
}
static int S_OPENAL_PickChannelBase ( int iEntNum , int iEntChannel , int iFirstChannel , int iLastChannel )
{
2024-01-12 00:04:36 +01:00
int i ;
int iBestChannel ;
openal_channel * pChannel ;
iBestChannel = - 1 ;
if ( iEntNum ! = ENTITYNUM_NONE & & iEntChannel ) {
bool bStoppedChannel = false ;
for ( i = iFirstChannel ; i < = iLastChannel ; i + + ) {
pChannel = openal . channel [ i ] ;
if ( ! pChannel ) {
continue ;
}
if ( pChannel - > is_free ( ) ) {
iBestChannel = i ;
continue ;
}
if ( pChannel - > iEntNum = = iEntNum & & pChannel - > iEntChannel = = iEntChannel ) {
pChannel - > end_sample ( ) ;
bStoppedChannel = 1 ;
iBestChannel = i ;
break ;
}
}
if ( ! bStoppedChannel ) {
for ( i = 0 ; i < iFirstChannel ; + + i ) {
pChannel = openal . channel [ i ] ;
if ( ! pChannel | | pChannel - > is_free ( ) ) {
continue ;
}
if ( pChannel - > iEntNum = = iEntNum & & pChannel - > iEntChannel = = iEntChannel ) {
bStoppedChannel = 1 ;
break ;
}
}
if ( ! bStoppedChannel ) {
i = iLastChannel ;
while ( + + i < = 95 ) {
pChannel = openal . channel [ i ] ;
if ( ! pChannel | | pChannel - > is_free ( ) ) {
continue ;
}
if ( pChannel - > iEntNum = = iEntNum & & pChannel - > iEntChannel = = iEntChannel ) {
break ;
}
}
}
}
}
if ( iBestChannel < 0 ) {
int iBestTime = 0x7FFFFFFF ;
for ( i = iFirstChannel ; i < = iLastChannel ; i + + ) {
pChannel = openal . channel [ i ] ;
if ( ! pChannel ) {
continue ;
}
if ( pChannel - > is_free ( ) ) {
return i ;
}
if ( pChannel - > iEntNum = = s_iListenerNumber & & iEntNum ! = pChannel - > iEntNum ) {
continue ;
}
if ( pChannel - > iEntChannel < iEntChannel
| | ( pChannel - > iEntChannel = = iEntChannel & & pChannel - > iStartTime < iBestTime ) ) {
iBestChannel = i ;
iEntChannel = pChannel - > iEntChannel ;
iBestTime = pChannel - > iStartTime ;
}
}
}
return iBestChannel ;
2024-01-07 19:47:58 +01:00
}
static int S_OPENAL_PickChannel3D ( int iEntNum , int iEntChannel )
{
2024-01-12 00:04:36 +01:00
return S_OPENAL_PickChannelBase ( iEntNum , iEntChannel , 0 , MAX_OPENAL_CHANNELS_3D - 1 ) ;
2024-01-07 19:47:58 +01:00
}
static int S_OPENAL_PickChannel2D ( int iEntNum , int iEntChannel )
{
2024-01-12 00:04:36 +01:00
return S_OPENAL_PickChannelBase (
iEntNum , iEntChannel , MAX_OPENAL_CHANNELS_3D , MAX_OPENAL_CHANNELS_3D + MAX_OPENAL_CHANNELS_2D - 1
) ;
2024-01-07 19:47:58 +01:00
}
static int S_OPENAL_PickChannel2DStreamed ( int iEntNum , int iEntChannel )
{
2024-01-12 00:04:36 +01:00
return S_OPENAL_PickChannelBase (
iEntNum ,
iEntChannel ,
MAX_OPENAL_CHANNELS_3D + MAX_OPENAL_CHANNELS_2D ,
MAX_OPENAL_CHANNELS_3D + MAX_OPENAL_CHANNELS_2D + MAX_OPENAL_CHANNELS_2D_STREAM - 1
) ;
2024-01-07 19:47:58 +01:00
}
void callbackServer ( int entnum , int channel_number , const char * name )
{
2024-01-12 00:04:36 +01:00
if ( ! com_sv_running - > integer ) {
return ;
}
SV_SoundCallback ( entnum , channel_number , name ) ;
2024-01-07 19:47:58 +01:00
}
static void S_OPENAL_Start2DSound (
2024-01-07 23:36:32 +01:00
const vec3_t vOrigin ,
int iEntNum ,
int iEntChannel ,
sfx_t * pSfx ,
float fVolume ,
float fMinDistance ,
float fPitch ,
float fMaxDistance
2024-01-07 19:47:58 +01:00
)
{
2024-01-12 00:04:36 +01:00
int iRealEntNum ;
int iFreeChannel ;
openal_channel * pChannel ;
float fRealVolume ;
bool bSupportWaitTillSoundDone ;
iRealEntNum = iEntNum & ~ S_FLAG_DO_CALLBACK ;
if ( pSfx - > iFlags & SFX_FLAG_NO_DATA ) {
iFreeChannel = S_OPENAL_PickChannel2DStreamed ( iRealEntNum , iEntChannel ) ;
} else {
iFreeChannel = S_OPENAL_PickChannel2D ( iRealEntNum , iEntChannel ) ;
}
if ( iFreeChannel < 0 ) {
Com_DPrintf (
" Couldn't play %s sound '%s' for entity %i on channel %s \n " ,
( pSfx - > iFlags & SFX_FLAG_NO_DATA ) ? " 2Dstreamed " : " 2D " ,
pSfx - > name ,
iEntNum & ~ S_FLAG_DO_CALLBACK ,
S_ChannelNumToName ( iEntChannel )
) ;
return ;
}
if ( iEntNum & S_FLAG_DO_CALLBACK ) {
callbackServer ( iEntNum , iFreeChannel , pSfx - > name ) ;
}
pChannel = openal . channel [ iFreeChannel ] ;
pChannel - > force_free ( ) ;
if ( fVolume < 0 ) {
fVolume = 1 ;
}
fRealVolume = S_GetBaseVolume ( ) * fVolume ;
pChannel - > fVolume = fVolume ;
if ( pChannel - > iEntChannel = = CHAN_LOCAL ) {
pChannel - > iFlags | = CHANNEL_FLAG_LOCAL_LISTENER ;
} else {
pChannel - > iFlags & = ~ CHANNEL_FLAG_LOCAL_LISTENER ;
}
pChannel - > iFlags & = ~ CHANNEL_FLAG_PAUSED ;
if ( fMinDistance < 0.0 ) {
fMinDistance = 200.0 ;
}
pChannel - > fMinDist = fMinDistance ;
if ( fMaxDistance < 0.0 ) {
fMaxDistance = pChannel - > fMinDist * 64 ;
}
pChannel - > fMaxDist = fMaxDistance ;
pChannel - > fNewPitchMult = fPitch ;
pChannel - > pSfx = pSfx ;
pChannel - > iEntNum = iRealEntNum ;
pChannel - > iEntChannel = iEntChannel ;
if ( iEntNum = = ENTITYNUM_NONE ) {
VectorClear ( pChannel - > vOrigin ) ;
pChannel - > iFlags | = CHANNEL_FLAG_NO_ENTITY ;
pChannel - > iEntNum = 0 ;
if ( vOrigin ) {
pChannel - > vOrigin [ 0 ] = - vOrigin [ 0 ] ;
pChannel - > vOrigin [ 1 ] = vOrigin [ 2 ] ;
pChannel - > vOrigin [ 2 ] = - vOrigin [ 1 ] ;
}
} else {
pChannel - > iFlags & = ~ CHANNEL_FLAG_NO_ENTITY ;
pChannel - > iEntNum = iRealEntNum ;
if ( vOrigin ) {
pChannel - > vOrigin [ 0 ] = - vOrigin [ 0 ] ;
pChannel - > vOrigin [ 1 ] = vOrigin [ 2 ] ;
pChannel - > vOrigin [ 2 ] = - vOrigin [ 1 ] ;
bSupportWaitTillSoundDone = cl . serverTime - 1 < 0 ;
pChannel - > iTime = cl . serverTime - 1 ;
if ( bSupportWaitTillSoundDone ) {
pChannel - > iTime = 0 ;
}
} else {
VectorClear ( pChannel - > vOrigin ) ;
pChannel - > iTime = 0 ;
}
}
pChannel - > iStartTime = cl . serverTime ;
pChannel - > iEndTime = ( int ) ( cl . serverTime + pSfx - > time_length + 250.f ) ;
if ( iFreeChannel > MAX_OPENAL_CHANNELS_3D + MAX_OPENAL_CHANNELS_2D ) {
// streamed
if ( ! pChannel - > set_sfx ( pSfx ) ) {
Com_DPrintf ( " Set stream error - %s \n " , pSfx - > name ) ;
return ;
}
pChannel - > iBaseRate = pChannel - > sample_playback_rate ( ) ;
pChannel - > set_no_3d ( ) ;
fRealVolume = fRealVolume * 84.f ;
pChannel - > set_gain ( fRealVolume ) ;
pChannel - > play ( ) ;
} else {
pChannel - > stop ( ) ;
pChannel - > set_no_3d ( ) ;
pChannel - > set_sfx ( pSfx ) ;
pChannel - > set_gain ( fRealVolume ) ;
pChannel - > play ( ) ;
}
if ( s_show_sounds - > integer > 0 ) {
Com_DPrintf (
" 2D - %d (#%i) - %s (vol %f, mindist %f, maxdist %f) \n " ,
cl . serverTime ,
iFreeChannel ,
pSfx - > name ,
fVolume ,
fMinDistance ,
fMaxDistance
) ;
}
2024-01-07 19:47:58 +01:00
}
void S_OPENAL_StartSound (
2024-01-07 23:42:32 +01:00
const vec3_t vOrigin ,
int iEntNum ,
int iEntChannel ,
sfxHandle_t sfxHandle ,
float fVolume ,
float fMinDist ,
float fPitch ,
float fMaxDist ,
qboolean bStreamed
2024-01-07 19:47:58 +01:00
)
{
2024-01-12 00:04:36 +01:00
int iChannel ;
openal_channel * pChannel ;
sfx_info_t * pSfxInfo ;
sfx_t * pSfx ;
ALint state ;
bool bOnlyUpdate ;
bool bSupportWaitTillSoundDone ;
bOnlyUpdate = false ;
pSfx = & s_knownSfx [ sfxHandle ] ;
if ( bStreamed ) {
pSfx - > iFlags | = SFX_FLAG_NO_DATA ;
}
if ( ! S_OPENAL_ShouldPlay ( pSfx ) )
{
Com_DPrintf ( " ^~^~^ Not playing sound '%s' \n " , pSfx - > name ) ;
return ;
}
if ( ( pSfx - > iFlags & ( SFX_FLAG_NO_OFFSET | SFX_FLAG_NO_DATA | SFX_FLAG_MP3 ) ) | | iEntChannel = = CHAN_MENU | | iEntChannel = = CHAN_LOCAL )
{
S_OPENAL_Start2DSound ( vOrigin , iEntNum , iEntChannel , pSfx , fVolume , fMinDist , fPitch , fMaxDist ) ;
return ;
}
bSupportWaitTillSoundDone = ( iEntNum & S_FLAG_DO_CALLBACK ) ! = 0 ;
iEntNum & = ~ S_FLAG_DO_CALLBACK ;
pSfxInfo = & sfx_infos [ pSfx - > sfx_info_index ] ;
if ( pSfx - > iFlags & SFX_FLAG_NO_DATA ) {
Com_DPrintf ( " 3D sounds not supported - couldn't play '%s' \n " , pSfx - > name ) ;
return ;
}
iChannel = S_OPENAL_PickChannel3D ( iEntNum , iEntChannel ) ;
if ( iChannel < 0 )
{
Com_DPrintf ( " Couldn't play %s sound '%s' for entity %i on channel %s \n " , ( pSfx - > iFlags & SFX_FLAG_NO_DATA ) ? " 3Dstreamed " : " 3D " , pSfx - > name , iEntNum , S_ChannelNumToName ( iEntChannel ) ) ;
return ;
}
if ( bSupportWaitTillSoundDone ) {
callbackServer ( iEntNum , iChannel , pSfx - > name ) ;
}
pChannel = & openal . chan_3D [ iChannel ] ;
pChannel - > fNewPitchMult = fPitch ;
pChannel - > iEntChannel = iEntChannel ;
pChannel - > iFlags & = ~ ( CHANNEL_FLAG_PAUSED | CHANNEL_FLAG_LOCAL_LISTENER ) ;
state = pChannel - > get_state ( ) ;
if ( pChannel - > iEntNum = = iEntNum & & ( state = = AL_PLAYING | | state = = AL_PAUSED ) & & pChannel - > pSfx = = pSfx ) {
bOnlyUpdate = true ;
} else {
pChannel - > stop ( ) ;
pChannel - > iFlags & = ~ ( CHANNEL_FLAG_LOOPING | CHANNEL_FLAG_PAUSED | CHANNEL_FLAG_LOCAL_LISTENER ) ;
if ( ! pChannel - > set_sfx ( pSfx ) ) {
Com_DPrintf ( " Set sample error - %s \n " , pSfx - > name ) ;
return ;
}
}
if ( fMinDist < 0.0 )
{
fMinDist = 200.0 ;
fMaxDist = 12800.0 ;
}
pChannel - > fMinDist = fMinDist ;
pChannel - > fMaxDist = fMaxDist ;
if ( fVolume < 0.0 ) {
fVolume = 1.0 ;
}
pChannel - > fVolume = S_GetBaseVolume ( ) * fVolume ;
pChannel - > set_gain ( pChannel - > fVolume ) ;
if ( s_show_sounds - > integer > 0 ) {
Com_DPrintf (
" %d (#%i) - %s (vol %f, mindist %f, maxdist %f) \n " ,
cl . serverTime ,
iChannel ,
pSfx - > name ,
pChannel - > fVolume ,
fMinDist ,
fMaxDist ) ;
}
pChannel - > set_velocity ( 0 , 0 , 0 ) ;
if ( iEntNum = = ENTITYNUM_NONE ) {
if ( vOrigin ) {
pChannel - > vOrigin [ 0 ] = - vOrigin [ 0 ] ;
pChannel - > vOrigin [ 1 ] = vOrigin [ 2 ] ;
pChannel - > vOrigin [ 2 ] = - vOrigin [ 1 ] ;
} else {
//VectorClear(vOrigin);
// Fixed in OPM
// Tiny mistake found in original where the vOrigin parameter is set to 0
VectorClear ( pChannel - > vOrigin ) ;
}
pChannel - > set_position ( pChannel - > vOrigin [ 0 ] / 52.49f , pChannel - > vOrigin [ 1 ] / 52.49f , pChannel - > vOrigin [ 2 ] / 52.49f ) ;
pChannel - > iFlags | = CHANNEL_FLAG_NO_ENTITY ;
pChannel - > iEntNum = 0 ;
} else {
pChannel - > iEntNum = iEntNum ;
if ( vOrigin ) {
pChannel - > vOrigin [ 0 ] = - * vOrigin ;
pChannel - > vOrigin [ 1 ] = vOrigin [ 2 ] ;
pChannel - > vOrigin [ 2 ] = - vOrigin [ 1 ] ;
bSupportWaitTillSoundDone = cl . serverTime - 1 < 0 ;
pChannel - > iTime = cl . serverTime - 1 ;
if ( bSupportWaitTillSoundDone ) {
pChannel - > iTime = 0 ;
}
} else {
VectorClear ( pChannel - > vOrigin ) ;
pChannel - > iTime = 0 ;
}
}
if ( pSfxInfo - > loop_start ! = - 1 ) {
pChannel - > set_sample_loop_block ( pSfxInfo - > loop_start , pSfxInfo - > loop_end ) ;
pChannel - > set_sample_loop_count ( 0 ) ;
pChannel - > iFlags | = CHANNEL_FLAG_LOOPING ;
if ( s_show_sounds - > integer ) {
Com_DPrintf ( " loopblock - %d to %d \n " , pSfxInfo - > loop_start , pSfxInfo - > loop_end ) ;
}
} else {
pChannel - > set_sample_loop_count ( 1 ) ;
}
if ( ! bOnlyUpdate & & S_OPENAL_ShouldStart ( pChannel - > vOrigin , pChannel - > fMinDist , pChannel - > fMaxDist ) )
{
pChannel - > play ( ) ;
pChannel - > iEndTime = cl . serverTime + ( int ) pChannel - > pSfx - > time_length + 250 ;
pChannel - > iBaseRate = pChannel - > sample_playback_rate ( ) ;
pChannel - > iStartTime = cl . serverTime ;
}
2024-01-07 19:47:58 +01:00
}
void S_OPENAL_AddLoopingSound (
2024-01-07 23:36:32 +01:00
const vec3_t vOrigin ,
const vec3_t vVelocity ,
sfxHandle_t sfxHandle ,
float fVolume ,
float fMinDist ,
float fMaxDist ,
float fPitch ,
int iFlags
2024-01-07 19:47:58 +01:00
)
{
2024-01-12 00:04:36 +01:00
int i ;
int iFreeLoopSound ;
sfx_t * pSfx ;
openal_loop_sound_t * pLoopSound ;
iFreeLoopSound = - 1 ;
pSfx = & s_knownSfx [ sfxHandle ] ;
if ( ! pSfx ) {
return ;
}
for ( i = 0 ; i < ( MAX_OPENAL_CHANNELS_3D + MAX_OPENAL_CHANNELS_2D ) ; i + + ) {
pLoopSound = & openal . loop_sounds [ i ] ;
if ( pLoopSound - > pSfx = = pSfx & & ! pLoopSound - > bInUse ) {
iFreeLoopSound = i ;
break ;
}
}
if ( iFreeLoopSound < 0 ) {
for ( i = 0 ; i < ( MAX_OPENAL_CHANNELS_3D + MAX_OPENAL_CHANNELS_2D ) ; i + + ) {
pLoopSound = & openal . loop_sounds [ i ] ;
if ( ! pLoopSound - > pSfx & & ! pLoopSound - > bInUse ) {
iFreeLoopSound = i ;
pLoopSound - > bPlaying = false ;
break ;
}
}
}
if ( iFreeLoopSound < 0 ) {
if ( cls . realtime > = s_iNextLoopingWarning ) {
Com_DPrintf ( " Too many looping sounds \n " ) ;
s_iNextLoopingWarning = cls . realtime + 1000 ;
}
return ;
}
pLoopSound = & openal . loop_sounds [ iFreeLoopSound ] ;
pLoopSound - > vOrigin [ 0 ] = - vOrigin [ 0 ] ;
pLoopSound - > vOrigin [ 1 ] = vOrigin [ 2 ] ;
pLoopSound - > vOrigin [ 2 ] = - vOrigin [ 1 ] ;
pLoopSound - > vVelocity [ 0 ] = - vVelocity [ 0 ] / 52.49f / 500.f ;
pLoopSound - > vVelocity [ 1 ] = vVelocity [ 2 ] / 52.49f / 500.f ;
pLoopSound - > vVelocity [ 2 ] = - vVelocity [ 1 ] / 52.49f / 500.f ;
pLoopSound - > pSfx = pSfx ;
pLoopSound - > bInUse = true ;
pLoopSound - > iStartTime = cls . realtime ;
pLoopSound - > fBaseVolume = fVolume ;
pLoopSound - > fMinDist = fMinDist ;
pLoopSound - > fMaxDist = fMaxDist ;
pLoopSound - > fPitch = fPitch ;
pLoopSound - > iFlags = iFlags ;
pLoopSound - > bCombine = VectorCompare ( vVelocity , vec_zero ) = = 0 ;
if ( pLoopSound - > bCombine ) {
for ( i = 0 ; i < ( MAX_OPENAL_CHANNELS_3D + MAX_OPENAL_CHANNELS_2D ) ; i + + ) {
if ( openal . loop_sounds [ i ] . pSfx = = pSfx & & openal . loop_sounds [ i ] . bInUse ) {
pLoopSound - > iStartTime = openal . loop_sounds [ i ] . iStartTime ;
if ( openal . loop_sounds [ i ] . bPlaying ) {
pLoopSound - > bPlaying = true ;
pLoopSound - > iChannel = openal . loop_sounds [ i ] . iChannel ;
}
}
}
}
2024-01-07 19:47:58 +01:00
}
void S_OPENAL_StopLoopingSound ( openal_loop_sound_t * pLoopSound )
{
2024-01-12 00:04:36 +01:00
bool bMayStop ;
int i ;
openal_channel * pChannel ;
if ( ! pLoopSound - > bPlaying ) {
return ;
}
bMayStop = true ;
if ( pLoopSound - > bCombine ) {
for ( i = 0 ; i < ( MAX_OPENAL_CHANNELS_3D + MAX_OPENAL_CHANNELS_2D ) ; i + + ) {
if ( openal . loop_sounds [ i ] . pSfx = = pLoopSound - > pSfx & & openal . loop_sounds [ i ] . bInUse ) {
bMayStop = false ;
break ;
}
}
}
if ( bMayStop ) {
if ( s_show_sounds - > integer > 0 ) {
Com_DPrintf ( " %d (#%i) - stopped loop - %s \n " , cl . serverTime , pLoopSound - > iChannel , openal . channel [ pLoopSound - > iChannel ] - > pSfx - > name ) ;
}
openal . channel [ pLoopSound - > iChannel ] - > force_free ( ) ;
}
pLoopSound - > pSfx = NULL ;
pLoopSound - > bPlaying = false ;
if ( pLoopSound - > bCombine ) {
for ( i = 0 ; i < ( MAX_OPENAL_CHANNELS_3D + MAX_OPENAL_CHANNELS_2D ) ; i + + ) {
if ( openal . loop_sounds [ i ] . pSfx = = pLoopSound - > pSfx )
{
openal . loop_sounds [ i ] . bPlaying = false ;
openal . loop_sounds [ i ] . pSfx = NULL ;
}
}
}
2024-01-07 19:47:58 +01:00
}
void S_OPENAL_ClearLoopingSounds ( )
{
2024-01-12 00:04:36 +01:00
int i ;
for ( i = 0 ; i < ( MAX_OPENAL_CHANNELS_3D + MAX_OPENAL_CHANNELS_2D ) ; i + + ) {
openal . loop_sounds [ i ] . bInUse = false ;
}
2024-01-07 19:47:58 +01:00
}
void S_OPENAL_StopLoopingSounds ( )
{
2024-01-12 00:04:36 +01:00
int i ;
for ( i = 0 ; i < ( MAX_OPENAL_CHANNELS_3D + MAX_OPENAL_CHANNELS_2D ) ; i + + ) {
openal . loop_sounds [ i ] . bInUse = false ;
S_OPENAL_StopLoopingSound ( & openal . loop_sounds [ i ] ) ;
}
2024-01-07 19:47:58 +01:00
}
2024-01-08 19:44:04 +01:00
void S_OPENAL_StopSound ( int iEntNum , int iEntChannel )
2024-01-07 19:47:58 +01:00
{
2024-01-12 00:04:36 +01:00
int i ;
for ( i = 0 ; i < MAX_OPENAL_POSITION_CHANNELS ; i + + ) {
openal_channel * pChannel = openal . channel [ i ] ;
if ( ! pChannel - > is_free ( ) & & pChannel - > iEntNum = = iEntNum & & pChannel - > iEntChannel = = iEntChannel ) {
pChannel - > end_sample ( ) ;
break ;
}
}
2024-01-07 19:47:58 +01:00
}
void S_OPENAL_StopAllSounds ( qboolean bStopMusic )
{
2024-01-12 00:04:36 +01:00
int i ;
if ( ! s_bSoundStarted ) {
return ;
}
for ( i = 0 ; i < MAX_OPENAL_POSITION_CHANNELS ; i + + ) {
openal_channel * pChannel = openal . channel [ i ] ;
if ( pChannel ) {
pChannel - > force_free ( ) ;
}
}
if ( bStopMusic ) {
MUSIC_FreeAllSongs ( ) ;
S_TriggeredMusic_Stop ( ) ;
}
2024-01-07 19:47:58 +01:00
// FIXME: unimplemented
}
static int S_OPENAL_Start2DLoopSound (
2024-01-07 23:36:32 +01:00
openal_loop_sound_t * pLoopSound , float fVolume , float fVolumeToPlay , float fMinDistance , const vec3_t vLoopOrigin
2024-01-07 19:47:58 +01:00
)
{
2024-01-12 00:04:36 +01:00
int iChannel ;
int iSoundOFfset ;
openal_channel * pChannel ;
if ( pLoopSound - > pSfx - > iFlags & SFX_FLAG_NO_DATA ) {
iChannel = S_OPENAL_PickChannel2DStreamed ( 0 , 0 ) ;
}
else {
iChannel = S_OPENAL_PickChannel2D ( 0 , 0 ) ;
}
if ( iChannel < 0 ) {
Com_DPrintf ( " Could not find a free 2D sound channel \n " ) ;
return iChannel ;
}
pChannel = openal . channel [ iChannel ] ;
pChannel - > force_free ( ) ;
pChannel - > fVolume = fVolume ;
if ( pLoopSound - > iFlags & LOOPSOUND_FLAG_NO_PAN ) {
pChannel - > iFlags | = CHANNEL_FLAG_LOCAL_LISTENER ;
} else {
pChannel - > iFlags & = ~ CHANNEL_FLAG_LOCAL_LISTENER ;
}
pChannel - > fMinDist = fMinDistance ;
if ( ! pChannel - > set_sfx ( pLoopSound - > pSfx ) ) {
Com_DPrintf ( " Set sample error \n " ) ;
pChannel - > iFlags & = ~ CHANNEL_FLAG_PLAYABLE ;
return - 1 ;
}
pChannel - > iEntNum = 0 ;
pChannel - > iEntChannel = 0 ;
pChannel - > pSfx = pLoopSound - > pSfx ;
pChannel - > iFlags | = CHANNEL_FLAG_PAUSED | CHANNEL_FLAG_NO_ENTITY ;
pChannel - > iBaseRate = pChannel - > sample_playback_rate ( ) ;
VectorCopy ( vLoopOrigin , pChannel - > vOrigin ) ;
pChannel - > set_sample_offset ( ( int ) ( pLoopSound - > pSfx - > info . width
* pLoopSound - > pSfx - > info . rate
* ( float ) ( cls . realtime - pLoopSound - > iStartTime )
/ 1000.0 )
% pLoopSound - > pSfx - > length ) ;
pChannel - > set_sample_loop_count ( 0 ) ;
pChannel - > fVolume = fVolumeToPlay ;
pChannel - > set_gain ( fVolumeToPlay ) ;
pChannel - > start_sample ( ) ;
if ( s_show_sounds - > integer > 0 ) {
Com_DPrintf ( " %d (#%i) - %s (vol %f) \n " , cl . serverTime , pLoopSound - > iChannel , pLoopSound - > pSfx - > name , fVolume ) ;
}
return iChannel ;
2024-01-07 19:47:58 +01:00
}
static int S_OPENAL_Start3DLoopSound (
openal_loop_sound_t * pLoopSound ,
float fVolumeToPlay ,
float fMinDistance ,
float fMaxDistance ,
2024-01-07 23:42:32 +01:00
const vec3_t vLoopOrigin ,
const vec3_t vListenerOrigin
2024-01-07 19:47:58 +01:00
)
{
2024-01-12 00:04:36 +01:00
int iChannel ;
vec3_t vDir ;
int iSoundOffset ;
openal_channel * pChan3D ;
if ( pLoopSound - > pSfx - > iFlags & SFX_FLAG_NO_DATA ) {
return - 1 ;
}
iChannel = S_OPENAL_PickChannel3D ( 0 , 0 ) ;
if ( iChannel < 0 )
{
Com_DPrintf ( " Could not find a free channel \n " ) ;
return iChannel ;
}
pChan3D = & openal . chan_3D [ iChannel ] ;
pChan3D - > force_free ( ) ;
pChan3D - > iEntNum = 0 ;
pChan3D - > iEntChannel = 0 ;
pChan3D - > set_3d ( ) ;
if ( ! pChan3D - > set_sfx ( pLoopSound - > pSfx ) ) {
Com_DPrintf ( " Set sample error - %s \n " , pLoopSound - > pSfx - > name ) ;
return - 1 ;
}
pChan3D - > set_position ( vLoopOrigin [ 0 ] / 52.49f , pLoopSound - > vVelocity [ 1 ] / 52.49f , vLoopOrigin [ 2 ] / 52.49f ) ;
pChan3D - > set_velocity ( pLoopSound - > vVelocity [ 0 ] / 52.49f , vLoopOrigin [ 1 ] / 52.49f , pLoopSound - > vVelocity [ 2 ] / 52.49f ) ;
pChan3D - > pSfx = pLoopSound - > pSfx ;
pChan3D - > iFlags | = CHANNEL_FLAG_PAUSED | CHANNEL_FLAG_NO_ENTITY ;
pChan3D - > iBaseRate = pChan3D - > sample_playback_rate ( ) ;
iSoundOffset = ( int ) ( ( int ) pLoopSound - > pSfx - > info . width
* pLoopSound - > pSfx - > info . rate
* ( float ) ( cls . realtime - pLoopSound - > iStartTime )
/ 1000.0 )
% pLoopSound - > pSfx - > length ;
pChan3D - > set_sample_offset ( iSoundOffset ) ;
pChan3D - > set_sample_loop_count ( 0 ) ;
pChan3D - > fVolume = fVolumeToPlay ;
pChan3D - > set_gain ( fVolumeToPlay ) ;
pChan3D - > play ( ) ;
S_OPENAL_reverb ( iChannel , s_iReverbType , s_fReverbLevel ) ;
return iChannel ;
2024-01-07 19:47:58 +01:00
}
static bool S_OPENAL_UpdateLoopSound (
openal_loop_sound_t * pLoopSound ,
float fVolumeToPlay ,
float fMinDistance ,
float fMaxDistance ,
2024-01-07 23:42:32 +01:00
const vec3_t vListenerOrigin ,
const vec3_t vTempAxis ,
const vec3_t vLoopOrigin
2024-01-07 19:47:58 +01:00
)
{
// FIXME: unimplemented
return false ;
}
2024-01-07 23:36:32 +01:00
void S_OPENAL_AddLoopSounds ( const vec3_t vTempAxis )
2024-01-07 19:47:58 +01:00
{
// FIXME: unimplemented
}
2024-01-07 23:36:32 +01:00
void S_OPENAL_Respatialize ( int iEntNum , const vec3_t vHeadPos , const vec3_t vAxis [ 3 ] )
2024-01-07 19:47:58 +01:00
{
// FIXME: unimplemented
}
2024-01-07 23:36:32 +01:00
static int S_OPENAL_SpatializeStereoSound ( const vec3_t listener_origin , const vec3_t listener_left , const vec3_t origin )
2024-01-07 19:47:58 +01:00
{
// FIXME: unimplemented
return 0 ;
}
static void S_OPENAL_reverb ( int iChannel , int iReverbType , float fReverbLevel )
{
// FIXME: unimplemented
}
void S_OPENAL_SetReverb ( int iType , float fLevel )
{
// FIXME: unimplemented
}
void S_OPENAL_Update ( )
{
// FIXME: unimplemented
}
qboolean S_IsSoundPlaying ( int channel_number , const char * sfxName )
{
// FIXME: unimplemented
return qfalse ;
}
static void S_StoreBase ( channelbasesavegame_t * pBase , openal_channel * pChannel )
{
// FIXME: unimplemented
}
static void
S_StartSoundFromBase ( channelbasesavegame_t * pBase , openal_channel * pChannel , sfx_t * pSfx , bool bStartUnpaused )
{
// FIXME: unimplemented
}
static void S_LoadBase ( channelbasesavegame_t * pBase , openal_channel * pChannel , bool bStartUnpaused )
{
// FIXME: unimplemented
}
void S_SaveData ( soundsystemsavegame_t * pSave )
{
// FIXME: unimplemented
}
void S_ReLoad ( soundsystemsavegame_t * pSave )
{
// FIXME: unimplemented
}
static void S_InitBase ( channelbasesavegame_t * pBase )
{
// FIXME: unimplemented
}
void S_LoadData ( soundsystemsavegame_t * pSave )
{
// FIXME: unimplemented
}
void openal_channel : : set_velocity ( float v0 , float v1 , float v2 )
{
// FIXME: unimplemented
}
void openal_channel : : set_position ( float v0 , float v1 , float v2 )
{
// FIXME: unimplemented
}
void openal_channel : : set_gain ( float gain )
{
// FIXME: unimplemented
}
void openal_channel : : set_no_3d ( )
{
// FIXME: unimplemented
}
void openal_channel : : set_3d ( )
{
// FIXME: unimplemented
}
void openal_channel : : play ( )
{
// FIXME: unimplemented
}
void openal_channel : : pause ( )
{
// FIXME: unimplemented
}
void openal_channel : : stop ( )
{
// FIXME: unimplemented
}
ALint openal_channel : : get_state ( )
{
// FIXME: unimplemented
return 0 ;
}
bool openal_channel : : is_free ( )
{
// FIXME: unimplemented
return false ;
}
bool openal_channel : : is_paused ( )
{
// FIXME: unimplemented
return false ;
}
bool openal_channel : : is_playing ( )
{
// FIXME: unimplemented
return false ;
}
void openal_channel : : force_free ( )
{
// FIXME: unimplemented
}
bool openal_channel : : set_sfx ( sfx_t * pSfx )
{
// FIXME: unimplemented
return false ;
}
void openal_channel : : start_sample ( )
{
// FIXME: unimplemented
}
void openal_channel : : stop_sample ( )
{
// FIXME: unimplemented
}
void openal_channel : : resume_sample ( )
{
// FIXME: unimplemented
}
void openal_channel : : end_sample ( )
{
// FIXME: unimplemented
}
void openal_channel : : set_sample_pan ( S32 pan )
{
// FIXME: unimplemented
}
void openal_channel : : set_sample_playback_rate ( S32 rate )
{
// FIXME: unimplemented
}
S32 openal_channel : : sample_playback_rate ( )
{
// FIXME: unimplemented
return 0 ;
}
S32 openal_channel : : sample_volume ( )
{
// FIXME: unimplemented
return 0 ;
}
U32 openal_channel : : sample_offset ( )
{
// FIXME: unimplemented
return 0 ;
}
U32 openal_channel : : sample_ms_offset ( )
{
// FIXME: unimplemented
return 0 ;
}
U32 openal_channel : : sample_loop_count ( )
{
// FIXME: unimplemented
return 0 ;
}
void openal_channel : : set_sample_offset ( U32 offset )
{
// FIXME: unimplemented
}
void openal_channel : : set_sample_ms_offset ( U32 offset )
{
// FIXME: unimplemented
}
void openal_channel : : set_sample_loop_count ( S32 count )
{
// FIXME: unimplemented
}
void openal_channel : : set_sample_loop_block ( S32 start_offset , S32 end_offset )
{
// FIXME: unimplemented
}
U32 openal_channel : : sample_status ( )
{
// FIXME: unimplemented
return 0 ;
}
qboolean MUSIC_LoadSoundtrackFile ( const char * filename )
{
// FIXME: unimplemented
return qfalse ;
}
qboolean MUSIC_SongValid ( const char * mood )
{
// FIXME: unimplemented
return qfalse ;
}
qboolean MUSIC_Loaded ( )
{
// FIXME: unimplemented
return qfalse ;
}
void Music_Update ( )
{
// FIXME: unimplemented
}
void MUSIC_SongEnded ( )
{
// FIXME: unimplemented
}
void MUSIC_NewSoundtrack ( const char * name )
{
// FIXME: unimplemented
}
void MUSIC_UpdateMood ( int current , int fallback )
{
// FIXME: unimplemented
}
void MUSIC_UpdateVolume ( float volume , float fade_time )
{
// FIXME: unimplemented
}
void MUSIC_StopAllSongs ( )
{
// FIXME: unimplemented
}
void MUSIC_FreeAllSongs ( )
{
// FIXME: unimplemented
}
qboolean MUSIC_Playing ( )
{
// FIXME: unimplemented
return qfalse ;
}
int MUSIC_FindSong ( const char * name )
{
// FIXME: unimplemented
return 0 ;
}
void S_loadsoundtrack ( )
{
// FIXME: unimplemented
}
const char * S_CurrentSoundtrack ( )
{
// FIXME: unimplemented
return NULL ;
}
void S_PlaySong ( )
{
// FIXME: unimplemented
}
int MUSIC_CurrentSongChannel ( )
{
// FIXME: unimplemented
return 0 ;
}
void MUSIC_StopChannel ( int channel_number )
{
// FIXME: unimplemented
}
qboolean MUSIC_PlaySong ( const char * alias )
{
// FIXME: unimplemented
return qfalse ;
}
void MUSIC_UpdateMusicVolumes ( )
{
// FIXME: unimplemented
}
void MUSIC_CheckForStoppedSongs ( )
{
// FIXME: unimplemented
}
void S_TriggeredMusic_SetupHandle ( const char * pszName , int iLoopCount , int iOffset , qboolean autostart )
{
// FIXME: unimplemented
}
void S_TriggeredMusic_Start ( )
{
// FIXME: unimplemented
}
void S_TriggeredMusic_StartLoop ( )
{
// FIXME: unimplemented
}
void S_TriggeredMusic_Stop ( )
{
// FIXME: unimplemented
}
void S_TriggeredMusic_Pause ( )
{
// FIXME: unimplemented
}
void S_TriggeredMusic_Unpause ( )
{
// FIXME: unimplemented
}
void S_TriggeredMusic_PlayIntroMusic ( )
{
// FIXME: unimplemented
}
void S_StopMovieAudio ( )
{
// FIXME: unimplemented
}
void S_SetupMovieAudio ( const char * pszMovieName )
{
// FIXME: unimplemented
}
int S_CurrentMoviePosition ( )
{
// FIXME: unimplemented
return 0 ;
}
# endif