Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
wine
Manage
Activity
Members
Labels
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container Registry
Model registry
Operate
Terraform modules
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Johnny Cai
wine
Commits
3291a058
Commit
3291a058
authored
24 years ago
by
Eric Pouech
Committed by
Alexandre Julliard
24 years ago
Browse files
Options
Downloads
Patches
Plain Diff
Added more conversion routines (rate conversion is implemented).
Cleaned up the code.
parent
9039421b
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
dlls/msacm/pcmconverter.c
+760
-204
760 additions, 204 deletions
dlls/msacm/pcmconverter.c
with
760 additions
and
204 deletions
dlls/msacm/pcmconverter.c
+
760
−
204
View file @
3291a058
...
...
@@ -4,6 +4,15 @@
* MSACM32 library
*
* Copyright 2000 Eric Pouech
*
* FIXME / TODO list
* + most of the computation should be done in fixed point arithmetic
* instead of floating point (16 bits for integral part, and 16 bits
* for fractional part for example)
* + implement PCM_FormatSuggest function
* + get rid of hack for PCM_DriverProc (msacm32.dll shouldn't export
* a DriverProc, but this would require implementing a generic
* embedded driver handling scheme in msacm32.dll which isn't done yet
*/
#include
<assert.h>
...
...
@@ -17,41 +26,65 @@
DEFAULT_DEBUG_CHANNEL
(
msacm
);
/***********************************************************************
* PCM_drvOpen
*/
static
DWORD
PCM_drvOpen
(
LPCSTR
str
)
{
return
1
;
}
/***********************************************************************
* PCM_drvClose
*/
static
DWORD
PCM_drvClose
(
DWORD
dwDevID
)
{
return
1
;
}
#define NUM_PCM_FORMATS (sizeof(PCM_Formats) / sizeof(PCM_Formats[0]))
#define NUM_OF(a,b) (((a)+(b)-1)/(b))
/* flags for fdwDriver */
#define PCM_RESAMPLE 1
/* 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
)(
struct
tagAcmPcmData
*
,
const
unsigned
char
*
,
LPDWORD
,
unsigned
char
*
,
LPDWORD
);
}
cvt
;
/* the following fields are used only with rate conversion) */
DWORD
srcPos
;
/* position in source stream */
double
dstPos
;
/* position in destination stream */
double
dstIncr
;
/* value to increment dst stream when src stream
is incremented by 1 */
/* last source stream value read */
union
{
unsigned
char
b
;
/* 8 bit value */
short
s
;
/* 16 bit value */
}
last
[
2
];
/* two channels max (stereo) */
}
AcmPcmData
;
/* table to list all supported formats... those are the basic ones. this
* also helps given a unique index to each of the supported formats
*/
static
struct
{
int
nChannels
;
int
nBits
;
int
rate
;
}
PCM_Formats
[]
=
{
{
1
,
8
,
8000
},
{
2
,
8
,
8000
},
{
1
,
16
,
8000
},
{
2
,
16
,
8000
},
{
1
,
8
,
11025
},
{
2
,
8
,
11025
},
{
1
,
16
,
11025
},
{
2
,
16
,
11025
},
{
1
,
8
,
22050
},
{
2
,
8
,
22050
},
{
1
,
16
,
22050
},
{
2
,
16
,
22050
},
{
1
,
8
,
44100
},
{
2
,
8
,
44100
},
{
1
,
16
,
44100
},
{
2
,
16
,
44100
},
{
1
,
8
,
8000
},
{
2
,
8
,
8000
},
{
1
,
16
,
8000
},
{
2
,
16
,
8000
},
{
1
,
8
,
11025
},
{
2
,
8
,
11025
},
{
1
,
16
,
11025
},
{
2
,
16
,
11025
},
{
1
,
8
,
22050
},
{
2
,
8
,
22050
},
{
1
,
16
,
22050
},
{
2
,
16
,
22050
},
{
1
,
8
,
44100
},
{
2
,
8
,
44100
},
{
1
,
16
,
44100
},
{
2
,
16
,
44100
},
};
#define NUM_PCM_FORMATS (sizeof(PCM_Formats) / sizeof(PCM_Formats[0]))
/***********************************************************************
* PCM_GetFormatIndex
*/
static
DWORD
PCM_GetFormatIndex
(
LPWAVEFORMATEX
wfx
)
{
int
i
;
...
...
@@ -65,6 +98,593 @@ static DWORD PCM_GetFormatIndex(LPWAVEFORMATEX wfx)
return
0xFFFFFFFF
;
}
/* PCM Conversions:
*
* parameters:
* + 8 bit unsigned vs 16 bit signed
* + mono vs stereo (1 or 2 channels)
* + sampling rate (8.0, 11.025, 22.05, 44.1 kHz are defined, but algo shall work
* in all cases)
*
* mono => stereo: copy the same sample on Left & Right channels
* stereo =) mono: use the average value of samples from Left & Right channels
* resampling; we lookup for each destination sample the two source adjacent samples
* were src <= dst < src+1 (dst is increased by a fractional value which is
* equivalent to the increment by one on src); then we use a linear
* interpolation between src and src+1
*/
/***********************************************************************
* C816
*
* Converts a 8 bit sample to a 16 bit one
*/
static
inline
short
C816
(
unsigned
char
b
)
{
return
(
short
)(
b
^
0x80
)
*
256
;
}
/***********************************************************************
* C168
*
* Converts a 16 bit sample to a 8 bit one (data loss !!)
*/
static
inline
unsigned
char
C168
(
short
s
)
{
return
HIBYTE
(
s
)
^
(
unsigned
char
)
0x80
;
}
/***********************************************************************
* R16
*
* Read a 16 bit sample (correctly handles endianess)
*/
static
inline
short
R16
(
const
unsigned
char
*
src
)
{
return
(
short
)((
unsigned
short
)
src
[
0
]
|
((
unsigned
short
)
src
[
1
]
<<
8
));
}
/***********************************************************************
* W16
*
* Write a 16 bit sample (correctly handles endianess)
*/
static
inline
void
W16
(
unsigned
char
*
dst
,
short
s
)
{
dst
[
0
]
=
LOBYTE
(
s
);
dst
[
1
]
=
HIBYTE
(
s
);
}
/***********************************************************************
* M16
*
* Convert the (l,r) 16 bit stereo sample into a 16 bit mono
* (takes the mid-point of the two values)
*/
static
inline
short
M16
(
short
l
,
short
r
)
{
return
(
l
+
r
)
/
2
;
}
/***********************************************************************
* M8
*
* Convert the (l,r) 8 bit stereo sample into a 8 bit mono
* (takes the mid-point of the two values)
*/
static
inline
unsigned
char
M8
(
unsigned
char
a
,
unsigned
char
b
)
{
return
(
unsigned
char
)((
a
+
b
)
/
2
);
}
/* the conversion routines without rate conversion are labelled cvt<X><Y><N><M>K
* where :
* <X> is the (M)ono/(S)tereo configuration of input channel
* <Y> is the (M)ono/(S)tereo configuration of output channel
* <N> is the number of bits of input channel (8 or 16)
* <M> is the number of bits of output channel (8 or 16)
*
* in the parameters, ns is always the number of samples, so the size of input
* buffer (resp output buffer) is ns * (<X> == 'Mono' ? 1:2) * (<N> == 8 ? 1:2)
*/
static
void
cvtMM88K
(
const
unsigned
char
*
src
,
int
ns
,
unsigned
char
*
dst
)
{
memcpy
(
dst
,
src
,
ns
);
}
static
void
cvtSS88K
(
const
unsigned
char
*
src
,
int
ns
,
unsigned
char
*
dst
)
{
memcpy
(
dst
,
src
,
ns
*
2
);
}
static
void
cvtMM1616K
(
const
unsigned
char
*
src
,
int
ns
,
unsigned
char
*
dst
)
{
memcpy
(
dst
,
src
,
ns
*
2
);
}
static
void
cvtSS1616K
(
const
unsigned
char
*
src
,
int
ns
,
unsigned
char
*
dst
)
{
memcpy
(
dst
,
src
,
ns
*
4
);
}
static
void
cvtMS88K
(
const
unsigned
char
*
src
,
int
ns
,
unsigned
char
*
dst
)
{
while
(
ns
--
)
{
*
dst
++
=
*
src
;
*
dst
++
=
*
src
++
;
}
}
static
void
cvtMS816K
(
const
unsigned
char
*
src
,
int
ns
,
unsigned
char
*
dst
)
{
short
v
;
while
(
ns
--
)
{
v
=
C816
(
*
src
++
);
W16
(
dst
,
v
);
dst
+=
2
;
W16
(
dst
,
v
);
dst
+=
2
;
}
}
static
void
cvtMS168K
(
const
unsigned
char
*
src
,
int
ns
,
unsigned
char
*
dst
)
{
unsigned
char
v
;
while
(
ns
--
)
{
v
=
C168
(
R16
(
src
));
src
+=
2
;
*
dst
++
=
v
;
*
dst
++
=
v
;
}
}
static
void
cvtMS1616K
(
const
unsigned
char
*
src
,
int
ns
,
unsigned
char
*
dst
)
{
short
v
;
while
(
ns
--
)
{
v
=
R16
(
src
);
src
+=
2
;
W16
(
dst
,
v
);
dst
+=
2
;
W16
(
dst
,
v
);
dst
+=
2
;
}
}
static
void
cvtSM88K
(
const
unsigned
char
*
src
,
int
ns
,
unsigned
char
*
dst
)
{
while
(
ns
--
)
{
*
dst
++
=
M8
(
src
[
0
],
src
[
1
]);
src
+=
2
;
}
}
static
void
cvtSM816K
(
const
unsigned
char
*
src
,
int
ns
,
unsigned
char
*
dst
)
{
short
v
;
while
(
ns
--
)
{
v
=
M16
(
C816
(
src
[
0
]),
C816
(
src
[
1
]));
src
+=
2
;
W16
(
dst
,
v
);
dst
+=
2
;
}
}
static
void
cvtSM168K
(
const
unsigned
char
*
src
,
int
ns
,
unsigned
char
*
dst
)
{
while
(
ns
--
)
{
*
dst
++
=
C168
(
M16
(
R16
(
src
),
R16
(
src
+
2
)));
src
+=
4
;
}
}
static
void
cvtSM1616K
(
const
unsigned
char
*
src
,
int
ns
,
unsigned
char
*
dst
)
{
while
(
ns
--
)
{
W16
(
dst
,
M16
(
R16
(
src
),
R16
(
src
+
2
)));
dst
+=
2
;
src
+=
4
;
}
}
static
void
cvtMM816K
(
const
unsigned
char
*
src
,
int
ns
,
unsigned
char
*
dst
)
{
while
(
ns
--
)
{
W16
(
dst
,
C816
(
*
src
++
));
dst
+=
2
;
}
}
static
void
cvtSS816K
(
const
unsigned
char
*
src
,
int
ns
,
unsigned
char
*
dst
)
{
while
(
ns
--
)
{
W16
(
dst
,
C816
(
*
src
++
));
dst
+=
2
;
W16
(
dst
,
C816
(
*
src
++
));
dst
+=
2
;
}
}
static
void
cvtMM168K
(
const
unsigned
char
*
src
,
int
ns
,
unsigned
char
*
dst
)
{
while
(
ns
--
)
{
*
dst
++
=
C168
(
R16
(
src
));
src
+=
2
;
}
}
static
void
cvtSS168K
(
const
unsigned
char
*
src
,
int
ns
,
unsigned
char
*
dst
)
{
while
(
ns
--
)
{
*
dst
++
=
C168
(
R16
(
src
));
src
+=
2
;
*
dst
++
=
C168
(
R16
(
src
));
src
+=
2
;
}
}
static
void
(
*
PCM_ConvertKeepRate
[
16
])(
const
unsigned
char
*
,
int
,
unsigned
char
*
)
=
{
cvtSS88K
,
cvtSM88K
,
cvtMS88K
,
cvtMM88K
,
cvtSS816K
,
cvtSM816K
,
cvtMS816K
,
cvtMM816K
,
cvtSS168K
,
cvtSM168K
,
cvtMS168K
,
cvtMM168K
,
cvtSS1616K
,
cvtSM1616K
,
cvtMS1616K
,
cvtMM1616K
,
};
/***********************************************************************
* I
*
* Interpolate the value at r (r in ]0, 1]) between the two points v1 and v2
* Linear interpolation is used
*/
static
inline
double
I
(
double
v1
,
double
v2
,
double
r
)
{
if
(
0
.
0
>=
r
||
r
>
1
.
0
)
FIXME
(
"r!! %f
\n
"
,
r
);
return
(
1
.
0
-
r
)
*
v1
+
r
*
v2
;
}
static
void
cvtSS88C
(
AcmPcmData
*
apd
,
const
unsigned
char
*
src
,
LPDWORD
nsrc
,
unsigned
char
*
dst
,
LPDWORD
ndst
)
{
double
r
;
while
(
*
nsrc
!=
0
&&
*
ndst
!=
0
)
{
while
((
r
=
(
double
)
apd
->
srcPos
-
apd
->
dstPos
)
<=
0
)
{
if
(
*
nsrc
==
0
)
return
;
apd
->
last
[
0
].
b
=
*
src
++
;
apd
->
last
[
1
].
b
=
*
src
++
;
apd
->
srcPos
++
;
(
*
nsrc
)
--
;
}
/* now do the interpolation */
*
dst
++
=
I
(
apd
->
last
[
0
].
b
,
src
[
0
],
r
);
*
dst
++
=
I
(
apd
->
last
[
1
].
b
,
src
[
1
],
r
);
apd
->
dstPos
+=
apd
->
dstIncr
;
(
*
ndst
)
--
;
}
}
/* the conversion routines with rate conversion are labelled cvt<X><Y><N><M>C
* where :
* <X> is the (M)ono/(S)tereo configuration of input channel
* <Y> is the (M)ono/(S)tereo configuration of output channel
* <N> is the number of bits of input channel (8 or 16)
* <M> is the number of bits of output channel (8 or 16)
*
*/
static
void
cvtSM88C
(
AcmPcmData
*
apd
,
const
unsigned
char
*
src
,
LPDWORD
nsrc
,
unsigned
char
*
dst
,
LPDWORD
ndst
)
{
double
r
;
while
(
*
nsrc
!=
0
&&
*
ndst
!=
0
)
{
while
((
r
=
(
double
)
apd
->
srcPos
-
apd
->
dstPos
)
<=
0
)
{
if
(
*
nsrc
==
0
)
return
;
apd
->
last
[
0
].
b
=
*
src
++
;
apd
->
last
[
1
].
b
=
*
src
++
;
apd
->
srcPos
++
;
(
*
nsrc
)
--
;
}
/* now do the interpolation */
*
dst
++
=
I
(
M8
(
apd
->
last
[
0
].
b
,
apd
->
last
[
1
].
b
),
M8
(
src
[
0
],
src
[
1
]),
r
);
apd
->
dstPos
+=
apd
->
dstIncr
;
(
*
ndst
)
--
;
}
}
static
void
cvtMS88C
(
AcmPcmData
*
apd
,
const
unsigned
char
*
src
,
LPDWORD
nsrc
,
unsigned
char
*
dst
,
LPDWORD
ndst
)
{
double
r
;
while
(
*
nsrc
!=
0
&&
*
ndst
!=
0
)
{
while
((
r
=
(
double
)
apd
->
srcPos
-
apd
->
dstPos
)
<=
0
)
{
if
(
*
nsrc
==
0
)
return
;
apd
->
last
[
0
].
b
=
*
src
++
;
apd
->
srcPos
++
;
(
*
nsrc
)
--
;
}
/* now do the interpolation */
dst
[
0
]
=
dst
[
1
]
=
I
(
apd
->
last
[
0
].
b
,
src
[
0
],
r
);
dst
+=
2
;
apd
->
dstPos
+=
apd
->
dstIncr
;
(
*
ndst
)
--
;
}
}
static
void
cvtMM88C
(
AcmPcmData
*
apd
,
const
unsigned
char
*
src
,
LPDWORD
nsrc
,
unsigned
char
*
dst
,
LPDWORD
ndst
)
{
double
r
;
while
(
*
nsrc
!=
0
&&
*
ndst
!=
0
)
{
while
((
r
=
(
double
)
apd
->
srcPos
-
apd
->
dstPos
)
<=
0
)
{
if
(
*
nsrc
==
0
)
return
;
apd
->
last
[
0
].
b
=
*
src
++
;
apd
->
srcPos
++
;
(
*
nsrc
)
--
;
}
/* now do the interpolation */
*
dst
++
=
I
(
apd
->
last
[
0
].
b
,
src
[
0
],
r
);
apd
->
dstPos
+=
apd
->
dstIncr
;
(
*
ndst
)
--
;
}
}
static
void
cvtSS816C
(
AcmPcmData
*
apd
,
const
unsigned
char
*
src
,
LPDWORD
nsrc
,
unsigned
char
*
dst
,
LPDWORD
ndst
)
{
double
r
;
while
(
*
nsrc
!=
0
&&
*
ndst
!=
0
)
{
while
((
r
=
(
double
)
apd
->
srcPos
-
apd
->
dstPos
)
<=
0
)
{
if
(
*
nsrc
==
0
)
return
;
apd
->
last
[
0
].
b
=
*
src
++
;
apd
->
last
[
1
].
b
=
*
src
++
;
apd
->
srcPos
++
;
(
*
nsrc
)
--
;
}
/* now do the interpolation */
W16
(
dst
,
I
(
C816
(
apd
->
last
[
0
].
b
),
C816
(
src
[
0
]),
r
));
dst
+=
2
;
W16
(
dst
,
I
(
C816
(
apd
->
last
[
1
].
b
),
C816
(
src
[
1
]),
r
));
dst
+=
2
;
apd
->
dstPos
+=
apd
->
dstIncr
;
(
*
ndst
)
--
;
}
}
static
void
cvtSM816C
(
AcmPcmData
*
apd
,
const
unsigned
char
*
src
,
LPDWORD
nsrc
,
unsigned
char
*
dst
,
LPDWORD
ndst
)
{
double
r
;
while
(
*
nsrc
!=
0
&&
*
ndst
!=
0
)
{
while
((
r
=
(
double
)
apd
->
srcPos
-
apd
->
dstPos
)
<=
0
)
{
if
(
*
nsrc
==
0
)
return
;
apd
->
last
[
0
].
b
=
*
src
++
;
apd
->
last
[
1
].
b
=
*
src
++
;
apd
->
srcPos
++
;
(
*
nsrc
)
--
;
}
/* now do the interpolation */
W16
(
dst
,
I
(
M16
(
C816
(
apd
->
last
[
0
].
b
),
C816
(
apd
->
last
[
1
].
b
)),
M16
(
C816
(
src
[
0
]),
C816
(
src
[
1
])),
r
));
dst
+=
2
;
apd
->
dstPos
+=
apd
->
dstIncr
;
(
*
ndst
)
--
;
}
}
static
void
cvtMS816C
(
AcmPcmData
*
apd
,
const
unsigned
char
*
src
,
LPDWORD
nsrc
,
unsigned
char
*
dst
,
LPDWORD
ndst
)
{
double
r
;
short
v
;
while
(
*
nsrc
!=
0
&&
*
ndst
!=
0
)
{
while
((
r
=
(
double
)
apd
->
srcPos
-
apd
->
dstPos
)
<=
0
)
{
if
(
*
nsrc
==
0
)
return
;
apd
->
last
[
0
].
b
=
*
src
++
;
apd
->
srcPos
++
;
(
*
nsrc
)
--
;
}
/* now do the interpolation */
v
=
I
(
C816
(
apd
->
last
[
0
].
b
),
C816
(
src
[
0
]),
r
);
W16
(
dst
,
v
);
dst
+=
2
;
W16
(
dst
,
v
);
dst
+=
2
;
apd
->
dstPos
+=
apd
->
dstIncr
;
(
*
ndst
)
--
;
}
}
static
void
cvtMM816C
(
AcmPcmData
*
apd
,
const
unsigned
char
*
src
,
LPDWORD
nsrc
,
unsigned
char
*
dst
,
LPDWORD
ndst
)
{
double
r
;
while
(
*
nsrc
!=
0
&&
*
ndst
!=
0
)
{
while
((
r
=
(
double
)
apd
->
srcPos
-
apd
->
dstPos
)
<=
0
)
{
if
(
*
nsrc
==
0
)
return
;
apd
->
last
[
0
].
b
=
*
src
++
;
apd
->
srcPos
++
;
(
*
nsrc
)
--
;
}
/* now do the interpolation */
W16
(
dst
,
I
(
C816
(
apd
->
last
[
0
].
b
),
C816
(
src
[
0
]),
r
));
dst
+=
2
;
apd
->
dstPos
+=
apd
->
dstIncr
;
(
*
ndst
)
--
;
}
}
static
void
cvtSS168C
(
AcmPcmData
*
apd
,
const
unsigned
char
*
src
,
LPDWORD
nsrc
,
unsigned
char
*
dst
,
LPDWORD
ndst
)
{
double
r
;
while
(
*
nsrc
!=
0
&&
*
ndst
!=
0
)
{
while
((
r
=
(
double
)
apd
->
srcPos
-
apd
->
dstPos
)
<=
0
)
{
if
(
*
nsrc
==
0
)
return
;
apd
->
last
[
0
].
s
=
R16
(
src
);
src
+=
2
;
apd
->
last
[
1
].
s
=
R16
(
src
);
src
+=
2
;
apd
->
srcPos
++
;
(
*
nsrc
)
--
;
}
/* now do the interpolation */
*
dst
++
=
C168
(
I
(
apd
->
last
[
0
].
s
,
R16
(
src
)
,
r
));
*
dst
++
=
C168
(
I
(
apd
->
last
[
1
].
s
,
R16
(
src
+
2
),
r
));
apd
->
dstPos
+=
apd
->
dstIncr
;
(
*
ndst
)
--
;
}
}
static
void
cvtSM168C
(
AcmPcmData
*
apd
,
const
unsigned
char
*
src
,
LPDWORD
nsrc
,
unsigned
char
*
dst
,
LPDWORD
ndst
)
{
double
r
;
while
(
*
nsrc
!=
0
&&
*
ndst
!=
0
)
{
while
((
r
=
(
double
)
apd
->
srcPos
-
apd
->
dstPos
)
<=
0
)
{
if
(
*
nsrc
==
0
)
return
;
apd
->
last
[
0
].
s
=
R16
(
src
);
src
+=
2
;
apd
->
last
[
1
].
s
=
R16
(
src
);
src
+=
2
;
apd
->
srcPos
++
;
(
*
nsrc
)
--
;
}
/* now do the interpolation */
*
dst
++
=
C168
(
I
(
M16
(
apd
->
last
[
0
].
s
,
apd
->
last
[
1
].
s
),
M16
(
R16
(
src
),
R16
(
src
+
2
)),
r
));
apd
->
dstPos
+=
apd
->
dstIncr
;
(
*
ndst
)
--
;
}
}
static
void
cvtMS168C
(
AcmPcmData
*
apd
,
const
unsigned
char
*
src
,
LPDWORD
nsrc
,
unsigned
char
*
dst
,
LPDWORD
ndst
)
{
double
r
;
while
(
*
nsrc
!=
0
&&
*
ndst
!=
0
)
{
while
((
r
=
(
double
)
apd
->
srcPos
-
apd
->
dstPos
)
<=
0
)
{
if
(
*
nsrc
==
0
)
return
;
apd
->
last
[
0
].
s
=
R16
(
src
);
src
+=
2
;
apd
->
srcPos
++
;
(
*
nsrc
)
--
;
}
/* now do the interpolation */
dst
[
0
]
=
dst
[
1
]
=
C168
(
I
(
apd
->
last
[
0
].
s
,
R16
(
src
),
r
));
dst
+=
2
;
apd
->
dstPos
+=
apd
->
dstIncr
;
(
*
ndst
)
--
;
}
}
static
void
cvtMM168C
(
AcmPcmData
*
apd
,
const
unsigned
char
*
src
,
LPDWORD
nsrc
,
unsigned
char
*
dst
,
LPDWORD
ndst
)
{
double
r
;
while
(
*
nsrc
!=
0
&&
*
ndst
!=
0
)
{
while
((
r
=
(
double
)
apd
->
srcPos
-
apd
->
dstPos
)
<=
0
)
{
if
(
*
nsrc
==
0
)
return
;
apd
->
last
[
0
].
s
=
R16
(
src
);
src
+=
2
;
apd
->
srcPos
++
;
(
*
nsrc
)
--
;
}
/* now do the interpolation */
*
dst
++
=
C168
(
I
(
apd
->
last
[
0
].
s
,
R16
(
src
),
r
));
apd
->
dstPos
+=
apd
->
dstIncr
;
(
*
ndst
)
--
;
}
}
static
void
cvtSS1616C
(
AcmPcmData
*
apd
,
const
unsigned
char
*
src
,
LPDWORD
nsrc
,
unsigned
char
*
dst
,
LPDWORD
ndst
)
{
double
r
;
while
(
*
nsrc
!=
0
&&
*
ndst
!=
0
)
{
while
((
r
=
(
double
)
apd
->
srcPos
-
apd
->
dstPos
)
<=
0
)
{
if
(
*
nsrc
==
0
)
return
;
apd
->
last
[
0
].
s
=
R16
(
src
);
src
+=
2
;
apd
->
last
[
1
].
s
=
R16
(
src
);
src
+=
2
;
apd
->
srcPos
++
;
(
*
nsrc
)
--
;
}
/* now do the interpolation */
W16
(
dst
,
I
(
apd
->
last
[
0
].
s
,
R16
(
src
)
,
r
));
dst
+=
2
;
W16
(
dst
,
I
(
apd
->
last
[
1
].
s
,
R16
(
src
+
2
),
r
));
dst
+=
2
;
apd
->
dstPos
+=
apd
->
dstIncr
;
(
*
ndst
)
--
;
}
}
static
void
cvtSM1616C
(
AcmPcmData
*
apd
,
const
unsigned
char
*
src
,
LPDWORD
nsrc
,
unsigned
char
*
dst
,
LPDWORD
ndst
)
{
double
r
;
while
(
*
nsrc
!=
0
&&
*
ndst
!=
0
)
{
while
((
r
=
(
double
)
apd
->
srcPos
-
apd
->
dstPos
)
<=
0
)
{
if
(
*
nsrc
==
0
)
return
;
apd
->
last
[
0
].
s
=
R16
(
src
);
src
+=
2
;
apd
->
last
[
1
].
s
=
R16
(
src
);
src
+=
2
;
apd
->
srcPos
++
;
(
*
nsrc
)
--
;
}
/* now do the interpolation */
W16
(
dst
,
I
(
M16
(
apd
->
last
[
0
].
s
,
apd
->
last
[
1
].
s
),
M16
(
R16
(
src
),
R16
(
src
+
2
)),
r
));
dst
+=
2
;
apd
->
dstPos
+=
apd
->
dstIncr
;
(
*
ndst
)
--
;
}
}
static
void
cvtMS1616C
(
AcmPcmData
*
apd
,
const
unsigned
char
*
src
,
LPDWORD
nsrc
,
unsigned
char
*
dst
,
LPDWORD
ndst
)
{
double
r
;
short
v
;
while
(
*
nsrc
!=
0
&&
*
ndst
!=
0
)
{
while
((
r
=
(
double
)
apd
->
srcPos
-
apd
->
dstPos
)
<=
0
)
{
if
(
*
nsrc
==
0
)
return
;
apd
->
last
[
0
].
s
=
R16
(
src
);
src
+=
2
;
apd
->
srcPos
++
;
(
*
nsrc
)
--
;
}
/* now do the interpolation */
v
=
I
(
apd
->
last
[
0
].
s
,
R16
(
src
),
r
);
W16
(
dst
,
v
);
dst
+=
2
;
W16
(
dst
,
v
);
dst
+=
2
;
apd
->
dstPos
+=
apd
->
dstIncr
;
(
*
ndst
)
--
;
}
}
static
void
cvtMM1616C
(
AcmPcmData
*
apd
,
const
unsigned
char
*
src
,
LPDWORD
nsrc
,
unsigned
char
*
dst
,
LPDWORD
ndst
)
{
double
r
;
while
(
*
nsrc
!=
0
&&
*
ndst
!=
0
)
{
while
((
r
=
(
double
)
apd
->
srcPos
-
apd
->
dstPos
)
<=
0
)
{
if
(
*
nsrc
==
0
)
return
;
apd
->
last
[
0
].
s
=
R16
(
src
);
src
+=
2
;
apd
->
srcPos
++
;
(
*
nsrc
)
--
;
}
/* now do the interpolation */
W16
(
dst
,
I
(
apd
->
last
[
0
].
s
,
R16
(
src
),
r
));
dst
+=
2
;
apd
->
dstPos
+=
apd
->
dstIncr
;
(
*
ndst
)
--
;
}
}
static
void
(
*
PCM_ConvertChangeRate
[
16
])(
AcmPcmData
*
apd
,
const
unsigned
char
*
src
,
LPDWORD
nsrc
,
unsigned
char
*
dst
,
LPDWORD
ndst
)
=
{
cvtSS88C
,
cvtSM88C
,
cvtMS88C
,
cvtMM88C
,
cvtSS816C
,
cvtSM816C
,
cvtMS816C
,
cvtMM816C
,
cvtSS168C
,
cvtSM168C
,
cvtMS168C
,
cvtMM168C
,
cvtSS1616C
,
cvtSM1616C
,
cvtMS1616C
,
cvtMM1616C
,
};
/***********************************************************************
* PCM_DriverDetails
*
*/
static
LRESULT
PCM_DriverDetails
(
PACMDRIVERDETAILSW
add
)
{
add
->
fccType
=
ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC
;
...
...
@@ -78,7 +698,7 @@ static LRESULT PCM_DriverDetails(PACMDRIVERDETAILSW add)
add
->
cFilterTags
=
0
;
add
->
hicon
=
(
HICON
)
0
;
lstrcpyAtoW
(
add
->
szShortName
,
"WINE-PCM"
);
lstrcpyAtoW
(
add
->
szLongName
,
"Wine PCM converter"
);
lstrcpyAtoW
(
add
->
szLongName
,
"Wine PCM converter"
);
lstrcpyAtoW
(
add
->
szCopyright
,
"Brought to you by the Wine team..."
);
lstrcpyAtoW
(
add
->
szLicensing
,
"Refer to LICENSE file"
);
add
->
szFeatures
[
0
]
=
0
;
...
...
@@ -86,6 +706,10 @@ static LRESULT PCM_DriverDetails(PACMDRIVERDETAILSW add)
return
MMSYSERR_NOERROR
;
}
/***********************************************************************
* PCM_FormatTagDetails
*
*/
static
LRESULT
PCM_FormatTagDetails
(
PACMFORMATTAGDETAILSW
aftd
,
DWORD
dwQuery
)
{
switch
(
dwQuery
)
{
...
...
@@ -96,7 +720,8 @@ static LRESULT PCM_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery)
if
(
aftd
->
dwFormatTag
!=
WAVE_FORMAT_PCM
)
return
ACMERR_NOTPOSSIBLE
;
break
;
case
ACM_FORMATTAGDETAILSF_LARGESTSIZE
:
if
(
aftd
->
dwFormatTag
!=
WAVE_FORMAT_UNKNOWN
&&
aftd
->
dwFormatTag
!=
WAVE_FORMAT_UNKNOWN
)
if
(
aftd
->
dwFormatTag
!=
WAVE_FORMAT_UNKNOWN
&&
aftd
->
dwFormatTag
!=
WAVE_FORMAT_UNKNOWN
)
return
ACMERR_NOTPOSSIBLE
;
break
;
default:
...
...
@@ -114,6 +739,10 @@ static LRESULT PCM_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery)
return
MMSYSERR_NOERROR
;
}
/***********************************************************************
* PCM_FormatDetails
*
*/
static
LRESULT
PCM_FormatDetails
(
PACMFORMATDETAILSW
afd
,
DWORD
dwQuery
)
{
switch
(
dwQuery
)
{
...
...
@@ -128,10 +757,12 @@ static LRESULT PCM_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery)
afd
->
pwfx
->
nSamplesPerSec
=
PCM_Formats
[
afd
->
dwFormatIndex
].
rate
;
afd
->
pwfx
->
wBitsPerSample
=
PCM_Formats
[
afd
->
dwFormatIndex
].
nBits
;
/* native MSACM uses a PCMWAVEFORMAT structure, so cbSize is not accessible
afd->pwfx->cbSize = 0;
*/
afd
->
pwfx
->
nBlockAlign
=
(
afd
->
pwfx
->
nChannels
*
afd
->
pwfx
->
wBitsPerSample
)
/
8
;
afd
->
pwfx
->
nAvgBytesPerSec
=
afd
->
pwfx
->
nSamplesPerSec
*
afd
->
pwfx
->
nBlockAlign
;
* afd->pwfx->cbSize = 0;
*/
afd
->
pwfx
->
nBlockAlign
=
(
afd
->
pwfx
->
nChannels
*
afd
->
pwfx
->
wBitsPerSample
)
/
8
;
afd
->
pwfx
->
nAvgBytesPerSec
=
afd
->
pwfx
->
nSamplesPerSec
*
afd
->
pwfx
->
nBlockAlign
;
break
;
default:
WARN
(
"Unsupported query %08lx
\n
"
,
dwQuery
);
...
...
@@ -145,44 +776,112 @@ static LRESULT PCM_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery)
return
MMSYSERR_NOERROR
;
}
/***********************************************************************
* PCM_FormatSuggest
*
*/
static
LRESULT
PCM_FormatSuggest
(
PACMDRVFORMATSUGGEST
adfs
)
{
FIXME
(
"(%p);
\n
"
,
adfs
);
return
MMSYSERR_NOTSUPPORTED
;
}
/***********************************************************************
* PCM_Reset
*
*/
static
void
PCM_Reset
(
AcmPcmData
*
apd
,
int
srcNumBits
)
{
apd
->
srcPos
=
0
;
apd
->
dstPos
=
0
;
/* initialize with neutral value */
if
(
srcNumBits
==
16
)
{
apd
->
last
[
0
].
s
=
0
;
apd
->
last
[
1
].
s
=
0
;
}
else
{
apd
->
last
[
0
].
b
=
(
BYTE
)
0x80
;
apd
->
last
[
1
].
b
=
(
BYTE
)
0x80
;
}
}
/***********************************************************************
* PCM_StreamOpen
*
*/
static
LRESULT
PCM_StreamOpen
(
PACMDRVSTREAMINSTANCE
adsi
)
{
AcmPcmData
*
apd
;
int
idx
=
0
;
assert
(
!
(
adsi
->
fdwOpen
&
ACM_STREAMOPENF_ASYNC
));
if
(
PCM_GetFormatIndex
(
adsi
->
pwfxSrc
)
==
0xFFFFFFFF
||
PCM_GetFormatIndex
(
adsi
->
pwfxDst
)
==
0xFFFFFFFF
)
return
ACMERR_NOTPOSSIBLE
;
apd
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
AcmPcmData
));
if
(
apd
==
0
)
return
MMSYSERR_NOMEM
;
adsi
->
dwDriver
=
(
DWORD
)
apd
;
adsi
->
fdwDriver
=
0
;
if
(
adsi
->
pwfxSrc
->
wBitsPerSample
==
16
)
idx
+=
8
;
if
(
adsi
->
pwfxDst
->
wBitsPerSample
==
16
)
idx
+=
4
;
if
(
adsi
->
pwfxSrc
->
nChannels
==
1
)
idx
+=
2
;
if
(
adsi
->
pwfxDst
->
nChannels
==
1
)
idx
+=
1
;
if
(
adsi
->
pwfxSrc
->
nSamplesPerSec
==
adsi
->
pwfxDst
->
nSamplesPerSec
)
{
apd
->
cvt
.
cvtKeepRate
=
PCM_ConvertKeepRate
[
idx
];
}
else
{
adsi
->
fdwDriver
|=
PCM_RESAMPLE
;
apd
->
dstIncr
=
(
double
)(
adsi
->
pwfxSrc
->
nSamplesPerSec
)
/
(
double
)(
adsi
->
pwfxDst
->
nSamplesPerSec
);
PCM_Reset
(
apd
,
adsi
->
pwfxSrc
->
wBitsPerSample
);
apd
->
cvt
.
cvtChangeRate
=
PCM_ConvertChangeRate
[
idx
];
}
return
MMSYSERR_NOERROR
;
}
/***********************************************************************
* PCM_StreamClose
*
*/
static
LRESULT
PCM_StreamClose
(
PACMDRVSTREAMINSTANCE
adsi
)
{
HeapFree
(
GetProcessHeap
(),
0
,
(
void
*
)
adsi
->
dwDriver
);
return
MMSYSERR_NOERROR
;
}
/***********************************************************************
* PCM_round
*
*/
static
inline
DWORD
PCM_round
(
DWORD
a
,
DWORD
b
,
DWORD
c
)
{
assert
(
a
&&
b
&&
c
);
/* to be sure, always return an entire number of c... */
return
(
a
*
b
+
c
-
1
)
/
c
;
return
(
(
double
)
a
*
(
double
)
b
+
(
double
)
c
-
1
)
/
(
double
)
c
;
}
/***********************************************************************
* PCM_StreamSize
*
*/
static
LRESULT
PCM_StreamSize
(
PACMDRVSTREAMINSTANCE
adsi
,
PACMDRVSTREAMSIZE
adss
)
{
switch
(
adss
->
fdwSize
)
{
case
ACM_STREAMSIZEF_DESTINATION
:
/* cbDstLength => cbSrcLength */
adss
->
cbSrcLength
=
PCM_round
(
adss
->
cbDstLength
,
adsi
->
pwfxSrc
->
nAvgBytesPerSec
,
adsi
->
pwfxDst
->
nAvgBytesPerSec
);
adss
->
cbSrcLength
=
PCM_round
(
adss
->
cbDstLength
,
adsi
->
pwfxSrc
->
nAvgBytesPerSec
,
adsi
->
pwfxDst
->
nAvgBytesPerSec
);
break
;
case
ACM_STREAMSIZEF_SOURCE
:
/* cbSrcLength => cbDstLength */
adss
->
cbDstLength
=
PCM_round
(
adss
->
cbSrcLength
,
adsi
->
pwfxDst
->
nAvgBytesPerSec
,
adsi
->
pwfxSrc
->
nAvgBytesPerSec
);
adss
->
cbDstLength
=
PCM_round
(
adss
->
cbSrcLength
,
adsi
->
pwfxDst
->
nAvgBytesPerSec
,
adsi
->
pwfxSrc
->
nAvgBytesPerSec
);
break
;
default:
WARN
(
"Unsupported query %08lx
\n
"
,
adss
->
fdwSize
);
...
...
@@ -191,193 +890,50 @@ static LRESULT PCM_StreamSize(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMSIZE adss
return
MMSYSERR_NOERROR
;
}
/*
parameters :
8 bit unsigned vs 16 bit signed (-32 / +32k ???)
mono vs stereo
sampling rate (8.0, 11.025, 22.05, 44.1 kHz)
*/
static
void
cvtMS88K
(
const
unsigned
char
*
src
,
int
ns
,
unsigned
char
*
dst
)
/***********************************************************************
* PCM_StreamConvert
*
*/
static
LRESULT
PCM_StreamConvert
(
PACMDRVSTREAMINSTANCE
adsi
,
PACMDRVSTREAMHEADER
adsh
)
{
while
(
ns
--
)
{
*
dst
++
=
*
src
;
*
dst
++
=
*
src
++
;
}
}
AcmPcmData
*
apd
=
(
AcmPcmData
*
)
adsi
->
dwDriver
;
DWORD
nsrc
=
NUM_OF
(
adsh
->
cbSrcLength
,
adsi
->
pwfxSrc
->
nBlockAlign
);
DWORD
ndst
=
NUM_OF
(
adsh
->
cbDstLength
,
adsi
->
pwfxDst
->
nBlockAlign
);
static
void
cvtMS816K
(
const
unsigned
char
*
src
,
int
ns
,
short
*
dst
)
{
int
v
;
while
(
ns
--
)
{
v
=
((
short
)(
*
src
++
)
^
0x80
)
*
256
;
*
dst
++
=
LOBYTE
(
v
);
*
dst
++
=
HIBYTE
(
v
);
*
dst
++
=
LOBYTE
(
v
);
*
dst
++
=
HIBYTE
(
v
);
if
(
adsh
->
fdwConvert
&
~
(
ACM_STREAMCONVERTF_BLOCKALIGN
|
ACM_STREAMCONVERTF_END
|
ACM_STREAMCONVERTF_START
))
{
FIXME
(
"Unsupported fdwConvert (%08lx), ignoring it
\n
"
,
adsh
->
fdwConvert
);
}
}
static
void
cvtMS168K
(
const
short
*
src
,
int
ns
,
unsigned
char
*
dst
)
{
unsigned
char
v
;
while
(
ns
--
)
{
v
=
HIBYTE
(
*
src
++
)
^
0x80
;
*
dst
++
=
v
;
*
dst
++
=
v
;
/* 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
)
&&
(
adsi
->
fdwDriver
&
PCM_RESAMPLE
))
{
PCM_Reset
(
apd
,
adsi
->
pwfxSrc
->
wBitsPerSample
);
}
}
static
void
cvtMS1616K
(
const
short
*
src
,
int
ns
,
short
*
dst
)
{
while
(
ns
--
)
{
*
dst
++
=
*
src
;
*
dst
++
=
*
src
++
;
}
}
static
void
cvtSM88K
(
const
unsigned
char
*
src
,
int
ns
,
unsigned
char
*
dst
)
{
while
(
ns
--
)
{
*
dst
++
=
(
src
[
0
]
+
src
[
1
])
/
2
;
src
+=
2
;
}
}
static
void
cvtSM816K
(
const
unsigned
char
*
src
,
int
ns
,
short
*
dst
)
{
int
v
;
while
(
ns
--
)
{
v
=
(((
short
)(
src
[
0
])
^
0x80
)
*
256
+
((
short
)(
src
[
1
])
^
0x80
)
*
256
)
/
2
;
src
+=
2
;
*
dst
++
=
LOBYTE
(
v
);
*
dst
++
=
HIBYTE
(
v
);
}
}
static
void
cvtSM168K
(
const
short
*
src
,
int
ns
,
unsigned
char
*
dst
)
{
unsigned
char
v
;
while
(
ns
--
)
{
v
=
((
HIBYTE
(
src
[
0
])
^
0x80
)
+
(
HIBYTE
(
src
[
1
])
^
0x80
))
/
2
;
src
+=
2
;
*
dst
++
=
v
;
}
}
static
void
cvtSM1616K
(
const
short
*
src
,
int
ns
,
short
*
dst
)
{
while
(
ns
--
)
{
*
dst
++
=
(
src
[
0
]
+
src
[
1
])
/
2
;
src
+=
2
;
}
}
static
void
cvtMM816K
(
const
unsigned
char
*
src
,
int
ns
,
short
*
dst
)
{
int
v
;
while
(
ns
--
)
{
v
=
((
short
)(
*
src
++
)
^
0x80
)
*
256
;
*
dst
++
=
LOBYTE
(
v
);
*
dst
++
=
HIBYTE
(
v
);
}
}
/* do the job */
if
(
adsi
->
fdwDriver
&
PCM_RESAMPLE
)
{
DWORD
nsrc2
=
nsrc
;
DWORD
ndst2
=
ndst
;
static
void
cvtSS816K
(
const
unsigned
char
*
src
,
int
ns
,
short
*
dst
)
{
int
v
;
while
(
ns
--
)
{
v
=
((
short
)(
*
src
++
)
^
0x80
)
*
256
;
*
dst
++
=
LOBYTE
(
v
);
*
dst
++
=
HIBYTE
(
v
);
v
=
((
short
)(
*
src
++
)
^
0x80
)
*
256
;
*
dst
++
=
LOBYTE
(
v
);
*
dst
++
=
HIBYTE
(
v
);
}
}
apd
->
cvt
.
cvtChangeRate
(
apd
,
adsh
->
pbSrc
,
&
nsrc2
,
adsh
->
pbDst
,
&
ndst2
);
nsrc
-=
nsrc2
;
ndst
-=
ndst2
;
}
else
{
if
(
nsrc
<
ndst
)
ndst
=
nsrc
;
else
nsrc
=
ndst
;
static
void
cvtMM168K
(
const
short
*
src
,
int
ns
,
unsigned
char
*
dst
)
{
while
(
ns
--
)
{
*
dst
++
=
HIBYTE
(
*
src
++
)
^
0x80
;
/* nsrc is now equal to ndst */
apd
->
cvt
.
cvtKeepRate
(
adsh
->
pbSrc
,
nsrc
,
adsh
->
pbDst
);
}
}
static
void
cvtSS168K
(
const
short
*
src
,
int
ns
,
unsigned
char
*
dst
)
{
while
(
ns
--
)
{
*
dst
++
=
HIBYTE
(
*
src
++
)
^
0x80
;
*
dst
++
=
HIBYTE
(
*
src
++
)
^
0x80
;
}
}
adsh
->
cbSrcLengthUsed
=
nsrc
*
adsi
->
pwfxSrc
->
nBlockAlign
;
adsh
->
cbDstLengthUsed
=
ndst
*
adsi
->
pwfxDst
->
nBlockAlign
;
static
LRESULT
PCM_StreamConvert
(
PACMDRVSTREAMINSTANCE
adsi
,
PACMDRVSTREAMHEADER
adsh
)
{
/* do the job */
if
(
adsi
->
pwfxSrc
->
nSamplesPerSec
==
adsi
->
pwfxDst
->
nSamplesPerSec
)
{
/* easy case */
if
(
adsi
->
pwfxSrc
->
wBitsPerSample
==
adsi
->
pwfxDst
->
wBitsPerSample
&&
adsi
->
pwfxSrc
->
nChannels
==
adsi
->
pwfxDst
->
nChannels
)
{
memcpy
(
adsh
->
pbDst
,
adsh
->
pbSrc
,
adsh
->
cbSrcLength
);
}
else
if
(
adsi
->
pwfxSrc
->
wBitsPerSample
==
8
&&
adsi
->
pwfxDst
->
wBitsPerSample
==
8
)
{
if
(
adsi
->
pwfxSrc
->
nChannels
==
1
&&
adsi
->
pwfxDst
->
nChannels
==
2
)
cvtMS88K
(
adsh
->
pbSrc
,
adsh
->
cbSrcLength
,
adsh
->
pbDst
);
else
if
(
adsi
->
pwfxSrc
->
nChannels
==
2
&&
adsi
->
pwfxDst
->
nChannels
==
1
)
cvtSM88K
(
adsh
->
pbSrc
,
adsh
->
cbSrcLength
/
2
,
adsh
->
pbDst
);
}
else
if
(
adsi
->
pwfxSrc
->
wBitsPerSample
==
8
&&
adsi
->
pwfxDst
->
wBitsPerSample
==
16
)
{
if
(
adsi
->
pwfxSrc
->
nChannels
==
1
&&
adsi
->
pwfxDst
->
nChannels
==
1
)
cvtMM816K
(
adsh
->
pbSrc
,
adsh
->
cbSrcLength
,
(
short
*
)
adsh
->
pbDst
);
else
if
(
adsi
->
pwfxSrc
->
nChannels
==
1
&&
adsi
->
pwfxDst
->
nChannels
==
2
)
cvtMS816K
(
adsh
->
pbSrc
,
adsh
->
cbSrcLength
,
(
short
*
)
adsh
->
pbDst
);
else
if
(
adsi
->
pwfxSrc
->
nChannels
==
2
&&
adsi
->
pwfxDst
->
nChannels
==
1
)
cvtSM816K
(
adsh
->
pbSrc
,
adsh
->
cbSrcLength
/
2
,
(
short
*
)
adsh
->
pbDst
);
else
if
(
adsi
->
pwfxSrc
->
nChannels
==
2
&&
adsi
->
pwfxDst
->
nChannels
==
2
)
cvtSS816K
(
adsh
->
pbSrc
,
adsh
->
cbSrcLength
/
2
,
(
short
*
)
adsh
->
pbDst
);
}
else
if
(
adsi
->
pwfxSrc
->
wBitsPerSample
==
16
&&
adsi
->
pwfxDst
->
wBitsPerSample
==
8
)
{
if
(
adsi
->
pwfxSrc
->
nChannels
==
1
&&
adsi
->
pwfxDst
->
nChannels
==
1
)
cvtMM168K
((
short
*
)
adsh
->
pbSrc
,
adsh
->
cbSrcLength
/
2
,
adsh
->
pbDst
);
else
if
(
adsi
->
pwfxSrc
->
nChannels
==
1
&&
adsi
->
pwfxDst
->
nChannels
==
2
)
cvtMS168K
((
short
*
)
adsh
->
pbSrc
,
adsh
->
cbSrcLength
/
2
,
adsh
->
pbDst
);
else
if
(
adsi
->
pwfxSrc
->
nChannels
==
2
&&
adsi
->
pwfxDst
->
nChannels
==
1
)
cvtSM168K
((
short
*
)
adsh
->
pbSrc
,
adsh
->
cbSrcLength
/
4
,
adsh
->
pbDst
);
else
if
(
adsi
->
pwfxSrc
->
nChannels
==
2
&&
adsi
->
pwfxDst
->
nChannels
==
2
)
cvtSS168K
((
short
*
)
adsh
->
pbSrc
,
adsh
->
cbSrcLength
/
4
,
adsh
->
pbDst
);
}
else
if
(
adsi
->
pwfxSrc
->
wBitsPerSample
==
16
&&
adsi
->
pwfxDst
->
wBitsPerSample
==
16
)
{
if
(
adsi
->
pwfxSrc
->
nChannels
==
1
&&
adsi
->
pwfxDst
->
nChannels
==
2
)
cvtMS1616K
((
short
*
)
adsh
->
pbSrc
,
adsh
->
cbSrcLength
/
2
,
(
short
*
)
adsh
->
pbDst
);
else
if
(
adsi
->
pwfxSrc
->
nChannels
==
2
&&
adsi
->
pwfxDst
->
nChannels
==
1
)
cvtSM1616K
((
short
*
)
adsh
->
pbSrc
,
adsh
->
cbSrcLength
/
4
,
(
short
*
)
adsh
->
pbDst
);
}
else
FIXME
(
"NIY
\n
"
);
/* FIXME: rounding shall be taken care off... */
adsh
->
cbSrcLengthUsed
=
adsh
->
cbSrcLength
;
adsh
->
cbDstLengthUsed
=
(
adsh
->
cbSrcLength
*
adsi
->
pwfxDst
->
nBlockAlign
)
/
adsi
->
pwfxSrc
->
nBlockAlign
;
}
else
{
FIXME
(
"NIY
\n
"
);
return
MMSYSERR_NOTSUPPORTED
;
}
return
MMSYSERR_NOERROR
;
}
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment