static void test_mmio_end_of_file(void) { char test_file[MAX_PATH], buffer[128], data[16]; MMIOINFO mmio; HMMIO hmmio; LONG ret; MMRESULT res; if (!create_test_file(test_file)) return; memset(&mmio, 0, sizeof(mmio)); mmio.fccIOProc = FOURCC_DOS; mmio.pchBuffer = buffer; mmio.cchBuffer = sizeof(buffer); hmmio = mmioOpen(test_file, &mmio, MMIO_READ); ok(hmmio != NULL, "mmioOpen error %u\n", mmio.wErrorRet); if (hmmio == NULL) { DeleteFileA(test_file); return; } ret = mmioSeek(hmmio, 0, SEEK_END); ok(sizeof(RIFF_buf) == ret, "got %d\n", ret); ret = mmioRead(hmmio, data, sizeof(data)); ok(ret == 0, "expected %d, got %d\n", 0, ret); res = mmioGetInfo(hmmio, &mmio, 0); ok(res == MMSYSERR_NOERROR, "expected 0, got %d\n", res); res = mmioAdvance(hmmio, &mmio, MMIO_READ); ok(res == MMSYSERR_NOERROR, "expected 0, got %d\n", res); ok(mmio.pchNext == mmio.pchEndRead, "expected %p, got %p\n", mmio.pchEndRead, mmio.pchNext); mmioClose(hmmio, 0); DeleteFileA(test_file); }
long ogg_mmio_tell(void* mmfp) { STRHDL* hdl = (STRHDL*)mmfp; return (mmioSeek(hdl->cfp, 0, SEEK_CUR) - hdl->true_offset); }
static HRESULT AVIFILE_SaveFile(const IAVIFileImpl *This) { MMCKINFO ckRIFF; MMCKINFO ck; mmioSeek(This->hmmio, 0, SEEK_SET); /* create the RIFF chunk with formtype WAVE */ ckRIFF.fccType = formtypeWAVE; ckRIFF.cksize = 0; if (mmioCreateChunk(This->hmmio, &ckRIFF, MMIO_CREATERIFF) != S_OK) return AVIERR_FILEWRITE; /* the next chunk is the format */ ck.ckid = ckidWAVEFORMAT; ck.cksize = This->cbFormat; if (mmioCreateChunk(This->hmmio, &ck, 0) != S_OK) return AVIERR_FILEWRITE; if (This->lpFormat != NULL && This->cbFormat > 0) { if (mmioWrite(This->hmmio, (HPSTR)This->lpFormat, ck.cksize) != ck.cksize) return AVIERR_FILEWRITE; } if (mmioAscend(This->hmmio, &ck, 0) != S_OK) return AVIERR_FILEWRITE; /* fact chunk is needed for non-pcm waveforms */ if (This->lpFormat != NULL && This->cbFormat > sizeof(PCMWAVEFORMAT) && This->lpFormat->wFormatTag != WAVE_FORMAT_PCM) { WAVEFORMATEX wfx; DWORD dwFactLength; HACMSTREAM has; /* try to open an appropriate audio codec to figure out * data for fact-chunk */ wfx.wFormatTag = WAVE_FORMAT_PCM; if (acmFormatSuggest(NULL, This->lpFormat, &wfx, sizeof(wfx), ACM_FORMATSUGGESTF_WFORMATTAG)) { acmStreamOpen(&has, NULL, This->lpFormat, &wfx, NULL, 0, 0, ACM_STREAMOPENF_NONREALTIME); acmStreamSize(has, This->ckData.cksize, &dwFactLength, ACM_STREAMSIZEF_SOURCE); dwFactLength /= wfx.nBlockAlign; acmStreamClose(has, 0); /* create the fact chunk */ ck.ckid = ckidWAVEFACT; ck.cksize = sizeof(dwFactLength); /* test for enough space before data chunk */ if (mmioSeek(This->hmmio, 0, SEEK_CUR) > This->ckData.dwDataOffset - ck.cksize - 4 * sizeof(DWORD)) return AVIERR_FILEWRITE; if (mmioCreateChunk(This->hmmio, &ck, 0) != S_OK) return AVIERR_FILEWRITE; if (mmioWrite(This->hmmio, (HPSTR)&dwFactLength, ck.cksize) != ck.cksize) return AVIERR_FILEWRITE; if (mmioAscend(This->hmmio, &ck, 0) != S_OK) return AVIERR_FILEWRITE; } else ERR(": fact chunk is needed for non-pcm files -- currently no codec found, so skipped!\n"); } /* if there was extra stuff, we need to fill it with JUNK */ if (mmioSeek(This->hmmio, 0, SEEK_CUR) + 2 * sizeof(DWORD) < This->ckData.dwDataOffset) { ck.ckid = ckidAVIPADDING; ck.cksize = 0; if (mmioCreateChunk(This->hmmio, &ck, 0) != S_OK) return AVIERR_FILEWRITE; if (mmioSeek(This->hmmio, This->ckData.dwDataOffset - 2 * sizeof(DWORD), SEEK_SET) == -1) return AVIERR_FILEWRITE; if (mmioAscend(This->hmmio, &ck, 0) != S_OK) return AVIERR_FILEWRITE; } /* create the data chunk */ ck.ckid = ckidWAVEDATA; ck.cksize = This->ckData.cksize; if (mmioCreateChunk(This->hmmio, &ck, 0) != S_OK) return AVIERR_FILEWRITE; if (mmioSeek(This->hmmio, This->ckData.cksize, SEEK_CUR) == -1) return AVIERR_FILEWRITE; if (mmioAscend(This->hmmio, &ck, 0) != S_OK) return AVIERR_FILEWRITE; /* some optional extra chunks? */ if (This->extra.lp != NULL && This->extra.cb > 0) { /* chunk headers are already in structure */ if (mmioWrite(This->hmmio, This->extra.lp, This->extra.cb) != This->extra.cb) return AVIERR_FILEWRITE; } /* close RIFF chunk */ if (mmioAscend(This->hmmio, &ckRIFF, 0) != S_OK) return AVIERR_FILEWRITE; if (mmioFlush(This->hmmio, 0) != S_OK) return AVIERR_FILEWRITE; return AVIERR_OK; }
static HRESULT AVIFILE_LoadFile(IAVIFileImpl *This) { MMCKINFO ckRIFF; MMCKINFO ck; This->sInfo.dwLength = 0; /* just to be sure */ This->fDirty = FALSE; /* search for RIFF chunk */ ckRIFF.fccType = 0; /* find any */ if (mmioDescend(This->hmmio, &ckRIFF, NULL, MMIO_FINDRIFF) != S_OK) { return AVIFILE_LoadSunFile(This); } if (ckRIFF.fccType != formtypeWAVE) return AVIERR_BADFORMAT; /* search WAVE format chunk */ ck.ckid = ckidWAVEFORMAT; if (FindChunkAndKeepExtras(&This->extra, This->hmmio, &ck, &ckRIFF, MMIO_FINDCHUNK) != S_OK) return AVIERR_FILEREAD; /* get memory for format and read it */ This->lpFormat = HeapAlloc(GetProcessHeap(), 0, ck.cksize); if (This->lpFormat == NULL) return AVIERR_FILEREAD; This->cbFormat = ck.cksize; if (mmioRead(This->hmmio, (HPSTR)This->lpFormat, ck.cksize) != ck.cksize) return AVIERR_FILEREAD; if (mmioAscend(This->hmmio, &ck, 0) != S_OK) return AVIERR_FILEREAD; /* Non-pcm formats have a fact chunk. * We don't need it, so simply add it to the extra chunks. */ /* find the big data chunk */ This->ckData.ckid = ckidWAVEDATA; if (FindChunkAndKeepExtras(&This->extra, This->hmmio, &This->ckData, &ckRIFF, MMIO_FINDCHUNK) != S_OK) return AVIERR_FILEREAD; memset(&This->sInfo, 0, sizeof(This->sInfo)); This->sInfo.fccType = streamtypeAUDIO; This->sInfo.dwRate = This->lpFormat->nAvgBytesPerSec; This->sInfo.dwSampleSize = This->sInfo.dwScale = This->lpFormat->nBlockAlign; This->sInfo.dwLength = This->ckData.cksize / This->lpFormat->nBlockAlign; This->sInfo.dwSuggestedBufferSize = This->ckData.cksize; This->fInfo.dwStreams = 1; if (mmioAscend(This->hmmio, &This->ckData, 0) != S_OK) { /* seems to be truncated */ WARN(": file seems to be truncated!\n"); This->ckData.cksize = mmioSeek(This->hmmio, 0, SEEK_END) - This->ckData.dwDataOffset; This->sInfo.dwLength = This->ckData.cksize / This->lpFormat->nBlockAlign; This->sInfo.dwSuggestedBufferSize = This->ckData.cksize; } /* ignore errors */ FindChunkAndKeepExtras(&This->extra, This->hmmio, &ck, &ckRIFF, 0); return AVIERR_OK; }
BOOL CreateSoundFromWave(PSOUND sound, PSTR waveFile, BOOL music) { MMRESULT mr = MMSYSERR_ERROR; HMMIO hmmio = NULL; ZeroMemory(sound, sizeof(SOUND)); hmmio = mmioOpen(waveFile, NULL, MMIO_ALLOCBUF | MMIO_READ); if (hmmio != NULL) { MMCKINFO riff = {0}; MMCKINFO chunk = {0}; PCMWAVEFORMAT pcmFormat = {0}; mr = mmioDescend(hmmio, &riff, NULL, 0); if (mr == 0) { /* ensure it's a proper wave file */ if (riff.ckid != FOURCC_RIFF || riff.fccType != mmioFOURCC('W', 'A', 'V', 'E')) { mr = MMSYSERR_ERROR; } } if (mr == 0) { /* find the format info */ chunk.ckid = mmioFOURCC( 'f', 'm', 't', ' ' ); if (mmioDescend(hmmio, &chunk, &riff, MMIO_FINDCHUNK) == 0) { if (mmioRead(hmmio, (HPSTR)&pcmFormat, sizeof(PCMWAVEFORMAT)) == sizeof(PCMWAVEFORMAT) && pcmFormat.wf.wFormatTag == WAVE_FORMAT_PCM) { memcpy(&sound->Format, &pcmFormat, sizeof(pcmFormat)); sound->Format.cbSize = 0; } else { mr = MMSYSERR_ERROR; } } else { mr = MMSYSERR_ERROR; } } if (mr == 0) { /* find the data chunk */ if (mmioSeek(hmmio, riff.dwDataOffset + sizeof(FOURCC), SEEK_SET) != -1) { chunk.ckid = mmioFOURCC('d', 'a', 't', 'a'); mr = mmioDescend(hmmio, &chunk, &riff, MMIO_FINDCHUNK); } else { mr = MMSYSERR_ERROR; } } if (mr == 0) { if (music) { /* if this is music, store off the streaming info and stop */ sound->IsMusic = TRUE; sound->Stream = (PSTREAMINFO)malloc(sizeof(STREAMINFO)); sound->Stream->Playing = FALSE; sound->Stream->Stream = hmmio; sound->Stream->TotalSize = chunk.cksize; sound->Stream->Riff = riff; sound->Stream->UsedSize = 0; mr = mmioGetInfo(hmmio, &sound->Stream->StreamInfo, 0); } else { /* if this is sound fx, then copy the buffer to the sound object so we can tear off instances */ MMIOINFO info = {0}; DWORD current; DWORD size = chunk.cksize; sound->IsMusic = FALSE; sound->Data = (LPWAVEHDR)malloc(sizeof(WAVEHDR)); ZeroMemory(sound->Data, sizeof(WAVEHDR)); mr = mmioGetInfo(hmmio, &info, 0); sound->Data->lpData = (LPSTR)malloc(size); sound->Data->dwBufferLength = size; for (current = 0; current < size && mr == MMSYSERR_NOERROR; ++current) { if (info.pchNext == info.pchEndRead) { mr = mmioAdvance(hmmio, &info, MMIO_READ); if (mr == MMSYSERR_NOERROR) { mr = (info.pchNext != info.pchEndRead ? MMSYSERR_NOERROR : MMSYSERR_ERROR); } } if (mr == MMSYSERR_NOERROR) { sound->Data->lpData[current] = *info.pchNext; ++info.pchNext; } } } } } if (mr == 0) { if (!music) { mmioClose(hmmio, 0); } return TRUE; } else { /* clean up any stank */ DestroySound(sound); if (hmmio) { mmioClose(hmmio, 0); } return FALSE; } }
//WAVEファイルをロードする int WaveLoader::ReadWaveData(WAVEFORMATEX* wfx, void** pdata, QWORD dwFrom, QWORD dwSizeToRead, bool isLoopWave) { static MMCKINFO parent, child; static char szBefore[MAX_PATH]; _ASSERT(m_FileInfo->name); if(pdata!=NULL) SAFE_GLOBALFREE(*pdata); //if(m_hmmio!=NULL && lstrcmp(m_FileInfo->name, szBefore)!=0){//ファイル名が指定されていたら開きなおす // SAFE_MMIOCLOSE(m_hmmio); //} if( !isLoaded ){ lstrcpy(szBefore, m_FileInfo->name); if( lstrcmp(m_FileInfo->name, CSL_LOAD_MEMORYIMAGE)==0 ){ // if(!m_hmmio){//最初の一回しかしない処理(ストリーミング用の処置) MMIOINFO mmioinfo; zeroMem(&mmioinfo, sizeof(MMIOINFO)); mmioinfo.pchBuffer = (HPSTR)m_FileInfo->pMemBuffer; mmioinfo.fccIOProc = FOURCC_MEM; mmioinfo.cchBuffer = m_FileInfo->fsize; if(NULL == (m_hmmio = mmioOpen(NULL, &mmioinfo, MMIO_READ|MMIO_ALLOCBUF))){ return CSL_E_UNEXP; } }else{ if(NULL == (m_hmmio = mmioOpen((LPSTR)m_FileInfo->name, NULL, MMIO_READ|MMIO_ALLOCBUF))){ return CSL_E_UNEXP; } } parent.fccType = mmioFOURCC('W', 'A', 'V', 'E');//waveファイルかどうか調べる if(mmioDescend(m_hmmio, &parent, NULL, MMIO_FINDRIFF) != MMSYSERR_NOERROR){ SAFE_MMIOCLOSE(m_hmmio); return CSL_E_UNEXP; } child.ckid = mmioFOURCC('f', 'm', 't', ' ');//fmtチャンクへ移動する if(mmioDescend(m_hmmio, &child, &parent, MMIO_FINDCHUNK) != MMSYSERR_NOERROR){ SAFE_MMIOCLOSE(m_hmmio); return CSL_E_UNEXP; } _ASSERT(wfx); if(mmioRead(m_hmmio, (HPSTR)wfx, (LONG)child.cksize) != (LONG)child.cksize){//fmtチャンク(WAVEFORMATEX)読み取り SAFE_MMIOCLOSE(m_hmmio); return CSL_E_UNEXP; } _ASSERT((wfx->wFormatTag==WAVE_FORMAT_PCM)); mmioAscend(m_hmmio, &child, 0);//fmtチャンクから出る child.ckid = mmioFOURCC('d', 'a', 't', 'a');//dataチャンクに移動 if(mmioDescend(m_hmmio, &child, &parent, MMIO_FINDCHUNK) != MMSYSERR_NOERROR) { SAFE_MMIOCLOSE(m_hmmio); return CSL_E_UNEXP; } m_dwDataLength = child.cksize;//WAVE領域のサイズ m_dwOffsetToWaveData = mmioSeek(m_hmmio, 0, SEEK_CUR);//データまでの位置を保存しておく } if(pdata){ if(dwSizeToRead<=0){//ファイル全体を読み込む (*pdata) = (LPBYTE)GlobalAlloc(GPTR, m_dwDataLength * sizeof(BYTE)); _ASSERT(*pdata); if(mmioRead(m_hmmio, (HPSTR)*pdata, (LONG)m_dwDataLength) != (LONG)m_dwDataLength){ GlobalFree(*pdata); SAFE_MMIOCLOSE(m_hmmio); return CSL_E_UNEXP; } SAFE_MMIOCLOSE(m_hmmio); //必要なデータがそろったので、ファイルを閉じる m_dwCurrentDecodedPos += dwSizeToRead; }else{ //DWORD dwInnerFinPos = dwFrom + dwSizeToRead; ////領域サイズ以上だったら収まるように値を補正 //if(m_dwDataLength < dwInnerFinPos){ // dwSizeToRead -= dwInnerFinPos-m_dwDataLength; //} //開始位置が指定されていれば, データ領域からのオフセットをStartとする. //指定されていなければ, それまで進んだカーソル位置から読み込みを開始する if(dwFrom>=0) mmioSeek(m_hmmio, (LONG)(m_dwOffsetToWaveData + dwFrom), SEEK_SET); //要求領域分のメモリ確保 (*pdata) = (LPBYTE)GlobalAlloc(GPTR, (SIZE_T)(dwSizeToRead * sizeof(BYTE))); _ASSERT(*pdata); //現在位置からリクエストサイズを読むとオーバーするようなら、ラップアラウンドする。 DWORD dwNowCursor = mmioSeek(m_hmmio, 0, SEEK_CUR) - m_dwOffsetToWaveData; if(m_dwDataLength < (dwNowCursor + dwSizeToRead)){ if( !isLoopWave ){ if( dwNowCursor>=m_dwDataLength ){ fillMem((BYTE*)*pdata, dwSizeToRead, (m_wfx.wBitsPerSample==8) ? 128:0); return CSL_E_OUTOFRANGE; } } DWORD dwBeforeWrapAround = m_dwDataLength-dwNowCursor; //とりあえず、最後まで読む if(mmioRead(m_hmmio, (HPSTR)*pdata, (LONG)dwBeforeWrapAround) != (LONG)dwBeforeWrapAround){ GlobalFree(*pdata); SAFE_MMIOCLOSE(m_hmmio); return CSL_E_UNEXP; } m_dwCurrentDecodedPos += dwBeforeWrapAround; if(isLoopWave){//残った部分を無音で埋めるかどうか mmioSeek(m_hmmio, 0, SEEK_SET); mmioSeek(m_hmmio, m_dwOffsetToWaveData, SEEK_CUR); //ポインタをWAVE領域始点に戻す //ラップアラウンド分を読む if(mmioRead(m_hmmio, (HPSTR)*pdata+dwBeforeWrapAround, (LONG)(dwSizeToRead - dwBeforeWrapAround)) != (LONG)(dwSizeToRead - dwBeforeWrapAround)){ GlobalFree(*pdata); SAFE_MMIOCLOSE(m_hmmio); return CSL_E_UNEXP; } m_dwCurrentDecodedPos = 0; m_dwCurrentDecodedPos += dwSizeToRead - dwBeforeWrapAround; }else{ fillMem((BYTE*)*pdata+dwBeforeWrapAround, dwSizeToRead - dwBeforeWrapAround, (m_wfx.wBitsPerSample==8) ? 128:0); return CSL_N_FIN; } }else{ //ラップアラウンドしなかった場合 if(mmioRead(m_hmmio, (HPSTR)*pdata, (LONG)dwSizeToRead) != (LONG)dwSizeToRead){ GlobalFree(*pdata); SAFE_MMIOCLOSE(m_hmmio); return CSL_E_UNEXP; } m_dwCurrentDecodedPos += dwSizeToRead; }//必要なデータはまだあるので、ファイルは閉じない } } return CSL_E_OK; }
int WaveCloseWriteFile( HMMIO *phmmioOut, // (IN) MMCKINFO *pckOut, // (IN) MMCKINFO *pckOutRIFF, // (IN) MMIOINFO *pmmioinfoOut, // (IN) DWORD cSamples // (IN) ) { int nError; nError = 0; if (*phmmioOut == NULL) return(0); pmmioinfoOut->dwFlags |= MMIO_DIRTY; if ((nError = mmioSetInfo(*phmmioOut, pmmioinfoOut, 0)) != 0) { // cannot flush, probably... goto ERROR_CANNOT_WRITE; } /* Ascend the output file out of the 'data' chunk -- this will cause * the chunk size of the 'data' chunk to be written. */ if ((nError = mmioAscend(*phmmioOut, pckOut, 0)) != 0) goto ERROR_CANNOT_WRITE; // cannot write file, probably // Do this here instead... if ((nError = mmioAscend(*phmmioOut, pckOutRIFF, 0)) != 0) goto ERROR_CANNOT_WRITE; // cannot write file, probably nError = mmioSeek(*phmmioOut, 0, SEEK_SET); if ((nError = (int)mmioDescend(*phmmioOut, pckOutRIFF, NULL, 0)) != 0) goto ERROR_CANNOT_WRITE; nError = 0; pckOut->ckid = mmioFOURCC('f', 'a', 'c', 't'); if ((nError = mmioDescend(*phmmioOut, pckOut, pckOutRIFF, MMIO_FINDCHUNK)) == 0) { // If it didn't fail, write the fact chunk out, if it failed, not critical, just // assert (below). nError = mmioWrite(*phmmioOut, (HPSTR)&cSamples, sizeof(DWORD)); nError = mmioAscend(*phmmioOut, pckOut, 0); nError = 0; } else { nError = 0; // ASSERT(FALSE); } /* Ascend the output file out of the 'RIFF' chunk -- this will cause * the chunk size of the 'RIFF' chunk to be written. */ if ((nError = mmioAscend(*phmmioOut, pckOutRIFF, 0)) != 0) goto ERROR_CANNOT_WRITE; // cannot write file, probably ERROR_CANNOT_WRITE: if (*phmmioOut != NULL) { mmioClose(*phmmioOut, 0); *phmmioOut = NULL; } return(nError); }
// Only PCM!!!!, no any check __rttype_ struct pcm_s *_open_wave (const char *name) { #ifdef __WINDOWS_ HMMIO mmioHandle; MMCKINFO mmckinfoParent; MMCKINFO mmckinfoSubChunk; struct pcm_s waveHandle; mmioHandle = mmioOpenA((LPSTR)name, NULL, MMIO_ALLOCBUF | MMIO_READ); if (!mmioHandle) return NULL; memset (&mmckinfoParent, 0, sizeof(MMCKINFO)); memset (&mmckinfoSubChunk, 0, sizeof(MMCKINFO)); memset (&waveHandle, 0, sizeof(waveHandle)); mmckinfoParent.fccType = mmioFOURCC('W', 'A', 'V', 'E'); if (MMSYSERR_NOERROR == mmioDescend(mmioHandle, (LPMMCKINFO) & mmckinfoParent, NULL, MMIO_FINDRIFF)) { mmckinfoSubChunk.ckid = mmioFOURCC('f', 'm', 't', ' '); /* Find 'fmt ' chunk */ if (MMSYSERR_NOERROR == mmioDescend(mmioHandle, &mmckinfoSubChunk, &mmckinfoParent, MMIO_FINDCHUNK)) { waveHandle.infos = dlmalloc (mmckinfoSubChunk.cksize); waveHandle.wf_size = mmckinfoSubChunk.cksize; if (NULL != waveHandle.infos) { if (mmckinfoSubChunk.cksize == mmioRead(mmioHandle, (HPSTR)waveHandle.infos, mmckinfoSubChunk.cksize)) { if (MMSYSERR_NOERROR == mmioAscend(mmioHandle, &mmckinfoSubChunk, 0)) { /* Find 'data' chunk */ mmckinfoSubChunk.ckid = mmioFOURCC('d', 'a', 't', 'a'); if (MMSYSERR_NOERROR == mmioDescend(mmioHandle, &mmckinfoSubChunk, &mmckinfoParent, MMIO_FINDCHUNK)) { if (0 != mmckinfoSubChunk.cksize) { waveHandle.snd_buf = dlmalloc (mmckinfoSubChunk.cksize + 176400); if (NULL != waveHandle.snd_buf) { if (-1 != mmioSeek(mmioHandle, mmckinfoSubChunk.dwDataOffset, SEEK_SET)) { if (-1 != mmioRead(mmioHandle, waveHandle.snd_buf, mmckinfoSubChunk.cksize)) { /* Read success !!! */ struct pcm_s *p = dlmalloc (sizeof(struct pcm_s)); if (NULL != p) { mmioClose (mmioHandle, 0); waveHandle.mb_size = mmckinfoSubChunk.cksize; waveHandle.fquad_ = ((float)mmckinfoSubChunk.cksize) / (float)waveHandle.infos->average_rate; waveHandle.quad_ = mmckinfoSubChunk.cksize / waveHandle.infos->average_rate; waveHandle.fsmall_ = fmod((float)mmckinfoSubChunk.cksize, (float)waveHandle.infos->average_rate) / (float)waveHandle.infos->average_rate; waveHandle.small_ = (int)(waveHandle.fsmall_ * (float)60.000); memcpy (p, &waveHandle, sizeof (struct pcm_s)); return p; } } } } } } } } } } } if (NULL != waveHandle.infos) dlfree (waveHandle.infos); if (NULL != waveHandle.snd_buf) dlfree (waveHandle.snd_buf); mmioClose (mmioHandle, 0); return NULL; #else #endif }
int main(int argc, char *argv[]) { // // initial seconds count, set to zero. int seconds = 0; // // Here we say who we are... cout << "WavMix Version 1.1 built " << __DATE__ << " " << __TIME__ << endl; cout << "Application mixes 44.1khz stereo wav files only." << endl; cout << endl; if (argc < 5) { // // cout << endl; cout << " Usage:" << endl; cout << " Provide two source filenames, a target file name, the number of seconds" << endl; cout << " you wish to mix, optional flag to just produce a sample mix, " << endl; cout << " This program REQUIRES MMPM/2 to be installed." << endl; cout << endl; cout << " This application mixes 44.1khz stereo wav files only. It will mix two" << endl; cout << " source wav files and create a target wav file. You set the amount of " << endl; cout << " overlap in seconds. WavMix will mix using the seconds of overlap. A " << endl; cout << " preview mode is provided. Since wave files of this type are extremely " << endl; cout << " large, it will produce a target wav file of just the overlap so you " << endl; cout << " may preview your mixdowns" << endl; cout << endl; cout << endl; cout << " Sample command line" << endl; cout << " [r:\\audio\\mixdown] wavmix track01.wav track02.wav output.wav 5 " << endl; cout << " Above line mixes track01.wav and track02.wav using 5 seconds " << endl; cout << " of overlap creating output.wav" << endl; cout << endl; cout << " [r:\\audio\\mixdown] wavmix track01.wav track02.wav output.wav 5 S" << endl; cout << " Above line mixes 5 seconds of audio from the end of track01.wav and the" << endl; cout << " start of track02.wav creating output.wav" << endl; cout << endl; cout << endl; cout << " Support questions or comments to [email protected]" << endl; cout << "Provide filename1 filename2 destinationfile secondtomix (Longcut)" << endl; return 1; } // // set the type of mix we are going to do. if this is true, we do a full mix, if its // false, we only will do a "sample" of the mix part. short longcut = TRUE; if (argc > 5) { if (strcmp(argv[5],"S")==0) { cout << "Output file will only be the overlap." << endl; longcut = FALSE; } } seconds= atoi(argv[4]); if (seconds == 0) { cout << " ERROR: You cannot set seconds-to-mix to 0. " << endl; return 5; } MMAUDIOHEADER mmAudioHeader,mmAudioHeader2; // // open file1 HMMIO hmmio = mmioOpen(argv[1],NULL,MMIO_READ | MMIO_ALLOCBUF); if (hmmio==0) { cout << "Failed to open file " << argv[1] << endl; return 1; } long BytesRead; int rc = mmioGetHeader(hmmio,(PVOID)&mmAudioHeader,sizeof(MMAUDIOHEADER),&BytesRead,NULL,NULL); if (rc) { cout << "Error on mmioGetHeader for file " << argv[1] << endl; } // // now open the second file HMMIO hmmio2 = mmioOpen(argv[2],NULL,MMIO_READ | MMIO_ALLOCBUF); if (hmmio2==0) { cout << "ERROR: Failed to open file " << argv[2] << endl; return 2; } rc = mmioGetHeader(hmmio2,(PVOID)&mmAudioHeader2,sizeof(MMAUDIOHEADER),&BytesRead,NULL,NULL); if (rc) { cout << "ERROR on mmioGetHeader 2 " << endl; return 3; } // // now we are going to create another wave file MMIOINFO mmioinfo; memset(&mmioinfo,'\0',sizeof(mmioinfo)); mmioinfo.ulTranslate = MMIO_TRANSLATEHEADER+MMIO_TRANSLATEDATA; mmioinfo.aulInfo[3] = MMIO_MEDIATYPE_AUDIO; mmioinfo.fccIOProc = mmioFOURCC('W','A','V','E'); HMMIO hmmioTo = mmioOpen(argv[3],&mmioinfo,MMIO_CREATE+MMIO_WRITE); if (!hmmioTo) { cout << "ERROR : Could not create file." << argv[3] << endl; return 1; } // here we calculate the OFFSET from the back of the file for the 5 second overlay long audiosize = 176400 * seconds; // seconds of audio long filesize1 = mmAudioHeader.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes; long filesize2 = mmAudioHeader2.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes; if (audiosize > filesize1) { cout << "ERROR, you cannot have a mix area that is larger than your source audio file. " << endl; return 1; } if (longcut != TRUE) { // // install the new file size in the buffer mmAudioHeader.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes = audiosize; cout << "Total resulting file size is: " << audiosize << endl; } if (longcut == TRUE) { // // install the new file size in the buffer mmAudioHeader.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes = filesize1 + filesize2; cout << "Total resulting file size is: " << (filesize1 + filesize2) << endl; } // // here we calculate the seekto, not necessary really with longcut long seekto = filesize1 - audiosize; cout << "Attempting to mix " << seconds << " seconds " << endl; // // first we copy the begining of file 1 to destfile if (longcut==TRUE) { cout << "Copying " << seekto << " bytes" << endl; copyaudio(hmmio,hmmioTo,seekto); } // // now seek to the new location in file 1 LONG newPos = mmioSeek(hmmio,seekto,0); assert(newPos == seekto); // // allocate a buffer PSHORT pAudio = NULL; DosAllocMem((void **) &pAudio,audiosize,PAG_WRITE | PAG_COMMIT); // // now read the FIRST file BytesRead = mmioRead(hmmio,(PCHAR)pAudio,audiosize); assert(BytesRead == audiosize); // // now allocate the second buffer PSHORT pAudio2 = NULL; DosAllocMem((void **) &pAudio2,audiosize,PAG_WRITE | PAG_COMMIT); // // and read that in BytesRead = mmioRead(hmmio2,(PCHAR)pAudio2,audiosize); assert(BytesRead == audiosize); // // now ADD them together? long shortsize = audiosize/2; for (unsigned long index = 0; index < shortsize ; index++) { short part1 = *(pAudio+index); short part2 = *(pAudio2+index); short result = part1 + part2; *(pAudio+index) = result; // *(pAudio+index) = *(pAudio2+index) + *(pAudio+index); } // // build the header rc = mmioSetHeader(hmmioTo,&mmAudioHeader,sizeof(MMAUDIOHEADER),&BytesRead,0,0); if (rc) { cout << "Error in mmioSetHeader" << endl; return 1; } // // write the new file rc = mmioWrite(hmmioTo,(PCHAR)pAudio,audiosize); if (rc < 0) { cout << "ERROR during a write" << endl; } // // now, copy the rest of file 2 if (longcut == TRUE) { cout << "Copying " << filesize2 - audiosize << " bytes" << endl; copyaudio(hmmio2,hmmioTo,filesize2 - audiosize); } DosFreeMem(pAudio); DosFreeMem(pAudio2); mmioClose(hmmio,0); mmioClose(hmmio2,0); mmioClose(hmmioTo,0); cout << "Finished, output file created" << endl; }
static void test_mmioDescend(void) { MMRESULT ret; HMMIO hmmio; MMIOINFO mmio; MMCKINFO ckRiff, ckList, ck; memset(&mmio, 0, sizeof(mmio)); mmio.fccIOProc = FOURCC_MEM; mmio.cchBuffer = sizeof(RIFF_buf); mmio.pchBuffer = (char *)&RIFF_buf; /*hmmio = mmioOpen("msrle.avi", NULL, MMIO_READ);*/ hmmio = mmioOpen(NULL, &mmio, MMIO_READ); ok(hmmio != 0, "mmioOpen error %u\n", mmio.wErrorRet); trace("hmmio = %p\n", hmmio); /* first normal RIFF AVI parsing */ ret = mmioDescend(hmmio, &ckRiff, NULL, 0); ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret); ok(ckRiff.ckid == FOURCC_RIFF, "wrong ckid: %04lx\n", ckRiff.ckid); ok(ckRiff.fccType == formtypeAVI, "wrong fccType: %04lx\n", ckRiff.fccType); trace("ckid %4.4s cksize %04lx fccType %4.4s off %04lx flags %04lx\n", (LPCSTR)&ckRiff.ckid, ckRiff.cksize, (LPCSTR)&ckRiff.fccType, ckRiff.dwDataOffset, ckRiff.dwFlags); ret = mmioDescend(hmmio, &ckList, &ckRiff, 0); ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret); ok(ckList.ckid == FOURCC_LIST, "wrong ckid: %04lx\n", ckList.ckid); ok(ckList.fccType == listtypeAVIHEADER, "wrong fccType: %04lx\n", ckList.fccType); trace("ckid %4.4s cksize %04lx fccType %4.4s off %04lx flags %04lx\n", (LPCSTR)&ckList.ckid, ckList.cksize, (LPCSTR)&ckList.fccType, ckList.dwDataOffset, ckList.dwFlags); ret = mmioDescend(hmmio, &ck, &ckList, 0); ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret); ok(ck.ckid == ckidAVIMAINHDR, "wrong ckid: %04lx\n", ck.ckid); ok(ck.fccType == 0, "wrong fccType: %04lx\n", ck.fccType); trace("ckid %4.4s cksize %04lx fccType %4.4s off %04lx flags %04lx\n", (LPCSTR)&ck.ckid, ck.cksize, (LPCSTR)&ck.fccType, ck.dwDataOffset, ck.dwFlags); /* test various mmioDescend flags */ mmioSeek(hmmio, 0, SEEK_SET); memset(&ck, 0x55, sizeof(ck)); ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDRIFF); ok(ret == MMIOERR_CHUNKNOTFOUND || ret == MMIOERR_INVALIDFILE, "mmioDescend returned %u\n", ret); mmioSeek(hmmio, 0, SEEK_SET); memset(&ck, 0x55, sizeof(ck)); ck.ckid = 0; ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDRIFF); ok(ret == MMIOERR_CHUNKNOTFOUND || ret == MMIOERR_INVALIDFILE, "mmioDescend returned %u\n", ret); mmioSeek(hmmio, 0, SEEK_SET); memset(&ck, 0x55, sizeof(ck)); ck.fccType = 0; ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDRIFF); ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret); ok(ck.ckid == FOURCC_RIFF, "wrong ckid: %04lx\n", ck.ckid); ok(ck.fccType == formtypeAVI, "wrong fccType: %04lx\n", ck.fccType); mmioSeek(hmmio, 0, SEEK_SET); memset(&ck, 0x55, sizeof(ck)); ret = mmioDescend(hmmio, &ck, NULL, 0); ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret); ok(ck.ckid == FOURCC_RIFF, "wrong ckid: %04lx\n", ck.ckid); ok(ck.fccType == formtypeAVI, "wrong fccType: %04lx\n", ck.fccType); /* do NOT seek, use current file position */ memset(&ck, 0x55, sizeof(ck)); ck.fccType = 0; ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDLIST); ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret); ok(ck.ckid == FOURCC_LIST, "wrong ckid: %04lx\n", ck.ckid); ok(ck.fccType == listtypeAVIHEADER, "wrong fccType: %04lx\n", ck.fccType); mmioSeek(hmmio, 0, SEEK_SET); memset(&ck, 0x55, sizeof(ck)); ck.ckid = 0; ck.fccType = listtypeAVIHEADER; ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDCHUNK); ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret); ok(ck.ckid == FOURCC_RIFF, "wrong ckid: %04lx\n", ck.ckid); ok(ck.fccType == formtypeAVI, "wrong fccType: %04lx\n", ck.fccType); /* do NOT seek, use current file position */ memset(&ck, 0x55, sizeof(ck)); ck.ckid = FOURCC_LIST; ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDCHUNK); ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret); ok(ck.ckid == FOURCC_LIST, "wrong ckid: %04lx\n", ck.ckid); ok(ck.fccType == listtypeAVIHEADER, "wrong fccType: %04lx\n", ck.fccType); mmioSeek(hmmio, 0, SEEK_SET); memset(&ck, 0x55, sizeof(ck)); ck.ckid = FOURCC_RIFF; ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDCHUNK); ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret); ok(ck.ckid == FOURCC_RIFF, "wrong ckid: %04lx\n", ck.ckid); ok(ck.fccType == formtypeAVI, "wrong fccType: %04lx\n", ck.fccType); /* do NOT seek, use current file position */ memset(&ckList, 0x55, sizeof(ckList)); ckList.ckid = 0; ret = mmioDescend(hmmio, &ckList, &ck, MMIO_FINDCHUNK); ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret); ok(ckList.ckid == FOURCC_LIST, "wrong ckid: %04lx\n", ckList.ckid); ok(ckList.fccType == listtypeAVIHEADER, "wrong fccType: %04lx\n", ckList.fccType); mmioSeek(hmmio, 0, SEEK_SET); memset(&ck, 0x55, sizeof(ck)); ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDCHUNK); ok(ret == MMIOERR_CHUNKNOTFOUND || ret == MMIOERR_INVALIDFILE, "mmioDescend returned %u\n", ret); ok(ck.ckid != 0x55555555, "wrong ckid: %04lx\n", ck.ckid); ok(ck.fccType != 0x55555555, "wrong fccType: %04lx\n", ck.fccType); ok(ck.dwDataOffset != 0x55555555, "wrong dwDataOffset: %04lx\n", ck.dwDataOffset); mmioSeek(hmmio, 0, SEEK_SET); memset(&ck, 0x55, sizeof(ck)); ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDRIFF); ok(ret == MMIOERR_CHUNKNOTFOUND || ret == MMIOERR_INVALIDFILE, "mmioDescend returned %u\n", ret); mmioClose(hmmio, 0); }
BOOL CWaveFile::PrepareWaveFile(LPCTSTR lpszFileName) { if(lpszFileName == NULL || *lpszFileName == _T('\0')) { _stprintf(m_szErrorMsg, _T("Empty file name")); return FALSE; } //The previous opened file is not closed yet if(m_hWaveFile != NULL) { _stprintf(m_szErrorMsg, _T("The previous open file [%s] is not closed yet"), m_szFileName); return FALSE; } _tcscpy(m_szFileName, lpszFileName); //Open wave file m_hWaveFile = mmioOpen(m_szFileName, NULL, MMIO_READ | MMIO_ALLOCBUF); if(m_hWaveFile == NULL) { _stprintf(m_szErrorMsg, _T("mmioOpen file %s failed"), m_szFileName); return FALSE; } //Chunk info structures MMCKINFO ckInfoParent, ckInfo; MMRESULT mmResult = 0; char* fmtBuffer = NULL; LONG lVar; BOOL bRet = FALSE; do { //Find riff wave ckInfoParent.fccType = mmioFOURCC('W', 'A', 'V', 'E'); mmResult = mmioDescend(m_hWaveFile, &ckInfoParent, NULL, MMIO_FINDRIFF); if(mmResult != MMSYSERR_NOERROR) { _stprintf(m_szErrorMsg, _T("mmioDescend find riff wave failed")); break; } //Find chunk "fmt " ckInfo.ckid = mmioFOURCC('f', 'm', 't', ' '); mmResult = mmioDescend(m_hWaveFile, &ckInfo, &ckInfoParent, MMIO_FINDCHUNK); if(mmResult != MMSYSERR_NOERROR) { _stprintf(m_szErrorMsg, _T("mmioDescend find chunk 'fmt ' failed")); break; } //create 'fmt ' buffer fmtBuffer = new char[ckInfo.cksize]; //Read 'fmt ' content lVar = mmioRead(m_hWaveFile, (HPSTR)fmtBuffer, ckInfo.cksize); if( (DWORD)lVar != ckInfo.cksize ) { _stprintf(m_szErrorMsg, _T("mmioRead read 'fmt ' content failed. fmtSize=%d, read=%d"), ckInfo.cksize, lVar); break; } //remember the fmt m_lpWaveFormat = (WAVEFORMATEX*)fmtBuffer; m_dwWaveFormatSize = ckInfo.cksize; //leave chunk 'fmt ' mmResult = mmioAscend(m_hWaveFile, &ckInfo, 0); if(mmResult != MMSYSERR_NOERROR) { _stprintf(m_szErrorMsg, _T("mmioAscend leave 'fmt ' chunk failed. mmResult=%u"), mmResult); break; } //Find chunk 'data' ckInfo.ckid = mmioFOURCC('d', 'a', 't', 'a'); mmResult = mmioDescend(m_hWaveFile, &ckInfo, &ckInfoParent, MMIO_FINDCHUNK); if(mmResult != MMSYSERR_NOERROR) { _stprintf(m_szErrorMsg, _T("mmioDescend find 'data' chunk failed. mmResult=%u"), mmResult); break; } //remember the data chunk info m_ckInfoData = ckInfo; m_dwDataReadCount = 0; //Seek the file position to the chunk 'data' start lVar = mmioSeek(m_hWaveFile, m_ckInfoData.dwDataOffset, SEEK_SET); if((DWORD)lVar != m_ckInfoData.dwDataOffset) { _stprintf(m_szErrorMsg, _T("mmioSeek to chunk 'data' failed. position=%d"), lVar); break; } //everything is ok bRet = TRUE; } while (FALSE); if(!bRet) { if(fmtBuffer != NULL) { delete[] fmtBuffer; fmtBuffer = NULL; } m_lpWaveFormat = NULL; } return bRet; }
/************************************************************************* * Name : PlayTheWave * * Description : This function initially opens the wave file to be played * and tells the MCD information about the file * that is about to be played. The Samples Per Second, * Bits Per Sample, and the number of channels with which * the waveform file was created has to be told to the MCD. * This function initially fills up the allocated buffer * of the playlist with the wave file. For 0 - MAXBUFF * the wave file is filled into the memory. The Wave file * is read in continously from 0 -MAXBUFF. * This same buffer is dynamically re-filled again and again * by the PlayThread thread. * * Concepts : The wave file is first opened and then continuously read * into the buffer. If the end of the wave file is reached * then we seek to the starting of the wave and keep on reading * the wave file till the buffer fills up. This displays the * double buffering concept because, while the playlist is * continuously looping and playing the wave file, the * playlist buffers are constantly being filled with data from * the wave file in the PlayThread thread. * * * * MMPM/2 API's : mmioOpen * mmioGetHeader * mmioRead * mmioSeek * mciSendCommand * MCI_SET * MCI_CUE * * Parameters : None. * * Return : ulReturn * *************************************************************************/ ULONG PlayTheWave() { MCI_WAVE_SET_PARMS lpWaveSet; ULONG ulReturn; MMAUDIOHEADER mmHeader; int i; long ulBytesRead; memset ( &lpWaveSet, 0, sizeof( MCI_WAVE_SET_PARMS ) ); /* Open the Wave File MyWave.Wav for Reading */ hmmioFileHandle = mmioOpen(WAVE_FILE_NAME, (PMMIOINFO) NULL, MMIO_READ); /* If the Wave File could not be opened */ if (!hmmioFileHandle) { ShowAMessage( IDS_ERROR_TITLE, IDS_CANT_OPEN_WAVE, MB_OK | MB_INFORMATION | MB_MOVEABLE | MB_HELP | MB_APPLMODAL, FALSE ); return ( TRUE ); } /* * Get the Header Information for the file so that we can set the channels, * Samples Per Second and Bits Per Sample to play the memory playlist. */ ulReturn = mmioGetHeader(hmmioFileHandle, (PVOID) &mmHeader, sizeof(MMAUDIOHEADER), (PLONG) &ulBytesRead, (ULONG) NULL, (ULONG) NULL); if (ulReturn != 0 ) return ( ulReturn ); /* Set the WaveSet Structure */ lpWaveSet.ulLevel = 100; lpWaveSet.ulSamplesPerSec = mmHeader.mmXWAVHeader.WAVEHeader.ulSamplesPerSec; lpWaveSet.usBitsPerSample = mmHeader.mmXWAVHeader.WAVEHeader.usBitsPerSample; lpWaveSet.usChannels = mmHeader.mmXWAVHeader.WAVEHeader.usChannels; lpWaveSet.ulAudio = MCI_SET_AUDIO_ALL; lpWaveSet.hwndCallback = (HWND) NULL; /* Set the Channels for the MCD */ ulReturn = mciSendCommand(usWaveDeviceId, MCI_SET, MCI_WAIT | MCI_WAVE_SET_CHANNELS, (PVOID) &lpWaveSet, (USHORT)NULL); if (ulReturn != 0 ) return ( ulReturn ); /* Set the Samples Per Second */ ulReturn = mciSendCommand(usWaveDeviceId, MCI_SET, MCI_WAIT | MCI_WAVE_SET_SAMPLESPERSEC, (PVOID) &lpWaveSet, (USHORT)NULL); if (ulReturn != 0 ) return ( ulReturn ); /* Set the Bits per Sample */ ulReturn = mciSendCommand(usWaveDeviceId, MCI_SET, MCI_WAIT | MCI_WAVE_SET_BITSPERSAMPLE, (PVOID) &lpWaveSet, (USHORT)NULL); if (ulReturn != 0 ) return ( ulReturn ); /* From 0 - MAXBUFF, fill the memory Playlist buffer with the wave file. */ for (i=0; i<MAXBUFF; i++) { ulBytesRead = mmioRead(hmmioFileHandle, (HPSTR) achDataBuffer[i], MAXSIZE); /* * If the end of the wave file is reached then Seek to the starting * of the wave file and start reading the wave into the appropriate * buffer */ if (ulBytesRead < MAXSIZE) { mmioSeek(hmmioFileHandle, 0, SEEK_SET); ulBytesRead = mmioRead(hmmioFileHandle, (HPSTR) achDataBuffer[i], MAXSIZE); } } /* * Create the thread that will maintain the playlist buffer */ fEndPlay = FALSE; if ( DosCreateThread ( &tidPlayThread, (PFNTHREAD) PlayThread, 0L, 0L, 8192L)) return ( TRUE ); return ( FALSE ); }
VOID APIENTRY PlayThread ( ULONG parm1 ) { ULONG ulBytesRead; ULONG ulBufferNum; ULONG ulPostCount; ULONG ulReturn; MCI_PLAY_PARMS mciPlayParameters; mciPlayParameters.hwndCallback = hwndDiag; /* * Send the Play Command to begin the playing of the memory playlist. */ ulReturn = mciSendCommand(usWaveDeviceId, MCI_PLAY, MCI_NOTIFY, (PVOID) &mciPlayParameters, 0); /* * Loop until the playlist is stopped. */ while( !fEndPlay ) { for( ulBufferNum = 0; ulBufferNum < MAXBUFF; ulBufferNum++ ) { /* * Use DosWaitEventSem to pause util the playlist plays this * buffer. Then refill the buffer and post the semaphore. */ ulReturn = DosWaitEventSem ( hevSem[ulBufferNum], 5000L ); DosResetEventSem ( hevSem[ulBufferNum], &ulPostCount ); if( fEndPlay ) break; /* * Read the Next MAXSIZE bytes of the wave file */ ulBytesRead = mmioRead(hmmioFileHandle, (HPSTR) achDataBuffer[ulBufferNum], MAXSIZE); /* * If we have reached the end of the wave file then set the file marker * to the begining of the file and start reading into the bufferno. * This causes the continuous filling and playing of the data buffer * again and again as long as the END push button is not pressed. * The wave file is going to keep on playing without any interruptions * util ther user selects the stop button. */ if (ulBytesRead < MAXSIZE) { /* Seek to the starting of the wave file */ mmioSeek(hmmioFileHandle, 0, SEEK_SET); /* Read the Next MAXSIZE bytes of the wave file */ mmioRead(hmmioFileHandle, (HPSTR) achDataBuffer[ulBufferNum], MAXSIZE); } } /* End of for loop */ } /* End of while loop */ } /* End of function PlayThread */
LONG APIENTRY CONVProc( PVOID pmmioStr, USHORT usMsg, LONG lParam1, LONG lParam2 ) { PCONVPROCINFO pInfo; // Converter I/O Procedure Info Block PMMIOINFO pmmioinfo; // I/O information block MMIOINFO mmioinfoSS; // I/O info block for Storage System PMMFORMATINFO pmmformatinfo; // formatinfo for this ioproc. PCONVHEADERINFO pconvHeaderInfo; // pointer to header struct for FFT files. PSZ pszFileName; // file name passed in from caller PSZ pszFormatString; // format string to return. PSZ pszData; CHAR szHeaderLength[2]; // storage for header length (USHORT) PCHAR pTemp; // temp pointer for use in Header manip. HFILE hFileHandle; // file handle created or passed in HMMIO hmmioSS; // handle for Storage System FOURCC fccStorageSystem; // SS I/O Proc FOURCC USHORT usReturnCode; // return code from mmioClose ULONG ulReturnCode; // return code from mmio API calls LONG lReturnCode; // return code from mmio API calls LONG lBytesCopied; // num of bytes of format string. LONG lBytesRead; // return from mmioRead LONG lBytesWritten; // return from mmioWrite LONG lHeaderLength; // storage for CONV header length input LONG lFilePosition; // return from mmioSeek LONG lSavedFilePosition; // saved LFP for the file. ULONG ulTempFlags; // temp flags for flags to be removed. /* * Initalize local file handle and Return Codes. */ hFileHandle = 0L; ulReturnCode = 0L; usReturnCode = 0; /* * Clear the error return before anything happens to insure valid results. */ if (pmmioStr) { pmmioinfo = (PMMIOINFO) pmmioStr; pInfo = (PCONVPROCINFO) &pmmioinfo->aulInfo; pmmioinfo->ulErrorRet = MMIO_SUCCESS; } else { pmmioinfo = NULL; pInfo = NULL; } /* * Route the MMIO message to the proper code handler. */ switch( usMsg ) { case MMIOM_OPEN: /* * Get the filename from parameter. Then create a File Format header * in memory since this message will use this structure. */ pszFileName = (CHAR *)lParam1; pconvHeaderInfo = (PCONVHEADERINFO)HhpAllocBuffer( sizeof(CONVHEADERINFO), 0); if (!pconvHeaderInfo) { return (MMIO_ERROR); } /* * If no Storage System I/O proc was determined from mmioOpen, * either determine the SS from the name (CREATE case) or * search I/O proc list for SS type. If the file is being created * and the storage system cannot be determined from the name, * default the storage system to DOS. */ if (!pmmioinfo->fccChildIOProc) { /* * Since no Storage system has been determined from mmioOpen, we * need to determine the Storage system from the filename. If * it cannot be determined from the name, since it's a create we * will default the storage system to DOS. */ if (pmmioinfo->ulFlags & MMIO_CREATE) { if (mmioDetermineSSIOProc( pszFileName, pmmioinfo, &fccStorageSystem, NULL )) { fccStorageSystem = FOURCC_DOS; } } else { /* * The file already exists, so we need to determine the storage * system by looping through all the SS I/O procs until the SS * is determined or it is not. If it is not then this file * cannot be opened, so return an error. */ if (mmioIdentifyStorageSystem( pszFileName, pmmioinfo, &fccStorageSystem )) { return (MMIO_ERROR); } } /* * Now we either have a SS, and if so assign it to the SS I/O * proc field of the pmmioinfo sent in, or we don't so return. */ if (!fccStorageSystem) { return (MMIO_ERROR); } else { pmmioinfo->fccChildIOProc = fccStorageSystem; } } /* * We have the Storage System FOURCC so open the SS. * To set up the mmioOpen call to the storage system : * * 1. Initialize the mmioinfo passed in for the Storage System. * 2. Set fccIOProc to the Storage System FOURCC. * 3. Save the hmmcf handle in aulInfo[1] if sent in. * 4. IMPORTANT: Use flags sent in EXCEPT Buffered I/O flags. * VERY IMPORTANT: Set the NOIDENTIFY flag before calling the * mmioOpen below to avoid and endless loop. * 5. The open call will handle the DELETE flag. * 6. Use the name passed in to this I/O proc for the open because * at this point the SS I/O proc will know how to deal with it. */ memset( &mmioinfoSS, '\0', sizeof(MMIOINFO)); mmioinfoSS.fccIOProc = pmmioinfo->fccChildIOProc; memmove( &mmioinfoSS.aulInfo, pmmioinfo->aulInfo,(4*sizeof(ULONG))); mmioinfoSS.ulFlags = pmmioinfo->ulFlags; ulTempFlags = (MMIO_CREATE|MMIO_READ|MMIO_WRITE|MMIO_READWRITE| MMIO_COMPAT|MMIO_EXCLUSIVE|MMIO_DENYWRITE| MMIO_DENYREAD|MMIO_DENYNONE|MMIO_DELETE|MMIO_VERTBAR| MMIO_APPEND|MMIO_USE_TEMP|MMIO_RWMODE|MMIO_SHAREMODE| MMIO_NOTRANSLATE|MMIO_TRANSLATEDATA| MMIO_TRANSLATEHEADER); mmioinfoSS.ulFlags &= ulTempFlags; mmioinfoSS.ulFlags |= MMIO_NOIDENTIFY; hmmioSS = mmioOpen( pszFileName, &mmioinfoSS, mmioinfoSS.ulFlags ); if (hmmioSS) { /* * Handle a DELETE request for the file format by returning * success if ( hmmio = TRUE = 1). */ if (pmmioinfo->ulFlags & MMIO_DELETE) { return (MMIO_SUCCESS); } pInfo->hmmioSS = hmmioSS; } else { return (mmioinfoSS.ulErrorRet); } /* * Get the header for the file if it already exists and * store it with the MMIOINFO for the file. */ if (!(pmmioinfo->ulFlags & MMIO_CREATE)) { /* * Seek the file to the beginning to read in the header. */ lFilePosition = mmioSeek( hmmioSS, 0L, SEEK_SET ); if (lFilePosition < 0L) { mmioClose( hmmioSS, 0L ); return (MMIO_ERROR); } /* * Read the header of the file into the provided buffer for the * given length. */ lBytesRead = mmioRead( hmmioSS, (PSZ)pconvHeaderInfo, sizeof(CONVHEADERINFO) ); if (lBytesRead < 0L) { mmioClose( hmmioSS, 0L ); return (MMIO_ERROR); } } else { /* * Make a new header for the file and write it to the beginning. */ pconvHeaderInfo->ulHeaderLength = sizeof(CONVHEADERINFO); strcpy( pconvHeaderInfo->szHeaderText, HEADER_STRING ); lFilePosition = mmioSeek( hmmioSS, 0L, SEEK_SET ); if (lFilePosition < 0L) { mmioClose( hmmioSS, 0L ); return (MMIO_ERROR); } /* * Write the newly created header to the file. */ lBytesWritten = mmioWrite( hmmioSS, (PSZ)pconvHeaderInfo, sizeof(CONVHEADERINFO) ); if (lBytesWritten < 0L) { mmioClose( hmmioSS, 0L ); return (MMIO_ERROR); } } pconvHeaderInfo->ulFlags = 0; pmmioinfo->pExtraInfoStruct = (PVOID)pconvHeaderInfo; /* * Seek the file past the header to allow reads/writes to occur * at the first byte of non-header data if the file already exists. */ lReturnCode = mmioSeek( hmmioSS, sizeof(CONVHEADERINFO), SEEK_SET ); if (lReturnCode >= 0L) { pmmioinfo->lLogicalFilePos = lReturnCode; } else { mmioClose( hmmioSS, 0L ); return (lReturnCode); } return (0L); break; case MMIOM_READ: /* * Call the read API with the Storage System handle using the * parameters that have been passed in to this I/O proc. */ lBytesRead = mmioRead( pInfo->hmmioSS, (CHAR *) lParam1, lParam2 ); /* * Check the return code and determine if read was successful. * Read must return: * -1 - an error occurred with mmioRead or somewhere internally. * x - number of bytes actually read by mmioRead. */ if ( lBytesRead < 0L ) { return( -1L ); } else { return( lBytesRead ); } break; case MMIOM_WRITE: /* * Call the write API with the Storage System handle using the * parameters that have been passed in to this I/O proc. */ lBytesWritten = mmioWrite( pInfo->hmmioSS, (CHAR *) lParam1, lParam2 ); /* * Check the return code and determine if write was successful. * Write must return: * -1 - an error occurred with mmioWrite or somewhere internally. * x - number of bytes actually written by mmioWrite. */ if ( lBytesWritten < 0L ) { return( -1L ); } else if ( lBytesWritten != lParam2 ) { pmmioinfo->ulErrorRet = MMIOERR_CANNOTWRITE; return( lBytesWritten ); } else { /* * Set the Flags field in the CONV header to show it was modified. */ pconvHeaderInfo = (PCONVHEADERINFO)pmmioinfo->pExtraInfoStruct; if (pconvHeaderInfo) pconvHeaderInfo->ulFlags = CONV_MODIFIED_FILE; return( lBytesWritten ); } break; case MMIOM_SEEK: /* * Call the seek API with the Storage System handle using the * parameters that have been passed in to this I/O proc. */ lReturnCode = mmioSeek( pInfo->hmmioSS, lParam1, lParam2 ); /* * Check the return code and determine if seek was successful. * Seek must return: * -1 - an error occurred with mmioSeek or somewhere internally. * x - new current file postion from the beginning of the file. */ if ( lReturnCode < 0L ) { return( -1L ); } return( lReturnCode ); break; case MMIOM_CLOSE: /* * If the CONV header structure was maintained in pExtraInfoStruct, * write it back to the beginning of the file. */ if (((pmmioinfo->ulFlags & MMIO_WRITE) || (pmmioinfo->ulFlags & MMIO_READWRITE)) && (pmmioinfo->pExtraInfoStruct)) { pconvHeaderInfo = (PCONVHEADERINFO)pmmioinfo->pExtraInfoStruct; lReturnCode = mmioSeek( pInfo->hmmioSS, 0L, SEEK_SET ); if (lReturnCode < 0L) { return (lReturnCode); } ulReturnCode = mmioSetHeader( pmmioinfo->hmmio, (PVOID)pmmioinfo->pExtraInfoStruct, sizeof(CONVHEADERINFO), &lBytesWritten, 0L, 0L ); if (ulReturnCode) { return (ulReturnCode); } } if (pmmioinfo->pExtraInfoStruct) HhpFreeBuffer((PBYTE)pmmioinfo->pExtraInfoStruct); /* * Call the close API with the Storage System handle using any * parameters that have been passed in to this I/O proc. */ usReturnCode = mmioClose( pInfo->hmmioSS, 0L ); return ((ULONG)usReturnCode); break; case MMIOM_IDENTIFYFILE: /* * Get the filename from parameter. Then create a File Format header * in memory since this message use this structure. */ pszFileName = (CHAR *)lParam1; // get the filename from parameter. pconvHeaderInfo = (PCONVHEADERINFO)HhpAllocBuffer( sizeof(CONVHEADERINFO), 0); if (!pconvHeaderInfo) { return (MMIO_ERROR); } hmmioSS = (HMMIO)lParam2; // get the SS handle to the file. if ( !hmmioSS ) { HhpFreeBuffer((PBYTE)pconvHeaderInfo); return (MMIO_ERROR); } else { /* * Seek the file to the beginning to read in the file header. */ lFilePosition = mmioSeek( hmmioSS, 0L, SEEK_SET ); if (lFilePosition < 0L) { HhpFreeBuffer((PBYTE)pconvHeaderInfo); return (MMIO_ERROR); } /* * Compare convHeaderInfo.szHeaderText with text string defined * in the convproc.h header file. */ lBytesRead = mmioRead( hmmioSS, (PSZ)pconvHeaderInfo, sizeof(CONVHEADERINFO) ); if ( lBytesRead <= 0L ) { HhpFreeBuffer((PBYTE)pconvHeaderInfo); return( -1L ); } pTemp = (CHAR *)pconvHeaderInfo; pTemp += 2 * sizeof(ULONG); if (!strncmp( pTemp, HEADER_STRING, strlen(HEADER_STRING) )) { HhpFreeBuffer((PBYTE)pconvHeaderInfo); return( 0L ); } else { HhpFreeBuffer((PBYTE)pconvHeaderInfo); return( -1L ); } } break; case MMIOM_GETFORMATINFO: /* * Fill in the mmformatinfo for the CONVProc. */ pmmformatinfo = (PMMFORMATINFO)lParam1; if (pmmformatinfo == NULL) { return( -1L ); } pmmformatinfo->ulStructLen = sizeof(MMFORMATINFO); pmmformatinfo->fccIOProc = FOURCC_FFT; pmmformatinfo->ulIOProcType = MMIO_IOPROC_FILEFORMAT; pmmformatinfo->ulMediaType = MMIO_MEDIATYPE_OTHER; pmmformatinfo->ulFlags = MMIO_CANREADUNTRANSLATED | MMIO_CANWRITEUNTRANSLATED | MMIO_CANREADWRITEUNTRANSLATED | MMIO_CANSEEKUNTRANSLATED; memset( pmmformatinfo->szDefaultFormatExt, '\0', sizeof(pmmformatinfo->szDefaultFormatExt) ); strcpy( pmmformatinfo->szDefaultFormatExt, "FFT" ); if (convhlpGetNLSData( &pmmformatinfo->ulCodePage, &pmmformatinfo->ulLanguage )) { return( -1L ); } if (convhlpGetFormatStringLength( FOURCC_FFT, &(pmmformatinfo->lNameLength) )) { return( -1L ); } return( 0L ); break; case MMIOM_GETFORMATNAME: /* * The string is in a resource file (CONVPROC.RC) for NLS purposes. */ pszFormatString = (CHAR *)lParam1; lBytesCopied = convhlpGetFormatString( FOURCC_FFT, pszFormatString, lParam2 ); return( lBytesCopied ); break; case MMIOM_QUERYHEADERLENGTH: /* * Save current file position for later restore. Then * seek the file to the beginning to read in the header. */ lSavedFilePosition = pmmioinfo->lLogicalFilePos; lFilePosition = mmioSeek( pInfo->hmmioSS, 0L, SEEK_SET ); if (lFilePosition < 0L) { return (0L); } /* * Read in the header length for the file. It is the first 4 bytes. */ lBytesRead = mmioRead( pInfo->hmmioSS, szHeaderLength, sizeof(ULONG) ); lReturnCode = mmioSeek( pInfo->hmmioSS, lSavedFilePosition, SEEK_SET ); if (lReturnCode != lSavedFilePosition) { return (0L); } if (lBytesRead <= 0L) { return (0L); } else { lHeaderLength = (LONG)(*((LONG *)szHeaderLength)); return (lHeaderLength); } break; case MMIOM_GETHEADER: /* * Save current file position for later restore. Then * seek the file to the beginning to read in the header. */ lSavedFilePosition = pmmioinfo->lLogicalFilePos; lFilePosition = mmioSeek( pInfo->hmmioSS, 0L, SEEK_SET ); if (lFilePosition < 0L) { return (0L); } /* * Read the header of the file into the provided buffer for the * given length. Then seek the file back to the saved position. */ lBytesRead = mmioRead( pInfo->hmmioSS, (CHAR *)lParam1, lParam2 ); lReturnCode = mmioSeek( pInfo->hmmioSS, lSavedFilePosition, SEEK_SET ); if (lReturnCode != lSavedFilePosition) { return (0L); } if (lBytesRead <= 0L) { return (0L); } else { return (lBytesRead); } break; case MMIOM_SETHEADER: /* * Save current file position for later restore. Then * seek the file to the beginning to read in the header. */ lSavedFilePosition = pmmioinfo->lLogicalFilePos; lFilePosition = mmioSeek( pInfo->hmmioSS, 0L, SEEK_SET ); if (lFilePosition < 0L) { return (0L); } /* * Write the entire header to the file. Then seek the file back * to the saved file position. */ lBytesWritten = mmioWrite( pInfo->hmmioSS, (CHAR *)lParam1, lParam2 ); lReturnCode = mmioSeek( pInfo->hmmioSS, lSavedFilePosition, SEEK_SET ); if (lReturnCode != lSavedFilePosition) { return (0L); } if (lBytesWritten <= 0L) { return (0L); } else { return (lBytesWritten); } break; case CONVM_TOUPPER: pszData = (CHAR *)lParam1; convhlpToUpper( (PUCHAR)pszData ); return (MMIO_SUCCESS); break; case CONVM_TOLOWER: pszData = (CHAR *)lParam1; convhlpToLower( (PUCHAR)pszData ); return (MMIO_SUCCESS); break; default: /* * If an IO Proc has a child IO Proc, then instead of * returning UNSUPPORTED_MESSAGE, send the message to * the child IO Proc to see if it can understand and * process the message. * * Since message is unexpected, need to check for valid * pointers. */ if (pInfo) { if (pInfo->hmmioSS) { lReturnCode = ( mmioSendMessage( pInfo->hmmioSS, usMsg, lParam1, lParam2 )); if (!lReturnCode) pmmioinfo->ulErrorRet = mmioGetLastError(pInfo->hmmioSS); return (lReturnCode); } } else { if (pmmioinfo) pmmioinfo->ulErrorRet = MMIOERR_UNSUPPORTED_MESSAGE; } return (MMIOERR_UNSUPPORTED_MESSAGE); } }
int main(int argc, char* argv[]) { // LPWSTR szFileName;//声音文件名 MMCKINFO mmckinfoParent; MMCKINFO mmckinfoSubChunk; DWORD dwFmtSize; HMMIO m_hmmio;//音频文件句柄 DWORD m_WaveLong; HPSTR lpData;//音频数据 HANDLE m_hData=NULL; HANDLE m_hFormat; WAVEFORMATEX * lpFormat; DWORD m_dwDataOffset; DWORD m_dwDataSize; WAVEHDR pWaveOutHdr; WAVEOUTCAPS pwoc; HWAVEOUT hWaveOut; int SoundOffset=0; int SoundLong=0; int DevsNum; //打开波形文件 if(!(m_hmmio=mmioOpen(argv[1],NULL,MMIO_READ|MMIO_ALLOCBUF))) { //File open Error printf("Failed to open the file.");//错误处理函数 return false; } //检查打开文件是否是声音文件 mmckinfoParent.fccType =mmioFOURCC('W','A','V','E'); if(mmioDescend(m_hmmio,(LPMMCKINFO)&mmckinfoParent,NULL,MMIO_FINDRIFF)) { printf("NOT WAVE FILE AND QUIT"); return 0; } //寻找 'fmt' 块 mmckinfoSubChunk.ckid =mmioFOURCC('f','m','t',' '); if(mmioDescend(m_hmmio,&mmckinfoSubChunk,&mmckinfoParent,MMIO_FINDCHUNK)) { printf("Can't find 'fmt' chunk"); return 0; } //获得 'fmt '块的大小,申请内存 dwFmtSize=mmckinfoSubChunk.cksize ; m_hFormat=LocalAlloc(LMEM_MOVEABLE,LOWORD(dwFmtSize)); if(!m_hFormat) { printf("failed alloc memory"); return 0; } lpFormat=(WAVEFORMATEX*)LocalLock(m_hFormat); if(!lpFormat) { printf("failed to lock the memory"); return 0; } if((unsigned long)mmioRead(m_hmmio,(HPSTR)lpFormat,dwFmtSize)!=dwFmtSize) { printf("failed to read format chunk"); return 0; } //离开 fmt 块 mmioAscend(m_hmmio,&mmckinfoSubChunk,0); //寻找 'data' 块 mmckinfoSubChunk.ckid=mmioFOURCC('d','a','t','a'); if(mmioDescend(m_hmmio,&mmckinfoSubChunk,&mmckinfoParent,MMIO_FINDCHUNK)) { printf("Can't find 'data' chunk"); return 0; } //获得 'data'块的大小 m_dwDataSize=mmckinfoSubChunk.cksize ; m_dwDataOffset =mmckinfoSubChunk.dwDataOffset ; if(m_dwDataSize==0L) { printf("no data in the 'data' chunk"); return 0; } //为音频数据分配内存 lpData=new char[m_dwDataSize]; if(!lpData) { printf("\ncan not alloc mem"); return 0; } if(mmioSeek(m_hmmio,m_dwDataOffset,SEEK_SET)<0) { printf("Failed to read the data chunk"); return 0; } // m_WaveLong=mmioRead(m_hmmio,lpData,SoundLong); m_WaveLong=mmioRead(m_hmmio,lpData,m_dwDataSize); if(m_WaveLong<0) { printf("Failed to read the data chunk"); return 0; } //检查音频设备,返回音频输出设备的性能 if(waveOutGetDevCaps(WAVE_MAPPER,&pwoc,sizeof(WAVEOUTCAPS))!=0) { printf("Unable to allocate or lock memory"); return 0; } //检查音频输出设备是否能播放指定的音频文件 DevsNum = WAVE_MAPPER; if(waveOutOpen(&hWaveOut,DevsNum,lpFormat,NULL,NULL,CALLBACK_NULL)!=0) { printf("Failed to OPEN the wave out devices"); // return 0; } //准备待播放的数据 pWaveOutHdr.lpData =(HPSTR)lpData; pWaveOutHdr.dwBufferLength =m_WaveLong; pWaveOutHdr.dwFlags =0; pWaveOutHdr.dwLoops = 10; if(waveOutPrepareHeader(hWaveOut,&pWaveOutHdr,sizeof(WAVEHDR))!=0) { printf("Failed to prepare the wave data buffer"); return 0; } printFlags(pWaveOutHdr.dwFlags, "after [waveOutPrepareHeader]"); pWaveOutHdr.dwFlags |= (WHDR_BEGINLOOP | WHDR_ENDLOOP); //播放音频数据文件 if(waveOutWrite(hWaveOut,&pWaveOutHdr,sizeof(WAVEHDR))!=0) { printf("Failed to write the wave data buffer"); return 0; } printFlags(pWaveOutHdr.dwFlags, "after [waveOutWrite]"); //关闭音频输出设备,释放内存 // printf("\npress any key"); // getchar(); Sleep(20000); printFlags(pWaveOutHdr.dwFlags, "after [Sleep]"); if(waveOutUnprepareHeader(hWaveOut, &pWaveOutHdr, sizeof(pWaveOutHdr)) != 0) { printf("Failed to unPrepare the wave data buffer"); return 0; } printFlags(pWaveOutHdr.dwFlags, "after [waveOutUnprepareHeader]"); waveOutReset(hWaveOut); printFlags(pWaveOutHdr.dwFlags, "after [waveOutReset]"); waveOutClose(hWaveOut); printFlags(pWaveOutHdr.dwFlags, "after [waveOutClose]"); LocalUnlock(m_hFormat); LocalFree(m_hFormat); delete [] lpData; return 0; }
static DWORD WINAPI proc_PlaySound(LPVOID arg) { WINE_PLAYSOUND* wps = arg; BOOL bRet = FALSE; HMMIO hmmio = 0; MMCKINFO ckMainRIFF; MMCKINFO mmckInfo; LPWAVEFORMATEX lpWaveFormat = NULL; HWAVEOUT hWave = 0; LPWAVEHDR waveHdr = NULL; INT count, bufsize, left, index; struct playsound_data s; void* data; s.hEvent = 0; TRACE("SoundName=%s !\n", debugstr_w(wps->pszSound)); /* if resource, grab it */ if ((wps->fdwSound & SND_RESOURCE) == SND_RESOURCE) { static const WCHAR wszWave[] = {'W','A','V','E',0}; HRSRC hRes; HGLOBAL hGlob; if ((hRes = FindResourceW(wps->hMod, wps->pszSound, wszWave)) == 0 || (hGlob = LoadResource(wps->hMod, hRes)) == 0) goto errCleanUp; if ((data = LockResource(hGlob)) == NULL) { FreeResource(hGlob); goto errCleanUp; } FreeResource(hGlob); } else data = (void*)wps->pszSound; /* construct an MMIO stream (either in memory, or from a file */ if (wps->fdwSound & SND_MEMORY) { /* NOTE: SND_RESOURCE has the SND_MEMORY bit set */ MMIOINFO mminfo; memset(&mminfo, 0, sizeof(mminfo)); mminfo.fccIOProc = FOURCC_MEM; mminfo.pchBuffer = data; mminfo.cchBuffer = -1; /* FIXME: when a resource, could grab real size */ TRACE("Memory sound %p\n", data); hmmio = mmioOpenW(NULL, &mminfo, MMIO_READ); } if (!hmmio && wps->fdwSound & SND_ALIAS) { if ((wps->fdwSound & SND_ALIAS_ID) == SND_ALIAS_ID) { static const WCHAR wszSystemAsterisk[] = {'S','y','s','t','e','m','A','s','t','e','r','i','s','k',0}; static const WCHAR wszSystemDefault[] = {'S','y','s','t','e','m','D','e','f','a','u','l','t',0}; static const WCHAR wszSystemExclamation[] = {'S','y','s','t','e','m','E','x','c','l','a','m','a','t','i','o','n',0}; static const WCHAR wszSystemExit[] = {'S','y','s','t','e','m','E','x','i','t',0}; static const WCHAR wszSystemHand[] = {'S','y','s','t','e','m','H','a','n','d',0}; static const WCHAR wszSystemQuestion[] = {'S','y','s','t','e','m','Q','u','e','s','t','i','o','n',0}; static const WCHAR wszSystemStart[] = {'S','y','s','t','e','m','S','t','a','r','t',0}; static const WCHAR wszSystemWelcome[] = {'S','y','s','t','e','m','W','e','l','c','o','m','e',0}; wps->fdwSound &= ~(SND_ALIAS_ID ^ SND_ALIAS); if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMASTERISK) wps->pszSound = wszSystemAsterisk; else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMDEFAULT) wps->pszSound = wszSystemDefault; else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMEXCLAMATION) wps->pszSound = wszSystemExclamation; else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMEXIT) wps->pszSound = wszSystemExit; else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMHAND) wps->pszSound = wszSystemHand; else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMQUESTION) wps->pszSound = wszSystemQuestion; else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMSTART) wps->pszSound = wszSystemStart; else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMWELCOME) wps->pszSound = wszSystemWelcome; else goto errCleanUp; } hmmio = get_mmioFromProfile(wps->fdwSound, wps->pszSound); if (!hmmio) { wps->fdwSound &= ~SND_ALIAS; wps->fdwSound |= SND_FILENAME; } } if (!hmmio && wps->fdwSound & SND_FILENAME) { hmmio = get_mmioFromFile(wps->pszSound); } if (!(wps->fdwSound & (SND_FILENAME|SND_ALIAS|SND_MEMORY))) { if ((hmmio = get_mmioFromProfile(wps->fdwSound | SND_NODEFAULT, wps->pszSound)) == 0) { if ((hmmio = get_mmioFromFile(wps->pszSound)) == 0) { hmmio = get_mmioFromProfile(wps->fdwSound, wps->pszSound); } } } if (hmmio == 0) goto errCleanUp; if (mmioDescend(hmmio, &ckMainRIFF, NULL, 0)) goto errCleanUp; TRACE("ParentChunk ckid=%.4s fccType=%.4s cksize=%08X\n", (LPSTR)&ckMainRIFF.ckid, (LPSTR)&ckMainRIFF.fccType, ckMainRIFF.cksize); if ((ckMainRIFF.ckid != FOURCC_RIFF) || (ckMainRIFF.fccType != mmioFOURCC('W', 'A', 'V', 'E'))) goto errCleanUp; mmckInfo.ckid = mmioFOURCC('f', 'm', 't', ' '); if (mmioDescend(hmmio, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK)) goto errCleanUp; TRACE("Chunk Found ckid=%.4s fccType=%08x cksize=%08X\n", (LPSTR)&mmckInfo.ckid, mmckInfo.fccType, mmckInfo.cksize); lpWaveFormat = HeapAlloc(GetProcessHeap(), 0, mmckInfo.cksize); if (!lpWaveFormat) goto errCleanUp; if (mmioRead(hmmio, (HPSTR)lpWaveFormat, mmckInfo.cksize) < sizeof(PCMWAVEFORMAT)) goto errCleanUp; TRACE("wFormatTag=%04X !\n", lpWaveFormat->wFormatTag); TRACE("nChannels=%d\n", lpWaveFormat->nChannels); TRACE("nSamplesPerSec=%d\n", lpWaveFormat->nSamplesPerSec); TRACE("nAvgBytesPerSec=%d\n", lpWaveFormat->nAvgBytesPerSec); TRACE("nBlockAlign=%d\n", lpWaveFormat->nBlockAlign); TRACE("wBitsPerSample=%u !\n", lpWaveFormat->wBitsPerSample); /* move to end of 'fmt ' chunk */ mmioAscend(hmmio, &mmckInfo, 0); mmckInfo.ckid = mmioFOURCC('d', 'a', 't', 'a'); if (mmioDescend(hmmio, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK)) goto errCleanUp; TRACE("Chunk Found ckid=%.4s fccType=%08x cksize=%08X\n", (LPSTR)&mmckInfo.ckid, mmckInfo.fccType, mmckInfo.cksize); s.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); if (!s.hEvent || bPlaySoundStop) goto errCleanUp; if (waveOutOpen(&hWave, WAVE_MAPPER, lpWaveFormat, (DWORD_PTR)PlaySound_Callback, (DWORD_PTR)&s, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) goto errCleanUp; /* make it so that 3 buffers per second are needed */ bufsize = (((lpWaveFormat->nAvgBytesPerSec / 3) - 1) / lpWaveFormat->nBlockAlign + 1) * lpWaveFormat->nBlockAlign; waveHdr = HeapAlloc(GetProcessHeap(), 0, 2 * sizeof(WAVEHDR) + 2 * bufsize); if (!waveHdr) goto errCleanUp; waveHdr[0].lpData = (char*)waveHdr + 2 * sizeof(WAVEHDR); waveHdr[1].lpData = (char*)waveHdr + 2 * sizeof(WAVEHDR) + bufsize; waveHdr[0].dwUser = waveHdr[1].dwUser = 0L; waveHdr[0].dwLoops = waveHdr[1].dwLoops = 0L; waveHdr[0].dwFlags = waveHdr[1].dwFlags = 0L; waveHdr[0].dwBufferLength = waveHdr[1].dwBufferLength = bufsize; if (waveOutPrepareHeader(hWave, &waveHdr[0], sizeof(WAVEHDR)) || waveOutPrepareHeader(hWave, &waveHdr[1], sizeof(WAVEHDR))) { goto errCleanUp; } wps->hWave = hWave; s.dwEventCount = 1L; /* for first buffer */ index = 0; do { left = mmckInfo.cksize; mmioSeek(hmmio, mmckInfo.dwDataOffset, SEEK_SET); while (left) { if (bPlaySoundStop) { wps->bLoop = FALSE; break; } count = mmioRead(hmmio, waveHdr[index].lpData, min(bufsize, left)); if (count < 1) break; left -= count; waveHdr[index].dwBufferLength = count; if (waveOutWrite(hWave, &waveHdr[index], sizeof(WAVEHDR)) == MMSYSERR_NOERROR) { index ^= 1; PlaySound_WaitDone(&s); } else { ERR("Aborting play loop, waveOutWrite error\n"); wps->bLoop = FALSE; break; } } bRet = TRUE; } while (wps->bLoop); PlaySound_WaitDone(&s); /* to balance first buffer */ waveOutReset(hWave); waveOutUnprepareHeader(hWave, &waveHdr[0], sizeof(WAVEHDR)); waveOutUnprepareHeader(hWave, &waveHdr[1], sizeof(WAVEHDR)); errCleanUp: TRACE("Done playing=%s => %s!\n", debugstr_w(wps->pszSound), bRet ? "ok" : "ko"); HeapFree(GetProcessHeap(), 0, lpWaveFormat); if (hWave) { EnterCriticalSection(&WINMM_cs); /* the CS prevents a concurrent waveOutReset */ wps->hWave = 0; LeaveCriticalSection(&WINMM_cs); while (waveOutClose(hWave) == WAVERR_STILLPLAYING) Sleep(100); } CloseHandle(s.hEvent); HeapFree(GetProcessHeap(), 0, waveHdr); if (hmmio) mmioClose(hmmio, 0); PlaySound_Free(wps); return bRet; }
/* ------------------------------------------------------------------------------------ */ int StreamingAudio::Create(char *szFileName) { int nError = 0; if(CCD->GetLogging()) { char szDebug[512]; sprintf(szDebug, "[INFO] Loaded %s", szFileName); CCD->ReportError(szDebug, false); } // Sanity check parameters if(szFileName == NULL) return RGF_FAILURE; // Wrong. // changed RF064 int len = strlen(szFileName)-4; if(stricmp((szFileName+len),".mp3") == 0) { if(Mpeg3 != NULL) return RGF_FAILURE; Mpeg3 = new CMp3Manager; Mpeg3->OpenMediaFile(szFileName); mp3 = true; m_fActive = true; // start a timer for this stream. MMRESULT nTimer = timeSetEvent(125, 5, &TimerFunction, (DWORD)this, TIME_PERIODIC | TIME_CALLBACK_FUNCTION); if(nTimer == NULL) { CCD->ReportError("[WARNING] StreamingAudio: Timer callback set-up failed", false); return RGF_FAILURE; // Timer startup failed. } m_nTimerID = nTimer; // Save timer ID return RGF_SUCCESS; } mp3 = false; if(stricmp((szFileName+len), ".ogg") == 0) { if(Ogg != NULL) return RGF_FAILURE; Ogg = new OggAudio(m_pDS); Ogg->Load(szFileName); ogg = true; m_fActive = true; return RGF_SUCCESS; } ogg = false; // start a timer for this stream. MMRESULT nTimer = timeSetEvent(125, 5, &TimerFunction, (DWORD)this, TIME_PERIODIC | TIME_CALLBACK_FUNCTION); if(nTimer == NULL) { CCD->ReportError("[WARNING] StreamingAudio: Timer callback set-up failed", false); return RGF_FAILURE; // Timer startup failed. } m_nTimerID = nTimer; // Save timer ID // end change RF064 // Check for stream availability if(m_pStream != NULL) return RGF_FAILURE; // Already loaded! // Open up the WAVE file. nError = WaveOpen(szFileName, &m_hWaveFile, &m_pWaveFormat, &m_rRiffData); if(nError != RGF_SUCCESS) { char szBug[128]; sprintf(szBug, "[WARNING] File %s - Line %d: Failed to open wave file '%s'\n(Note: streamig audio can't be placed in VFS)", __FILE__, __LINE__, szFileName); CCD->ReportError(szBug, false); return RGF_FAILURE; // Problem here, too! } // Get current position in file, which will be the start of the // ..WAVE data. m_nDataPosition = mmioSeek(m_hWaveFile, 0, SEEK_CUR); m_nDataSize = m_rRiffData.cksize; // Save data size // Fetch DirectSound interface we want LPDIRECTSOUND pDSIF; nError = m_pDS->QueryInterface(IID_IDirectSound, (LPVOID *)&pDSIF); // Create a DSound buffer to stream into DSBUFFERDESC theDesc; memset(&theDesc, 0, sizeof(DSBUFFERDESC)); theDesc.dwSize = sizeof(DSBUFFERDESC); theDesc.dwBufferBytes = kBufferSize; theDesc.lpwfxFormat = m_pWaveFormat; theDesc.dwFlags = DSBCAPS_CTRLVOLUME; nError = pDSIF->CreateSoundBuffer(&theDesc, &m_pStream, NULL); pDSIF->Release(); // Done w/ this. if(nError != 0) // Error! Sick out. { char szBug[128]; sprintf(szBug, "StreamingAudio: Failed to create buffer for '%s'\n", szFileName); OutputDebugString(szBug); mmioClose(m_hWaveFile, 0); m_hWaveFile = NULL; delete m_pWaveFormat; m_pWaveFormat = NULL; return RGF_FAILURE; } m_nOffset = 0; // Start at top of buffer // changed RF064 //m_fActive = true; // Set as active // end change RF064 PumpWave(kBufferSize); // Initial buffer load return RGF_SUCCESS; }
/************************************************************************** * mmioDescend [WINMM.@] */ MMRESULT WINAPI mmioDescend(HMMIO hmmio, LPMMCKINFO lpck, const MMCKINFO* lpckParent, UINT uFlags) { DWORD dwOldPos; FOURCC srchCkId; FOURCC srchType; TRACE("(%p, %p, %p, %04X);\n", hmmio, lpck, lpckParent, uFlags); if (lpck == NULL) return MMSYSERR_INVALPARAM; dwOldPos = mmioSeek(hmmio, 0, SEEK_CUR); TRACE("dwOldPos=%d\n", dwOldPos); if (lpckParent != NULL) { TRACE("seek inside parent at %d !\n", lpckParent->dwDataOffset); /* EPP: was dwOldPos = mmioSeek(hmmio,lpckParent->dwDataOffset,SEEK_SET); */ if (dwOldPos < lpckParent->dwDataOffset || dwOldPos >= lpckParent->dwDataOffset + lpckParent->cksize) { WARN("outside parent chunk\n"); return MMIOERR_CHUNKNOTFOUND; } } /* The SDK docu says 'ckid' is used for all cases. Real World * examples disagree -Marcus,990216. */ srchCkId = 0; srchType = 0; /* find_chunk looks for 'ckid' */ if (uFlags & MMIO_FINDCHUNK) srchCkId = lpck->ckid; /* find_riff and find_list look for 'fccType' */ if (uFlags & MMIO_FINDLIST) { srchCkId = FOURCC_LIST; srchType = lpck->fccType; } if (uFlags & MMIO_FINDRIFF) { srchCkId = FOURCC_RIFF; srchType = lpck->fccType; } TRACE("searching for %4.4s.%4.4s\n", (LPCSTR)&srchCkId, srchType ? (LPCSTR)&srchType : "any"); while (TRUE) { LONG ix; ix = mmioRead(hmmio, (LPSTR)lpck, 3 * sizeof(DWORD)); if (ix < 2*sizeof(DWORD)) { mmioSeek(hmmio, dwOldPos, SEEK_SET); WARN("return ChunkNotFound\n"); return MMIOERR_CHUNKNOTFOUND; } lpck->dwDataOffset = dwOldPos + 2 * sizeof(DWORD); TRACE("ckid=%4.4s fcc=%4.4s cksize=%08X !\n", (LPCSTR)&lpck->ckid, srchType ? (LPCSTR)&lpck->fccType:"<na>", lpck->cksize); if ( (!srchCkId || (srchCkId == lpck->ckid)) && (!srchType || (srchType == lpck->fccType)) ) break; dwOldPos = lpck->dwDataOffset + ((lpck->cksize + 1) & ~1); mmioSeek(hmmio, dwOldPos, SEEK_SET); } lpck->dwFlags = 0; /* If we were looking for RIFF/LIST chunks, the final file position * is after the chunkid. If we were just looking for the chunk * it is after the cksize. So add 4 in RIFF/LIST case. */ if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST) mmioSeek(hmmio, lpck->dwDataOffset + sizeof(DWORD), SEEK_SET); else { mmioSeek(hmmio, lpck->dwDataOffset, SEEK_SET); lpck->fccType = 0; } TRACE("lpck: ckid=%.4s, cksize=%d, dwDataOffset=%d fccType=%08X (%.4s)!\n", (LPSTR)&lpck->ckid, lpck->cksize, lpck->dwDataOffset, lpck->fccType, srchType?(LPSTR)&lpck->fccType:""); return MMSYSERR_NOERROR; }
STDMETHODIMP CAVIFileRemote::Open(LPCSTR szFile, UINT mode, LPCOLESTR lpszFileName) { HMMIO hmmio = NULL; MMCKINFO mmiriff, mmi; MMRESULT mmerr; HRESULT final = S_OK; _RPT2(0,"CAVIFileRemote::Open(\"%s\", %08lx)\n", szFile, mode); if (pafTunnel) { pafTunnel->Release(); pafTunnel = NULL; } if (mode & (OF_CREATE|OF_WRITE)) { IPersistFile *ppf; if (FAILED(CoCreateInstance(CLSID_AVIFile, NULL, CLSCTX_INPROC_SERVER, another_IID_IAVIFile, (void **)&pafTunnel))) return (HRESULT)E_FAIL; if (FAILED(pafTunnel->QueryInterface(IID_IPersistFile, (void **)&ppf))) return (HRESULT)E_FAIL; HRESULT hr = ppf->Load(lpszFileName, mode); ppf->Release(); return hr; } if (!(hmmio = mmioOpen((char *)szFile, NULL, MMIO_READ))) return E_FAIL; _RPT0(0,"File opened.\n"); // RIFF <size> VDRM { PATH <remote-path> } try { char buf[16]; _RPT0(0,"Checking for Avisynth signature...\n"); if (16==mmioRead(hmmio, buf, 16)) { buf[9] = 0; if (!_stricmp(buf, "#avisynth")) { mmioClose(hmmio, 0); // Hand it off to the Avisynth handler. IPersistFile *ppf; // Okay, it's not one of our files. Now try passing it off // to the regular AVI handler! _RPT0(0,"Attempt avisynth tunnel create\n"); if (FAILED(CoCreateInstance(CLSID_Avisynth, NULL, CLSCTX_INPROC_SERVER, another_IID_IAVIFile, (void **)&pafTunnel))) return (HRESULT)E_FAIL; _RPT0(0,"Attempt avisynth tunnel query -> IPersistFile\n"); if (FAILED(pafTunnel->QueryInterface(IID_IPersistFile, (void **)&ppf))) return (HRESULT)E_FAIL; _RPT0(0,"Attempt avisynth tunnel load\n"); HRESULT hr = ppf->Load(lpszFileName, mode); ppf->Release(); return hr; } } mmioSeek(hmmio, 0, SEEK_SET); _RPT0(0,"Attempting to find 'VDRM'...\n"); mmiriff.fccType = 'MRDV'; mmerr = mmioDescend(hmmio, &mmiriff, NULL, MMIO_FINDRIFF); if (mmerr == MMIOERR_CHUNKNOTFOUND) { IPersistFile *ppf; mmioClose(hmmio, 0); // Okay, it's not one of our files. Now try passing it off // to the regular AVI handler! _RPT0(0,"Attempt tunnel create\n"); if (FAILED(CoCreateInstance(CLSID_AVIFile, NULL, CLSCTX_INPROC_SERVER, another_IID_IAVIFile, (void **)&pafTunnel))) return (HRESULT)E_FAIL; _RPT0(0,"Attempt tunnel query -> IPersistFile\n"); if (FAILED(pafTunnel->QueryInterface(IID_IPersistFile, (void **)&ppf))) return (HRESULT)E_FAIL; _RPT0(0,"Attempt tunnel load\n"); HRESULT hr = ppf->Load(lpszFileName, mode); ppf->Release(); return hr; } else if (mmerr != MMSYSERR_NOERROR) throw (HRESULT)E_FAIL; _RPT0(0,"Attempting to find 'PATH'...\n"); mmi.ckid = 'HTAP'; mmerr = mmioDescend(hmmio, &mmi, &mmiriff, MMIO_FINDCHUNK); if (mmerr == MMIOERR_CHUNKNOTFOUND) throw (HRESULT)E_FAIL; else if (mmerr != MMSYSERR_NOERROR) throw (HRESULT)E_FAIL; _RPT0(0,"Allocate path memory...\n"); if (!(szPath = new char[mmi.cksize+1])) throw (HRESULT)E_OUTOFMEMORY; szPath[mmi.cksize]=0; _RPT0(0,"Read in path...\n"); if ((LONG)mmi.cksize != mmioRead(hmmio, szPath, mmi.cksize)) throw (HRESULT)E_FAIL; _RPT1(0,"File parsed, remote-path: [%s]\n", szPath); // now attempt to open the link ivdsl = GetDubServerInterface(); if (!ivdsl) throw (HRESULT)E_FAIL; _RPT0(0,"Have dub server interface.\n"); ivdac = ivdsl->FrameServerConnect(szPath); if (!ivdac) throw (HRESULT)E_FAIL; // retrieve streaminfo and format information _RPT0(0,"Connected to frameserver.\n"); fHasAudio = ivdac->hasAudio(); _RPT0(0,"Reading video stream info...\n"); if (!ivdac->readStreamInfo(&vStreamInfo, FALSE, &vSampleFirst, &vSampleLast)) throw (HRESULT)E_FAIL; _RPT0(0,"Reading video format length...\n"); if ((vFormatLen = ivdac->readFormat(NULL, FALSE))<=0) throw (HRESULT)E_FAIL; _RPT1(0,"Allocating video format (%ld bytes)...\n", vFormatLen); if (!(vFormat = (BITMAPINFOHEADER *)malloc(vFormatLen))) throw (HRESULT)E_OUTOFMEMORY; _RPT0(0,"Reading video format...\n"); if (ivdac->readFormat(vFormat, FALSE)<=0) throw (HRESULT)E_FAIL; if (fHasAudio) { _RPT0(0,"Reading audio stream info...\n"); if (!ivdac->readStreamInfo(&aStreamInfo, TRUE, &aSampleFirst, &aSampleLast)) throw (HRESULT)E_FAIL; _RPT0(0,"Reading audio format length...\n"); if ((aFormatLen = ivdac->readFormat(NULL, TRUE))<=0) throw (HRESULT)E_FAIL; _RPT1(0,"Allocating audio format (%ld bytes)...\n", aFormatLen); if (!(aFormat = (WAVEFORMATEX *)malloc(aFormatLen))) throw (HRESULT)E_OUTOFMEMORY; _RPT0(0,"Reading audio format...\n"); if (ivdac->readFormat(aFormat, TRUE)<=0) throw (HRESULT)E_FAIL; } } catch(HRESULT res) { _RPT0(0,"*** failed!\n"); final = res; }
void __fastcall CWaveStrage::Seek(int n) { mmioSeek(m_Handle, n, SEEK_SET); m_pos = n; }
int WaveCopyUselessChunks( HMMIO *phmmioIn, MMCKINFO *pckIn, MMCKINFO *pckInRiff, HMMIO *phmmioOut, MMCKINFO *pckOut, MMCKINFO *pckOutRiff) { int nError; nError = 0; // First seek to the stinking start of the file, not including the riff header... if ((nError = mmioSeek(*phmmioIn, pckInRiff->dwDataOffset + sizeof(FOURCC), SEEK_SET)) == -1) { nError = ER_CANNOTREAD; goto ERROR_IN_PROC; } nError = 0; while (mmioDescend(*phmmioIn, pckIn, pckInRiff, 0) == 0) { // quickly check for corrupt RIFF file--don't ascend past end! if ((pckIn->dwDataOffset + pckIn->cksize) > (pckInRiff->dwDataOffset + pckInRiff->cksize)) goto ERROR_IN_PROC; switch (pckIn->ckid) { // explicitly skip these... case mmioFOURCC('f', 'm', 't', ' '): break; case mmioFOURCC('d', 'a', 't', 'a'): break; case mmioFOURCC('f', 'a', 'c', 't'): break; case mmioFOURCC('J', 'U', 'N', 'K'): break; case mmioFOURCC('P', 'A', 'D', ' '): break; case mmioFOURCC('c', 'u', 'e', ' '): break; // copy chunks that are OK to copy case mmioFOURCC('p', 'l', 's', 't'): // although without the 'cue' chunk, it doesn't make much sense riffCopyChunk(*phmmioIn, *phmmioOut, pckIn); break; case mmioFOURCC('D', 'I', 'S', 'P'): riffCopyChunk(*phmmioIn, *phmmioOut, pckIn); break; // don't copy unknown chunks default: break; } // step up to prepare for next chunk.. mmioAscend(*phmmioIn, pckIn, 0); } ERROR_IN_PROC: { int nErrorT; // Seek back to riff header nErrorT = mmioSeek(*phmmioIn, pckInRiff->dwDataOffset + sizeof(FOURCC), SEEK_SET); } return(nError); }
static void test_mmioOpen(char *fname) { char buf[MMIO_DEFAULTBUFFER]; MMRESULT ret; HMMIO hmmio; MMIOINFO mmio; memset(&mmio, 0, sizeof(mmio)); mmio.fccIOProc = fname ? FOURCC_DOS : FOURCC_MEM; mmio.cchBuffer = sizeof(buf); mmio.pchBuffer = buf; hmmio = mmioOpen(fname, &mmio, MMIO_READ); if (fname && !hmmio) { skip("%s file is missing, skipping the test\n", fname); return; } ok(hmmio != 0, "mmioOpen error %u\n", mmio.wErrorRet); memset(&mmio, 0, sizeof(mmio)); ret = mmioGetInfo(hmmio, &mmio, 0); ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret); ok(mmio.dwFlags == MMIO_READ, "expected MMIO_READ, got %x\n", mmio.dwFlags); ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet); ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc); ok(mmio.cchBuffer == sizeof(buf), "got %u\n", mmio.cchBuffer); ok(mmio.pchBuffer == buf, "expected %p, got %p\n", buf, mmio.pchBuffer); ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext); if (mmio.fccIOProc == FOURCC_DOS) ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead); else ok(mmio.pchEndRead == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndRead); ok(mmio.pchEndWrite == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndWrite); ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset); ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset); ret = mmioSeek(hmmio, 0, SEEK_CUR); ok(ret == 0, "expected 0, got %d\n", ret); mmioClose(hmmio, 0); memset(&mmio, 0, sizeof(mmio)); mmio.fccIOProc = fname ? FOURCC_DOS : FOURCC_MEM; mmio.cchBuffer = 0; mmio.pchBuffer = buf; hmmio = mmioOpen(fname, &mmio, MMIO_READ); ok(hmmio != 0, "mmioOpen error %u\n", mmio.wErrorRet); memset(&mmio, 0, sizeof(mmio)); ret = mmioGetInfo(hmmio, &mmio, 0); ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret); ok(mmio.dwFlags == MMIO_READ, "expected MMIO_READ, got %x\n", mmio.dwFlags); ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet); ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc); ok(mmio.cchBuffer == 0, "expected 0, got %u\n", mmio.cchBuffer); ok(mmio.pchBuffer == buf, "expected %p, got %p\n", buf, mmio.pchBuffer); ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext); ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead); ok(mmio.pchEndWrite == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndWrite); ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset); ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset); ret = mmioSeek(hmmio, 0, SEEK_CUR); ok(ret == 0, "expected 0, got %d\n", ret); mmioClose(hmmio, 0); memset(&mmio, 0, sizeof(mmio)); mmio.fccIOProc = fname ? FOURCC_DOS : FOURCC_MEM; mmio.cchBuffer = 0; mmio.pchBuffer = NULL; hmmio = mmioOpen(fname, &mmio, MMIO_READ); ok(hmmio != 0, "mmioOpen error %u\n", mmio.wErrorRet); memset(&mmio, 0, sizeof(mmio)); ret = mmioGetInfo(hmmio, &mmio, 0); ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret); ok(mmio.dwFlags == MMIO_READ, "expected MMIO_READ, got %x\n", mmio.dwFlags); ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet); ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc); ok(mmio.cchBuffer == 0, "expected 0, got %u\n", mmio.cchBuffer); ok(mmio.pchBuffer == NULL, "expected NULL\n"); ok(mmio.pchNext == NULL, "expected NULL\n"); ok(mmio.pchEndRead == NULL, "expected NULL\n"); ok(mmio.pchEndWrite == NULL, "expected NULL\n"); ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset); ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset); #if 0 /* remove once passes under Wine */ ret = mmioSeek(hmmio, 0, SEEK_CUR); ok(ret == 0, "expected 0, got %d\n", ret); #endif mmioClose(hmmio, 0); memset(&mmio, 0, sizeof(mmio)); mmio.fccIOProc = fname ? FOURCC_DOS : FOURCC_MEM; mmio.cchBuffer = 256; mmio.pchBuffer = NULL; hmmio = mmioOpen(fname, &mmio, MMIO_READ); ok(hmmio != 0, "mmioOpen error %u\n", mmio.wErrorRet); memset(&mmio, 0, sizeof(mmio)); ret = mmioGetInfo(hmmio, &mmio, 0); ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret); ok(mmio.dwFlags == (MMIO_READ|MMIO_ALLOCBUF), "expected MMIO_READ|MMIO_ALLOCBUF, got %x\n", mmio.dwFlags); ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet); ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc); ok(mmio.cchBuffer == 256, "expected 256, got %u\n", mmio.cchBuffer); ok(mmio.pchBuffer != NULL, "expected not NULL\n"); ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext); if (mmio.fccIOProc == FOURCC_DOS) ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead); else ok(mmio.pchEndRead == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndRead); ok(mmio.pchEndWrite == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndWrite); ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset); ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset); #if 0 /* remove once passes under Wine */ ret = mmioSeek(hmmio, 0, SEEK_CUR); ok(ret == 0, "expected 0, got %d\n", ret); #endif mmioClose(hmmio, 0); memset(&mmio, 0, sizeof(mmio)); mmio.fccIOProc = fname ? FOURCC_DOS : FOURCC_MEM; mmio.cchBuffer = sizeof(buf); mmio.pchBuffer = buf; hmmio = mmioOpen(fname, &mmio, MMIO_READ | MMIO_ALLOCBUF); ok(hmmio != 0, "mmioOpen error %u\n", mmio.wErrorRet); memset(&mmio, 0, sizeof(mmio)); ret = mmioGetInfo(hmmio, &mmio, 0); ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret); ok(mmio.dwFlags == MMIO_READ, "expected MMIO_READ, got %x\n", mmio.dwFlags); ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet); ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc); ok(mmio.cchBuffer == sizeof(buf), "got %u\n", mmio.cchBuffer); ok(mmio.pchBuffer == buf, "expected %p, got %p\n", buf, mmio.pchBuffer); ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext); if (mmio.fccIOProc == FOURCC_DOS) ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead); else ok(mmio.pchEndRead == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndRead); ok(mmio.pchEndWrite == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndWrite); ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset); ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset); ret = mmioSeek(hmmio, 0, SEEK_CUR); ok(ret == 0, "expected 0, got %d\n", ret); mmioClose(hmmio, 0); memset(&mmio, 0, sizeof(mmio)); mmio.fccIOProc = fname ? FOURCC_DOS : FOURCC_MEM; mmio.cchBuffer = 0; mmio.pchBuffer = NULL; hmmio = mmioOpen(fname, &mmio, MMIO_READ | MMIO_ALLOCBUF); ok(hmmio != 0, "mmioOpen error %u\n", mmio.wErrorRet); memset(&mmio, 0, sizeof(mmio)); ret = mmioGetInfo(hmmio, &mmio, 0); ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret); ok(mmio.dwFlags == (MMIO_READ|MMIO_ALLOCBUF), "expected MMIO_READ|MMIO_ALLOCBUF, got %x\n", mmio.dwFlags); ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet); ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc); ok(mmio.cchBuffer == MMIO_DEFAULTBUFFER, "expected MMIO_DEFAULTBUFFER, got %u\n", mmio.cchBuffer); ok(mmio.pchBuffer != NULL, "expected not NULL\n"); ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext); if (mmio.fccIOProc == FOURCC_DOS) ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead); else ok(mmio.pchEndRead == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndRead); ok(mmio.pchEndWrite == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndWrite); ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset); ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset); #if 0 /* remove once passes under Wine */ ret = mmioSeek(hmmio, 0, SEEK_CUR); ok(ret == 0, "expected 0, got %d\n", ret); #endif mmioClose(hmmio, 0); memset(&mmio, 0, sizeof(mmio)); mmio.fccIOProc = fname ? FOURCC_DOS : FOURCC_MEM; mmio.cchBuffer = 256; mmio.pchBuffer = NULL; hmmio = mmioOpen(fname, &mmio, MMIO_READ | MMIO_ALLOCBUF); ok(hmmio != 0, "mmioOpen error %u\n", mmio.wErrorRet); memset(&mmio, 0, sizeof(mmio)); ret = mmioGetInfo(hmmio, &mmio, 0); ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret); ok(mmio.dwFlags == (MMIO_READ|MMIO_ALLOCBUF), "expected MMIO_READ|MMIO_ALLOCBUF, got %x\n", mmio.dwFlags); ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet); ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc); ok(mmio.cchBuffer == 256, "expected 256, got %u\n", mmio.cchBuffer); ok(mmio.pchBuffer != NULL, "expected not NULL\n"); ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext); if (mmio.fccIOProc == FOURCC_DOS) ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead); else ok(mmio.pchEndRead == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndRead); ok(mmio.pchEndWrite == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndWrite); ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset); ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset); #if 0 /* remove once passes under Wine */ ret = mmioSeek(hmmio, 0, SEEK_CUR); ok(ret == 0, "expected 0, got %d\n", ret); #endif mmioClose(hmmio, 0); memset(&mmio, 0, sizeof(mmio)); mmio.fccIOProc = fname ? FOURCC_DOS : FOURCC_MEM; mmio.cchBuffer = 0; mmio.pchBuffer = buf; hmmio = mmioOpen(fname, &mmio, MMIO_READ | MMIO_ALLOCBUF); if (!hmmio && mmio.wErrorRet == ERROR_BAD_FORMAT) { /* Seen on Win9x, WinMe but also XP-SP1 */ skip("Some Windows versions don't like a 0 size and a given buffer\n"); return; } ok(hmmio != 0, "mmioOpen error %u\n", mmio.wErrorRet); memset(&mmio, 0, sizeof(mmio)); ret = mmioGetInfo(hmmio, &mmio, 0); ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret); ok(mmio.dwFlags == MMIO_READ, "expected MMIO_READ, got %x\n", mmio.dwFlags); ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet); ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc); ok(mmio.cchBuffer == MMIO_DEFAULTBUFFER, "expected MMIO_DEFAULTBUFFER, got %u\n", mmio.cchBuffer); ok(mmio.pchBuffer == buf, "expected %p, got %p\n", buf, mmio.pchBuffer); ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext); if (mmio.fccIOProc == FOURCC_DOS) ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead); else ok(mmio.pchEndRead == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndRead); ok(mmio.pchEndWrite == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndWrite); ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset); ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset); ret = mmioSeek(hmmio, 0, SEEK_CUR); ok(ret == 0, "expected 0, got %d\n", ret); mmioClose(hmmio, 0); }
int SoundEvent::PlaySound(char *filenames,int newbuffer, double offset) { HMMIO m_hmmio; HRESULT hr; TRACESETUP("PLAYSOUND"); if(newbuffer) { m_hmmio = mmioOpen( filenames, NULL, MMIO_ALLOCBUF | MMIO_READ ); if( NULL == m_hmmio ) { TRACE ("DIRECT SOUND ERROR MMIOOPEN"); return (false); } MMCKINFO ckIn; // chunk info. for general use. PCMWAVEFORMAT pcmWaveFormat; // Temp PCM structure to load in. WAVEFORMATEX* m_pwfx; // Pointer to WAVEFORMATEX structure MMCKINFO m_ck; // Multimedia RIFF chunk MMCKINFO m_ckRiff; // Use in opening a WAVE file DWORD m_dwSize; // The size of the wave file MMIOINFO m_mmioinfoOut; DWORD m_dwFlags; #define WAVEFILE_READ 1 #define WAVEFILE_WRITE 2 m_pwfx = NULL; if( ( 0 != mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) ) { TRACE ("DIRECT SOUND ERROR MMIODESCEND"); return (false); } // Check to make sure this is a valid wave file if( (m_ckRiff.ckid != FOURCC_RIFF) || (m_ckRiff.fccType != mmioFOURCC('W', 'A', 'V', 'E') ) ) { return(false); TRACE ("DIRECT SOUND ERROR MMIOFOURCC"); } // Search the input file for for the 'fmt ' chunk. ckIn.ckid = mmioFOURCC('f', 'm', 't', ' '); if( 0 != mmioDescend( m_hmmio, &ckIn, &m_ckRiff, MMIO_FINDCHUNK ) ) { TRACE("DIRECT SOUND ERROR MMIDESCENT FIND CHUNK"); return(false); } // Expect the 'fmt' chunk to be at least as large as <PCMWAVEFORMAT>; // if there are extra parameters at the end, we'll ignore them if( ckIn.cksize < (LONG) sizeof(PCMWAVEFORMAT) ) { TRACE ("DIRECT SOUND ERROR CHUNKSIZE"); return(false); } // Read the 'fmt ' chunk into <pcmWaveFormat>. if( mmioRead( m_hmmio, (HPSTR) &pcmWaveFormat, sizeof(pcmWaveFormat)) != sizeof(pcmWaveFormat) ) { TRACE ("DIRECT SOUND ERROR MMIOREAD"); return(false); } // Allocate the waveformatex, but if its not pcm format, read the next // word, and thats how many extra bytes to allocate. if( pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM ) { m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) ]; if( NULL == m_pwfx ) { TRACE("DIRECT SOUND ERROR ALLOC"); return(false); } // Copy the bytes from the pcm structure to the waveformatex structure memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) ); m_pwfx->cbSize = 0; } else { // Read in length of extra bytes. WORD cbExtraBytes = 0L; if( mmioRead( m_hmmio, (CHAR*)&cbExtraBytes, sizeof(WORD)) != sizeof(WORD) ) { TRACE ("DIRECT SOUND ERROR M_HMMIO"); return(false); } m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) + cbExtraBytes ]; if( NULL == m_pwfx ) { TRACE("DIRECT SOUND ERREOR ALLOC 2"); return(false); } // Copy the bytes from the pcm structure to the waveformatex structure memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) ); m_pwfx->cbSize = cbExtraBytes; // Now, read those extra bytes into the structure, if cbExtraAlloc != 0. if( mmioRead( m_hmmio, (CHAR*)(((BYTE*)&(m_pwfx->cbSize))+sizeof(WORD)), cbExtraBytes ) != cbExtraBytes ) { //SAFE_DELETE( m_pwfx ); TRACE("DIRECT SOUND ERROR MMIOREAD2"); return(false); } } // Ascend the input file out of the 'fmt ' chunk. if( 0 != mmioAscend( m_hmmio, &ckIn, 0 ) ) { //SAFE_DELETE( m_pwfx ); TRACE("DIRECT SOUND ERROR MMIOASCEND"); return(false); } TRACE("DIRECTSOUND READMMIO OK"); m_dwFlags = WAVEFILE_READ; if( m_dwFlags == WAVEFILE_READ ) { // Seek to the data if( -1 == mmioSeek( m_hmmio, m_ckRiff.dwDataOffset + sizeof(FOURCC), SEEK_SET ) ) { TRACE ("DIRECT SOUND ERROR MMIOSEEK"); return(false); } // Search the input file for the 'data' chunk. m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a'); if( 0 != mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) { TRACE ("DIRECT SOUND ERROR MMIODESCEND"); return(false); } } else { // Create the 'data' chunk that holds the waveform samples. m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a'); m_ck.cksize = 0; if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) ) { TRACE("DIRECT SOUND ERROR MMIOCREATECHUNK"); return(false); } if( 0 != mmioGetInfo( m_hmmio, &m_mmioinfoOut, 0 ) ) { TRACE ("DIRECT SOUND ERROR MMMIOGETINFO"); return(false); } } TRACE("DIRECTSOUND RESETFILE OK"); // After the reset, the size of the wav file is m_ck.cksize so store it now m_dwSize = m_ck.cksize; char buffers[80]; TRACE ("DIRECTSOUND TAILLE BUFFER"); sprintf(buffers,"%d", m_dwSize); TRACE (buffers); DWORD dwDSBufferSize = NULL; apDSBuffer = new LPDIRECTSOUNDBUFFER[1]; if( apDSBuffer == NULL ) { TRACE("ERROR DIRECTSOUND NEW BUFFER"); return(false); } // Make the DirectSound buffer the same size as the wav file dwDSBufferSize = m_dwSize; // Create the direct sound buffer, and only request the flags needed // since each requires some overhead and limits if the buffer can // be hardware accelerated DSBUFFERDESC dsbd2; ZeroMemory( &dsbd2, sizeof(DSBUFFERDESC) ); dsbd2.dwSize = sizeof(DSBUFFERDESC); dsbd2.dwFlags = 0; dsbd2.dwBufferBytes = dwDSBufferSize; dsbd2.guid3DAlgorithm = GUID_NULL; dsbd2.lpwfxFormat = m_pwfx; TRACE ("APPEL CREATE SOUND BUFFER"); // DirectSound is only guarenteed to play PCM data. Other // formats may or may not work depending the sound card driver. hr = m_pDS->CreateSoundBuffer( &dsbd2, &apDSBuffer[0], NULL ); if (hr != DS_OK) TRACE ("ERROR DIRECTSOUND CREATE SOUND BUFFER") else TRACE("DIRECTSOUND CREATE SOUND BUFFER OK"); // Make sure we have focus, and we didn't just switch in from // an app which had a DirectSound device // hr = RestoreBuffer( &apDSBuffer[0], NULL ); // if (hr != DS_OK) // TRACE ("ERROR DIRECTSOUND RESTORE SOUND BUFFER") // else TRACE("DIRECTSOUND RESTORE SOUND BUFFER OK"); // Lock the buffer down hr = apDSBuffer[0]->Lock( 0, m_dwSize, &pDSLockedBuffer, &dwDSLockedBufferSize, NULL, NULL, 0L ); if (hr != DS_OK) TRACE ("ERROR DIRECTSOUND LOCK") else TRACE ("DIRECTSOUND LOCK OK"); // Reset the wave file to the beginning // Seek to the data if( -1 == mmioSeek( m_hmmio, m_ckRiff.dwDataOffset + sizeof(FOURCC), SEEK_SET ) ) TRACE ("ERROR DIRECTSOUND MMIOSEEK") else TRACE ("DIRECTSOUND MMIOSSEEK OK"); // Search the input file for the 'data' chunk. m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a'); if( 0 != mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) TRACE ("ERROR DIRECTSOUND MMIODESCEND") else TRACE ("DIRECTSOUND MMIODESCEND OK"); MMIOINFO mmioinfoIn; // current status of m_hmmio DWORD dwWavDataRead = 0; // Amount of data read from the wav file dwWavDataRead = 0; if( 0 != mmioGetInfo( m_hmmio, &mmioinfoIn, 0 ) ) TRACE ("ERROR DIRECTSOUND MMIOGETINFO") else TRACE ("DIRECTSOUND MMIOGETINFO OK"); UINT cbDataIn = m_dwSize; if( cbDataIn > m_ck.cksize ) cbDataIn = m_ck.cksize; m_ck.cksize -= cbDataIn; for( DWORD cT = 0; cT < cbDataIn; cT++ ) { // Copy the bytes from the io to the buffer. if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) { if( 0 != mmioAdvance( m_hmmio, &mmioinfoIn, MMIO_READ ) ) TRACE ("ERROR DIRECTSOUND MMIOADVANCE") else /* TRACE ("DIRECTSOUND MMIOADVANCE OK")*/; if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) TRACE ("ERROR DIRECTSOUND READ FIC") else /* TRACE ("DIRECTSOUND READ FIC OK") */; } // Actual copy. *((BYTE*)pDSLockedBuffer+cT) = *((BYTE*)mmioinfoIn.pchNext); mmioinfoIn.pchNext++; } if( 0 != mmioSetInfo( m_hmmio, &mmioinfoIn, 0 ) ) TRACE ("ERROR DIRECTSOUND MMIOSETINFO") else TRACE ("DIRECTSOUND MMIOSETINFO OK"); mmioClose( m_hmmio, 0 ); dwWavDataRead = cbDataIn; } // end of newbuffer part // Unlock the buffer, we don't need it anymore. // apDSBuffer[0]->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); if (offset > 0.) { DWORD curplay,curwrite; char buffers[80]; apDSBuffer[0]->GetCurrentPosition(&curplay,&curwrite); sprintf(buffers, "POS CURPLAY AVT %d", curplay); TRACE(buffers); curplay = DWORD (offset * 8000.); hr = apDSBuffer[0]->SetCurrentPosition(curplay); if (hr != DS_OK) TRACE ("ERROR DIRECTSOUND SETCURRENT") else TRACE ("DIRECTSOUND SETCURRENT OK"); apDSBuffer[0]->GetCurrentPosition(&curplay,&curwrite); sprintf(buffers, "POS CURPLAY APS %d", curplay); TRACE(buffers); }
static void test_mmioSetBuffer(char *fname) { char buf[256]; MMRESULT ret; HMMIO hmmio; MMIOINFO mmio; memset(&mmio, 0, sizeof(mmio)); mmio.fccIOProc = fname ? FOURCC_DOS : FOURCC_MEM; mmio.cchBuffer = sizeof(buf); mmio.pchBuffer = buf; hmmio = mmioOpen(fname, &mmio, MMIO_READ); if (fname && !hmmio) { skip("%s file is missing, skipping the test\n", fname); return; } ok(hmmio != 0, "mmioOpen error %u\n", mmio.wErrorRet); memset(&mmio, 0, sizeof(mmio)); ret = mmioGetInfo(hmmio, &mmio, 0); ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret); ok(mmio.dwFlags == MMIO_READ, "expected MMIO_READ, got %x\n", mmio.dwFlags); ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet); ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc); ok(mmio.cchBuffer == sizeof(buf), "got %u\n", mmio.cchBuffer); ok(mmio.pchBuffer == buf, "expected %p, got %p\n", buf, mmio.pchBuffer); ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext); if (mmio.fccIOProc == FOURCC_DOS) ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead); else ok(mmio.pchEndRead == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndRead); ok(mmio.pchEndWrite == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndWrite); ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset); ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset); ret = mmioSeek(hmmio, 0, SEEK_CUR); ok(ret == 0, "expected 0, got %d\n", ret); ret = mmioSetBuffer(hmmio, NULL, 0, 0); ok(ret == MMSYSERR_NOERROR, "mmioSetBuffer error %u\n", ret); memset(&mmio, 0, sizeof(mmio)); ret = mmioGetInfo(hmmio, &mmio, 0); ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret); ok(mmio.dwFlags == MMIO_READ, "expected MMIO_READ, got %x\n", mmio.dwFlags); ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet); ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc); ok(mmio.cchBuffer == 0, "got not 0\n"); ok(mmio.pchBuffer == NULL, "got not NULL buf\n"); ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext); ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead); ok(mmio.pchEndWrite == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndWrite); #if 0 /* remove once passes under Wine */ ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset); ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset); #endif #if 0 /* remove once passes under Wine */ ret = mmioSeek(hmmio, 0, SEEK_CUR); ok(ret == 0, "expected 0, got %d\n", ret); #endif ret = mmioSetBuffer(hmmio, NULL, 0, MMIO_ALLOCBUF); ok(ret == MMSYSERR_NOERROR, "mmioSetBuffer error %u\n", ret); memset(&mmio, 0, sizeof(mmio)); ret = mmioGetInfo(hmmio, &mmio, 0); ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret); ok(mmio.dwFlags == MMIO_READ, "expected MMIO_READ, got %x\n", mmio.dwFlags); ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet); ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc); ok(mmio.cchBuffer == 0, "got not 0\n"); ok(mmio.pchBuffer == NULL, "got not NULL buf\n"); ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext); ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead); ok(mmio.pchEndWrite == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndWrite); #if 0 /* remove once passes under Wine */ ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset); ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset); #endif #if 0 /* remove once passes under Wine */ ret = mmioSeek(hmmio, 0, SEEK_CUR); ok(ret == 0, "expected 0, got %d\n", ret); #endif ret = mmioSetBuffer(hmmio, buf, 0, MMIO_ALLOCBUF); ok(ret == MMSYSERR_NOERROR, "mmioSetBuffer error %u\n", ret); memset(&mmio, 0, sizeof(mmio)); ret = mmioGetInfo(hmmio, &mmio, 0); ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret); ok(mmio.dwFlags == MMIO_READ, "expected MMIO_READ, got %x\n", mmio.dwFlags); ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet); ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc); ok(mmio.cchBuffer == 0, "got not 0\n"); ok(mmio.pchBuffer == buf, "expected %p, got %p\n", buf, mmio.pchBuffer); ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext); ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead); ok(mmio.pchEndWrite == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndWrite); #if 0 /* remove once passes under Wine */ ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset); ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset); #endif #if 0 /* remove once passes under Wine */ ret = mmioSeek(hmmio, 0, SEEK_CUR); ok(ret == 0, "expected 0, got %d\n", ret); #endif ret = mmioSetBuffer(hmmio, NULL, 256, MMIO_WRITE|MMIO_ALLOCBUF); ok(ret == MMSYSERR_NOERROR, "mmioSetBuffer error %u\n", ret); memset(&mmio, 0, sizeof(mmio)); ret = mmioGetInfo(hmmio, &mmio, 0); ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret); ok(mmio.dwFlags == (MMIO_READ|MMIO_ALLOCBUF), "expected MMIO_READ|MMIO_ALLOCBUF, got %x\n", mmio.dwFlags); ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet); ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc); ok(mmio.cchBuffer == 256, "got %u\n", mmio.cchBuffer); ok(mmio.pchBuffer != NULL, "expected not NULL\n"); ok(mmio.pchBuffer != buf, "expected != buf\n"); ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext); ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", buf, mmio.pchEndRead); ok(mmio.pchEndWrite == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndWrite); #if 0 /* remove once passes under Wine */ ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset); ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset); #endif #if 0 /* remove once passes under Wine */ ret = mmioSeek(hmmio, 0, SEEK_CUR); ok(ret == 0, "expected 0, got %d\n", ret); #endif mmioClose(hmmio, 0); }
/************************************************************************** * mmioSeek [MMSYSTEM.1214] */ LONG WINAPI mmioSeek16(HMMIO16 hmmio, LONG lOffset, INT16 iOrigin) { return mmioSeek(HMMIO_32(hmmio), lOffset, iOrigin); }
static void test_mmioDescend(char *fname) { MMRESULT ret; HMMIO hmmio; MMIOINFO mmio; MMCKINFO ckRiff, ckList, ck, ckList2; memset(&mmio, 0, sizeof(mmio)); mmio.fccIOProc = fname ? FOURCC_DOS : FOURCC_MEM; mmio.cchBuffer = sizeof(RIFF_buf); mmio.pchBuffer = (char *)RIFF_buf; hmmio = mmioOpen(fname, &mmio, MMIO_READ); if (fname && !hmmio) { skip("%s file is missing, skipping the test\n", fname); return; } ok(hmmio != 0, "mmioOpen error %u\n", mmio.wErrorRet); expect_buf_offset(hmmio, 0); /* first normal RIFF AVI parsing */ ret = mmioDescend(hmmio, &ckRiff, NULL, 0); ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret); ok(ckRiff.ckid == FOURCC_RIFF, "wrong ckid: %04x\n", ckRiff.ckid); ok(ckRiff.fccType == formtypeAVI, "wrong fccType: %04x\n", ckRiff.fccType); ok(ckRiff.dwDataOffset == 8, "expected 8 got %u\n", ckRiff.dwDataOffset); trace("ckid %4.4s cksize %04x fccType %4.4s off %04x flags %04x\n", (LPCSTR)&ckRiff.ckid, ckRiff.cksize, (LPCSTR)&ckRiff.fccType, ckRiff.dwDataOffset, ckRiff.dwFlags); expect_buf_offset(hmmio, 12); ret = mmioDescend(hmmio, &ckList, &ckRiff, 0); ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret); ok(ckList.ckid == FOURCC_LIST, "wrong ckid: %04x\n", ckList.ckid); ok(ckList.fccType == listtypeAVIHEADER, "wrong fccType: %04x\n", ckList.fccType); ok(ckList.dwDataOffset == 20, "expected 20 got %u\n", ckList.dwDataOffset); trace("ckid %4.4s cksize %04x fccType %4.4s off %04x flags %04x\n", (LPCSTR)&ckList.ckid, ckList.cksize, (LPCSTR)&ckList.fccType, ckList.dwDataOffset, ckList.dwFlags); expect_buf_offset(hmmio, 24); ret = mmioDescend(hmmio, &ck, &ckList, 0); ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret); ok(ck.ckid == ckidAVIMAINHDR, "wrong ckid: %04x\n", ck.ckid); ok(ck.fccType == 0, "wrong fccType: %04x\n", ck.fccType); trace("ckid %4.4s cksize %04x fccType %4.4s off %04x flags %04x\n", (LPCSTR)&ck.ckid, ck.cksize, (LPCSTR)&ck.fccType, ck.dwDataOffset, ck.dwFlags); expect_buf_offset(hmmio, 32); /* Skip chunk data */ ret = mmioSeek(hmmio, ck.cksize, SEEK_CUR); ok(ret == 0x58, "expected 0x58, got %#x\n", ret); ret = mmioDescend(hmmio, &ckList2, &ckList, 0); ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret); ok(ckList2.ckid == FOURCC_LIST, "wrong ckid: %04x\n", ckList2.ckid); ok(ckList2.fccType == listtypeSTREAMHEADER, "wrong fccType: %04x\n", ckList2.fccType); trace("ckid %4.4s cksize %04x fccType %4.4s off %04x flags %04x\n", (LPCSTR)&ckList2.ckid, ckList2.cksize, (LPCSTR)&ckList2.fccType, ckList2.dwDataOffset, ckList2.dwFlags); expect_buf_offset(hmmio, 100); ret = mmioDescend(hmmio, &ck, &ckList2, 0); ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret); ok(ck.ckid == ckidSTREAMHEADER, "wrong ckid: %04x\n", ck.ckid); ok(ck.fccType == 0, "wrong fccType: %04x\n", ck.fccType); trace("ckid %4.4s cksize %04x fccType %4.4s off %04x flags %04x\n", (LPCSTR)&ck.ckid, ck.cksize, (LPCSTR)&ck.fccType, ck.dwDataOffset, ck.dwFlags); expect_buf_offset(hmmio, 108); /* test various mmioDescend flags */ mmioSeek(hmmio, 0, SEEK_SET); memset(&ck, 0x66, sizeof(ck)); ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDRIFF); ok(ret == MMIOERR_CHUNKNOTFOUND || ret == MMIOERR_INVALIDFILE, "mmioDescend returned %u\n", ret); mmioSeek(hmmio, 0, SEEK_SET); memset(&ck, 0x66, sizeof(ck)); ck.ckid = 0; ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDRIFF); ok(ret == MMIOERR_CHUNKNOTFOUND || ret == MMIOERR_INVALIDFILE, "mmioDescend returned %u\n", ret); mmioSeek(hmmio, 0, SEEK_SET); memset(&ck, 0x66, sizeof(ck)); ck.fccType = 0; ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDRIFF); ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret); ok(ck.ckid == FOURCC_RIFF, "wrong ckid: %04x\n", ck.ckid); ok(ck.fccType == formtypeAVI, "wrong fccType: %04x\n", ck.fccType); mmioSeek(hmmio, 0, SEEK_SET); memset(&ck, 0x66, sizeof(ck)); ret = mmioDescend(hmmio, &ck, NULL, 0); ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret); ok(ck.ckid == FOURCC_RIFF, "wrong ckid: %04x\n", ck.ckid); ok(ck.fccType == formtypeAVI, "wrong fccType: %04x\n", ck.fccType); /* do NOT seek, use current file position */ memset(&ck, 0x66, sizeof(ck)); ck.fccType = 0; ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDLIST); ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret); ok(ck.ckid == FOURCC_LIST, "wrong ckid: %04x\n", ck.ckid); ok(ck.fccType == listtypeAVIHEADER, "wrong fccType: %04x\n", ck.fccType); mmioSeek(hmmio, 0, SEEK_SET); memset(&ck, 0x66, sizeof(ck)); ck.ckid = 0; ck.fccType = listtypeAVIHEADER; ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDCHUNK); ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret); ok(ck.ckid == FOURCC_RIFF, "wrong ckid: %04x\n", ck.ckid); ok(ck.fccType == formtypeAVI, "wrong fccType: %04x\n", ck.fccType); /* do NOT seek, use current file position */ memset(&ck, 0x66, sizeof(ck)); ck.ckid = FOURCC_LIST; ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDCHUNK); ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret); ok(ck.ckid == FOURCC_LIST, "wrong ckid: %04x\n", ck.ckid); ok(ck.fccType == listtypeAVIHEADER, "wrong fccType: %04x\n", ck.fccType); mmioSeek(hmmio, 0, SEEK_SET); memset(&ck, 0x66, sizeof(ck)); ck.ckid = FOURCC_RIFF; ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDCHUNK); ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret); ok(ck.ckid == FOURCC_RIFF, "wrong ckid: %04x\n", ck.ckid); ok(ck.fccType == formtypeAVI, "wrong fccType: %04x\n", ck.fccType); /* do NOT seek, use current file position */ memset(&ckList, 0x66, sizeof(ckList)); ckList.ckid = 0; ret = mmioDescend(hmmio, &ckList, &ck, MMIO_FINDCHUNK); ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret); ok(ckList.ckid == FOURCC_LIST, "wrong ckid: %04x\n", ckList.ckid); ok(ckList.fccType == listtypeAVIHEADER, "wrong fccType: %04x\n", ckList.fccType); mmioSeek(hmmio, 0, SEEK_SET); memset(&ck, 0x66, sizeof(ck)); ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDCHUNK); ok(ret == MMIOERR_CHUNKNOTFOUND || ret == MMIOERR_INVALIDFILE, "mmioDescend returned %u\n", ret); ok(ck.ckid != 0x66666666, "wrong ckid: %04x\n", ck.ckid); ok(ck.fccType != 0x66666666, "wrong fccType: %04x\n", ck.fccType); ok(ck.dwDataOffset != 0x66666666, "wrong dwDataOffset: %04x\n", ck.dwDataOffset); mmioSeek(hmmio, 0, SEEK_SET); memset(&ck, 0x66, sizeof(ck)); ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDRIFF); ok(ret == MMIOERR_CHUNKNOTFOUND || ret == MMIOERR_INVALIDFILE, "mmioDescend returned %u\n", ret); mmioClose(hmmio, 0); }
static HRESULT AVIFILE_LoadSunFile(IAVIFileImpl *This) { SUNAUDIOHEADER auhdr; mmioSeek(This->hmmio, 0, SEEK_SET); if (mmioRead(This->hmmio, (HPSTR)&auhdr, sizeof(auhdr)) != sizeof(auhdr)) return AVIERR_FILEREAD; if (auhdr.fccType == 0x0064732E) { /* header in little endian */ This->ckData.dwDataOffset = LE2H_DWORD(auhdr.offset); This->ckData.cksize = LE2H_DWORD(auhdr.size); auhdr.encoding = LE2H_DWORD(auhdr.encoding); auhdr.sampleRate = LE2H_DWORD(auhdr.sampleRate); auhdr.channels = LE2H_DWORD(auhdr.channels); } else if (auhdr.fccType == mmioFOURCC('.','s','n','d')) { /* header in big endian */ This->ckData.dwDataOffset = BE2H_DWORD(auhdr.offset); This->ckData.cksize = BE2H_DWORD(auhdr.size); auhdr.encoding = BE2H_DWORD(auhdr.encoding); auhdr.sampleRate = BE2H_DWORD(auhdr.sampleRate); auhdr.channels = BE2H_DWORD(auhdr.channels); } else return AVIERR_FILEREAD; if (auhdr.channels < 1) return AVIERR_BADFORMAT; /* get size of header */ switch(auhdr.encoding) { case AU_ENCODING_ADPCM_G721_32: This->cbFormat = sizeof(G721_ADPCMWAVEFORMAT); break; case AU_ENCODING_ADPCM_G723_24: This->cbFormat = sizeof(G723_ADPCMWAVEFORMAT); break; case AU_ENCODING_ADPCM_G722: case AU_ENCODING_ADPCM_G723_5: WARN("unsupported Sun audio format %d\n", auhdr.encoding); return AVIERR_UNSUPPORTED; /* FIXME */ default: This->cbFormat = sizeof(WAVEFORMATEX); break; }; This->lpFormat = HeapAlloc(GetProcessHeap(), 0, This->cbFormat); if (This->lpFormat == NULL) return AVIERR_MEMORY; This->lpFormat->nChannels = auhdr.channels; This->lpFormat->nSamplesPerSec = auhdr.sampleRate; switch(auhdr.encoding) { case AU_ENCODING_ULAW_8: This->lpFormat->wFormatTag = WAVE_FORMAT_MULAW; This->lpFormat->wBitsPerSample = 8; break; case AU_ENCODING_PCM_8: This->lpFormat->wFormatTag = WAVE_FORMAT_PCM; This->lpFormat->wBitsPerSample = 8; break; case AU_ENCODING_PCM_16: This->lpFormat->wFormatTag = WAVE_FORMAT_PCM; This->lpFormat->wBitsPerSample = 16; break; case AU_ENCODING_PCM_24: This->lpFormat->wFormatTag = WAVE_FORMAT_PCM; This->lpFormat->wBitsPerSample = 24; break; case AU_ENCODING_PCM_32: This->lpFormat->wFormatTag = WAVE_FORMAT_PCM; This->lpFormat->wBitsPerSample = 32; break; case AU_ENCODING_ALAW_8: This->lpFormat->wFormatTag = WAVE_FORMAT_ALAW; This->lpFormat->wBitsPerSample = 8; break; case AU_ENCODING_ADPCM_G721_32: This->lpFormat->wFormatTag = WAVE_FORMAT_G721_ADPCM; This->lpFormat->wBitsPerSample = (3*5*8); This->lpFormat->nBlockAlign = 15*15*8; This->lpFormat->cbSize = sizeof(WORD); ((LPG721_ADPCMWAVEFORMAT)This->lpFormat)->nAuxBlockSize = 0; break; case AU_ENCODING_ADPCM_G723_24: This->lpFormat->wFormatTag = WAVE_FORMAT_G723_ADPCM; This->lpFormat->wBitsPerSample = (3*5*8); This->lpFormat->nBlockAlign = 15*15*8; This->lpFormat->cbSize = 2*sizeof(WORD); ((LPG723_ADPCMWAVEFORMAT)This->lpFormat)->cbExtraSize = 0; ((LPG723_ADPCMWAVEFORMAT)This->lpFormat)->nAuxBlockSize = 0; break; default: WARN("unsupported Sun audio format %d\n", auhdr.encoding); return AVIERR_UNSUPPORTED; }; This->lpFormat->nBlockAlign = (This->lpFormat->nChannels * This->lpFormat->wBitsPerSample) / 8; if (This->lpFormat->nBlockAlign == 0 && This->lpFormat->wBitsPerSample < 8) This->lpFormat->nBlockAlign++; This->lpFormat->nAvgBytesPerSec = This->lpFormat->nBlockAlign * This->lpFormat->nSamplesPerSec; This->fDirty = FALSE; This->sInfo.fccType = streamtypeAUDIO; This->sInfo.fccHandler = 0; This->sInfo.dwFlags = 0; This->sInfo.wPriority = 0; This->sInfo.wLanguage = 0; This->sInfo.dwInitialFrames = 0; This->sInfo.dwScale = This->lpFormat->nBlockAlign; This->sInfo.dwRate = This->lpFormat->nAvgBytesPerSec; This->sInfo.dwStart = 0; This->sInfo.dwLength = This->ckData.cksize / This->lpFormat->nBlockAlign; This->sInfo.dwSuggestedBufferSize = This->sInfo.dwLength; This->sInfo.dwSampleSize = This->lpFormat->nBlockAlign; This->fInfo.dwStreams = 1; This->fInfo.dwScale = 1; This->fInfo.dwRate = This->lpFormat->nSamplesPerSec; This->fInfo.dwLength = MulDiv(This->ckData.cksize, This->lpFormat->nSamplesPerSec, This->lpFormat->nAvgBytesPerSec); return AVIERR_OK; }
// Open BOOL WaveFile::Open (LPSTR pszFilename) { int done = FALSE; WORD cbExtra = 0; BOOL fRtn = SUCCESS; // assume success PCMWAVEFORMAT pcmwf; char fullpath[_MAX_PATH]; m_total_uncompressed_bytes_read = 0; m_max_uncompressed_bytes_to_read = AS_HIGHEST_MAX; int FileSize, FileOffset; if ( !cf_find_file_location(pszFilename, CF_TYPE_ANY, fullpath, &FileSize, &FileOffset )) { goto OPEN_ERROR; } cfp = mmioOpen(fullpath, NULL, MMIO_ALLOCBUF | MMIO_READ); if ( cfp == NULL ) { goto OPEN_ERROR; } // Skip the "RIFF" tag and file size (8 bytes) // Skip the "WAVE" tag (4 bytes) mmioSeek( cfp, 12+FileOffset, SEEK_SET ); // Now read RIFF tags until the end of file uint tag, size, next_chunk; while(done == FALSE) { if ( mmioRead(cfp, (char *)&tag, sizeof(uint)) != sizeof(uint) ) break; if ( mmioRead(cfp, (char *)&size, sizeof(uint)) != sizeof(uint) ) break; next_chunk = mmioSeek( cfp, 0, SEEK_CUR ); next_chunk += size; switch( tag ) { case 0x20746d66: // The 'fmt ' tag mmioRead( cfp, (char *)&pcmwf, sizeof(PCMWAVEFORMAT) ); if ( pcmwf.wf.wFormatTag != WAVE_FORMAT_PCM ) { mmioRead( cfp, (char *)&cbExtra, sizeof(short) ); } // Allocate memory for WAVEFORMATEX structure + extra bytes if ( (m_pwfmt_original = (WAVEFORMATEX *) malloc ( sizeof(WAVEFORMATEX)+cbExtra )) != NULL ){ Assert(m_pwfmt_original != NULL); // Copy bytes from temporary format structure memcpy (m_pwfmt_original, &pcmwf, sizeof(pcmwf)); m_pwfmt_original->cbSize = cbExtra; // Read those extra bytes, append to WAVEFORMATEX structure if (cbExtra != 0) { mmioRead( cfp, (char *)((ubyte *)(m_pwfmt_original) + sizeof(WAVEFORMATEX)), cbExtra ); } } else { Int3(); // malloc failed goto OPEN_ERROR; } break; case 0x61746164: // the 'data' tag m_nDataSize = size; // This is size of data chunk. Compressed if ADPCM. m_data_bytes_left = size; m_data_offset = mmioSeek( cfp, 0, SEEK_CUR); done = TRUE; break; default: // unknown, skip it break; } // end switch mmioSeek( cfp, next_chunk, SEEK_SET ); } // At this stage, examine source format, and set up WAVEFORATEX structure for DirectSound. // Since DirectSound only supports PCM, force this structure to be PCM compliant. We will // need to convert data on the fly later if our souce is not PCM switch ( m_pwfmt_original->wFormatTag ) { case WAVE_FORMAT_PCM: m_wave_format = WAVE_FORMAT_PCM; m_wfmt.wBitsPerSample = m_pwfmt_original->wBitsPerSample; break; case WAVE_FORMAT_ADPCM: m_wave_format = WAVE_FORMAT_ADPCM; m_wfmt.wBitsPerSample = 16; break; default: nprintf(("SOUND", "SOUND => Not supporting %d format for playing wave files\n")); //Int3(); goto OPEN_ERROR; break; } // end switch // Set up the WAVEFORMATEX structure to have the right PCM characteristics m_wfmt.wFormatTag = WAVE_FORMAT_PCM; m_wfmt.nChannels = m_pwfmt_original->nChannels; m_wfmt.nSamplesPerSec = m_pwfmt_original->nSamplesPerSec; m_wfmt.cbSize = 0; m_wfmt.nBlockAlign = (unsigned short)(( m_wfmt.nChannels * m_wfmt.wBitsPerSample ) / 8); m_wfmt.nAvgBytesPerSec = m_wfmt.nBlockAlign * m_wfmt.nSamplesPerSec; // Init some member data from format chunk m_nBlockAlign = m_pwfmt_original->nBlockAlign; m_nUncompressedAvgDataRate = m_wfmt.nAvgBytesPerSec; // Cue for streaming Cue (); // Successful open goto OPEN_DONE; OPEN_ERROR: // Handle all errors here nprintf(("SOUND","SOUND ==> Could not open wave file %s for streaming\n",pszFilename)); fRtn = FAILURE; if (cfp != NULL) { // Close file mmioClose( cfp, 0 ); cfp = NULL; } if (m_pwfmt_original) { free(m_pwfmt_original); m_pwfmt_original = NULL; } OPEN_DONE: return (fRtn); }
static HRESULT WINAPI IAVIStream_fnRead(IAVIStream *iface, LONG start, LONG samples, void *buffer, LONG buffersize, LONG *bytesread, LONG *samplesread) { IAVIFileImpl *This = impl_from_IAVIStream(iface); TRACE("(%p,%d,%d,%p,%d,%p,%p)\n", iface, start, samples, buffer, buffersize, bytesread, samplesread); /* clear return parameters if given */ if (bytesread != NULL) *bytesread = 0; if (samplesread != NULL) *samplesread = 0; /* positions without data */ if (start < 0 || (DWORD)start > This->sInfo.dwLength) return AVIERR_OK; /* check samples */ if (samples < 0) samples = 0; if (buffersize > 0) { if (samples > 0) samples = min((DWORD)samples, buffersize / This->sInfo.dwSampleSize); else samples = buffersize / This->sInfo.dwSampleSize; } /* limit to end of stream */ if ((DWORD)(start + samples) > This->sInfo.dwLength) samples = This->sInfo.dwLength - start; /* request only the sizes? */ if (buffer == NULL || buffersize <= 0) { /* then I need at least one parameter for it */ if (bytesread == NULL && samplesread == NULL) return AVIERR_BADPARAM; if (bytesread != NULL) *bytesread = samples * This->sInfo.dwSampleSize; if (samplesread != NULL) *samplesread = samples; return AVIERR_OK; } /* nothing to read? */ if (samples == 0) return AVIERR_OK; /* Can I read at least one sample? */ if ((DWORD)buffersize < This->sInfo.dwSampleSize) return AVIERR_BUFFERTOOSMALL; buffersize = samples * This->sInfo.dwSampleSize; if (mmioSeek(This->hmmio, This->ckData.dwDataOffset + start * This->sInfo.dwSampleSize, SEEK_SET) == -1) return AVIERR_FILEREAD; if (mmioRead(This->hmmio, buffer, buffersize) != buffersize) return AVIERR_FILEREAD; /* fill out return parameters if given */ if (bytesread != NULL) *bytesread = buffersize; if (samplesread != NULL) *samplesread = samples; return AVIERR_OK; }
// Read // // Returns number of bytes actually read. // // Returns -1 if there is nothing more to be read. This function can return 0, since // sometimes the amount of bytes requested is too small for the ACM decompression to // locate a suitable block int WaveFile::Read(BYTE *pbDest, UINT cbSize, int service) { unsigned char *dest_buf=NULL, *uncompressed_wave_data; int rc, uncompressed_bytes_written; unsigned int src_bytes_used, convert_len, num_bytes_desired=0, num_bytes_read; // nprintf(("Alan","Reqeusted: %d\n", cbSize)); if ( service ) { uncompressed_wave_data = Wavedata_service_buffer; } else { uncompressed_wave_data = Wavedata_load_buffer; } switch ( m_wave_format ) { case WAVE_FORMAT_PCM: num_bytes_desired = cbSize; dest_buf = pbDest; break; case WAVE_FORMAT_ADPCM: if ( !m_hStream_open ) { if ( !ACM_stream_open(m_pwfmt_original, &m_wfxDest, (void**)&m_hStream), m_bits_per_sample_uncompressed ) { m_hStream_open = 1; } else { Int3(); } } num_bytes_desired = cbSize; if ( service ) { dest_buf = Compressed_service_buffer; } else { dest_buf = Compressed_buffer; } if ( num_bytes_desired <= 0 ) { num_bytes_desired = 0; // nprintf(("Alan","No bytes required for ADPCM time interval\n")); } else { num_bytes_desired = ACM_query_source_size((void*)m_hStream, cbSize); // nprintf(("Alan","Num bytes desired: %d\n", num_bytes_desired)); } break; default: nprintf(("SOUND", "SOUND => Not supporting %d format for playing wave files\n")); Int3(); break; } // end switch num_bytes_read = 0; convert_len = 0; src_bytes_used = 0; // read data from disk if ( m_data_bytes_left <= 0 ) { num_bytes_read = 0; uncompressed_bytes_written = 0; return -1; } if ( m_data_bytes_left > 0 && num_bytes_desired > 0 ) { int actual_read; if ( num_bytes_desired <= (unsigned int)m_data_bytes_left ) { num_bytes_read = num_bytes_desired; } else { num_bytes_read = m_data_bytes_left; } actual_read = mmioRead( cfp, (char *)dest_buf, num_bytes_read ); if ( (actual_read <= 0) || (m_abort_next_read) ) { num_bytes_read = 0; uncompressed_bytes_written = 0; return -1; } if ( num_bytes_desired >= (unsigned int)m_data_bytes_left ) { m_abort_next_read = 1; } num_bytes_read = actual_read; } // convert data if necessary, to PCM if ( m_wave_format == WAVE_FORMAT_ADPCM ) { if ( num_bytes_read > 0 ) { rc = ACM_convert((void*)m_hStream, dest_buf, num_bytes_read, uncompressed_wave_data, BIGBUF_SIZE, &convert_len, &src_bytes_used); if ( rc == -1 ) { goto READ_ERROR; } if ( convert_len == 0 ) { Int3(); } } Assert(src_bytes_used <= num_bytes_read); if ( src_bytes_used < num_bytes_read ) { // seek back file pointer to reposition before unused source data mmioSeek(cfp, src_bytes_used - num_bytes_read, SEEK_CUR); } // Adjust number of bytes left m_data_bytes_left -= src_bytes_used; m_nBytesPlayed += src_bytes_used; uncompressed_bytes_written = convert_len; // Successful read, keep running total of number of data bytes read goto READ_DONE; } else { // Successful read, keep running total of number of data bytes read // Adjust number of bytes left m_data_bytes_left -= num_bytes_read; m_nBytesPlayed += num_bytes_read; uncompressed_bytes_written = num_bytes_read; goto READ_DONE; } READ_ERROR: num_bytes_read = 0; uncompressed_bytes_written = 0; READ_DONE: m_total_uncompressed_bytes_read += uncompressed_bytes_written; // nprintf(("Alan","Read: %d\n", uncompressed_bytes_written)); return (uncompressed_bytes_written); }