Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
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-cw
Commits
d402231e
Commit
d402231e
authored
Aug 16, 2012
by
Andrew Eikum
Committed by
Alexandre Julliard
Aug 17, 2012
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
winealsa.drv: Remap mmdevapi channels to correct ALSA channels.
parent
36eb79e7
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
173 additions
and
28 deletions
+173
-28
mmdevdrv.c
dlls/winealsa.drv/mmdevdrv.c
+173
-28
No files found.
dlls/winealsa.drv/mmdevdrv.c
View file @
d402231e
...
@@ -108,15 +108,20 @@ struct ACImpl {
...
@@ -108,15 +108,20 @@ struct ACImpl {
HANDLE
event
;
HANDLE
event
;
float
*
vols
;
float
*
vols
;
BOOL
need_remapping
;
int
alsa_channels
;
int
alsa_channel_map
[
32
];
BOOL
initted
,
started
;
BOOL
initted
,
started
;
REFERENCE_TIME
mmdev_period_rt
;
REFERENCE_TIME
mmdev_period_rt
;
UINT64
written_frames
,
last_pos_frames
;
UINT64
written_frames
,
last_pos_frames
;
UINT32
bufsize_frames
,
held_frames
,
tmp_buffer_frames
,
mmdev_period_frames
;
UINT32
bufsize_frames
,
held_frames
,
tmp_buffer_frames
,
mmdev_period_frames
;
snd_pcm_uframes_t
remapping_buf_frames
;
UINT32
lcl_offs_frames
;
/* offs into local_buffer where valid data starts */
UINT32
lcl_offs_frames
;
/* offs into local_buffer where valid data starts */
UINT32
hidden_frames
;
/* ALSA reserve to ensure continuous rendering */
UINT32
hidden_frames
;
/* ALSA reserve to ensure continuous rendering */
HANDLE
timer
;
HANDLE
timer
;
BYTE
*
local_buffer
,
*
tmp_buffer
;
BYTE
*
local_buffer
,
*
tmp_buffer
,
*
remapping_buf
;
LONG32
getbuf_last
;
/* <0 when using tmp_buffer */
LONG32
getbuf_last
;
/* <0 when using tmp_buffer */
CRITICAL_SECTION
lock
;
CRITICAL_SECTION
lock
;
...
@@ -885,6 +890,7 @@ static ULONG WINAPI AudioClient_Release(IAudioClient *iface)
...
@@ -885,6 +890,7 @@ static ULONG WINAPI AudioClient_Release(IAudioClient *iface)
}
}
HeapFree
(
GetProcessHeap
(),
0
,
This
->
vols
);
HeapFree
(
GetProcessHeap
(),
0
,
This
->
vols
);
HeapFree
(
GetProcessHeap
(),
0
,
This
->
local_buffer
);
HeapFree
(
GetProcessHeap
(),
0
,
This
->
local_buffer
);
HeapFree
(
GetProcessHeap
(),
0
,
This
->
remapping_buf
);
HeapFree
(
GetProcessHeap
(),
0
,
This
->
tmp_buffer
);
HeapFree
(
GetProcessHeap
(),
0
,
This
->
tmp_buffer
);
HeapFree
(
GetProcessHeap
(),
0
,
This
->
hw_params
);
HeapFree
(
GetProcessHeap
(),
0
,
This
->
hw_params
);
CoTaskMemFree
(
This
->
fmt
);
CoTaskMemFree
(
This
->
fmt
);
...
@@ -1071,6 +1077,121 @@ static HRESULT get_audio_session(const GUID *sessionguid,
...
@@ -1071,6 +1077,121 @@ static HRESULT get_audio_session(const GUID *sessionguid,
return
S_OK
;
return
S_OK
;
}
}
static
int
alsa_channel_index
(
DWORD
flag
)
{
switch
(
flag
){
case
SPEAKER_FRONT_LEFT
:
return
0
;
case
SPEAKER_FRONT_RIGHT
:
return
1
;
case
SPEAKER_BACK_LEFT
:
return
2
;
case
SPEAKER_BACK_RIGHT
:
return
3
;
case
SPEAKER_FRONT_CENTER
:
return
4
;
case
SPEAKER_LOW_FREQUENCY
:
return
5
;
case
SPEAKER_SIDE_LEFT
:
return
6
;
case
SPEAKER_SIDE_RIGHT
:
return
7
;
}
return
-
1
;
}
static
BOOL
need_remapping
(
ACImpl
*
This
,
const
WAVEFORMATEX
*
fmt
)
{
unsigned
int
i
;
for
(
i
=
0
;
i
<
fmt
->
nChannels
;
++
i
){
if
(
This
->
alsa_channel_map
[
i
]
!=
i
)
return
TRUE
;
}
return
FALSE
;
}
static
DWORD
get_channel_mask
(
unsigned
int
channels
)
{
switch
(
channels
){
case
0
:
return
0
;
case
1
:
return
KSAUDIO_SPEAKER_MONO
;
case
2
:
return
KSAUDIO_SPEAKER_STEREO
;
case
3
:
return
KSAUDIO_SPEAKER_STEREO
|
SPEAKER_LOW_FREQUENCY
;
case
4
:
return
KSAUDIO_SPEAKER_QUAD
;
/* not _SURROUND */
case
5
:
return
KSAUDIO_SPEAKER_QUAD
|
SPEAKER_LOW_FREQUENCY
;
case
6
:
return
KSAUDIO_SPEAKER_5POINT1
;
/* not 5POINT1_SURROUND */
case
7
:
return
KSAUDIO_SPEAKER_5POINT1
|
SPEAKER_BACK_CENTER
;
case
8
:
return
KSAUDIO_SPEAKER_7POINT1_SURROUND
;
/* Vista deprecates 7POINT1 */
}
FIXME
(
"Unknown speaker configuration: %u
\n
"
,
channels
);
return
0
;
}
static
HRESULT
map_channels
(
ACImpl
*
This
,
const
WAVEFORMATEX
*
fmt
)
{
if
(
fmt
->
wFormatTag
==
WAVE_FORMAT_EXTENSIBLE
||
fmt
->
nChannels
>
2
){
WAVEFORMATEXTENSIBLE
*
fmtex
=
(
void
*
)
fmt
;
DWORD
mask
,
flag
=
SPEAKER_FRONT_LEFT
;
UINT
i
=
0
;
if
(
fmt
->
wFormatTag
==
WAVE_FORMAT_EXTENSIBLE
&&
fmtex
->
dwChannelMask
!=
0
)
mask
=
fmtex
->
dwChannelMask
;
else
mask
=
get_channel_mask
(
fmt
->
nChannels
);
This
->
alsa_channels
=
0
;
while
(
i
<
fmt
->
nChannels
&&
!
(
flag
&
SPEAKER_RESERVED
)){
if
(
mask
&
flag
){
This
->
alsa_channel_map
[
i
]
=
alsa_channel_index
(
flag
);
TRACE
(
"Mapping mmdevapi channel %u (0x%x) to ALSA channel %d
\n
"
,
i
,
flag
,
This
->
alsa_channel_map
[
i
]);
if
(
This
->
alsa_channel_map
[
i
]
>=
This
->
alsa_channels
)
This
->
alsa_channels
=
This
->
alsa_channel_map
[
i
]
+
1
;
++
i
;
}
flag
<<=
1
;
}
while
(
i
<
fmt
->
nChannels
){
This
->
alsa_channel_map
[
i
]
=
This
->
alsa_channels
;
TRACE
(
"Mapping mmdevapi channel %u to ALSA channel %d
\n
"
,
i
,
This
->
alsa_channel_map
[
i
]);
++
This
->
alsa_channels
;
++
i
;
}
for
(
i
=
0
;
i
<
fmt
->
nChannels
;
++
i
){
if
(
This
->
alsa_channel_map
[
i
]
==
-
1
){
This
->
alsa_channel_map
[
i
]
=
This
->
alsa_channels
;
++
This
->
alsa_channels
;
TRACE
(
"Remapping mmdevapi channel %u to ALSA channel %d
\n
"
,
i
,
This
->
alsa_channel_map
[
i
]);
}
}
This
->
need_remapping
=
need_remapping
(
This
,
fmt
);
TRACE
(
"need_remapping: %u, alsa_channels: %d
\n
"
,
This
->
need_remapping
,
This
->
alsa_channels
);
}
else
{
This
->
need_remapping
=
FALSE
;
This
->
alsa_channels
=
fmt
->
nChannels
;
TRACE
(
"need_remapping: %u, alsa_channels: %d
\n
"
,
This
->
need_remapping
,
This
->
alsa_channels
);
}
return
S_OK
;
}
static
HRESULT
WINAPI
AudioClient_Initialize
(
IAudioClient
*
iface
,
static
HRESULT
WINAPI
AudioClient_Initialize
(
IAudioClient
*
iface
,
AUDCLNT_SHAREMODE
mode
,
DWORD
flags
,
REFERENCE_TIME
duration
,
AUDCLNT_SHAREMODE
mode
,
DWORD
flags
,
REFERENCE_TIME
duration
,
REFERENCE_TIME
period
,
const
WAVEFORMATEX
*
fmt
,
REFERENCE_TIME
period
,
const
WAVEFORMATEX
*
fmt
,
...
@@ -1135,6 +1256,12 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient *iface,
...
@@ -1135,6 +1256,12 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient *iface,
dump_fmt
(
fmt
);
dump_fmt
(
fmt
);
if
(
FAILED
(
map_channels
(
This
,
fmt
))){
WARN
(
"map_channels failed
\n
"
);
hr
=
AUDCLNT_E_ENDPOINT_CREATE_FAILED
;
goto
exit
;
}
if
((
err
=
snd_pcm_hw_params_any
(
This
->
pcm_handle
,
This
->
hw_params
))
<
0
){
if
((
err
=
snd_pcm_hw_params_any
(
This
->
pcm_handle
,
This
->
hw_params
))
<
0
){
WARN
(
"Unable to get hw_params: %d (%s)
\n
"
,
err
,
snd_strerror
(
err
));
WARN
(
"Unable to get hw_params: %d (%s)
\n
"
,
err
,
snd_strerror
(
err
));
hr
=
AUDCLNT_E_ENDPOINT_CREATE_FAILED
;
hr
=
AUDCLNT_E_ENDPOINT_CREATE_FAILED
;
...
@@ -1174,7 +1301,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient *iface,
...
@@ -1174,7 +1301,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient *iface,
}
}
if
((
err
=
snd_pcm_hw_params_set_channels
(
This
->
pcm_handle
,
This
->
hw_params
,
if
((
err
=
snd_pcm_hw_params_set_channels
(
This
->
pcm_handle
,
This
->
hw_params
,
fmt
->
nC
hannels
))
<
0
){
This
->
alsa_c
hannels
))
<
0
){
WARN
(
"Unable to set channels to %u: %d (%s)
\n
"
,
fmt
->
nChannels
,
err
,
WARN
(
"Unable to set channels to %u: %d (%s)
\n
"
,
fmt
->
nChannels
,
err
,
snd_strerror
(
err
));
snd_strerror
(
err
));
hr
=
AUDCLNT_E_UNSUPPORTED_FORMAT
;
hr
=
AUDCLNT_E_UNSUPPORTED_FORMAT
;
...
@@ -1428,32 +1555,6 @@ static HRESULT WINAPI AudioClient_GetCurrentPadding(IAudioClient *iface,
...
@@ -1428,32 +1555,6 @@ static HRESULT WINAPI AudioClient_GetCurrentPadding(IAudioClient *iface,
return
S_OK
;
return
S_OK
;
}
}
static
DWORD
get_channel_mask
(
unsigned
int
channels
)
{
switch
(
channels
){
case
0
:
return
0
;
case
1
:
return
KSAUDIO_SPEAKER_MONO
;
case
2
:
return
KSAUDIO_SPEAKER_STEREO
;
case
3
:
return
KSAUDIO_SPEAKER_STEREO
|
SPEAKER_LOW_FREQUENCY
;
case
4
:
return
KSAUDIO_SPEAKER_QUAD
;
/* not _SURROUND */
case
5
:
return
KSAUDIO_SPEAKER_QUAD
|
SPEAKER_LOW_FREQUENCY
;
case
6
:
return
KSAUDIO_SPEAKER_5POINT1
;
/* not 5POINT1_SURROUND */
case
7
:
return
KSAUDIO_SPEAKER_5POINT1
|
SPEAKER_BACK_CENTER
;
case
8
:
return
KSAUDIO_SPEAKER_7POINT1_SURROUND
;
/* Vista deprecates 7POINT1 */
}
FIXME
(
"Unknown speaker configuration: %u
\n
"
,
channels
);
return
0
;
}
static
HRESULT
WINAPI
AudioClient_IsFormatSupported
(
IAudioClient
*
iface
,
static
HRESULT
WINAPI
AudioClient_IsFormatSupported
(
IAudioClient
*
iface
,
AUDCLNT_SHAREMODE
mode
,
const
WAVEFORMATEX
*
fmt
,
AUDCLNT_SHAREMODE
mode
,
const
WAVEFORMATEX
*
fmt
,
WAVEFORMATEX
**
out
)
WAVEFORMATEX
**
out
)
...
@@ -1550,6 +1651,16 @@ static HRESULT WINAPI AudioClient_IsFormatSupported(IAudioClient *iface,
...
@@ -1550,6 +1651,16 @@ static HRESULT WINAPI AudioClient_IsFormatSupported(IAudioClient *iface,
closest
->
nChannels
=
min
;
closest
->
nChannels
=
min
;
}
}
if
(
FAILED
(
map_channels
(
This
,
fmt
))){
hr
=
AUDCLNT_E_DEVICE_INVALIDATED
;
WARN
(
"map_channels failed
\n
"
);
goto
exit
;
}
if
(
This
->
alsa_channels
>
max
){
hr
=
S_FALSE
;
closest
->
nChannels
=
max
;
}
if
(
closest
->
wFormatTag
==
WAVE_FORMAT_EXTENSIBLE
)
if
(
closest
->
wFormatTag
==
WAVE_FORMAT_EXTENSIBLE
)
((
WAVEFORMATEXTENSIBLE
*
)
closest
)
->
dwChannelMask
=
get_channel_mask
(
closest
->
nChannels
);
((
WAVEFORMATEXTENSIBLE
*
)
closest
)
->
dwChannelMask
=
get_channel_mask
(
closest
->
nChannels
);
...
@@ -1706,6 +1817,38 @@ static HRESULT WINAPI AudioClient_GetDevicePeriod(IAudioClient *iface,
...
@@ -1706,6 +1817,38 @@ static HRESULT WINAPI AudioClient_GetDevicePeriod(IAudioClient *iface,
return
S_OK
;
return
S_OK
;
}
}
static
BYTE
*
remap_channels
(
ACImpl
*
This
,
BYTE
*
buf
,
snd_pcm_uframes_t
frames
)
{
snd_pcm_uframes_t
i
;
UINT
c
;
UINT
bytes_per_sample
=
This
->
fmt
->
wBitsPerSample
/
8
;
if
(
!
This
->
need_remapping
)
return
buf
;
if
(
!
This
->
remapping_buf
){
This
->
remapping_buf
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
This
->
fmt
->
wBitsPerSample
/
8
)
*
This
->
alsa_channels
*
frames
);
This
->
remapping_buf_frames
=
frames
;
}
else
if
(
This
->
remapping_buf_frames
<
frames
){
This
->
remapping_buf
=
HeapReAlloc
(
GetProcessHeap
(),
0
,
This
->
remapping_buf
,
(
This
->
fmt
->
wBitsPerSample
/
8
)
*
This
->
alsa_channels
*
frames
);
This
->
remapping_buf_frames
=
frames
;
}
snd_pcm_format_set_silence
(
This
->
alsa_format
,
This
->
remapping_buf
,
frames
*
This
->
alsa_channels
);
for
(
i
=
0
;
i
<
frames
;
++
i
){
for
(
c
=
0
;
c
<
This
->
fmt
->
nChannels
;
++
c
){
memcpy
(
&
This
->
remapping_buf
[(
i
*
This
->
alsa_channels
+
This
->
alsa_channel_map
[
c
])
*
bytes_per_sample
],
&
buf
[(
i
*
This
->
fmt
->
nChannels
+
c
)
*
bytes_per_sample
],
bytes_per_sample
);
}
}
return
This
->
remapping_buf
;
}
static
snd_pcm_sframes_t
alsa_write_best_effort
(
snd_pcm_t
*
handle
,
BYTE
*
buf
,
static
snd_pcm_sframes_t
alsa_write_best_effort
(
snd_pcm_t
*
handle
,
BYTE
*
buf
,
snd_pcm_uframes_t
frames
,
ACImpl
*
This
,
BOOL
mute
)
snd_pcm_uframes_t
frames
,
ACImpl
*
This
,
BOOL
mute
)
{
{
...
@@ -1719,6 +1862,8 @@ static snd_pcm_sframes_t alsa_write_best_effort(snd_pcm_t *handle, BYTE *buf,
...
@@ -1719,6 +1862,8 @@ static snd_pcm_sframes_t alsa_write_best_effort(snd_pcm_t *handle, BYTE *buf,
snd_strerror
(
err
));
snd_strerror
(
err
));
}
}
buf
=
remap_channels
(
This
,
buf
,
frames
);
written
=
snd_pcm_writei
(
handle
,
buf
,
frames
);
written
=
snd_pcm_writei
(
handle
,
buf
,
frames
);
if
(
written
<
0
){
if
(
written
<
0
){
int
ret
;
int
ret
;
...
...
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