Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-1.1
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc-1.1
Commits
aad898d5
Commit
aad898d5
authored
Jan 26, 2003
by
Gildas Bazin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
* modules/audio_output/waveout.c: multichannel and spdif support (spdif untested).
parent
ae704c8c
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
471 additions
and
74 deletions
+471
-74
modules/audio_output/waveout.c
modules/audio_output/waveout.c
+471
-74
No files found.
modules/audio_output/waveout.c
View file @
aad898d5
...
...
@@ -2,7 +2,7 @@
* waveout.c : Windows waveOut plugin for vlc
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: waveout.c,v 1.1
3 2002/12/10 18:22:01
gbazin Exp $
* $Id: waveout.c,v 1.1
4 2003/01/26 16:37:20
gbazin Exp $
*
* Authors: Gildas Bazin <gbazin@netcourrier.com>
*
...
...
@@ -40,10 +40,69 @@
/*****************************************************************************
* Useful macros
*****************************************************************************/
#ifdef UNDER_CE
# define DWORD_PTR DWORD
#endif
#ifndef WAVE_FORMAT_IEEE_FLOAT
# define WAVE_FORMAT_IEEE_FLOAT 0x0003
#endif
#ifndef WAVE_FORMAT_DOLBY_AC3_SPDIF
# define WAVE_FORMAT_DOLBY_AC3_SPDIF 0x0092
#endif
#ifndef WAVE_FORMAT_EXTENSIBLE
#define WAVE_FORMAT_EXTENSIBLE 0xFFFE
#endif
#ifndef SPEAKER_FRONT_LEFT
# define SPEAKER_FRONT_LEFT 0x1
# define SPEAKER_FRONT_RIGHT 0x2
# define SPEAKER_FRONT_CENTER 0x4
# define SPEAKER_LOW_FREQUENCY 0x8
# define SPEAKER_BACK_LEFT 0x10
# define SPEAKER_BACK_RIGHT 0x20
# define SPEAKER_FRONT_LEFT_OF_CENTER 0x40
# define SPEAKER_FRONT_RIGHT_OF_CENTER 0x80
# define SPEAKER_BACK_CENTER 0x100
# define SPEAKER_SIDE_LEFT 0x200
# define SPEAKER_SIDE_RIGHT 0x400
# define SPEAKER_TOP_CENTER 0x800
# define SPEAKER_TOP_FRONT_LEFT 0x1000
# define SPEAKER_TOP_FRONT_CENTER 0x2000
# define SPEAKER_TOP_FRONT_RIGHT 0x4000
# define SPEAKER_TOP_BACK_LEFT 0x8000
# define SPEAKER_TOP_BACK_CENTER 0x10000
# define SPEAKER_TOP_BACK_RIGHT 0x20000
# define SPEAKER_RESERVED 0x80000000
#endif
#ifndef _WAVEFORMATEXTENSIBLE_
typedef
struct
{
WAVEFORMATEX
Format
;
union
{
WORD
wValidBitsPerSample
;
/* bits of precision */
WORD
wSamplesPerBlock
;
/* valid if wBitsPerSample==0 */
WORD
wReserved
;
/* If neither applies, set to zero. */
}
Samples
;
DWORD
dwChannelMask
;
/* which channels are */
/* present in stream */
GUID
SubFormat
;
}
WAVEFORMATEXTENSIBLE
,
*
PWAVEFORMATEXTENSIBLE
;
#endif
#include <initguid.h>
#ifndef KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
DEFINE_GUID
(
KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
,
WAVE_FORMAT_IEEE_FLOAT
,
0x0000
,
0x0010
,
0x80
,
0x00
,
0x00
,
0xaa
,
0x00
,
0x38
,
0x9b
,
0x71
);
#endif
#ifndef KSDATAFORMAT_SUBTYPE_PCM
DEFINE_GUID
(
KSDATAFORMAT_SUBTYPE_PCM
,
WAVE_FORMAT_PCM
,
0x0000
,
0x0010
,
0x80
,
0x00
,
0x00
,
0xaa
,
0x00
,
0x38
,
0x9b
,
0x71
);
#endif
#ifndef KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF
DEFINE_GUID
(
KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF
,
WAVE_FORMAT_DOLBY_AC3_SPDIF
,
0x0000
,
0x0010
,
0x80
,
0x00
,
0x00
,
0xaa
,
0x00
,
0x38
,
0x9b
,
0x71
);
#endif
/*****************************************************************************
* Local prototypes
*****************************************************************************/
...
...
@@ -52,13 +111,17 @@ static void Close ( vlc_object_t * );
static
void
Play
(
aout_instance_t
*
);
/* local functions */
static
int
OpenWaveOut
(
aout_instance_t
*
p_aout
,
int
i_format
,
int
i_channels
,
int
i_rate
);
static
void
Probe
(
aout_instance_t
*
);
static
int
OpenWaveOut
(
aout_instance_t
*
,
int
,
int
,
int
,
int
,
vlc_bool_t
);
static
int
OpenWaveOutPCM
(
aout_instance_t
*
,
int
*
,
int
,
int
,
int
,
vlc_bool_t
);
static
void
CheckReordering
(
aout_instance_t
*
,
int
);
static
int
PlayWaveOut
(
aout_instance_t
*
,
HWAVEOUT
,
WAVEHDR
*
,
aout_buffer_t
*
);
static
void
CALLBACK
WaveOutCallback
(
HWAVEOUT
h_waveout
,
UINT
uMsg
,
DWORD
_p_aout
,
DWORD
dwParam1
,
DWORD
dwParam2
);
static
void
CALLBACK
WaveOutCallback
(
HWAVEOUT
,
UINT
,
DWORD
,
DWORD
,
DWORD
);
static
void
InterleaveFloat32
(
float
*
,
int
*
,
int
);
static
void
InterleaveS16
(
int16_t
*
,
int
*
,
int
);
/*****************************************************************************
* Module descriptor
...
...
@@ -79,15 +142,31 @@ struct aout_sys_t
{
HWAVEOUT
h_waveout
;
/* handle to waveout instance */
WAVEFORMATEX
waveformat
;
/* audio format */
WAVEFORMATEX
TENSIBLE
waveformat
;
/* audio format */
WAVEHDR
waveheader
[
FRAMES_NUM
];
int
i_buffer_size
;
byte_t
*
p_silence_buffer
;
/* buffer we use to play silence */
vlc_bool_t
b_chan_reorder
;
/* do we need channel reordering */
int
*
pi_chan_table
;
};
static
const
uint32_t
pi_channels_in
[]
=
{
AOUT_CHAN_LEFT
,
AOUT_CHAN_RIGHT
,
AOUT_CHAN_REARLEFT
,
AOUT_CHAN_REARRIGHT
,
AOUT_CHAN_CENTER
,
AOUT_CHAN_LFE
};
static
const
uint32_t
pi_channels_out
[]
=
{
SPEAKER_FRONT_LEFT
,
SPEAKER_FRONT_RIGHT
,
SPEAKER_BACK_LEFT
,
SPEAKER_BACK_RIGHT
,
SPEAKER_FRONT_CENTER
,
SPEAKER_LOW_FREQUENCY
};
static
const
uint32_t
pi_channels_ordered
[]
=
{
SPEAKER_FRONT_LEFT
,
SPEAKER_FRONT_RIGHT
,
SPEAKER_FRONT_CENTER
,
SPEAKER_LOW_FREQUENCY
,
SPEAKER_BACK_LEFT
,
SPEAKER_BACK_RIGHT
};
/*****************************************************************************
* Open: open the audio device
*****************************************************************************
...
...
@@ -96,7 +175,8 @@ struct aout_sys_t
static
int
Open
(
vlc_object_t
*
p_this
)
{
aout_instance_t
*
p_aout
=
(
aout_instance_t
*
)
p_this
;
int
i_nb_channels
,
i
;
vlc_value_t
val
;
int
i
;
/* Allocate structure */
p_aout
->
output
.
p_sys
=
malloc
(
sizeof
(
aout_sys_t
)
);
...
...
@@ -109,38 +189,77 @@ static int Open( vlc_object_t *p_this )
p_aout
->
output
.
pf_play
=
Play
;
aout_VolumeSoftInit
(
p_aout
);
p_aout
->
output
.
p_sys
->
pi_chan_table
=
NULL
;
p_aout
->
b_die
=
VLC_FALSE
;
i_nb_channels
=
aout_FormatNbChannels
(
&
p_aout
->
output
.
output
);
if
(
i_nb_channels
>=
2
)
if
(
var_Type
(
p_aout
,
"audio-device"
)
==
0
)
{
i_nb_channels
=
2
;
p_aout
->
output
.
output
.
i_physical_channels
=
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
;
Probe
(
p_aout
);
}
else
if
(
var_Get
(
p_aout
,
"audio-device"
,
&
val
)
<
0
)
{
i_nb_channels
=
1
;
p_aout
->
output
.
output
.
i_physical_channels
=
AOUT_CHAN_CENTER
;
/* Probe() has failed. */
free
(
p_aout
->
output
.
p_sys
);
return
VLC_EGENERIC
;
}
/* We need to open the device with default values to be sure it is
* available */
p_aout
->
output
.
output
.
i_format
=
VLC_FOURCC
(
'f'
,
'l'
,
'3'
,
'2'
);
if
(
OpenWaveOut
(
p_aout
,
WAVE_FORMAT_IEEE_FLOAT
,
i_nb_channels
,
p_aout
->
output
.
output
.
i_rate
)
)
/* Open the device */
if
(
!
strcmp
(
val
.
psz_string
,
N_
(
"A/52 over S/PDIF"
)
)
)
{
p_aout
->
output
.
output
.
i_format
=
VLC_FOURCC
(
's'
,
'p'
,
'd'
,
'i'
);
free
(
val
.
psz_string
);
if
(
OpenWaveOut
(
p_aout
,
VLC_FOURCC
(
's'
,
'p'
,
'd'
,
'i'
),
p_aout
->
output
.
output
.
i_physical_channels
,
aout_FormatNbChannels
(
&
p_aout
->
output
.
output
),
p_aout
->
output
.
output
.
i_rate
,
VLC_FALSE
)
!=
VLC_SUCCESS
)
{
msg_Err
(
p_aout
,
"cannot open waveout audio device"
);
free
(
p_aout
->
output
.
p_sys
);
return
VLC_EGENERIC
;
}
}
else
{
if
(
!
strcmp
(
val
.
psz_string
,
N_
(
"5.1"
)
)
)
{
p_aout
->
output
.
output
.
i_physical_channels
=
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
|
AOUT_CHAN_CENTER
|
AOUT_CHAN_REARLEFT
|
AOUT_CHAN_REARRIGHT
|
AOUT_CHAN_LFE
;
}
else
if
(
!
strcmp
(
val
.
psz_string
,
N_
(
"2 Front 2 Rear"
)
)
)
{
msg_Warn
(
p_aout
,
"Audio device can't use WAVE_FORMAT_IEEE_FLOAT"
);
p_aout
->
output
.
output
.
i_physical_channels
=
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
|
AOUT_CHAN_REARLEFT
|
AOUT_CHAN_REARRIGHT
;
}
else
if
(
!
strcmp
(
val
.
psz_string
,
"Mono"
)
)
{
p_aout
->
output
.
output
.
i_physical_channels
=
AOUT_CHAN_CENTER
;
}
else
{
p_aout
->
output
.
output
.
i_physical_channels
=
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
;
}
free
(
val
.
psz_string
);
p_aout
->
output
.
output
.
i_format
=
VLC_FOURCC
(
's'
,
'1'
,
'6'
,
'l'
);
if
(
OpenWaveOut
(
p_aout
,
WAVE_FORMAT_PCM
,
i_nb_channels
,
p_aout
->
output
.
output
.
i_rate
)
)
if
(
OpenWaveOutPCM
(
p_aout
,
&
p_aout
->
output
.
output
.
i_format
,
p_aout
->
output
.
output
.
i_physical_channels
,
aout_FormatNbChannels
(
&
p_aout
->
output
.
output
),
p_aout
->
output
.
output
.
i_rate
,
VLC_FALSE
)
!=
VLC_SUCCESS
)
{
msg_Err
(
p_aout
,
"cannot open waveout audio device"
);
free
(
p_aout
->
output
.
p_sys
);
return
VLC_EGENERIC
;
}
}
waveOutReset
(
p_aout
->
output
.
p_sys
->
h_waveout
);
/* Calculate the frame size in bytes */
...
...
@@ -149,22 +268,18 @@ static int Open( vlc_object_t *p_this )
p_aout
->
output
.
p_sys
->
i_buffer_size
=
FRAME_SIZE
*
p_aout
->
output
.
output
.
i_bytes_per_frame
;
/* Allocate silence buffer */
#ifndef UNDER_CE
p_aout
->
output
.
p_sys
->
p_silence_buffer
=
calloc
(
p_aout
->
output
.
p_sys
->
i_buffer_size
,
1
);
#else
p_aout
->
output
.
p_sys
->
p_silence_buffer
=
malloc
(
p_aout
->
output
.
p_sys
->
i_buffer_size
);
#endif
if
(
p_aout
->
output
.
p_sys
->
p_silence_buffer
==
NULL
)
{
free
(
p_aout
->
output
.
p_sys
);
msg_Err
(
p_aout
,
"out of memory"
);
return
1
;
}
#ifdef UNDER_CE
/* Zero the buffer. WinCE doesn't have calloc(). */
memset
(
p_aout
->
output
.
p_sys
->
p_silence_buffer
,
0
,
p_aout
->
output
.
p_sys
->
i_buffer_size
);
#endif
/* We need to kick off the playback in order to have the callback properly
* working */
...
...
@@ -176,6 +291,100 @@ static int Open( vlc_object_t *p_this )
return
0
;
}
/*****************************************************************************
* Probe: probe the audio device for available formats and channels
*****************************************************************************/
static
void
Probe
(
aout_instance_t
*
p_aout
)
{
vlc_value_t
val
;
int
i_format
;
unsigned
int
i_physical_channels
;
var_Create
(
p_aout
,
"audio-device"
,
VLC_VAR_STRING
|
VLC_VAR_HASCHOICE
);
/* Test for SPDIF support */
if
(
AOUT_FMT_NON_LINEAR
(
&
p_aout
->
output
.
output
)
)
{
if
(
OpenWaveOut
(
p_aout
,
VLC_FOURCC
(
's'
,
'p'
,
'd'
,
'i'
),
p_aout
->
output
.
output
.
i_physical_channels
,
aout_FormatNbChannels
(
&
p_aout
->
output
.
output
),
p_aout
->
output
.
output
.
i_rate
,
VLC_TRUE
)
==
VLC_SUCCESS
)
{
msg_Dbg
(
p_aout
,
"device supports A/52 over S/PDIF"
);
val
.
psz_string
=
N_
(
"A/52 over S/PDIF"
);
var_Change
(
p_aout
,
"audio-device"
,
VLC_VAR_ADDCHOICE
,
&
val
);
}
}
/* Test for 5.1 support */
i_physical_channels
=
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
|
AOUT_CHAN_CENTER
|
AOUT_CHAN_REARLEFT
|
AOUT_CHAN_REARRIGHT
|
AOUT_CHAN_LFE
;
if
(
p_aout
->
output
.
output
.
i_physical_channels
==
i_physical_channels
)
{
if
(
OpenWaveOutPCM
(
p_aout
,
&
i_format
,
i_physical_channels
,
6
,
p_aout
->
output
.
output
.
i_rate
,
VLC_TRUE
)
==
VLC_SUCCESS
)
{
val
.
psz_string
=
N_
(
"5.1"
);
var_Change
(
p_aout
,
"audio-device"
,
VLC_VAR_ADDCHOICE
,
&
val
);
}
else
msg_Dbg
(
p_aout
,
"device supports 5.1 channels"
);
}
/* Test for 2 Front 2 Rear support */
i_physical_channels
=
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
|
AOUT_CHAN_REARLEFT
|
AOUT_CHAN_REARRIGHT
;
if
(
p_aout
->
output
.
output
.
i_physical_channels
&
i_physical_channels
)
{
if
(
OpenWaveOutPCM
(
p_aout
,
&
i_format
,
i_physical_channels
,
4
,
p_aout
->
output
.
output
.
i_rate
,
VLC_TRUE
)
==
VLC_SUCCESS
)
{
val
.
psz_string
=
N_
(
"2 Front 2 Rear"
);
var_Change
(
p_aout
,
"audio-device"
,
VLC_VAR_ADDCHOICE
,
&
val
);
}
else
msg_Dbg
(
p_aout
,
"device supports 4 channels"
);
}
/* Test for stereo support */
i_physical_channels
=
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
;
if
(
OpenWaveOutPCM
(
p_aout
,
&
i_format
,
i_physical_channels
,
2
,
p_aout
->
output
.
output
.
i_rate
,
VLC_TRUE
)
==
VLC_SUCCESS
)
{
val
.
psz_string
=
N_
(
"Stereo"
);
var_Change
(
p_aout
,
"audio-device"
,
VLC_VAR_ADDCHOICE
,
&
val
);
var_Set
(
p_aout
,
"audio-device"
,
val
);
}
else
msg_Dbg
(
p_aout
,
"device supports 2 channels"
);
/* Test for mono support */
i_physical_channels
=
AOUT_CHAN_CENTER
;
if
(
OpenWaveOutPCM
(
p_aout
,
&
i_format
,
i_physical_channels
,
1
,
p_aout
->
output
.
output
.
i_rate
,
VLC_TRUE
)
==
VLC_SUCCESS
)
{
val
.
psz_string
=
N_
(
"Mono"
);
var_Change
(
p_aout
,
"audio-device"
,
VLC_VAR_ADDCHOICE
,
&
val
);
}
else
msg_Dbg
(
p_aout
,
"device supports 1 channel"
);
var_AddCallback
(
p_aout
,
"audio-device"
,
aout_ChannelsRestart
,
NULL
);
val
.
b_bool
=
VLC_TRUE
;
var_Set
(
p_aout
,
"intf-change"
,
val
);
}
/*****************************************************************************
* Play: play a sound buffer
*****************************************************************************
...
...
@@ -195,25 +404,36 @@ static void Close( vlc_object_t *p_this )
/* Before calling waveOutClose we must reset the device */
p_aout
->
b_die
=
VLC_TRUE
;
//Hmmm, waveOutReset never seems to return... why ???
//waveOutReset( p_aout->output.p_sys->h_waveout );
/* Wait for the waveout buffers to be freed */
while
(
!
(
p_aout
->
output
.
p_sys
->
waveheader
[
0
].
dwFlags
&
WHDR_DONE
)
||
!
(
p_aout
->
output
.
p_sys
->
waveheader
[
1
].
dwFlags
&
WHDR_DONE
)
)
while
(
VLC_TRUE
)
{
int
i
;
vlc_bool_t
b_not_done
=
VLC_FALSE
;
for
(
i
=
0
;
i
<
FRAMES_NUM
;
i
++
)
{
if
(
!
(
p_aout
->
output
.
p_sys
->
waveheader
[
i
].
dwFlags
&
WHDR_DONE
)
)
b_not_done
=
VLC_TRUE
;
}
if
(
!
b_not_done
)
break
;
msleep
(
1000
);
}
waveOutReset
(
p_aout
->
output
.
p_sys
->
h_waveout
);
/* Close the device */
if
(
waveOutClose
(
p_aout
->
output
.
p_sys
->
h_waveout
)
!=
MMSYSERR_NOERROR
)
{
msg_Err
(
p_aout
,
"waveOutClose failed"
);
}
/* Free silence buffer */
free
(
p_aout
->
output
.
p_sys
->
p_silence_buffer
);
if
(
p_aout
->
output
.
p_sys
->
pi_chan_table
)
free
(
p_aout
->
output
.
p_sys
->
pi_chan_table
);
free
(
p_aout
->
output
.
p_sys
);
}
...
...
@@ -221,52 +441,184 @@ static void Close( vlc_object_t *p_this )
* OpenWaveOut: open the waveout sound device
****************************************************************************/
static
int
OpenWaveOut
(
aout_instance_t
*
p_aout
,
int
i_format
,
int
i_channels
,
int
i_rate
)
int
i_channels
,
int
i_nb_channels
,
int
i_rate
,
vlc_bool_t
b_probe
)
{
MMRESULT
result
;
unsigned
int
i
;
/* Set sound format */
p_aout
->
output
.
p_sys
->
waveformat
.
wFormatTag
=
i_format
;
p_aout
->
output
.
p_sys
->
waveformat
.
nChannels
=
i_channels
;
p_aout
->
output
.
p_sys
->
waveformat
.
nSamplesPerSec
=
i_rate
;
#define waveformat p_aout->output.p_sys->waveformat
waveformat
.
dwChannelMask
=
0
;
for
(
i
=
0
;
i
<
sizeof
(
pi_channels_in
)
/
sizeof
(
uint32_t
);
i
++
)
{
if
(
i_channels
&
pi_channels_in
[
i
]
)
waveformat
.
dwChannelMask
|=
pi_channels_out
[
i
];
}
switch
(
i_format
)
{
case
WAVE_FORMAT_PCM
:
p_aout
->
output
.
p_sys
->
waveformat
.
wBitsPerSample
=
16
;
case
VLC_FOURCC
(
's'
,
'p'
,
'd'
,
'i'
):
i_nb_channels
=
2
;
waveformat
.
Format
.
wBitsPerSample
=
16
;
waveformat
.
Samples
.
wValidBitsPerSample
=
waveformat
.
Format
.
wBitsPerSample
;
waveformat
.
Format
.
wFormatTag
=
WAVE_FORMAT_DOLBY_AC3_SPDIF
;
waveformat
.
SubFormat
=
KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF
;
break
;
case
VLC_FOURCC
(
'f'
,
'l'
,
'3'
,
'2'
):
waveformat
.
Format
.
wBitsPerSample
=
sizeof
(
float
)
*
8
;
waveformat
.
Samples
.
wValidBitsPerSample
=
waveformat
.
Format
.
wBitsPerSample
;
waveformat
.
Format
.
wFormatTag
=
WAVE_FORMAT_IEEE_FLOAT
;
waveformat
.
SubFormat
=
KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
;
break
;
case
WAVE_FORMAT_IEEE_FLOAT
:
p_aout
->
output
.
p_sys
->
waveformat
.
wBitsPerSample
=
sizeof
(
float
)
*
8
;
case
VLC_FOURCC
(
's'
,
'1'
,
'6'
,
'l'
):
waveformat
.
Format
.
wBitsPerSample
=
16
;
waveformat
.
Samples
.
wValidBitsPerSample
=
waveformat
.
Format
.
wBitsPerSample
;
waveformat
.
Format
.
wFormatTag
=
WAVE_FORMAT_PCM
;
waveformat
.
SubFormat
=
KSDATAFORMAT_SUBTYPE_PCM
;
break
;
}
p_aout
->
output
.
p_sys
->
waveformat
.
nBlockAlign
=
p_aout
->
output
.
p_sys
->
waveformat
.
wBitsPerSample
/
8
*
i_channels
;
p_aout
->
output
.
p_sys
->
waveformat
.
nAvgBytesPerSec
=
p_aout
->
output
.
p_sys
->
waveformat
.
nSamplesPerSec
*
p_aout
->
output
.
p_sys
->
waveformat
.
nBlockAlign
;
waveformat
.
Format
.
nChannels
=
i_nb_channels
;
waveformat
.
Format
.
nSamplesPerSec
=
i_rate
;
waveformat
.
Format
.
nBlockAlign
=
waveformat
.
Format
.
wBitsPerSample
/
8
*
i_nb_channels
;
waveformat
.
Format
.
nAvgBytesPerSec
=
waveformat
.
Format
.
nSamplesPerSec
*
waveformat
.
Format
.
nBlockAlign
;
/* Only use the new WAVE_FORMAT_EXTENSIBLE format for multichannel audio */
if
(
i_nb_channels
<=
2
)
{
waveformat
.
Format
.
cbSize
=
0
;
}
else
{
waveformat
.
Format
.
wFormatTag
=
WAVE_FORMAT_EXTENSIBLE
;
waveformat
.
Format
.
cbSize
=
sizeof
(
WAVEFORMATEXTENSIBLE
)
-
sizeof
(
WAVEFORMATEX
);
}
/* Open the device */
result
=
waveOutOpen
(
&
p_aout
->
output
.
p_sys
->
h_waveout
,
WAVE_MAPPER
,
&
p_aout
->
output
.
p_sys
->
waveformat
,
#ifndef UNDER_CE
(
WAVEFORMATEX
*
)
&
waveformat
,
(
DWORD_PTR
)
WaveOutCallback
,
(
DWORD_PTR
)
p_aout
,
#else
(
DWORD
)
WaveOutCallback
,
(
DWORD
)
p_aout
,
#endif
CALLBACK_FUNCTION
);
CALLBACK_FUNCTION
|
(
b_probe
?
WAVE_FORMAT_QUERY
:
0
)
);
if
(
result
==
WAVERR_BADFORMAT
)
{
msg_Warn
(
p_aout
,
"waveOutOpen failed WAVERR_BADFORMAT"
);
return
1
;
return
VLC_EGENERIC
;
}
if
(
result
==
MMSYSERR_ALLOCATED
)
{
msg_Warn
(
p_aout
,
"waveOutOpen failed WAVERR_ALLOCATED"
);
return
VLC_EGENERIC
;
}
if
(
result
!=
MMSYSERR_NOERROR
)
{
msg_Warn
(
p_aout
,
"waveOutOpen failed"
);
return
1
;
return
VLC_EGENERIC
;
}
return
0
;
CheckReordering
(
p_aout
,
i_nb_channels
);
return
VLC_SUCCESS
;
#undef waveformat
}
/*****************************************************************************
* OpenWaveOutPCM: open a PCM waveout sound device
****************************************************************************/
static
int
OpenWaveOutPCM
(
aout_instance_t
*
p_aout
,
int
*
i_format
,
int
i_channels
,
int
i_nb_channels
,
int
i_rate
,
vlc_bool_t
b_probe
)
{
if
(
OpenWaveOut
(
p_aout
,
VLC_FOURCC
(
'f'
,
'l'
,
'3'
,
'2'
),
i_channels
,
i_nb_channels
,
i_rate
,
b_probe
)
!=
VLC_SUCCESS
)
{
if
(
OpenWaveOut
(
p_aout
,
VLC_FOURCC
(
's'
,
'1'
,
'6'
,
'l'
),
i_channels
,
i_nb_channels
,
i_rate
,
b_probe
)
!=
VLC_SUCCESS
)
{
return
VLC_EGENERIC
;
}
else
{
*
i_format
=
VLC_FOURCC
(
's'
,
'1'
,
'6'
,
'l'
);
return
VLC_SUCCESS
;
}
}
else
{
*
i_format
=
VLC_FOURCC
(
'f'
,
'l'
,
'3'
,
'2'
);
return
VLC_SUCCESS
;
}
}
/*****************************************************************************
* CheckReordering: Check if we need to do some channel re-ordering (the ac3
* channel order is different from the one chosen by
* Microsoft).
*****************************************************************************/
static
void
CheckReordering
(
aout_instance_t
*
p_aout
,
int
i_nb_channels
)
{
int
i
,
j
,
k
,
l
;
#define waveformat p_aout->output.p_sys->waveformat
#define pi_chan_table p_aout->output.p_sys->pi_chan_table
p_aout
->
output
.
p_sys
->
b_chan_reorder
=
VLC_FALSE
;
pi_chan_table
=
malloc
(
i_nb_channels
*
sizeof
(
int
)
);
if
(
!
pi_chan_table
)
{
return
;
}
for
(
i
=
0
,
j
=
0
;
i
<
(
int
)(
sizeof
(
pi_channels_out
)
/
sizeof
(
uint32_t
));
i
++
)
{
if
(
waveformat
.
dwChannelMask
&
pi_channels_out
[
i
]
)
{
for
(
k
=
0
,
l
=
0
;
pi_channels_out
[
i
]
!=
pi_channels_ordered
[
k
];
k
++
)
{
if
(
waveformat
.
dwChannelMask
&
pi_channels_ordered
[
k
]
)
{
l
++
;
}
}
pi_chan_table
[
j
]
=
l
;
j
++
;
}
}
for
(
i
=
0
;
i
<
i_nb_channels
;
i
++
)
{
if
(
pi_chan_table
[
i
]
!=
i
)
{
p_aout
->
output
.
p_sys
->
b_chan_reorder
=
VLC_TRUE
;
}
}
if
(
p_aout
->
output
.
p_sys
->
b_chan_reorder
)
{
msg_Dbg
(
p_aout
,
"channel reordering needed"
);
}
#undef pi_chan_table
#undef waveformat
}
/*****************************************************************************
...
...
@@ -284,11 +636,7 @@ static int PlayWaveOut( aout_instance_t *p_aout, HWAVEOUT h_waveout,
/* Use silence buffer instead */
p_waveheader
->
lpData
=
p_aout
->
output
.
p_sys
->
p_silence_buffer
;
#ifndef UNDER_CE
p_waveheader
->
dwUser
=
(
DWORD_PTR
)
p_buffer
;
#else
p_waveheader
->
dwUser
=
(
DWORD
)
p_buffer
;
#endif
p_waveheader
->
dwBufferLength
=
p_aout
->
output
.
p_sys
->
i_buffer_size
;
p_waveheader
->
dwFlags
=
0
;
...
...
@@ -296,7 +644,7 @@ static int PlayWaveOut( aout_instance_t *p_aout, HWAVEOUT h_waveout,
if
(
result
!=
MMSYSERR_NOERROR
)
{
msg_Err
(
p_aout
,
"waveOutPrepareHeader failed"
);
return
1
;
return
VLC_EGENERIC
;
}
/* Send the buffer to the waveOut queue */
...
...
@@ -304,10 +652,10 @@ static int PlayWaveOut( aout_instance_t *p_aout, HWAVEOUT h_waveout,
if
(
result
!=
MMSYSERR_NOERROR
)
{
msg_Err
(
p_aout
,
"waveOutWrite failed"
);
return
1
;
return
VLC_EGENERIC
;
}
return
0
;
return
VLC_SUCCESS
;
}
/*****************************************************************************
...
...
@@ -330,10 +678,59 @@ static void CALLBACK WaveOutCallback( HWAVEOUT h_waveout, UINT uMsg,
if
(
p_aout
->
b_die
)
return
;
/* Take into account
WaveOut
latency ( 1 FRAME ) */
/* Take into account
the
latency ( 1 FRAME ) */
p_buffer
=
aout_OutputNextBuffer
(
p_aout
,
mdate
()
+
1000000
/
p_aout
->
output
.
output
.
i_rate
*
FRAME_SIZE
,
VLC_FALSE
);
/* Do the channel reordering here */
if
(
p_buffer
&&
p_aout
->
output
.
p_sys
->
b_chan_reorder
)
{
if
(
p_aout
->
output
.
output
.
i_format
==
VLC_FOURCC
(
's'
,
'1'
,
'6'
,
'l'
)
)
InterleaveS16
(
(
int16_t
*
)
p_buffer
->
p_buffer
,
p_aout
->
output
.
p_sys
->
pi_chan_table
,
aout_FormatNbChannels
(
&
p_aout
->
output
.
output
)
);
else
InterleaveFloat32
(
(
float
*
)
p_buffer
->
p_buffer
,
p_aout
->
output
.
p_sys
->
pi_chan_table
,
aout_FormatNbChannels
(
&
p_aout
->
output
.
output
)
);
}
PlayWaveOut
(
p_aout
,
h_waveout
,
p_waveheader
,
p_buffer
);
}
static
void
InterleaveFloat32
(
float
*
p_buf
,
int
*
pi_chan_table
,
int
i_nb_channels
)
{
int
i
,
j
;
float
p_tmp
[
10
];
for
(
i
=
0
;
i
<
FRAME_SIZE
;
i
++
)
{
for
(
j
=
0
;
j
<
i_nb_channels
;
j
++
)
{
p_tmp
[
pi_chan_table
[
j
]]
=
p_buf
[
i
*
i_nb_channels
+
j
];
}
memcpy
(
&
p_buf
[
i
*
i_nb_channels
],
p_tmp
,
i_nb_channels
*
sizeof
(
float
)
);
}
}
static
void
InterleaveS16
(
int16_t
*
p_buf
,
int
*
pi_chan_table
,
int
i_nb_channels
)
{
int
i
,
j
;
int16_t
p_tmp
[
10
];
for
(
i
=
0
;
i
<
FRAME_SIZE
;
i
++
)
{
for
(
j
=
0
;
j
<
i_nb_channels
;
j
++
)
{
p_tmp
[
pi_chan_table
[
j
]]
=
p_buf
[
i
*
i_nb_channels
+
j
];
}
memcpy
(
&
p_buf
[
i
*
i_nb_channels
],
p_tmp
,
i_nb_channels
*
sizeof
(
int16_t
)
);
}
}
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