# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

buffer_dsound.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2001 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 
00027 #include "stddsound.h"
00028 #include "buffer_dsound.h"
00029 #include "nel/misc/path.h"
00030 
00031 
00032 #include <windows.h>
00033 #include <mmsystem.h>
00034 
00035 using namespace NLMISC;
00036 using namespace std;
00037 
00038 namespace NLSOUND {
00039 
00040 
00041 CBufferDSound::CBufferDSound()
00042 {
00043     _Data = NULL;
00044     _Size = 0; 
00045     _Format = Mono16;
00046     _Freq = 0;
00047 }
00048 
00049 CBufferDSound::~CBufferDSound()
00050 {
00051         nldebug("Destroying DirectSound buffer %s (%p)", _Name.c_str(), this);
00052 
00053     if (_Data != NULL)
00054     {
00055         delete[] _Data;
00056     }
00057 }
00058 
00059 void CBufferDSound::presetName(const std::string &bufferName)
00060 {
00061         _Name = bufferName;
00062 }
00063 
00064 
00065 void CBufferDSound::setFormat( TSampleFormat format, uint freq )
00066 {
00067     _Format = format;
00068     _Freq = freq;
00069 }
00070 
00071 
00072 bool CBufferDSound::fillBuffer( void *src, uint32 bufsize )
00073 {
00074     return false;
00075 }
00076 
00077 
00078 float CBufferDSound::getDuration() const
00079 {
00080     float frames = (float) _Size;
00081 
00082     switch (_Format) {
00083     case Mono8:
00084         break;
00085     case Mono16:
00086         frames /= 2.0f;
00087         break;
00088     case Stereo8:
00089         frames /= 2.0f;
00090         break;
00091     case Stereo16:
00092         frames /= 4.0f;
00093         break;
00094     }
00095 
00096     return 1000.0f * frames / (float) _Freq;
00097 }
00098 
00099 
00100 bool CBufferDSound::loadWavFile(const char* file) 
00101 {
00102     sint error; 
00103     sint32 num;
00104     HMMIO hmmio;
00105     WAVEFORMATEX format;
00106     MMCKINFO riff_chunk;
00107     MMCKINFO data_chunk;
00108     MMCKINFO chunk;
00109 
00110   
00111     if (_Data != NULL)
00112     {
00113         free(_Data);
00114         _Data = NULL;
00115     }
00116 
00117 
00118     // Open the file 
00119     hmmio = mmioOpen((char*) file, NULL, MMIO_READ | MMIO_DENYWRITE);
00120 
00121     if (hmmio == NULL) 
00122     {
00123         throw ESoundDriver("Failed to open the file");
00124     }
00125 
00126 
00127     // Check it's a WAVE file 
00128     riff_chunk.ckid = FOURCC_RIFF;
00129 
00130     error = (sint) mmioDescend(hmmio, &riff_chunk, NULL, 0);
00131 
00132     if ((error != 0) || (riff_chunk.ckid != FOURCC_RIFF) || (riff_chunk.fccType != mmioFOURCC('W', 'A', 'V', 'E'))) 
00133     {
00134         mmioClose(hmmio, 0);
00135         throw ESoundDriver("Not a WAVE file");
00136     }
00137 
00138 
00139     // Search the format chunk 
00140     chunk.ckid = mmioFOURCC('f', 'm', 't', ' ');
00141 
00142     error = (sint) mmioDescend(hmmio, &chunk, &riff_chunk, MMIO_FINDCHUNK);
00143 
00144     if (error != 0) 
00145     {
00146         mmioClose(hmmio, 0);
00147         throw ESoundDriver("Couldn't find the format chunk");
00148     }
00149 
00150     if (chunk.cksize < (long) sizeof(PCMWAVEFORMAT)) 
00151     {
00152         mmioClose(hmmio, 0);
00153         throw ESoundDriver("Invalid format chunk size");
00154     }
00155 
00156 
00157     // read in the format data
00158 
00159     num = mmioRead(hmmio, (HPSTR) &format, (long) sizeof(format));
00160     if (num != (long) sizeof(format)) 
00161     {
00162         mmioClose(hmmio, 0);
00163         throw ESoundDriver("Read failed");
00164     }
00165 
00166     format.cbSize = 0;
00167 
00168     // Get out of the format chunk
00169 
00170     if (mmioAscend(hmmio, &chunk, 0) != 0) 
00171     {
00172         mmioClose(hmmio, 0);
00173         throw ESoundDriver("Read failed");
00174     }
00175 
00176 
00177     // copy the format data 
00178 
00179     if (format.wFormatTag != WAVE_FORMAT_PCM) 
00180     {
00181         mmioClose(hmmio, 0);
00182         throw ESoundDriver("Unsupported sample format");
00183     }
00184 
00185     _Freq = format.nSamplesPerSec;
00186 
00187     if (format.nChannels == 1) 
00188     {
00189         if (format.wBitsPerSample == 8)
00190         {
00191             _Format = Mono8;
00192         } 
00193         else if (format.wBitsPerSample == 16)
00194         {
00195             _Format = Mono16;
00196         }
00197         else
00198         {
00199             mmioClose(hmmio, 0);
00200             throw ESoundDriver("Unsupported sample size");
00201         }
00202     }
00203     else if (format.nChannels == 2)
00204     {
00205         if (format.wBitsPerSample == 8)
00206         {
00207             _Format = Stereo8;
00208         } 
00209         else if (format.wBitsPerSample == 16)
00210         {
00211             _Format = Stereo16;
00212         }
00213         else
00214         {
00215             mmioClose(hmmio, 0);
00216             throw ESoundDriver("Unsupported sample size");
00217         }
00218     }
00219     else // Shouldn't normally happen
00220     {
00221         mmioClose(hmmio, 0);
00222         throw ESoundDriver("Unsupported number of channels");
00223     }
00224 
00225     
00226     // Set the file position to the beginning of the data chunk */
00227  
00228     sint32 pos = mmioSeek(hmmio, riff_chunk.dwDataOffset + sizeof(FOURCC), SEEK_SET);
00229 
00230     if (pos < 0) 
00231     {
00232         mmioClose(hmmio, 0);
00233         throw ESoundDriver("Read to set the read position");
00234     }
00235 
00236     data_chunk.ckid = mmioFOURCC('d', 'a', 't', 'a');
00237 
00238     if (mmioDescend(hmmio, &data_chunk, &riff_chunk, MMIO_FINDCHUNK) != 0) 
00239     {
00240         mmioClose(hmmio, 0);
00241         throw ESoundDriver("Read to set the read position");
00242     }
00243 
00244 
00245     // Allocate the sample buffer
00246     _Size = data_chunk.cksize;
00247 
00248     _Data = new uint8[_Size];
00249 
00250     if (_Data == NULL)
00251     {
00252         mmioClose(hmmio, 0);
00253         throw ESoundDriver("Out of memory");
00254     }
00255 
00256 
00257     // Read the sample data
00258 
00259     num = mmioRead(hmmio, (HPSTR) _Data, _Size);
00260 
00261     if (num < 0) 
00262     {
00263         throw ESoundDriver("Failed to read the samples");
00264     }
00265     else if ((uint32) num < _Size)
00266     {
00267         // FIXME: print warning or throw exception ???
00268         char* p = (char*) _Data;
00269         ZeroMemory(p + num, _Size - num);
00270     }
00271 
00272 
00273     mmioClose(hmmio, 0);
00274 
00275 
00276         std::string name = CFile::getFilenameWithoutExtension(file);
00277         // if name is preseted, the name must match.
00278         if (!_Name.empty())
00279         {
00280                 nlassertex(_Name == name, ("The preseted name and buffer name doen't match !"));
00281         }
00282         _Name = name;
00283 
00284         return true;
00285 
00286 }
00287 
00288 
00289 } // NLSOUND
00290 
00291 
00292