diff options
author | Torbjörn Andersson | 2003-09-22 06:36:38 +0000 |
---|---|---|
committer | Torbjörn Andersson | 2003-09-22 06:36:38 +0000 |
commit | 8e28b0c6b4c004a93b76a89d8cb84926a13a0b4a (patch) | |
tree | 8d33f7fbdfec73957d4446c5ffea82be0c374169 /sword2 | |
parent | 18961542f96d0b1983a3e240997ec3da4b6abdb3 (diff) | |
download | scummvm-rg350-8e28b0c6b4c004a93b76a89d8cb84926a13a0b4a.tar.gz scummvm-rg350-8e28b0c6b4c004a93b76a89d8cb84926a13a0b4a.tar.bz2 scummvm-rg350-8e28b0c6b4c004a93b76a89d8cb84926a13a0b4a.zip |
Cleaned up the sound code enough to add cutscene voice-overs. I haven't had
the time to do much testing yet, but it seems to work for me.
svn-id: r10361
Diffstat (limited to 'sword2')
-rw-r--r-- | sword2/anims.cpp | 56 | ||||
-rw-r--r-- | sword2/driver/d_draw.cpp | 13 | ||||
-rw-r--r-- | sword2/driver/d_sound.cpp | 176 | ||||
-rw-r--r-- | sword2/driver/d_sound.h | 3 | ||||
-rw-r--r-- | sword2/driver/driver96.h | 3 |
5 files changed, 64 insertions, 187 deletions
diff --git a/sword2/anims.cpp b/sword2/anims.cpp index 4783f4d233..8d72c7f39c 100644 --- a/sword2/anims.cpp +++ b/sword2/anims.cpp @@ -479,7 +479,8 @@ typedef struct { uint16 startFrame; uint16 endFrame; mem *text_mem; - mem *speech_mem; + uint32 speechBufferSize; + uint16 *speech_mem; } _sequenceTextInfo; // keeps count of number of text lines to disaply during the sequence @@ -513,10 +514,9 @@ void CreateSequenceSpeech(_movieTextObject *sequenceText[]) { // (James23may97) uint32 local_text; uint32 text_res; uint8 *text; - int16 wavId; // ie. offical text number (actor text number) + uint32 wavId; // ie. offical text number (actor text number) uint8 speechRunning; char speechFile[256]; - int32 wavSize; // for each sequence text line that's been logged for (line = 0; line < sequenceTextLines; line++) { @@ -568,45 +568,10 @@ void CreateSequenceSpeech(_movieTextObject *sequenceText[]) { // (James23may97) else strcpy(speechFile, "speech.clu"); - wavSize = g_sound->GetCompSpeechSize(speechFile, wavId); - if (wavSize) { - // if we've got the wav - // allocate memory for speech buffer - // last param is an optional id for type of - // mem block - - sequence_text_list[line].speech_mem = Twalloc(wavSize, MEM_locked, UID_temp); - - // if mem allocated ok (should be fine, but - // worth checking) - - if (sequence_text_list[line].speech_mem) { - // Load speech & decompress to our - // buffer - - if (g_sound->PreFetchCompSpeech(speechFile, wavId, sequence_text_list[line].speech_mem->ad) == RD_OK) { - // ok, we've got speech! - - // now float this buffer so we - // can make space for the next - // text sprites and/or speech - // samples - - Float_mem(sequence_text_list[line].speech_mem); - speechRunning = 1; - } else { - // whoops, sample didn't load - // & decompress for some - // reason... - - // may as well free up speech - // buffer now, rather than in - // ClearSequenceSpeech(); - - Free_mem(sequence_text_list[line].speech_mem); - sequence_text_list[line].speech_mem = NULL; - } - } + sequence_text_list[line].speechBufferSize = g_sound->PreFetchCompSpeech((char *) speechFile, wavId, &sequence_text_list[line].speech_mem); + if (sequence_text_list[line].speechBufferSize) { + // ok, we've got speech! + speechRunning = 1; } } @@ -664,12 +629,11 @@ void CreateSequenceSpeech(_movieTextObject *sequenceText[]) { // (James23may97) // if we've loaded a speech sample for this line... if (sequence_text_list[line].speech_mem) { - Lock_mem(sequence_text_list[line].speech_mem); - // for drivers: set up pointer to decompressed wav in // memory - sequenceText[line]->speech = (_wavHeader *) sequence_text_list[line].speech_mem->ad; + sequenceText[line]->speechBufferSize = sequence_text_list[line].speechBufferSize; + sequenceText[line]->speech = sequence_text_list[line].speech_mem; } } } @@ -689,7 +653,7 @@ void ClearSequenceSpeech(_movieTextObject *textSprites[]) { // (James27may97) // free up the mem block containing this speech sample if (sequence_text_list[line].speech_mem) - Free_mem(sequence_text_list[line].speech_mem); + free(sequence_text_list[line].speech_mem); } // IMPORTANT! Reset the line count ready for the next sequence! diff --git a/sword2/driver/d_draw.cpp b/sword2/driver/d_draw.cpp index 9499ffcae3..ef92092bb2 100644 --- a/sword2/driver/d_draw.cpp +++ b/sword2/driver/d_draw.cpp @@ -23,6 +23,8 @@ #include "bs2/header.h" // HACK: For cutscenes instruction message #include "bs2/memory.h" // HACK: For cutscenes instruction message #include "bs2/maketext.h" // HACK: For cutscenes instruction message +#include "bs2/sword2.h" +#include "sound/mixer.h" #include "rdwin.h" #include "_mouse.h" #include "d_draw.h" @@ -542,8 +544,6 @@ int32 PlaySmacker(char *filename, _movieTextObject *text[], uint8 *musicOut) { // WORKAROUND: For now, we just do the voice-over parts of the // movies, since they're separate from the actual smacker files. - // TODO: Play the voice-over sounds. - // Do we really need to pre-cache the text sprites and speech data // like this? It'd be simpler to just store the text id and construct // the data as we go along. @@ -600,6 +600,8 @@ int32 PlaySmacker(char *filename, _movieTextObject *text[], uint8 *musicOut) { BS2_SetPalette(0, 256, tmpPal, RDPAL_INSTANT); while (1) { + PlayingSoundHandle handle; + if (!text[textCounter]) break; @@ -607,8 +609,9 @@ int32 PlaySmacker(char *filename, _movieTextObject *text[], uint8 *musicOut) { EraseBackBuffer(); OpenTextObject(text[textCounter]); DrawTextObject(text[textCounter]); - if (text[textCounter]->speech) - debug(0, "FIXME: Play subtitle speech"); + if (text[textCounter]->speech) { + g_sword2->_mixer->playRaw(&handle, text[textCounter]->speech, text[textCounter]->speechBufferSize, 22050, SoundMixer::FLAG_16BITS); + } } if (frameCounter == text[textCounter]->endFrame) { @@ -624,7 +627,7 @@ int32 PlaySmacker(char *filename, _movieTextObject *text[], uint8 *musicOut) { char key; if (ReadKey(&key) == RD_OK && key == 27) { - // StopWavSpeech() + g_sword2->_mixer->stopHandle(handle); break; } diff --git a/sword2/driver/d_sound.cpp b/sword2/driver/d_sound.cpp index 0941654313..7c9f98de67 100644 --- a/sword2/driver/d_sound.cpp +++ b/sword2/driver/d_sound.cpp @@ -330,184 +330,100 @@ int32 Sword2Sound::AmISpeaking() { return RDSE_QUIET; } -int32 Sword2Sound::GetCompSpeechSize(const char *filename, uint32 speechid) { +uint32 Sword2Sound::PreFetchCompSpeech(const char *filename, uint32 speechid, uint16 **buf) { + uint32 i; + uint8 *data8; uint32 speechIndex[2]; File fp; - + uint32 bufferSize; + + *buf = NULL; + // Open the speech cluster and find the data offset & size fp.open(filename); - if (fp.isOpen() == false) + if (!fp.isOpen()) return 0; - fp.seek((++speechid) * 8, SEEK_SET); + fp.seek((speechid + 1) * 8, SEEK_SET); if (fp.read(speechIndex, sizeof(uint32) * 2) != (sizeof(uint32) * 2)) { fp.close(); return 0; } - fp.close(); - #ifdef SCUMM_BIG_ENDIAN speechIndex[0] = SWAP_BYTES_32(speechIndex[0]); speechIndex[1] = SWAP_BYTES_32(speechIndex[1]); #endif - if (!speechIndex[0] || !speechIndex[1]) + if (!speechIndex[0] || !speechIndex[1]) { + fp.close(); return 0; + } - return (speechIndex[1] - 1) * 2 + sizeof(_wavHeader) + 8; -} - -int32 Sword2Sound::PreFetchCompSpeech(const char *filename, uint32 speechid, uint8 *waveMem) { - uint32 i; - uint16 *data16; - uint8 *data8; - uint32 speechIndex[2]; - _wavHeader *pwf = (_wavHeader *) waveMem; - File fp; - - // Open the speech cluster and find the data offset & size - fp.open(filename); - if (fp.isOpen() == false) - return RDERR_INVALIDFILENAME; - - fp.seek((++speechid) * 8, SEEK_SET); - - if (fp.read(speechIndex, sizeof(uint32) * 2) != (sizeof(uint32) * 2)) { + // Create a temporary buffer for compressed speech + if ((data8 = (uint8 *) malloc(speechIndex[1])) == NULL) { fp.close(); - return RDERR_READERROR; + return 0; } -#ifdef SCUMM_BIG_ENDIAN - speechIndex[0] = SWAP_BYTES_32(speechIndex[0]); - speechIndex[1] = SWAP_BYTES_32(speechIndex[1]); -#endif + fp.seek(speechIndex[0], SEEK_SET); - if (!speechIndex[0] || !speechIndex[1]) { + if (fp.read(data8, speechIndex[1]) != speechIndex[1]) { fp.close(); - return RDERR_INVALIDID; + free(data8); + return 0; } - data16 = (uint16 *) (waveMem + sizeof(_wavHeader)); - - memset(pwf, 0, sizeof(_wavHeader)); - - pwf->riff = MKID('RIFF'); - pwf->wavID = MKID('WAVE'); - pwf->format = MKID('fmt '); - - pwf->formatLen = TO_LE_32(0x00000010); - pwf->formatTag = TO_LE_16(0x0001); - pwf->channels = TO_LE_16(0x0001); - pwf->samplesPerSec = TO_LE_16(0x5622); - pwf->avgBytesPerSec = TO_LE_16(0x0000); - pwf->blockAlign = TO_LE_16(0xAC44); - pwf->unknown1 = TO_LE_16(0x0000); - pwf->unknown2 = TO_LE_16(0x0002); - pwf->bitsPerSample = TO_LE_16(0x0010); - - *((uint32 *) data16) = MKID('data'); - - data16 += 2; - - *((uint32 *) data16) = TO_LE_32((speechIndex[1] - 1) * 2); + fp.close(); - data16 += 2; + // Decompress data into speech buffer. - pwf->fileLength = (speechIndex[1] - 1) * 2 + sizeof(_wavHeader) + 8; + bufferSize = (speechIndex[1] - 1) * 2; - // Calculate position in buffer to load compressed sound into - data8 = (uint8 *) data16 + (speechIndex[1] - 1); - - fp.seek(speechIndex[0], SEEK_SET); - - if (fp.read(data8, speechIndex[1]) != speechIndex[1]) { - fp.close(); - return RDERR_INVALIDID; + *buf = (uint16 *) malloc(bufferSize); + if (!*buf) { + free(data8); + return 0; } - fp.close(); + uint16 *data16 = *buf; // Starting Value data16[0] = READ_LE_UINT16(data8); - for (i = 1; i < (speechIndex[1] - 1); i++) { + for (i = 1; i < speechIndex[1] - 1; i++) { if (GetCompressedSign(data8[i + 1])) data16[i] = data16[i - 1] - (GetCompressedAmplitude(data8[i + 1]) << GetCompressedShift(data8[i + 1])); else data16[i] = data16[i - 1] + (GetCompressedAmplitude(data8[i + 1]) << GetCompressedShift(data8[i + 1])); } - return RD_OK; + free(data8); + +#ifndef SCUMM_BIG_ENDIAN + // Until the mixer supports LE samples natively, we need to convert + // our LE ones to BE + for (uint j = 0; j < bufferSize / 2; j++) + data16[j] = SWAP_BYTES_16(data16[j]); +#endif + + return bufferSize; } int32 Sword2Sound::PlayCompSpeech(const char *filename, uint32 speechid, uint8 vol, int8 pan) { - uint32 i; uint16 *data16; - uint8 *data8; - uint32 speechIndex[2]; - File fp; uint32 bufferSize; if (!speechMuted) { if (GetSpeechStatus() == RDERR_SPEECHPLAYING) return RDERR_SPEECHPLAYING; - // Open the speech cluster and find the data offset & size - fp.open(filename); - if (fp.isOpen() == false) - return RDERR_INVALIDFILENAME; - - fp.seek((++speechid) * 8, SEEK_SET); - - if (fp.read(speechIndex, sizeof(uint32) * 2) != (sizeof(uint32) * 2)) { - fp.close(); - return RDERR_READERROR; - } - -#ifdef SCUMM_BIG_ENDIAN - speechIndex[0] = SWAP_BYTES_32(speechIndex[0]); - speechIndex[1] = SWAP_BYTES_32(speechIndex[1]); -#endif - - if (speechIndex[0] == 0 || speechIndex[1] == 0) { - fp.close(); - return RDERR_INVALIDID; - } - - bufferSize = (speechIndex[1] - 1) * 2; - - // Create tempory buffer for compressed speech - if ((data8 = (uint8 *) malloc(speechIndex[1])) == NULL) { - fp.close(); - return(RDERR_OUTOFMEMORY); - } - - fp.seek(speechIndex[0], SEEK_SET); - - if (fp.read(data8, speechIndex[1]) != speechIndex[1]) { - fp.close(); - free(data8); - return RDERR_INVALIDID; - } - - fp.close(); - - // Decompress data into speech buffer. - data16 = (uint16 *) malloc(bufferSize); + bufferSize = PreFetchCompSpeech(filename, speechid, &data16); - // Starting Value - data16[0] = READ_LE_UINT16(data8); - - for (i = 1; i < bufferSize / 2; i++) { - if (GetCompressedSign(data8[i + 1])) - data16[i] = data16[i - 1] - (GetCompressedAmplitude(data8[i + 1]) << GetCompressedShift(data8[i + 1])); - else - data16[i] = data16[i - 1] + (GetCompressedAmplitude(data8[i + 1]) << GetCompressedShift(data8[i + 1])); - } - - free(data8); + // We don't know exactly what went wrong here. + if (bufferSize == 0) + return RDERR_OUTOFMEMORY; // Modify the volume according to the master volume @@ -520,13 +436,6 @@ int32 Sword2Sound::PlayCompSpeech(const char *filename, uint32 speechid, uint8 v uint32 flags = SoundMixer::FLAG_16BITS | SoundMixer::FLAG_AUTOFREE; -#ifndef SCUMM_BIG_ENDIAN - // Until the mixer supports LE samples natively, we need to - // convert our LE ones to BE - for (uint j = 0; j < (bufferSize / 2); j++) - data16[j] = SWAP_BYTES_16(data16[j]); -#endif - _mixer->playRaw(&soundHandleSpeech, data16, bufferSize, 22050, flags, -1, volume, p); speechStatus = 1; @@ -667,6 +576,7 @@ int32 Sword2Sound::OpenFx(int32 id, uint8 *data) { i++; data++; } + if (!data32) return RDERR_INVALIDWAV; diff --git a/sword2/driver/d_sound.h b/sword2/driver/d_sound.h index a32ddc59f8..f8beeba60a 100644 --- a/sword2/driver/d_sound.h +++ b/sword2/driver/d_sound.h @@ -74,8 +74,7 @@ class Sword2Sound { void FxServer(void); int32 PlaySpeech(uint8 *data, uint8 vol, int8 pan); int32 PlayCompSpeech(const char *filename, uint32 speechid, uint8 vol, int8 pan); - int32 PreFetchCompSpeech(const char *filename, uint32 speechid, uint8 *waveMem); - int32 GetCompSpeechSize(const char *filename, uint32 speechid); + uint32 PreFetchCompSpeech(const char *filename, uint32 speechid, uint16 **buf); int32 AmISpeaking(); int32 StopSpeechSword2(void); int32 GetSpeechStatus(void); diff --git a/sword2/driver/driver96.h b/sword2/driver/driver96.h index 3c5aed2a5c..54bba17ef4 100644 --- a/sword2/driver/driver96.h +++ b/sword2/driver/driver96.h @@ -1293,7 +1293,8 @@ typedef struct uint16 startFrame; uint16 endFrame; _spriteInfo *textSprite; - _wavHeader *speech; + uint32 speechBufferSize; + uint16 *speech; } _movieTextObject; |