00001
00002
00003
00004
00005 #include "audio3/nwavfile.h"
00006 #include "kernel/nfileserver2.h"
00007 #include "kernel/nfile.h"
00008
00009 bool nWavFile::mmioProcInstalled = false;
00010
00011
00018 LRESULT CALLBACK
00019 mmioProc(LPSTR lpstr, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
00020 {
00021 MMIOINFO* lpMMIOInfo = (MMIOINFO*)lpstr;
00022
00023 n_assert(0 != lpMMIOInfo);
00024 n_assert(mmioFOURCC('N','E','B','2') == lpMMIOInfo->fccIOProc);
00025 n_assert(mmioProc == lpMMIOInfo->pIOProc);
00026
00027 switch (uMsg)
00028 {
00029 case MMIOM_OPEN:
00030 {
00031 if (0 == (lpMMIOInfo->dwFlags & (MMIO_WRITE | MMIO_READWRITE)))
00032 {
00033
00034 nString rawName((const char*)lParam1);
00035 nString filename = rawName.ExtractRange(7, rawName.Length() - 7);
00036
00037
00038 nFile* file = nFileServer2::Instance()->NewFileObject();
00039 if (file->Open(filename, "rb"))
00040 {
00041
00042 lpMMIOInfo->adwInfo[0] = (DWORD) file;
00043 return MMSYSERR_NOERROR;
00044 }
00045 else
00046 {
00047 file->Release();
00048 }
00049 }
00050
00051
00052 return MMIOERR_CANNOTOPEN;
00053 }
00054
00055 case MMIOM_CLOSE:
00056 {
00057 nFile* file = (nFile*)lpMMIOInfo->adwInfo[0];
00058 n_assert(0 != file);
00059
00060 file->Close();
00061 file->Release();
00062 lpMMIOInfo->adwInfo[0] = 0;
00063
00064 return 0;
00065 }
00066
00067 case MMIOM_READ:
00068 {
00069 nFile* file = (nFile*)lpMMIOInfo->adwInfo[0];
00070 n_assert(0 != file && file->IsOpen());
00071
00072 int bytesRead = file->Read((HPSTR)lParam1, (LONG)lParam2);
00073 lpMMIOInfo->lDiskOffset += bytesRead;
00074
00075 return bytesRead;
00076 }
00077
00078 case MMIOM_SEEK:
00079 {
00080 nFile* file = (nFile*)lpMMIOInfo->adwInfo[0];
00081 n_assert(0 != file && file->IsOpen());
00082
00083 nFile::nSeekType seekType;
00084 switch ((int)lParam2)
00085 {
00086 case SEEK_CUR: seekType = nFile::CURRENT; break;
00087 case SEEK_END: seekType = nFile::END; break;
00088 default: seekType = nFile::START; break;
00089 }
00090
00091 if (file->Seek((LONG)lParam1, seekType))
00092 {
00093 lpMMIOInfo->lDiskOffset = file->Tell();
00094 return lpMMIOInfo->lDiskOffset;
00095 }
00096 else
00097 {
00098 return -1;
00099 }
00100 }
00101
00102 case MMIOM_WRITE:
00103 case MMIOM_WRITEFLUSH:
00104
00105 return -1;
00106 }
00107
00108
00109 return 0;
00110 }
00111
00112
00115 nWavFile::nWavFile() :
00116 m_pwfx(0),
00117 m_hmmio(NULL),
00118 m_dwSize(0)
00119 {
00120
00121 if (!mmioProcInstalled)
00122 {
00123 LPMMIOPROC p = mmioInstallIOProc(mmioFOURCC('N','E','B','2'), mmioProc, MMIO_INSTALLPROC);
00124 n_assert(p);
00125 mmioProcInstalled = true;
00126 }
00127 }
00128
00129
00132 nWavFile::~nWavFile()
00133 {
00134 if (this->IsOpen())
00135 {
00136 this->Close();
00137 }
00138 }
00139
00140
00143 bool
00144 nWavFile::Open(const nString& filename)
00145 {
00146 n_assert(!this->IsOpen());
00147 n_assert(filename.IsValid());
00148
00149
00150 nString mangledPath = nFileServer2::Instance()->ManglePath(filename);
00151 nString mmioFilename("X.NEB2+");
00152 mmioFilename.Append(mangledPath);
00153
00154
00155 this->m_hmmio = mmioOpen((LPSTR)mmioFilename.Get(), NULL, MMIO_ALLOCBUF | MMIO_READ);
00156 if (NULL == this->m_hmmio)
00157 {
00158 n_error("nWavFile::Open(): failed to open file '%s'!", filename.Get());
00159 return false;
00160 }
00161
00162
00163 if (!this->ReadMMIO())
00164 {
00165 mmioClose(this->m_hmmio, 0);
00166 n_error("nWavFile::Open(): not a wav file (%s)!", filename.Get());
00167 return false;
00168 }
00169
00170
00171 this->Reset();
00172
00173
00174 this->m_dwSize = this->m_ck.cksize;
00175
00176 this->isOpen = true;
00177 return true;
00178 }
00179
00180
00183 void
00184 nWavFile::Close()
00185 {
00186 n_assert(this->IsOpen());
00187 n_assert(0 != this->m_hmmio);
00188
00189 n_delete(this->m_pwfx);
00190 this->m_pwfx = 0;
00191
00192 mmioClose(this->m_hmmio, 0);
00193 this->m_hmmio = 0;
00194 this->isOpen = false;
00195 }
00196
00197
00200 int
00201 nWavFile::GetSize() const
00202 {
00203 n_assert(this->IsOpen());
00204 return this->m_dwSize;
00205 }
00206
00207
00210 WAVEFORMATEX*
00211 nWavFile::GetFormat() const
00212 {
00213 return this->m_pwfx;
00214 }
00215
00216
00221 bool
00222 nWavFile::ReadMMIO()
00223 {
00224 n_assert(this->m_hmmio);
00225
00226 MMCKINFO ckIn;
00227 PCMWAVEFORMAT pcmWaveFormat;
00228
00229 this->m_pwfx = NULL;
00230
00231
00232 if (0 != mmioDescend(this->m_hmmio, &this->m_ckRiff, NULL, 0))
00233 {
00234 return false;
00235 }
00236
00237
00238 if ((this->m_ckRiff.ckid != FOURCC_RIFF) ||
00239 (this->m_ckRiff.fccType != mmioFOURCC('W','A','V','E')))
00240 {
00241 return false;
00242 }
00243
00244
00245 ckIn.ckid = mmioFOURCC('f','m','t',' ');
00246 if (0 != mmioDescend(this->m_hmmio, &ckIn, &this->m_ckRiff, MMIO_FINDCHUNK))
00247 {
00248 return false;
00249 }
00250
00251
00252
00253 if (ckIn.cksize < (LONG)sizeof(PCMWAVEFORMAT))
00254 {
00255 return false;
00256 }
00257
00258
00259 if (mmioRead(this->m_hmmio, (HPSTR)&pcmWaveFormat, sizeof(pcmWaveFormat)) != sizeof(pcmWaveFormat))
00260 {
00261 return false;
00262 }
00263
00264
00265
00266 if (pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM)
00267 {
00268 this->m_pwfx = (WAVEFORMATEX*) n_new(char[sizeof(WAVEFORMATEX)]);
00269 n_assert(this->m_pwfx);
00270
00271
00272 memcpy(this->m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat));
00273 this->m_pwfx->cbSize = 0;
00274 }
00275 else
00276 {
00277
00278 WORD cbExtraBytes = 0L;
00279 if (mmioRead(m_hmmio, (CHAR*)&cbExtraBytes, sizeof(WORD)) != sizeof(WORD))
00280 {
00281 return false;
00282 }
00283
00284 this->m_pwfx = (WAVEFORMATEX*)n_new(char[sizeof(WAVEFORMATEX) + cbExtraBytes]);
00285 n_assert(this->m_pwfx);
00286
00287
00288 memcpy(this->m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat));
00289 this->m_pwfx->cbSize = cbExtraBytes;
00290
00291
00292 if (mmioRead(this->m_hmmio, (CHAR*)(((BYTE*)&(m_pwfx->cbSize)) + sizeof(WORD)), cbExtraBytes) != cbExtraBytes)
00293 {
00294 n_delete(this->m_pwfx);
00295 this->m_pwfx = 0;
00296 return false;
00297 }
00298 }
00299
00300
00301 if (0 != mmioAscend(this->m_hmmio, &ckIn, 0))
00302 {
00303 n_delete(this->m_pwfx);
00304 this->m_pwfx = 0;
00305 return false;
00306 }
00307 return true;
00308 }
00309
00310
00314 bool
00315 nWavFile::Reset()
00316 {
00317 n_assert(this->m_hmmio);
00318
00319
00320 if (-1 == mmioSeek(this->m_hmmio, this->m_ckRiff.dwDataOffset + sizeof(FOURCC), SEEK_SET))
00321 {
00322 return false;
00323 }
00324
00325
00326 this->m_ck.ckid = mmioFOURCC('d','a','t','a');
00327 if (0 != mmioDescend(this->m_hmmio, &this->m_ck, &this->m_ckRiff, MMIO_FINDCHUNK))
00328 {
00329 return false;
00330 }
00331 return true;
00332 }
00333
00334
00342 uint
00343 nWavFile::Read(void* buffer, uint bytesToRead)
00344 {
00345 n_assert(this->IsOpen());
00346 n_assert(this->m_hmmio);
00347 n_assert(buffer);
00348 n_assert(bytesToRead > 0);
00349
00350 MMIOINFO mmioInfoIn;
00351 mmioGetInfo(this->m_hmmio, &mmioInfoIn, 0);
00352
00353 uint cbDataIn = bytesToRead;
00354 if (cbDataIn > this->m_ck.cksize)
00355 {
00356 cbDataIn = this->m_ck.cksize;
00357 }
00358 this->m_ck.cksize -= cbDataIn;
00359
00360 DWORD cT;
00361 for (cT = 0; cT < cbDataIn; cT++)
00362 {
00363
00364 if (mmioInfoIn.pchNext == mmioInfoIn.pchEndRead)
00365 {
00366 mmioAdvance(this->m_hmmio, &mmioInfoIn, MMIO_READ);
00367 }
00368
00369
00370 *((uchar*)buffer + cT) = *((uchar*)mmioInfoIn.pchNext);
00371 mmioInfoIn.pchNext++;
00372 }
00373 mmioSetInfo(this->m_hmmio, &mmioInfoIn, 0);
00374 return cbDataIn;
00375 }