void CAudioFormatDlg::SuggestLocalCompressFormat() { m_bAudioCompression = TRUE; AllocCompressFormat(); // 1st try MPEGLAYER3 // TODO: Why???? WAVEFORMATEX sWaveFormat; BuildLocalRecordingFormat(sWaveFormat); MMRESULT mmr = MMSYSERR_ERROR; if ((sWaveFormat.nSamplesPerSec == 22050) && (sWaveFormat.nChannels == 2) && (sWaveFormat.wBitsPerSample <= 16)) { m_pwfx->wFormatTag = WAVE_FORMAT_MPEGLAYER3; mmr = ::acmFormatSuggest(NULL, &sWaveFormat, m_pwfx, m_cbwfx, ACM_FORMATSUGGESTF_WFORMATTAG); } if (0 != mmr) { //ver 1.6, use PCM if MP3 not available //Then try ADPCM //BuildLocalRecordingFormat(); //m_pwfx->wFormatTag = WAVE_FORMAT_ADPCM; //mmr = acmFormatSuggest(NULL, &m_sWaveFormat, m_pwfx, m_cbwfx, ACM_FORMATSUGGESTF_WFORMATTAG); // if (mmr != 0) { //Use the PCM as default BuildLocalRecordingFormat(sWaveFormat); m_pwfx->wFormatTag = WAVE_FORMAT_PCM; mmr = acmFormatSuggest(NULL, &sWaveFormat, m_pwfx, m_cbwfx, ACM_FORMATSUGGESTF_WFORMATTAG); if (mmr != 0) { m_bAudioCompression = FALSE; } //} } }
LRESULT CAcm::Open(WAVEFORMATEX *pWFormat,LPVOID lpSrcBuf,DWORD dwSrcLength){ Close(); // 忘れんうちに引数をコピー:p m_lpSrcWFormat = pWFormat; m_lpSrcBuf = lpSrcBuf; m_dwSrcLength = dwSrcLength; // 構造体初期化 ZERO(m_destWFormat); ZERO(m_acmheader); m_hAcm = NULL; m_dwDestLength = 0; m_destWFormat.wFormatTag = WAVE_FORMAT_PCM; // PCMになって欲しいねん! if (acmFormatSuggest(NULL,pWFormat,&m_destWFormat,sizeof(WAVEFORMATEX),ACM_FORMATSUGGESTF_WFORMATTAG)!=0){ return 1; // acm無いんとちゃう? } if (acmStreamOpen(&m_hAcm,NULL,pWFormat,&m_destWFormat,NULL,NULL,NULL,ACM_STREAMOPENF_NONREALTIME)!=0){ return 2; // acmおかしんとちゃう? } if (acmStreamSize(m_hAcm,dwSrcLength,&m_dwDestLength,ACM_STREAMSIZEF_SOURCE)!=0){ return 3; // なんでやねんと言いたい(笑) } if (m_dwDestLength == 0) return 4; // なぜじゃー m_bOpen = true; // Openに成功。これより任務に移る:p return 0; }
BOOL CPlayer::WavIsValidFile(LPCTSTR pszFile) { CReader reader; DWORD dwBuf = 0, dwRead = 0; WAVEFORMATEX *pwfxSrc, wfxDst; pwfxSrc = NULL; if (!reader.Open(pszFile)) return FALSE; // "RIFF" if (!reader.Read((LPBYTE)&dwBuf, sizeof(dwBuf), &dwRead) || dwBuf != MAKEFOURCC('R', 'I', 'F', 'F')) goto error; // "WAVE" reader.SetPointer(4, FILE_CURRENT); if (!reader.Read((LPBYTE)&dwBuf, sizeof(dwBuf), &dwRead) || dwBuf != MAKEFOURCC('W', 'A', 'V', 'E')) goto error; // "fmt " while (TRUE) { if (!reader.Read((LPBYTE)&dwBuf, sizeof(dwBuf), &dwRead)) goto error; if (dwBuf = MAKEFOURCC('f', 'm', 't', ' ')) break; if (!reader.Read((LPBYTE)&dwBuf, sizeof(dwBuf), &dwRead)) goto error; if (reader.SetPointer(dwBuf, FILE_CURRENT) == MAXLONGLONG) goto error; } if (!reader.Read((LPBYTE)&dwBuf, sizeof(dwBuf), &dwRead)) goto error; pwfxSrc = (WAVEFORMATEX*)new BYTE[dwBuf]; if (!reader.Read((LPBYTE)pwfxSrc, dwBuf, &dwRead)) goto error; #if 1 memset(&wfxDst, 0, sizeof(wfxDst)); wfxDst.wFormatTag = WAVE_FORMAT_PCM; if (acmFormatSuggest(NULL, pwfxSrc, &wfxDst, sizeof(WAVEFORMATEX), ACM_FORMATSUGGESTF_WFORMATTAG) != 0) goto error; #endif delete pwfxSrc; reader.Close(); return TRUE; error: if (pwfxSrc) delete pwfxSrc; reader.Close(); return FALSE; }
static HRESULT AVIFILE_OpenCompressor(IAVIStreamImpl *This) { HRESULT hr; /* pre-conditions */ assert(This != NULL); assert(This->pStream != NULL); if (This->has != NULL) return AVIERR_OK; if (This->lpInFormat == NULL) { /* decode or encode the data from pStream */ hr = AVIStreamFormatSize(This->pStream, This->sInfo.dwStart, &This->cbInFormat); if (FAILED(hr)) return hr; This->lpInFormat = HeapAlloc(GetProcessHeap(), 0, This->cbInFormat); if (This->lpInFormat == NULL) return AVIERR_MEMORY; hr = IAVIStream_ReadFormat(This->pStream, This->sInfo.dwStart, This->lpInFormat, &This->cbInFormat); if (FAILED(hr)) return hr; if (This->lpOutFormat == NULL) { /* we must decode to default format */ This->cbOutFormat = sizeof(PCMWAVEFORMAT); This->lpOutFormat = HeapAlloc(GetProcessHeap(), 0, This->cbOutFormat); if (This->lpOutFormat == NULL) return AVIERR_MEMORY; This->lpOutFormat->wFormatTag = WAVE_FORMAT_PCM; if (acmFormatSuggest(NULL, This->lpInFormat, This->lpOutFormat, This->cbOutFormat, ACM_FORMATSUGGESTF_WFORMATTAG) != S_OK) return AVIERR_NOCOMPRESSOR; } } else if (This->lpOutFormat == NULL) return AVIERR_ERROR; /* To what should I encode? */ if (acmStreamOpen(&This->has, NULL, This->lpInFormat, This->lpOutFormat, NULL, 0, 0, ACM_STREAMOPENF_NONREALTIME) != S_OK) return AVIERR_NOCOMPRESSOR; /* update AVISTREAMINFO structure */ This->sInfo.dwSampleSize = This->lpOutFormat->nBlockAlign; This->sInfo.dwScale = This->lpOutFormat->nBlockAlign; This->sInfo.dwRate = This->lpOutFormat->nAvgBytesPerSec; This->sInfo.dwQuality = (DWORD)ICQUALITY_DEFAULT; SetRectEmpty(&This->sInfo.rcFrame); /* convert positions and sizes to output format */ CONVERT_STREAM_to_THIS(&This->sInfo.dwStart); CONVERT_STREAM_to_THIS(&This->sInfo.dwLength); CONVERT_STREAM_to_THIS(&This->sInfo.dwSuggestedBufferSize); return AVIERR_OK; }
int ToADPCM(short *Source, short *Dest, int Size) { int Src_size; int Dest_Size; Wave_Format.wFormatTag = WAVE_FORMAT_PCM; Wave_Format.nChannels = 1; Wave_Format.cbSize = 0; Wave_Format.wBitsPerSample = 16; Wave_Format.nSamplesPerSec = 44100; Wave_Format.nBlockAlign = Wave_Format.nChannels * Wave_Format.wBitsPerSample / 8; Wave_Format.nAvgBytesPerSec = Wave_Format.nSamplesPerSec * Wave_Format.nBlockAlign; ADPCM_Format.wfx.wFormatTag = WAVE_FORMAT_IMA_ADPCM; acmFormatSuggest(NULL, (LPWAVEFORMATEX) &Wave_Format, (LPWAVEFORMATEX) &ADPCM_Format, sizeof(TrueSpeech_Format), ACM_FORMATSUGGESTF_WFORMATTAG); acmStreamOpen(&Pack_Stream, NULL, (LPWAVEFORMATEX) &Wave_Format, (LPWAVEFORMATEX) &ADPCM_Format, NULL, 0, 0, ACM_STREAMOPENF_NONREALTIME); Src_size = Size; unsigned long rawbufsize = 0; acmStreamSize(Pack_Stream, Src_size, &rawbufsize, ACM_STREAMSIZEF_SOURCE); Uint8 *Pack_Buf = (Uint8 *) malloc(Src_size + 8); memset(Pack_Buf, 0, Src_size + 8); Uint8 *rawbuf = (Uint8 *) malloc(rawbufsize + 8); memset(rawbuf, 0, rawbufsize + 8); ACMSTREAMHEADER Pack_Stream_Head; ZeroMemory(&Pack_Stream_Head, sizeof(ACMSTREAMHEADER)); Pack_Stream_Head.cbStruct = sizeof(ACMSTREAMHEADER); Pack_Stream_Head.pbSrc = (Uint8 *) Pack_Buf; Pack_Stream_Head.cbSrcLength = Src_size; Pack_Stream_Head.pbDst = rawbuf; Pack_Stream_Head.cbDstLength = rawbufsize; acmStreamPrepareHeader(Pack_Stream, &Pack_Stream_Head, 0); memcpy(Pack_Buf, Source, Src_size); acmStreamConvert(Pack_Stream, &Pack_Stream_Head, 0); Dest_Size = Pack_Stream_Head.cbDstLengthUsed; if(Dest_Size < Src_size) { memcpy(Dest, rawbuf, Dest_Size); } else { Dest_Size = 0; } acmStreamUnprepareHeader(Pack_Stream, &Pack_Stream_Head, 0); if(rawbuf) free(rawbuf); if(Pack_Buf) free(Pack_Buf); acmStreamClose(Pack_Stream, 0); return(Dest_Size); }
void SuggestLocalCompressFormat() { bAudioCompressionLocal = TRUE; AllocLocalCompressFormat(); //1st try MPEGLAYER3 BuildLocalRecordingFormat(); MMRESULT mmr; if ((m_FormatLocal.nSamplesPerSec == 22050) && (m_FormatLocal.nChannels==2) && (m_FormatLocal.wBitsPerSample <= 16)) { pwfxLocal->wFormatTag = WAVE_FORMAT_MPEGLAYER3; mmr = acmFormatSuggest(NULL, &m_FormatLocal, pwfxLocal, cbwfxLocal, ACM_FORMATSUGGESTF_WFORMATTAG); } //if (mmr!=0) { //Then try ADPCM //BuildLocalRecordingFormat(); //pwfxLocal->wFormatTag = WAVE_FORMAT_ADPCM; //MMRESULT mmr = acmFormatSuggest(NULL, &m_FormatLocal, pwfxLocal, cbwfxLocal, ACM_FORMATSUGGESTF_WFORMATTAG); if (mmr!=0) { //Use the PCM as default BuildLocalRecordingFormat(); pwfxLocal->wFormatTag = WAVE_FORMAT_PCM; MMRESULT mmr = acmFormatSuggest(NULL, &m_FormatLocal, pwfxLocal, cbwfxLocal, ACM_FORMATSUGGESTF_WFORMATTAG); if (mmr!=0) { bAudioCompressionLocal = FALSE; } //} } }
//-------------------------------------------------------------------------------------------------- void CSoundStream::LoadADPCM( ) { char buf [255]; int pos; sxr_riff riff; sxr_hdr hdr; string256 fn; strconcat (fn,fName,".ogg"); DataPos = NULL; hf = FS.r_open("$game_sounds$",fn); R_ASSERT (hf>=0); ZeroMemory (&riff, sizeof(riff)); XRead (riff); CopyMemory (buf,riff.id,4); buf[4]=0; CopyMemory (buf,riff.wave_id,4); buf[4]=0; while (!hf->eof()) { XRead (hdr); CopyMemory (buf,hdr.id,4); buf[4]=0; pos = hf->tell(); if (stricmp(buf, "fmt ")==0) { dwFMT_Size = hdr.len; psrc = (LPWAVEFORMATEX)xr_malloc(dwFMT_Size); pwfx = (LPWAVEFORMATEX)xr_malloc(dwFMT_Size); hf->r (psrc, dwFMT_Size); CopyMemory (pwfx,psrc, dwFMT_Size); pwfx->wFormatTag = WAVE_FORMAT_PCM; } else { if (stricmp(buf,"data")==0) { DataPos=hf->tell(); dwTotalSize=hdr.len; } } hf->seek(hdr.len+pos); } VERIFY (DataPos); // dest format CHK_DX (acmFormatSuggest(NULL,psrc,pwfx,dwFMT_Size,ACM_FORMATSUGGESTF_WFORMATTAG)); // dest buffer (const size) WaveDest = (unsigned char *)xr_malloc(dwDestBufSize); // wave source -- alloc on Play // DSound---------------------------------------------------------------- ADPCMCreateSoundBuffer (SoundRender.pDevice, &pBuffer, pwfx); }
/// <summary> /// <c>wACMFormatSuggest</c> /// </summary> /// <remarks> /// </remarks> /// <param name="had"></param> /// <param name="pwfxSrc"></param> /// <param name="pwfxDst"></param> /// <param name="cbwfxDst"></param> /// <param name="fdwSuggest"></param> /// <returns>HRESULT __stdcall</returns> HRESULT __stdcall wACMFormatSuggest(HACMDRIVER had, const PWAVEFORMATEX pwfxSrc, const PWAVEFORMATEX pwfxDst, ULONG cbwfxDst, ULONG fdwSuggest) { PSTR pszwfDst; PSTR pszwfSrc; PSTR pszErrorMessage; char Buffer2[128]; char Buffer[128]; MMRESULT hResult; pszwfDst = GetWaveFormat(Buffer, pwfxDst); pszwfSrc = GetWaveFormat(Buffer2, pwfxSrc); InternalFunctionSpew( "GameOS_DirectSound", "acmFormatSuggest(0x%x, %s, %s, 0x%x, 0x%x)", had, pszwfSrc, pszwfDst, cbwfxDst, fdwSuggest); hResult = acmFormatSuggest(had, pwfxSrc, pwfxDst, cbwfxDst, fdwSuggest); if (MMFAILED(hResult)) { pszwfDst = GetWaveFormat(Buffer, pwfxDst); pszwfSrc = GetWaveFormat(Buffer2, pwfxSrc); pszErrorMessage = ErrorNumberToMessage(hResult); if ( InternalFunctionPause( "FAILED (0x%x - %s) - acmFormatSuggest(0x%x, %s, %s, 0x%x, 0x%x)", hResult, pszErrorMessage, had, pszwfSrc, pszwfDst, cbwfxDst, fdwSuggest) ) ENTER_DEBUGGER; } return hResult; }
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; }
BOOL ClSoundDS::AddSoundBuffer(int handle,char *fileBuf,BOOL b3DSound) { HRESULT hr; RiffHead riffHead; FmtHead fmtHead; PCMWAVEFORMAT pcmFormat; LPBYTE lpBlockAdd1, lpBlockAdd2; DWORD blockSize1, blockSize2; CopyMemory(&riffHead,fileBuf,sizeof(RiffHead)); fileBuf += sizeof(RiffHead); if(strncmp(riffHead.riff,"RIFF",4) || strncmp(riffHead.type,"WAVE",4)){ return FALSE; } if(NULL==lpDSBufferTop){ lpDSBufferTop = lpDSBufferTail = new ClSoundBuffer; }else{ lpDSBufferTail->lpNext = new ClSoundBuffer; lpDSBufferTail->lpNext->lpPrev = lpDSBufferTail; lpDSBufferTail = lpDSBufferTail->lpNext; } lpDSBufferTail->bufType = memory_sound; CopyMemory(&fmtHead,fileBuf,sizeof(FmtHead)); fileBuf += sizeof(FmtHead); CopyMemory(&pcmFormat,fileBuf,sizeof(PCMWAVEFORMAT)); if(pcmFormat.wf.wFormatTag == WAVE_FORMAT_PCM){ fileBuf += fmtHead.size; CopyMemory(&fmtHead,fileBuf,sizeof(FmtHead)); fileBuf += sizeof(FmtHead); while(0!=strncmp(fmtHead.fmt,"data",4)){ fileBuf += fmtHead.size; CopyMemory(&fmtHead,fileBuf,sizeof(FmtHead)); fileBuf += sizeof(FmtHead); } DSBUFFERDESC dsbdesc; WAVEFORMATEX audioFmt; ZeroMemory(&dsbdesc, sizeof(DSBUFFERDESC)); dsbdesc.dwSize = sizeof(DSBUFFERDESC); dsbdesc.dwFlags = DSBCAPS_STATIC | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_LOCSOFTWARE | DSBCAPS_GLOBALFOCUS; if(b3DSound) dsbdesc.dwFlags |= (DSBCAPS_CTRL3D | DSBCAPS_MUTE3DATMAXDISTANCE); dsbdesc.dwBufferBytes = fmtHead.size; CopyMemory(&audioFmt,&pcmFormat,sizeof(WAVEFORMAT)); audioFmt.wBitsPerSample = pcmFormat.wBitsPerSample; audioFmt.cbSize = 0; dsbdesc.lpwfxFormat = &audioFmt; hr = lpDSound->CreateSoundBuffer(&dsbdesc, &lpTmpBuffer, NULL); lpTmpBuffer->QueryInterface(IID_IDirectSoundBuffer8,(LPVOID *)&lpDSBufferTail->lpDSBuffer); RELEASE(lpTmpBuffer); hr = lpDSBufferTail->lpDSBuffer->Lock(0,fmtHead.size, (LPVOID*)&lpBlockAdd1, &blockSize1,(LPVOID*)&lpBlockAdd2, &blockSize2, 0); if(DS_OK==hr){ CopyMemory(lpBlockAdd1,fileBuf,blockSize1); if(fmtHead.size>blockSize1){ CopyMemory(lpBlockAdd2,fileBuf+blockSize1,blockSize2); } lpDSBufferTail->lpDSBuffer->Unlock(lpBlockAdd1, blockSize1, lpBlockAdd2, blockSize2); } lpDSBufferTail->handle = handle; }else{ WAVEFORMATEX dstWF; WAVEFORMATEX *pwfxInfo; WORD cbExtraAlloc; MMRESULT mmResult; fileBuf += sizeof(PCMWAVEFORMAT); CopyMemory(&cbExtraAlloc,fileBuf,sizeof(WORD)); fileBuf += sizeof(WORD); pwfxInfo = (WAVEFORMATEX *)cl_malloc(sizeof(WAVEFORMATEX) +cbExtraAlloc); CopyMemory(pwfxInfo,&pcmFormat,sizeof(PCMWAVEFORMAT)); pwfxInfo->cbSize = cbExtraAlloc; CopyMemory((char *)pwfxInfo +sizeof(WAVEFORMATEX),fileBuf,cbExtraAlloc); fileBuf += (fmtHead.size -sizeof(WAVEFORMATEX)); CopyMemory(&fmtHead,fileBuf,sizeof(FmtHead)); fileBuf += sizeof(FmtHead); while(0!=strncmp(fmtHead.fmt,"data",4)){ fileBuf += fmtHead.size; CopyMemory(&fmtHead,fileBuf,sizeof(FmtHead)); fileBuf += sizeof(FmtHead); } ZeroMemory(&dstWF,sizeof(dstWF)); dstWF.wFormatTag = WAVE_FORMAT_PCM; mmResult = acmFormatSuggest( NULL, pwfxInfo, &dstWF, sizeof(dstWF), ACM_FORMATSUGGESTF_WFORMATTAG); if(mmResult != 0){ myOutputDebugString("オーディオ圧縮が無効です\n"); return FALSE; } HACMSTREAM hAcm = NULL; ACMSTREAMHEADER ash; AcmBuffer acmDst; AcmBuffer acmSrc; acmStreamOpen(&hAcm, NULL,pwfxInfo,&dstWF, NULL, 0L, 0L, ACM_STREAMOPENF_NONREALTIME); acmSrc.dwStreamSize = fmtHead.size; acmStreamSize(hAcm, acmSrc.dwStreamSize, &acmDst.dwStreamSize, ACM_STREAMSIZEF_SOURCE); cl_free(pwfxInfo); acmSrc.lpStream = (LPBYTE)cl_malloc(acmSrc.dwStreamSize); acmDst.lpStream = (LPBYTE)cl_malloc(acmDst.dwStreamSize); ZeroMemory(&ash,sizeof(ash)); ash.cbStruct = sizeof(ash); ash.pbSrc = acmSrc.lpStream; ash.cbSrcLength = acmSrc.dwStreamSize; ash.dwSrcUser = acmSrc.dwStreamSize; ash.pbDst = acmDst.lpStream; ash.cbDstLength = acmDst.dwStreamSize; ash.dwDstUser = acmDst.dwStreamSize; acmStreamPrepareHeader(hAcm,&ash,0); CopyMemory(acmSrc.lpStream,fileBuf,acmSrc.dwStreamSize); MMRESULT nError = acmStreamConvert(hAcm,&ash, ACM_STREAMCONVERTF_BLOCKALIGN); DSBUFFERDESC dsbdesc; ZeroMemory(&dsbdesc, sizeof(DSBUFFERDESC)); dsbdesc.dwSize = sizeof(DSBUFFERDESC); dsbdesc.dwFlags = DSBCAPS_STATIC | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_LOCSOFTWARE | DSBCAPS_GLOBALFOCUS; if(b3DSound) dsbdesc.dwFlags |= (DSBCAPS_CTRL3D | DSBCAPS_MUTE3DATMAXDISTANCE); dsbdesc.dwBufferBytes = ash.cbDstLengthUsed; dsbdesc.lpwfxFormat = &dstWF; hr = lpDSound->CreateSoundBuffer(&dsbdesc, &lpTmpBuffer, NULL); lpTmpBuffer->QueryInterface(IID_IDirectSoundBuffer8,(LPVOID *)&lpDSBufferTail->lpDSBuffer); RELEASE(lpTmpBuffer); hr = lpDSBufferTail->lpDSBuffer->Lock(0,ash.cbDstLengthUsed, (LPVOID*)&lpBlockAdd1, &blockSize1,(LPVOID*)&lpBlockAdd2, &blockSize2, 0); if(DS_OK==hr){ if(ash.cbDstLengthUsed < blockSize1){ CopyMemory(lpBlockAdd1, acmDst.lpStream, ash.cbDstLengthUsed); ZeroMemory(lpBlockAdd1 +ash.cbDstLengthUsed, blockSize1 -ash.cbDstLengthUsed); if(blockSize2)ZeroMemory(lpBlockAdd2,blockSize2); }else{ CopyMemory(lpBlockAdd1, acmDst.lpStream, blockSize1); if(blockSize2){ CopyMemory(lpBlockAdd2, acmDst.lpStream+blockSize1, ash.cbDstLengthUsed -blockSize1); } } lpDSBufferTail->lpDSBuffer->Unlock(lpBlockAdd1, blockSize1, lpBlockAdd2, blockSize2); } if(hAcm){ acmStreamUnprepareHeader(hAcm,&ash,0); acmStreamClose(hAcm,0); cl_free(acmSrc.lpStream); cl_free(acmDst.lpStream); } lpDSBufferTail->handle = handle; } return TRUE; } // ClSoundDS::AddSoundBuffer
BOOL ClSoundDS::CreateStreamBuffer(int handle,int arcFileNum,int playNum) { int size,stream,dataTopOffset,nextStream = -1; HRESULT hr; RiffHead riffHead; FmtHead fmtHead; PCMWAVEFORMAT pcmFormat; BOOL bOGG = FALSE; ReleaseSoundBuffer(handle); stream = lpReadFile->StreamOpenFileNum(arcFileNum,playNum,size); if(pack_bgmfile!=arcFileNum && pack_voice!=arcFileNum){ lpReadFile->StreamReadFile(arcFileNum,stream,(char *)&riffHead,sizeof(RiffHead)); if(strncmp(riffHead.riff,"RIFF",4) || strncmp(riffHead.type,"WAVE",4)){ lpReadFile->StreamCloseFile(arcFileNum,stream); return FALSE; } lpReadFile->StreamReadFile(arcFileNum,stream,(char *)&fmtHead,sizeof(FmtHead)); lpReadFile->StreamReadFile(arcFileNum,stream,(char *)&pcmFormat,sizeof(PCMWAVEFORMAT)); }else{ char chkFmt[4]; bOGG = TRUE; char *fname = lpReadFile->GetFileName(arcFileNum,playNum); lpReadFile->StreamReadFile(arcFileNum,stream,(char *)&chkFmt,4); lpReadFile->StreamSeekFile(arcFileNum,stream,0,FILE_BEGIN); if(0!=strncmp(chkFmt,"OggS",4))return FALSE; dataTopOffset = 0; if(NULL==lpDSBufferTop){ lpDSBufferTop = lpDSBufferTail = new ClSoundBuffer; }else{ lpDSBufferTail->lpNext = new ClSoundBuffer; lpDSBufferTail->lpNext->lpPrev = lpDSBufferTail; lpDSBufferTail = lpDSBufferTail->lpNext; } lpDSBufferTail->dataTopOffset = dataTopOffset; lpDSBufferTail->o_dat = new OggDec; if(_strnicmp(&fname[strlen(fname)-6],"_A.",3) == 0){ char workBuf[32]; strcpy(workBuf,fname); workBuf[strlen(fname)-5] = 'B'; nextStream = lpReadFile->SearchFile(arcFileNum,workBuf); } WAVEFORMATEX dstWF; char workBuf[4096]; lpReadFile->StreamReadFile(arcFileNum,stream,workBuf,4096); lpDSBufferTail->o_dat->GetWaveformat(&dstWF,workBuf); DSBUFFERDESC dsbdesc; ZeroMemory(&dsbdesc, sizeof(DSBUFFERDESC)); dsbdesc.dwSize = sizeof(DSBUFFERDESC); dsbdesc.dwFlags = DSBCAPS_STATIC | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_LOCSOFTWARE | DSBCAPS_GLOBALFOCUS; dsbdesc.dwBufferBytes = dstWF.nAvgBytesPerSec *2; dsbdesc.lpwfxFormat = &dstWF; hr = lpDSound->CreateSoundBuffer(&dsbdesc, &lpTmpBuffer, NULL); lpTmpBuffer->QueryInterface(IID_IDirectSoundBuffer8,(LPVOID *)&lpDSBufferTail->lpDSBuffer); RELEASE(lpTmpBuffer); lpDSBufferTail->streamBlockSize = dstWF.nAvgBytesPerSec; } if(bOGG){ pcmFormat.wf.wFormatTag = WAVE_FORMAT_OGG; }else if(pcmFormat.wf.wFormatTag != WAVE_FORMAT_PCM){ WAVEFORMATEX dstWF; WAVEFORMATEX *pwfxInfo; WORD cbExtraAlloc; MMRESULT mmResult; lpReadFile->StreamReadFile(arcFileNum,stream,(char *)&cbExtraAlloc,sizeof(WORD)); pwfxInfo = (WAVEFORMATEX *)cl_malloc(sizeof(WAVEFORMATEX) +cbExtraAlloc); CopyMemory(pwfxInfo,&pcmFormat,sizeof(PCMWAVEFORMAT)); pwfxInfo->cbSize = cbExtraAlloc; lpReadFile->StreamReadFile(arcFileNum,stream,(char *)pwfxInfo +sizeof(WAVEFORMATEX),cbExtraAlloc); lpReadFile->StreamSeekFile(arcFileNum,stream,sizeof(RiffHead),FILE_BEGIN); lpReadFile->StreamReadFile(arcFileNum,stream,(char *)&fmtHead,sizeof(FmtHead)); dataTopOffset = sizeof(RiffHead) +sizeof(FmtHead); while(0!=strncmp(fmtHead.fmt,"data",4)){ lpReadFile->StreamSeekFile(arcFileNum,stream,fmtHead.size,FILE_CURRENT); dataTopOffset += fmtHead.size; lpReadFile->StreamReadFile(arcFileNum,stream,(char *)&fmtHead,sizeof(FmtHead)); dataTopOffset += sizeof(FmtHead); } ZeroMemory(&dstWF,sizeof(dstWF)); dstWF.wFormatTag = WAVE_FORMAT_PCM; mmResult = acmFormatSuggest( NULL, pwfxInfo, &dstWF, sizeof(dstWF), ACM_FORMATSUGGESTF_WFORMATTAG); if(mmResult != 0){ myOutputDebugString("オーディオ圧縮が無効です\n"); return FALSE; } if(NULL==lpDSBufferTop){ lpDSBufferTop = lpDSBufferTail = new ClSoundBuffer; }else{ lpDSBufferTail->lpNext = new ClSoundBuffer; lpDSBufferTail->lpNext->lpPrev = lpDSBufferTail; lpDSBufferTail = lpDSBufferTail->lpNext; } lpDSBufferTail->dataTopOffset = dataTopOffset; acmStreamOpen(&lpDSBufferTail->hAcm, NULL,pwfxInfo,&dstWF, NULL, 0L, 0L, ACM_STREAMOPENF_NONREALTIME); size = pwfxInfo->nAvgBytesPerSec; if(size % pwfxInfo->nBlockAlign){ size = (size/pwfxInfo->nBlockAlign +1)*pwfxInfo->nBlockAlign; } acmStreamSize(lpDSBufferTail->hAcm,size, &lpDSBufferTail->acmDst.dwStreamSize, ACM_STREAMSIZEF_SOURCE); acmStreamSize(lpDSBufferTail->hAcm, lpDSBufferTail->acmDst.dwStreamSize, &lpDSBufferTail->acmSrc.dwStreamSize, ACM_STREAMSIZEF_DESTINATION); acmStreamSize(lpDSBufferTail->hAcm, lpDSBufferTail->acmSrc.dwStreamSize, &lpDSBufferTail->acmDst.dwStreamSize, ACM_STREAMSIZEF_SOURCE); cl_free(pwfxInfo); if(fmtHead.size < lpDSBufferTail->acmSrc.dwStreamSize*2){ acmStreamClose(lpDSBufferTail->hAcm, 0); lpDSBufferTail->hAcm = NULL; lpReadFile->StreamCloseFile(arcFileNum,stream); if(lpDSBufferTop == lpDSBufferTail){ delete lpDSBufferTail; lpDSBufferTop = lpDSBufferTail = NULL; }else{ lpDSBufferTail = lpDSBufferTail->lpPrev; delete(lpDSBufferTail->lpNext); lpDSBufferTail->lpNext = NULL; } return -1; } lpDSBufferTail->acmSrc.lpStream = (LPBYTE)cl_malloc(lpDSBufferTail->acmSrc.dwStreamSize); lpDSBufferTail->acmDst.lpStream = (LPBYTE)cl_malloc(lpDSBufferTail->acmDst.dwStreamSize); ZeroMemory(&lpDSBufferTail->ash,sizeof(lpDSBufferTail->ash)); lpDSBufferTail->ash.cbStruct = sizeof(lpDSBufferTail->ash); lpDSBufferTail->ash.pbSrc = lpDSBufferTail->acmSrc.lpStream; lpDSBufferTail->ash.cbSrcLength = lpDSBufferTail->acmSrc.dwStreamSize; lpDSBufferTail->ash.dwSrcUser = lpDSBufferTail->acmSrc.dwStreamSize; lpDSBufferTail->ash.pbDst = lpDSBufferTail->acmDst.lpStream; lpDSBufferTail->ash.cbDstLength = lpDSBufferTail->acmDst.dwStreamSize; lpDSBufferTail->ash.dwDstUser = lpDSBufferTail->acmDst.dwStreamSize; acmStreamPrepareHeader(lpDSBufferTail->hAcm,&lpDSBufferTail->ash,0); DSBUFFERDESC dsbdesc; ZeroMemory(&dsbdesc, sizeof(DSBUFFERDESC)); dsbdesc.dwSize = sizeof(DSBUFFERDESC); dsbdesc.dwFlags = DSBCAPS_STATIC | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_LOCSOFTWARE | DSBCAPS_GLOBALFOCUS; dsbdesc.dwBufferBytes = lpDSBufferTail->acmDst.dwStreamSize *2; dsbdesc.lpwfxFormat = &dstWF; hr = lpDSound->CreateSoundBuffer(&dsbdesc, &lpTmpBuffer, NULL); lpTmpBuffer->QueryInterface(IID_IDirectSoundBuffer8,(LPVOID *)&lpDSBufferTail->lpDSBuffer); RELEASE(lpTmpBuffer); lpDSBufferTail->streamBlockSize = lpDSBufferTail->acmDst.dwStreamSize; }else{ dataTopOffset = sizeof(RiffHead) +sizeof(FmtHead) +fmtHead.size; lpReadFile->StreamSeekFile(arcFileNum,stream,fmtHead.size -sizeof(PCMWAVEFORMAT),FILE_CURRENT); lpReadFile->StreamReadFile(arcFileNum,stream,(char *)&fmtHead,sizeof(FmtHead)); dataTopOffset += sizeof(FmtHead); while(0!=strncmp(fmtHead.fmt,"data",4)){ lpReadFile->StreamSeekFile(arcFileNum,stream,fmtHead.size,FILE_CURRENT); dataTopOffset += fmtHead.size; lpReadFile->StreamReadFile(arcFileNum,stream,(char *)&fmtHead,sizeof(FmtHead)); dataTopOffset += sizeof(FmtHead); } if(fmtHead.size < pcmFormat.wf.nAvgBytesPerSec*2){ lpReadFile->StreamCloseFile(arcFileNum,stream); return -1; } if(NULL==lpDSBufferTop){ lpDSBufferTop = lpDSBufferTail = new ClSoundBuffer; }else{ lpDSBufferTail->lpNext = new ClSoundBuffer; lpDSBufferTail->lpNext->lpPrev = lpDSBufferTail; lpDSBufferTail = lpDSBufferTail->lpNext; } lpDSBufferTail->dataTopOffset = dataTopOffset; DSBUFFERDESC dsbdesc; WAVEFORMATEX audioFmt; ZeroMemory(&dsbdesc, sizeof(DSBUFFERDESC)); dsbdesc.dwSize = sizeof(DSBUFFERDESC); dsbdesc.dwFlags = DSBCAPS_STATIC | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_LOCSOFTWARE | DSBCAPS_GLOBALFOCUS; CopyMemory(&audioFmt,&pcmFormat,sizeof(WAVEFORMAT)); audioFmt.wBitsPerSample = pcmFormat.wBitsPerSample; audioFmt.cbSize = 0; dsbdesc.dwBufferBytes = audioFmt.nAvgBytesPerSec *2; dsbdesc.lpwfxFormat = &audioFmt; hr = lpDSound->CreateSoundBuffer(&dsbdesc, &lpTmpBuffer, NULL); lpTmpBuffer->QueryInterface(IID_IDirectSoundBuffer8,(LPVOID *)&lpDSBufferTail->lpDSBuffer); RELEASE(lpTmpBuffer); lpDSBufferTail->streamBlockSize = audioFmt.nAvgBytesPerSec; } lpDSBufferTail->arcFileNum = arcFileNum; lpDSBufferTail->musicNum = lpDSBufferTail->orgMusicNum = playNum; lpDSBufferTail->streamNum = stream; lpDSBufferTail->nextStream = nextStream; lpDSBufferTail->handle = handle; lpDSBufferTail->bufType = stream_sound; lpDSBufferTail->readFile = lpReadFile; lpDSBufferTail->wFormatTag = pcmFormat.wf.wFormatTag; return TRUE; } // ClSoundDS::CreateStreamBuffer
static void test_acmFormatSuggest(void) { WAVEFORMATEX src, dst; DWORD suggest; MMRESULT rc; /* Test a valid PCM format */ src.wFormatTag = WAVE_FORMAT_PCM; src.nChannels = 1; src.nSamplesPerSec = 8000; src.nAvgBytesPerSec = 16000; src.nBlockAlign = 2; src.wBitsPerSample = 16; src.cbSize = 0; suggest = 0; memset(&dst, 0, sizeof(dst)); rc = acmFormatSuggest(NULL, &src, &dst, sizeof(dst), suggest); ok(rc == MMSYSERR_NOERROR, "failed with error 0x%x\n", rc); todo_wine ok(src.wFormatTag == dst.wFormatTag, "expected %d, got %d\n", src.wFormatTag, dst.wFormatTag); ok(src.nChannels == dst.nChannels, "expected %d, got %d\n", src.nChannels, dst.nChannels); ok(src.nSamplesPerSec == dst.nSamplesPerSec, "expected %d, got %d\n", src.nSamplesPerSec, dst.nSamplesPerSec); todo_wine ok(src.nAvgBytesPerSec == dst.nAvgBytesPerSec, "expected %d, got %d\n", src.nAvgBytesPerSec, dst.nAvgBytesPerSec); todo_wine ok(src.nBlockAlign == dst.nBlockAlign, "expected %d, got %d\n", src.nBlockAlign, dst.nBlockAlign); todo_wine ok(src.wBitsPerSample == dst.wBitsPerSample, "expected %d, got %d\n", src.wBitsPerSample, dst.wBitsPerSample); /* All parameters from destination are valid */ suggest = ACM_FORMATSUGGESTF_NCHANNELS | ACM_FORMATSUGGESTF_NSAMPLESPERSEC | ACM_FORMATSUGGESTF_WBITSPERSAMPLE | ACM_FORMATSUGGESTF_WFORMATTAG; dst = src; rc = acmFormatSuggest(NULL, &src, &dst, sizeof(dst), suggest); ok(rc == MMSYSERR_NOERROR, "failed with error 0x%x\n", rc); ok(src.wFormatTag == dst.wFormatTag, "expected %d, got %d\n", src.wFormatTag, dst.wFormatTag); ok(src.nChannels == dst.nChannels, "expected %d, got %d\n", src.nChannels, dst.nChannels); ok(src.nSamplesPerSec == dst.nSamplesPerSec, "expected %d, got %d\n", src.nSamplesPerSec, dst.nSamplesPerSec); ok(src.nAvgBytesPerSec == dst.nAvgBytesPerSec, "expected %d, got %d\n", src.nAvgBytesPerSec, dst.nAvgBytesPerSec); ok(src.nBlockAlign == dst.nBlockAlign, "expected %d, got %d\n", src.nBlockAlign, dst.nBlockAlign); ok(src.wBitsPerSample == dst.wBitsPerSample, "expected %d, got %d\n", src.wBitsPerSample, dst.wBitsPerSample); /* Test for WAVE_FORMAT_MSRT24 used in Monster Truck Madness 2 */ src.wFormatTag = WAVE_FORMAT_MSRT24; src.nChannels = 1; src.nSamplesPerSec = 8000; src.nAvgBytesPerSec = 16000; src.nBlockAlign = 2; src.wBitsPerSample = 16; src.cbSize = 0; dst = src; suggest = ACM_FORMATSUGGESTF_NCHANNELS | ACM_FORMATSUGGESTF_NSAMPLESPERSEC | ACM_FORMATSUGGESTF_WBITSPERSAMPLE | ACM_FORMATSUGGESTF_WFORMATTAG; rc = acmFormatSuggest(NULL, &src, &dst, sizeof(dst), suggest); ok(rc == ACMERR_NOTPOSSIBLE, "failed with error 0x%x\n", rc); memset(&dst, 0, sizeof(dst)); suggest = 0; rc = acmFormatSuggest(NULL, &src, &dst, sizeof(dst), suggest); todo_wine ok(rc == MMSYSERR_INVALPARAM, "failed with error 0x%x\n", rc); /* Invalid struct size */ src.wFormatTag = WAVE_FORMAT_PCM; rc = acmFormatSuggest(NULL, &src, &dst, 0, suggest); todo_wine ok(rc == MMSYSERR_INVALPARAM, "failed with error 0x%x\n", rc); rc = acmFormatSuggest(NULL, &src, &dst, sizeof(dst) / 2, suggest); todo_wine ok(rc == MMSYSERR_INVALPARAM, "failed with error 0x%x\n", rc); /* cbSize is the last parameter and not required for PCM */ rc = acmFormatSuggest(NULL, &src, &dst, sizeof(dst) - 1, suggest); ok(rc == MMSYSERR_NOERROR, "failed with error 0x%x\n", rc); rc = acmFormatSuggest(NULL, &src, &dst, sizeof(dst) - sizeof(dst.cbSize), suggest); ok(rc == MMSYSERR_NOERROR, "failed with error 0x%x\n", rc); rc = acmFormatSuggest(NULL, &src, &dst, sizeof(dst) - sizeof(dst.cbSize) - 1, suggest); todo_wine ok(rc == MMSYSERR_INVALPARAM, "failed with error 0x%x\n", rc); /* cbSize is required for others */ src.wFormatTag = WAVE_FORMAT_ADPCM; rc = acmFormatSuggest(NULL, &src, &dst, sizeof(dst) - sizeof(dst.cbSize), suggest); todo_wine ok(rc == MMSYSERR_INVALPARAM, "failed with error 0x%x\n", rc); rc = acmFormatSuggest(NULL, &src, &dst, sizeof(dst) - 1, suggest); todo_wine ok(rc == MMSYSERR_INVALPARAM, "failed with error 0x%x\n", rc); /* Invalid suggest flags */ src.wFormatTag = WAVE_FORMAT_PCM; suggest = 0xFFFFFFFF; rc = acmFormatSuggest(NULL, &src, &dst, sizeof(dst), suggest); ok(rc == MMSYSERR_INVALFLAG, "failed with error 0x%x\n", rc); /* Invalid source and destination */ suggest = 0; rc = acmFormatSuggest(NULL, NULL, &dst, sizeof(dst), suggest); ok(rc == MMSYSERR_INVALPARAM, "failed with error 0x%x\n", rc); rc = acmFormatSuggest(NULL, &src, NULL, sizeof(dst), suggest); ok(rc == MMSYSERR_INVALPARAM, "failed with error 0x%x\n", rc); rc = acmFormatSuggest(NULL, NULL, NULL, sizeof(dst), suggest); ok(rc == MMSYSERR_INVALPARAM, "failed with error 0x%x\n", rc); }
void ConvertNode(HWND hwnd, AFile* node, const char* fname, WORD tag) { FSHandle* file; HANDLE wavfile; RIFFHeader riffhdr; ChunkHeader chunkhdr; DWORD riffsize,factsize,datasize,written,rate,buffpos,pcmsize,dstsize,sizeToFill,sizeFilled; DWORD pos_riffsize,pos_factsize,pos_datasize; WORD channels,bits; char str[MAX_PATH+100],*pcmBuffer=NULL,*dstBuffer=NULL; LPWAVEFORMATEX pwfex; ACMFORMATTAGDETAILS aftd={0}; MMRESULT mmr; WAVEFORMATEX wfexPCM; HACMSTREAM hACMStream; ACMSTREAMHEADER acmshdr; if ((file=FSOpenForPlayback(hwnd,node,&rate,&channels,&bits))==NULL) return; wfexPCM.wFormatTag=WAVE_FORMAT_PCM; wfexPCM.nChannels=channels; wfexPCM.nSamplesPerSec=rate; wfexPCM.wBitsPerSample=bits; wfexPCM.cbSize=0; wfexPCM.nBlockAlign=channels*(bits/8); wfexPCM.nAvgBytesPerSec=rate*wfexPCM.nBlockAlign; switch (tag) { case WAVE_FORMAT_PCM: pwfex=NULL; // ??? hACMStream=NULL; dstBuffer=NULL; // ??? pcmBuffer=(char*)GlobalAlloc(GPTR,BUFFERSIZE); break; default: aftd.cbStruct=sizeof(aftd); aftd.dwFormatTag=tag; mmr=acmFormatTagDetails(NULL,&aftd,ACM_FORMATTAGDETAILSF_LARGESTSIZE); if (mmr!=MMSYSERR_NOERROR) { AFPLUGIN(node)->ShutdownPlayback(file); FSCloseFile(file); wsprintf(str,"Failed to get details for wave format tag: 0x%X",tag); ReportMMError(hwnd,mmr,str); return; } pwfex=(LPWAVEFORMATEX)LocalAlloc(LPTR,aftd.cbFormatSize); pwfex->wFormatTag=tag; mmr=acmFormatSuggest(NULL,&wfexPCM,pwfex,aftd.cbFormatSize,ACM_FORMATSUGGESTF_WFORMATTAG); if (mmr!=MMSYSERR_NOERROR) { LocalFree(pwfex); AFPLUGIN(node)->ShutdownPlayback(file); FSCloseFile(file); wsprintf(str,"No format suggested for wave format tag: 0x%X",tag); ReportMMError(hwnd,mmr,str); return; } mmr=acmStreamOpen(&hACMStream,NULL,&wfexPCM,pwfex,NULL,0,0,ACM_STREAMOPENF_NONREALTIME); if (mmr!=MMSYSERR_NOERROR) { LocalFree(pwfex); AFPLUGIN(node)->ShutdownPlayback(file); FSCloseFile(file); wsprintf(str,"Failed to open conversion stream for wave format tag: 0x%X",tag); ReportMMError(hwnd,mmr,str); return; } if (acmStreamSize(hACMStream,BUFFERSIZE,&dstsize,ACM_STREAMSIZEF_SOURCE)!=MMSYSERR_NOERROR) dstsize=BUFFERSIZE; pcmBuffer=(char*)GlobalAlloc(GPTR,BUFFERSIZE); dstBuffer=(char*)GlobalAlloc(GPTR,dstsize); memset(&acmshdr,0x00,sizeof(acmshdr)); // ??? acmshdr.cbStruct=sizeof(ACMSTREAMHEADER); acmshdr.fdwStatus=0; acmshdr.pbSrc=pcmBuffer; acmshdr.cbSrcLength=BUFFERSIZE; acmshdr.cbSrcLengthUsed=0; acmshdr.pbDst=dstBuffer; acmshdr.cbDstLength=dstsize; acmshdr.cbDstLengthUsed=0; mmr=acmStreamPrepareHeader(hACMStream,&acmshdr,0L); if (mmr!=MMSYSERR_NOERROR) { GlobalFree(dstBuffer); GlobalFree(pcmBuffer); acmStreamClose(hACMStream,0); LocalFree(pwfex); AFPLUGIN(node)->ShutdownPlayback(file); FSCloseFile(file); ReportMMError(hwnd,mmr,"Failed to prepare conversion stream header."); return; } acmshdr.cbSrcLength=0; } if (!EnsureDirPresence(fname)) { if (hACMStream!=NULL) { acmStreamUnprepareHeader(hACMStream,&acmshdr,0L); acmStreamClose(hACMStream,0); } GlobalFree(dstBuffer); GlobalFree(pcmBuffer); LocalFree(pwfex); AFPLUGIN(node)->ShutdownPlayback(file); FSCloseFile(file); return; } wavfile=CreateFile(fname, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if (wavfile==INVALID_HANDLE_VALUE) { if (hACMStream!=NULL) { acmStreamUnprepareHeader(hACMStream,&acmshdr,0L); acmStreamClose(hACMStream,0); } GlobalFree(dstBuffer); GlobalFree(pcmBuffer); LocalFree(pwfex); AFPLUGIN(node)->ShutdownPlayback(file); FSCloseFile(file); wsprintf(str,"Cannot open WAV file: %s",fname); ReportError(hwnd,str,NULL); return; } ShowProgressHeaderMsg(fname); datasize=0; factsize=0; ShowProgressStateMsg("Writing RIFF header..."); SetFilePointer(wavfile,0,NULL,FILE_BEGIN); lstrcpy(riffhdr.riffid,IDSTR_RIFF); lstrcpy(riffhdr.rifftype,IDSTR_WAVE); riffhdr.riffsize=0; WriteFile(wavfile,&riffhdr,sizeof(RIFFHeader),&written,NULL); pos_riffsize=SetFilePointer(wavfile,0,NULL,FILE_CURRENT)-sizeof(riffhdr.rifftype)-sizeof(riffhdr.riffsize); CorrectOddPos(wavfile); ShowProgressStateMsg("Writing fmt chunk..."); lstrcpy(chunkhdr.id,IDSTR_fmt); switch (tag) { case WAVE_FORMAT_PCM: chunkhdr.size=sizeof(wfexPCM); WriteFile(wavfile,&chunkhdr,sizeof(chunkhdr),&written,NULL); WriteFile(wavfile,&wfexPCM,chunkhdr.size,&written,NULL); CorrectOddPos(wavfile); break; default: chunkhdr.size=aftd.cbFormatSize; WriteFile(wavfile,&chunkhdr,sizeof(chunkhdr),&written,NULL); WriteFile(wavfile,pwfex,chunkhdr.size,&written,NULL); CorrectOddPos(wavfile); lstrcpy(chunkhdr.id,IDSTR_fact); chunkhdr.size=sizeof(factsize); WriteFile(wavfile,&chunkhdr,sizeof(chunkhdr),&written,NULL); pos_factsize=SetFilePointer(wavfile,0,NULL,FILE_CURRENT); WriteFile(wavfile,&factsize,sizeof(factsize),&written,NULL); CorrectOddPos(wavfile); } lstrcpy(chunkhdr.id,IDSTR_data); chunkhdr.size=datasize; WriteFile(wavfile,&chunkhdr,sizeof(chunkhdr),&written,NULL); pos_datasize=SetFilePointer(wavfile,0,NULL,FILE_CURRENT)-sizeof(datasize); while (1) { if (IsCancelled()) break; switch (tag) { case WAVE_FORMAT_PCM: sizeToFill=BUFFERSIZE; sizeFilled=0; break; default: if (acmshdr.cbSrcLengthUsed!=0L) { memmove(pcmBuffer,pcmBuffer+acmshdr.cbSrcLengthUsed,acmshdr.cbSrcLength-acmshdr.cbSrcLengthUsed); acmshdr.cbSrcLength-=acmshdr.cbSrcLengthUsed; } if (acmshdr.cbSrcLength<BUFFERSIZE) sizeToFill=BUFFERSIZE-acmshdr.cbSrcLength; sizeFilled=acmshdr.cbSrcLength; } wsprintf(str,"Converting %s data block to PCM...",file->node->afID); ShowProgressStateMsg(str); pcmsize=0; if (sizeToFill>0) pcmsize=AFPLUGIN(node)->FillPCMBuffer(file,pcmBuffer+sizeFilled,sizeToFill,&buffpos); if (tag==WAVE_FORMAT_PCM) { if (pcmsize==0L) break; ShowProgressStateMsg("Writing WAV data block..."); WriteFile(wavfile,pcmBuffer,pcmsize,&written,NULL); if (written!=pcmsize) { ReportError(hwnd,"Failure writing WAV file.",NULL); SetCancelFlag(); break; } datasize+=written; } else { acmshdr.cbSrcLength+=pcmsize; if (acmshdr.cbSrcLength==0L) break; acmshdr.fdwStatus^=ACMSTREAMHEADER_STATUSF_DONE; acmshdr.cbSrcLengthUsed=0; acmshdr.cbDstLength=dstsize; acmshdr.cbDstLengthUsed=0; wsprintf(str,"Compressing PCM data block..."); ShowProgressStateMsg(str); mmr=acmStreamConvert(hACMStream,&acmshdr,ACM_STREAMCONVERTF_BLOCKALIGN); if (mmr!=MMSYSERR_NOERROR) { CloseHandle(wavfile); DeleteFile(fname); acmStreamUnprepareHeader(hACMStream,&acmshdr,0L); acmStreamClose(hACMStream,0); GlobalFree(dstBuffer); GlobalFree(pcmBuffer); LocalFree(pwfex); AFPLUGIN(node)->ShutdownPlayback(file); FSCloseFile(file); ReportMMError(hwnd,mmr,"Error during compression."); return; } if (acmshdr.cbSrcLengthUsed==0L) { acmshdr.fdwStatus^=ACMSTREAMHEADER_STATUSF_DONE; acmStreamConvert(hACMStream,&acmshdr,0L); } factsize+=acmshdr.cbSrcLengthUsed/wfexPCM.nBlockAlign; ShowProgressStateMsg("Writing WAV data block..."); WriteFile(wavfile,dstBuffer,acmshdr.cbDstLengthUsed,&written,NULL); if (written!=acmshdr.cbDstLengthUsed) { ReportError(hwnd,"Failure writing WAV file.",NULL); SetCancelFlag(); break; } datasize+=written; } ShowProgress(FSGetFilePointer(file),FSGetFileSize(file)); // ??? } if (IsCancelled()) { ShowProgressStateMsg("Deleting WAV file..."); CloseHandle(wavfile); DeleteFile(fname); } else { CorrectOddPos(wavfile); ShowProgressStateMsg("Rewriting WAV header..."); riffsize=GetFileSize(wavfile,NULL)-8; SetFilePointer(wavfile,pos_riffsize,NULL,FILE_BEGIN); WriteFile(wavfile,&riffsize,sizeof(riffsize),&written,NULL); if (tag!=WAVE_FORMAT_PCM) { SetFilePointer(wavfile,pos_factsize,NULL,FILE_BEGIN); WriteFile(wavfile,&factsize,sizeof(factsize),&written,NULL); } SetFilePointer(wavfile,pos_datasize,NULL,FILE_BEGIN); WriteFile(wavfile,&datasize,sizeof(datasize),&written,NULL); CloseHandle(wavfile); } if (hACMStream!=NULL) { ShowProgressStateMsg("Closing conversion stream..."); acmStreamUnprepareHeader(hACMStream,&acmshdr,0L); acmStreamClose(hACMStream,0); } ShowProgressStateMsg("Freeing conversion buffers..."); GlobalFree(dstBuffer); GlobalFree(pcmBuffer); LocalFree(pwfex); wsprintf(str,"Shutting down %s decoder...",file->node->afID); ShowProgressStateMsg(str); AFPLUGIN(node)->ShutdownPlayback(file); FSCloseFile(file); }
BOOL CPlayer::WavScanFile() { DWORD dwSamples = 0; DWORD dwBuf = 0, dwRead = 0; m_Reader.SetPointer(0, FILE_BEGIN); WAVEFORMATEX *pwfxSrc, wfxDst; pwfxSrc = NULL; // "RIFF" if (!m_Reader.Read((LPBYTE)&dwBuf, sizeof(dwBuf), &dwRead) || dwBuf != MAKEFOURCC('R', 'I', 'F', 'F')) return FALSE; // "WAVE" m_Reader.SetPointer(4, FILE_CURRENT); if (!m_Reader.Read((LPBYTE)&dwBuf, sizeof(dwBuf), &dwRead) || dwBuf != MAKEFOURCC('W', 'A', 'V', 'E')) goto fail; // "fmt " while (TRUE) { if (!m_Reader.Read((LPBYTE)&dwBuf, sizeof(dwBuf), &dwRead)) goto fail; if (dwBuf == MAKEFOURCC('f', 'm', 't', ' ')) break; if (!m_Reader.Read((LPBYTE)&dwBuf, sizeof(dwBuf), &dwRead)) goto fail; if (m_Reader.SetPointer(dwBuf, FILE_CURRENT) == MAXLONGLONG) goto fail; } if (!m_Reader.Read((LPBYTE)&dwBuf, sizeof(dwBuf), &dwRead) || dwRead != sizeof(DWORD)) goto fail; pwfxSrc = (WAVEFORMATEX*)new BYTE[dwBuf]; if (!m_Reader.Read((LPBYTE)pwfxSrc, dwBuf, &dwRead) || dwRead != dwBuf) goto fail; if (pwfxSrc->nBlockAlign > WAV_FILE_BUFF_LEN) goto fail; #if 1 memset(&wfxDst, 0, sizeof(wfxDst)); wfxDst.wFormatTag = WAVE_FORMAT_PCM; if (acmFormatSuggest(NULL, pwfxSrc, &wfxDst, sizeof(WAVEFORMATEX), ACM_FORMATSUGGESTF_WFORMATTAG) != 0) goto fail; #endif // "fact" or "data" m_Reader.SetPointer(dwBuf - dwRead, FILE_CURRENT); if (!m_Reader.Read((LPBYTE)&dwBuf, sizeof(dwBuf), &dwRead)) goto fail; if (dwBuf == MAKEFOURCC('f', 'a', 'c', 't')) { if (!m_Reader.Read((LPBYTE)&dwBuf, sizeof(dwBuf), &dwRead) || dwBuf != 4) goto fail; if (!m_Reader.Read((LPBYTE)&dwBuf, sizeof(dwBuf), &dwRead) || dwRead != sizeof(DWORD)) goto fail; dwSamples = dwBuf; if (!m_Reader.Read((LPBYTE)&dwBuf, sizeof(dwBuf), &dwRead) || dwRead != sizeof(DWORD)) goto fail; } // "data" //if (dwBuf != MAKEFOURCC('d', 'a', 't', 'a')) // goto fail; retry: while (dwBuf != MAKEFOURCC('d', 'a', 't', 'a')) { BYTE b; if (!m_Reader.Read(&b, sizeof(b), &dwRead) || !dwRead) goto fail; LPBYTE pb = (LPBYTE)&dwBuf; pb[0] = pb[1]; pb[1] = pb[2]; pb[2] = pb[3]; pb[3] = b; } if (!m_Reader.Read((LPBYTE)&dwBuf, sizeof(dwBuf), &dwRead) || !dwRead) goto fail; if (dwBuf == 0) goto retry; // データの準備 m_dwDataSize = dwBuf; m_llDataOffset = m_Reader.SetPointer(0, FILE_CURRENT); if (m_dwDataSize > m_Reader.GetSize() - m_llDataOffset) { m_dwDataSize = (DWORD)(m_Reader.GetSize() - m_llDataOffset); } if (pwfxSrc->wFormatTag == WAVE_FORMAT_PCM) { dwSamples = m_dwDataSize / (pwfxSrc->nChannels * pwfxSrc->wBitsPerSample / 8); wfxDst = *pwfxSrc; } else if (!dwSamples) { dwSamples = m_dwDataSize / pwfxSrc->nAvgBytesPerSec * pwfxSrc->nSamplesPerSec; } memset(&m_Info, 0, sizeof(m_Info)); m_Info.nChannels = wfxDst.nChannels; m_Info.nSamplingRate = wfxDst.nSamplesPerSec; m_Info.nBitRate = pwfxSrc->nAvgBytesPerSec * 8 / 1000; m_nDuration = dwSamples; #if 1 // ACMを開く if (acmStreamOpen(&m_hAcm, NULL, pwfxSrc, &wfxDst, NULL, 0, 0, ACM_STREAMOPENF_NONREALTIME)) goto fail; #endif m_pwfxSrc = pwfxSrc; m_pwfxDst = new WAVEFORMATEX; *m_pwfxDst = wfxDst; m_dwCurrentSize = 0; return TRUE; fail: m_Reader.Close(); if (pwfxSrc) delete pwfxSrc; return FALSE; }
bool VDAudioCodecW32::Init(const WAVEFORMATEX *pSrcFormat, const WAVEFORMATEX *pDstFormat, bool isCompression, const char *pDriverShortNameHint, bool throwOnError) { Shutdown(); SafeCopyWaveFormat(mSrcFormat, (const VDWaveFormat *)pSrcFormat); if (pDstFormat) SafeCopyWaveFormat(mDstFormat, (const VDWaveFormat *)pDstFormat); // enumerate IDs for all installed codecs ACMDriverList driverList(pDriverShortNameHint); // try one driver at a time MMRESULT res = 0; for(ACMDriverList::const_iterator it(driverList.begin()), itEnd(driverList.end()); it != itEnd; ++it) { const HACMDRIVERID driverId = *it; // open driver HACMDRIVER hDriver = NULL; if (acmDriverOpen(&hDriver, *it, 0)) continue; if (!pDstFormat) { VDASSERT(!isCompression); DWORD dwDstFormatSize = 0; VDVERIFY(!acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT, (LPVOID)&dwDstFormatSize)); if (dwDstFormatSize < sizeof(WAVEFORMATEX)) dwDstFormatSize = sizeof(WAVEFORMATEX); mDstFormat.resize(dwDstFormatSize); memset(mDstFormat.data(), 0, dwDstFormatSize); mDstFormat->mTag = WAVE_FORMAT_PCM; if (acmFormatSuggest(hDriver, (WAVEFORMATEX *)pSrcFormat, (WAVEFORMATEX *)mDstFormat.data(), dwDstFormatSize, ACM_FORMATSUGGESTF_WFORMATTAG)) { acmDriverClose(hDriver, NULL); continue; } // sanitize the destination format a bit if (mDstFormat->mSampleBits != 8 && mDstFormat->mSampleBits != 16) mDstFormat->mSampleBits = 16; if (mDstFormat->mChannels != 1 && mDstFormat->mChannels !=2) mDstFormat->mChannels = 2; mDstFormat->mBlockSize = (uint16)((mDstFormat->mSampleBits >> 3) * mDstFormat->mChannels); mDstFormat->mDataRate = mDstFormat->mBlockSize * mDstFormat->mSamplingRate; mDstFormat->mExtraSize = 0; mDstFormat.resize(sizeof(WAVEFORMATEX)); } // open conversion stream res = acmStreamOpen(&mhStream, hDriver, (WAVEFORMATEX *)pSrcFormat, (WAVEFORMATEX *)mDstFormat.data(), NULL, 0, 0, ACM_STREAMOPENF_NONREALTIME); if (!res) { mhDriver = hDriver; break; } // Aud-X accepts PCM/6ch but not WAVE_FORMAT_EXTENSIBLE/PCM/6ch. Argh. We attempt to work // around this by trying a PCM version if WFE doesn't work. if (isCompression) { // Need to put this somewhere. struct WaveFormatExtensibleW32 { WAVEFORMATEX mFormat; union { uint16 mBitDepth; uint16 mSamplesPerBlock; // may be zero, according to MSDN }; uint32 mChannelMask; GUID mGuid; }; static const GUID local_KSDATAFORMAT_SUBTYPE_PCM={ // so we don't have to bring in ksmedia.h WAVE_FORMAT_PCM, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }; if (pSrcFormat->wFormatTag == WAVE_FORMAT_EXTENSIBLE && pSrcFormat->cbSize >= sizeof(WaveFormatExtensibleW32) - sizeof(WAVEFORMATEX)) { const WaveFormatExtensibleW32& wfexex = *(const WaveFormatExtensibleW32 *)pSrcFormat; if (wfexex.mGuid == local_KSDATAFORMAT_SUBTYPE_PCM) { // Rewrite the format to be straight PCM and try again. vdstructex<VDWaveFormat> srcFormat2(mSrcFormat.data(), sizeof(VDWaveFormat)); srcFormat2->mExtraSize = 0; srcFormat2->mTag = WAVE_FORMAT_PCM; MMRESULT res2 = acmStreamOpen(&mhStream, hDriver, (WAVEFORMATEX *)srcFormat2.data(), (WAVEFORMATEX *)mDstFormat.data(), NULL, 0, 0, ACM_STREAMOPENF_NONREALTIME); if (!res2) { res = res2; mSrcFormat = srcFormat2; pSrcFormat = (WAVEFORMATEX *)mSrcFormat.data(); mhDriver = hDriver; break; } } } } acmDriverClose(hDriver, 0); }
AudioConverterStream::AudioConverterStream(WaveFormat sourceFormat, WaveFormat destFormat, WaveFormat** prevSourceFormats , int numPrevSourceFormats) : outBuffer(nullptr), outSize(0), outBufferAllocated(0), stream(nullptr), isProxy(false), m_failed(false), subConverter(nullptr), startOffset(0) { if (sourceFormat.GetSize() == destFormat.GetSize()) { LPWAVEFORMATEX src = static_cast<LPWAVEFORMATEX>(sourceFormat); LPWAVEFORMATEX dest = static_cast<LPWAVEFORMATEX>(destFormat); if (memcmp(src, dest, sourceFormat.GetSize()) == 0) { // Source and destination formats are identical, so we'll just pass the input through to // the output isProxy = true; return; } } MMRESULT mm = acmStreamOpen(&stream, nullptr, sourceFormat, destFormat, nullptr, 0, 0, ACM_STREAMOPENF_NONREALTIME); if (mm != MMSYSERR_NOERROR) { // Not supported directly, so try letting ACM suggest an intermediate format, so we can // perform the conversion in multiple stages. WaveFormat intermediateFormat; // This weird looping structure is because we must try all combinations of four flags, and // even when a given combination yields a valid suggestion, we must be able to backtrack and // continue looping (tryMoreSuggestions) if the conversion based on that suggestion later // fails or dead-ends. bool foundSuggest = false; int chan, samp, bits, form, done; for (done = 0; done < 1 && !foundSuggest; foundSuggest ? 0 : ++done) { for (chan = 1; chan >= 0 && !foundSuggest; foundSuggest ? 0 : --chan) { for (samp = 1; samp >= 0 && !foundSuggest; foundSuggest ? 0 : --samp) { for (bits = 0; bits <= 1 && !foundSuggest; foundSuggest ? 0 : ++bits) { for (form = 0; form <= 1 && !foundSuggest; foundSuggest ? 0 : ++form) { int flags = 0; flags |= chan ? ACM_FORMATSUGGESTF_NCHANNELS : 0; flags |= samp ? ACM_FORMATSUGGESTF_NSAMPLESPERSEC : 0; flags |= bits ? ACM_FORMATSUGGESTF_WBITSPERSAMPLE : 0; flags |= form ? ACM_FORMATSUGGESTF_WFORMATTAG : 0; intermediateFormat = destFormat; MMRESULT mmSuggest = acmFormatSuggest(NULL, sourceFormat, intermediateFormat, intermediateFormat.GetSize(), flags); if (mmSuggest == MMSYSERR_NOERROR) { // Got a possibly-valid suggestion, but it might be a suggestion to // do absolutely nothing (which would be bad), so we first make sure // there's some sort of change involved: if (!FormatsMatch(sourceFormat, intermediateFormat)) { // We got a suggestion foundSuggest = true; // Now check to see if it's identical to a previous conversion // state. If it is, then we'll revert foundSuggest to false to // prevent endless conversion cycles. for (int prev = 0; prev < numPrevSourceFormats && prevSourceFormats && foundSuggest; prev++) { WaveFormat& oldFormat = *prevSourceFormats[prev]; if (FormatsMatch(oldFormat, intermediateFormat)) { // We already went through this exact format foundSuggest = false; } } } } tryMoreSuggestions: continue; } } } } } if (!foundSuggest) { m_failed = true; return; } // we'll handle conversion to the intermediate format mm = acmStreamOpen(&stream, nullptr, sourceFormat, intermediateFormat, nullptr, 0, 0, ACM_STREAMOPENF_NONREALTIME); if (mm != MMSYSERR_NOERROR) { if (!done) { foundSuggest = false; goto tryMoreSuggestions; // continue the search } // reached dead end m_failed = true; return; } // create temporary updated conversion history for cycle prevention size_t prevSize = sizeof(WaveFormat*) * (numPrevSourceFormats + 1); WaveFormat** prevFormats = static_cast<WaveFormat**>(alloca(prevSize)); if (prevSourceFormats) { memcpy(prevFormats, prevSourceFormats, prevSize); } prevFormats[numPrevSourceFormats] = &sourceFormat; // delegate the rest of the conversion to a new converter (recursive construction) subConverter = new AudioConverterStream(intermediateFormat, destFormat, prevFormats, numPrevSourceFormats + 1); if (subConverter->m_failed) { delete subConverter; subConverter = nullptr; if (!done) { foundSuggest = false; goto tryMoreSuggestions; // continue the search } // reached dead end m_failed = true; return; } } // prepare the stream header memset(&header, 0, sizeof(ACMSTREAMHEADER)); header.cbStruct = sizeof(ACMSTREAMHEADER); header.pbSrc = inWorkBuffer; header.cbSrcLength = sizeof(inWorkBuffer); header.pbDst = outWorkBuffer; header.cbDstLength = sizeof(outWorkBuffer); mm = acmStreamPrepareHeader(stream, &header, 0); if (mm != MMSYSERR_NOERROR) { m_failed = true; } }
// // GetMediaType // HRESULT CSynthStream::GetMediaType(CMediaType *pmt) { CheckPointer(pmt,E_POINTER); // The caller must hold the state lock because this function // calls get_OutputFormat() and GetPCMFormatStructure(). // The function assumes that the state of the m_Synth // object does not change between the two calls. The // m_Synth object's state will not change if the // state lock is held. ASSERT(CritCheckIn(m_pParent->pStateLock())); WAVEFORMATEX *pwfex; SYNTH_OUTPUT_FORMAT ofCurrent; HRESULT hr = m_Synth->get_OutputFormat( &ofCurrent ); if(FAILED(hr)) { return hr; } if(SYNTH_OF_PCM == ofCurrent) { pwfex = (WAVEFORMATEX *) pmt->AllocFormatBuffer(sizeof(WAVEFORMATEX)); if(NULL == pwfex) { return E_OUTOFMEMORY; } m_Synth->GetPCMFormatStructure(pwfex); } else if(SYNTH_OF_MS_ADPCM == ofCurrent) { DWORD dwMaxWAVEFORMATEXSize; MMRESULT mmr = acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT, (void*)&dwMaxWAVEFORMATEXSize); // acmMetrics() returns 0 if no errors occur. if(0 != mmr) { return E_FAIL; } pwfex = (WAVEFORMATEX *) pmt->AllocFormatBuffer(dwMaxWAVEFORMATEXSize); if(NULL == pwfex) { return E_OUTOFMEMORY; } WAVEFORMATEX wfexSourceFormat; m_Synth->GetPCMFormatStructure(&wfexSourceFormat); ZeroMemory(pwfex, dwMaxWAVEFORMATEXSize); pwfex->wFormatTag = WAVE_FORMAT_ADPCM; pwfex->cbSize = (USHORT)(dwMaxWAVEFORMATEXSize - sizeof(WAVEFORMATEX)); pwfex->nChannels = wfexSourceFormat.nChannels; pwfex->nSamplesPerSec = wfexSourceFormat.nSamplesPerSec; mmr = acmFormatSuggest(NULL, &wfexSourceFormat, pwfex, dwMaxWAVEFORMATEXSize, ACM_FORMATSUGGESTF_WFORMATTAG | ACM_FORMATSUGGESTF_NSAMPLESPERSEC | ACM_FORMATSUGGESTF_NCHANNELS); // acmFormatSuggest() returns 0 if no errors occur. if(0 != mmr) { return E_FAIL; } } else { return E_UNEXPECTED; } return CreateAudioMediaType(pwfex, pmt, FALSE); }