Added ifactorsound & stopactorsound, fixed qsprintf issues, removed dead unfinished fmod support code, fiddled with structure packing and data sizes to increase the max concurrent playbacks of the same sound from 4 to 8, fixed several sound bugs where when one player's jetpack or scuba sounds stopped in multiplayer, everyone's hitched, increased max sound voices to 96 (was 32)

git-svn-id: https://svn.eduke32.com/eduke32@1461 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
terminx 2009-07-15 01:26:38 +00:00
parent e3a2e0a066
commit f0f56a6738
12 changed files with 154 additions and 899 deletions

View file

@ -5647,7 +5647,7 @@ static void G_MoveEffectors(void) //STATNUM 3
}
if (s->xvel <= 64 && (sc->floorstat&1) == 0 && (sc->ceilingstat&1) == 0)
A_StopSound(ActorExtra[i].lastvx,i);
S_StopEnvSound(ActorExtra[i].lastvx,i);
if ((sc->floorz-sc->ceilingz) < (108<<8))
{
@ -7622,8 +7622,8 @@ static void G_MoveEffectors(void) //STATNUM 3
ActorExtra[i].lightptr->flags.invalidate = 1;
}
if ((sprite[i].xvel != ActorExtra[i].lightptr->color[0]) ||
(sprite[i].yvel != ActorExtra[i].lightptr->color[1]) ||
(sprite[i].zvel != ActorExtra[i].lightptr->color[2]))
(sprite[i].yvel != ActorExtra[i].lightptr->color[1]) ||
(sprite[i].zvel != ActorExtra[i].lightptr->color[2]))
{
ActorExtra[i].lightptr->color[0] = sprite[i].xvel;
ActorExtra[i].lightptr->color[1] = sprite[i].yvel;
@ -7684,8 +7684,8 @@ static void G_MoveEffectors(void) //STATNUM 3
ActorExtra[i].lightptr->flags.invalidate = 1;
}
if ((sprite[i].xvel != ActorExtra[i].lightptr->color[0]) ||
(sprite[i].yvel != ActorExtra[i].lightptr->color[1]) ||
(sprite[i].zvel != ActorExtra[i].lightptr->color[2]))
(sprite[i].yvel != ActorExtra[i].lightptr->color[1]) ||
(sprite[i].zvel != ActorExtra[i].lightptr->color[2]))
{
ActorExtra[i].lightptr->color[0] = sprite[i].xvel;
ActorExtra[i].lightptr->color[1] = sprite[i].yvel;

View file

@ -273,14 +273,16 @@ extern input_t recsync[RECSYNCBUFSIZ];
extern int32_t movefifosendplc;
typedef struct {
int32_t voice;
int32_t i;
int16_t voice;
int16_t i;
} SOUNDOWNER;
#define SOUNDMAX 8
typedef struct {
int32_t length, num, soundsiz; // 12b
char *filename, *ptr, *filename1; // 12b/24b
SOUNDOWNER SoundOwner[4]; // 32b
SOUNDOWNER SoundOwner[SOUNDMAX]; // 32b
int16_t ps,pe,vo; // 6b
char pr,m; // 2b
} sound_t;

View file

@ -34,7 +34,7 @@ extern void S_MenuSound(void);
extern int32_t S_PlayMusic(const char *fn, const int32_t sel);
extern int32_t S_LoadSound(unsigned num);
extern int32_t S_PlaySoundXYZ(int32_t num,int32_t i,const vec3_t *pos);
extern void S_PlaySound(int32_t num);
extern int32_t S_PlaySound(int32_t num);
extern int32_t A_PlaySound(uint32_t num,int32_t i);
extern void S_StopSound(int32_t num);
extern void S_StopEnvSound(int32_t num,int32_t i);

View file

@ -492,6 +492,8 @@ const char *keyw[] =
"<null>", // 346 internal inversion function
"sectorofwall", // 347
"qstrncat", // 348
"ifactorsound", // 349
"stopactorsound", // 350
"<null>"
};
@ -3806,6 +3808,10 @@ static int32_t C_ParseCommand(void)
break;
}
case CON_STOPACTORSOUND:
C_GetManyVars(2);
break;
case CON_SECTOROFWALL:
C_GetNextVarType(GAMEVAR_READONLY);
C_GetNextVar();
@ -4246,6 +4252,7 @@ static int32_t C_ParseCommand(void)
return 0;
}
case CON_IFACTORSOUND:
case CON_IFVARVARG:
case CON_IFVARVARL:
case CON_IFVARVARE:
@ -4860,6 +4867,7 @@ repeatcase:
g_scriptPtr++;
break;
case CON_IFSOUND:
case CON_IFACTORSOUND:
if (C_CheckEventSync(g_currentEvent))
{
C_ReportError(WARNING_REVEVENTSYNC);

View file

@ -906,6 +906,8 @@ enum ScriptKeywords_t
CON_INV, // 346
CON_SECTOROFWALL, // 347
CON_QSTRNCAT, // 348
CON_IFACTORSOUND, // 349
CON_STOPACTORSOUND, // 350
CON_END
};
#endif

View file

