1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "common/debug.h"
24 #include "common/file.h"
25 #include "common/mutex.h"
26 #include "common/textconsole.h"
27 #include "common/queue.h"
28 #include "common/util.h"
29 
30 #include "audio/audiostream.h"
31 #include "audio/decoders/flac.h"
32 #include "audio/decoders/mp3.h"
33 #include "audio/decoders/quicktime.h"
34 #include "audio/decoders/raw.h"
35 #include "audio/decoders/vorbis.h"
36 #include "audio/mixer.h"
37 
38 
39 namespace Audio {
40 
41 struct StreamFileFormat {
42 	/** Decodername */
43 	const char *decoderName;
44 	const char *fileExtension;
45 	/**
46 	 * Pointer to a function which tries to open a file of type StreamFormat.
47 	 * Return NULL in case of an error (invalid/nonexisting file).
48 	 */
49 	SeekableAudioStream *(*openStreamFile)(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse);
50 };
51 
52 static const StreamFileFormat STREAM_FILEFORMATS[] = {
53 	/* decoderName,  fileExt, openStreamFunction */
54 #ifdef USE_FLAC
55 	{ "FLAC",         ".flac", makeFLACStream },
56 	{ "FLAC",         ".fla",  makeFLACStream },
57 #endif
58 #ifdef USE_VORBIS
59 	{ "Ogg Vorbis",   ".ogg",  makeVorbisStream },
60 #endif
61 #ifdef USE_MAD
62 	{ "MPEG Layer 3", ".mp3",  makeMP3Stream },
63 #endif
64 	{ "MPEG-4 Audio",   ".m4a",  makeQuickTimeStream },
65 };
66 
openStreamFile(const Common::String & basename)67 SeekableAudioStream *SeekableAudioStream::openStreamFile(const Common::String &basename) {
68 	SeekableAudioStream *stream = NULL;
69 	Common::File *fileHandle = new Common::File();
70 
71 	for (int i = 0; i < ARRAYSIZE(STREAM_FILEFORMATS); ++i) {
72 		Common::String filename = basename + STREAM_FILEFORMATS[i].fileExtension;
73 		fileHandle->open(filename);
74 		if (fileHandle->isOpen()) {
75 			// Create the stream object
76 			stream = STREAM_FILEFORMATS[i].openStreamFile(fileHandle, DisposeAfterUse::YES);
77 			fileHandle = 0;
78 			break;
79 		}
80 	}
81 
82 	delete fileHandle;
83 
84 	if (stream == NULL)
85 		debug(1, "SeekableAudioStream::openStreamFile: Could not open compressed AudioFile %s", basename.c_str());
86 
87 	return stream;
88 }
89 
90 #pragma mark -
91 #pragma mark --- LoopingAudioStream ---
92 #pragma mark -
93 
LoopingAudioStream(RewindableAudioStream * stream,uint loops,DisposeAfterUse::Flag disposeAfterUse)94 LoopingAudioStream::LoopingAudioStream(RewindableAudioStream *stream, uint loops, DisposeAfterUse::Flag disposeAfterUse)
95     : _parent(stream, disposeAfterUse), _loops(loops), _completeIterations(0) {
96 	assert(stream);
97 
98 	if (!stream->rewind()) {
99 		// TODO: Properly indicate error
100 		_loops = _completeIterations = 1;
101 	}
102 	if (stream->endOfStream()) {
103 		// Apparently this is an empty stream
104 		_loops = _completeIterations = 1;
105 	}
106 }
107 
readBuffer(int16 * buffer,const int numSamples)108 int LoopingAudioStream::readBuffer(int16 *buffer, const int numSamples) {
109 	if ((_loops && _completeIterations == _loops) || !numSamples)
110 		return 0;
111 
112 	int samplesRead = _parent->readBuffer(buffer, numSamples);
113 
114 	if (_parent->endOfStream()) {
115 		++_completeIterations;
116 		if (_completeIterations == _loops)
117 			return samplesRead;
118 
119 		const int remainingSamples = numSamples - samplesRead;
120 
121 		if (!_parent->rewind()) {
122 			// TODO: Properly indicate error
123 			_loops = _completeIterations = 1;
124 			return samplesRead;
125 		}
126 		if (_parent->endOfStream()) {
127 			// Apparently this is an empty stream
128 			_loops = _completeIterations = 1;
129 		}
130 
131 		return samplesRead + readBuffer(buffer + samplesRead, remainingSamples);
132 	}
133 
134 	return samplesRead;
135 }
136 
endOfData() const137 bool LoopingAudioStream::endOfData() const {
138 	return (_loops != 0 && _completeIterations == _loops) || _parent->endOfData();
139 }
140 
endOfStream() const141 bool LoopingAudioStream::endOfStream() const {
142 	return _loops != 0 && _completeIterations == _loops;
143 }
144 
makeLoopingAudioStream(RewindableAudioStream * stream,uint loops)145 AudioStream *makeLoopingAudioStream(RewindableAudioStream *stream, uint loops) {
146 	if (loops != 1)
147 		return new LoopingAudioStream(stream, loops);
148 	else
149 		return stream;
150 }
151 
makeLoopingAudioStream(SeekableAudioStream * stream,Timestamp start,Timestamp end,uint loops)152 AudioStream *makeLoopingAudioStream(SeekableAudioStream *stream, Timestamp start, Timestamp end, uint loops) {
153 	if (!start.totalNumberOfFrames() && (!end.totalNumberOfFrames() || end == stream->getLength())) {
154 		return makeLoopingAudioStream(stream, loops);
155 	} else {
156 		if (!end.totalNumberOfFrames())
157 			end = stream->getLength();
158 
159 		if (start >= end) {
160 			warning("makeLoopingAudioStream: start (%d) >= end (%d)", start.msecs(), end.msecs());
161 			delete stream;
162 			return 0;
163 		}
164 
165 		return makeLoopingAudioStream(new SubSeekableAudioStream(stream, start, end), loops);
166 	}
167 }
168 
169 #pragma mark -
170 #pragma mark --- SubLoopingAudioStream ---
171 #pragma mark -
172 
SubLoopingAudioStream(SeekableAudioStream * stream,uint loops,const Timestamp loopStart,const Timestamp loopEnd,DisposeAfterUse::Flag disposeAfterUse)173 SubLoopingAudioStream::SubLoopingAudioStream(SeekableAudioStream *stream,
174                                              uint loops,
175                                              const Timestamp loopStart,
176                                              const Timestamp loopEnd,
177                                              DisposeAfterUse::Flag disposeAfterUse)
178     : _parent(stream, disposeAfterUse), _loops(loops),
179       _pos(0, getRate() * (isStereo() ? 2 : 1)),
180       _loopStart(convertTimeToStreamPos(loopStart, getRate(), isStereo())),
181       _loopEnd(convertTimeToStreamPos(loopEnd, getRate(), isStereo())),
182       _done(false) {
183 	assert(loopStart < loopEnd);
184 
185 	if (!_parent->rewind())
186 		_done = true;
187 }
188 
readBuffer(int16 * buffer,const int numSamples)189 int SubLoopingAudioStream::readBuffer(int16 *buffer, const int numSamples) {
190 	if (_done)
191 		return 0;
192 
193 	int framesLeft = MIN(_loopEnd.frameDiff(_pos), numSamples);
194 	int framesRead = _parent->readBuffer(buffer, framesLeft);
195 	_pos = _pos.addFrames(framesRead);
196 
197 	if (framesRead < framesLeft && _parent->endOfStream()) {
198 		// TODO: Proper error indication.
199 		_done = true;
200 		return framesRead;
201 	} else if (_pos == _loopEnd) {
202 		if (_loops != 0) {
203 			--_loops;
204 			if (!_loops) {
205 				_done = true;
206 				return framesRead;
207 			}
208 		}
209 
210 		if (!_parent->seek(_loopStart)) {
211 			// TODO: Proper error indication.
212 			_done = true;
213 			return framesRead;
214 		}
215 
216 		_pos = _loopStart;
217 		framesLeft = numSamples - framesLeft;
218 		return framesRead + readBuffer(buffer + framesRead, framesLeft);
219 	} else {
220 		return framesRead;
221 	}
222 }
223 
endOfData() const224 bool SubLoopingAudioStream::endOfData() const {
225 	// We're out of data if this stream is finished or the parent
226 	// has run out of data for now.
227 	return _done || _parent->endOfData();
228 }
229 
endOfStream() const230 bool SubLoopingAudioStream::endOfStream() const {
231 	// The end of the stream has been reached only when we've gone
232 	// through all the iterations.
233 	return _done;
234 }
235 
236 #pragma mark -
237 #pragma mark --- SubSeekableAudioStream ---
238 #pragma mark -
239 
SubSeekableAudioStream(SeekableAudioStream * parent,const Timestamp start,const Timestamp end,DisposeAfterUse::Flag disposeAfterUse)240 SubSeekableAudioStream::SubSeekableAudioStream(SeekableAudioStream *parent, const Timestamp start, const Timestamp end, DisposeAfterUse::Flag disposeAfterUse)
241     : _parent(parent, disposeAfterUse),
242       _start(convertTimeToStreamPos(start, getRate(), isStereo())),
243       _pos(0, getRate() * (isStereo() ? 2 : 1)),
244       _length(convertTimeToStreamPos(end, getRate(), isStereo()) - _start) {
245 
246 	assert(_length.totalNumberOfFrames() % (isStereo() ? 2 : 1) == 0);
247 	_parent->seek(_start);
248 }
249 
readBuffer(int16 * buffer,const int numSamples)250 int SubSeekableAudioStream::readBuffer(int16 *buffer, const int numSamples) {
251 	int framesLeft = MIN(_length.frameDiff(_pos), numSamples);
252 	int framesRead = _parent->readBuffer(buffer, framesLeft);
253 	_pos = _pos.addFrames(framesRead);
254 	return framesRead;
255 }
256 
seek(const Timestamp & where)257 bool SubSeekableAudioStream::seek(const Timestamp &where) {
258 	_pos = convertTimeToStreamPos(where, getRate(), isStereo());
259 	if (_pos > _length) {
260 		_pos = _length;
261 		return false;
262 	}
263 
264 	if (_parent->seek(_pos + _start)) {
265 		return true;
266 	} else {
267 		_pos = _length;
268 		return false;
269 	}
270 }
271 
272 #pragma mark -
273 #pragma mark --- Queueing audio stream ---
274 #pragma mark -
275 
276 
queueBuffer(byte * data,uint32 size,DisposeAfterUse::Flag disposeAfterUse,byte flags)277 void QueuingAudioStream::queueBuffer(byte *data, uint32 size, DisposeAfterUse::Flag disposeAfterUse, byte flags) {
278 	AudioStream *stream = makeRawStream(data, size, getRate(), flags, disposeAfterUse);
279 	queueAudioStream(stream, DisposeAfterUse::YES);
280 }
281 
282 
283 class QueuingAudioStreamImpl : public QueuingAudioStream {
284 private:
285 	/**
286 	 * We queue a number of (pointers to) audio stream objects.
287 	 * In addition, we need to remember for each stream whether
288 	 * to dispose it after all data has been read from it.
289 	 * Hence, we don't store pointers to stream objects directly,
290 	 * but rather StreamHolder structs.
291 	 */
292 	struct StreamHolder {
293 		AudioStream *_stream;
294 		DisposeAfterUse::Flag _disposeAfterUse;
StreamHolderAudio::QueuingAudioStreamImpl::StreamHolder295 		StreamHolder(AudioStream *stream, DisposeAfterUse::Flag disposeAfterUse)
296 		    : _stream(stream),
297 		      _disposeAfterUse(disposeAfterUse) {}
298 	};
299 
300 	/**
301 	 * The sampling rate of this audio stream.
302 	 */
303 	const int _rate;
304 
305 	/**
306 	 * Whether this audio stream is mono (=false) or stereo (=true).
307 	 */
308 	const int _stereo;
309 
310 	/**
311 	 * This flag is set by the finish() method only. See there for more details.
312 	 */
313 	bool _finished;
314 
315 	/**
316 	 * A mutex to avoid access problems (causing e.g. corruption of
317 	 * the linked list) in thread aware environments.
318 	 */
319 	Common::Mutex _mutex;
320 
321 	/**
322 	 * The queue of audio streams.
323 	 */
324 	Common::Queue<StreamHolder> _queue;
325 
326 public:
QueuingAudioStreamImpl(int rate,bool stereo)327 	QueuingAudioStreamImpl(int rate, bool stereo)
328 	    : _rate(rate), _stereo(stereo), _finished(false) {}
329 	~QueuingAudioStreamImpl();
330 
331 	// Implement the AudioStream API
332 	virtual int readBuffer(int16 *buffer, const int numSamples);
isStereo() const333 	virtual bool isStereo() const { return _stereo; }
getRate() const334 	virtual int getRate() const { return _rate; }
335 
endOfData() const336 	virtual bool endOfData() const {
337 		Common::StackLock lock(_mutex);
338 		return _queue.empty() || _queue.front()._stream->endOfData();
339 	}
340 
endOfStream() const341 	virtual bool endOfStream() const {
342 		Common::StackLock lock(_mutex);
343 		return _finished && _queue.empty();
344 	}
345 
346 	// Implement the QueuingAudioStream API
347 	virtual void queueAudioStream(AudioStream *stream, DisposeAfterUse::Flag disposeAfterUse);
348 
finish()349 	virtual void finish() {
350 		Common::StackLock lock(_mutex);
351 		_finished = true;
352 	}
353 
numQueuedStreams() const354 	uint32 numQueuedStreams() const {
355 		Common::StackLock lock(_mutex);
356 		return _queue.size();
357 	}
358 };
359 
~QueuingAudioStreamImpl()360 QueuingAudioStreamImpl::~QueuingAudioStreamImpl() {
361 	while (!_queue.empty()) {
362 		StreamHolder tmp = _queue.pop();
363 		if (tmp._disposeAfterUse == DisposeAfterUse::YES)
364 			delete tmp._stream;
365 	}
366 }
367 
queueAudioStream(AudioStream * stream,DisposeAfterUse::Flag disposeAfterUse)368 void QueuingAudioStreamImpl::queueAudioStream(AudioStream *stream, DisposeAfterUse::Flag disposeAfterUse) {
369 	assert(!_finished);
370 	if ((stream->getRate() != getRate()) || (stream->isStereo() != isStereo()))
371 		error("QueuingAudioStreamImpl::queueAudioStream: stream has mismatched parameters");
372 
373 	Common::StackLock lock(_mutex);
374 	_queue.push(StreamHolder(stream, disposeAfterUse));
375 }
376 
readBuffer(int16 * buffer,const int numSamples)377 int QueuingAudioStreamImpl::readBuffer(int16 *buffer, const int numSamples) {
378 	Common::StackLock lock(_mutex);
379 	int samplesDecoded = 0;
380 
381 	while (samplesDecoded < numSamples && !_queue.empty()) {
382 		AudioStream *stream = _queue.front()._stream;
383 		samplesDecoded += stream->readBuffer(buffer + samplesDecoded, numSamples - samplesDecoded);
384 
385 		// Done with the stream completely
386 		if (stream->endOfStream()) {
387 			StreamHolder tmp = _queue.pop();
388 			if (tmp._disposeAfterUse == DisposeAfterUse::YES)
389 				delete stream;
390 			continue;
391 		}
392 
393 		// Done with data but not the stream, bail out
394 		if (stream->endOfData())
395 			break;
396 	}
397 
398 	return samplesDecoded;
399 }
400 
makeQueuingAudioStream(int rate,bool stereo)401 QueuingAudioStream *makeQueuingAudioStream(int rate, bool stereo) {
402 	return new QueuingAudioStreamImpl(rate, stereo);
403 }
404 
convertTimeToStreamPos(const Timestamp & where,int rate,bool isStereo)405 Timestamp convertTimeToStreamPos(const Timestamp &where, int rate, bool isStereo) {
406 	Timestamp result(where.convertToFramerate(rate * (isStereo ? 2 : 1)));
407 
408 	// When the Stream is a stereo stream, we have to assure
409 	// that the sample position is an even number.
410 	if (isStereo && (result.totalNumberOfFrames() & 1))
411 		result = result.addFrames(-1); // We cut off one sample here.
412 
413 	// Since Timestamp allows sub-frame-precision it might lead to odd behaviors
414 	// when we would just return result.
415 	//
416 	// An example is when converting the timestamp 500ms to a 11025 Hz based
417 	// stream. It would have an internal frame counter of 5512.5. Now when
418 	// doing calculations at frame precision, this might lead to unexpected
419 	// results: The frame difference between a timestamp 1000ms and the above
420 	// mentioned timestamp (both with 11025 as framerate) would be 5512,
421 	// instead of 5513, which is what a frame-precision based code would expect.
422 	//
423 	// By creating a new Timestamp with the given parameters, we create a
424 	// Timestamp with frame-precision, which just drops a sub-frame-precision
425 	// information (i.e. rounds down).
426 	return Timestamp(result.secs(), result.numberOfFrames(), result.framerate());
427 }
428 
429 /**
430  * An AudioStream wrapper that cuts off the amount of samples read after a
431  * given time length is reached.
432  */
433 class LimitingAudioStream : public AudioStream {
434 public:
LimitingAudioStream(AudioStream * parentStream,const Audio::Timestamp & length,DisposeAfterUse::Flag disposeAfterUse)435 	LimitingAudioStream(AudioStream *parentStream, const Audio::Timestamp &length, DisposeAfterUse::Flag disposeAfterUse) :
436 			_parentStream(parentStream), _samplesRead(0), _disposeAfterUse(disposeAfterUse),
437 			_totalSamples(length.convertToFramerate(getRate()).totalNumberOfFrames() * getChannels()) {}
438 
~LimitingAudioStream()439 	~LimitingAudioStream() {
440 		if (_disposeAfterUse == DisposeAfterUse::YES)
441 			delete _parentStream;
442 	}
443 
readBuffer(int16 * buffer,const int numSamples)444 	int readBuffer(int16 *buffer, const int numSamples) {
445 		// Cap us off so we don't read past _totalSamples
446 		int samplesRead = _parentStream->readBuffer(buffer, MIN<int>(numSamples, _totalSamples - _samplesRead));
447 		_samplesRead += samplesRead;
448 		return samplesRead;
449 	}
450 
endOfData() const451 	bool endOfData() const { return _parentStream->endOfData() || reachedLimit(); }
endOfStream() const452 	bool endOfStream() const { return _parentStream->endOfStream() || reachedLimit(); }
isStereo() const453 	bool isStereo() const { return _parentStream->isStereo(); }
getRate() const454 	int getRate() const { return _parentStream->getRate(); }
455 
456 private:
getChannels() const457 	int getChannels() const { return isStereo() ? 2 : 1; }
reachedLimit() const458 	bool reachedLimit() const { return _samplesRead >= _totalSamples; }
459 
460 	AudioStream *_parentStream;
461 	DisposeAfterUse::Flag _disposeAfterUse;
462 	uint32 _totalSamples, _samplesRead;
463 };
464 
makeLimitingAudioStream(AudioStream * parentStream,const Timestamp & length,DisposeAfterUse::Flag disposeAfterUse)465 AudioStream *makeLimitingAudioStream(AudioStream *parentStream, const Timestamp &length, DisposeAfterUse::Flag disposeAfterUse) {
466 	return new LimitingAudioStream(parentStream, length, disposeAfterUse);
467 }
468 
469 /**
470  * An AudioStream that plays nothing and immediately returns that
471  * the endOfStream() has been reached
472  */
473 class NullAudioStream : public AudioStream {
474 public:
isStereo() const475         bool isStereo() const { return false; }
476         int getRate() const;
readBuffer(int16 * data,const int numSamples)477         int readBuffer(int16 *data, const int numSamples) { return 0; }
endOfData() const478         bool endOfData() const { return true; }
479 };
480 
getRate() const481 int NullAudioStream::getRate() const {
482 	return g_system->getMixer()->getOutputRate();
483 }
484 
makeNullAudioStream()485 AudioStream *makeNullAudioStream() {
486 	return new NullAudioStream();
487 }
488 
489 } // End of namespace Audio
490