[Scummvm-cvs-logs] SF.net SVN: scummvm: [25792] scummvm/trunk/sound
fingolfin at users.sourceforge.net
fingolfin at users.sourceforge.net
Thu Feb 22 19:21:01 CET 2007
Revision: 25792
http://scummvm.svn.sourceforge.net/scummvm/?rev=25792&view=rev
Author: fingolfin
Date: 2007-02-22 10:21:01 -0800 (Thu, 22 Feb 2007)
Log Message:
-----------
Updated FLAC code to match the changes made to the MP3 & Vorbis decoders (e.g. use a SeekableReadStream for input, allow specifying parts of a stream via time-valued parameters, etc.) -- note: looping is not yet implemented, even though it is already present in the API
Modified Paths:
--------------
scummvm/trunk/sound/flac.cpp
scummvm/trunk/sound/flac.h
scummvm/trunk/sound/vorbis.cpp
Modified: scummvm/trunk/sound/flac.cpp
===================================================================
--- scummvm/trunk/sound/flac.cpp 2007-02-22 18:03:05 UTC (rev 25791)
+++ scummvm/trunk/sound/flac.cpp 2007-02-22 18:21:01 UTC (rev 25792)
@@ -82,61 +82,14 @@
class FlacInputStream : public AudioStream {
-
-public:
- FlacInputStream(File *sourceFile, const uint32 fileStart, const uint32 fileStop);
- FlacInputStream(File *sourceFile, const uint32 fileStart = 0);
- virtual ~FlacInputStream();
-
- int readBuffer(int16 *buffer, const int numSamples);
-
- bool isStereo() const { return _streaminfo.channels >= 2; }
- int getRate() const { return _streaminfo.sample_rate; }
- bool endOfStream() const { return _streaminfo.channels == 0 || (_lastSampleWritten && getBufferedSamples() == 0); }
- /** the mixer aint supporting it right now.. */
- //bool endOfData() const { return getBufferedSamples() == 0; }
- bool endOfData() const { return endOfStream(); }
-
- uint getChannels() const { return MIN(_streaminfo.channels, MAX_OUTPUT_CHANNELS); }
- uint getBufferedSamples() const { return _preBuffer.bufFill; };
-
- const FLAC__StreamMetadata_StreamInfo& getStreamInfo() const {return _streaminfo;}
-
- inline FLAC__SeekableStreamDecoderState getState() const;
- inline FLAC__StreamDecoderState getStreamDecoderState() const;
-
-
- bool isStreamDecoderReady() const { return getStreamDecoderState() == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC ; }
- bool init();
- bool finish();
- bool flush();
- inline bool processSingleBlock();
- inline bool processUntilEndOfMetadata();
- bool seekAbsolute(FLAC__uint64 sample);
- inline void setLastSample(FLAC__uint64 absoluteSample);
-
protected:
- inline ::FLAC__SeekableStreamDecoderReadStatus callbackRead(FLAC__byte buffer[], FLAC_size_t *bytes);
- inline ::FLAC__SeekableStreamDecoderSeekStatus callbackSeek(FLAC__uint64 absoluteByteOffset);
- inline ::FLAC__SeekableStreamDecoderTellStatus callbackTell(FLAC__uint64 *absoluteByteOffset);
- inline ::FLAC__SeekableStreamDecoderLengthStatus callbackLength(FLAC__uint64 *streamLength);
- inline bool callbackEOF();
- inline ::FLAC__StreamDecoderWriteStatus callbackWrite(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
- inline void callbackMetadata(const ::FLAC__StreamMetadata *metadata);
- inline void callbackError(::FLAC__StreamDecoderErrorStatus status);
+ Common::SeekableReadStream *_inStream;
+ bool _disposeAfterUse;
+ uint _numLoops;
+
::FLAC__SeekableStreamDecoder *_decoder;
-private:
- static ::FLAC__SeekableStreamDecoderReadStatus callWrapRead(const ::FLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], FLAC_size_t *bytes, void *clientData);
- static ::FLAC__SeekableStreamDecoderSeekStatus callWrapSeek(const ::FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absoluteByteOffset, void *clientData);
- static ::FLAC__SeekableStreamDecoderTellStatus callWrapTell(const ::FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absoluteByteOffset, void *clientData);
- static ::FLAC__SeekableStreamDecoderLengthStatus callWrapLength(const ::FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *streamLength, void *clientData);
- static FLAC__bool callWrapEOF(const ::FLAC__SeekableStreamDecoder *decoder, void *clientData);
- static ::FLAC__StreamDecoderWriteStatus callWrapWrite(const ::FLAC__SeekableStreamDecoder *decoder, const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *clientData);
- static void callWrapMetadata(const ::FLAC__SeekableStreamDecoder *decoder, const ::FLAC__StreamMetadata *metadata, void *clientData);
- static void callWrapError(const ::FLAC__SeekableStreamDecoder *decoder, ::FLAC__StreamDecoderErrorStatus status, void *clientData);
-
// Private and undefined so you can't use them:
FlacInputStream(const FlacInputStream &);
void operator=(const FlacInputStream &);
@@ -150,19 +103,9 @@
/** Header of the Stream */
FLAC__StreamMetadata_StreamInfo _streaminfo;
- struct {
- /** Handle to the File */
- File *fileHandle;
- /** Index of next Byte to read */
- uint32 filePos;
- /** start of stream - not necessary start of file */
- uint32 fileStartPos;
- /** last index of Stream + 1(!) - not necessary end of file */
- uint32 fileEndPos;
- } _fileInfo;
-
/** index of the first Sample to be played */
FLAC__uint64 _firstSample;
+
/** index + 1(!) of the last Sample to be played - 0 is end of Stream*/
FLAC__uint64 _lastSample;
@@ -182,9 +125,52 @@
bufType *_outBuffer;
uint _requestedSamples;
- void setBestConvertBufferMethod();
typedef void (*PFCONVERTBUFFERS)(bufType*,const FLAC__int32*[], uint, const uint, const uint8);
PFCONVERTBUFFERS _methodConvertBuffers;
+
+
+public:
+ FlacInputStream(Common::SeekableReadStream *inStream, bool dispose, uint startTime = 0, uint endTime = 0, uint numLoops = 1);
+ virtual ~FlacInputStream();
+
+ int readBuffer(int16 *buffer, const int numSamples);
+
+ bool isStereo() const { return _streaminfo.channels >= 2; }
+ int getRate() const { return _streaminfo.sample_rate; }
+ bool endOfData() const { return _streaminfo.channels == 0 || (_lastSampleWritten && _preBuffer.bufFill == 0); }
+
+ bool isStreamDecoderReady() const { return getStreamDecoderState() == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC ; }
+
+protected:
+ uint getChannels() const { return MIN(_streaminfo.channels, MAX_OUTPUT_CHANNELS); }
+
+ inline FLAC__SeekableStreamDecoderState getState() const;
+ inline FLAC__StreamDecoderState getStreamDecoderState() const;
+
+ inline bool processSingleBlock();
+ inline bool processUntilEndOfMetadata();
+ bool seekAbsolute(FLAC__uint64 sample);
+
+ inline ::FLAC__SeekableStreamDecoderReadStatus callbackRead(FLAC__byte buffer[], FLAC_size_t *bytes);
+ inline ::FLAC__SeekableStreamDecoderSeekStatus callbackSeek(FLAC__uint64 absoluteByteOffset);
+ inline ::FLAC__SeekableStreamDecoderTellStatus callbackTell(FLAC__uint64 *absoluteByteOffset);
+ inline ::FLAC__SeekableStreamDecoderLengthStatus callbackLength(FLAC__uint64 *streamLength);
+ inline bool callbackEOF();
+ inline ::FLAC__StreamDecoderWriteStatus callbackWrite(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
+ inline void callbackMetadata(const ::FLAC__StreamMetadata *metadata);
+ inline void callbackError(::FLAC__StreamDecoderErrorStatus status);
+
+private:
+ static ::FLAC__SeekableStreamDecoderReadStatus callWrapRead(const ::FLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], FLAC_size_t *bytes, void *clientData);
+ static ::FLAC__SeekableStreamDecoderSeekStatus callWrapSeek(const ::FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absoluteByteOffset, void *clientData);
+ static ::FLAC__SeekableStreamDecoderTellStatus callWrapTell(const ::FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absoluteByteOffset, void *clientData);
+ static ::FLAC__SeekableStreamDecoderLengthStatus callWrapLength(const ::FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *streamLength, void *clientData);
+ static FLAC__bool callWrapEOF(const ::FLAC__SeekableStreamDecoder *decoder, void *clientData);
+ static ::FLAC__StreamDecoderWriteStatus callWrapWrite(const ::FLAC__SeekableStreamDecoder *decoder, const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *clientData);
+ static void callWrapMetadata(const ::FLAC__SeekableStreamDecoder *decoder, const ::FLAC__StreamMetadata *metadata, void *clientData);
+ static void callWrapError(const ::FLAC__SeekableStreamDecoder *decoder, ::FLAC__StreamDecoderErrorStatus status, void *clientData);
+
+ void setBestConvertBufferMethod();
static void convertBuffersGeneric(bufType* bufDestination, const FLAC__int32 *inChannels[], uint numSamples, const uint numChannels, const uint8 numBits);
static void convertBuffersStereoNS(bufType* bufDestination, const FLAC__int32 *inChannels[], uint numSamples, const uint numChannels, const uint8 numBits);
static void convertBuffersStereo8Bit(bufType* bufDestination, const FLAC__int32 *inChannels[], uint numSamples, const uint numChannels, const uint8 numBits);
@@ -192,102 +178,33 @@
static void convertBuffersMono8Bit(bufType* bufDestination, const FLAC__int32 *inChannels[], uint numSamples, const uint numChannels, const uint8 numBits);
};
-FlacInputStream::FlacInputStream(File *sourceFile, const uint32 fileStart)
+FlacInputStream::FlacInputStream(Common::SeekableReadStream *inStream, bool dispose, uint startTime, uint endTime, uint numLoops)
#ifdef LEGACY_FLAC
: _decoder(::FLAC__seekable_stream_decoder_new()),
#else
: _decoder(::FLAC__stream_decoder_new()),
#endif
- _firstSample(0), _lastSample(0),
- _outBuffer(NULL), _requestedSamples(0), _lastSampleWritten(true),
- _methodConvertBuffers(&FlacInputStream::convertBuffersGeneric)
+ _inStream(inStream),
+ _disposeAfterUse(dispose),
+ _numLoops(numLoops),
+ _firstSample(0), _lastSample(0),
+ _outBuffer(NULL), _requestedSamples(0), _lastSampleWritten(true),
+ _methodConvertBuffers(&FlacInputStream::convertBuffersGeneric)
{
- assert(sourceFile != NULL && sourceFile->isOpen());
-
+ assert(_inStream);
memset(&_streaminfo, 0, sizeof(_streaminfo));
- _preBuffer.bufData = NULL;
- _preBuffer.bufFill = 0;
- _preBuffer.bufSize = 0;
+// TODO: Implement looping support
- _fileInfo.fileHandle = sourceFile;
- _fileInfo.fileStartPos = fileStart;
- _fileInfo.filePos = fileStart;
- _fileInfo.fileEndPos = sourceFile->size();
-
- _fileInfo.fileHandle->incRef();
-}
-
-FlacInputStream::FlacInputStream(File *sourceFile, const uint32 fileStart, const uint32 fileStop)
-#ifdef LEGACY_FLAC
- : _decoder(::FLAC__seekable_stream_decoder_new()),
-#else
- : _decoder(::FLAC__stream_decoder_new()),
-#endif
- _firstSample(0), _lastSample(0),
- _outBuffer(NULL), _requestedSamples(0), _lastSampleWritten(true),
- _methodConvertBuffers(&FlacInputStream::convertBuffersGeneric)
-{
- assert(sourceFile != NULL && sourceFile->isOpen());
- assert(fileStop <= 0 || (fileStart < fileStop && fileStop <= sourceFile->size()));
-
- memset(&_streaminfo, 0, sizeof(_streaminfo));
-
_preBuffer.bufData = NULL;
_preBuffer.bufFill = 0;
_preBuffer.bufSize = 0;
- _fileInfo.fileHandle = sourceFile;
- _fileInfo.fileStartPos = fileStart;
- _fileInfo.filePos = fileStart;
- _fileInfo.fileEndPos = fileStop;
-
- _fileInfo.fileHandle->incRef();
-}
-
-FlacInputStream::~FlacInputStream() {
- if (_decoder != NULL) {
-#ifdef LEGACY_FLAC
- (void) ::FLAC__seekable_stream_decoder_finish(_decoder);
- ::FLAC__seekable_stream_decoder_delete(_decoder);
-#else
- (void) ::FLAC__stream_decoder_finish(_decoder);
- ::FLAC__stream_decoder_delete(_decoder);
-#endif
- }
- if (_preBuffer.bufData != NULL)
- delete[] _preBuffer.bufData;
-
- _fileInfo.fileHandle->decRef();
-}
-
-inline FLAC__SeekableStreamDecoderState FlacInputStream::getState() const {
- assert(isValid());
-#ifdef LEGACY_FLAC
- return ::FLAC__seekable_stream_decoder_get_state(_decoder);
-#else
- return ::FLAC__stream_decoder_get_state(_decoder);
-#endif
-}
-
-inline FLAC__StreamDecoderState FlacInputStream::getStreamDecoderState() const {
- assert(isValid());
-#ifdef LEGACY_FLAC
- return ::FLAC__seekable_stream_decoder_get_stream_decoder_state(_decoder);
-#else
- return ::FLAC__stream_decoder_get_state(_decoder);
-#endif
-}
-
-bool FlacInputStream::init() {
- assert(isValid());
-
- memset(&_streaminfo, 0, sizeof (_streaminfo));
deleteBuffer();
- _fileInfo.filePos = _fileInfo.fileStartPos;
_lastSampleWritten = false;
_methodConvertBuffers = &FlacInputStream::convertBuffersGeneric;
+ bool success;
#ifdef LEGACY_FLAC
::FLAC__seekable_stream_decoder_set_read_callback(_decoder, &FlacInputStream::callWrapRead);
::FLAC__seekable_stream_decoder_set_seek_callback(_decoder, &FlacInputStream::callWrapSeek);
@@ -299,16 +216,9 @@
::FLAC__seekable_stream_decoder_set_error_callback(_decoder, &FlacInputStream::callWrapError);
::FLAC__seekable_stream_decoder_set_client_data(_decoder, (void*)this);
- if (::FLAC__seekable_stream_decoder_init(_decoder) == FLAC__SEEKABLE_STREAM_DECODER_OK) {
- if (processUntilEndOfMetadata() && _streaminfo.channels > 0) {
- if (_firstSample == 0 || 0 != ::FLAC__seekable_stream_decoder_seek_absolute(_decoder, _firstSample)) {
- // FLAC__StreamDecoderState state = getStreamDecoderState();
- return true; // no error occured
- }
- }
- }
+ success = (::FLAC__seekable_stream_decoder_init(_decoder) == FLAC__SEEKABLE_STREAM_DECODER_OK);
#else
- if (::FLAC__stream_decoder_init_stream(
+ success = (::FLAC__stream_decoder_init_stream(
_decoder,
&FlacInputStream::callWrapRead,
&FlacInputStream::callWrapSeek,
@@ -319,37 +229,52 @@
&FlacInputStream::callWrapMetadata,
&FlacInputStream::callWrapError,
(void*)this
- ) == FLAC__STREAM_DECODER_INIT_STATUS_OK) {
+ ) == FLAC__STREAM_DECODER_INIT_STATUS_OK);
+#endif
+ if (success) {
if (processUntilEndOfMetadata() && _streaminfo.channels > 0) {
- if (_firstSample == 0 || 0 != ::FLAC__stream_decoder_seek_absolute(_decoder, _firstSample)) {
- // FLAC__StreamDecoderState state = getStreamDecoderState();
- return true; // no error occured
+ _firstSample = (FLAC__uint64)(startTime * (_streaminfo.sample_rate / 1000.0));
+ _lastSample = (FLAC__uint64)(endTime * (_streaminfo.sample_rate / 1000.0));
+ if (_firstSample == 0 || seekAbsolute(_firstSample)) {
+ return; // no error occured
}
}
}
+
+ warning("FlacInputStream: could not create audio stream");
+}
+
+FlacInputStream::~FlacInputStream() {
+ if (_decoder != NULL) {
+#ifdef LEGACY_FLAC
+ (void) ::FLAC__seekable_stream_decoder_finish(_decoder);
+ ::FLAC__seekable_stream_decoder_delete(_decoder);
+#else
+ (void) ::FLAC__stream_decoder_finish(_decoder);
+ ::FLAC__stream_decoder_delete(_decoder);
#endif
+ }
+ delete[] _preBuffer.bufData;
- warning("FlacInputStream: could not create an Audiostream from File %s", _fileInfo.fileHandle->name());
- return false;
+ if (_disposeAfterUse)
+ delete _inStream;
}
-bool FlacInputStream::finish() {
+inline FLAC__SeekableStreamDecoderState FlacInputStream::getState() const {
assert(isValid());
- deleteBuffer();
#ifdef LEGACY_FLAC
- return 0 != ::FLAC__seekable_stream_decoder_finish(_decoder);
+ return ::FLAC__seekable_stream_decoder_get_state(_decoder);
#else
- return 0 != ::FLAC__stream_decoder_finish(_decoder);
+ return ::FLAC__stream_decoder_get_state(_decoder);
#endif
}
-bool FlacInputStream::flush() {
+inline FLAC__StreamDecoderState FlacInputStream::getStreamDecoderState() const {
assert(isValid());
- flushBuffer();
#ifdef LEGACY_FLAC
- return 0 != ::FLAC__seekable_stream_decoder_flush(_decoder);
+ return ::FLAC__seekable_stream_decoder_get_stream_decoder_state(_decoder);
#else
- return 0 != ::FLAC__stream_decoder_flush(_decoder);
+ return ::FLAC__stream_decoder_get_state(_decoder);
#endif
}
@@ -451,8 +376,6 @@
}
inline ::FLAC__SeekableStreamDecoderReadStatus FlacInputStream::callbackRead(FLAC__byte buffer[], FLAC_size_t *bytes) {
- assert(_fileInfo.fileHandle != NULL);
-
if (*bytes == 0)
#ifdef LEGACY_FLAC
return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; /* abort to avoid a deadlock */
@@ -460,19 +383,15 @@
return FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */
#endif
- const uint32 length = MIN(_fileInfo.fileEndPos - _fileInfo.filePos, static_cast<uint32>(*bytes));
+ const uint32 bytesRead = _inStream->read(buffer, *bytes);
- _fileInfo.fileHandle->seek(_fileInfo.filePos);
- const uint32 bytesRead = _fileInfo.fileHandle->read(buffer, length);
-
- if (bytesRead == 0 && _fileInfo.fileHandle->ioFailed())
+ if (bytesRead == 0 && _inStream->ioFailed())
#ifdef LEGACY_FLAC
return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
#else
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
#endif
- _fileInfo.filePos += bytesRead;
*bytes = static_cast<uint>(bytesRead);
#ifdef LEGACY_FLAC
return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
@@ -481,12 +400,6 @@
#endif
}
-inline void FlacInputStream::setLastSample(FLAC__uint64 absoluteSample) {
- if (_lastSampleWritten && absoluteSample > _lastSample)
- _lastSampleWritten = false;
- _lastSample = absoluteSample;
-}
-
inline void FlacInputStream::flushBuffer() {
_lastSampleWritten = _lastSampleWritten && _preBuffer.bufFill == 0;
_preBuffer.bufFill = 0;
@@ -751,12 +664,9 @@
}
inline ::FLAC__SeekableStreamDecoderSeekStatus FlacInputStream::callbackSeek(FLAC__uint64 absoluteByteOffset) {
- FLAC__uint64 newPos = absoluteByteOffset + _fileInfo.fileStartPos;
- const bool result = (newPos < _fileInfo.fileEndPos);
+ _inStream->seek(absoluteByteOffset, SEEK_SET);
+ const bool result = (absoluteByteOffset == _inStream->pos());
- if (result)
- _fileInfo.filePos = static_cast<uint32>(newPos);
-
#ifdef LEGACY_FLAC
return result ? FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK : FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
#else
@@ -765,9 +675,7 @@
}
inline ::FLAC__SeekableStreamDecoderTellStatus FlacInputStream::callbackTell(FLAC__uint64 *absoluteByteOffset) {
- /*if ()
- return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;*/
- *absoluteByteOffset = static_cast<FLAC__uint64>(_fileInfo.filePos-_fileInfo.fileStartPos);
+ *absoluteByteOffset = static_cast<FLAC__uint64>(_inStream->pos());
#ifdef LEGACY_FLAC
return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
#else
@@ -776,15 +684,8 @@
}
inline ::FLAC__SeekableStreamDecoderLengthStatus FlacInputStream::callbackLength(FLAC__uint64 *streamLength) {
- if (_fileInfo.fileStartPos > _fileInfo.fileEndPos)
+ *streamLength = static_cast<FLAC__uint64>(_inStream->size());
#ifdef LEGACY_FLAC
- return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR;
-#else
- return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
-#endif
-
- *streamLength = static_cast<FLAC__uint64>(_fileInfo.fileEndPos - _fileInfo.fileStartPos);
-#ifdef LEGACY_FLAC
return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
#else
return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
@@ -792,7 +693,7 @@
}
inline bool FlacInputStream::callbackEOF() {
- return _fileInfo.filePos >= _fileInfo.fileEndPos;
+ return _inStream->eos();
}
@@ -895,10 +796,10 @@
}
// Next, try to create a FlacInputStream from it
- FlacInputStream *tempStream = new FlacInputStream(&file);
+ FlacInputStream *tempStream = new FlacInputStream(&file, false);
// If initialising the stream fails, we set the error flag
- if (!tempStream || !tempStream->init())
+ if (!tempStream || !tempStream->isStreamDecoderReady())
_errorFlag = true;
delete tempStream;
@@ -919,28 +820,19 @@
return;
}
- // Create an AudioStream from the file
- FlacInputStream *flac = new FlacInputStream(file);
- flac->init();
- file->decRef();
+ // Convert startFrame & duration from frames (1/75 s) to milliseconds (1/1000s)
+ uint start = startFrame * 1000 / 75;
+ uint end = duration ? ((startFrame + duration) * 1000 / 75) : 0;
- // Seek to the correct start position and start playback
- if (flac->isStreamDecoderReady()) {
- const FLAC__StreamMetadata_StreamInfo &info = flac->getStreamInfo();
- if (duration)
- flac->setLastSample(static_cast<FLAC__uint64>(startFrame + duration) * (info.sample_rate / 75));
- else
- flac->setLastSample(0);
-
- if (flac->seekAbsolute(static_cast<FLAC__uint64>(startFrame) * (info.sample_rate / 75))) {
- mixer->playInputStream(Audio::Mixer::kMusicSoundType, handle, flac);
- return;
- }
- // startSample is beyond the existing Samples
- debug(1, "FlacTrackInfo: Audiostream %s could not seek to frame %d (ca %d secs)", _filename.c_str(), startFrame, startFrame/75);
- flac->finish();
+ // ... create an AudioStream ...
+ FlacInputStream *input = new FlacInputStream(file, true, start, end);
+ if (!input->isStreamDecoderReady()) {
+ delete input;
+ return;
}
- delete flac;
+
+ // ... and play it
+ mixer->playInputStream(Audio::Mixer::kMusicSoundType, handle, input);
}
DigitalTrackInfo* getFlacTrack(int track) {
@@ -964,19 +856,46 @@
return NULL;
}
-AudioStream *makeFlacStream(File *file, uint32 length) {
- assert(file != NULL);
- uint32 start = file->pos();
+AudioStream *makeFlacStream(File *file, uint32 size) {
+ assert(file);
- FlacInputStream *flac = new FlacInputStream(file, start, start + length);
- if (flac->init())
- return flac;
+ // FIXME: For now, just read the whole data into memory, and be done
+ // with it. Of course this is in general *not* a nice thing to do...
- delete flac;
- return NULL;
+ // If no size was specified, read the whole remainder of the file
+ if (!size)
+ size = file->size() - file->pos();
+
+ // Read 'size' bytes of data into a MemoryReadStream
+ Common::MemoryReadStream *stream = file->readStream(size);
+
+ // .. and create an MP3InputStream from all this
+ FlacInputStream *input = new FlacInputStream(stream, true);
+ if (!input->isStreamDecoderReady()) {
+ delete input;
+ return 0;
+ }
+ return input;
}
+AudioStream *makeFlacStream(
+ Common::SeekableReadStream *stream,
+ bool disposeAfterUse,
+ uint32 startTime,
+ uint32 duration,
+ uint numLoops) {
+ uint32 endTime = duration ? (startTime + duration) : 0;
+
+ FlacInputStream *input = new FlacInputStream(stream, disposeAfterUse, startTime, endTime, numLoops);
+ if (!input->isStreamDecoderReady()) {
+ delete input;
+ return 0;
+ }
+ return input;
+}
+
+
} // End of namespace Audio
#endif // #ifdef USE_FLAC
Modified: scummvm/trunk/sound/flac.h
===================================================================
--- scummvm/trunk/sound/flac.h 2007-02-22 18:03:05 UTC (rev 25791)
+++ scummvm/trunk/sound/flac.h 2007-02-22 18:21:01 UTC (rev 25792)
@@ -30,6 +30,7 @@
namespace Common {
class File;
+ class SeekableReadStream;
}
namespace Audio {
@@ -47,6 +48,27 @@
*/
AudioStream *makeFlacStream(Common::File *file, uint32 size);
+
+/**
+ * Create a new AudioStream from the FLAC data in the given stream.
+ * Allows for looping (which is why we require a SeekableReadStream),
+ * and specifying only a portion of the data to be played, based
+ * on time offsets.
+ *
+ * @param stream the SeekableReadStream from which to read the MP3 data
+ * @param disposeAfterUse whether to delete the stream after use
+ * @param startTime the (optional) time offset in milliseconds from which to start playback
+ * @param duration the (optional) time in milliseconds specifying how long to play
+ * @param numLoops how often the data shall be looped (0 = infinite)
+ * @return a new AudioStream, or NULL, if an error occured
+ */
+AudioStream *makeFlacStream(
+ Common::SeekableReadStream *stream,
+ bool disposeAfterUse,
+ uint32 startTime = 0,
+ uint32 duration = 0,
+ uint numLoops = 1);
+
} // End of namespace Audio
#endif // #ifdef USE_FLAC
Modified: scummvm/trunk/sound/vorbis.cpp
===================================================================
--- scummvm/trunk/sound/vorbis.cpp 2007-02-22 18:03:05 UTC (rev 25791)
+++ scummvm/trunk/sound/vorbis.cpp 2007-02-22 18:21:01 UTC (rev 25792)
@@ -332,7 +332,6 @@
void VorbisTrackInfo::play(Audio::Mixer *mixer, Audio::SoundHandle *handle, int startFrame, int duration) {
assert(!_errorFlag);
- uint start, end;
// Open the file
Common::File *file = new Common::File();
@@ -343,8 +342,8 @@
}
// Convert startFrame & duration from frames (1/75 s) to milliseconds (1/1000s)
- start = startFrame * 1000 / 75;
- end = duration ? ((startFrame + duration) * 1000 / 75) : 0;
+ uint start = startFrame * 1000 / 75;
+ uint end = duration ? ((startFrame + duration) * 1000 / 75) : 0;
// ... create an AudioStream ...
VorbisInputStream *input = new VorbisInputStream(file, true, start, end);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Scummvm-git-logs
mailing list