@ -969,7 +969,7 @@ skip_check:
insptr++;
continue;
}
if (!A_CheckSoundPlaying(vm.g_i,vm.g_sp->yvel))
if (!S_CheckSoundPlaying(vm.g_i,vm.g_sp->yvel))
A_PlaySound(vm.g_sp->yvel,vm.g_i);
continue;
@ -1020,10 +1020,26 @@ skip_check:
OSD_Printf(CON_ERROR "Invalid sound %d\n",g_errorLineNum,keyw[g_tw],*insptr++);
continue;
}
if (!A_CheckSoundPlaying(vm.g_i,*insptr++))
if (!S_CheckSoundPlaying(vm.g_i,*insptr++))
A_PlaySound(*(insptr-1),vm.g_i);
continue;
case CON_IFACTORSOUND:
insptr++;
{
int32_t i = Gv_GetVarX(*insptr++), j = Gv_GetVarX(*insptr++);
if ((j<0 || j>=MAXSOUNDS) /* && g_scriptSanityChecks */)
{
OSD_Printf(CON_ERROR "Invalid sound %d\n",g_errorLineNum,keyw[g_tw],j);
insptr++;
continue;
}
insptr--;
X_DoConditional(A_CheckSoundPlaying(i,j));
}
continue;
case CON_IFSOUND:
insptr++;
if ((*insptr<0 || *insptr>=MAXSOUNDS) /* && g_scriptSanityChecks */)
@ -1032,7 +1048,7 @@ skip_check:
insptr++;
continue;
}
X_DoConditional(A_CheckSoundPlaying(vm.g_i,*insptr));
X_DoConditional(S_CheckSoundPlaying(vm.g_i,*insptr));
// X_DoConditional(SoundOwner[*insptr][0].i == vm.g_i);
continue;
@ -1044,11 +1060,28 @@ skip_check:
insptr++;
continue;
}
if (A_CheckSoundPlaying(vm.g_i,*insptr))
if (S_CheckSoundPlaying(vm.g_i,*insptr))
A_StopSound((int16_t)*insptr,vm.g_i);
insptr++;
continue;
case CON_STOPACTORSOUND:
insptr++;
{
int32_t i = Gv_GetVarX(*insptr++), j = Gv_GetVarX(*insptr++);
if ((j<0 || j>=MAXSOUNDS) /* && g_scriptSanityChecks */)
{
OSD_Printf(CON_ERROR "Invalid sound %d\n",g_errorLineNum,keyw[g_tw],j);
continue;
}
if (A_CheckSoundPlaying(i,j))
S_StopEnvSound(j,i);
continue;
}
case CON_GLOBALSOUND:
insptr++;
if ((*insptr<0 || *insptr>=MAXSOUNDS) /* && g_scriptSanityChecks */)
@ -1058,7 +1091,7 @@ skip_check:
continue;
}
if (vm.g_p == screenpeek || (GametypeFlags[ud.coop]&GAMETYPE_COOPSOUND))
A_PlaySound((int16_t) *insptr,g_player[screenpeek].ps->i);
A_PlaySound(*insptr,g_player[screenpeek].ps->i);
insptr++;
continue;
@ -1070,7 +1103,7 @@ skip_check:
insptr++;
continue;
}
A_PlaySound((int16_t) *insptr++,vm.g_i);
A_PlaySound(*insptr++,vm.g_i);
continue;
case CON_TIP:
@ -1235,7 +1268,7 @@ skip_check:
if ((*insptr<0 ||*insptr>=MAX_WEAPONS) /* && g_scriptSanityChecks */)
{
OSD_Printf(CON_ERROR "Invalid weapon ID %d\n",g_errorLineNum,keyw[g_tw],*insptr);
insptr+=2;
insptr+=2;
continue;
}
if (g_player[vm.g_p].ps->gotweapon[*insptr] == 0)
@ -2150,7 +2183,7 @@ nullquote:
{
case CON_SOUNDONCEVAR:
if ((j<0 || j>=MAXSOUNDS) /* && g_scriptSanityChecks */) {OSD_Printf(CON_ERROR "Invalid sound %d\n",g_errorLineNum,keyw[g_tw],j); break;}
if (!A_CheckSoundPlaying(vm.g_i,j))
if (!S_CheckSoundPlaying(vm.g_i,j))
A_PlaySound((int16_t)j,vm.g_i);
break;
case CON_GLOBALSOUNDVAR:
@ -2159,7 +2192,7 @@ nullquote:
break;
case CON_STOPSOUNDVAR:
if ((j<0 || j>=MAXSOUNDS) /* && g_scriptSanityChecks */) {OSD_Printf(CON_ERROR "Invalid sound %d\n",g_errorLineNum,keyw[g_tw],j); break;}
if (A_CheckSoundPlaying(vm.g_i,j))
if (S_CheckSoundPlaying(vm.g_i,j))
A_StopSound((int16_t)j,vm.g_i);
break;
case CON_SOUNDVAR:
@ -3131,7 +3164,10 @@ nullquote:
if ((ScriptQuotes[sq] == NULL || ScriptQuotes[dq] == NULL) /* && g_scriptSanityChecks */)
{
OSD_Printf(CON_ERROR "null quote %d\n",g_errorLineNum,keyw[g_tw],ScriptQuotes[sq] ? dq : sq);
insptr += 4;
while ((*insptr & 0xFFF) != CON_NULLOP)
Gv_GetVarX(*insptr++);
insptr++; // skip the NOP
continue;
}
@ -3140,8 +3176,10 @@ nullquote:
int32_t len = Bstrlen(ScriptQuotes[sq]);
char tempbuf[MAXQUOTELEN];
while ((*insptr & 0xFFF) != CON_NULLOP)
while ((*insptr & 0xFFF) != CON_NULLOP && i < 32)
{
arg[i++] = Gv_GetVarX(*insptr++);
}
insptr++; // skip the NOP
@ -3158,26 +3196,40 @@ nullquote:
switch (ScriptQuotes[sq][k])
{
case 'l':
if (ScriptQuotes[sq][k+1] != 'd')
{
// write the % and l
tempbuf[j++] = ScriptQuotes[sq][k-1];
tempbuf[j++] = ScriptQuotes[sq][k++];
break;
}
k++;
case 'd':
{
char buf[16];
int32_t ii = 0;
Bsprintf(buf, "%d", arg[i++]);
Bstrcat(tempbuf, buf);
j += Bstrlen(buf);
ii = Bstrlen(buf);
Bmemcpy(&tempbuf[j], buf, ii);
j += ii;
k++;
}
break;
case 's':
Bstrcat(tempbuf, ScriptQuotes[arg[i]]);
j += Bstrlen(ScriptQuotes[arg[i++]]);
{
int32_t ii = Bstrlen(ScriptQuotes[arg[i]]);
Bmemcpy(&tempbuf[j], ScriptQuotes[arg[i]], ii);
j += ii;
k++;
break;
}
break;
default:
tempbuf[j++] = ScriptQuotes[sq][k++];
tempbuf[j++] = ScriptQuotes[sq][k-1];
break;
}
}
@ -4610,7 +4662,7 @@ nullquote:
break;
}
}
return 0;
}

