예제 #1
0
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;
			}
		//}
	}
}
예제 #2
0
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;
}
예제 #3
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;
}
예제 #4
0
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;
}
예제 #5
0
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);
}
예제 #6
0
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;

			}

		//}

	}

}
예제 #7
0
//--------------------------------------------------------------------------------------------------
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);
}
예제 #8
0
/// <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;
}
예제 #9
0
파일: wavfile.c 프로젝트: UIKit0/wine-1
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;
}
예제 #10
0
파일: soundDS.cpp 프로젝트: 0xrofi/Aquaplus
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
예제 #11
0
파일: soundDS.cpp 프로젝트: 0xrofi/Aquaplus
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
예제 #12
0
파일: msacm.c 프로젝트: KoKuToru/wine
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);
}
예제 #13
0
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);
}
예제 #14
0
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;
}
예제 #15
0
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;
    }
}
예제 #17
0
//
// 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);
}