[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