View file

@ -1,757 +0,0 @@
//-------------------------------------------------------------------------
/*
Duke Nukem Copyright (C) 1996, 2003 3D Realms Entertainment
This file is part of Duke Nukem 3D version 1.5 - Atomic Edition
Duke Nukem 3D 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
FMOD AudioLib implementation by Jonathon Fowler (jonof@edgenetwk.com)
*/
//-------------------------------------------------------------------------
#include "fx_man_fmod.h"
#include "duke3d.h"
#include "fmod.h"
#define TRUE (1==1)
#define FALSE (1==0)
#define dprintOSD(...)
#ifdef WINDOWS
extern int32_t hWindow;
#endif
void(*FX_CallBackFunc)(uint32_t) = NULL;
int32_t FX_ErrorCode = FX_Ok;
#define FX_SetErrorCode( status ) \
FX_ErrorCode = ( status );
FSOUND_SAMPLE * FX_Samples[MAXSOUNDS + 11]; // 11 remote ridicules
int32_t FX_NumVoices = 0;
static char chtoggle=0;
static char *chstates=NULL, *chstatesa, *chstatesb;
static int32_t *chcallvals=NULL;
int32_t FX_ReadVOCInfo(char *data, int32_t size, int32_t *samplerate, int32_t *channels, int32_t *samplesize, int32_t *datalen);
int32_t FX_ReadVOCData(char *data, char *buf, int32_t bufferlen, char eightbit);
int32_t FX_SimulateCallbacks(void);
/*---------------------------------------------------------------------
Function: FX_ErrorString
Returns a pointer to the error message associated with an error
number. A -1 returns a pointer the current error.
---------------------------------------------------------------------*/
char *FX_ErrorString(int32_t ErrorNumber)
{
char *ErrorString;
switch (ErrorNumber)
{
case FX_Warning :
case FX_Error :
ErrorString = FX_ErrorString(FX_ErrorCode);
break;
case FX_Ok :
ErrorString = "Fx ok.";
break;
case FX_ASSVersion :
ErrorString = "Apogee Sound System Version WinMM "
"Programmed by Jim Dose, Ported by Jonathon Fowler\n"
"(c) Copyright 1995 James R. Dose. All Rights Reserved.\n";
break;
case FX_FMODInit :
ErrorString = "Failed initializing FMOD.";
break;
default :
ErrorString = "Unknown Fx error code.";
break;
}
return(ErrorString);
}
/*---------------------------------------------------------------------
Function: FX_Init
Selects which sound device to use.
---------------------------------------------------------------------*/
static char *OutputType(int32_t a)
{
switch (a)
{
case FSOUND_OUTPUT_NOSOUND: return "no-sound";
case FSOUND_OUTPUT_WINMM: return "WinMM";
case FSOUND_OUTPUT_DSOUND: return "DirectSound";
case FSOUND_OUTPUT_A3D: return "Aureal3D";
case FSOUND_OUTPUT_OSS: return "OSS";
case FSOUND_OUTPUT_ESD: return "ESD";
case FSOUND_OUTPUT_ALSA: return "ALSA";
case FSOUND_OUTPUT_ASIO: return "ASIO";
case FSOUND_OUTPUT_XBOX: return "Xbox";
case FSOUND_OUTPUT_PS2: return "Playstation2";
case FSOUND_OUTPUT_MAC: return "Macintosh Sound Manager";
default: return "unknown";
}
}
int32_t FX_Init(int32_t SoundCard, int32_t numvoices, int32_t numchannels, int32_t samplebits, uint32_t mixrate)
{
FSOUND_Close();
memset(FX_Samples, 0, sizeof(FX_Samples));
#ifdef WINDOWS
if (hWindow)
{
//FSOUND_SetHWND(&hWindow);
}
#endif
if (!FSOUND_Init(mixrate, numvoices, FSOUND_INIT_GLOBALFOCUS))
{
FX_SetErrorCode(FX_FMODInit);
return FX_Error;
}
printOSD("FX_Init(): %d voices, %d channels, %dHz samplerate\n", numvoices,numchannels,FSOUND_GetOutputRate());
printOSD("FX_Init(): FMOD is using the %s output driver\n", OutputType(FSOUND_GetOutput()));
chtoggle=0;
if (chstates) free(chstates);
chstates = (char*)malloc(numvoices*2 + sizeof(int32_t)*numvoices);
memset(chstates,0,numvoices*2 + sizeof(int32_t)*numvoices);
chcallvals = (int32_t*)(chstates + numvoices*2);
chstatesa = chstates;
chstatesb = chstates + numvoices;
FX_NumVoices = numvoices;
FX_SetErrorCode(FX_Ok);
return FX_Ok;
}
/*---------------------------------------------------------------------
Function: FX_Shutdown
Terminates use of sound device.
---------------------------------------------------------------------*/
int32_t FX_Shutdown(void)
{
uint32_t curalloced, maxalloced;
if (chstates)
{
FSOUND_GetMemoryStats(&curalloced, &maxalloced);
printOSD("FX_Shutdown(): allocation stats - currently %d bytes, maximum %d bytes\n",curalloced,maxalloced);
}
FSOUND_Close();
if (chstates) free(chstates);
chstates=chstatesa=chstatesb=0;
FX_SetErrorCode(FX_Ok);
return FX_Ok;
}
/*---------------------------------------------------------------------
Function: FX_SetCallback
Sets the function to call when a voice is done.
---------------------------------------------------------------------*/
int32_t FX_SetCallBack(void(*function)(uint32_t))
{
FX_CallBackFunc = function;
FX_SetErrorCode(FX_Ok);
return FX_Ok;
}
/*---------------------------------------------------------------------
Function: FX_SetVolume
Sets the volume of the current sound device.
---------------------------------------------------------------------*/
void FX_SetVolume(int32_t volume)
{
FSOUND_SetSFXMasterVolume(volume);
}
/*---------------------------------------------------------------------
Function: FX_SetReverseStereo
Set the orientation of the left and right channels.
---------------------------------------------------------------------*/
void FX_SetReverseStereo(int32_t setting)
{}
/*---------------------------------------------------------------------
Function: FX_GetReverseStereo
Returns the orientation of the left and right channels.
---------------------------------------------------------------------*/
int32_t FX_GetReverseStereo(void)
{
return 0;
}
/*---------------------------------------------------------------------
Function: FX_SetReverb
Sets the reverb level.
---------------------------------------------------------------------*/
void FX_SetReverb(int32_t reverb)
{}
/*---------------------------------------------------------------------
Function: FX_SetReverbDelay
Sets the delay level of reverb to add to mix.
---------------------------------------------------------------------*/
void FX_SetReverbDelay(int32_t delay)
{}
/*---------------------------------------------------------------------
Function: FX_VoiceAvailable
Checks if a voice can be play at the specified priority.
---------------------------------------------------------------------*/
int32_t FX_VoiceAvailable(int32_t priority)
{
FX_SimulateCallbacks();
return 1;
}
/*---------------------------------------------------------------------
Function: FX_PlayLoopedVOC
Begin playback of sound data with the given volume and priority.
JBF: As a hack, since Duke3D passes the sound/sample number as the
callbackval parameter, we can use this as an index into the
FX_Samples array to access samples if they've already been loaded.
RemoteRidicule sounds have negative callback values, so they
take up residence at the end of FX_Samples.
---------------------------------------------------------------------*/
int32_t FX_PlayLoopedVOC
(
char *ptr,
int32_t loopstart,
int32_t loopend,
int32_t pitchoffset,
int32_t vol,
int32_t left,
int32_t right,
int32_t priority,
uint32_t callbackval
)
{
return FX_PlayLoopedSound(pitchoffset, vol, callbackval);
}
/*---------------------------------------------------------------------
Function: FX_PlayWAV
Begin playback of sound data with the given volume and priority.
---------------------------------------------------------------------*/
int32_t FX_PlayLoopedWAV
(
char *ptr,
int32_t loopstart,
int32_t loopend,
int32_t pitchoffset,
int32_t vol,
int32_t left,
int32_t right,
int32_t priority,
uint32_t callbackval
)
{
return FX_PlayLoopedSound(pitchoffset, vol, callbackval);
}
/*---------------------------------------------------------------------
Function: FX_PlayVOC3D
Begin playback of sound data at specified angle and distance
from listener.
---------------------------------------------------------------------*/
int32_t FX_PlayVOC3D
(
char *ptr,
int32_t pitchoffset,
int32_t angle,
int32_t distance,
int32_t priority,
uint32_t callbackval
)
{
return FX_PlayPositionedSound(pitchoffset, angle, distance, callbackval);
}
/*---------------------------------------------------------------------
Function: FX_PlayWAV3D
Begin playback of sound data at specified angle and distance
from listener.
---------------------------------------------------------------------*/
int32_t FX_PlayWAV3D
(
char *ptr,
int32_t pitchoffset,
int32_t angle,
int32_t distance,
int32_t priority,
uint32_t callbackval
)
{
return FX_PlayPositionedSound(pitchoffset, angle, distance, callbackval);
}
/*---------------------------------------------------------------------
Function: FX_Pan3D
Set the angle and distance from the listener of the voice associated
with the specified handle.
---------------------------------------------------------------------*/
int32_t FX_Pan3D
(
int32_t handle,
int32_t angle,
int32_t distance
)
{
return FX_Ok;
}
/*---------------------------------------------------------------------
Function: FX_StopSound
Halts playback of a specific voice
---------------------------------------------------------------------*/
int32_t FX_StopSound(int32_t handle)
{
FX_SimulateCallbacks();
FSOUND_StopSound(handle);
if (handle>=0 && handle<FX_NumVoices)
chstatesa[handle] = chstatesb[handle] = 0; // no callback for you!
FX_SetErrorCode(FX_Ok);
return FX_Ok;
}
/*---------------------------------------------------------------------
Function: FX_StopAllSounds
Halts playback of all sounds.
---------------------------------------------------------------------*/
int32_t FX_StopAllSounds(void)
{
FX_SimulateCallbacks();
FSOUND_StopSound(FSOUND_ALL);
memset(chstates, 0, FX_NumVoices*2); // no callbacks for any of you!
FX_SetErrorCode(FX_Ok);
return FX_Ok;
}
/*---------------------------------------------------------------------
Function: FX_Play*Sound
Internal function to load a sound file and play it, returning
the channel number it played on.
---------------------------------------------------------------------*/
int32_t FX_PlayLoopedSound(
int32_t pitchoffset,
int32_t vol,
uint32_t num
)
{
int32_t chan;
FX_SimulateCallbacks();
if (!FX_Samples[num]) return -1;
chan = FSOUND_PlaySoundEx(FSOUND_FREE, FX_Samples[num], NULL, TRUE) & 4095;
if (chan < 0) return -1;
// channel was already playing
if (chstatesa[chan] && FX_CallBackFunc) FX_CallBackFunc(chcallvals[chan]);
// set pitch
FSOUND_SetVolume(chan, vol);
if (FSOUND_Sample_GetMode(FX_Samples[num]) & FSOUND_STEREO)
FSOUND_SetPan(chan, FSOUND_STEREOPAN);
else
FSOUND_SetPan(chan, 128);
FSOUND_SetLoopMode(chan, FSOUND_LOOP_NORMAL);
chcallvals[chan] = num;
FSOUND_SetPaused(chan, FALSE);
dprintOSD("FX_PlayLoopedSound(): Play sound %d in channel %d\n",num,chan);
return chan;
}
int32_t FX_PlayPositionedSound(
int32_t pitchoffset,
int32_t angle,
int32_t distance,
uint32_t num
)
{
int32_t chan;
FX_SimulateCallbacks();
if (!FX_Samples[num]) return -1;
chan = FSOUND_PlaySoundEx(FSOUND_FREE, FX_Samples[num], NULL, TRUE) & 4095;
if (chan < 0) return -1;
// channel was already playing
if (chstatesa[chan] && FX_CallBackFunc) FX_CallBackFunc(chcallvals[chan]);
if (angle<0) angle = 255-angle; // behind us
// set pitch
FSOUND_SetVolume(chan,255);
FSOUND_SetPan(chan,128);
FSOUND_SetLoopMode(chan, FSOUND_LOOP_OFF);
chcallvals[chan] = num;
FSOUND_SetPaused(chan, FALSE);
dprintOSD("FX_PlayPositionedSound(): Play sound %d in channel %d\n",num,chan);
return chan;
}
int32_t FX_LoadSample(char *ptr, int32_t size, uint32_t number, int32_t priority)
{
FSOUND_SAMPLE *samp = NULL;
int32_t samplerate=0, channels=0, samplesize=0;
int32_t flags=0;
int32_t datalen=0;
void *ptr1,*ptr2;
int32_t ptr1len,ptr2len;
if (!memcmp(ptr, "Creative Voice File", 0x13))
{
// VOC file
if (FX_ReadVOCInfo(ptr,size,&samplerate,&channels,&samplesize,&datalen) == 0)
{
flags |= (channels==2)?FSOUND_STEREO:FSOUND_MONO;
flags |= (samplesize==16)?FSOUND_16BITS:FSOUND_8BITS;
flags |= FSOUND_SIGNED;
samp = FSOUND_Sample_Alloc(number, (datalen >> (channels-1)) / (samplesize>>3), flags, samplerate, -1, -1, priority);
if (samp)
{
if (FSOUND_Sample_Lock(samp,0,datalen,&ptr1,&ptr2,&ptr1len,&ptr2len))
{
if (FX_ReadVOCData(ptr,ptr1,datalen,(samplesize==8))) ;
FSOUND_Sample_Unlock(samp,ptr1,ptr2,ptr1len,ptr2len);
}
}
}
}
else
{
samp = FSOUND_Sample_Load(number, ptr, FSOUND_LOADMEMORY, size);
}
dprintOSD("FX_LoadSample(): loaded sound %d\n",number);
if (samp) FSOUND_Sample_SetDefaults(samp, -1, -1, -1, priority);
FX_Samples[number] = samp;
return (samp != NULL);
}
int32_t FX_SampleLoaded(uint32_t number)
{
return (FX_Samples[number] != NULL);
}
#define REGRESSTC(tc) (256000000/(65536-(tc)))
#define REGRESSSR(sr) (1000000/(256-(sr)))
int32_t FX_ReadVOCInfo(char *data, int32_t size, int32_t *samplerate, int32_t *channels, int32_t *samplesize, int32_t *datalen)
{
int16_t version,version2;
char blocktype=0;
int32_t blocklen=0;
char *ptr=data;
if (memcmp(ptr, "Creative Voice File\x1A", 0x14)) return -1;
ptr += 0x14;
ptr += 2;
version = ((int16_t*)ptr)[0];
version2 = ((int16_t*)ptr)[1];
if (~version + 0x1234 != version2) return -1;
ptr += 4;
while (1)
{
blocktype = *(ptr++);
if ((ptr-data)>size) return -1; // truncated
if (blocktype == 0)
break;
blocklen = *(ptr++);
blocklen |= *(ptr++) << 8;
blocklen |= *(ptr++) << 16;
switch (blocktype)
{
case 1: /* sound data begin block */
if (!*samplerate)
*samplerate = REGRESSSR(ptr[0]);
if (ptr[1] != 0)
{
/* only 8-bit files please */
return -1;
}
if (!*channels) *channels = 1;
*samplesize = 8;
*datalen += blocklen-2;
ptr += blocklen;
break;
case 2: /* sound continue */
*datalen += blocklen;
ptr += blocklen;
break;
#if 0
case 3: /* silence */
kread(fh, blockprop, 3);
/*
length = blockprop[0] | (blockprop[1] << 8)
sample rate = REGRESSSR(blockprop[2]))
*/
break;
case 4: /* marker */
kread(fh, &blockprop, 2);
/*
id = blockprop[0] | (blockprop[1] << 8))
*/
break;
case 5: /* ASCII data */
klseek(fh, blocklen, SEEK_CUR);
/*
asciiz string
*/
break;
case 6: /* repeat */
kread(fh, blockprop, 2);
/*
num repetitions = (blockprop[0] | (blockprop[1] << 8)) - 1
*/
break;
case 7: /* end repeat */
break;
#endif
case 8: /* sound attribute extension block */
*samplerate = REGRESSTC(ptr[0] | (ptr[1] << 8));
*samplesize = 8;
if (ptr[3] == 1)
{
*samplerate >>= 1;
*channels = 2;
}
else
*channels = 1;
if (ptr[2] != 0)
{
/* only 8-bit files please */
return -1;
}
ptr += 4;
/* a block 1 follows */
break;
case 9: /* sound data format 3 */
*samplerate = *((int32_t*)(ptr));
*samplesize = ptr[4];
*channels = ptr[5];
if ((ptr[6] | (ptr[7] << 8)) != 0 &&
(ptr[6] | (ptr[7] << 8)) != 4)
{
/* only PCM please */
return -1;
}
*datalen += blocklen-12;
ptr += blocklen;
break;
default:
ptr += blocklen;
break;
}
}
return 0;
}
int32_t FX_ReadVOCData(char *data, char *buf, int32_t bufferlen, char eightbit)
{
int16_t offset;
char blocktype=0;
int32_t blocklen=0, br;
data += 0x14 + 2 + 4;
while (bufferlen>0)
{
blocktype = *(data++);
if (blocktype == 0)
break;
blocklen = *(data++);
blocklen |= *(data++) << 8;
blocklen |= *(data++) << 16;
switch (blocktype)
{
case 1: /* sound data */
data += 2;
br = min(blocklen-2, bufferlen);
goto convertdata;
case 2: /* sound continue */
br = min(blocklen, bufferlen);
goto convertdata;
case 9: /* sound data format 3 */
data += 12;
br = min(blocklen-12, bufferlen);
goto convertdata;
default:
data += blocklen;
continue;
}
convertdata:
bufferlen -= br;
if (eightbit)
{
// FMOD wants signed data
for (; br>0; br--)
*(buf++) = (uint8_t)((int16_t)(*(data++)) - 0x80);
}
else
{
Bmemcpy(buf,data,br);
buf += br;
data += br;
}
}
return 0;
}
int32_t FX_SimulateCallbacks(void)
{
int32_t i;
if (!FX_CallBackFunc || !chstates) return 0;
chstatesa = chstates + (FX_NumVoices * chtoggle);
chstatesb = chstates + (FX_NumVoices * (chtoggle^1));
for (i=0;i<FX_NumVoices;i++)
{
chstatesa[i] = FSOUND_IsPlaying(i);
if (chstatesa[i] == chstatesb[i]) continue; // channel is still silent/playing
if (chstatesa[i] > chstatesb[i]) continue; // channel has begun playing
// channel has ended playing
FX_CallBackFunc(chcallvals[i]);
dprintOSD("FX_SimulateCallbacks(): channel %d ended sound %d\n",i,chcallvals[i]);
}
chtoggle ^= 1;
return 0;
}

