📄 imaadp32.c
字号:
adfs->pwfxDst->wBitsPerSample = 4;
else
adfs->pwfxDst->wBitsPerSample = 16;
}
if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG))
{
if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
adfs->pwfxDst->wFormatTag = WAVE_FORMAT_IMA_ADPCM;
else
adfs->pwfxDst->wFormatTag = WAVE_FORMAT_PCM;
}
/* check if result is ok */
if (ADPCM_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
/* recompute other values */
switch (adfs->pwfxDst->wFormatTag)
{
case WAVE_FORMAT_PCM:
adfs->pwfxDst->nBlockAlign = (adfs->pwfxDst->nChannels * adfs->pwfxDst->wBitsPerSample) / 8;
adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxDst->nBlockAlign;
break;
case WAVE_FORMAT_IMA_ADPCM:
adfs->pwfxDst->nBlockAlign = 1024;
/* FIXME: not handling header overhead */
adfs->pwfxDst->nAvgBytesPerSec = ((adfs->pwfxDst->nSamplesPerSec * 4) / 8) * adfs->pwfxSrc->nChannels;
((IMAADPCMWAVEFORMAT*)adfs->pwfxDst)->wSamplesPerBlock = (1024 - 4 * adfs->pwfxSrc->nChannels) * (2 / adfs->pwfxSrc->nChannels) + 1;
TRACE("setting spb=%u\n", ((IMAADPCMWAVEFORMAT*)adfs->pwfxDst)->wSamplesPerBlock);
break;
default:
FIXME("\n");
break;
}
return MMSYSERR_NOERROR;
}
/***********************************************************************
* ADPCM_Reset
*
*/
static void ADPCM_Reset(PACMDRVSTREAMINSTANCE adsi, AcmAdpcmData* aad)
{
aad->stepIndexL = aad->stepIndexR = 0;
}
/***********************************************************************
* ADPCM_StreamOpen
*
*/
static LRESULT ADPCM_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
{
AcmAdpcmData* aad;
unsigned nspb;
assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC));
if (ADPCM_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF ||
ADPCM_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF)
return ACMERR_NOTPOSSIBLE;
aad = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmAdpcmData));
if (aad == 0) return MMSYSERR_NOMEM;
adsi->dwDriver = (DWORD)aad;
if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
{
goto theEnd;
}
else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_IMA_ADPCM &&
adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
{
/* resampling or mono <=> stereo not available
* ADPCM algo only define 16 bit per sample output
*/
if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
adsi->pwfxDst->wBitsPerSample != 16)
goto theEnd;
nspb = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxSrc)->wSamplesPerBlock;
TRACE("spb=%u\n", nspb);
/* we check that in a block, after the header, samples are present on
* 4-sample packet pattern
* we also check that the block alignement is bigger than the expected size
*/
if (((nspb - 1) & 3) != 0) goto theEnd;
if ((((nspb - 1) / 2) + 4) * adsi->pwfxSrc->nChannels < adsi->pwfxSrc->nBlockAlign)
goto theEnd;
/* adpcm decoding... */
if (adsi->pwfxDst->wBitsPerSample == 16 && adsi->pwfxDst->nChannels == 2)
aad->convert = cvtSSima16K;
if (adsi->pwfxDst->wBitsPerSample == 16 && adsi->pwfxDst->nChannels == 1)
aad->convert = cvtMMima16K;
}
else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
adsi->pwfxDst->wFormatTag == WAVE_FORMAT_IMA_ADPCM)
{
if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
adsi->pwfxSrc->wBitsPerSample != 16)
goto theEnd;
nspb = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxDst)->wSamplesPerBlock;
TRACE("spb=%u\n", nspb);
/* we check that in a block, after the header, samples are present on
* 4-sample packet pattern
* we also check that the block alignement is bigger than the expected size
*/
if (((nspb - 1) & 3) != 0) goto theEnd;
if ((((nspb - 1) / 2) + 4) * adsi->pwfxDst->nChannels < adsi->pwfxDst->nBlockAlign)
goto theEnd;
/* adpcm coding... */
if (adsi->pwfxSrc->wBitsPerSample == 16 && adsi->pwfxSrc->nChannels == 2)
aad->convert = cvtSS16imaK;
if (adsi->pwfxSrc->wBitsPerSample == 16 && adsi->pwfxSrc->nChannels == 1)
aad->convert = cvtMM16imaK;
}
else goto theEnd;
ADPCM_Reset(adsi, aad);
return MMSYSERR_NOERROR;
theEnd:
HeapFree(GetProcessHeap(), 0, aad);
adsi->dwDriver = 0L;
return MMSYSERR_NOTSUPPORTED;
}
/***********************************************************************
* ADPCM_StreamClose
*
*/
static LRESULT ADPCM_StreamClose(PACMDRVSTREAMINSTANCE adsi)
{
HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver);
return MMSYSERR_NOERROR;
}
/***********************************************************************
* ADPCM_round
*
*/
static inline DWORD ADPCM_round(DWORD a, DWORD b, DWORD c)
{
assert(a && b && c);
/* to be sure, always return an entire number of c... */
return ((double)a * (double)b + (double)c - 1) / (double)c;
}
/***********************************************************************
* ADPCM_StreamSize
*
*/
static LRESULT ADPCM_StreamSize(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMSIZE adss)
{
switch (adss->fdwSize)
{
case ACM_STREAMSIZEF_DESTINATION:
/* cbDstLength => cbSrcLength */
if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
adsi->pwfxDst->wFormatTag == WAVE_FORMAT_IMA_ADPCM)
{
/* don't take block overhead into account, doesn't matter too much */
adss->cbSrcLength = adss->cbDstLength * 4;
}
else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_IMA_ADPCM &&
adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
{
FIXME("misses the block header overhead\n");
adss->cbSrcLength = 256 + adss->cbDstLength / 4;
}
else
{
return MMSYSERR_NOTSUPPORTED;
}
break;
case ACM_STREAMSIZEF_SOURCE:
/* cbSrcLength => cbDstLength */
if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
adsi->pwfxDst->wFormatTag == WAVE_FORMAT_IMA_ADPCM)
{
FIXME("misses the block header overhead\n");
adss->cbDstLength = 256 + adss->cbSrcLength / 4;
}
else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_IMA_ADPCM &&
adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
{
/* don't take block overhead into account, doesn't matter too much */
adss->cbDstLength = adss->cbSrcLength * 4;
}
else
{
return MMSYSERR_NOTSUPPORTED;
}
break;
default:
WARN("Unsupported query %08lx\n", adss->fdwSize);
return MMSYSERR_NOTSUPPORTED;
}
return MMSYSERR_NOERROR;
}
/***********************************************************************
* ADPCM_StreamConvert
*
*/
static LRESULT ADPCM_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh)
{
AcmAdpcmData* aad = (AcmAdpcmData*)adsi->dwDriver;
DWORD nsrc = adsh->cbSrcLength;
DWORD ndst = adsh->cbDstLength;
if (adsh->fdwConvert &
~(ACM_STREAMCONVERTF_BLOCKALIGN|
ACM_STREAMCONVERTF_END|
ACM_STREAMCONVERTF_START))
{
FIXME("Unsupported fdwConvert (%08lx), ignoring it\n", adsh->fdwConvert);
}
/* ACM_STREAMCONVERTF_BLOCKALIGN
* currently all conversions are block aligned, so do nothing for this flag
* ACM_STREAMCONVERTF_END
* no pending data, so do nothing for this flag
*/
if ((adsh->fdwConvert & ACM_STREAMCONVERTF_START))
{
ADPCM_Reset(adsi, aad);
}
aad->convert(adsi, adsh->pbSrc, &nsrc, adsh->pbDst, &ndst);
adsh->cbSrcLengthUsed = nsrc;
adsh->cbDstLengthUsed = ndst;
return MMSYSERR_NOERROR;
}
/**************************************************************************
* ADPCM_DriverProc [exported]
*/
LRESULT CALLBACK ADPCM_DriverProc(DWORD dwDevID, HDRVR hDriv, UINT wMsg,
LPARAM dwParam1, LPARAM dwParam2)
{
TRACE("(%08lx %08lx %04x %08lx %08lx);\n",
dwDevID, (DWORD)hDriv, wMsg, dwParam1, dwParam2);
switch (wMsg)
{
case DRV_LOAD: return 1;
case DRV_FREE: return 1;
case DRV_OPEN: return ADPCM_drvOpen((LPSTR)dwParam1);
case DRV_CLOSE: return ADPCM_drvClose(dwDevID);
case DRV_ENABLE: return 1;
case DRV_DISABLE: return 1;
case DRV_QUERYCONFIGURE: return 1;
case DRV_CONFIGURE: MessageBoxA(0, "MSACM IMA ADPCM filter !", "Wine Driver", MB_OK); return 1;
case DRV_INSTALL: return DRVCNF_RESTART;
case DRV_REMOVE: return DRVCNF_RESTART;
case ACMDM_DRIVER_NOTIFY:
/* no caching from other ACM drivers is done so far */
return MMSYSERR_NOERROR;
case ACMDM_DRIVER_DETAILS:
return ADPCM_DriverDetails((PACMDRIVERDETAILSW)dwParam1);
case ACMDM_FORMATTAG_DETAILS:
return ADPCM_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2);
case ACMDM_FORMAT_DETAILS:
return ADPCM_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2);
case ACMDM_FORMAT_SUGGEST:
return ADPCM_FormatSuggest((PACMDRVFORMATSUGGEST)dwParam1);
case ACMDM_STREAM_OPEN:
return ADPCM_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1);
case ACMDM_STREAM_CLOSE:
return ADPCM_StreamClose((PACMDRVSTREAMINSTANCE)dwParam1);
case ACMDM_STREAM_SIZE:
return ADPCM_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2);
case ACMDM_STREAM_CONVERT:
return ADPCM_StreamConvert((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMHEADER)dwParam2);
case ACMDM_HARDWARE_WAVE_CAPS_INPUT:
case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT:
/* this converter is not a hardware driver */
case ACMDM_FILTERTAG_DETAILS:
case ACMDM_FILTER_DETAILS:
/* this converter is not a filter */
case ACMDM_STREAM_RESET:
/* only needed for asynchronous driver... we aren't, so just say it */
return MMSYSERR_NOTSUPPORTED;
case ACMDM_STREAM_PREPARE:
case ACMDM_STREAM_UNPREPARE:
/* nothing special to do here... so don't do anything */
return MMSYSERR_NOERROR;
default:
return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -