diff options
author | Torbjörn Andersson | 2004-08-22 14:28:11 +0000 |
---|---|---|
committer | Torbjörn Andersson | 2004-08-22 14:28:11 +0000 |
commit | e00f9f4a97dc2bcd1b8007a043396e49d0583b0d (patch) | |
tree | c401cb8f2f05cb0a927ae905f7b0864de7cf9826 | |
parent | 759cd67de518a583804ccfb14d5fead44ef05e96 (diff) | |
download | scummvm-rg350-e00f9f4a97dc2bcd1b8007a043396e49d0583b0d.tar.gz scummvm-rg350-e00f9f4a97dc2bcd1b8007a043396e49d0583b0d.tar.bz2 scummvm-rg350-e00f9f4a97dc2bcd1b8007a043396e49d0583b0d.zip |
Experimental (i.e. slightly broken) code for handling compressed speech.
The equally experimental compression tool is in patch #854561.
Support for compressed music will require some restructuring first.
svn-id: r14684
-rw-r--r-- | sword2/anims.cpp | 18 | ||||
-rw-r--r-- | sword2/driver/d_sound.cpp | 125 | ||||
-rw-r--r-- | sword2/driver/d_sound.h | 13 | ||||
-rw-r--r-- | sword2/speech.cpp | 16 |
4 files changed, 113 insertions, 59 deletions
diff --git a/sword2/anims.cpp b/sword2/anims.cpp index 685d922a02..6d2a89ab36 100644 --- a/sword2/anims.cpp +++ b/sword2/anims.cpp @@ -341,7 +341,6 @@ void Logic::createSequenceSpeech(MovieTextObject *sequenceText[]) { byte *text; uint32 wavId; // ie. offical text number (actor text number) bool speechRunning; - char speechFile[256]; // for each sequence text line that's been logged for (line = 0; line < _sequenceTextLines; line++) { @@ -375,22 +374,7 @@ void Logic::createSequenceSpeech(MovieTextObject *sequenceText[]) { sequenceText[line]->speech = NULL; if (!_vm->_sound->isSpeechMute()) { - // speech is selected, so try that first - - // set up path to speech cluster - // first checking if we have speech1.clu or - // speech2.clu in current directory (for translators - // to test) - - File fp; - - sprintf(speechFile, "speech%d.clu", _vm->_resman->whichCd()); - if (fp.open(speechFile)) - fp.close(); - else - strcpy(speechFile, "speech.clu"); - - _sequenceTextList[line].speechBufferSize = _vm->_sound->preFetchCompSpeech(speechFile, wavId, &_sequenceTextList[line].speech_mem); + _sequenceTextList[line].speechBufferSize = _vm->_sound->preFetchCompSpeech(wavId, &_sequenceTextList[line].speech_mem); if (_sequenceTextList[line].speechBufferSize) { // ok, we've got speech! speechRunning = true; diff --git a/sword2/driver/d_sound.cpp b/sword2/driver/d_sound.cpp index db45b18bec..0157b9f54e 100644 --- a/sword2/driver/d_sound.cpp +++ b/sword2/driver/d_sound.cpp @@ -35,7 +35,11 @@ #include "common/stdafx.h" #include "common/file.h" #include "sound/rate.h" +#include "sound/mp3.h" +#include "sound/vorbis.h" +#include "sound/flac.h" #include "sword2/sword2.h" +#include "sword2/resman.h" #include "sword2/driver/d_draw.h" #include "sword2/driver/d_sound.h" @@ -93,6 +97,42 @@ Sound::~Sound() { _vm->_system->deleteMutex(_mutex); } +int Sound::openSoundFile(File *fp, const char *base) { + struct { + const char *ext; + int mode; + } file_types[] = { +#ifdef USE_MAD + { "cl3", kMP3Mode }, +#endif +#ifdef USE_VORBIS + { "clg", kVorbisMode }, +#endif +#ifdef USE_FLAC + { "clf", kFlacMode }, +#endif + { "clu", kWAVMode } + }; + + char filename[20]; + int cd = _vm->_resman->whichCd(); + int i; + + for (i = 0; i < ARRAYSIZE(file_types); i++) { + sprintf(filename, "%s%d.%s", base, cd, file_types[i].ext); + if (fp->open(filename)) + return file_types[i].mode; + } + + for (i = 0; i < ARRAYSIZE(file_types); i++) { + sprintf(filename, "%s.%s", base, file_types[i].ext); + if (fp->open(filename)) + return file_types[i].mode; + } + + return 0; +} + void Sound::streamMusic(int16 *data, uint len) { Common::StackLock lock(_mutex); @@ -749,64 +789,97 @@ int32 Sound::amISpeaking(void) { * @param filename the file name of the speech cluster file * @param speechid the text line id used to reference the speech * @param buf a pointer to the buffer that will be allocated for the sound - */ + */ -uint32 Sound::preFetchCompSpeech(const char *filename, uint32 speechid, uint16 **buf) { - uint32 i; - byte *data8; - uint32 speechPos, speechLength; +uint32 Sound::preFetchCompSpeech(uint32 speechid, uint16 **buf) { + AudioStream *input = NULL; File fp; - uint32 bufferSize; + int soundMode = kWAVMode; *buf = NULL; // Open the speech cluster and find the data offset & size - if (!fp.open(filename)) + + soundMode = openSoundFile(&fp, "speech"); + if (!soundMode) return 0; fp.seek((speechid + 1) * 8, SEEK_SET); - speechPos = fp.readUint32LE(); - speechLength = fp.readUint32LE(); + uint32 speechPos = fp.readUint32LE(); + uint32 speechLength = fp.readUint32LE(); if (!speechPos || !speechLength) { fp.close(); return 0; } - // Create a temporary buffer for compressed speech - data8 = (byte *) malloc(speechLength); - if (!data8) { - fp.close(); - return 0; + fp.seek(speechPos, SEEK_SET); + + switch (soundMode) { +#ifdef USE_MAD + case kMP3Mode: + input = makeMP3Stream(&fp, speechLength); + break; +#endif +#ifdef USE_VORBIS + case kVorbisMode: + input = makeVorbisStream(&fp, speechLength); + break; +#endif +#ifdef USE_FLAC + case kFlacMode: + input = makeFlacStream(&fp, speechLength); + break; +#endif + default: + break; } - fp.seek(speechPos, SEEK_SET); + // Decompress data into speech buffer. - if (fp.read(data8, speechLength) != speechLength) { + uint32 bufferSize = speechLength * 2; + + *buf = (uint16 *) malloc(bufferSize); + if (!*buf) { + delete input; fp.close(); - free(data8); return 0; } - fp.close(); + if (input) { + int numSamples = input->readBuffer((int16 *) *buf, speechLength); + fp.close(); + delete input; + return numSamples * 2; + } - // Decompress data into speech buffer. + uint16 *data16 = *buf; - bufferSize = (speechLength - 1) * 2; + // Create a temporary buffer for compressed speech + byte *data8 = (byte *) malloc(speechLength); + if (!data8) { + free(data16); + fp.close(); + return 0; + } - *buf = (uint16 *) malloc(bufferSize); - if (!*buf) { + // FIXME: Create an AudioStream-based class for this. This could then + // also be used by the music code. + + if (fp.read(data8, speechLength) != speechLength) { + fp.close(); + free(data16); free(data8); return 0; } - uint16 *data16 = *buf; + fp.close(); // Starting Value data16[0] = READ_LE_UINT16(data8); - for (i = 1; i < speechLength - 1; i++) { + for (uint32 i = 1; i < speechLength; i++) { if (GetCompressedSign(data8[i + 1])) data16[i] = data16[i - 1] - (GetCompressedAmplitude(data8[i + 1]) << GetCompressedShift(data8[i + 1])); else @@ -826,7 +899,7 @@ uint32 Sound::preFetchCompSpeech(const char *filename, uint32 speechid, uint16 * * @param pan panning, -16 (full left) to 16 (full right) */ -int32 Sound::playCompSpeech(const char *filename, uint32 speechid, uint8 vol, int8 pan) { +int32 Sound::playCompSpeech(uint32 speechid, uint8 vol, int8 pan) { if (_speechMuted) return RD_OK; @@ -836,7 +909,7 @@ int32 Sound::playCompSpeech(const char *filename, uint32 speechid, uint8 vol, in if (getSpeechStatus() == RDERR_SPEECHPLAYING) return RDERR_SPEECHPLAYING; - bufferSize = preFetchCompSpeech(filename, speechid, &data16); + bufferSize = preFetchCompSpeech(speechid, &data16); // We don't know exactly what went wrong here. if (bufferSize == 0) diff --git a/sword2/driver/d_sound.h b/sword2/driver/d_sound.h index bc1c487b39..c530916877 100644 --- a/sword2/driver/d_sound.h +++ b/sword2/driver/d_sound.h @@ -31,6 +31,13 @@ namespace Sword2 { #define MAXFX 16 #define MAXMUS 2 +enum { + kWAVMode = 1, + kMP3Mode, + kVorbisMode, + kFlacMode +}; + extern void sword2_sound_handler(void *refCon); struct WavInfo { @@ -108,6 +115,8 @@ private: int32 getFxIndex(int32 id); void stopFxHandle(int i); + int openSoundFile(File *fp, const char *base); + public: Sound(Sword2Engine *vm); ~Sound(); @@ -139,8 +148,8 @@ public: int32 stopSpeech(void); int32 getSpeechStatus(void); int32 amISpeaking(void); - uint32 preFetchCompSpeech(const char *filename, uint32 speechid, uint16 **buf); - int32 playCompSpeech(const char *filename, uint32 speechid, uint8 vol, int8 pan); + uint32 preFetchCompSpeech(uint32 speechid, uint16 **buf); + int32 playCompSpeech(uint32 speechid, uint8 vol, int8 pan); void muteFx(bool mute); bool isFxMute(void); diff --git a/sword2/speech.cpp b/sword2/speech.cpp index 254878fc7d..99876bc08a 100644 --- a/sword2/speech.cpp +++ b/sword2/speech.cpp @@ -895,19 +895,7 @@ int32 Logic::fnISpeak(int32 *params) { else if (speech_pan > 16) speech_pan = 16; - char speechFile[20]; - - sprintf(speechFile, "speech%d.clu", _vm->_resman->whichCd()); - - File fp; - - if (fp.open(speechFile)) - fp.close(); - else - strcpy(speechFile, "speech.clu"); - - // Load speech but don't start playing yet - uint32 rv = _vm->_sound->playCompSpeech(speechFile, params[S_WAV], 16, speech_pan); + uint32 rv = _vm->_sound->playCompSpeech(params[S_WAV], 16, speech_pan); if (rv == RD_OK) { // Ok, we've got something to play. Set it @@ -917,7 +905,7 @@ int32 Logic::fnISpeak(int32 *params) { speechRunning = true; _vm->_sound->unpauseSpeech(); } else { - debug(5, "ERROR: PlayCompSpeech(speechFile=\"%s\", wav=%d (res=%d pos=%d)) returned %.8x", speechFile, params[S_WAV], text_res, local_text, rv); + debug(5, "ERROR: PlayCompSpeech(wav=%d (res=%d pos=%d)) returned %.8x", params[S_WAV], text_res, local_text, rv); } } |