View file

@ -1,78 +0,0 @@
//-------------------------------------------------------------------------
/*
Copyright (C) 1996, 2003 - 3D Realms Entertainment
This file is part of Duke Nukem 3D version 1.5 - Atomic Edition
Duke Nukem 3D 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Original Source: 1994 - Jim Dose
Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms
Modifications for JonoF's port by Jonathon Fowler (jonof@edgenetwk.com)
*/
//-------------------------------------------------------------------------
#ifndef __FX_MAN_H
#define __FX_MAN_H
enum FX_ERRORS
{
FX_Warning = -2,
FX_Error = -1,
FX_Ok = 0,
FX_ASSVersion,
FX_FMODInit
};
char *FX_ErrorString( int32_t ErrorNumber );
int32_t FX_Init( int32_t SoundCard, int32_t numvoices, int32_t numchannels, int32_t samplebits, uint32_t mixrate );
int32_t FX_Shutdown( void );
int32_t FX_SetCallBack( void ( *function )( uint32_t ) );
void FX_SetVolume( int32_t volume );
void FX_SetReverseStereo( int32_t setting );
int32_t FX_GetReverseStereo( void );
void FX_SetReverb( int32_t reverb );
void FX_SetReverbDelay( int32_t delay );
int32_t FX_VoiceAvailable( int32_t priority );
int32_t FX_PlayLoopedVOC( char *ptr, int32_t loopstart, int32_t loopend,
int32_t pitchoffset, int32_t vol, int32_t left, int32_t right, int32_t priority,
uint32_t callbackval );
int32_t FX_PlayLoopedWAV( char *ptr, int32_t loopstart, int32_t loopend,
int32_t pitchoffset, int32_t vol, int32_t left, int32_t right, int32_t priority,
uint32_t callbackval );
int32_t FX_PlayVOC3D( char *ptr, int32_t pitchoffset, int32_t angle, int32_t distance,
int32_t priority, uint32_t callbackval );
int32_t FX_PlayWAV3D( char *ptr, int32_t pitchoffset, int32_t angle, int32_t distance,
int32_t priority, uint32_t callbackval );
int32_t FX_Pan3D( int32_t handle, int32_t angle, int32_t distance );
int32_t FX_StopSound( int32_t handle );
int32_t FX_StopAllSounds( void );
int32_t FX_LoadSample(char *ptr, int32_t size, uint32_t number, int32_t priority);
int32_t FX_SampleLoaded(uint32_t number);
int32_t FX_PlayLoopedSound(int32_t,int32_t,uint32_t);
int32_t FX_PlayPositionedSound(int32_t,int32_t,int32_t,uint32_t);
int32_t FX_SimulateCallbacks(void);
#endif

