RewindableAudioStream *XACTWaveBank_ASCII::getWave(size_t index) const { if (index >= _waves.size()) throw Common::Exception("XACTWaveBank_ASCII::getWave(): Index out of range (%s >= %s)", Common::composeString(index).c_str(), Common::composeString(_waves.size()).c_str()); const Wave &wave = _waves[index]; std::unique_ptr<Common::SeekableReadStream> dataStream(ResMan.getResource(wave.name, Aurora::kFileTypeOGG)); if (!dataStream) throw Common::Exception("XACTWaveBank_ASCII::getWave(): No such resource \"%s\"", wave.name.c_str()); #ifdef ENABLE_VORBIS return makeVorbisStream(dataStream.release(), true); #else throw Common::Exception("XACTWaveBank_ASCII::getWave(): Vorbis decoding disabled when building without libvorbis"); #endif }
AudioStream *SoundManager::makeAudioStream(Common::SeekableReadStream *stream) { bool isMP3 = false; uint32 tag = stream->readUint32BE(); if (tag == 0xfff360c4) { // Modified WAVE file (used in streamsounds folder, at least in KotOR 1/2) stream = new Common::SeekableSubReadStream(stream, 0x1D6, stream->size(), true); } else if (tag == MKTAG('R', 'I', 'F', 'F')) { stream->seek(12); tag = stream->readUint32BE(); if (tag != MKTAG('f', 'm', 't', ' ')) throw Common::Exception("Broken WAVE file"); // Skip fmt chunk stream->skip(stream->readUint32LE()); tag = stream->readUint32BE(); while ((tag == MKTAG('f', 'a', 'c', 't')) || (tag == MKTAG('P', 'A', 'D', ' ')) || (tag == MKTAG('c', 'u', 'e', ' ')) || (tag == MKTAG('L', 'I', 'S', 'T')) || (tag == MKTAG('s', 'm', 'p', 'l'))) { // Skip useless chunks stream->skip(stream->readUint32LE()); tag = stream->readUint32BE(); } if (tag != MKTAG('d', 'a', 't', 'a')) throw Common::Exception("Found invalid tag in WAVE file: %x", tag); uint32 dataSize = stream->readUint32LE(); if (dataSize == 0) { isMP3 = true; stream = new Common::SeekableSubReadStream(stream, stream->pos(), stream->size(), true); } else // Just a regular WAVE stream->seek(0); } else if ((tag == MKTAG('B', 'M', 'U', ' ')) && (stream->readUint32BE() == MKTAG('V', '1', '.', '0'))) { // BMU files: MP3 with extra header isMP3 = true; stream = new Common::SeekableSubReadStream(stream, stream->pos(), stream->size(), true); } else if (tag == MKTAG('O', 'g', 'g', 'S')) { stream->seek(0); return makeVorbisStream(stream, true); } else if (tag == 0x3026B275) { // ASF (most probably with WMAv2) stream->seek(0); return makeASFStream(stream, true); } else if (((tag & 0xFFFFFF00) | 0x20) == MKTAG('I', 'D', '3', ' ')) { // ID3v2 tag found => Should be MP3. stream->seek(0); isMP3 = true; } else if ((tag & 0xFFFA0000) == 0xFFFA0000) { // MPEG sync + MPEG1 layer 3 bits found => Should be MP3. // NOTE: To decrease the chances of false positives, we could look at more than just the first frame. stream->seek(0); isMP3 = true; } else throw Common::Exception("Unknown sound format"); if (isMP3) return makeMP3Stream(stream, true); return makeWAVStream(stream, true); }