xoreos  0.0.5
wave.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 #include "src/common/error.h"
26 #include "src/common/util.h"
27 #include "src/common/strutil.h"
28 #include "src/common/readstream.h"
29 
30 #include "src/sound/audiostream.h"
33 #include "src/sound/decoders/pcm.h"
35 
36 namespace Sound {
37 
39  uint32 riffTag = stream->readUint32BE();
40  if (riffTag != MKTAG('R', 'I', 'F', 'F'))
41  throw Common::Exception("makeWAVStream(): No 'RIFF' header (%s)", Common::debugTag(riffTag).c_str());
42 
43  /* uint32 fileSize = */ stream->readUint32LE();
44 
45  uint32 waveTag = stream->readUint32BE();
46  if (waveTag != MKTAG('W', 'A', 'V', 'E'))
47  throw Common::Exception("makeWAVStream(): No 'WAVE' RIFF type (%s)", Common::debugTag(waveTag).c_str());
48 
49  uint32 fmtTag = stream->readUint32BE();
50  if (fmtTag != MKTAG('f', 'm', 't', ' '))
51  throw Common::Exception("makeWAVStream(): No 'fmt ' chunk (%s)", Common::debugTag(fmtTag).c_str());
52 
53  uint32 fmtLength = stream->readUint32LE();
54  if (fmtLength < 16) // A valid fmt chunk always contains at least 16 bytes
55  throw Common::Exception("makeWAVStream(): Invalid wave format size %d", fmtLength);
56 
57  // Now parse the WAVEFORMAT(EX) structure
58  uint16 compression = stream->readUint16LE();
59  uint16 channels = stream->readUint16LE();
60  uint32 sampleRate = stream->readUint32LE();
61  /* uint32 avgBytesPerSecond = */ stream->readUint32LE();
62  uint16 blockAlign = stream->readUint16LE();
63  uint16 bitsPerSample = stream->readUint16LE();
64 
65  // Skip over the rest of the fmt chunk.
66  stream->skip(fmtLength - 16);
67 
68  // Skip over all chunks until we hit the data
69  for (;;) {
70  if (stream->readUint32BE() == MKTAG('d', 'a', 't', 'a'))
71  break;
72 
73  if (stream->eos())
74  throw Common::Exception("makeWAVStream(): Unexpected eos");
75 
76  stream->skip(stream->readUint32LE());
77  }
78 
79  uint32 size = stream->readUint32LE();
80  Common::SeekableSubReadStream *subStream = new Common::SeekableSubReadStream(stream, stream->pos(), stream->pos() + size, disposeAfterUse);
81 
82  // Return the decoder we need
83  switch (compression) {
84  case kWavePCM: {
85  byte flags = 0;
86 
87  // 8 bit data is unsigned, 16 bit data signed
88  if (bitsPerSample == 8)
89  flags |= FLAG_UNSIGNED;
90  else if (bitsPerSample == 16)
91  flags |= (FLAG_16BITS | FLAG_LITTLE_ENDIAN);
92  else
93  throw Common::Exception("makeWAVStream(): Unsupported PCM bits per sample %d", bitsPerSample);
94 
95  return makePCMStream(subStream, sampleRate, flags, channels, true);
96  }
97  case kWaveMSIMAADPCM:
98  case kWaveMSIMAADPCM2:
99  return makeADPCMStream(subStream, true, size, kADPCMMSIma, sampleRate, channels, blockAlign);
100  case kWaveMSADPCM:
101  return makeADPCMStream(subStream, true, size, kADPCMMS, sampleRate, channels, blockAlign);
102  }
103 
104  throw Common::Exception("makeWAVStream(): Unhandled wave type 0x%04x", compression);
105  return 0;
106 }
107 
108 } // End of namespace Sound
#define MKTAG(a0, a1, a2, a3)
A wrapper macro used around four character constants, like &#39;DATA&#39;, to ensure portability.
Definition: endianness.h:140
uint16 readUint16LE()
Read an unsigned 16-bit word stored in little endian (LSB first) order from the stream and return it...
Definition: readstream.h:122
uint32 readUint32LE()
Read an unsigned 32-bit word stored in little endian (LSB first) order from the stream and return it...
Definition: readstream.h:133
Decoding RIFF WAVE (Resource Interchange File Format Waveform).
virtual bool eos() const =0
Returns true if a read failed because the stream has been reached.
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).
Compression types in Microsoft&#39;s WAVEFORMAT(EX).
Utility templates and functions for working with strings and streams.
Exception that provides a stack of explanations.
Definition: error.h:36
Definition: game.h:37
Basic exceptions to throw.
Decoding ADPCM (Adaptive Differential Pulse Code Modulation).
A rewindable audio stream.
Definition: audiostream.h:125
uint16_t uint16
Definition: types.h:202
Utility templates and functions.
RewindableAudioStream * makeWAVStream(Common::SeekableReadStream *stream, bool disposeAfterUse)
Try to load a WAVE from the given seekable stream and create an AudioStream from that data...
Definition: wave.cpp:38
RewindableAudioStream * makeADPCMStream(Common::SeekableReadStream *stream, bool disposeAfterUse, uint32 size, ADPCMTypes type, int rate, int channels, uint32 blockAlign)
Takes an input stream containing ADPCM compressed sound data and creates an RewindableAudioStream fro...
Definition: adpcm.cpp:640
virtual size_t skip(ptrdiff_t offset)
Skip the specified number of bytes, adding that offset to the current position in the stream...
Definition: readstream.h:317
StackException Exception
Definition: error.h:59
Basic reading stream interfaces.
virtual size_t pos() const =0
Obtains the current value of the stream position indicator of the stream.
uint32 readUint32BE()
Read an unsigned 32-bit word stored in big endian (MSB first) order from the stream and return it...
Definition: readstream.h:166
sound is 16 bits wide (default: 8bit)
Definition: pcm.h:72
uint32_t uint32
Definition: types.h:204
UString debugTag(uint32 tag, bool trim)
Create an elaborate string from an integer tag, for debugging purposes.
Definition: strutil.cpp:117
samples are little endian (default: big endian)
Definition: pcm.h:75
SeekableSubReadStream provides access to a SeekableReadStream restricted to the range [begin...
Definition: readstream.h:359
Interface for a seekable & readable data stream.
Definition: readstream.h:265
Streaming audio.
uint8 byte
Definition: types.h:209