xoreos  0.0.5
pcm.cpp
Go to the documentation of this file.
1 /* xoreos - A reimplementation of BioWare's Aurora engine
2  *
3  * xoreos is the legal property of its developers, whose names
4  * can be found in the AUTHORS file distributed with this source
5  * distribution.
6  *
7  * xoreos 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 3
10  * of the License, or (at your option) any later version.
11  *
12  * xoreos 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 xoreos. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
25 /* Based on ScummVM (<http://scummvm.org>) code, which is released
26  * under the terms of version 2 or later of the GNU General Public
27  * License.
28  *
29  * The original copyright note in ScummVM reads as follows:
30  *
31  * ScummVM is the legal property of its developers, whose names
32  * are too numerous to list here. Please refer to the COPYRIGHT
33  * file distributed with this source distribution.
34  *
35  * This program is free software; you can redistribute it and/or
36  * modify it under the terms of the GNU General Public License
37  * as published by the Free Software Foundation; either version 2
38  * of the License, or (at your option) any later version.
39  *
40  * This program is distributed in the hope that it will be useful,
41  * but WITHOUT ANY WARRANTY; without even the implied warranty of
42  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
43  * GNU General Public License for more details.
44  *
45  * You should have received a copy of the GNU General Public License
46  * along with this program; if not, write to the Free Software
47  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
48  */
49 
51 #include "src/common/readstream.h"
52 
53 #include "src/sound/audiostream.h"
54 #include "src/sound/decoders/pcm.h"
55 
56 namespace Sound {
57 
58 // This used to be an inline template function, but
59 // buggy template function handling in MSVC6 forced
60 // us to go with the macro approach. So far this is
61 // the only template function that MSVC6 seemed to
62 // compile incorrectly. Knock on wood.
63 #define READ_ENDIAN_SAMPLE(is16Bit, isUnsigned, ptr, isLE) \
64  ((is16Bit ? (isLE ? _stream->readUint16LE() : _stream->readUint16BE()) : (_stream->readByte() << 8)) ^ (isUnsigned ? 0x8000 : 0))
65 
66 
71 template<bool is16Bit, bool isUnsigned, bool isLE>
73 
74 protected:
75  const int _rate;
76  const int _channels;
77 
79 
81 
82 public:
83  PCMStream(int rate, int channels, bool disposeStream, Common::SeekableReadStream *stream)
84  : _rate(rate), _channels(channels), _stream(stream, disposeStream) {
85 
86  _length = stream->size() / _channels / (is16Bit ? 2 : 1);
87  }
88 
89  virtual ~PCMStream() {
90  }
91 
92  size_t readBuffer(int16 *buffer, const size_t numSamples);
93 
94  int getChannels() const { return _channels; }
95  bool endOfData() const { return _stream->pos() >= _stream->size(); }
96  int getRate() const { return _rate; }
97  uint64 getLength() const { return _length; }
98 
99  bool rewind();
100 };
101 
102 template<bool is16Bit, bool isUnsigned, bool isLE>
103 size_t PCMStream<is16Bit, isUnsigned, isLE>::readBuffer(int16 *buffer, const size_t numSamples) {
104  size_t samples = numSamples;
105 
106  while (samples > 0 && !endOfData()) {
107  *buffer++ = READ_ENDIAN_SAMPLE(is16Bit, isUnsigned, _ptr, isLE);
108  samples--;
109  }
110 
111  return numSamples - samples;
112 }
113 
114 template<bool is16Bit, bool isUnsigned, bool isLE>
116  // Easy peasy, lemon squeezee
117  _stream->seek(0);
118  return true;
119 }
120 
121 /* In the following, we use preprocessor / macro tricks to simplify the code
122  * which instantiates the input streams. We used to use template functions for
123  * this, but MSVC6 / EVC 3-4 (used for WinCE builds) are extremely buggy when it
124  * comes to this feature of C++... so as a compromise we use macros to cut down
125  * on the (source) code duplication a bit.
126  * So while normally macro tricks are said to make maintenance harder, in this
127  * particular case it should actually help it :-)
128  */
129 
130 #define MAKE_RAW_STREAM(UNSIGNED) \
131  if (is16Bit) { \
132  if (isLE) \
133  return new PCMStream<true, UNSIGNED, true>(rate, channels, disposeAfterUse, stream); \
134  else \
135  return new PCMStream<true, UNSIGNED, false>(rate, channels, disposeAfterUse, stream); \
136  } else \
137  return new PCMStream<false, UNSIGNED, false>(rate, channels, disposeAfterUse, stream)
138 
139 
141  int rate, byte flags, int channels,
142  bool disposeAfterUse) {
143 
144  const bool is16Bit = (flags & FLAG_16BITS) != 0;
145  const bool isUnsigned = (flags & FLAG_UNSIGNED) != 0;
146  const bool isLE = (flags & FLAG_LITTLE_ENDIAN) != 0;
147 
148  if (isUnsigned) {
149  MAKE_RAW_STREAM(true);
150  } else {
151  MAKE_RAW_STREAM(false);
152  }
153 }
154 
156 public:
157  PacketizedPCMStream(int rate, byte flags, int channels) :
158  StatelessPacketizedAudioStream(rate, channels), _flags(flags) {}
159 
160 protected:
162 
163 private:
165 };
166 
168  return makePCMStream(data, getRate(), _flags, getChannels());
169 }
170 
171 PacketizedAudioStream *makePacketizedPCMStream(int rate, byte flags, int channels) {
172  return new PacketizedPCMStream(rate, flags, channels);
173 }
174 
175 } // End of namespace Sound
int getRate() const
Sample rate of the stream.
Definition: audiostream.h:308
PacketizedAudioStream * makePacketizedPCMStream(int rate, byte flags, int channels)
Creates a PacketizedAudioStream that will automatically queue packets as individual AudioStreams like...
Definition: pcm.cpp:171
virtual ~PCMStream()
Definition: pcm.cpp:89
uint64_t uint64
Definition: types.h:206
A PacketizedAudioStream that works closer to a QueuingAudioStream.
Definition: audiostream.h:300
unsigned samples (default: signed)
Definition: pcm.h:69
RewindableAudioStream * makePCMStream(Common::SeekableReadStream *stream, int rate, byte flags, int channels, bool disposeAfterUse)
Creates an audio stream, which plays from the given stream.
Definition: pcm.cpp:140
Decoding PCM (Pulse Code Modulation).
const int _rate
Sample rate of stream.
Definition: pcm.cpp:75
int16_t int16
Definition: types.h:201
bool rewind()
Rewinds the stream to its start.
Definition: pcm.cpp:115
const int _channels
Amount of channels.
Definition: pcm.cpp:76
int getChannels() const
Return the number channels in this stream.
Definition: pcm.cpp:94
Definition: game.h:37
A rewindable audio stream.
Definition: audiostream.h:125
AudioStream * makeStream(Common::SeekableReadStream *data)
Make the AudioStream for a given packet.
Definition: pcm.cpp:167
int getChannels() const
Return the number channels in this stream.
Definition: audiostream.h:307
#define MAKE_RAW_STREAM(UNSIGNED)
Definition: pcm.cpp:130
bool endOfData() const
End of data reached? If this returns true, it means that at this time there is no data available in t...
Definition: pcm.cpp:95
Common::DisposablePtr< Common::SeekableReadStream > _stream
Stream to read data from.
Definition: pcm.cpp:80
An AudioStream designed to work in terms of packets.
Definition: audiostream.h:271
This is a stream, which allows for playing raw PCM data from a stream.
Definition: pcm.cpp:72
int getRate() const
Sample rate of the stream.
Definition: pcm.cpp:96
PCMStream(int rate, int channels, bool disposeStream, Common::SeekableReadStream *stream)
Definition: pcm.cpp:83
virtual size_t size() const =0
Obtains the total size of the stream, measured in bytes.
Basic reading stream interfaces.
uint64 _length
Definition: pcm.cpp:78
sound is 16 bits wide (default: 8bit)
Definition: pcm.h:72
Generic audio input stream.
Definition: audiostream.h:70
PacketizedPCMStream(int rate, byte flags, int channels)
Definition: pcm.cpp:157
A smart pointer with a deletion flag.
uint64 getLength() const
Estimate the total number of samples per channel in this stream.
Definition: pcm.cpp:97
samples are little endian (default: big endian)
Definition: pcm.h:75
#define READ_ENDIAN_SAMPLE(is16Bit, isUnsigned, ptr, isLE)
Definition: pcm.cpp:63
size_t readBuffer(int16 *buffer, const size_t numSamples)
Fill the given buffer with up to numSamples samples.
Definition: pcm.cpp:103
Interface for a seekable & readable data stream.
Definition: readstream.h:265
Streaming audio.
uint8 byte
Definition: types.h:209