Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
3291a058
Commit
3291a058
authored
Oct 22, 2000
by
Eric Pouech
Committed by
Alexandre Julliard
Oct 22, 2000
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added more conversion routines (rate conversion is implemented).
Cleaned up the code.
parent
9039421b
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
760 additions
and
204 deletions
+760
-204
pcmconverter.c
dlls/msacm/pcmconverter.c
+760
-204
No files found.
dlls/msacm/pcmconverter.c
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
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment