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 #ifndef AUDIO_AUDIOSTREAM_H 24 #define AUDIO_AUDIOSTREAM_H 25 26 #include "common/ptr.h" 27 #include "common/scummsys.h" 28 #include "common/str.h" 29 #include "common/types.h" 30 31 #include "audio/timestamp.h" 32 33 namespace Common { 34 class SeekableReadStream; 35 } 36 37 namespace Audio { 38 39 /** 40 * Generic audio input stream. Subclasses of this are used to feed arbitrary 41 * sampled audio data into ScummVM's audio mixer. 42 */ 43 class AudioStream { 44 public: ~AudioStream()45 virtual ~AudioStream() {} 46 47 /** 48 * Fill the given buffer with up to numSamples samples. Returns the actual 49 * number of samples read, or -1 if a critical error occurred (note: you 50 * *must* check if this value is less than what you requested, this can 51 * happen when the stream is fully used up). 52 * 53 * Data has to be in native endianess, 16 bit per sample, signed. For stereo 54 * stream, buffer will be filled with interleaved left and right channel 55 * samples, starting with a left sample. Furthermore, the samples in the 56 * left and right are summed up. So if you request 4 samples from a stereo 57 * stream, you will get a total of two left channel and two right channel 58 * samples. 59 */ 60 virtual int readBuffer(int16 *buffer, const int numSamples) = 0; 61 62 /** Is this a stereo stream? */ 63 virtual bool isStereo() const = 0; 64 65 /** Sample rate of the stream. */ 66 virtual int getRate() const = 0; 67 68 /** 69 * End of data reached? If this returns true, it means that at this 70 * time there is no data available in the stream. However there may be 71 * more data in the future. 72 * This is used by e.g. a rate converter to decide whether to keep on 73 * converting data or stop. 74 */ 75 virtual bool endOfData() const = 0; 76 77 /** 78 * End of stream reached? If this returns true, it means that all data 79 * in this stream is used up and no additional data will appear in it 80 * in the future. 81 * This is used by the mixer to decide whether a given stream shall be 82 * removed from the list of active streams (and thus be destroyed). 83 * By default this maps to endOfData() 84 */ endOfStream()85 virtual bool endOfStream() const { return endOfData(); } 86 }; 87 88 /** 89 * A rewindable audio stream. This allows for reseting the AudioStream 90 * to its initial state. Note that rewinding itself is not required to 91 * be working when the stream is being played by Mixer! 92 */ 93 class RewindableAudioStream : public virtual AudioStream { 94 public: 95 /** 96 * Rewinds the stream to its start. 97 * 98 * @return true on success, false otherwise. 99 */ 100 virtual bool rewind() = 0; 101 }; 102 103 /** 104 * A looping audio stream. This object does nothing besides using 105 * a RewindableAudioStream to play a stream in a loop. 106 */ 107 class LoopingAudioStream : public AudioStream { 108 public: 109 /** 110 * Creates a looping audio stream object. 111 * 112 * Note that on creation of the LoopingAudioStream object 113 * the underlying stream will be rewound. 114 * 115 * @see makeLoopingAudioStream 116 * 117 * @param stream Stream to loop 118 * @param loops How often to loop (0 = infinite) 119 * @param disposeAfterUse Destroy the stream after the LoopingAudioStream has finished playback. 120 */ 121 LoopingAudioStream(RewindableAudioStream *stream, uint loops, DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES); 122 123 int readBuffer(int16 *buffer, const int numSamples); 124 bool endOfData() const; 125 bool endOfStream() const; 126 isStereo()127 bool isStereo() const { return _parent->isStereo(); } getRate()128 int getRate() const { return _parent->getRate(); } 129 130 /** 131 * Returns number of loops the stream has played. 132 */ getCompleteIterations()133 uint getCompleteIterations() const { return _completeIterations; } 134 private: 135 Common::DisposablePtr<RewindableAudioStream> _parent; 136 137 uint _loops; 138 uint _completeIterations; 139 }; 140 141 /** 142 * Wrapper functionality to efficiently create a stream, which might be looped. 143 * 144 * Note that this function does not return a LoopingAudioStream, because it does 145 * not create one when the loop count is "1". This allows to keep the runtime 146 * overhead down, when the code does not require any functionality only offered 147 * by LoopingAudioStream. 148 * 149 * @param stream Stream to loop (will be automatically destroyed, when the looping is done) 150 * @param loops How often to loop (0 = infinite) 151 * @return A new AudioStream, which offers the desired functionality. 152 */ 153 AudioStream *makeLoopingAudioStream(RewindableAudioStream *stream, uint loops); 154 155 /** 156 * A seekable audio stream. Subclasses of this class implement an 157 * interface for seeking. The seeking itself is not required to be 158 * working while the stream is being played by Mixer! 159 */ 160 class SeekableAudioStream : public virtual RewindableAudioStream { 161 public: 162 /** 163 * Tries to load a file by trying all available formats. 164 * In case of an error, the file handle will be closed, but deleting 165 * it is still the responsibility of the caller. 166 * 167 * @param basename a filename without an extension 168 * @return an SeekableAudioStream ready to use in case of success; 169 * NULL in case of an error (e.g. invalid/nonexisting file) 170 */ 171 static SeekableAudioStream *openStreamFile(const Common::String &basename); 172 173 /** 174 * Seeks to a given offset in the stream. 175 * 176 * @param where offset in milliseconds 177 * @return true on success, false on failure. 178 */ seek(uint32 where)179 bool seek(uint32 where) { 180 return seek(Timestamp(where, getRate())); 181 } 182 183 /** 184 * Seeks to a given offset in the stream. 185 * 186 * @param where offset as timestamp 187 * @return true on success, false on failure. 188 */ 189 virtual bool seek(const Timestamp &where) = 0; 190 191 /** 192 * Returns the length of the stream. 193 * 194 * @return length as Timestamp. 195 */ 196 virtual Timestamp getLength() const = 0; 197 rewind()198 virtual bool rewind() { return seek(0); } 199 }; 200 201 /** 202 * Wrapper functionality to efficiently create a stream, which might be looped 203 * in a certain interval. 204 * 205 * This automatically starts the stream at time "start"! 206 * 207 * Note that this function does not return a LoopingAudioStream, because it does 208 * not create one when the loop count is "1". This allows to keep the runtime 209 * overhead down, when the code does not require any functionality only offered 210 * by LoopingAudioStream. 211 * 212 * @param stream Stream to loop (will be automatically destroyed, when the looping is done) 213 * @param start Starttime of the stream interval to be looped 214 * @param end End of the stream interval to be looped (a zero time, means till end) 215 * @param loops How often to loop (0 = infinite) 216 * @return A new AudioStream, which offers the desired functionality. 217 */ 218 AudioStream *makeLoopingAudioStream(SeekableAudioStream *stream, Timestamp start, Timestamp end, uint loops); 219 220 /** 221 * A looping audio stream, which features looping of a nested part of the 222 * stream. 223 * 224 * NOTE: 225 * Currently this implementation stops after the nested loop finished 226 * playback. 227 * 228 * IMPORTANT: 229 * This might be merged with SubSeekableAudioStream for playback purposes. 230 * (After extending it to accept a start time). 231 */ 232 class SubLoopingAudioStream : public AudioStream { 233 public: 234 /** 235 * Constructor for a SubLoopingAudioStream. 236 * 237 * Note that on creation of the SubLoopingAudioStream object 238 * the underlying stream will be rewound. 239 * 240 * @param stream Stream to loop 241 * @param loops How often the stream should be looped (0 means infinite) 242 * @param loopStart Start of the loop (this must be smaller than loopEnd) 243 * @param loopEnd End of the loop (thus must be greater than loopStart) 244 * @param disposeAfterUse Whether the stream should be disposed, when the 245 * SubLoopingAudioStream is destroyed. 246 */ 247 SubLoopingAudioStream(SeekableAudioStream *stream, uint loops, 248 const Timestamp loopStart, 249 const Timestamp loopEnd, 250 DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES); 251 252 int readBuffer(int16 *buffer, const int numSamples); 253 bool endOfData() const; 254 bool endOfStream() const; 255 isStereo()256 bool isStereo() const { return _parent->isStereo(); } getRate()257 int getRate() const { return _parent->getRate(); } 258 private: 259 Common::DisposablePtr<SeekableAudioStream> _parent; 260 261 uint _loops; 262 Timestamp _pos; 263 Timestamp _loopStart, _loopEnd; 264 265 bool _done; 266 }; 267 268 269 /** 270 * A SubSeekableAudioStream provides access to a SeekableAudioStream 271 * just in the range [start, end). 272 * The same caveats apply to SubSeekableAudioStream as do to SeekableAudioStream. 273 * 274 * Manipulating the parent stream directly /will/ mess up a substream. 275 */ 276 class SubSeekableAudioStream : public SeekableAudioStream { 277 public: 278 /** 279 * Creates a new SubSeekableAudioStream. 280 * 281 * @param parent parent stream object. 282 * @param start Start time. 283 * @param end End time. 284 * @param disposeAfterUse Whether the parent stream object should be destroyed on destruction of the SubSeekableAudioStream. 285 */ 286 SubSeekableAudioStream(SeekableAudioStream *parent, const Timestamp start, const Timestamp end, DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES); 287 288 int readBuffer(int16 *buffer, const int numSamples); 289 isStereo()290 bool isStereo() const { return _parent->isStereo(); } 291 getRate()292 int getRate() const { return _parent->getRate(); } 293 endOfData()294 bool endOfData() const { return (_pos >= _length) || _parent->endOfData(); } endOfStream()295 bool endOfStream() const { return (_pos >= _length) || _parent->endOfStream(); } 296 297 bool seek(const Timestamp &where); 298 getLength()299 Timestamp getLength() const { return _length; } 300 private: 301 Common::DisposablePtr<SeekableAudioStream> _parent; 302 303 const Timestamp _start; 304 const Timestamp _length; 305 Timestamp _pos; 306 }; 307 308 class QueuingAudioStream : public Audio::AudioStream { 309 public: 310 311 /** 312 * Queue an audio stream for playback. This stream plays all queued 313 * streams, in the order they were queued. If disposeAfterUse is set to 314 * DisposeAfterUse::YES, then the queued stream is deleted after all data 315 * contained in it has been played. 316 */ 317 virtual void queueAudioStream(Audio::AudioStream *audStream, 318 DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES) = 0; 319 320 /** 321 * Queue a block of raw audio data for playback. This stream plays all 322 * queued block, in the order they were queued. If disposeAfterUse is set 323 * to DisposeAfterUse::YES, then the queued block is released using free() 324 * after all data contained in it has been played. 325 * 326 * @note Make sure to allocate the data block with malloc(), not with new[]. 327 * 328 * @param data pointer to the audio data block 329 * @param size length of the audio data block 330 * @param disposeAfterUse if equal to DisposeAfterUse::YES, the block is released using free() after use. 331 * @param flags a bit-ORed combination of RawFlags describing the audio data format 332 */ 333 void queueBuffer(byte *data, uint32 size, DisposeAfterUse::Flag disposeAfterUse, byte flags); 334 335 /** 336 * Mark this stream as finished. That is, signal that no further data 337 * will be queued to it. Only after this has been done can this 338 * stream ever 'end'. 339 */ 340 virtual void finish() = 0; 341 342 /** 343 * Return the number of streams still queued for playback (including 344 * the currently playing stream). 345 */ 346 virtual uint32 numQueuedStreams() const = 0; 347 }; 348 349 /** 350 * Factory function for an QueuingAudioStream. 351 */ 352 QueuingAudioStream *makeQueuingAudioStream(int rate, bool stereo); 353 354 /** 355 * Converts a point in time to a precise sample offset 356 * with the given parameters. 357 * 358 * @param where Point in time. 359 * @param rate Rate of the stream. 360 * @param isStereo Is the stream a stereo stream? 361 */ 362 Timestamp convertTimeToStreamPos(const Timestamp &where, int rate, bool isStereo); 363 364 /** 365 * Factory function for an AudioStream wrapper that cuts off the amount of samples read after a 366 * given time length is reached. 367 * 368 * @param parentStream The stream to limit 369 * @param length The time length to limit the stream to 370 * @param disposeAfterUse Whether the parent stream object should be destroyed on destruction of the returned stream 371 */ 372 AudioStream *makeLimitingAudioStream(AudioStream *parentStream, const Timestamp &length, DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES); 373 374 /** 375 * An AudioStream designed to work in terms of packets. 376 * 377 * It is similar in concept to QueuingAudioStream, but does not 378 * necessarily rely on the data from each queued AudioStream 379 * being separate. 380 */ 381 class PacketizedAudioStream : public virtual AudioStream { 382 public: ~PacketizedAudioStream()383 virtual ~PacketizedAudioStream() {} 384 385 /** 386 * Queue the next packet to be decoded. 387 */ 388 virtual void queuePacket(Common::SeekableReadStream *data) = 0; 389 390 /** 391 * Mark this stream as finished. That is, signal that no further data 392 * will be queued to it. Only after this has been done can this 393 * stream ever 'end'. 394 */ 395 virtual void finish() = 0; 396 }; 397 398 /** 399 * A PacketizedAudioStream that works closer to a QueuingAudioStream. 400 * It queues individual packets as whole AudioStream to an internal 401 * QueuingAudioStream. This is used for writing quick wrappers against 402 * e.g. RawStream, which can be made into PacketizedAudioStreams with 403 * little effort. 404 */ 405 class StatelessPacketizedAudioStream : public PacketizedAudioStream { 406 public: StatelessPacketizedAudioStream(uint rate,uint channels)407 StatelessPacketizedAudioStream(uint rate, uint channels) : 408 _rate(rate), _channels(channels), _stream(makeQueuingAudioStream(rate, channels == 2)) {} ~StatelessPacketizedAudioStream()409 virtual ~StatelessPacketizedAudioStream() {} 410 411 // AudioStream API isStereo()412 bool isStereo() const { return _channels == 2; } getRate()413 int getRate() const { return _rate; } readBuffer(int16 * data,const int numSamples)414 int readBuffer(int16 *data, const int numSamples) { return _stream->readBuffer(data, numSamples); } endOfData()415 bool endOfData() const { return _stream->endOfData(); } endOfStream()416 bool endOfStream() const { return _stream->endOfStream(); } 417 418 // PacketizedAudioStream API queuePacket(Common::SeekableReadStream * data)419 void queuePacket(Common::SeekableReadStream *data) { _stream->queueAudioStream(makeStream(data)); } finish()420 void finish() { _stream->finish(); } 421 getChannels()422 uint getChannels() const { return _channels; } 423 424 protected: 425 /** 426 * Make the AudioStream for a given packet 427 */ 428 virtual AudioStream *makeStream(Common::SeekableReadStream *data) = 0; 429 430 private: 431 uint _rate; 432 uint _channels; 433 Common::ScopedPtr<QueuingAudioStream> _stream; 434 }; 435 436 /** 437 * Create an AudioStream that plays nothing and immediately returns that 438 * endOfStream() has been reached. 439 */ 440 AudioStream *makeNullAudioStream(); 441 442 } // End of namespace Audio 443 444 #endif 445