MercurySoundSourceWAV.cpp

Go to the documentation of this file.
00001 //#include <iostream>
00002 #include "global.h"
00003 #include "MercurySoundSourceWAV.h"
00004 #include "MercuryLog.h"
00005 #include "MercurySoundDriverALSA.h"
00006 
00007 MercurySoundSourceWAV::MercurySoundSourceWAV()
00008     :m_file(NULL)
00009 {
00010 }
00011 
00012 MercurySoundSourceWAV::~MercurySoundSourceWAV()
00013 {
00014     if (m_playState==PLAYING)
00015         MercurySoundDriverALSA::GetInstance().RemoveSound(this);
00016     SAFE_DELETE( m_file );
00017 }
00018 
00019 bool MercurySoundSourceWAV::Open(const MString& path)
00020 {
00021     RiffChunk chunk;
00022     WaveHead head;
00023     FmtChunk dataHead;
00024     
00025     m_file = FILEMAN.Open( path );
00026     if (!m_file)
00027     {
00028         LOG.Warn("Could not open " + path);
00029         return false;
00030     }
00031     
00032     m_file->Read(&head, sizeof(WaveHead));
00033     head.info.id = Swap32(head.info.id); //to little endian
00034     TO_ENDIAN( head.info.id );
00035     head.type = Swap32(head.type); //to little endian
00036     TO_ENDIAN( head.type );
00037 
00038     if (head.info.id != 0x52494646)
00039     {
00040         LOG.Log(GetType() + ":" + path + " not a valid RIFF");
00041         return false;
00042     }
00043 
00044     if (head.type != 0x57415645)
00045     {
00046         LOG.Log(GetType() + ":" + "Only type WAVE supported");
00047         return false;
00048     }
00049 
00050     m_file->Read(&chunk, sizeof(RiffChunk)); //The compiler pads this one, manually set size 8
00051     m_file->Read(&dataHead, chunk.size); //The compiler pads this one, manually set size
00052     chunk.id = Swap32(chunk.id); //to little endian
00053     TO_ENDIAN( chunk.id );
00054 
00055     if (chunk.id != 0x666D7420)
00056     {
00057         LOG.Log(GetType() + ":" + "Invalid chunk, only fmt chunks supported");
00058         return false;
00059     }   
00060 
00061     TO_ENDIAN2(dataHead.comp );
00062     TO_ENDIAN2(dataHead.channels );
00063     TO_ENDIAN( dataHead.srate );
00064     if (dataHead.comp != 1)
00065     {
00066         LOG.Log(GetType() + ":" + "WAV not PCM");
00067         return false;
00068     }
00069 
00070     if (dataHead.channels > 2)
00071     {
00072         LOG.Log(GetType() + ":" + "Only mono or stereo is supported");
00073         return false;
00074     }
00075     
00076     m_chunkSize = 0;
00077     m_chunkPosition = 0;
00078     m_atAudioChunk = false;
00079     m_destroyOnStop = false;
00080 }
00081 
00082 bool MercurySoundSourceWAV::LocateAudioData()
00083 {
00084     RiffChunk chunk;
00085     while (!m_file->Eof())
00086     {
00087         char str[5];
00088         str[4] = '\0';
00089         m_file->Read(&chunk, sizeof(RiffChunk));
00090         memcpy(str, &chunk.id, 4);
00091         chunk.id = Swap32(chunk.id);
00092         TO_ENDIAN( chunk.id );
00093         TO_ENDIAN( chunk.size );
00094         
00095         if (chunk.id == 0x64617461)
00096         {
00097             m_chunkSize = chunk.size;
00098             m_chunkPosition = 0;
00099             m_atAudioChunk = true;
00100             return true;
00101         }
00102         else
00103         {
00104             LOG.Info( GetType() + ":" + "Skipping unknown chunk." );
00105             m_file->Seek( m_file->Tell() + chunk.size);
00106         }
00107     }
00108     return false;
00109 }
00110 
00111 float* Read(unsigned long samples);
00112 
00113 
00114 float* MercurySoundSourceWAV::ReadData(unsigned long samples)
00115 {
00116     if (m_chunkPosition >= m_chunkSize)
00117         m_atAudioChunk = false;
00118         
00119     if (!m_atAudioChunk)
00120         LocateAudioData();
00121     
00122     if (!m_atAudioChunk)
00123     {
00124         Stop();
00125         return NULL;
00126     }
00127     
00128     unsigned long bytes( samples*sizeof(int16_t) );
00129     int16_t* data = new int16_t[samples];
00130     float* fdata = new float[samples];
00131     
00132     memset(data, 0 , bytes);
00133     m_file->Read(data, bytes);
00134     m_chunkPosition += bytes;
00135     
00136     for (unsigned int i = 0; i < samples; ++i)
00137         fdata[i] = Clamp(data[i]/32767.0f, -1.0f, 1.0f);
00138     
00139     delete data;
00140     return fdata;
00141 }
00142 
00143 bool MercurySoundSourceWAV::Play()
00144 {
00145     if (m_playState == PLAYING)
00146     {
00147         LOG.Info(GetType() + ":" + "Streamed sound already playing");
00148         return false;
00149     }
00150     m_playState = PLAYING;
00151     MercurySoundDriverALSA::GetInstance().AddSound(this);
00152     return true;
00153 }
00154 
00155 bool MercurySoundSourceWAV::Stop()
00156 {
00157     m_playState = STOPPED;
00158     MercurySoundDriverALSA::GetInstance().RemoveSound(this);
00159     if (m_destroyOnStop)
00160         delete this;
00161 }
00162 void MercurySoundSourceWAV::Pause(bool pause)
00163 {
00164     if ( (m_playState==PLAYING)&&pause )
00165         m_playState = PAUSED;
00166     else if ((m_playState==PAUSED)&&!pause)
00167         m_playState = PLAYING;
00168 }
00169 
00170 /* 
00171  * Copyright (c) 2007 Joshua Allen
00172  * All rights reserved.
00173  *
00174  * Redistribution and use in source and binary forms, with or
00175  * without modification, are permitted provided that the following
00176  * conditions are met:
00177  *  -   Redistributions of source code must retain the above
00178  *      copyright notice, this list of conditions and the following disclaimer.
00179  *  -   Redistributions in binary form must reproduce the above copyright
00180  *      notice, this list of conditions and the following disclaimer in
00181  *      the documentation and/or other materials provided with the distribution.
00182  *  -   Neither the name of the Mercury Engine nor the names of its
00183  *      contributors may be used to endorse or promote products derived from
00184  *      this software without specific prior written permission.
00185  *
00186  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00187  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00188  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00189  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
00190  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00191  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00192  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00193  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00194  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00195  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00196  */

Hosted by SourceForge.net Logo