From 5ff3b3f32915f624358b9acabd082e385fca6e3b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 5 Oct 2010 22:31:22 +0000 Subject: [PATCH] - added Gez's VOC loader. SVN r2901 (trunk) --- src/s_sound.cpp | 7 +- src/sound/fmodsound.cpp | 6 +- src/sound/fmodsound.h | 2 +- src/sound/i_sound.cpp | 157 +++++++++++++++++++++++++++++++++++++++- src/sound/i_sound.h | 3 +- 5 files changed, 169 insertions(+), 6 deletions(-) diff --git a/src/s_sound.cpp b/src/s_sound.cpp index b2565b950..593fc4eaf 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -1307,10 +1307,15 @@ sfxinfo_t *S_LoadSound(sfxinfo_t *sfx) wlump.Read(sfxdata, size); SDWORD len = LittleLong(((SDWORD *)sfxdata)[1]); + // If the sound is voc, use the custom loader. + if (strncmp ((const char *)sfxstart, "Creative Voice File", 19) == 0) + { + sfx->data = GSnd->LoadSoundVoc(sfxstart, len); + } // If the sound is raw, just load it as such. // Otherwise, try the sound as DMX format. // If that fails, let FMOD try and figure it out. - if (sfx->bLoadRAW || + else if (sfx->bLoadRAW || (((BYTE *)sfxdata)[0] == 3 && ((BYTE *)sfxdata)[1] == 0 && len <= size - 8)) { int frequency; diff --git a/src/sound/fmodsound.cpp b/src/sound/fmodsound.cpp index 23e374a7b..399322061 100644 --- a/src/sound/fmodsound.cpp +++ b/src/sound/fmodsound.cpp @@ -2316,7 +2316,7 @@ void FMODSoundRenderer::UpdateSounds() // //========================================================================== -SoundHandle FMODSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart) +SoundHandle FMODSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend) { FMOD_CREATESOUNDEXINFO exinfo; SoundHandle retval = { NULL }; @@ -2372,7 +2372,9 @@ SoundHandle FMODSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequ if (loopstart >= 0) { - sample->setLoopPoints(loopstart, FMOD_TIMEUNIT_PCM, numsamples - 1, FMOD_TIMEUNIT_PCM); + if (loopend == -1) + loopend = numsamples - 1; + sample->setLoopPoints(loopstart, FMOD_TIMEUNIT_PCM, loopend, FMOD_TIMEUNIT_PCM); } retval.data = sample; diff --git a/src/sound/fmodsound.h b/src/sound/fmodsound.h index 1460b697b..8e28d0743 100644 --- a/src/sound/fmodsound.h +++ b/src/sound/fmodsound.h @@ -14,7 +14,7 @@ public: void SetSfxVolume (float volume); void SetMusicVolume (float volume); SoundHandle LoadSound(BYTE *sfxdata, int length); - SoundHandle LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart); + SoundHandle LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend = -1); void UnloadSound (SoundHandle sfx); unsigned int GetMSLength(SoundHandle sfx); unsigned int GetSampleLength(SoundHandle sfx); diff --git a/src/sound/i_sound.cpp b/src/sound/i_sound.cpp index 0a946b3c1..8f62d3e69 100644 --- a/src/sound/i_sound.cpp +++ b/src/sound/i_sound.cpp @@ -124,7 +124,7 @@ public: SoundHandle retval = { NULL }; return retval; } - SoundHandle LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart) + SoundHandle LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend) { SoundHandle retval = { NULL }; return retval; @@ -344,3 +344,158 @@ FString SoundStream::GetStats() { return "No stream stats available."; } + +//========================================================================== +// +// SoundRenderer :: LoadSoundVoc +// +//========================================================================== + +SoundHandle SoundRenderer::LoadSoundVoc(BYTE *sfxdata, int length) +{ + BYTE * data = NULL; + int len, frequency, channels, bits, loopstart, loopend; + len = frequency = channels = bits = 0; + loopstart = loopend = -1; + do if (length > 26) + { + // First pass to parse data and validate the file + if (strncmp ((const char *)sfxdata, "Creative Voice File", 19)) + break; + int i = 26, blocktype = 0, blocksize = 0, codec = -1; + bool noextra = true, okay = true; + while (i < length) + { + // Read block header + blocktype = sfxdata[i]; + if (blocktype == 0) + break; + blocksize = sfxdata[i+1] + (sfxdata[i+2]<<8) + (sfxdata[i+3]<<16); + i += 4; + if (i + blocksize > length) + { + okay = false; + break; + } + + // Read block data + switch (blocktype) + { + case 1: // Sound data + if (noextra && (codec == -1 || codec == sfxdata[i+1])) + { + frequency = 1000000/(256 - sfxdata[i]); + channels = 1; + codec = sfxdata[i+1]; + if (codec == 0) + bits = 8; + else if (codec == 4) + bits = -16; + else okay = false; + len += blocksize - 2; + } + break; + case 2: // Sound data continuation + if (codec == -1) + okay = false; + len += blocksize; + break; + case 3: // Silence + if (frequency == 1000000/(256 - sfxdata[i+2])) + { + int silength = 1 + sfxdata[i] + (sfxdata[i+1]<<8); + if (codec == 0) // 8-bit unsigned PCM + len += silength; + else if (codec == 4) // 16-bit signed PCM + len += silength<<1; + else okay = false; + } else okay = false; + break; + case 4: // Mark (ignored) + case 5: // Text (ignored) + break; + case 6: // Repeat start + loopstart = len; + break; + case 7: // Repeat end + loopend = len; + if (loopend < loopstart) + okay = false; + break; + case 8: // Extra info + noextra = false; + if (codec == -1) + { + codec = sfxdata[i+2]; + channels = 1+sfxdata[i+3]; + frequency = 256000000/(channels * (65536 - (sfxdata[i]+(sfxdata[i+1]<<8)))); + } else okay = false; + break; + case 9: // Sound data in new format + if (codec == -1) + { + frequency = sfxdata[i] + (sfxdata[i+1]<<8) + (sfxdata[i+2]<<16) + (sfxdata[i+3]<<24); + bits = sfxdata[i+4]; + channels = sfxdata[i+5]; + codec = sfxdata[i+6] + (sfxdata[i+7]<<8); + if (codec == 0) + bits = 8; + else if (codec == 4) + bits = -16; + else okay = false; + len += blocksize - 12; + } else okay = false; + break; + default: // Unknown block type + okay = false; + DPrintf ("Unknown VOC block type %i\n", blocktype); + break; + } + // Move to next block + i += blocksize; + } + + // Second pass to write the data + if (okay) + { + data = new BYTE[len]; + i = 26; + int j = 0; + while (i < length) + { + // Read block header again + blocktype = sfxdata[i]; + if (blocktype == 0) break; + blocksize = sfxdata[i+1] + (sfxdata[i+2]<<8) + (sfxdata[i+3]<<16); + i += 4; + switch (blocktype) + { + case 1: memcpy(data+j, sfxdata+i+2, blocksize-2 ); j += blocksize-2; break; + case 2: memcpy(data+j, sfxdata+i, blocksize ); j += blocksize; break; + case 9: memcpy(data+j, sfxdata+i+12, blocksize-12); j += blocksize-12; break; + case 3: + { + int silength = 1 + sfxdata[i] + (sfxdata[i+1]<<8); + if (bits == 8) + { + memset(data+j, 128, silength); + j += silength; + } + else if (bits == -16) + { + memset(data+j, 0, silength<<1); + j += silength<<1; + } + } + break; + default: break; + } + } + } + + } while (false); + SoundHandle retval = LoadSoundRaw(data, len, frequency, channels, bits, loopstart, loopend); + if (data) delete[] data; + return retval; +} + diff --git a/src/sound/i_sound.h b/src/sound/i_sound.h index e5edcbb40..9aea1b525 100644 --- a/src/sound/i_sound.h +++ b/src/sound/i_sound.h @@ -92,7 +92,8 @@ public: virtual void SetSfxVolume (float volume) = 0; virtual void SetMusicVolume (float volume) = 0; virtual SoundHandle LoadSound(BYTE *sfxdata, int length) = 0; - virtual SoundHandle LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart) = 0; + SoundHandle LoadSoundVoc(BYTE *sfxdata, int length); + virtual SoundHandle LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend = -1) = 0; virtual void UnloadSound (SoundHandle sfx) = 0; // unloads a sound from memory virtual unsigned int GetMSLength(SoundHandle sfx) = 0; // Gets the length of a sound at its default frequency virtual unsigned int GetSampleLength(SoundHandle sfx) = 0; // Gets the length of a sound at its default frequency