View file

@ -1324,7 +1324,7 @@ int32_t registerosdcommands(void)
{ "snd_musvolume", "snd_musvolume: volume of midi music", (void*)&ud.config.MusicVolume, CVAR_INT, 0, 0, 255 },
{ "snd_numbits", "snd_numbits: sound bits", (void*)&ud.config.NumBits, CVAR_INT, 0, 8, 16 },
{ "snd_numchannels", "snd_numchannels: the number of sound channels", (void*)&ud.config.NumChannels, CVAR_INT, 0, 0, 2 },
{ "snd_numvoices", "snd_numvoices: the number of concurrent sounds", (void*)&ud.config.NumVoices, CVAR_INT, 0, 0, 32 },
{ "snd_numvoices", "snd_numvoices: the number of concurrent sounds", (void*)&ud.config.NumVoices, CVAR_INT, 0, 0, 96 },
{ "snd_reversestereo", "snd_reversestereo: reverses the stereo channels", (void*)&ud.config.ReverseStereo, CVAR_BOOL, 0, 0, 16 },
{ "vid_gamma","vid_gamma <gamma>: adjusts gamma ramp",(void*)&vid_gamma, CVAR_DOUBLE|CVAR_FUNCPTR, 0, 0, 10 },
{ "vid_contrast","vid_contrast <gamma>: adjusts gamma ramp",(void*)&vid_contrast, CVAR_DOUBLE|CVAR_FUNCPTR, 0, 0, 10 },

