cAudio  2.3.0
3d Audio Engine
 All Classes Namespaces Functions Variables Enumerations Pages
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 
10 namespace 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 
AudioFormats
Enumeration of audio formats supported by the engine.
Definition: EAudioFormats.h:10