diff options
author | James Haley | 2010-09-11 21:12:06 +0000 |
---|---|---|
committer | James Haley | 2010-09-11 21:12:06 +0000 |
commit | 90c196e4eb1d079fa946e764ed72a9ecd2c86dac (patch) | |
tree | eccef190c9caa7ce4d6ff5e585286749c1432bb8 /src/strife/s_sound.c | |
parent | b6938d1533d624a5815660c40aeda9125090f55e (diff) | |
download | chocolate-doom-90c196e4eb1d079fa946e764ed72a9ecd2c86dac.tar.gz chocolate-doom-90c196e4eb1d079fa946e764ed72a9ecd2c86dac.tar.bz2 chocolate-doom-90c196e4eb1d079fa946e764ed72a9ecd2c86dac.zip |
Added code (some possibly temporary?) to load voices.wad. Fixed several
problems with playing of voice sounds - especially had to add a dynamic
hashtable of voice sfxinfo_t's because Choco won't tolerate overwriting
them once they've been used (see channel_playing array in i_sdlsound.c)
- PROBLEM: Random Z_Malloc failures when trying to play sounds. Cannot
catch in debugger so far.
Subversion-branch: /branches/strife-branch
Subversion-revision: 2065
Diffstat (limited to 'src/strife/s_sound.c')
-rw-r--r-- | src/strife/s_sound.c | 117 |
1 files changed, 99 insertions, 18 deletions
diff --git a/src/strife/s_sound.c b/src/strife/s_sound.c index 52751e10..6a6ddd15 100644 --- a/src/strife/s_sound.c +++ b/src/strife/s_sound.c @@ -137,8 +137,9 @@ int disable_voices = 0; // Sets channels, SFX and music volume, // allocates channel buffer, sets S_sfx lookup. // - -void S_Init(int sfxVolume, int musicVolume) +// haleyjd 09/11/10: Added voice volume +// +void S_Init(int sfxVolume, int musicVolume, int voiceVolume) { int i; @@ -149,6 +150,7 @@ void S_Init(int sfxVolume, int musicVolume) S_SetSfxVolume(sfxVolume); S_SetMusicVolume(musicVolume); + S_SetVoiceVolume(voiceVolume); // Allocating the internal channels for mixing // (the maximum numer of sounds rendered @@ -257,6 +259,10 @@ void S_StopSound(mobj_t *origin) for (cnum=0 ; cnum<snd_channels ; cnum++) { + // haleyjd: do not stop voice here. + if(cnum == i_voicehandle) + continue; + if (channels[cnum].sfxinfo && channels[cnum].origin == origin) { S_StopChannel(cnum); @@ -280,7 +286,7 @@ static int S_GetChannel(mobj_t *origin, sfxinfo_t *sfxinfo, boolean isvoice) channel_t* c; // Find an open channel - for (cnum=0 ; cnum<snd_channels ; cnum++) + for (cnum=0 ; cnum<snd_channels ; cnum++) { if (!channels[cnum].sfxinfo) { @@ -495,7 +501,81 @@ void S_StartSound(void *origin_p, int sfx_id) } channels[cnum].handle = I_StartSound(sfx, cnum, volume, sep); -} +} + + +// haleyjd 09/11/10: [STRIFE] +// None of this was necessary in the vanilla EXE but Choco's low-level code +// won't play nice with a temporary sfxinfo because it insists that the +// "driver_data" member remain valid from the last time the sound was used, +// even if it has already stopped playing. Thanks to this cuteness I get +// to maintain a dynamic cache of sfxinfo objects! + +typedef struct voiceinfo_s +{ + sfxinfo_t sfx; + struct voiceinfo_s *next; // next on hash chain +} voiceinfo_t; + +#define NUMVOICECHAINS 257 + +// +// Ripped from Eternity. +// +static unsigned int S_voiceHash(const char *str) +{ + const char *c = str; + unsigned int h = 0; + + if(!str) + I_Error("S_voiceHash: cannot hash NULL string!\n"); + + // note: this needs to be case insensitive for lump names + while(*c) + { + h = 5 * h + toupper(*c); + ++c; + } + + return h;} + +static voiceinfo_t *voices[NUMVOICECHAINS]; + +// +// S_getVoice +// +// Gets an entry from the voice table, if it exists. If it does not, one will be +// created. +// +static voiceinfo_t *S_getVoice(const char *name, int lumpnum) +{ + voiceinfo_t *voice; + int hashkey = S_voiceHash(name) % NUMVOICECHAINS; + + voice = voices[hashkey]; + + while(voice && strcasecmp(voice->sfx.name, name)) + voice = voice->next; + + if(!voice) + { + voice = calloc(1, sizeof(voiceinfo_t)); + + strncpy(voice->sfx.name, name, 8); + voice->sfx.priority = INT_MIN; // make highest possible priority + voice->sfx.pitch = -1; + voice->sfx.volume = -1; + voice->sfx.numchannels = -1; + voice->sfx.usefulness = -1; + voice->sfx.lumpnum = lumpnum; + + // throw it onto the table. + voice->next = voices[hashkey]; + voices[hashkey] = voice; + } + + return voice; +} // // I_StartVoice @@ -508,14 +588,14 @@ void S_StartSound(void *origin_p, int sfx_id) // void I_StartVoice(const char *lumpname) { - static sfxinfo_t voicesfx; // a static "fake" sfxinfo for voices. int lumpnum; + voiceinfo_t *voice; // choco-specific // no voices in deathmatch mode. if(netgame) return; - // TODO: checks if sfx_SndDevice == 83 + // STRIFE-TODO: checks if snd_SfxDevice == 83 // This is probably turning off voice if using PC speaker... // user has disabled voices? @@ -523,25 +603,26 @@ void I_StartVoice(const char *lumpname) return; // have a voice playing already? stop it. - if (i_voicehandle > 0) + if (i_voicehandle >= 0) S_StopChannel(i_voicehandle); - // haleyjd: Choco-specific: initialize the voicesfx structure - memset(&voicesfx, 0, sizeof(sfxinfo_t)); - strncpy(voicesfx.name, lumpname, 8); - voicesfx.priority = INT_MIN; // make highest possible priority - voicesfx.pitch = -1; - voicesfx.volume = -1; - voicesfx.numchannels = -1; - voicesfx.usefulness = -1; + // Vanilla STRIFE appears to have stopped any current voice without + // starting a new one if NULL was passed in here, though I cannot + // find an explicit check for NULL in the assembly. Either way, it + // didn't crash, so do a check now: + if(lumpname == NULL) + return; if((lumpnum = W_CheckNumForName(lumpname)) != -1) { + // haleyjd: Choco-specific: get a voice structure + voice = S_getVoice(lumpname, lumpnum); + // get a channel for the voice - i_voicehandle = S_GetChannel(NULL, &voicesfx, true); - voicesfx.lumpnum = lumpnum; + i_voicehandle = S_GetChannel(NULL, &voice->sfx, true); + channels[i_voicehandle].handle - = I_StartSound(&voicesfx, i_voicehandle, snd_VoiceVolume, NORM_SEP); + = I_StartSound(&voice->sfx, i_voicehandle, snd_VoiceVolume, NORM_SEP); } } |