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