{1, 4, 22050}, {2, 4, 22050}, {1, 4, 44100}, {2, 4, 44100},
};
-#define NUM_PCM_FORMATS (sizeof(PCM_Formats) / sizeof(PCM_Formats[0]))
-#define NUM_ADPCM_FORMATS (sizeof(ADPCM_Formats) / sizeof(ADPCM_Formats[0]))
-
/***********************************************************************
* ADPCM_GetFormatIndex
*/
switch (wfx->wFormatTag)
{
case WAVE_FORMAT_PCM:
- hi = NUM_PCM_FORMATS;
+ hi = ARRAY_SIZE(PCM_Formats);
fmts = PCM_Formats;
break;
case WAVE_FORMAT_IMA_ADPCM:
- hi = NUM_ADPCM_FORMATS;
+ hi = ARRAY_SIZE(ADPCM_Formats);
fmts = ADPCM_Formats;
break;
default:
static void init_wfx_ima_adpcm(IMAADPCMWAVEFORMAT* awfx/*, DWORD nba*/)
{
- register WAVEFORMATEX* pwfx = &awfx->wfx;
+ WAVEFORMATEX* pwfx = &awfx->wfx;
/* we assume wFormatTag, nChannels, nSamplesPerSec and wBitsPerSample
* have been initialized... */
}
pwfx->cbSize = sizeof(WORD);
- awfx->wSamplesPerBlock = (pwfx->nBlockAlign - (4 * pwfx->nChannels) * 2) / pwfx->nChannels + 1;
+ awfx->wSamplesPerBlock = (pwfx->nBlockAlign - (4 * pwfx->nChannels)) * (2 / pwfx->nChannels) + 1;
pwfx->nAvgBytesPerSec = (pwfx->nSamplesPerSec * pwfx->nBlockAlign) / awfx->wSamplesPerBlock;
}
dst[1] = HIBYTE(s);
}
+/***********************************************************************
+ * W8
+ *
+ * Write a 8 bit sample
+ */
+static inline void W8(unsigned char* dst, short s)
+{
+ dst[0] = (unsigned char)((s + 32768) >> 8);
+}
+
+
+static inline void W8_16(unsigned char* dst, short s, int bytes)
+{
+ if(bytes == 1)
+ W8(dst, s);
+ else
+ W16(dst, s);
+}
+
/* IMA (or DVI) APDCM codec routines */
static const unsigned IMA_StepTable[89] =
}
}
-static void cvtMMima16K(PACMDRVSTREAMINSTANCE adsi,
- const unsigned char* src, LPDWORD nsrc,
- unsigned char* dst, LPDWORD ndst)
+static void cvtMMimaK(PACMDRVSTREAMINSTANCE adsi,
+ const unsigned char* src, LPDWORD nsrc,
+ unsigned char* dst, LPDWORD ndst)
{
- int sample;
- int stepIndex;
- int nsamp_blk = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxSrc)->wSamplesPerBlock;
- int nsamp;
+ int sample;
+ int stepIndex;
+ int nsamp_blk = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxSrc)->wSamplesPerBlock;
+ int nsamp;
+ int bytesPerSample = adsi->pwfxDst->wBitsPerSample / 8;
/* compute the number of entire blocks we can decode...
* it's the min of the number of entire blocks in source buffer and the number
* of entire blocks in destination buffer
*/
- DWORD nblock = min(*nsrc / adsi->pwfxSrc->nBlockAlign,
- *ndst / (nsamp_blk * 2));
+ DWORD nblock = min(*nsrc / adsi->pwfxSrc->nBlockAlign, *ndst / (nsamp_blk * bytesPerSample));
*nsrc = nblock * adsi->pwfxSrc->nBlockAlign;
- *ndst = nblock * nsamp_blk * 2;
+ *ndst = nblock * nsamp_blk * bytesPerSample;
nsamp_blk--; /* remove the sample in block header */
for (; nblock > 0; nblock--)
{
- const unsigned char* in_src = src;
+ const unsigned char* in_src = src;
- /* handle header first */
- sample = R16(src);
- stepIndex = (unsigned)*(src + 2);
+ /* handle header first */
+ sample = R16(src);
+ stepIndex = (unsigned)*(src + 2);
clamp_step_index(&stepIndex);
- src += 4;
- W16(dst, sample); dst += 2;
+ src += 4;
+ W8_16(dst, sample, bytesPerSample); dst += bytesPerSample;
- for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 2)
+ for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 2)
{
process_nibble(*src, &stepIndex, &sample);
- W16(dst, sample); dst += 2;
+ W8_16(dst, sample, bytesPerSample); dst += bytesPerSample;
process_nibble(*src++ >> 4, &stepIndex, &sample);
- W16(dst, sample); dst += 2;
- }
+ W8_16(dst, sample, bytesPerSample); dst += bytesPerSample;
+ }
/* we have now to realign the source pointer on block */
src = in_src + adsi->pwfxSrc->nBlockAlign;
}
/* generate header */
sampleL = R16(src); src += 2;
W16(dst, sampleL); dst += 2;
- *dst = (unsigned char)(unsigned)stepIndexL;
- dst += 2;
+ W16(dst, stepIndexL); dst += 2;
sampleR = R16(src); src += 2;
W16(dst, sampleR); dst += 2;
- *dst = (unsigned char)(unsigned)stepIndexR;
- dst += 2;
+ W16(dst, stepIndexR); dst += 2;
for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 8)
{
for (i = 0; i < 4; i++)
{
- code1 = generate_nibble(R16(src + (2 * i + 0) * 2 + 0),
+ code1 = generate_nibble(R16(src + (4 * i + 0) * 2),
&stepIndexL, &sampleL);
- code2 = generate_nibble(R16(src + (2 * i + 1) * 2 + 0),
+ code2 = generate_nibble(R16(src + (4 * i + 2) * 2),
&stepIndexL, &sampleL);
- *dst++ = (code1 << 4) | code2;
+ *dst++ = (code2 << 4) | code1;
}
for (i = 0; i < 4; i++)
{
- code1 = generate_nibble(R16(src + (2 * i + 0) * 2 + 1),
+ code1 = generate_nibble(R16(src + (4 * i + 1) * 2),
&stepIndexR, &sampleR);
- code2 = generate_nibble(R16(src + (2 * i + 1) * 2 + 1),
+ code2 = generate_nibble(R16(src + (4 * i + 3) * 2),
&stepIndexR, &sampleR);
- *dst++ = (code1 << 4) | code2;
+ *dst++ = (code2 << 4) | code1;
}
src += 32;
}
src += 2;
code2 = generate_nibble(R16(src), &stepIndex, &sample);
src += 2;
- *dst++ = (code1 << 4) | code2;
+ *dst++ = (code2 << 4) | code1;
}
dst = in_dst + adsi->pwfxDst->nBlockAlign;
}
{
add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
- add->wMid = 0x1;
- add->wPid = 0x22;
+ add->wMid = MM_MICROSOFT;
+ add->wPid = MM_MSFT_ACM_IMAADPCM;
add->vdwACM = 0x3320000;
add->vdwDriver = 0x04000000;
add->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
add->cFilterTags = 0;
add->hicon = NULL;
MultiByteToWideChar( CP_ACP, 0, "Microsoft IMA ADPCM", -1,
- add->szShortName, sizeof(add->szShortName)/sizeof(WCHAR) );
+ add->szShortName, ARRAY_SIZE(add->szShortName) );
MultiByteToWideChar( CP_ACP, 0, "Microsoft IMA ADPCM CODEC", -1,
- add->szLongName, sizeof(add->szLongName)/sizeof(WCHAR) );
+ add->szLongName, ARRAY_SIZE(add->szLongName) );
MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team...", -1,
- add->szCopyright, sizeof(add->szCopyright)/sizeof(WCHAR) );
+ add->szCopyright, ARRAY_SIZE(add->szCopyright) );
MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1,
- add->szLicensing, sizeof(add->szLicensing)/sizeof(WCHAR) );
+ add->szLicensing, ARRAY_SIZE(add->szLicensing) );
add->szFeatures[0] = 0;
return MMSYSERR_NOERROR;
aftd->dwFormatTagIndex = 1; /* WAVE_FORMAT_IMA_ADPCM is bigger than PCM */
break;
}
- /* fall thru */
+ /* fall through */
case ACM_FORMATTAGDETAILSF_FORMATTAG:
switch (aftd->dwFormatTag)
{
case 0:
aftd->dwFormatTag = WAVE_FORMAT_PCM;
aftd->cbFormatSize = sizeof(PCMWAVEFORMAT);
- aftd->cStandardFormats = NUM_PCM_FORMATS;
+ aftd->cStandardFormats = ARRAY_SIZE(PCM_Formats);
lstrcpyW(aftd->szFormatTag, szPcm);
break;
case 1:
aftd->dwFormatTag = WAVE_FORMAT_IMA_ADPCM;
aftd->cbFormatSize = sizeof(IMAADPCMWAVEFORMAT);
- aftd->cStandardFormats = NUM_ADPCM_FORMATS;
+ aftd->cStandardFormats = ARRAY_SIZE(ADPCM_Formats);
lstrcpyW(aftd->szFormatTag, szImaAdPcm);
break;
}
switch (afd->dwFormatTag)
{
case WAVE_FORMAT_PCM:
- if (afd->dwFormatIndex >= NUM_PCM_FORMATS) return ACMERR_NOTPOSSIBLE;
+ if (afd->dwFormatIndex >= ARRAY_SIZE(PCM_Formats)) return ACMERR_NOTPOSSIBLE;
afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels;
afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate;
afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits;
afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign;
break;
case WAVE_FORMAT_IMA_ADPCM:
- if (afd->dwFormatIndex >= NUM_ADPCM_FORMATS) return ACMERR_NOTPOSSIBLE;
+ if (afd->dwFormatIndex >= ARRAY_SIZE(ADPCM_Formats)) return ACMERR_NOTPOSSIBLE;
afd->pwfx->nChannels = ADPCM_Formats[afd->dwFormatIndex].nChannels;
afd->pwfx->nSamplesPerSec = ADPCM_Formats[afd->dwFormatIndex].rate;
afd->pwfx->wBitsPerSample = ADPCM_Formats[afd->dwFormatIndex].nBits;
- afd->pwfx->nBlockAlign = 1024;
- /* we got 4 bits per sample */
- afd->pwfx->nAvgBytesPerSec =
- (afd->pwfx->nSamplesPerSec * 4) / 8;
- if (afd->cbwfx >= sizeof(WAVEFORMATEX))
- afd->pwfx->cbSize = sizeof(WORD);
- if (afd->cbwfx >= sizeof(IMAADPCMWAVEFORMAT))
- ((IMAADPCMWAVEFORMAT*)afd->pwfx)->wSamplesPerBlock = (1024 - 4 * afd->pwfx->nChannels) * (2 / afd->pwfx->nChannels) + 1;
+ init_wfx_ima_adpcm((IMAADPCMWAVEFORMAT *)afd->pwfx);
break;
default:
WARN("Unsupported tag %08x\n", afd->dwFormatTag);
else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_IMA_ADPCM &&
adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
{
- /* resampling or mono <=> stereo not available
+ /* resampling or mono <=> stereo not available
* ADPCM algo only define 16 bit per sample output
+ * (The API seems to still allow 8 bit per sample output)
*/
- if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
- adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
- adsi->pwfxDst->wBitsPerSample != 16)
- goto theEnd;
+ if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
+ adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
+ (adsi->pwfxDst->wBitsPerSample != 16 && adsi->pwfxDst->wBitsPerSample != 8))
+ goto theEnd;
nspb = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxSrc)->wSamplesPerBlock;
TRACE("spb=%u\n", nspb);
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;
+ /* 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 = cvtMMimaK;
+ if (adsi->pwfxDst->wBitsPerSample == 8 && adsi->pwfxDst->nChannels == 1)
+ aad->convert = cvtMMimaK;
+ /* FIXME: Stereo support for 8bit samples*/
+ if (adsi->pwfxDst->wBitsPerSample == 8 && adsi->pwfxDst->nChannels == 2)
+ goto theEnd;
}
else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
adsi->pwfxDst->wFormatTag == WAVE_FORMAT_IMA_ADPCM)