aboutsummaryrefslogtreecommitdiff
path: root/sword2
diff options
context:
space:
mode:
authorTorbjörn Andersson2003-09-22 06:36:38 +0000
committerTorbjörn Andersson2003-09-22 06:36:38 +0000
commit8e28b0c6b4c004a93b76a89d8cb84926a13a0b4a (patch)
tree8d33f7fbdfec73957d4446c5ffea82be0c374169 /sword2
parent18961542f96d0b1983a3e240997ec3da4b6abdb3 (diff)
downloadscummvm-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.cpp56
-rw-r--r--sword2/driver/d_draw.cpp13
-rw-r--r--sword2/driver/d_sound.cpp176
-rw-r--r--sword2/driver/d_sound.h3
-rw-r--r--sword2/driver/driver96.h3
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;