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 namespace Audio {
27 
28 /**
29  * Generic audio input stream. Subclasses of this are used to feed arbitrary
30  * sampled audio data into ScummVM's audio mixer.
31  */
32 class AudioStream {
33 public:
34 	int16 mVolume;
35 
~AudioStream()36 	virtual ~AudioStream() {}
37 
38 	/**
39 	 * Fill the given buffer with up to numSamples samples. Returns the actual
40 	 * number of samples read, or -1 if a critical error occurred (note: you
41 	 * *must* check if this value is less than what you requested, this can
42 	 * happen when the stream is fully used up).
43 	 *
44 	 * Data has to be in native endianess, 16 bit per sample, signed. For stereo
45 	 * stream, buffer will be filled with interleaved left and right channel
46 	 * samples, starting with a left sample. Furthermore, the samples in the
47 	 * left and right are summed up. So if you request 4 samples from a stereo
48 	 * stream, you will get a total of two left channel and two right channel
49 	 * samples.
50 	 */
51 	virtual int readBuffer(int16 *buffer, const int numSamples) = 0;
52 
53 	/** Is this a stereo stream? */
54 	virtual bool isStereo() const = 0;
55 
56 	/** Sample rate of the stream. */
57 	virtual int getRate() const = 0;
58 
59 	/**
60 	 * End of data reached? If this returns true, it means that at this
61 	 * time there is no data available in the stream. However there may be
62 	 * more data in the future.
63 	 * This is used by e.g. a rate converter to decide whether to keep on
64 	 * converting data or stop.
65 	 */
66 	virtual bool endOfData() const = 0;
67 
68 	/**
69 	 * End of stream reached? If this returns true, it means that all data
70 	 * in this stream is used up and no additional data will appear in it
71 	 * in the future.
72 	 * This is used by the mixer to decide whether a given stream shall be
73 	 * removed from the list of active streams (and thus be destroyed).
74 	 * By default this maps to endOfData()
75 	 */
endOfStream() const76 	virtual bool endOfStream() const { return endOfData(); }
77 };
78 
79 /**
80  * A rewindable audio stream. This allows for reseting the AudioStream
81  * to its initial state. Note that rewinding itself is not required to
82  * be working when the stream is being played by Mixer!
83  */
84 class RewindableAudioStream : public virtual AudioStream {
85 public:
86 	/**
87 	 * Rewinds the stream to its start.
88 	 *
89 	 * @return true on success, false otherwise.
90 	 */
91 	virtual bool rewind() = 0;
92 };
93 
94 /**
95  * A looping audio stream. This object does nothing besides using
96  * a RewindableAudioStream to play a stream in a loop.
97  */
98 class LoopingAudioStream : public AudioStream {
99 public:
100 	/**
101 	 * Creates a looping audio stream object.
102 	 *
103 	 * Note that on creation of the LoopingAudioStream object
104 	 * the underlying stream will be rewound.
105 	 *
106 	 * @see makeLoopingAudioStream
107 	 *
108 	 * @param stream Stream to loop
109 	 * @param loops How often to loop (0 = infinite)
110 	 * @param disposeAfterUse Destroy the stream after the LoopingAudioStream has finished playback.
111 	 */
112 	LoopingAudioStream(RewindableAudioStream *stream, size_t loops);
113 
114 	int readBuffer(int16 *buffer, const int numSamples);
115 	bool endOfData() const;
116 	bool endOfStream() const;
117 
isStereo() const118 	bool isStereo() const { return _parent->isStereo(); }
getRate() const119 	int getRate() const { return _parent->getRate(); }
120 
121 	/**
122 	 * Returns number of loops the stream has played.
123 	 */
getCompleteIterations() const124 	size_t getCompleteIterations() const { return _completeIterations; }
125 private:
126 	RewindableAudioStream* _parent;
127 
128 	size_t _loops;
129 	size_t _completeIterations;
130 };
131 
132 /**
133  * Wrapper functionality to efficiently create a stream, which might be looped.
134  *
135  * Note that this function does not return a LoopingAudioStream, because it does
136  * not create one when the loop count is "1". This allows to keep the runtime
137  * overhead down, when the code does not require any functionality only offered
138  * by LoopingAudioStream.
139  *
140  * @param stream  Stream to loop (will be automatically destroyed, when the looping is done)
141  * @param loops   How often to loop (0 = infinite)
142  * @return A new AudioStream, which offers the desired functionality.
143  */
144 AudioStream *makeLoopingAudioStream(RewindableAudioStream *stream, size_t loops);
145 
146 } // End of namespace Audio
147 
148 #endif
149