cAudio 2.3.0
3d Audio Engine
Loading...
Searching...
No Matches
cWavDecoder.cpp
1// Copyright (c) 2008-2011 Raynaldo (Wildicv) Rivera, Joshua (Dark_Kilauea) Jones, Murat (wolfmanfx) Sari
2// This file is part of the "cAudio Engine"
3// For conditions of distribution and use, see copyright notice in cAudio.h
4
5#include "cWavDecoder.h"
6#include <string.h>
7
8#if CAUDIO_COMPILE_WITH_WAV_DECODER == 1
9
10namespace cAudio
11{
12 cWavDecoder::cWavDecoder(IDataSource* stream) : IAudioDecoder(stream), Valid(false)
13 {
14 const char* RIFFTAG = "RIFF";
15 const char* WAVETAG = "WAVE";
16 const char* FORMATTAG = "fmt ";
17 const char* DATATAG = "data";
18
19 char ident[4];
20 int tempint32 = 0;
21 short tempint16 = 0;
22
23 unsigned int startOffset = 0;
24
25 //Read the first 4 bytes
26 Stream->seek(0, false);
27 Stream->read(ident, 4);
28 //Check to see if it is a valid RIFF file
29 if(strncmp(ident, RIFFTAG, 4) == 0)
30 {
31 Stream->read(&tempint32, 4);
32 //Check to see if the file is big enough to be valid (not completely accurate)
33 if(tempint32 >= 44)
34 {
35 Stream->read(ident, 4);
36 //Check that it is a wave file
37 if(strncmp(ident, WAVETAG, 4) == 0)
38 {
39 //Save our position
40 startOffset = Stream->getCurrentPos();
41
42 //Scan for the first fmt chuck (not necessarily right after)
43 do
44 {
45 Stream->read(ident, 4);
46 }
47 while((strncmp(ident, FORMATTAG, 4) != 0) && (Stream->getCurrentPos() < Stream->getSize()));
48
49 //Did we find it?
50 if(Stream->getCurrentPos() < (Stream->getSize() - 16))
51 {
52 //Yes, read it in
53 Stream->read(&tempint32, 4);
54 if(tempint32 >= 16)
55 {
56 //Check that it is in PCM format, we don't support compressed wavs
57 Stream->read(&tempint16, 2);
58 if(tempint16 == 1)
59 {
60 Stream->read(&tempint16, 2);
61 Channels = tempint16;
62 //We only support mono or stereo wavs
63 if(Channels == 1 || Channels == 2)
64 {
65 Stream->read(&tempint32, 4);
66 SampleRate = tempint32;
67 Stream->read(&tempint32, 4);
68 ByteRate = tempint32;
69 Stream->read(&tempint16, 2);
70 BlockAlign = tempint16;
71 Stream->read(&tempint16, 2);
72 BitsPerSample = tempint16;
73
74 //We only support 8 bit or 16 bit wavs
75 if(BitsPerSample == 8 || BitsPerSample == 16)
76 {
77 //Reset our pointer to start scanning for the data block
78 Stream->seek(startOffset, false);
79 //Scan for the first data chuck (not necessarily right after)
80 do
81 {
82 Stream->read(ident, 4);
83 }
84 while((strncmp(ident, DATATAG, 4) != 0) && (Stream->getCurrentPos() < Stream->getSize()));
85
86 //Did we find it?
87 if(Stream->getCurrentPos() < Stream->getSize())
88 {
89 //Get size of data block
90 Stream->read(&tempint32, 4);
91 DataSize = tempint32;
92 DataOffset = Stream->getCurrentPos();
93
94 Valid = true;
95 }
96 }
97 }
98 }
99 }
100 }
101 }
102 }
103 }
104 }
105
106 cWavDecoder::~cWavDecoder()
107 {
108 Channels = 0;
109 SampleRate = 0;
110 ByteRate = 0;
111 BlockAlign = 0;
112 BitsPerSample = 0;
113 DataSize = 0;
114 DataOffset = 0;
115 Valid = false;
116 }
117
118 AudioFormats cWavDecoder::getFormat()
119 {
120 if(Channels == 1 && BitsPerSample == 8)
121 return EAF_8BIT_MONO;
122 else if(Channels == 1 && BitsPerSample == 16)
123 return EAF_16BIT_MONO;
124 else if(Channels == 2 && BitsPerSample == 8)
125 return EAF_8BIT_STEREO;
126 else
127 return EAF_16BIT_STEREO;
128 }
129
130 int cWavDecoder::getFrequency()
131 {
132 return SampleRate;
133 }
134
135 bool cWavDecoder::isSeekingSupported()
136 {
137 return true;
138 }
139
140 bool cWavDecoder::isValid()
141 {
142 return Valid;
143 }
144
145 int cWavDecoder::readAudioData(void* output, int amount)
146 {
147 int currentPos = Stream->getCurrentPos();
148 int startPos = DataOffset;
149 int endPos = DataOffset + DataSize;
150 int amountToRead = amount;
151
152 //Bounds checks (and adjustments if possible)
153 if(currentPos > endPos)
154 return 0;
155
156 if(currentPos < startPos)
157 {
158 Stream->seek(startPos, false);
159 currentPos = Stream->getCurrentPos();
160 }
161
162 if((currentPos + amountToRead) > endPos)
163 amountToRead = endPos - currentPos;
164
165 if(amountToRead < 0)
166 amountToRead = 0;
167
168 return Stream->read(output,amountToRead);
169
170 }
171
172 bool cWavDecoder::setPosition(int position, bool relative)
173 {
174 int currentPos = Stream->getCurrentPos();
175 int startPos = DataOffset;
176 int endPos = DataOffset + DataSize;
177
178 //Bounds checks (and adjustments if possible)
179 if(!relative && position < startPos)
180 position = startPos;
181 if(!relative && position > endPos)
182 position = endPos;
183 if(relative && currentPos + position < startPos)
184 position = startPos - currentPos;
185 if(relative && currentPos + position > startPos)
186 position = endPos - currentPos;
187
188 Stream->seek(position,relative);
189 return true;
190 }
191
192 bool cWavDecoder::seek(float seconds,bool relative)
193 {
194 int amountToSeek = (int) (seconds * (float)SampleRate * (float)Channels * (float)(BitsPerSample/8));
195 return setPosition(amountToSeek, relative);
196 }
197
198 float cWavDecoder::getTotalTime()
199 {
200 return (float)Stream->getSize() / ((float)SampleRate * (float)Channels * (float)(BitsPerSample/8));
201 }
202
203 int cWavDecoder::getTotalSize()
204 {
205 return Stream->getSize();
206 }
207
208 int cWavDecoder::getCompressedSize()
209 {
210 return Stream->getSize();
211 }
212
213 float cWavDecoder::getCurrentTime()
214 {
215 return (float)Stream->getCurrentPos() / ((float)SampleRate * (float)Channels * (float)(BitsPerSample/8));
216 }
217
218 int cWavDecoder::getCurrentPosition()
219 {
220 return Stream->getCurrentPos();
221 }
222
223 int cWavDecoder::getCurrentCompressedPosition()
224 {
225 return Stream->getCurrentPos();
226 }
227
228 cAudioString cWavDecoder::getType() const
229 {
230 return cAudioString(_CTEXT("cWavDecoder"));
231 }
232};
233
234#endif
235
236
Main namespace for the entire cAudio library.
Definition: cAudioCapture.h:16
AudioFormats
Enumeration of audio formats supported by the engine.
Definition: EAudioFormats.h:11