diff options
Diffstat (limited to 'engines/sword1')
-rw-r--r-- | engines/sword1/music.cpp | 177 | ||||
-rw-r--r-- | engines/sword1/music.h | 21 |
2 files changed, 86 insertions, 112 deletions
diff --git a/engines/sword1/music.cpp b/engines/sword1/music.cpp index 610ea1de1b..209140f9a4 100644 --- a/engines/sword1/music.cpp +++ b/engines/sword1/music.cpp @@ -36,132 +36,130 @@ namespace Sword1 { -WaveAudioStream *makeWaveStream(Common::File *source, uint32 size) { - return new WaveAudioStream(source, size); +class WaveAudioStream : public Audio::AudioStream { +public: + WaveAudioStream(Common::SeekableReadStream *source, bool loop); + virtual ~WaveAudioStream(); + virtual int readBuffer(int16 *buffer, const int numSamples); + virtual bool isStereo() const { return _isStereo; } + virtual bool endOfData() const { return (_samplesLeft == 0); } + virtual int getRate() const { return _rate; } +private: + Common::SeekableReadStream *_sourceStream; + uint8 *_sampleBuf; + uint32 _rate; + bool _isStereo; + uint32 _samplesLeft; + uint16 _bitsPerSample; + bool _loop; + + void rewind(); +}; + +WaveAudioStream::WaveAudioStream(Common::SeekableReadStream *source, bool loop) { + // TODO: honor the loop flag + + _sourceStream = source; + _sampleBuf = (uint8*)malloc(SMP_BUFSIZE); + + _samplesLeft = 0; + _isStereo = false; + _bitsPerSample = 16; + _rate = 22050; + _loop = loop; + + rewind(); + + if (_samplesLeft == 0) + _loop = false; +} + +WaveAudioStream::~WaveAudioStream() { + free(_sampleBuf); } -WaveAudioStream::WaveAudioStream(Common::File *source, uint32 pSize) { +void WaveAudioStream::rewind() { int rate, size; byte flags; + + _sourceStream->seek(0); - _sourceFile = source; - _sampleBuf = (uint8*)malloc(SMP_BUFSIZE); - if (_sourceFile->isOpen() && Audio::loadWAVFromStream(*_sourceFile, size, rate, flags)) { + if (Audio::loadWAVFromStream(*_sourceStream, size, rate, flags)) { _isStereo = (flags & Audio::Mixer::FLAG_STEREO) != 0; _rate = rate; - if (pSize && (int)pSize < size) - size = pSize; - assert((uint32)size <= (source->size() - source->pos())); + assert((uint)size <= (_sourceStream->size() - _sourceStream->pos())); _bitsPerSample = ((flags & Audio::Mixer::FLAG_16BITS) != 0) ? 16 : 8; _samplesLeft = (size * 8) / _bitsPerSample; if ((_bitsPerSample != 16) && (_bitsPerSample != 8)) error("WaveAudioStream: unknown wave type"); - } else { - _samplesLeft = 0; - _isStereo = false; - _bitsPerSample = 16; - _rate = 22050; } } -WaveAudioStream::~WaveAudioStream(void) { - free(_sampleBuf); -} - int WaveAudioStream::readBuffer(int16 *buffer, const int numSamples) { - int samples = MIN((int)_samplesLeft, numSamples); - int retVal = samples; - - while (samples > 0) { - int readBytes = MIN(samples * (_bitsPerSample >> 3), SMP_BUFSIZE); - _sourceFile->read(_sampleBuf, readBytes); - if (_bitsPerSample == 16) { - readBytes >>= 1; - samples -= readBytes; - int16 *src = (int16*)_sampleBuf; - while (readBytes--) - *buffer++ = (int16)READ_LE_UINT16(src++); - } else { - samples -= readBytes; - int8 *src = (int8*)_sampleBuf; - while (readBytes--) - *buffer++ = (int16)*src++ << 8; + int retVal = 0; + + while (retVal < numSamples && _samplesLeft > 0) { + int samples = MIN((int)_samplesLeft, numSamples); + retVal += samples; + _samplesLeft -= samples; + while (samples > 0) { + int readBytes = MIN(samples * (_bitsPerSample >> 3), SMP_BUFSIZE); + _sourceStream->read(_sampleBuf, readBytes); + if (_bitsPerSample == 16) { + readBytes >>= 1; + samples -= readBytes; + int16 *src = (int16*)_sampleBuf; + while (readBytes--) + *buffer++ = (int16)READ_LE_UINT16(src++); + } else { + samples -= readBytes; + int8 *src = (int8*)_sampleBuf; + while (readBytes--) + *buffer++ = (int16)*src++ << 8; + } + } + + if (!_samplesLeft && _loop) { + rewind(); } } - _samplesLeft -= retVal; + return retVal; } -bool WaveAudioStream::endOfData(void) const { - if (_samplesLeft == 0) - return true; - else - return false; -} - // This means fading takes 3 seconds. #define FADE_LENGTH 3 // These functions are only called from Music, so I'm just going to // assume that if locking is needed it has already been taken care of. -Audio::AudioStream *MusicHandle::createAudioSource(void) { - _file.seek(0); - switch (_musicMode) { -#ifdef USE_MAD - case MusicMp3: - return Audio::makeMP3Stream(&_file, _file.size()); -#endif -#ifdef USE_VORBIS - case MusicVorbis: - return Audio::makeVorbisStream(&_file, _file.size()); -#endif - case MusicWave: - return makeWaveStream(&_file, 0); - case MusicNone: // shouldn't happen - warning("createAudioSource ran into null create\n"); - return NULL; - default: - error("MusicHandle::createAudioSource: called with illegal MusicMode"); - } - return NULL; // never reached -} - bool MusicHandle::play(const char *fileBase, bool loop) { -/* -TODO/FIXME: This should be rewritten to make use of the new audio stream factories. -In particular, it should take advantage of the looping capabilities; and it -should avoid reading all the data into memory (by not using the old factory functions). -Essentially, it seems to me as if we could get rid of createAudioSource(). - -Maybe it could even be change to use AudioStream::openStreamFile. -*/ char fileName[30]; stop(); - _musicMode = MusicNone; + #ifdef USE_VORBIS - if (!_file.isOpen()) { + if (!_audioSource) { sprintf(fileName, "%s.ogg", fileBase); if (_file.open(fileName)) - _musicMode = MusicVorbis; + _audioSource = Audio::makeVorbisStream(&_file, false, 0, 0, loop ? 0 : 1); } #endif #ifdef USE_MAD - if (!_file.isOpen()) { + if (!_audioSource) { sprintf(fileName, "%s.mp3", fileBase); if (_file.open(fileName)) - _musicMode = MusicMp3; + _audioSource = Audio::makeMP3Stream(&_file, false, 0, 0, loop ? 0 : 1); } #endif - if (!_file.isOpen()) { + if (!_audioSource) { sprintf(fileName, "%s.wav", fileBase); if (_file.open(fileName)) - _musicMode = MusicWave; - else - return false; + _audioSource = new WaveAudioStream(&_file, loop); } - _audioSource = createAudioSource(); - _looping = loop; + + if (!_audioSource) + return false; + fadeUp(); return true; } @@ -217,18 +215,14 @@ int MusicHandle::readBuffer(int16 *buffer, const int numSamples) { expectedSamples -= samplesReturned; if ((expectedSamples > 0) && _audioSource->endOfData()) { debug(2, "Music reached EOF"); - if (_looping) { - delete _audioSource; // recreate same source. - _audioSource = createAudioSource(); - } - if ((!_looping) || (!_audioSource)) - stop(); + stop(); } } // buffer was filled, now do the fading (if necessary) int samplePos = 0; while ((_fading > 0) && (samplePos < totalSamples)) { // fade down - bufStart[samplePos] = (bufStart[samplePos] * --_fading) / _fadeSamples; + --_fading; + bufStart[samplePos] = (bufStart[samplePos] * _fading) / _fadeSamples; samplePos++; if (_fading == 0) { stop(); @@ -253,7 +247,6 @@ void MusicHandle::stop() { if (_file.isOpen()) _file.close(); _fading = 0; - _looping = false; } Music::Music(Audio::Mixer *pMixer) { diff --git a/engines/sword1/music.h b/engines/sword1/music.h index 75bb2521c1..ccce57fbb9 100644 --- a/engines/sword1/music.h +++ b/engines/sword1/music.h @@ -41,34 +41,15 @@ enum MusicMode { MusicVorbis }; -class WaveAudioStream : public Audio::AudioStream { -public: - WaveAudioStream(Common::File *source, uint32 pSize); - virtual ~WaveAudioStream(); - virtual int readBuffer(int16 *buffer, const int numSamples); - virtual bool isStereo(void) const { return _isStereo; }; - virtual bool endOfData(void) const; - virtual int getRate(void) const { return _rate; }; -private: - Common::File *_sourceFile; - uint8 *_sampleBuf; - uint32 _rate; - bool _isStereo; - uint32 _samplesLeft; - uint16 _bitsPerSample; -}; - class MusicHandle : public Audio::AudioStream { private: Common::File _file; - bool _looping; int32 _fading; int32 _fadeSamples; MusicMode _musicMode; Audio::AudioStream *_audioSource; - Audio::AudioStream *createAudioSource(void); public: - MusicHandle() : _looping(false), _fading(0), _audioSource(NULL) {} + MusicHandle() : _fading(0), _audioSource(NULL) {} virtual int readBuffer(int16 *buffer, const int numSamples); bool play(const char *filename, bool loop); void stop(); |