Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc
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
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 @@
...
@@ -2,7 +2,7 @@
* waveout.c : Windows waveOut plugin for vlc
* waveout.c : Windows waveOut plugin for vlc
*****************************************************************************
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* 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>
* Authors: Gildas Bazin <gbazin@netcourrier.com>
*
*
...
@@ -40,10 +40,69 @@
...
@@ -40,10 +40,69 @@
/*****************************************************************************
/*****************************************************************************
* Useful macros
* Useful macros
*****************************************************************************/
*****************************************************************************/
#ifdef UNDER_CE
# define DWORD_PTR DWORD
#endif
#ifndef WAVE_FORMAT_IEEE_FLOAT
#ifndef WAVE_FORMAT_IEEE_FLOAT
# define WAVE_FORMAT_IEEE_FLOAT 0x0003
# define WAVE_FORMAT_IEEE_FLOAT 0x0003
#endif
#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
* Local prototypes
*****************************************************************************/
*****************************************************************************/
...
@@ -52,13 +111,17 @@ static void Close ( vlc_object_t * );
...
@@ -52,13 +111,17 @@ static void Close ( vlc_object_t * );
static
void
Play
(
aout_instance_t
*
);
static
void
Play
(
aout_instance_t
*
);
/* local functions */
/* local functions */
static
int
OpenWaveOut
(
aout_instance_t
*
p_aout
,
int
i_format
,
static
void
Probe
(
aout_instance_t
*
);
int
i_channels
,
int
i_rate
);
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
*
,
static
int
PlayWaveOut
(
aout_instance_t
*
,
HWAVEOUT
,
WAVEHDR
*
,
aout_buffer_t
*
);
aout_buffer_t
*
);
static
void
CALLBACK
WaveOutCallback
(
HWAVEOUT
h_waveout
,
UINT
uMsg
,
DWORD
_p_aout
,
static
void
CALLBACK
WaveOutCallback
(
HWAVEOUT
,
UINT
,
DWORD
,
DWORD
,
DWORD
);
DWORD
dwParam1
,
DWORD
dwParam2
);
static
void
InterleaveFloat32
(
float
*
,
int
*
,
int
);
static
void
InterleaveS16
(
int16_t
*
,
int
*
,
int
);
/*****************************************************************************
/*****************************************************************************
* Module descriptor
* Module descriptor
...
@@ -79,15 +142,31 @@ struct aout_sys_t
...
@@ -79,15 +142,31 @@ struct aout_sys_t
{
{
HWAVEOUT
h_waveout
;
/* handle to waveout instance */
HWAVEOUT
h_waveout
;
/* handle to waveout instance */
WAVEFORMATEX
waveformat
;
/* audio format */
WAVEFORMATEX
TENSIBLE
waveformat
;
/* audio format */
WAVEHDR
waveheader
[
FRAMES_NUM
];
WAVEHDR
waveheader
[
FRAMES_NUM
];
int
i_buffer_size
;
int
i_buffer_size
;
byte_t
*
p_silence_buffer
;
/* buffer we use to play silence */
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
* Open: open the audio device
*****************************************************************************
*****************************************************************************
...
@@ -96,7 +175,8 @@ struct aout_sys_t
...
@@ -96,7 +175,8 @@ struct aout_sys_t
static
int
Open
(
vlc_object_t
*
p_this
)
static
int
Open
(
vlc_object_t
*
p_this
)
{
{
aout_instance_t
*
p_aout
=
(
aout_instance_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 */
/* Allocate structure */
p_aout
->
output
.
p_sys
=
malloc
(
sizeof
(
aout_sys_t
)
);
p_aout
->
output
.
p_sys
=
malloc
(
sizeof
(
aout_sys_t
)
);
...
@@ -109,38 +189,77 @@ static int Open( vlc_object_t *p_this )
...
@@ -109,38 +189,77 @@ static int Open( vlc_object_t *p_this )
p_aout
->
output
.
pf_play
=
Play
;
p_aout
->
output
.
pf_play
=
Play
;
aout_VolumeSoftInit
(
p_aout
);
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
(
var_Type
(
p_aout
,
"audio-device"
)
==
0
)
if
(
i_nb_channels
>=
2
)
{
{
i_nb_channels
=
2
;
Probe
(
p_aout
);
p_aout
->
output
.
output
.
i_physical_channels
=
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
;
}
}
else
if
(
var_Get
(
p_aout
,
"audio-device"
,
&
val
)
<
0
)
{
{
i_nb_channels
=
1
;
/* Probe() has failed. */
p_aout
->
output
.
output
.
i_physical_channels
=
free
(
p_aout
->
output
.
p_sys
);
AOUT_CHAN_CENTER
;
return
VLC_EGENERIC
;
}
}
/* We need to open the device with default values to be sure it is
/* Open the device */
* available */
if
(
!
strcmp
(
val
.
psz_string
,
N_
(
"A/52 over S/PDIF"
)
)
)
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_format
=
VLC_FOURCC
(
's'
,
'p'
,
'd'
,
'i'
);
p_aout
->
output
.
output
.
i_rate
)
)
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
(
OpenWaveOutPCM
(
p_aout
,
&
p_aout
->
output
.
output
.
i_format
,
if
(
OpenWaveOut
(
p_aout
,
WAVE_FORMAT_PCM
,
i_nb_channels
,
p_aout
->
output
.
output
.
i_physical_channels
,
p_aout
->
output
.
output
.
i_rate
)
)
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"
);
msg_Err
(
p_aout
,
"cannot open waveout audio device"
);
free
(
p_aout
->
output
.
p_sys
);
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
}
}
waveOutReset
(
p_aout
->
output
.
p_sys
->
h_waveout
);
waveOutReset
(
p_aout
->
output
.
p_sys
->
h_waveout
);
/* Calculate the frame size in bytes */
/* Calculate the frame size in bytes */
...
@@ -149,22 +268,18 @@ static int Open( vlc_object_t *p_this )
...
@@ -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
.
p_sys
->
i_buffer_size
=
FRAME_SIZE
*
p_aout
->
output
.
output
.
i_bytes_per_frame
;
p_aout
->
output
.
output
.
i_bytes_per_frame
;
/* Allocate silence buffer */
/* 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
=
p_aout
->
output
.
p_sys
->
p_silence_buffer
=
malloc
(
p_aout
->
output
.
p_sys
->
i_buffer_size
);
malloc
(
p_aout
->
output
.
p_sys
->
i_buffer_size
);
#endif
if
(
p_aout
->
output
.
p_sys
->
p_silence_buffer
==
NULL
)
if
(
p_aout
->
output
.
p_sys
->
p_silence_buffer
==
NULL
)
{
{
free
(
p_aout
->
output
.
p_sys
);
msg_Err
(
p_aout
,
"out of memory"
);
msg_Err
(
p_aout
,
"out of memory"
);
return
1
;
return
1
;
}
}
#ifdef UNDER_CE
/* Zero the buffer. WinCE doesn't have calloc(). */
memset
(
p_aout
->
output
.
p_sys
->
p_silence_buffer
,
0
,
memset
(
p_aout
->
output
.
p_sys
->
p_silence_buffer
,
0
,
p_aout
->
output
.
p_sys
->
i_buffer_size
);
p_aout
->
output
.
p_sys
->
i_buffer_size
);
#endif
/* We need to kick off the playback in order to have the callback properly
/* We need to kick off the playback in order to have the callback properly
* working */
* working */
...
@@ -176,6 +291,100 @@ static int Open( vlc_object_t *p_this )
...
@@ -176,6 +291,100 @@ static int Open( vlc_object_t *p_this )
return
0
;
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
* Play: play a sound buffer
*****************************************************************************
*****************************************************************************
...
@@ -195,25 +404,36 @@ static void Close( vlc_object_t *p_this )
...
@@ -195,25 +404,36 @@ static void Close( vlc_object_t *p_this )
/* Before calling waveOutClose we must reset the device */
/* Before calling waveOutClose we must reset the device */
p_aout
->
b_die
=
VLC_TRUE
;
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 */
/* Wait for the waveout buffers to be freed */
while
(
!
(
p_aout
->
output
.
p_sys
->
waveheader
[
0
].
dwFlags
&
WHDR_DONE
)
||
while
(
VLC_TRUE
)
!
(
p_aout
->
output
.
p_sys
->
waveheader
[
1
].
dwFlags
&
WHDR_DONE
)
)
{
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
);
msleep
(
1000
);
}
}
waveOutReset
(
p_aout
->
output
.
p_sys
->
h_waveout
);
/* Close the device */
/* Close the device */
if
(
waveOutClose
(
p_aout
->
output
.
p_sys
->
h_waveout
)
!=
MMSYSERR_NOERROR
)
if
(
waveOutClose
(
p_aout
->
output
.
p_sys
->
h_waveout
)
!=
MMSYSERR_NOERROR
)
{
{
msg_Err
(
p_aout
,
"waveOutClose failed"
);
msg_Err
(
p_aout
,
"waveOutClose failed"
);
}
}
/* Free silence buffer */
free
(
p_aout
->
output
.
p_sys
->
p_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
);
free
(
p_aout
->
output
.
p_sys
);
}
}
...
@@ -221,52 +441,184 @@ static void Close( vlc_object_t *p_this )
...
@@ -221,52 +441,184 @@ static void Close( vlc_object_t *p_this )
* OpenWaveOut: open the waveout sound device
* OpenWaveOut: open the waveout sound device
****************************************************************************/
****************************************************************************/
static
int
OpenWaveOut
(
aout_instance_t
*
p_aout
,
int
i_format
,
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
;
MMRESULT
result
;
unsigned
int
i
;
/* Set sound format */
/* Set sound format */
p_aout
->
output
.
p_sys
->
waveformat
.
wFormatTag
=
i_format
;
p_aout
->
output
.
p_sys
->
waveformat
.
nChannels
=
i_channels
;
#define waveformat p_aout->output.p_sys->waveformat
p_aout
->
output
.
p_sys
->
waveformat
.
nSamplesPerSec
=
i_rate
;
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
)
switch
(
i_format
)
{
{
case
WAVE_FORMAT_PCM
:
case
VLC_FOURCC
(
's'
,
'p'
,
'd'
,
'i'
):
p_aout
->
output
.
p_sys
->
waveformat
.
wBitsPerSample
=
16
;
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
;
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
;
break
;
}
}
p_aout
->
output
.
p_sys
->
waveformat
.
nBlockAlign
=
waveformat
.
Format
.
nChannels
=
i_nb_channels
;
p_aout
->
output
.
p_sys
->
waveformat
.
wBitsPerSample
/
8
*
i_channels
;
waveformat
.
Format
.
nSamplesPerSec
=
i_rate
;
p_aout
->
output
.
p_sys
->
waveformat
.
nAvgBytesPerSec
=
waveformat
.
Format
.
nBlockAlign
=
p_aout
->
output
.
p_sys
->
waveformat
.
nSamplesPerSec
*
waveformat
.
Format
.
wBitsPerSample
/
8
*
i_nb_channels
;
p_aout
->
output
.
p_sys
->
waveformat
.
nBlockAlign
;
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 */
/* Open the device */
result
=
waveOutOpen
(
&
p_aout
->
output
.
p_sys
->
h_waveout
,
WAVE_MAPPER
,
result
=
waveOutOpen
(
&
p_aout
->
output
.
p_sys
->
h_waveout
,
WAVE_MAPPER
,
&
p_aout
->
output
.
p_sys
->
waveformat
,
(
WAVEFORMATEX
*
)
&
waveformat
,
#ifndef UNDER_CE
(
DWORD_PTR
)
WaveOutCallback
,
(
DWORD_PTR
)
p_aout
,
(
DWORD_PTR
)
WaveOutCallback
,
(
DWORD_PTR
)
p_aout
,
#else
CALLBACK_FUNCTION
|
(
b_probe
?
WAVE_FORMAT_QUERY
:
0
)
);
(
DWORD
)
WaveOutCallback
,
(
DWORD
)
p_aout
,
#endif
CALLBACK_FUNCTION
);
if
(
result
==
WAVERR_BADFORMAT
)
if
(
result
==
WAVERR_BADFORMAT
)
{
{
msg_Warn
(
p_aout
,
"waveOutOpen failed 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
)
if
(
result
!=
MMSYSERR_NOERROR
)
{
{
msg_Warn
(
p_aout
,
"waveOutOpen failed"
);
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,
...
@@ -284,11 +636,7 @@ static int PlayWaveOut( aout_instance_t *p_aout, HWAVEOUT h_waveout,
/* Use silence buffer instead */
/* Use silence buffer instead */
p_waveheader
->
lpData
=
p_aout
->
output
.
p_sys
->
p_silence_buffer
;
p_waveheader
->
lpData
=
p_aout
->
output
.
p_sys
->
p_silence_buffer
;
#ifndef UNDER_CE
p_waveheader
->
dwUser
=
(
DWORD_PTR
)
p_buffer
;
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
->
dwBufferLength
=
p_aout
->
output
.
p_sys
->
i_buffer_size
;
p_waveheader
->
dwFlags
=
0
;
p_waveheader
->
dwFlags
=
0
;
...
@@ -296,7 +644,7 @@ static int PlayWaveOut( aout_instance_t *p_aout, HWAVEOUT h_waveout,
...
@@ -296,7 +644,7 @@ static int PlayWaveOut( aout_instance_t *p_aout, HWAVEOUT h_waveout,
if
(
result
!=
MMSYSERR_NOERROR
)
if
(
result
!=
MMSYSERR_NOERROR
)
{
{
msg_Err
(
p_aout
,
"waveOutPrepareHeader failed"
);
msg_Err
(
p_aout
,
"waveOutPrepareHeader failed"
);
return
1
;
return
VLC_EGENERIC
;
}
}
/* Send the buffer to the waveOut queue */
/* Send the buffer to the waveOut queue */
...
@@ -304,10 +652,10 @@ static int PlayWaveOut( aout_instance_t *p_aout, HWAVEOUT h_waveout,
...
@@ -304,10 +652,10 @@ static int PlayWaveOut( aout_instance_t *p_aout, HWAVEOUT h_waveout,
if
(
result
!=
MMSYSERR_NOERROR
)
if
(
result
!=
MMSYSERR_NOERROR
)
{
{
msg_Err
(
p_aout
,
"waveOutWrite failed"
);
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,
...
@@ -330,10 +678,59 @@ static void CALLBACK WaveOutCallback( HWAVEOUT h_waveout, UINT uMsg,
if
(
p_aout
->
b_die
)
return
;
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
,
p_buffer
=
aout_OutputNextBuffer
(
p_aout
,
mdate
()
+
1000000
/
p_aout
->
output
.
output
.
i_rate
*
FRAME_SIZE
,
mdate
()
+
1000000
/
p_aout
->
output
.
output
.
i_rate
*
FRAME_SIZE
,
VLC_FALSE
);
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
);
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