aboutsummaryrefslogtreecommitdiff
path: root/sword2/driver
diff options
context:
space:
mode:
Diffstat (limited to 'sword2/driver')
-rw-r--r--sword2/driver/d_sound.cpp195
1 files changed, 108 insertions, 87 deletions
diff --git a/sword2/driver/d_sound.cpp b/sword2/driver/d_sound.cpp
index a8e3d444e0..81890e6fbb 100644
--- a/sword2/driver/d_sound.cpp
+++ b/sword2/driver/d_sound.cpp
@@ -40,95 +40,106 @@ namespace Sword2 {
static AudioStream *makeCLUStream(File *fp, int size);
-static AudioStream *getAudioStream(File *fp, const char *base, int cd, uint32 id, uint32 *numSamples) {
- 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", kCLUMode }
- };
+static AudioStream *getAudioStream(SoundFileHandle *fh, const char *base, int cd, uint32 id, uint32 *numSamples) {
+ if (!fh->file->isOpen()) {
+ 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", kCLUMode }
+ };
+
+ int soundMode = -1;
+ char filename[20];
+
+ for (int i = 0; i < ARRAYSIZE(file_types); i++) {
+ File f;
+
+ sprintf(filename, "%s%d.%s", base, cd, file_types[i].ext);
+ if (f.open(filename)) {
+ soundMode = file_types[i].mode;
+ break;
+ }
- int soundMode = -1;
- char filename[20];
+ sprintf(filename, "%s.%s", base, file_types[i].ext);
+ if (f.open(filename)) {
+ soundMode = file_types[i].mode;
+ break;
+ }
+ }
- for (int i = 0; i < ARRAYSIZE(file_types); i++) {
- File f;
+ if (soundMode == 0)
+ return NULL;
- sprintf(filename, "%s%d.%s", base, cd, file_types[i].ext);
- if (f.open(filename)) {
- soundMode = file_types[i].mode;
- break;
+ fh->file->open(filename);
+ fh->fileType = soundMode;
+ if (!fh->file->isOpen()) {
+ warning("Very strange fopen error");
+ return NULL;
}
-
- sprintf(filename, "%s.%s", base, file_types[i].ext);
- if (f.open(filename)) {
- soundMode = file_types[i].mode;
- break;
+ if (fh->fileSize != fh->file->size()) {
+ if (fh->idxTab) {
+ free(fh->idxTab);
+ fh->idxTab = NULL;
+ }
}
}
- if (soundMode == 0)
- return NULL;
-
- // The assumption here is that a sound file is closed when the sound
- // finishes, and we never play sounds from two different files at the
- // same time. Thus, if the file is already open it's the correct file,
- // and the loop above was just needed to figure out the compression.
- //
- // This is to avoid having two file handles open to the same file at
- // the same time. There was some speculation that some of our target
- // systems may have trouble with that.
+ uint32 entrySize = (fh->fileType == kCLUMode) ? 2 : 3;
- if (!fp->isOpen())
- fp->open(filename);
-
- if (!fp->isOpen())
- return NULL;
+ if (!fh->idxTab) {
+ fh->file->seek(0);
+ fh->idxLen = fh->file->readUint32LE();
+ fh->file->seek(entrySize * 4);
- fp->seek((id + 1) * ((soundMode == kCLUMode) ? 8 : 12), SEEK_SET);
+ fh->idxTab = (uint32*)malloc(fh->idxLen * 3 * sizeof(uint32));
+ for (uint32 cnt = 0; cnt < fh->idxLen; cnt++) {
+ fh->idxTab[cnt * 3 + 0] = fh->file->readUint32LE();
+ fh->idxTab[cnt * 3 + 1] = fh->file->readUint32LE();
+ if (fh->fileType == kCLUMode)
+ fh->idxTab[cnt * 3 + 2] = fh->idxTab[cnt * 3 + 1] + 1;
+ else
+ fh->idxTab[cnt * 3 + 2] = fh->file->readUint32LE();
+ }
+ }
- uint32 pos = fp->readUint32LE();
- uint32 len = fp->readUint32LE();
- uint32 enc_len;
+ uint32 pos = fh->idxTab[id * 3 + 0];
+ uint32 len = fh->idxTab[id * 3 + 1];
+ uint32 enc_len = fh->idxTab[id * 3 + 2];
if (numSamples)
*numSamples = len;
- if (soundMode != kCLUMode)
- enc_len = fp->readUint32LE();
- else
- enc_len = len + 1;
-
if (!pos || !len) {
- fp->close();
+ fh->file->close();
return NULL;
}
- fp->seek(pos, SEEK_SET);
+ fh->file->seek(pos, SEEK_SET);
- switch (soundMode) {
+ switch (fh->fileType) {
case kCLUMode:
- return makeCLUStream(fp, enc_len);
+ return makeCLUStream(fh->file, enc_len);
#ifdef USE_MAD
case kMP3Mode:
- return makeMP3Stream(fp, enc_len);
+ return makeMP3Stream(fh->file, enc_len);
#endif
#ifdef USE_VORBIS
case kVorbisMode:
- return makeVorbisStream(fp, enc_len);
+ return makeVorbisStream(fh->file, enc_len);
#endif
#ifdef USE_FLAC
case kFlacMode:
- return makeFlacStream(fp, enc_len);
+ return makeFlacStream(fh->file, enc_len);
#endif
default:
return NULL;
@@ -225,9 +236,9 @@ AudioStream *makeCLUStream(File *file, int size) {
// The length of a fade-in/out, in milliseconds.
#define FADE_LENGTH 3000
-MusicInputStream::MusicInputStream(int cd, File *fp, uint32 musicId, bool looping) {
+MusicInputStream::MusicInputStream(int cd, SoundFileHandle *fh, uint32 musicId, bool looping) {
_cd = cd;
- _file = fp;
+ _fh = fh;
_musicId = musicId;
_looping = looping;
@@ -235,7 +246,7 @@ MusicInputStream::MusicInputStream(int cd, File *fp, uint32 musicId, bool loopin
_remove = false;
_fading = 0;
- _decoder = getAudioStream(fp, "music", _cd, _musicId, &_numSamples);
+ _decoder = getAudioStream(_fh, "music", _cd, _musicId, &_numSamples);
if (_decoder) {
_samplesLeft = _numSamples;
_fadeSamples = (getRate() * FADE_LENGTH) / 1000;
@@ -353,7 +364,7 @@ void MusicInputStream::refill() {
if (!_samplesLeft) {
if (_looping) {
delete _decoder;
- _decoder = getAudioStream(_file, "music", _cd, _musicId, &_numSamples);
+ _decoder = getAudioStream(_fh, "music", _cd, _musicId, &_numSamples);
_samplesLeft = _numSamples;
} else
_remove = true;
@@ -448,8 +459,8 @@ int Sound::readBuffer(int16 *buffer, const int numSamples) {
}
for (i = 0; i < MAXMUS; i++) {
- if (!inUse[i] && _musicFile[i].isOpen())
- _musicFile[i].close();
+ if (!inUse[i] && !_musicFile[i].inUse && _musicFile[i].file->isOpen())
+ _musicFile[i].file->close();
}
return numSamples;
@@ -457,7 +468,7 @@ int Sound::readBuffer(int16 *buffer, const int numSamples) {
bool Sound::endOfData() const {
for (int i = 0; i < MAXMUS; i++) {
- if (_musicFile[i].isOpen())
+ if (_musicFile[i].file->isOpen())
return false;
}
@@ -516,8 +527,9 @@ void Sound::stopMusic(bool immediately) {
* @return RD_OK or an error code
*/
int32 Sound::streamCompMusic(uint32 musicId, bool loop) {
- Common::StackLock lock(_mutex);
+ //Common::StackLock lock(_mutex);
+ _mutex.lock();
int cd = _vm->_resman->whichCd();
if (loop)
@@ -572,23 +584,32 @@ int32 Sound::streamCompMusic(uint32 musicId, bool loop) {
primary = 0;
// Don't start streaming if the volume is off.
- if (isMusicMute())
+ if (isMusicMute()) {
+ _mutex.unlock();
return RD_OK;
+ }
if (secondary != -1)
_music[secondary]->fadeDown();
+ SoundFileHandle *fh = (cd == 1) ? &_musicFile[0] : &_musicFile[1];
+ fh->inUse = true;
+ _mutex.unlock();
- File *fp = (cd == 1) ? &_musicFile[0] : &_musicFile[1];
-
- _music[primary] = new MusicInputStream(cd, fp, musicId, loop);
+ MusicInputStream *tmp = new MusicInputStream(cd, fh, musicId, loop);
- if (!_music[primary]->isReady()) {
- delete _music[primary];
- _music[primary] = NULL;
+ if (tmp->isReady()) {
+ _mutex.lock();
+ _music[primary] = tmp;
+ fh->inUse = false;
+ _mutex.unlock();
+ return RD_OK;
+ } else {
+ _mutex.lock();
+ fh->inUse = false;
+ _mutex.unlock();
+ delete tmp;
return RDERR_INVALIDFILENAME;
}
-
- return RD_OK;
}
/**
@@ -685,10 +706,12 @@ int32 Sound::amISpeaking() {
*/
uint32 Sound::preFetchCompSpeech(uint32 speechId, uint16 **buf) {
- File fp;
+ int cd = _vm->_resman->whichCd();
uint32 numSamples;
- AudioStream *input = getAudioStream(&fp, "speech", _vm->_resman->whichCd(), speechId, &numSamples);
+ SoundFileHandle *fh = (cd == 1) ? &_speechFile[0] : &_speechFile[1];
+
+ AudioStream *input = getAudioStream(fh, "speech", cd, speechId, &numSamples);
if (!input)
return 0;
@@ -702,13 +725,13 @@ uint32 Sound::preFetchCompSpeech(uint32 speechId, uint16 **buf) {
*buf = (uint16 *) malloc(bufferSize);
if (!*buf) {
delete input;
- fp.close();
+ fh->file->close();
return 0;
}
uint32 readSamples = input->readBuffer((int16 *) *buf, numSamples);
- fp.close();
+ fh->file->close();
delete input;
return 2 * readSamples;
@@ -729,12 +752,10 @@ int32 Sound::playCompSpeech(uint32 speechId, uint8 vol, int8 pan) {
if (getSpeechStatus() == RDERR_SPEECHPLAYING)
return RDERR_SPEECHPLAYING;
- File *fp = new File;
- AudioStream *input = getAudioStream(fp, "speech", _vm->_resman->whichCd(), speechId, NULL);
+ int cd = _vm->_resman->whichCd();
+ SoundFileHandle *fh = (cd == 1) ? &_speechFile[0] : &_speechFile[1];
- // Make the AudioStream object the sole owner of the file so that it
- // will die along with the AudioStream when the speech has finished.
- fp->decRef();
+ AudioStream *input = getAudioStream(fh, "speech", cd, speechId, NULL);
if (!input)
return RDERR_INVALIDID;