View file

@ -3404,8 +3404,8 @@ static int32_t P_DoCounters(DukePlayer_t *p)
p->jetpack_on = 0;
P_SelectNextInvItem(p);
A_PlaySound(DUKE_JETPACK_OFF,p->i);
A_StopSound(DUKE_JETPACK_IDLE,p->i);
A_StopSound(DUKE_JETPACK_ON,p->i);
S_StopEnvSound(DUKE_JETPACK_IDLE,p->i);
S_StopEnvSound(DUKE_JETPACK_ON,p->i);
}
}
@ -3567,7 +3567,7 @@ void P_AddWeaponNoSwitch(DukePlayer_t *p, int32_t weapon)
}
if (aplWeaponSelectSound[p->curr_weapon][snum])
A_StopSound(aplWeaponSelectSound[p->curr_weapon][snum],p->i);
S_StopEnvSound(aplWeaponSelectSound[p->curr_weapon][snum],p->i);
if (aplWeaponSelectSound[weapon][snum])
A_PlaySound(aplWeaponSelectSound[weapon][snum],p->i);
}
@ -4064,7 +4064,7 @@ void P_ProcessInput(int32_t snum)
p->jetpack_on = 0;
p->holoduke_on = -1;
A_StopSound(DUKE_JETPACK_IDLE,p->i);
S_StopEnvSound(DUKE_JETPACK_IDLE,p->i);
if (p->scream_voice > FX_Ok)
{
FX_StopSound(p->scream_voice);

View file

@ -53,7 +53,7 @@ int32_t A_CallSound(int32_t sn,int32_t whatsprite)
{
A_PlaySound(SLT,whatsprite);
if (SHT && SLT != SHT && SHT < MAXSOUNDS)
A_StopSound(SHT,T6);
S_StopEnvSound(SHT,T6);
T6 = whatsprite;
}
@ -65,7 +65,7 @@ int32_t A_CallSound(int32_t sn,int32_t whatsprite)
{
if (SHT) A_PlaySound(SHT,whatsprite);
if ((g_sounds[SLT].m&1) || (SHT && SHT != SLT))
A_StopSound(SLT,T6);
S_StopEnvSound(SLT,T6);
T6 = whatsprite;
T1 = 0;
}
@ -3060,8 +3060,8 @@ CHECKINV1:
p->hard_landing = 0;
p->poszv = 0;
A_PlaySound(DUKE_JETPACK_OFF,p->i);
A_StopSound(DUKE_JETPACK_IDLE,p->i);
A_StopSound(DUKE_JETPACK_ON,p->i);
S_StopEnvSound(DUKE_JETPACK_IDLE,p->i);
S_StopEnvSound(DUKE_JETPACK_ON,p->i);
P_DoQuote(53,p);
}
}

