00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
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
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
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
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
00169
00170 if (mmioAscend(hmmio, &chunk, 0) != 0)
00171 {
00172 mmioClose(hmmio, 0);
00173 throw ESoundDriver("Read failed");
00174 }
00175
00176
00177
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
00220 {
00221 mmioClose(hmmio, 0);
00222 throw ESoundDriver("Unsupported number of channels");
00223 }
00224
00225
00226
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
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
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
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
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 }
00290
00291
00292