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
6cc67347
Commit
6cc67347
authored
Dec 05, 2016
by
Andrew Eikum
Committed by
Alexandre Julliard
Dec 06, 2016
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
msacm32: Support conversion from 24-bit PCM.
Signed-off-by:
Andrew Eikum
<
aeikum@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
eb3c4f43
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
299 additions
and
21 deletions
+299
-21
pcmconverter.c
dlls/msacm32/pcmconverter.c
+299
-21
No files found.
dlls/msacm32/pcmconverter.c
View file @
6cc67347
...
...
@@ -95,12 +95,12 @@ static const struct {
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
,
48000
},
{
2
,
8
,
48000
},
{
1
,
16
,
48000
},
{
2
,
16
,
48000
},
{
1
,
8
,
96000
},
{
2
,
8
,
96000
},
{
1
,
16
,
96000
},
{
2
,
16
,
96000
}
{
1
,
8
,
8000
},
{
2
,
8
,
8000
},
{
1
,
16
,
8000
},
{
2
,
16
,
8000
},
{
1
,
24
,
8000
},
{
2
,
24
,
8000
},
{
1
,
8
,
11025
},
{
2
,
8
,
11025
},
{
1
,
16
,
11025
},
{
2
,
16
,
11025
},
{
1
,
24
,
11025
},
{
2
,
24
,
11025
},
{
1
,
8
,
22050
},
{
2
,
8
,
22050
},
{
1
,
16
,
22050
},
{
2
,
16
,
22050
},
{
1
,
24
,
22050
},
{
2
,
24
,
22050
},
{
1
,
8
,
44100
},
{
2
,
8
,
44100
},
{
1
,
16
,
44100
},
{
2
,
16
,
44100
},
{
1
,
24
,
44100
},
{
2
,
24
,
44100
},
{
1
,
8
,
48000
},
{
2
,
8
,
48000
},
{
1
,
16
,
48000
},
{
2
,
16
,
48000
},
{
1
,
24
,
48000
},
{
2
,
24
,
48000
},
{
1
,
8
,
96000
},
{
2
,
8
,
96000
},
{
1
,
16
,
96000
},
{
2
,
16
,
96000
}
,
{
1
,
24
,
96000
},
{
2
,
24
,
96000
},
};
/***********************************************************************
...
...
@@ -153,6 +153,26 @@ static inline unsigned char C168(short s)
}
/***********************************************************************
* C248
*
* Converts a 24 bit sample to a 8 bit one (data loss !!)
*/
static
inline
unsigned
char
C248
(
int
s
)
{
return
HIBYTE
(
HIWORD
(
s
))
^
(
unsigned
char
)
0x80
;
}
/***********************************************************************
* C2416
*
* Converts a 24 bit sample to a 16 bit one (data loss !!)
*/
static
inline
short
C2416
(
int
s
)
{
return
HIWORD
(
s
);
}
/***********************************************************************
* R16
*
* Read a 16 bit sample (correctly handles endianness)
...
...
@@ -163,6 +183,18 @@ static inline short R16(const unsigned char* src)
}
/***********************************************************************
* R24
*
* Read a 24 bit sample (correctly handles endianness)
* Note, to support signed arithmetic, the values are shifted high in the int
* and low 8 bytes are unused.
*/
static
inline
int
R24
(
const
unsigned
char
*
src
)
{
return
((
int
)
src
[
0
]
|
(
int
)
src
[
1
]
<<
8
|
(
int
)
src
[
2
]
<<
16
)
<<
8
;
}
/***********************************************************************
* W16
*
* Write a 16 bit sample (correctly handles endianness)
...
...
@@ -174,6 +206,37 @@ static inline void W16(unsigned char* dst, short s)
}
/***********************************************************************
* W24
*
* Write a 24 bit sample (correctly handles endianness)
*/
static
inline
void
W24
(
unsigned
char
*
dst
,
int
s
)
{
dst
[
0
]
=
HIBYTE
(
LOWORD
(
s
));
dst
[
1
]
=
LOBYTE
(
HIWORD
(
s
));
dst
[
2
]
=
HIBYTE
(
HIWORD
(
s
));
}
/***********************************************************************
* M24
*
* Convert the (l,r) 24 bit stereo sample into a 24 bit mono
* (takes the sum of the two values)
*/
static
inline
int
M24
(
int
l
,
int
r
)
{
LONGLONG
sum
=
l
+
r
;
/* clip sum to saturation */
if
(
sum
>
0x7fffff00
)
sum
=
0x7fffff00
;
else
if
(
sum
<
-
0x7fffff00
)
sum
=
-
0x7fffff00
;
return
sum
;
}
/***********************************************************************
* M16
*
* Convert the (l,r) 16 bit stereo sample into a 16 bit mono
...
...
@@ -374,14 +437,102 @@ static void cvtSS168K(const unsigned char* src, int ns, unsigned char* dst)
}
}
static
void
cvtMS248K
(
const
unsigned
char
*
src
,
int
ns
,
unsigned
char
*
dst
)
{
unsigned
char
v
;
TRACE
(
"(%p, %d, %p)
\n
"
,
src
,
ns
,
dst
);
while
(
ns
--
)
{
v
=
C248
(
R24
(
src
));
src
+=
3
;
*
dst
++
=
v
;
*
dst
++
=
v
;
}
}
static
void
cvtSM248K
(
const
unsigned
char
*
src
,
int
ns
,
unsigned
char
*
dst
)
{
TRACE
(
"(%p, %d, %p)
\n
"
,
src
,
ns
,
dst
);
while
(
ns
--
)
{
*
dst
++
=
C248
(
M24
(
R24
(
src
),
R24
(
src
+
3
)));
src
+=
6
;
}
}
static
void
cvtMM248K
(
const
unsigned
char
*
src
,
int
ns
,
unsigned
char
*
dst
)
{
TRACE
(
"(%p, %d, %p)
\n
"
,
src
,
ns
,
dst
);
while
(
ns
--
)
{
*
dst
++
=
C248
(
R24
(
src
));
src
+=
3
;
}
}
static
void
cvtSS248K
(
const
unsigned
char
*
src
,
int
ns
,
unsigned
char
*
dst
)
{
TRACE
(
"(%p, %d, %p)
\n
"
,
src
,
ns
,
dst
);
while
(
ns
--
)
{
*
dst
++
=
C248
(
R24
(
src
));
src
+=
3
;
*
dst
++
=
C248
(
R24
(
src
));
src
+=
3
;
}
}
static
void
cvtMS2416K
(
const
unsigned
char
*
src
,
int
ns
,
unsigned
char
*
dst
)
{
short
v
;
TRACE
(
"(%p, %d, %p)
\n
"
,
src
,
ns
,
dst
);
while
(
ns
--
)
{
v
=
C2416
(
R24
(
src
));
src
+=
3
;
W16
(
dst
,
v
);
dst
+=
2
;
W16
(
dst
,
v
);
dst
+=
2
;
}
}
static
void
cvtSM2416K
(
const
unsigned
char
*
src
,
int
ns
,
unsigned
char
*
dst
)
{
TRACE
(
"(%p, %d, %p)
\n
"
,
src
,
ns
,
dst
);
while
(
ns
--
)
{
W16
(
dst
,
C2416
(
M24
(
R24
(
src
),
R24
(
src
+
3
))));
dst
+=
2
;
src
+=
6
;
}
}
static
void
cvtMM2416K
(
const
unsigned
char
*
src
,
int
ns
,
unsigned
char
*
dst
)
{
TRACE
(
"(%p, %d, %p)
\n
"
,
src
,
ns
,
dst
);
while
(
ns
--
)
{
W16
(
dst
,
C2416
(
R24
(
src
)));
dst
+=
2
;
src
+=
3
;
}
}
static
void
cvtSS2416K
(
const
unsigned
char
*
src
,
int
ns
,
unsigned
char
*
dst
)
{
TRACE
(
"(%p, %d, %p)
\n
"
,
src
,
ns
,
dst
);
while
(
ns
--
)
{
W16
(
dst
,
C2416
(
R24
(
src
)));
dst
+=
2
;
src
+=
3
;
W16
(
dst
,
C2416
(
R24
(
src
)));
dst
+=
2
;
src
+=
3
;
}
}
typedef
void
(
*
PCM_CONVERT_KEEP_RATE
)(
const
unsigned
char
*
,
int
,
unsigned
char
*
);
static
const
PCM_CONVERT_KEEP_RATE
PCM_ConvertKeepRate
[
16
]
=
{
static
const
PCM_CONVERT_KEEP_RATE
PCM_ConvertKeepRate
[]
=
{
cvtSS88K
,
cvtSM88K
,
cvtMS88K
,
cvtMM88K
,
cvtSS816K
,
cvtSM816K
,
cvtMS816K
,
cvtMM816K
,
NULL
,
NULL
,
NULL
,
NULL
,
/* TODO: 8->24 */
cvtSS168K
,
cvtSM168K
,
cvtMS168K
,
cvtMM168K
,
cvtSS1616K
,
cvtSM1616K
,
cvtMS1616K
,
cvtMM1616K
,
NULL
,
NULL
,
NULL
,
NULL
,
/* TODO: 16->24 */
cvtSS248K
,
cvtSM248K
,
cvtMS248K
,
cvtMM248K
,
cvtSS2416K
,
cvtSM2416K
,
cvtMS2416K
,
cvtMM2416K
,
NULL
,
NULL
,
NULL
,
NULL
,
/* TODO: 24->24 */
};
/* the conversion routines with rate conversion are labelled cvt<X><Y><N><M>C
...
...
@@ -704,13 +855,96 @@ static void cvtMM1616C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
}
}
static
void
cvtSS2424C
(
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
)
--
)
{
W24
(
dst
,
R24
(
src
));
dst
+=
3
;
W24
(
dst
,
R24
(
src
));
dst
+=
3
;
error
=
error
+
srcRate
;
while
(
error
>
dstRate
)
{
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
)
{
DWORD
error
=
dstRate
/
2
;
TRACE
(
"(%d, %p, %p, %d, %p, %p)
\n
"
,
srcRate
,
src
,
nsrc
,
dstRate
,
dst
,
ndst
);
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
)
{
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
)
return
;
error
=
error
-
dstRate
;
}
}
}
static
void
cvtMM2424C
(
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
)
--
)
{
W24
(
dst
,
R24
(
src
));
dst
+=
3
;
error
=
error
+
srcRate
;
while
(
error
>
dstRate
)
{
src
+=
3
;
(
*
nsrc
)
--
;
if
(
*
nsrc
==
0
)
return
;
error
=
error
-
dstRate
;
}
}
}
typedef
void
(
*
PCM_CONVERT_CHANGE_RATE
)(
DWORD
,
const
unsigned
char
*
,
LPDWORD
,
DWORD
,
unsigned
char
*
,
LPDWORD
);
static
const
PCM_CONVERT_CHANGE_RATE
PCM_ConvertChangeRate
[
16
]
=
{
static
const
PCM_CONVERT_CHANGE_RATE
PCM_ConvertChangeRate
[]
=
{
cvtSS88C
,
cvtSM88C
,
cvtMS88C
,
cvtMM88C
,
cvtSS816C
,
cvtSM816C
,
cvtMS816C
,
cvtMM816C
,
NULL
,
NULL
,
NULL
,
NULL
,
/* TODO: 8->24 */
cvtSS168C
,
cvtSM168C
,
cvtMS168C
,
cvtMM168C
,
cvtSS1616C
,
cvtSM1616C
,
cvtMS1616C
,
cvtMM1616C
,
NULL
,
NULL
,
NULL
,
NULL
,
/* TODO: 16->24 */
NULL
,
NULL
,
NULL
,
NULL
,
/* TODO: 24->8 */
NULL
,
NULL
,
NULL
,
NULL
,
/* TODO: 24->16 */
cvtSS2424C
,
cvtSM2424C
,
cvtMS2424C
,
cvtMM2424C
,
};
/***********************************************************************
...
...
@@ -886,34 +1120,78 @@ static LRESULT PCM_FormatSuggest(PACMDRVFORMATSUGGEST adfs)
*/
static
LRESULT
PCM_StreamOpen
(
PACMDRVSTREAMINSTANCE
adsi
)
{
AcmPcmData
*
apd
;
int
idx
=
0
;
AcmPcmData
*
apd
;
int
idx
;
DWORD
flags
;
TRACE
(
"(%p)
\n
"
,
adsi
);
assert
(
!
(
adsi
->
fdwOpen
&
ACM_STREAMOPENF_ASYNC
));
apd
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
AcmPcmData
));
if
(
apd
==
0
)
{
WARN
(
"no memory
\n
"
);
return
MMSYSERR_NOMEM
;
switch
(
adsi
->
pwfxSrc
->
wBitsPerSample
){
case
8
:
idx
=
0
;
break
;
case
16
:
idx
=
12
;
break
;
case
24
:
if
(
adsi
->
pwfxSrc
->
nBlockAlign
!=
3
*
adsi
->
pwfxSrc
->
nChannels
)
{
FIXME
(
"Source: 24-bit samples must be packed
\n
"
);
return
MMSYSERR_NOTSUPPORTED
;
}
idx
=
24
;
break
;
default:
FIXME
(
"Unsupported source bit depth: %u
\n
"
,
adsi
->
pwfxSrc
->
wBitsPerSample
);
return
MMSYSERR_NOTSUPPORTED
;
}
adsi
->
dwDriver
=
(
DWORD_PTR
)
apd
;
adsi
->
fdwDriver
=
0
;
switch
(
adsi
->
pwfxDst
->
wBitsPerSample
){
case
8
:
break
;
case
16
:
idx
+=
4
;
break
;
case
24
:
if
(
adsi
->
pwfxDst
->
nBlockAlign
!=
3
*
adsi
->
pwfxSrc
->
nChannels
)
{
FIXME
(
"Destination: 24-bit samples must be packed
\n
"
);
return
MMSYSERR_NOTSUPPORTED
;
}
idx
+=
8
;
break
;
default:
FIXME
(
"Unsupported destination bit depth: %u
\n
"
,
adsi
->
pwfxDst
->
wBitsPerSample
);
return
MMSYSERR_NOTSUPPORTED
;
}
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
;
apd
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
AcmPcmData
));
if
(
!
apd
)
return
MMSYSERR_NOMEM
;
if
(
adsi
->
pwfxSrc
->
nSamplesPerSec
==
adsi
->
pwfxDst
->
nSamplesPerSec
)
{
apd
->
cvt
.
cvtKeepRate
=
PCM_ConvertKeepRate
[
idx
];
flags
=
0
;
apd
->
cvt
.
cvtKeepRate
=
PCM_ConvertKeepRate
[
idx
];
}
else
{
adsi
->
fdwDriver
|=
PCM_RESAMPLE
;
apd
->
cvt
.
cvtChangeRate
=
PCM_ConvertChangeRate
[
idx
];
flags
=
PCM_RESAMPLE
;
apd
->
cvt
.
cvtChangeRate
=
PCM_ConvertChangeRate
[
idx
];
}
if
(
!
apd
->
cvt
.
cvtChangeRate
&&
!
apd
->
cvt
.
cvtKeepRate
){
FIXME
(
"Unimplemented conversion from %u -> %u bps
\n
"
,
adsi
->
pwfxSrc
->
wBitsPerSample
,
adsi
->
pwfxDst
->
wBitsPerSample
);
HeapFree
(
GetProcessHeap
(),
0
,
apd
);
return
MMSYSERR_NOTSUPPORTED
;
}
adsi
->
dwDriver
=
(
DWORD_PTR
)
apd
;
adsi
->
fdwDriver
=
flags
;
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