From 812603e29eef2bd0c224a9b3b4c2bf29b2d3b653 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Wed, 27 Jan 2010 08:08:33 +0000 Subject: Fix invalid sample position on Timestamp to sample conversion for Stereo streams. svn-id: r47591 --- engines/kyra/sound_digital.cpp | 2 +- sound/audiostream.cpp | 21 ++++++++++++++++----- sound/audiostream.h | 19 +++++++++---------- sound/decoders/flac.cpp | 2 +- sound/decoders/raw.cpp | 11 ++--------- sound/decoders/vorbis.cpp | 2 +- 6 files changed, 30 insertions(+), 27 deletions(-) diff --git a/engines/kyra/sound_digital.cpp b/engines/kyra/sound_digital.cpp index 393a2f3eda..7a04fc0691 100644 --- a/engines/kyra/sound_digital.cpp +++ b/engines/kyra/sound_digital.cpp @@ -356,7 +356,7 @@ int AUDStream::readChunk(int16 *buffer, const int maxSamples) { } bool AUDStream::seek(const Audio::Timestamp &where) { - const uint32 seekSample = Audio::calculateSampleOffset(where, getRate()); + const uint32 seekSample = Audio::convertTimeToStreamPos(where, getRate(), isStereo()).totalNumberOfFrames(); _stream->seek(_streamStart); _processedSize = 0; diff --git a/sound/audiostream.cpp b/sound/audiostream.cpp index e781149a55..08ea636a1d 100644 --- a/sound/audiostream.cpp +++ b/sound/audiostream.cpp @@ -164,8 +164,8 @@ SubLoopingAudioStream::SubLoopingAudioStream(SeekableAudioStream *stream, DisposeAfterUse::Flag disposeAfterUse) : _parent(stream), _disposeAfterUse(disposeAfterUse), _loops(loops), _pos(0, getRate() * (isStereo() ? 2 : 1)), - _loopStart(loopStart.convertToFramerate(getRate() * (isStereo() ? 2 : 1))), - _loopEnd(loopEnd.convertToFramerate(getRate() * (isStereo() ? 2 : 1))), + _loopStart(convertTimeToStreamPos(loopStart, getRate(), isStereo())), + _loopEnd(convertTimeToStreamPos(loopEnd, getRate(), isStereo())), _done(false) { if (!_parent->rewind()) _done = true; @@ -212,9 +212,9 @@ int SubLoopingAudioStream::readBuffer(int16 *buffer, const int numSamples) { SubSeekableAudioStream::SubSeekableAudioStream(SeekableAudioStream *parent, const Timestamp start, const Timestamp end, DisposeAfterUse::Flag disposeAfterUse) : _parent(parent), _disposeAfterUse(disposeAfterUse), - _start(start.convertToFramerate(getRate())), + _start(convertTimeToStreamPos(start, getRate(), isStereo())), _pos(0, getRate() * (isStereo() ? 2 : 1)), - _length((end - start).convertToFramerate(getRate() * (isStereo() ? 2 : 1))) { + _length(convertTimeToStreamPos(end - start, getRate(), isStereo())) { assert(_length.totalNumberOfFrames() % (isStereo() ? 2 : 1) == 0); _parent->seek(_start); @@ -233,7 +233,7 @@ int SubSeekableAudioStream::readBuffer(int16 *buffer, const int numSamples) { } bool SubSeekableAudioStream::seek(const Timestamp &where) { - _pos = where.convertToFramerate(getRate()); + _pos = convertTimeToStreamPos(where, getRate(), isStereo()); if (_pos > _length) { _pos = _length; return false; @@ -364,4 +364,15 @@ QueuingAudioStream *makeQueuingAudioStream(int rate, bool stereo) { return new QueuingAudioStreamImpl(rate, stereo); } +Timestamp convertTimeToStreamPos(const Timestamp &where, int rate, bool isStereo) { + Timestamp result(where.convertToFramerate(rate * (isStereo ? 2 : 1))); + + // When the Stream is a stereo stream, we have to assure + // that the sample position is an even number. + if (isStereo && (result.totalNumberOfFrames() & 1)) + return result.addFrames(-1); // We cut off one sample here. + else + return result; +} + } // End of namespace Audio diff --git a/sound/audiostream.h b/sound/audiostream.h index bb0edaa100..764662e378 100644 --- a/sound/audiostream.h +++ b/sound/audiostream.h @@ -162,9 +162,9 @@ public: * Tries to load a file by trying all available formats. * In case of an error, the file handle will be closed, but deleting * it is still the responsibility of the caller. - * @param basename a filename without an extension - * @return an SeekableAudioStream ready to use in case of success; - * NULL in case of an error (e.g. invalid/nonexisting file) + * @param basename a filename without an extension + * @return an SeekableAudioStream ready to use in case of success; + * NULL in case of an error (e.g. invalid/nonexisting file) */ static SeekableAudioStream *openStreamFile(const Common::String &basename); @@ -337,16 +337,15 @@ public: */ QueuingAudioStream *makeQueuingAudioStream(int rate, bool stereo); - /** - * Calculates the sample, which the timestamp describes in a - * AudioStream with the given framerate. + * Converts a point in time to a precise sample offset + * with the given parameters. * - * @param where point in time - * @param rate rate of the AudioStream - * @return sample index + * @param where Point in time. + * @param rate Rate of the stream. + * @param isStereo Is the stream a stereo stream? */ -uint32 calculateSampleOffset(const Timestamp &where, int rate); +Timestamp convertTimeToStreamPos(const Timestamp &where, int rate, bool isStereo); } // End of namespace Audio diff --git a/sound/decoders/flac.cpp b/sound/decoders/flac.cpp index 29302827da..6fa7302a9a 100644 --- a/sound/decoders/flac.cpp +++ b/sound/decoders/flac.cpp @@ -294,7 +294,7 @@ bool FlacInputStream::seekAbsolute(FLAC__uint64 sample) { bool FlacInputStream::seek(const Timestamp &where) { _sampleCache.bufFill = 0; _sampleCache.bufReadPos = NULL; - return seekAbsolute((FLAC__uint64)calculateSampleOffset(where, _streaminfo.sample_rate)); + return seekAbsolute((FLAC__uint64)convertTimeToStreamPos(where, getRate(), isStereo()).totalNumberOfFrames()); } int FlacInputStream::readBuffer(int16 *buffer, const int numSamples) { diff --git a/sound/decoders/raw.cpp b/sound/decoders/raw.cpp index 6747111a1a..ecdde10250 100644 --- a/sound/decoders/raw.cpp +++ b/sound/decoders/raw.cpp @@ -41,13 +41,6 @@ namespace Audio { ((is16Bit ? (isLE ? READ_LE_UINT16(ptr) : READ_BE_UINT16(ptr)) : (*ptr << 8)) ^ (isUnsigned ? 0x8000 : 0)) -// TODO: Get rid of this -uint32 calculateSampleOffset(const Timestamp &where, int rate) { - return where.convertToFramerate(rate).totalNumberOfFrames(); -} - - - #pragma mark - #pragma mark --- RawMemoryStream --- #pragma mark - @@ -110,7 +103,7 @@ int RawMemoryStream::readBuffer(int16 *buffer template bool RawMemoryStream::seek(const Timestamp &where) { - const uint8 *ptr = _origPtr + calculateSampleOffset(where, getRate()) * (is16Bit ? 2 : 1) * (stereo ? 2 : 1); + const uint8 *ptr = _origPtr + convertTimeToStreamPos(where, getRate(), isStereo()).totalNumberOfFrames() * (is16Bit ? 2 : 1); if (ptr > _end) { _ptr = _end; return false; @@ -275,7 +268,7 @@ int RawDiskStream::readBuffer(int16 *buffer, template bool RawDiskStream::seek(const Timestamp &where) { - const uint32 seekSample = calculateSampleOffset(where, getRate()) * (stereo ? 2 : 1); + const uint32 seekSample = convertTimeToStreamPos(where, getRate(), isStereo()).totalNumberOfFrames(); uint32 curSample = 0; // Search for the disk block in which the specific sample is placed diff --git a/sound/decoders/vorbis.cpp b/sound/decoders/vorbis.cpp index 46a94a6214..f5ebc112c3 100644 --- a/sound/decoders/vorbis.cpp +++ b/sound/decoders/vorbis.cpp @@ -169,7 +169,7 @@ int VorbisInputStream::readBuffer(int16 *buffer, const int numSamples) { } bool VorbisInputStream::seek(const Timestamp &where) { - int res = ov_pcm_seek(&_ovFile, calculateSampleOffset(where, getRate())); + int res = ov_pcm_seek(&_ovFile, convertTimeToStreamPos(where, getRate(), isStereo()).totalNumberOfFrames()); if (res) { warning("Error seeking in Vorbis stream (%d)", res); _pos = _bufferEnd; -- cgit v1.2.3