static Audio::AudioStream *getAudioStream(SoundFileHandle *fh, const char *base, int cd, uint32 id, uint32 *numSamples) { bool alreadyOpen; if (!fh->file.isOpen()) { alreadyOpen = false; struct { const char *ext; int mode; } file_types[] = { #ifdef USE_FLAC { "clf", kFLACMode }, #endif #ifdef USE_VORBIS { "clg", kVorbisMode }, #endif #ifdef USE_MAD { "cl3", kMP3Mode }, #endif { "clu", kCLUMode } }; int soundMode = 0; char filename[20]; for (int i = 0; i < ARRAYSIZE(file_types); i++) { sprintf(filename, "%s%d.%s", base, cd, file_types[i].ext); if (Common::File::exists(filename)) { soundMode = file_types[i].mode; break; } sprintf(filename, "%s.%s", base, file_types[i].ext); if (Common::File::exists(filename)) { soundMode = file_types[i].mode; break; } } if (soundMode == 0) return NULL; fh->file.open(filename); fh->fileType = soundMode; if (!fh->file.isOpen()) { warning("BS2 getAudioStream: Failed opening file '%s'", filename); return NULL; } if (fh->fileSize != fh->file.size()) { free(fh->idxTab); fh->idxTab = NULL; } } else alreadyOpen = true; uint32 entrySize = (fh->fileType == kCLUMode) ? 2 : 3; if (!fh->idxTab) { fh->file.seek(0); fh->idxLen = fh->file.readUint32LE(); fh->file.seek(entrySize * 4); 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]; fh->idxTab[cnt * 3 + 1]--; } else fh->idxTab[cnt * 3 + 2] = fh->file.readUint32LE(); } } // FIXME: In the forest maze on Zombie Island, the scripts will often // try to play song 451, which doesn't exist. We could easily substitute // another for it here, but which one? There are roughly 250 musical // cues to choose from. 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 (!pos || !len) { // We couldn't find the sound. Possibly as a result of a bad // installation (e.g. using the music file from CD 2 as the // first music file). Don't close the file if it was already // open though, because something is playing from it. warning("getAudioStream: Could not find %s ID %d! Possibly the wrong file", base, id); if (!alreadyOpen) fh->file.close(); return NULL; } fh->file.seek(pos, SEEK_SET); switch (fh->fileType) { case kCLUMode: if (Sword2Engine::isPsx()) return makePSXCLUStream(&fh->file, enc_len); else return makeCLUStream(&fh->file, enc_len); #ifdef USE_MAD case kMP3Mode: { SafeSubReadStream *tmp = new SafeSubReadStream(&fh->file, pos, pos + enc_len); return Audio::makeMP3Stream(tmp, DisposeAfterUse::YES); } #endif #ifdef USE_VORBIS case kVorbisMode: { SafeSubReadStream *tmp = new SafeSubReadStream(&fh->file, pos, pos + enc_len); return Audio::makeVorbisStream(tmp, DisposeAfterUse::YES); } #endif #ifdef USE_FLAC case kFLACMode: { SafeSubReadStream *tmp = new SafeSubReadStream(&fh->file, pos, pos + enc_len); return Audio::makeFLACStream(tmp, DisposeAfterUse::YES); } #endif default: return NULL; } }
static Audio::AudioStream *getAudioStream(SoundFileHandle *fh, const char *base, int cd, uint32 id, uint32 *numSamples) { debug(3, "Playing %s from CD %d", base, cd); 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 = 0; char filename[20]; for (int i = 0; i < ARRAYSIZE(file_types); i++) { Common::File f; sprintf(filename, "%s%d.%s", base, cd, file_types[i].ext); if (f.open(filename)) { soundMode = file_types[i].mode; break; } sprintf(filename, "%s.%s", base, file_types[i].ext); if (f.open(filename)) { soundMode = file_types[i].mode; break; } } if (soundMode == 0) return NULL; fh->file.open(filename); fh->fileType = soundMode; if (!fh->file.isOpen()) { warning("Very strange fopen error"); return NULL; } if (fh->fileSize != fh->file.size()) { if (fh->idxTab) { free(fh->idxTab); fh->idxTab = NULL; } } } uint32 entrySize = (fh->fileType == kCLUMode) ? 2 : 3; if (!fh->idxTab) { fh->file.seek(0); fh->idxLen = fh->file.readUint32LE(); fh->file.seek(entrySize * 4); 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]; fh->idxTab[cnt * 3 + 1]--; } else fh->idxTab[cnt * 3 + 2] = fh->file.readUint32LE(); } } 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 (!pos || !len) { fh->file.close(); return NULL; } fh->file.seek(pos, SEEK_SET); switch (fh->fileType) { case kCLUMode: return makeCLUStream(&fh->file, enc_len); #ifdef USE_MAD case kMP3Mode: return Audio::makeMP3Stream(&fh->file, enc_len); #endif #ifdef USE_VORBIS case kVorbisMode: return Audio::makeVorbisStream(&fh->file, enc_len); #endif #ifdef USE_FLAC case kFlacMode: return Audio::makeFlacStream(&fh->file, enc_len); #endif default: return NULL; } }