cWavDecoder.cpp

00001 // Copyright (c) 2008-2010 Raynaldo (Wildicv) Rivera, Joshua (Dark_Kilauea) Jones
00002 // This file is part of the "cAudio Engine"
00003 // For conditions of distribution and use, see copyright notice in cAudio.h
00004 
00005 #include "../Headers/cWavDecoder.h"
00006 #include <string.h>
00007 
00008 #ifdef CAUDIO_COMPILE_WITH_WAV_DECODER
00009 
00010 namespace cAudio
00011 {
00012         cWavDecoder::cWavDecoder(IDataSource* stream) : IAudioDecoder(stream), Valid(false)
00013     {
00014         const char* RIFFTAG = "RIFF";
00015                 const char* WAVETAG = "WAVE";
00016                 const char* FORMATTAG = "fmt ";
00017                 const char* DATATAG = "data";
00018 
00019                 char ident[4];
00020                 int tempint32 = 0;
00021                 short tempint16 = 0;
00022                 char tempint8 = 0;
00023 
00024                 unsigned int startOffset = 0;
00025 
00026                 //Read the first 4 bytes
00027                 Stream->seek(0, false);
00028                 Stream->read(ident, 4);
00029                 //Check to see if it is a valid RIFF file
00030                 if(strncmp(ident, RIFFTAG, 4) == 0)
00031                 {
00032                         Stream->read(&tempint32, 4);
00033                         //Check to see if the file is big enough to be valid (not completely accurate)
00034                         if(tempint32 >= 44)
00035                         {
00036                                 Stream->read(ident, 4);
00037                                 //Check that it is a wave file
00038                                 if(strncmp(ident, WAVETAG, 4) == 0)
00039                                 {
00040                                         //Save our position
00041                                         startOffset = Stream->getCurrentPos();
00042 
00043                                         //Scan for the first fmt chuck (not necessarily right after)
00044                                         do
00045                                         {
00046                                                 Stream->read(ident, 4);
00047                                         }
00048                                         while((strncmp(ident, FORMATTAG, 4) != 0) && (Stream->getCurrentPos() < Stream->getSize()));
00049 
00050                                         //Did we find it?
00051                                         if(Stream->getCurrentPos() < (Stream->getSize() - 16))
00052                                         {
00053                                                 //Yes, read it in
00054                                                 Stream->read(&tempint32, 4);
00055                                                 if(tempint32 >= 16)
00056                                                 {
00057                                                         //Check that it is in PCM format, we don't support compressed wavs
00058                                                         Stream->read(&tempint16, 2);
00059                                                         if(tempint16 == 1)
00060                                                         {
00061                                                                 Stream->read(&tempint16, 2);
00062                                                                 Channels = tempint16;
00063                                                                 //We only support mono or stereo wavs
00064                                                                 if(Channels == 1 || Channels == 2)
00065                                                                 {
00066                                                                         Stream->read(&tempint32, 4);
00067                                                                         SampleRate = tempint32;
00068                                                                         Stream->read(&tempint32, 4);
00069                                                                         ByteRate = tempint32;
00070                                                                         Stream->read(&tempint16, 2);
00071                                                                         BlockAlign = tempint16;
00072                                                                         Stream->read(&tempint16, 2);
00073                                                                         BitsPerSample = tempint16;
00074 
00075                                                                         //We only support 8 bit or 16 bit wavs
00076                                                                         if(BitsPerSample == 8 || BitsPerSample == 16)
00077                                                                         {
00078                                                                                 //Reset our pointer to start scanning for the data block
00079                                                                                 Stream->seek(startOffset, false);
00080                                                                                 //Scan for the first data chuck (not necessarily right after)
00081                                                                                 do
00082                                                                                 {
00083                                                                                         Stream->read(ident, 4);
00084                                                                                 }
00085                                                                                 while((strncmp(ident, DATATAG, 4) != 0) && (Stream->getCurrentPos() < Stream->getSize()));
00086 
00087                                                                                 //Did we find it?
00088                                                                                 if(Stream->getCurrentPos() < Stream->getSize())
00089                                                                                 {
00090                                                                                         //Get size of data block
00091                                                                                         Stream->read(&tempint32, 4);
00092                                                                                         DataSize = tempint32;
00093                                                                                         DataOffset = Stream->getCurrentPos();
00094 
00095                                                                                         Valid = true;
00096                                                                                 }
00097                                                                         }
00098                                                                 }
00099                                                         }
00100                                                 }
00101                                         }
00102                                 }
00103                         }
00104                 }
00105     }
00106 
00107     cWavDecoder::~cWavDecoder()
00108     {
00109                 Channels = 0;
00110                 SampleRate = 0;
00111                 ByteRate = 0;
00112                 BlockAlign = 0;
00113                 BitsPerSample = 0;
00114                 DataSize = 0;
00115                 DataOffset = 0;
00116                 Valid = false;
00117     }
00118 
00119     AudioFormats cWavDecoder::getFormat()
00120     {
00121         if(Channels == 1 && BitsPerSample == 8)
00122             return EAF_8BIT_MONO;
00123                 else if(Channels == 1 && BitsPerSample == 16)
00124             return EAF_16BIT_MONO;
00125                 else if(Channels == 2 && BitsPerSample == 8)
00126             return EAF_8BIT_STEREO;
00127         else
00128             return EAF_16BIT_STEREO;
00129     }
00130 
00131     int cWavDecoder::getFrequency()
00132     {
00133         return SampleRate;
00134     }
00135 
00136     bool cWavDecoder::isSeekingSupported()
00137     {
00138         return true;
00139     }
00140 
00141         bool cWavDecoder::isValid()
00142         {
00143                 return Valid;
00144         }
00145 
00146     int cWavDecoder::readAudioData(void* output, int amount)
00147     {
00148                 int currentPos = Stream->getCurrentPos();
00149                 int startPos = DataOffset;
00150                 int endPos = DataOffset + DataSize;
00151                 int amountToRead = amount;
00152 
00153                 //Bounds checks (and adjustments if possible)
00154                 if(currentPos > endPos)
00155                         return 0;
00156 
00157                 if(currentPos < startPos)
00158                 {
00159                         Stream->seek(startPos, false);
00160                         currentPos = Stream->getCurrentPos();
00161                 }
00162 
00163                 if((currentPos + amountToRead) > endPos)
00164                         amountToRead = endPos - currentPos;
00165 
00166                 if(amountToRead < 0)
00167                         amountToRead = 0;
00168 
00169                 return Stream->read(output,amountToRead);
00170 
00171     }
00172 
00173     bool cWavDecoder::setPosition(int position, bool relative)
00174     {
00175                 int currentPos = Stream->getCurrentPos();
00176                 int startPos = DataOffset;
00177                 int endPos = DataOffset + DataSize;
00178 
00179                 //Bounds checks (and adjustments if possible)
00180                 if(!relative && position < startPos)
00181                         position = startPos;
00182                 if(!relative && position > endPos)
00183                         position = endPos;
00184                 if(relative && currentPos + position < startPos)
00185                         position = startPos - currentPos;
00186                 if(relative && currentPos + position > startPos)
00187                         position = endPos - currentPos;
00188 
00189         Stream->seek(position,relative);
00190         return true;
00191     }
00192 
00193     bool cWavDecoder::seek(float seconds,bool relative)
00194     {
00195                 int amountToSeek = seconds * (float)SampleRate * (float)Channels * (float)(BitsPerSample/8);
00196         return setPosition(amountToSeek, relative);
00197     }
00198 
00199         float cWavDecoder::getTotalTime()
00200         {
00201                 return (float)Stream->getSize() / ((float)SampleRate * (float)Channels * (float)(BitsPerSample/8));
00202         }
00203 
00204         int cWavDecoder::getTotalSize()
00205         {
00206                 return Stream->getSize();
00207         }
00208 
00209         int cWavDecoder::getCompressedSize()
00210         {
00211                 return Stream->getSize();
00212         }
00213 
00214         float cWavDecoder::getCurrentTime()
00215         {
00216                 return (float)Stream->getCurrentPos() / ((float)SampleRate * (float)Channels * (float)(BitsPerSample/8));
00217         }
00218 
00219         int cWavDecoder::getCurrentPosition()
00220         {
00221                 return Stream->getCurrentPos();
00222         }
00223 
00224         int cWavDecoder::getCurrentCompressedPosition()
00225         {
00226                 return Stream->getCurrentPos();
00227         }
00228 };
00229 
00230 #endif
00231 
00232 
 All Classes Namespaces Functions Variables Enumerations

Generated on Sat Feb 20 22:55:09 2010 for cAudio by  doxygen 1.6.2