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/endian.h"
24 #include "common/memstream.h"
25 #include "common/textconsole.h"
26 #include "common/util.h"
27 
28 #include "audio/audiostream.h"
29 #include "audio/decoders/raw.h"
30 
31 namespace Audio {
32 
33 #pragma mark -
34 #pragma mark --- RawStream ---
35 #pragma mark -
36 
37 /**
38  * This is a stream, which allows for playing raw PCM data from a stream.
39  */
40 template<int bytesPerSample, bool isUnsigned, bool isLE>
41 class RawStream : public SeekableAudioStream {
42 public:
RawStream(int rate,bool stereo,DisposeAfterUse::Flag disposeStream,Common::SeekableReadStream * stream)43 	RawStream(int rate, bool stereo, DisposeAfterUse::Flag disposeStream, Common::SeekableReadStream *stream)
44 		: _rate(rate), _isStereo(stereo), _playtime(0, rate), _stream(stream, disposeStream), _endOfData(false), _buffer(0) {
45 		// Setup our buffer for readBuffer
46 		_buffer = new byte[kSampleBufferLength * bytesPerSample];
47 		assert(_buffer);
48 
49 		// Calculate the total playtime of the stream
50 		_playtime = Timestamp(0, _stream->size() / (_isStereo ? 2 : 1) / bytesPerSample, rate);
51 	}
52 
~RawStream()53 	~RawStream() {
54 		delete[] _buffer;
55 	}
56 
57 	int readBuffer(int16 *buffer, const int numSamples);
58 
isStereo() const59 	bool isStereo() const  { return _isStereo; }
endOfData() const60 	bool endOfData() const { return _endOfData; }
61 
getRate() const62 	int getRate() const         { return _rate; }
getLength() const63 	Timestamp getLength() const { return _playtime; }
64 
65 	bool seek(const Timestamp &where);
66 private:
67 	const int _rate;                                           ///< Sample rate of stream
68 	const bool _isStereo;                                      ///< Whether this is an stereo stream
69 	Timestamp _playtime;                                       ///< Calculated total play time
70 	Common::DisposablePtr<Common::SeekableReadStream> _stream; ///< Stream to read data from
71 	bool _endOfData;                                           ///< Whether the stream end has been reached
72 
73 	byte *_buffer;                                             ///< Buffer used in readBuffer
74 	enum {
75 		/**
76 		 * How many samples we can buffer at once.
77 		 *
78 		 * TODO: Check whether this size suffices
79 		 * for systems with slow disk I/O.
80 		 */
81 		kSampleBufferLength = 2048
82 	};
83 
84 	/**
85 	 * Fill the temporary sample buffer used in readBuffer.
86 	 *
87 	 * @param maxSamples Maximum samples to read.
88 	 * @return actual count of samples read.
89 	 */
90 	int fillBuffer(int maxSamples);
91 };
92 
93 template<int bytesPerSample, bool isUnsigned, bool isLE>
readBuffer(int16 * buffer,const int numSamples)94 int RawStream<bytesPerSample, isUnsigned, isLE>::readBuffer(int16 *buffer, const int numSamples) {
95 	int samplesLeft = numSamples;
96 
97 	while (samplesLeft > 0) {
98 		// Try to read up to "samplesLeft" samples.
99 		int len = fillBuffer(samplesLeft);
100 
101 		// In case we were not able to read any samples
102 		// we will stop reading here.
103 		if (!len)
104 			break;
105 
106 		// Adjust the samples left to read.
107 		samplesLeft -= len;
108 
109 		// Copy the data to the caller's buffer.
110 		const byte *src = _buffer;
111 		while (len-- > 0) {
112 			if (bytesPerSample == 1)
113 				*buffer++ = (*src << 8) ^ (isUnsigned ? 0x8000 : 0);
114 			else if (bytesPerSample == 2)
115 				*buffer++ = ((isLE ? READ_LE_UINT16(src) : READ_BE_UINT16(src)) ^ (isUnsigned ? 0x8000 : 0));
116 			else // if (bytesPerSample == 3)
117 				*buffer++ = (((int16)((isLE ? READ_LE_UINT24(src) : READ_BE_UINT24(src)) >> 8)) ^ (isUnsigned ? 0x8000 : 0));
118 
119 			src += bytesPerSample;
120 		}
121 	}
122 
123 	return numSamples - samplesLeft;
124 }
125 
126 template<int bytesPerSample, bool isUnsigned, bool isLE>
fillBuffer(int maxSamples)127 int RawStream<bytesPerSample, isUnsigned, isLE>::fillBuffer(int maxSamples) {
128 	int bufferedSamples = 0;
129 	byte *dst = _buffer;
130 
131 	// We can only read up to "kSampleBufferLength" samples
132 	// so we take this into consideration, when trying to
133 	// read up to maxSamples.
134 	maxSamples = MIN<int>(kSampleBufferLength, maxSamples);
135 
136 	// We will only read up to maxSamples
137 	while (maxSamples > 0 && !endOfData()) {
138 		// Try to read all the sample data and update the
139 		// destination pointer.
140 		const int bytesRead = _stream->read(dst, maxSamples * bytesPerSample);
141 		dst += bytesRead;
142 
143 		// Calculate how many samples we actually read.
144 		const int samplesRead = bytesRead / bytesPerSample;
145 
146 		// Update all status variables
147 		bufferedSamples += samplesRead;
148 		maxSamples -= samplesRead;
149 
150 		// We stop stream playback, when we reached the end of the data stream.
151 		// We also stop playback when an error occures.
152 		if (_stream->pos() == _stream->size() || _stream->err() || _stream->eos())
153 			_endOfData = true;
154 	}
155 
156 	return bufferedSamples;
157 }
158 
159 template<int bytesPerSample, bool isUnsigned, bool isLE>
seek(const Timestamp & where)160 bool RawStream<bytesPerSample, isUnsigned, isLE>::seek(const Timestamp &where) {
161 	_endOfData = true;
162 
163 	if (where > _playtime)
164 		return false;
165 
166 	const uint32 seekSample = convertTimeToStreamPos(where, getRate(), isStereo()).totalNumberOfFrames();
167 	_stream->seek(seekSample * bytesPerSample, SEEK_SET);
168 
169 	// In case of an error we will not continue stream playback.
170 	if (!_stream->err() && !_stream->eos() && _stream->pos() != _stream->size())
171 		_endOfData = false;
172 
173 	return true;
174 }
175 
176 #pragma mark -
177 #pragma mark --- Raw stream factories ---
178 #pragma mark -
179 
180 /* In the following, we use preprocessor / macro tricks to simplify the code
181  * which instantiates the input streams. We used to use template functions for
182  * this, but MSVC6 / EVC 3-4 (used for WinCE builds) are extremely buggy when it
183  * comes to this feature of C++... so as a compromise we use macros to cut down
184  * on the (source) code duplication a bit.
185  * So while normally macro tricks are said to make maintenance harder, in this
186  * particular case it should actually help it :-)
187  */
188 
189 #define MAKE_RAW_STREAM(UNSIGNED) \
190 		if (bytesPerSample == 3) { \
191 			if (isLE) \
192 				return new RawStream<3, UNSIGNED, true>(rate, isStereo, disposeAfterUse, stream); \
193 			else  \
194 				return new RawStream<3, UNSIGNED, false>(rate, isStereo, disposeAfterUse, stream); \
195 		} else if (bytesPerSample == 2) { \
196 			if (isLE) \
197 				return new RawStream<2, UNSIGNED, true>(rate, isStereo, disposeAfterUse, stream); \
198 			else  \
199 				return new RawStream<2, UNSIGNED, false>(rate, isStereo, disposeAfterUse, stream); \
200 		} else \
201 			return new RawStream<1, UNSIGNED, false>(rate, isStereo, disposeAfterUse, stream)
202 
makeRawStream(Common::SeekableReadStream * stream,int rate,byte flags,DisposeAfterUse::Flag disposeAfterUse)203 SeekableAudioStream *makeRawStream(Common::SeekableReadStream *stream,
204 								   int rate, byte flags,
205 								   DisposeAfterUse::Flag disposeAfterUse) {
206 	const bool isStereo      = (flags & Audio::FLAG_STEREO) != 0;
207 	const int bytesPerSample = (flags & Audio::FLAG_24BITS ? 3 : (flags & Audio::FLAG_16BITS ? 2 : 1));
208 	const bool isUnsigned    = (flags & Audio::FLAG_UNSIGNED) != 0;
209 	const bool isLE          = (flags & Audio::FLAG_LITTLE_ENDIAN) != 0;
210 
211 	assert(stream->size() % (bytesPerSample * (isStereo ? 2 : 1)) == 0);
212 
213 	if (isUnsigned) {
214 		MAKE_RAW_STREAM(true);
215 	} else {
216 		MAKE_RAW_STREAM(false);
217 	}
218 }
219 
makeRawStream(const byte * buffer,uint32 size,int rate,byte flags,DisposeAfterUse::Flag disposeAfterUse)220 SeekableAudioStream *makeRawStream(const byte *buffer, uint32 size,
221 								   int rate, byte flags,
222 								   DisposeAfterUse::Flag disposeAfterUse) {
223 	return makeRawStream(new Common::MemoryReadStream(buffer, size, disposeAfterUse), rate, flags, DisposeAfterUse::YES);
224 }
225 
226 class PacketizedRawStream : public StatelessPacketizedAudioStream {
227 public:
PacketizedRawStream(int rate,byte flags)228 	PacketizedRawStream(int rate, byte flags) :
229 		StatelessPacketizedAudioStream(rate, ((flags & FLAG_STEREO) != 0) ? 2 : 1), _flags(flags) {}
230 
231 protected:
232 	AudioStream *makeStream(Common::SeekableReadStream *data);
233 
234 private:
235 	byte _flags;
236 };
237 
makeStream(Common::SeekableReadStream * data)238 AudioStream *PacketizedRawStream::makeStream(Common::SeekableReadStream *data) {
239 	return makeRawStream(data, getRate(), _flags);
240 }
241 
makePacketizedRawStream(int rate,byte flags)242 PacketizedAudioStream *makePacketizedRawStream(int rate, byte flags) {
243 	return new PacketizedRawStream(rate, flags);
244 }
245 
246 } // End of namespace Audio
247