View file

@ -312,15 +312,23 @@ int32_t S_PlaySoundXYZ(int32_t num, int32_t i, const vec3_t *pos)
ud.config.FXDevice < 0 ||
((g_sounds[num].m&8) && ud.lockout) ||
ud.config.SoundToggle == 0 ||
g_sounds[num].num > 3 ||
g_sounds[num].num >= SOUNDMAX ||
FX_VoiceAvailable(g_sounds[num].pr) == 0 ||
(g_player[myconnectindex].ps->timebeforeexit > 0 && g_player[myconnectindex].ps->timebeforeexit <= GAMETICSPERSEC*3) ||
g_player[myconnectindex].ps->gm&MODE_MENU) return -1;
if (g_sounds[num].m&128)
{
S_PlaySound(num);
return 0;
voice = S_PlaySound(num);
if (voice >= FX_Ok && g_sounds[num].num < SOUNDMAX)
{
g_sounds[num].SoundOwner[g_sounds[num].num].i = i;
g_sounds[num].SoundOwner[g_sounds[num].num].voice = voice;
g_sounds[num].num++;
}
return voice;
}
if (g_sounds[num].m&4)
@ -448,7 +456,7 @@ int32_t S_PlaySoundXYZ(int32_t num, int32_t i, const vec3_t *pos)
voice = FX_PlayWAV3D(g_sounds[ num ].ptr,pitch,sndang>>6,sndist>>6, g_sounds[num].pr, num);
}
if (voice > FX_Ok)
if (voice >= FX_Ok)
{
g_sounds[num].SoundOwner[g_sounds[num].num].i = i;
g_sounds[num].SoundOwner[g_sounds[num].num].voice = voice;
@ -458,21 +466,21 @@ int32_t S_PlaySoundXYZ(int32_t num, int32_t i, const vec3_t *pos)
return (voice);
}
void S_PlaySound(int32_t num)
int32_t S_PlaySound(int32_t num)
{
int32_t pitch,pitche,pitchs,cx;
int32_t voice;
int32_t start;
if (ud.config.FXDevice < 0) return;
if (ud.config.SoundToggle==0) return;
if (!(ud.config.VoiceToggle&1) && (g_sounds[num].m&4)) return;
if ((g_sounds[num].m&8) && ud.lockout) return;
if (FX_VoiceAvailable(g_sounds[num].pr) == 0) return;
if (ud.config.FXDevice < 0) return -1;
if (ud.config.SoundToggle==0) return -1;
if (!(ud.config.VoiceToggle&1) && (g_sounds[num].m&4)) return -1;
if ((g_sounds[num].m&8) && ud.lockout) return -1;
if (FX_VoiceAvailable(g_sounds[num].pr) == 0) return -1;
if (num > MAXSOUNDS-1 || !g_sounds[num].filename)
{
OSD_Printf("WARNING: invalid sound #%d\n",num);
return;
return -1;
}
pitchs = g_sounds[num].ps;
@ -489,7 +497,7 @@ void S_PlaySound(int32_t num)
if (g_sounds[num].ptr == 0)
{
if (S_LoadSound(num) == 0) return;
if (S_LoadSound(num) == 0) return -1;
}
else
{
@ -529,25 +537,22 @@ void S_PlaySound(int32_t num)
voice = FX_PlayWAV3D(g_sounds[ num ].ptr, pitch,0,255-LOUDESTVOLUME,g_sounds[num].pr, num);
}
if (voice > FX_Ok) return;
if (voice >= FX_Ok) return voice;
g_soundlocks[num]--;
return -1;
}
int32_t A_PlaySound(uint32_t num, int32_t i)
{
if (num >= MAXSOUNDS) return -1;
if (i < 0)
{
S_PlaySound(num);
return 0;
}
{
/*
vec3_t davector;
Bmemcpy(&davector,&sprite[i],sizeof(intptr_t) * 3); */
// OSD_Printf("x: %d y: %d z: %d\n",davector.x,davector.y,davector.z);
return S_PlaySoundXYZ(num,i, (vec3_t *)&sprite[i]);
}
return S_PlaySoundXYZ(num, i, (vec3_t *)&sprite[i]);
}
void A_StopSound(int32_t num, int32_t i)
@ -568,19 +573,23 @@ void S_StopSound(int32_t num)
void S_StopEnvSound(int32_t num,int32_t i)
{
int32_t j, k;
if (num >= 0 && num < MAXSOUNDS)
{
if (g_sounds[num].num > 0)
{
k = g_sounds[num].num;
for (j=0; j<k; j++)
int32_t j=g_sounds[num].num-1;
for (; j>=0; j--)
{
if (g_sounds[num].SoundOwner[j].i == i)
{
FX_StopSound(g_sounds[num].SoundOwner[j].voice);
break;
S_TestSoundCallback(num);
return;
}
}
}
}
}
void S_Pan3D(void)
@ -716,18 +725,35 @@ void S_ClearSoundLocks(void)
int32_t A_CheckSoundPlaying(int32_t i, int32_t num)
{
UNREFERENCED_PARAMETER(i);
if (num < 0) num=0; // FIXME
return (g_sounds[num].num > 0);
int32_t j;
num = clamp(num, 0, MAXSOUNDS); // FIXME
if (i == -1)
return (g_sounds[num].num > 0);
if (g_sounds[num].num > 0)
{
for (j=g_sounds[num].num-1; j>=0; j--)
if (g_sounds[num].SoundOwner[j].i == i)
{
return 1;
}
}
return 0;
}
int32_t S_CheckSoundPlaying(int32_t i, int32_t num)
{
num = clamp(num, 0, MAXSOUNDS); // FIXME
if (i == -1)
{
if (g_soundlocks[num] == 200)
return 1;
return 0;
}
return(g_sounds[num].num);
}