msacm32: Rewrite PCM conversion functions.
Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Andrew Eikum <aeikum@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
7f23bbe7f9
commit
cadedd73f9
|
@ -77,13 +77,16 @@ static DWORD PCM_drvClose(DWORD dwDevID)
|
|||
/* flags for fdwDriver */
|
||||
#define PCM_RESAMPLE 1
|
||||
|
||||
typedef void (*PCM_CONVERT_KEEP_RATE)(const unsigned char*, int, unsigned char*);
|
||||
|
||||
typedef void (*PCM_CONVERT_CHANGE_RATE)(const DWORD, const unsigned char*, DWORD*, const DWORD, unsigned char*, DWORD*);
|
||||
|
||||
/* data used while converting */
|
||||
typedef struct tagAcmPcmData {
|
||||
/* conversion routine, depending if rate conversion is required */
|
||||
union {
|
||||
void (*cvtKeepRate)(const unsigned char*, int, unsigned char*);
|
||||
void (*cvtChangeRate)(DWORD, const unsigned char*, LPDWORD,
|
||||
DWORD, unsigned char*, LPDWORD);
|
||||
PCM_CONVERT_KEEP_RATE cvtKeepRate;
|
||||
PCM_CONVERT_CHANGE_RATE cvtChangeRate;
|
||||
} cvt;
|
||||
} AcmPcmData;
|
||||
|
||||
|
@ -521,8 +524,6 @@ static void cvtSS2416K(const unsigned char* src, int ns, unsigned char* dst)
|
|||
}
|
||||
|
||||
|
||||
typedef void (*PCM_CONVERT_KEEP_RATE)(const unsigned char*, int, unsigned char*);
|
||||
|
||||
static const PCM_CONVERT_KEEP_RATE PCM_ConvertKeepRate[] = {
|
||||
cvtSS88K, cvtSM88K, cvtMS88K, cvtMM88K,
|
||||
cvtSS816K, cvtSM816K, cvtMS816K, cvtMM816K,
|
||||
|
@ -543,397 +544,416 @@ static const PCM_CONVERT_KEEP_RATE PCM_ConvertKeepRate[] = {
|
|||
* <M> is the number of bits of output channel (8 or 16)
|
||||
*
|
||||
*/
|
||||
static void cvtSS88C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
|
||||
DWORD dstRate, unsigned char* dst, LPDWORD ndst)
|
||||
{
|
||||
DWORD error = dstRate / 2;
|
||||
TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
|
||||
|
||||
while ((*ndst)--) {
|
||||
*dst++ = *src;
|
||||
*dst++ = *src;
|
||||
error = error + srcRate;
|
||||
while (error > dstRate) {
|
||||
src += 2;
|
||||
(*nsrc)--;
|
||||
if (*nsrc == 0)
|
||||
static void cvtSS88C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
|
||||
const DWORD dstRate, unsigned char *dst, DWORD *ndst)
|
||||
{
|
||||
DWORD error = srcRate / 2;
|
||||
DWORD maxSrc = *nsrc, maxDst = *ndst;
|
||||
*ndst = 0;
|
||||
for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
|
||||
error += dstRate;
|
||||
while (error > srcRate) {
|
||||
if (*ndst == maxDst)
|
||||
return;
|
||||
error = error - dstRate;
|
||||
(*ndst)++;
|
||||
error -= srcRate;
|
||||
|
||||
*dst++ = src[0];
|
||||
*dst++ = src[1];
|
||||
}
|
||||
src += 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void cvtSM88C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
|
||||
DWORD dstRate, unsigned char* dst, LPDWORD ndst)
|
||||
static void cvtSM88C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
|
||||
const DWORD dstRate, unsigned char *dst, DWORD *ndst)
|
||||
{
|
||||
DWORD error = dstRate / 2;
|
||||
TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
|
||||
DWORD error = srcRate / 2;
|
||||
DWORD maxSrc = *nsrc, maxDst = *ndst;
|
||||
*ndst = 0;
|
||||
for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
|
||||
error += dstRate;
|
||||
while (error > srcRate) {
|
||||
if (*ndst == maxDst)
|
||||
return;
|
||||
(*ndst)++;
|
||||
error -= srcRate;
|
||||
|
||||
while ((*ndst)--) {
|
||||
*dst++ = M8(src[0], src[1]);
|
||||
error = error + srcRate;
|
||||
while (error > dstRate) {
|
||||
}
|
||||
src += 2;
|
||||
(*nsrc)--;
|
||||
if (*nsrc == 0)
|
||||
return;
|
||||
error = error - dstRate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cvtMS88C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
|
||||
DWORD dstRate, unsigned char* dst, LPDWORD ndst)
|
||||
static void cvtMS88C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
|
||||
const DWORD dstRate, unsigned char *dst, DWORD *ndst)
|
||||
{
|
||||
DWORD error = dstRate / 2;
|
||||
TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
|
||||
|
||||
while ((*ndst)--) {
|
||||
*dst++ = *src;
|
||||
*dst++ = *src;
|
||||
error = error + srcRate;
|
||||
while (error > dstRate) {
|
||||
src++;
|
||||
(*nsrc)--;
|
||||
if (*nsrc == 0)
|
||||
DWORD error = srcRate / 2;
|
||||
DWORD maxSrc = *nsrc, maxDst = *ndst;
|
||||
*ndst = 0;
|
||||
for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
|
||||
error += dstRate;
|
||||
while (error > srcRate) {
|
||||
if (*ndst == maxDst)
|
||||
return;
|
||||
error = error - dstRate;
|
||||
(*ndst)++;
|
||||
error -= srcRate;
|
||||
|
||||
*dst++ = src[0];
|
||||
*dst++ = src[0];
|
||||
}
|
||||
src += 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void cvtMM88C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
|
||||
DWORD dstRate, unsigned char* dst, LPDWORD ndst)
|
||||
static void cvtMM88C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
|
||||
const DWORD dstRate, unsigned char *dst, DWORD *ndst)
|
||||
{
|
||||
DWORD error = dstRate / 2;
|
||||
TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
|
||||
|
||||
while ((*ndst)--) {
|
||||
*dst++ = *src;
|
||||
error = error + srcRate;
|
||||
while (error > dstRate) {
|
||||
src++;
|
||||
(*nsrc)--;
|
||||
if (*nsrc==0)
|
||||
DWORD error = srcRate / 2;
|
||||
DWORD maxSrc = *nsrc, maxDst = *ndst;
|
||||
*ndst = 0;
|
||||
for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
|
||||
error += dstRate;
|
||||
while (error > srcRate) {
|
||||
if (*ndst == maxDst)
|
||||
return;
|
||||
error = error - dstRate;
|
||||
(*ndst)++;
|
||||
error -= srcRate;
|
||||
|
||||
*dst++ = src[0];
|
||||
}
|
||||
src += 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void cvtSS816C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
|
||||
DWORD dstRate, unsigned char* dst, LPDWORD ndst)
|
||||
static void cvtSS816C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
|
||||
const DWORD dstRate, unsigned char *dst, DWORD *ndst)
|
||||
{
|
||||
DWORD error = dstRate / 2;
|
||||
TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
|
||||
DWORD error = srcRate / 2;
|
||||
DWORD maxSrc = *nsrc, maxDst = *ndst;
|
||||
*ndst = 0;
|
||||
for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
|
||||
error += dstRate;
|
||||
while (error > srcRate) {
|
||||
if (*ndst == maxDst)
|
||||
return;
|
||||
(*ndst)++;
|
||||
error -= srcRate;
|
||||
|
||||
while ((*ndst)--) {
|
||||
W16(dst, C816(src[0])); dst += 2;
|
||||
W16(dst, C816(src[1])); dst += 2;
|
||||
error = error + srcRate;
|
||||
while (error > dstRate) {
|
||||
}
|
||||
src += 2;
|
||||
(*nsrc)--;
|
||||
if (*nsrc==0)
|
||||
return;
|
||||
error = error - dstRate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cvtSM816C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
|
||||
DWORD dstRate, unsigned char* dst, LPDWORD ndst)
|
||||
static void cvtSM816C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
|
||||
const DWORD dstRate, unsigned char *dst, DWORD *ndst)
|
||||
{
|
||||
DWORD error = dstRate / 2;
|
||||
TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
|
||||
DWORD error = srcRate / 2;
|
||||
DWORD maxSrc = *nsrc, maxDst = *ndst;
|
||||
*ndst = 0;
|
||||
for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
|
||||
error += dstRate;
|
||||
while (error > srcRate) {
|
||||
if (*ndst == maxDst)
|
||||
return;
|
||||
(*ndst)++;
|
||||
error -= srcRate;
|
||||
|
||||
while ((*ndst)--) {
|
||||
W16(dst, M16(C816(src[0]), C816(src[1]))); dst += 2;
|
||||
error = error + srcRate;
|
||||
while (error > dstRate) {
|
||||
}
|
||||
src += 2;
|
||||
(*nsrc)--;
|
||||
if (*nsrc==0)
|
||||
return;
|
||||
error = error - dstRate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cvtMS816C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
|
||||
DWORD dstRate, unsigned char* dst, LPDWORD ndst)
|
||||
static void cvtMS816C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
|
||||
const DWORD dstRate, unsigned char *dst, DWORD *ndst)
|
||||
{
|
||||
DWORD error = dstRate / 2;
|
||||
TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
|
||||
|
||||
while ((*ndst)--) {
|
||||
W16(dst, C816(*src)); dst += 2;
|
||||
W16(dst, C816(*src)); dst += 2;
|
||||
error = error + srcRate;
|
||||
while (error > dstRate) {
|
||||
src++;
|
||||
(*nsrc)--;
|
||||
if (*nsrc==0)
|
||||
DWORD error = srcRate / 2;
|
||||
DWORD maxSrc = *nsrc, maxDst = *ndst;
|
||||
*ndst = 0;
|
||||
for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
|
||||
error += dstRate;
|
||||
while (error > srcRate) {
|
||||
if (*ndst == maxDst)
|
||||
return;
|
||||
error = error - dstRate;
|
||||
(*ndst)++;
|
||||
error -= srcRate;
|
||||
|
||||
W16(dst, C816(src[0])); dst += 2;
|
||||
W16(dst, C816(src[0])); dst += 2;
|
||||
}
|
||||
src += 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void cvtMM816C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
|
||||
DWORD dstRate, unsigned char* dst, LPDWORD ndst)
|
||||
static void cvtMM816C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
|
||||
const DWORD dstRate, unsigned char *dst, DWORD *ndst)
|
||||
{
|
||||
DWORD error = dstRate / 2;
|
||||
TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
|
||||
|
||||
while ((*ndst)--) {
|
||||
W16(dst, C816(*src)); dst += 2;
|
||||
error = error + srcRate;
|
||||
while (error > dstRate) {
|
||||
src++;
|
||||
(*nsrc)--;
|
||||
if (*nsrc==0)
|
||||
DWORD error = srcRate / 2;
|
||||
DWORD maxSrc = *nsrc, maxDst = *ndst;
|
||||
*ndst = 0;
|
||||
for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
|
||||
error += dstRate;
|
||||
while (error > srcRate) {
|
||||
if (*ndst == maxDst)
|
||||
return;
|
||||
error = error - dstRate;
|
||||
(*ndst)++;
|
||||
error -= srcRate;
|
||||
|
||||
W16(dst, C816(src[0])); dst += 2;
|
||||
}
|
||||
src += 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void cvtSS168C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
|
||||
DWORD dstRate, unsigned char* dst, LPDWORD ndst)
|
||||
static void cvtSS168C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
|
||||
const DWORD dstRate, unsigned char *dst, DWORD *ndst)
|
||||
{
|
||||
DWORD error = dstRate / 2;
|
||||
TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
|
||||
DWORD error = srcRate / 2;
|
||||
DWORD maxSrc = *nsrc, maxDst = *ndst;
|
||||
*ndst = 0;
|
||||
for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
|
||||
error += dstRate;
|
||||
while (error > srcRate) {
|
||||
if (*ndst == maxDst)
|
||||
return;
|
||||
(*ndst)++;
|
||||
error -= srcRate;
|
||||
|
||||
while ((*ndst)--) {
|
||||
*dst++ = C168(R16(src));
|
||||
*dst++ = C168(R16(src + 2));
|
||||
error = error + srcRate;
|
||||
while (error > dstRate) {
|
||||
}
|
||||
src += 4;
|
||||
(*nsrc)--;
|
||||
if (*nsrc==0)
|
||||
return;
|
||||
error = error - dstRate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cvtSM168C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
|
||||
DWORD dstRate, unsigned char* dst, LPDWORD ndst)
|
||||
static void cvtSM168C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
|
||||
const DWORD dstRate, unsigned char *dst, DWORD *ndst)
|
||||
{
|
||||
DWORD error = dstRate / 2;
|
||||
TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
|
||||
DWORD error = srcRate / 2;
|
||||
DWORD maxSrc = *nsrc, maxDst = *ndst;
|
||||
*ndst = 0;
|
||||
for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
|
||||
error += dstRate;
|
||||
while (error > srcRate) {
|
||||
if (*ndst == maxDst)
|
||||
return;
|
||||
(*ndst)++;
|
||||
error -= srcRate;
|
||||
|
||||
while ((*ndst)--) {
|
||||
*dst++ = C168(M16(R16(src), R16(src + 2)));
|
||||
error = error + srcRate;
|
||||
while (error > dstRate) {
|
||||
}
|
||||
src += 4;
|
||||
(*nsrc)--;
|
||||
if (*nsrc==0)
|
||||
return;
|
||||
error = error - dstRate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cvtMS168C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
|
||||
DWORD dstRate, unsigned char* dst, LPDWORD ndst)
|
||||
static void cvtMS168C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
|
||||
const DWORD dstRate, unsigned char *dst, DWORD *ndst)
|
||||
{
|
||||
DWORD error = dstRate / 2;
|
||||
TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
|
||||
DWORD error = srcRate / 2;
|
||||
DWORD maxSrc = *nsrc, maxDst = *ndst;
|
||||
*ndst = 0;
|
||||
for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
|
||||
error += dstRate;
|
||||
while (error > srcRate) {
|
||||
if (*ndst == maxDst)
|
||||
return;
|
||||
(*ndst)++;
|
||||
error -= srcRate;
|
||||
|
||||
while ((*ndst)--) {
|
||||
*dst++ = C168(R16(src));
|
||||
*dst++ = C168(R16(src));
|
||||
error = error + srcRate;
|
||||
while (error > dstRate) {
|
||||
}
|
||||
src += 2;
|
||||
(*nsrc)--;
|
||||
if (*nsrc==0)
|
||||
return;
|
||||
error = error - dstRate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cvtMM168C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
|
||||
DWORD dstRate, unsigned char* dst, LPDWORD ndst)
|
||||
static void cvtMM168C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
|
||||
const DWORD dstRate, unsigned char *dst, DWORD *ndst)
|
||||
{
|
||||
DWORD error = dstRate / 2;
|
||||
TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
|
||||
DWORD error = srcRate / 2;
|
||||
DWORD maxSrc = *nsrc, maxDst = *ndst;
|
||||
*ndst = 0;
|
||||
for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
|
||||
error += dstRate;
|
||||
while (error > srcRate) {
|
||||
if (*ndst == maxDst)
|
||||
return;
|
||||
(*ndst)++;
|
||||
error -= srcRate;
|
||||
|
||||
while ((*ndst)--) {
|
||||
*dst++ = C168(R16(src));
|
||||
error = error + srcRate;
|
||||
while (error > dstRate) {
|
||||
}
|
||||
src += 2;
|
||||
(*nsrc)--;
|
||||
if (*nsrc == 0)
|
||||
return;
|
||||
error = error - dstRate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cvtSS1616C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
|
||||
DWORD dstRate, unsigned char* dst, LPDWORD ndst)
|
||||
static void cvtSS1616C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
|
||||
const DWORD dstRate, unsigned char *dst, DWORD *ndst)
|
||||
{
|
||||
DWORD error = dstRate / 2;
|
||||
TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
|
||||
DWORD error = srcRate / 2;
|
||||
DWORD maxSrc = *nsrc, maxDst = *ndst;
|
||||
*ndst = 0;
|
||||
for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
|
||||
error += dstRate;
|
||||
while (error > srcRate) {
|
||||
if (*ndst == maxDst)
|
||||
return;
|
||||
(*ndst)++;
|
||||
error -= srcRate;
|
||||
|
||||
while ((*ndst)--) {
|
||||
W16(dst, R16(src)); dst += 2;
|
||||
W16(dst, R16(src)); dst += 2;
|
||||
error = error + srcRate;
|
||||
while (error > dstRate) {
|
||||
W16(dst, R16(src + 2)); dst += 2;
|
||||
}
|
||||
src += 4;
|
||||
(*nsrc)--;
|
||||
if (*nsrc == 0)
|
||||
return;
|
||||
error = error - dstRate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cvtSM1616C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
|
||||
DWORD dstRate, unsigned char* dst, LPDWORD ndst)
|
||||
static void cvtSM1616C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
|
||||
const DWORD dstRate, unsigned char *dst, DWORD *ndst)
|
||||
{
|
||||
DWORD error = dstRate / 2;
|
||||
TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
|
||||
DWORD error = srcRate / 2;
|
||||
DWORD maxSrc = *nsrc, maxDst = *ndst;
|
||||
*ndst = 0;
|
||||
for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
|
||||
error += dstRate;
|
||||
while (error > srcRate) {
|
||||
if (*ndst == maxDst)
|
||||
return;
|
||||
(*ndst)++;
|
||||
error -= srcRate;
|
||||
|
||||
while ((*ndst)--) {
|
||||
W16(dst, M16(R16(src), R16(src + 2))); dst += 2;
|
||||
error = error + srcRate;
|
||||
while (error > dstRate) {
|
||||
}
|
||||
src += 4;
|
||||
(*nsrc)--;
|
||||
if (*nsrc == 0)
|
||||
return;
|
||||
error = error - dstRate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cvtMS1616C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
|
||||
DWORD dstRate, unsigned char* dst, LPDWORD ndst)
|
||||
static void cvtMS1616C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
|
||||
const DWORD dstRate, unsigned char *dst, DWORD *ndst)
|
||||
{
|
||||
DWORD error = dstRate / 2;
|
||||
TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
|
||||
DWORD error = srcRate / 2;
|
||||
DWORD maxSrc = *nsrc, maxDst = *ndst;
|
||||
*ndst = 0;
|
||||
for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
|
||||
error += dstRate;
|
||||
while (error > srcRate) {
|
||||
if (*ndst == maxDst)
|
||||
return;
|
||||
(*ndst)++;
|
||||
error -= srcRate;
|
||||
|
||||
while((*ndst)--) {
|
||||
W16(dst, R16(src)); dst += 2;
|
||||
W16(dst, R16(src)); dst += 2;
|
||||
error = error + srcRate;
|
||||
while (error > dstRate) {
|
||||
}
|
||||
src += 2;
|
||||
(*nsrc)--;
|
||||
if (*nsrc == 0)
|
||||
return;
|
||||
error = error - dstRate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cvtMM1616C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
|
||||
DWORD dstRate, unsigned char* dst, LPDWORD ndst)
|
||||
static void cvtMM1616C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
|
||||
const DWORD dstRate, unsigned char *dst, DWORD *ndst)
|
||||
{
|
||||
DWORD error = dstRate / 2;
|
||||
TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
|
||||
DWORD error = srcRate / 2;
|
||||
DWORD maxSrc = *nsrc, maxDst = *ndst;
|
||||
*ndst = 0;
|
||||
for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
|
||||
error += dstRate;
|
||||
while (error > srcRate) {
|
||||
if (*ndst == maxDst)
|
||||
return;
|
||||
(*ndst)++;
|
||||
error -= srcRate;
|
||||
|
||||
while ((*ndst)--) {
|
||||
W16(dst, R16(src)); dst += 2;
|
||||
error = error + srcRate;
|
||||
while (error > dstRate) {
|
||||
}
|
||||
src += 2;
|
||||
(*nsrc)--;
|
||||
if (*nsrc == 0)
|
||||
return;
|
||||
error = error - dstRate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cvtSS2424C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
|
||||
DWORD dstRate, unsigned char* dst, LPDWORD ndst)
|
||||
static void cvtSS2424C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
|
||||
const DWORD dstRate, unsigned char *dst, DWORD *ndst)
|
||||
{
|
||||
DWORD error = dstRate / 2;
|
||||
TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
|
||||
DWORD error = srcRate / 2;
|
||||
DWORD maxSrc = *nsrc, maxDst = *ndst;
|
||||
*ndst = 0;
|
||||
for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
|
||||
error += dstRate;
|
||||
while (error > srcRate) {
|
||||
if (*ndst == maxDst)
|
||||
return;
|
||||
(*ndst)++;
|
||||
error -= srcRate;
|
||||
|
||||
while ((*ndst)--) {
|
||||
W24(dst, R24(src)); dst += 3;
|
||||
W24(dst, R24(src)); dst += 3;
|
||||
error = error + srcRate;
|
||||
while (error > dstRate) {
|
||||
W24(dst, R24(src + 3)); dst += 3;
|
||||
}
|
||||
src += 6;
|
||||
(*nsrc)--;
|
||||
if (*nsrc == 0)
|
||||
return;
|
||||
error = error - dstRate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cvtSM2424C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
|
||||
DWORD dstRate, unsigned char* dst, LPDWORD ndst)
|
||||
static void cvtSM2424C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
|
||||
const DWORD dstRate, unsigned char *dst, DWORD *ndst)
|
||||
{
|
||||
DWORD error = dstRate / 2;
|
||||
TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
|
||||
DWORD error = srcRate / 2;
|
||||
DWORD maxSrc = *nsrc, maxDst = *ndst;
|
||||
*ndst = 0;
|
||||
for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
|
||||
error += dstRate;
|
||||
while (error > srcRate) {
|
||||
if (*ndst == maxDst)
|
||||
return;
|
||||
(*ndst)++;
|
||||
error -= srcRate;
|
||||
|
||||
while ((*ndst)--) {
|
||||
W24(dst, M24(R24(src), R24(src + 3))); dst += 3;
|
||||
error = error + srcRate;
|
||||
while (error > dstRate) {
|
||||
}
|
||||
src += 6;
|
||||
(*nsrc)--;
|
||||
if (*nsrc == 0)
|
||||
return;
|
||||
error = error - dstRate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cvtMS2424C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
|
||||
DWORD dstRate, unsigned char* dst, LPDWORD ndst)
|
||||
static void cvtMS2424C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
|
||||
const DWORD dstRate, unsigned char *dst, DWORD *ndst)
|
||||
{
|
||||
DWORD error = dstRate / 2;
|
||||
TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
|
||||
|
||||
while((*ndst)--) {
|
||||
W24(dst, R24(src)); dst += 3;
|
||||
W24(dst, R24(src)); dst += 3;
|
||||
error = error + srcRate;
|
||||
while (error > dstRate) {
|
||||
src += 3;
|
||||
(*nsrc)--;
|
||||
if (*nsrc == 0)
|
||||
DWORD error = srcRate / 2;
|
||||
DWORD maxSrc = *nsrc, maxDst = *ndst;
|
||||
*ndst = 0;
|
||||
for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
|
||||
error += dstRate;
|
||||
while (error > srcRate) {
|
||||
if (*ndst == maxDst)
|
||||
return;
|
||||
error = error - dstRate;
|
||||
(*ndst)++;
|
||||
error -= srcRate;
|
||||
|
||||
W24(dst, R24(src)); dst += 3;
|
||||
W24(dst, R24(src)); dst += 3;
|
||||
}
|
||||
src += 3;
|
||||
}
|
||||
}
|
||||
|
||||
static void cvtMM2424C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
|
||||
DWORD dstRate, unsigned char* dst, LPDWORD ndst)
|
||||
static void cvtMM2424C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
|
||||
const DWORD dstRate, unsigned char *dst, DWORD *ndst)
|
||||
{
|
||||
DWORD error = dstRate / 2;
|
||||
TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
|
||||
|
||||
while ((*ndst)--) {
|
||||
W24(dst, R24(src)); dst += 3;
|
||||
error = error + srcRate;
|
||||
while (error > dstRate) {
|
||||
src += 3;
|
||||
(*nsrc)--;
|
||||
if (*nsrc == 0)
|
||||
DWORD error = srcRate / 2;
|
||||
DWORD maxSrc = *nsrc, maxDst = *ndst;
|
||||
*ndst = 0;
|
||||
for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
|
||||
error += dstRate;
|
||||
while (error > srcRate) {
|
||||
if (*ndst == maxDst)
|
||||
return;
|
||||
error = error - dstRate;
|
||||
}
|
||||
}
|
||||
}
|
||||
(*ndst)++;
|
||||
error -= srcRate;
|
||||
|
||||
typedef void (*PCM_CONVERT_CHANGE_RATE)(DWORD, const unsigned char*, LPDWORD, DWORD, unsigned char*, LPDWORD);
|
||||
W24(dst, R24(src)); dst += 3;
|
||||
}
|
||||
src += 3;
|
||||
}
|
||||
}
|
||||
|
||||
static const PCM_CONVERT_CHANGE_RATE PCM_ConvertChangeRate[] = {
|
||||
cvtSS88C, cvtSM88C, cvtMS88C, cvtMM88C,
|
||||
|
@ -1287,12 +1307,8 @@ static LRESULT PCM_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER
|
|||
|
||||
/* do the job */
|
||||
if (adsi->fdwDriver & PCM_RESAMPLE) {
|
||||
DWORD nsrc2 = nsrc;
|
||||
DWORD ndst2 = ndst;
|
||||
apd->cvt.cvtChangeRate(adsi->pwfxSrc->nSamplesPerSec, adsh->pbSrc, &nsrc2,
|
||||
adsi->pwfxDst->nSamplesPerSec, adsh->pbDst, &ndst2);
|
||||
nsrc -= nsrc2;
|
||||
ndst -= ndst2;
|
||||
apd->cvt.cvtChangeRate(adsi->pwfxSrc->nSamplesPerSec, adsh->pbSrc, &nsrc,
|
||||
adsi->pwfxDst->nSamplesPerSec, adsh->pbDst, &ndst);
|
||||
} else {
|
||||
if (nsrc < ndst) ndst = nsrc; else nsrc = ndst;
|
||||
|
||||
|
|
|
@ -1042,6 +1042,104 @@ todo_wine
|
|||
ok(mr == MMSYSERR_NOERROR, "close failed: 0x%x\n", mr);
|
||||
}
|
||||
|
||||
static const BYTE input[64] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63};
|
||||
|
||||
struct stream_output
|
||||
{
|
||||
WAVEFORMATEX src;
|
||||
WAVEFORMATEX dst;
|
||||
BYTE output[256];
|
||||
DWORD dst_used;
|
||||
BOOL todo;
|
||||
};
|
||||
|
||||
static const struct stream_output expected_output[] = {
|
||||
/* #0: Identical conversion */
|
||||
{{WAVE_FORMAT_PCM, 1, 8000, 8000, 1, 8}, {WAVE_FORMAT_PCM, 1, 8000, 8000, 1, 8}, {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63}, 64, FALSE},
|
||||
|
||||
/* #1: 1 -> 2 channels */
|
||||
{{WAVE_FORMAT_PCM, 1, 8000, 8000, 1, 8}, {WAVE_FORMAT_PCM, 2, 8000, 16000, 2, 8}, {0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,45,45,46,46,47,47,48,48,49,49,50,50,51,51,52,52,53,53,54,54,55,55,56,56,57,57,58,58,59,59,60,60,61,61,62,62,63,63}, 128, FALSE},
|
||||
|
||||
/* #2: 2 -> 1 channels: all of the audio underflows due to addition */
|
||||
{{WAVE_FORMAT_PCM, 2, 8000, 16000, 2, 8}, {WAVE_FORMAT_PCM, 1, 8000, 8000, 1, 8}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 32, FALSE},
|
||||
|
||||
/* #3: 2 -> 2 channels */
|
||||
{{WAVE_FORMAT_PCM, 2, 8000, 16000, 2, 8}, {WAVE_FORMAT_PCM, 2, 8000, 16000, 2, 8}, {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63}, 64, FALSE},
|
||||
|
||||
/* #4: 8 -> 16 bits per sample */
|
||||
{{WAVE_FORMAT_PCM, 1, 8000, 8000, 1, 8}, {WAVE_FORMAT_PCM, 1, 8000, 16000, 2, 16}, {0,128,0,129,0,130,0,131,0,132,0,133,0,134,0,135,0,136,0,137,0,138,0,139,0,140,0,141,0,142,0,143,0,144,0,145,0,146,0,147,0,148,0,149,0,150,0,151,0,152,0,153,0,154,0,155,0,156,0,157,0,158,0,159,0,160,0,161,0,162,0,163,0,164,0,165,0,166,0,167,0,168,0,169,0,170,0,171,0,172,0,173,0,174,0,175,0,176,0,177,0,178,0,179,0,180,0,181,0,182,0,183,0,184,0,185,0,186,0,187,0,188,0,189,0,190,0,191}, 128, FALSE},
|
||||
|
||||
/* #5: 16 -> 8 bits per sample */
|
||||
{{WAVE_FORMAT_PCM, 1, 8000, 16000, 2, 16}, {WAVE_FORMAT_PCM, 1, 8000, 8000, 1, 8}, {129,131,133,135,137,139,141,143,145,147,149,151,153,155,157,159,161,163,165,167,169,171,173,175,177,179,181,183,185,187,189,191}, 32, FALSE},
|
||||
|
||||
/* #6: 16 bits per sample, 2 -> 1 channels */
|
||||
{{WAVE_FORMAT_PCM, 2, 8000, 32000, 4, 16}, {WAVE_FORMAT_PCM, 1, 8000, 16000, 2, 16}, {2,4,10,12,18,20,26,28,34,36,42,44,50,52,58,60,66,68,74,76,82,84,90,92,98,100,106,108,114,116,122,124}, 32, FALSE},
|
||||
|
||||
/* #7: 8000 -> 11025 sample rate */
|
||||
/* FIXME: upsampling is slightly off on wine - the algorithm is wrong whenever error > (srcrate + dstrate) / 2 */
|
||||
{{WAVE_FORMAT_PCM, 1, 8000, 8000, 1, 8}, {WAVE_FORMAT_PCM, 1, 11025, 11025, 1, 8}, {0,1,1,2,3,4,4,5,6,7,7,8,9,9,10,11,12,12,13,14,15,15,16,17,17,18,19,20,20,21,22,22,23,24,25,25,26,27,28,28,29,30,30,31,32,33,33,34,35,36,36,37,38,38,39,40,41,41,42,43,44,44,45,46,46,47,48,49,49,50,51,52,52,53,54,54,55,56,57,57,58,59,60,60,61,62,62,63}, 88, TRUE},
|
||||
|
||||
/* #8: 8000 -> 22050 sample rate */
|
||||
{{WAVE_FORMAT_PCM, 1, 8000, 8000, 1, 8}, {WAVE_FORMAT_PCM, 1, 22050, 22050, 1, 8}, {0,0,1,1,1,2,2,3,3,3,4,4,4,5,5,5,6,6,7,7,7,8,8,8,9,9,9,10,10,11,11,11,12,12,12,13,13,13,14,14,15,15,15,16,16,16,17,17,17,18,18,19,19,19,20,20,20,21,21,21,22,22,22,23,23,24,24,24,25,25,25,26,26,26,27,27,28,28,28,29,29,29,30,30,30,31,31,32,32,32,33,33,33,34,34,34,35,35,36,36,36,37,37,37,38,38,38,39,39,40,40,40,41,41,41,42,42,42,43,43,44,44,44,45,45,45,46,46,46,47,47,48,48,48,49,49,49,50,50,50,51,51,52,52,52,53,53,53,54,54,54,55,55,56,56,56,57,57,57,58,58,58,59,59,60,60,60,61,61,61,62,62,62,63,63,63}, 176, TRUE},
|
||||
|
||||
/* #9: 11025 -> 22050 sample rate */
|
||||
{{WAVE_FORMAT_PCM, 1, 11025, 11025, 1, 8}, {WAVE_FORMAT_PCM, 1, 22050, 22050, 1, 8}, {0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,45,45,46,46,47,47,48,48,49,49,50,50,51,51,52,52,53,53,54,54,55,55,56,56,57,57,58,58,59,59,60,60,61,61,62,62,63,63}, 128, FALSE},
|
||||
|
||||
/* #10: 22050 -> 11025 sample rate */
|
||||
{{WAVE_FORMAT_PCM, 1, 22050, 22050, 1, 8}, {WAVE_FORMAT_PCM, 1, 11025, 11025, 1, 8}, {1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49,51,53,55,57,59,61,63}, 32, FALSE},
|
||||
|
||||
/* #11: 11025 -> 8000 sample rate */
|
||||
{{WAVE_FORMAT_PCM, 1, 11025, 11025, 1, 8}, {WAVE_FORMAT_PCM, 1, 8000, 8000, 1, 8}, {0,2,3,4,6,7,8,10,11,13,14,15,17,18,19,21,22,24,25,26,28,29,31,32,33,35,36,37,39,40,42,43,44,46,47,48,50,51,53,54,55,57,58,59,61,62}, 46, FALSE},
|
||||
|
||||
/* #12: 22050 -> 8000 sample rate */
|
||||
{{WAVE_FORMAT_PCM, 1, 22050, 22050, 1, 8}, {WAVE_FORMAT_PCM, 1, 8000, 8000, 1, 8}, {1,4,6,9,12,15,17,20,23,26,28,31,34,37,39,42,45,48,50,53,56,59,62}, 23, FALSE},
|
||||
|
||||
/* #13: 44100 -> 8000 sample rate */
|
||||
{{WAVE_FORMAT_PCM, 1, 44100, 44100, 1, 8}, {WAVE_FORMAT_PCM, 1, 8000, 8000, 1, 8}, {2,8,13,19,24,30,35,41,46,52,57,63}, 12, FALSE},
|
||||
};
|
||||
|
||||
static void test_convert(void)
|
||||
{
|
||||
HACMSTREAM has;
|
||||
ACMSTREAMHEADER hdr = {0};
|
||||
BYTE output[256];
|
||||
MMRESULT mmr;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < sizeof(expected_output)/sizeof(struct stream_output); i++)
|
||||
{
|
||||
mmr = acmStreamOpen(&has, NULL, (WAVEFORMATEX *)&expected_output[i].src, (WAVEFORMATEX *)&expected_output[i].dst, NULL, 0, 0, 0);
|
||||
ok(mmr == MMSYSERR_NOERROR, "#%d: open failed: 0x%x\n", i, mmr);
|
||||
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
hdr.cbStruct = sizeof(hdr);
|
||||
hdr.pbSrc = (BYTE *)input;
|
||||
hdr.cbSrcLength = sizeof(input);
|
||||
hdr.pbDst = output;
|
||||
hdr.cbDstLength = sizeof(output);
|
||||
|
||||
mmr = acmStreamPrepareHeader(has, &hdr, 0);
|
||||
ok(mmr == MMSYSERR_NOERROR, "#%d: prepare failed: 0x%x\n", i, mmr);
|
||||
ok(hdr.fdwStatus == ACMSTREAMHEADER_STATUSF_PREPARED, "#%d: header wasn't prepared: 0x%x\n", i, hdr.fdwStatus);
|
||||
|
||||
memset(&output, 0, sizeof(output));
|
||||
mmr = acmStreamConvert(has, &hdr, ACM_STREAMCONVERTF_BLOCKALIGN);
|
||||
ok(mmr == MMSYSERR_NOERROR, "#%d: convert failed: 0x%x\n", i, mmr);
|
||||
ok(hdr.fdwStatus & ACMSTREAMHEADER_STATUSF_DONE, "#%d: conversion was not done: 0x%x\n", i, hdr.fdwStatus);
|
||||
ok(hdr.cbSrcLengthUsed == hdr.cbSrcLength, "#%d: expected %d, got %d\n", i, hdr.cbSrcLength, hdr.cbSrcLengthUsed);
|
||||
ok(hdr.cbDstLengthUsed == expected_output[i].dst_used, "#%d: expected %d, got %d\n", i, expected_output[i].dst_used, hdr.cbDstLengthUsed);
|
||||
todo_wine_if(expected_output[i].todo)
|
||||
ok(!memcmp(expected_output[i].output, output, hdr.cbDstLengthUsed), "#%d: output does not match\n", i);
|
||||
|
||||
mmr = acmStreamUnprepareHeader(has, &hdr, 0);
|
||||
ok(mmr == MMSYSERR_NOERROR, "#%d: unprepare failed: 0x%x\n", i, mmr);
|
||||
ok(hdr.fdwStatus == ACMSTREAMHEADER_STATUSF_DONE, "#%d: header wasn't unprepared: 0x%x\n", i, hdr.fdwStatus);
|
||||
|
||||
mmr = acmStreamClose(has, 0);
|
||||
ok(mmr == MMSYSERR_NOERROR, "#%d: close failed: 0x%x\n", i, mmr);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_acmFormatSuggest(void)
|
||||
{
|
||||
WAVEFORMATEX src, dst;
|
||||
|
@ -1317,6 +1415,7 @@ START_TEST(msacm)
|
|||
{
|
||||
driver_tests();
|
||||
test_prepareheader();
|
||||
test_convert();
|
||||
test_acmFormatSuggest();
|
||||
test_acmFormatTagDetails();
|
||||
/* Test acmDriverAdd in the end as it may conflict
|
||||
|
|
Loading…
Reference in New Issue