Commit 435dc16d authored by Boris Dorès's avatar Boris Dorès

+ src/input/decoder.c src/libvlc.h:

  - more precise message for the "force-dolby-surround" option
  - don't use -1 as a value in an integer list option (dangerous casts
    in the wxWidgets interface)
+ modules/audio_filter/converter/a52tofloat32.c:
  - option to disable the internal upmixing algorithm
+ modules/audio_filter/channel_mixer/headphone.c:
  - option to partially compensate the delay introduced by the algorithm
  - option to accept raw Dolby Surround encoded streams
parent 4dfaa7dc
...@@ -25,9 +25,13 @@ Services discovery: ...@@ -25,9 +25,13 @@ Services discovery:
* UPnP service discovery * UPnP service discovery
* Bonjour service discovery using avahi (Linux only) * Bonjour service discovery using avahi (Linux only)
Video Filters: Video filters:
* RSS feed overlay * RSS feed overlay
Audio filters:
* Fixes, enhancements and new options related to the Headphone Channel
Mixer and Dolby Surround
Stream output: Stream output:
* New shout output module to forward streams to icecast servers * New shout output module to forward streams to icecast servers
* Fixed several SAP and SDP announcement bugs * Fixed several SAP and SDP announcement bugs
......
...@@ -57,6 +57,18 @@ static void DoWork ( aout_instance_t *, aout_filter_t *, aout_buffer_t *, ...@@ -57,6 +57,18 @@ static void DoWork ( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
#define HEADPHONE_DIM_LONGTEXT N_( \ #define HEADPHONE_DIM_LONGTEXT N_( \
"Distance between front left speaker and listener in meters.") "Distance between front left speaker and listener in meters.")
#define HEADPHONE_COMPENSATE_TEXT N_("Compensate delay")
#define HEADPHONE_COMPENSATE_LONGTEXT N_( \
"The delay which is introduced by the physical algorithm may "\
"sometimes be disturbing for the lipsync. In that case, turn "\
"this on to compensate.")
#define HEADPHONE_DOLBY_TEXT N_("No decoding of Dolby Surround")
#define HEADPHONE_DOLBY_LONGTEXT N_( \
"If this option is turned on (not recommended), Dolby Surround "\
"encoded streams won't be decoded before being processed by this "\
"filter.")
vlc_module_begin(); vlc_module_begin();
set_description( N_("Headphone channel mixer with virtual spatialization effect") ); set_description( N_("Headphone channel mixer with virtual spatialization effect") );
set_shortname( _("Headphone effect") ); set_shortname( _("Headphone effect") );
...@@ -65,6 +77,10 @@ vlc_module_begin(); ...@@ -65,6 +77,10 @@ vlc_module_begin();
add_integer( "headphone-dim", 10, NULL, HEADPHONE_DIM_TEXT, add_integer( "headphone-dim", 10, NULL, HEADPHONE_DIM_TEXT,
HEADPHONE_DIM_LONGTEXT, VLC_FALSE ); HEADPHONE_DIM_LONGTEXT, VLC_FALSE );
add_bool( "headphone-compensate", 0, NULL, HEADPHONE_COMPENSATE_TEXT,
HEADPHONE_COMPENSATE_LONGTEXT, VLC_TRUE );
add_bool( "headphone-dolby", 0, NULL, HEADPHONE_DOLBY_TEXT,
HEADPHONE_DOLBY_LONGTEXT, VLC_TRUE );
set_capability( "audio filter", 0 ); set_capability( "audio filter", 0 );
set_callbacks( Create, Destroy ); set_callbacks( Create, Destroy );
...@@ -112,9 +128,10 @@ struct aout_filter_sys_t ...@@ -112,9 +128,10 @@ struct aout_filter_sys_t
static void ComputeChannelOperations ( struct aout_filter_sys_t * p_data static void ComputeChannelOperations ( struct aout_filter_sys_t * p_data
, unsigned int i_rate , unsigned int i_next_atomic_operation , unsigned int i_rate , unsigned int i_next_atomic_operation
, int i_source_channel_offset , double d_x , double d_z , int i_source_channel_offset , double d_x , double d_z
, double d_channel_amplitude_factor ) , double d_compensation_length , double d_channel_amplitude_factor )
{ {
double d_c = 340; /*sound celerity (unit: m/s)*/ double d_c = 340; /*sound celerity (unit: m/s)*/
double d_compensation_delay = (d_compensation_length-0.1) / d_c * i_rate;
/* Left ear */ /* Left ear */
p_data->p_atomic_operations[i_next_atomic_operation] p_data->p_atomic_operations[i_next_atomic_operation]
...@@ -123,7 +140,7 @@ static void ComputeChannelOperations ( struct aout_filter_sys_t * p_data ...@@ -123,7 +140,7 @@ static void ComputeChannelOperations ( struct aout_filter_sys_t * p_data
.i_dest_channel_offset = 0;/* left */ .i_dest_channel_offset = 0;/* left */
p_data->p_atomic_operations[i_next_atomic_operation] p_data->p_atomic_operations[i_next_atomic_operation]
.i_delay = (int)( sqrt( (-0.1-d_x)*(-0.1-d_x) + (0-d_z)*(0-d_z) ) .i_delay = (int)( sqrt( (-0.1-d_x)*(-0.1-d_x) + (0-d_z)*(0-d_z) )
/ d_c * i_rate ); / d_c * i_rate - d_compensation_delay );
if ( d_x < 0 ) if ( d_x < 0 )
{ {
p_data->p_atomic_operations[i_next_atomic_operation] p_data->p_atomic_operations[i_next_atomic_operation]
...@@ -147,7 +164,7 @@ static void ComputeChannelOperations ( struct aout_filter_sys_t * p_data ...@@ -147,7 +164,7 @@ static void ComputeChannelOperations ( struct aout_filter_sys_t * p_data
.i_dest_channel_offset = 1;/* right */ .i_dest_channel_offset = 1;/* right */
p_data->p_atomic_operations[i_next_atomic_operation + 1] p_data->p_atomic_operations[i_next_atomic_operation + 1]
.i_delay = (int)( sqrt( (0.1-d_x)*(0.1-d_x) + (0-d_z)*(0-d_z) ) .i_delay = (int)( sqrt( (0.1-d_x)*(0.1-d_x) + (0-d_z)*(0-d_z) )
/ d_c * i_rate ); / d_c * i_rate - d_compensation_delay );
if ( d_x < 0 ) if ( d_x < 0 )
{ {
p_data->p_atomic_operations[i_next_atomic_operation + 1] p_data->p_atomic_operations[i_next_atomic_operation + 1]
...@@ -172,6 +189,7 @@ static int Init ( aout_filter_t * p_filter , struct aout_filter_sys_t * p_data ...@@ -172,6 +189,7 @@ static int Init ( aout_filter_t * p_filter , struct aout_filter_sys_t * p_data
double d_x = config_GetInt ( p_filter , "headphone-dim" ); double d_x = config_GetInt ( p_filter , "headphone-dim" );
double d_z = d_x; double d_z = d_x;
double d_z_rear = -d_x/3; double d_z_rear = -d_x/3;
double d_min = 0;
unsigned int i_next_atomic_operation; unsigned int i_next_atomic_operation;
int i_source_channel_offset; int i_source_channel_offset;
unsigned int i; unsigned int i;
...@@ -182,6 +200,19 @@ static int Init ( aout_filter_t * p_filter , struct aout_filter_sys_t * p_data ...@@ -182,6 +200,19 @@ static int Init ( aout_filter_t * p_filter , struct aout_filter_sys_t * p_data
return 0; return 0;
} }
if ( config_GetInt ( p_filter , "headphone-compensate" ) )
{
/* minimal distance to any speaker */
if ( i_physical_channels & AOUT_CHAN_REARCENTER )
{
d_min = d_z_rear;
}
else
{
d_min = d_z;
}
}
/* Number of elementary operations */ /* Number of elementary operations */
p_data->i_nb_atomic_operations = i_nb_channels * 2; p_data->i_nb_atomic_operations = i_nb_channels * 2;
if ( i_physical_channels & AOUT_CHAN_CENTER ) if ( i_physical_channels & AOUT_CHAN_CENTER )
...@@ -204,7 +235,7 @@ static int Init ( aout_filter_t * p_filter , struct aout_filter_sys_t * p_data ...@@ -204,7 +235,7 @@ static int Init ( aout_filter_t * p_filter , struct aout_filter_sys_t * p_data
{ {
ComputeChannelOperations ( p_data , i_rate ComputeChannelOperations ( p_data , i_rate
, i_next_atomic_operation , i_source_channel_offset , i_next_atomic_operation , i_source_channel_offset
, -d_x , d_z , 2.0 / i_nb_channels ); , -d_x , d_z , d_min , 2.0 / i_nb_channels );
i_next_atomic_operation += 2; i_next_atomic_operation += 2;
i_source_channel_offset++; i_source_channel_offset++;
} }
...@@ -212,7 +243,7 @@ static int Init ( aout_filter_t * p_filter , struct aout_filter_sys_t * p_data ...@@ -212,7 +243,7 @@ static int Init ( aout_filter_t * p_filter , struct aout_filter_sys_t * p_data
{ {
ComputeChannelOperations ( p_data , i_rate ComputeChannelOperations ( p_data , i_rate
, i_next_atomic_operation , i_source_channel_offset , i_next_atomic_operation , i_source_channel_offset
, d_x , d_z , 2.0 / i_nb_channels ); , d_x , d_z , d_min , 2.0 / i_nb_channels );
i_next_atomic_operation += 2; i_next_atomic_operation += 2;
i_source_channel_offset++; i_source_channel_offset++;
} }
...@@ -220,7 +251,7 @@ static int Init ( aout_filter_t * p_filter , struct aout_filter_sys_t * p_data ...@@ -220,7 +251,7 @@ static int Init ( aout_filter_t * p_filter , struct aout_filter_sys_t * p_data
{ {
ComputeChannelOperations ( p_data , i_rate ComputeChannelOperations ( p_data , i_rate
, i_next_atomic_operation , i_source_channel_offset , i_next_atomic_operation , i_source_channel_offset
, -d_x , 0 , 1.5 / i_nb_channels ); , -d_x , 0 , d_min , 1.5 / i_nb_channels );
i_next_atomic_operation += 2; i_next_atomic_operation += 2;
i_source_channel_offset++; i_source_channel_offset++;
} }
...@@ -228,7 +259,7 @@ static int Init ( aout_filter_t * p_filter , struct aout_filter_sys_t * p_data ...@@ -228,7 +259,7 @@ static int Init ( aout_filter_t * p_filter , struct aout_filter_sys_t * p_data
{ {
ComputeChannelOperations ( p_data , i_rate ComputeChannelOperations ( p_data , i_rate
, i_next_atomic_operation , i_source_channel_offset , i_next_atomic_operation , i_source_channel_offset
, d_x , 0 , 1.5 / i_nb_channels ); , d_x , 0 , d_min , 1.5 / i_nb_channels );
i_next_atomic_operation += 2; i_next_atomic_operation += 2;
i_source_channel_offset++; i_source_channel_offset++;
} }
...@@ -236,7 +267,7 @@ static int Init ( aout_filter_t * p_filter , struct aout_filter_sys_t * p_data ...@@ -236,7 +267,7 @@ static int Init ( aout_filter_t * p_filter , struct aout_filter_sys_t * p_data
{ {
ComputeChannelOperations ( p_data , i_rate ComputeChannelOperations ( p_data , i_rate
, i_next_atomic_operation , i_source_channel_offset , i_next_atomic_operation , i_source_channel_offset
, -d_x , d_z_rear , 1.5 / i_nb_channels ); , -d_x , d_z_rear , d_min , 1.5 / i_nb_channels );
i_next_atomic_operation += 2; i_next_atomic_operation += 2;
i_source_channel_offset++; i_source_channel_offset++;
} }
...@@ -244,7 +275,7 @@ static int Init ( aout_filter_t * p_filter , struct aout_filter_sys_t * p_data ...@@ -244,7 +275,7 @@ static int Init ( aout_filter_t * p_filter , struct aout_filter_sys_t * p_data
{ {
ComputeChannelOperations ( p_data , i_rate ComputeChannelOperations ( p_data , i_rate
, i_next_atomic_operation , i_source_channel_offset , i_next_atomic_operation , i_source_channel_offset
, d_x , d_z_rear , 1.5 / i_nb_channels ); , d_x , d_z_rear , d_min , 1.5 / i_nb_channels );
i_next_atomic_operation += 2; i_next_atomic_operation += 2;
i_source_channel_offset++; i_source_channel_offset++;
} }
...@@ -252,7 +283,7 @@ static int Init ( aout_filter_t * p_filter , struct aout_filter_sys_t * p_data ...@@ -252,7 +283,7 @@ static int Init ( aout_filter_t * p_filter , struct aout_filter_sys_t * p_data
{ {
ComputeChannelOperations ( p_data , i_rate ComputeChannelOperations ( p_data , i_rate
, i_next_atomic_operation , i_source_channel_offset , i_next_atomic_operation , i_source_channel_offset
, 0 , -d_z , 1.5 / i_nb_channels ); , 0 , -d_z , d_min , 1.5 / i_nb_channels );
i_next_atomic_operation += 2; i_next_atomic_operation += 2;
i_source_channel_offset++; i_source_channel_offset++;
} }
...@@ -261,11 +292,11 @@ static int Init ( aout_filter_t * p_filter , struct aout_filter_sys_t * p_data ...@@ -261,11 +292,11 @@ static int Init ( aout_filter_t * p_filter , struct aout_filter_sys_t * p_data
/* having two center channels increases the spatialization effect */ /* having two center channels increases the spatialization effect */
ComputeChannelOperations ( p_data , i_rate ComputeChannelOperations ( p_data , i_rate
, i_next_atomic_operation , i_source_channel_offset , i_next_atomic_operation , i_source_channel_offset
, d_x / 5.0 , d_z , 0.75 / i_nb_channels ); , d_x / 5.0 , d_z , d_min , 0.75 / i_nb_channels );
i_next_atomic_operation += 2; i_next_atomic_operation += 2;
ComputeChannelOperations ( p_data , i_rate ComputeChannelOperations ( p_data , i_rate
, i_next_atomic_operation , i_source_channel_offset , i_next_atomic_operation , i_source_channel_offset
, -d_x / 5.0 , d_z , 0.75 / i_nb_channels ); , -d_x / 5.0 , d_z , d_min , 0.75 / i_nb_channels );
i_next_atomic_operation += 2; i_next_atomic_operation += 2;
i_source_channel_offset++; i_source_channel_offset++;
} }
...@@ -273,7 +304,7 @@ static int Init ( aout_filter_t * p_filter , struct aout_filter_sys_t * p_data ...@@ -273,7 +304,7 @@ static int Init ( aout_filter_t * p_filter , struct aout_filter_sys_t * p_data
{ {
ComputeChannelOperations ( p_data , i_rate ComputeChannelOperations ( p_data , i_rate
, i_next_atomic_operation , i_source_channel_offset , i_next_atomic_operation , i_source_channel_offset
, 0 , d_z_rear , 5.0 / i_nb_channels ); , 0 , d_z_rear , d_min , 5.0 / i_nb_channels );
i_next_atomic_operation += 2; i_next_atomic_operation += 2;
i_source_channel_offset++; i_source_channel_offset++;
} }
...@@ -337,7 +368,8 @@ static int Create( vlc_object_t *p_this ) ...@@ -337,7 +368,8 @@ static int Create( vlc_object_t *p_this )
p_filter->input.i_rate = p_filter->output.i_rate; p_filter->input.i_rate = p_filter->output.i_rate;
} }
if ( p_filter->input.i_physical_channels == (AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT) if ( p_filter->input.i_physical_channels == (AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT)
&& ( p_filter->input.i_original_channels & AOUT_CHAN_DOLBYSTEREO ) ) && ( p_filter->input.i_original_channels & AOUT_CHAN_DOLBYSTEREO )
&& ! config_GetInt ( p_filter , "headphone-dolby" ) )
{ {
b_fit = VLC_FALSE; b_fit = VLC_FALSE;
p_filter->input.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | p_filter->input.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
......
...@@ -98,6 +98,9 @@ struct filter_sys_t ...@@ -98,6 +98,9 @@ struct filter_sys_t
"environment without disturbing anyone. If you disable the dynamic range "\ "environment without disturbing anyone. If you disable the dynamic range "\
"compression the playback will be more adapted to a movie theater or a " \ "compression the playback will be more adapted to a movie theater or a " \
"listening room.") "listening room.")
#define UPMIX_TEXT N_("Enable internal upmixing")
#define UPMIX_LONGTEXT N_( \
"Enable the internal upmixing algorithm (not recommended).")
vlc_module_begin(); vlc_module_begin();
set_shortname( "A/52" ); set_shortname( "A/52" );
...@@ -105,6 +108,7 @@ vlc_module_begin(); ...@@ -105,6 +108,7 @@ vlc_module_begin();
set_category( CAT_INPUT ); set_category( CAT_INPUT );
set_subcategory( SUBCAT_INPUT_ACODEC ); set_subcategory( SUBCAT_INPUT_ACODEC );
add_bool( "a52-dynrng", 1, NULL, DYNRNG_TEXT, DYNRNG_LONGTEXT, VLC_FALSE ); add_bool( "a52-dynrng", 1, NULL, DYNRNG_TEXT, DYNRNG_LONGTEXT, VLC_FALSE );
add_bool( "a52-upmix", 0, NULL, UPMIX_TEXT, UPMIX_LONGTEXT, VLC_TRUE );
set_capability( "audio filter", 100 ); set_capability( "audio filter", 100 );
set_callbacks( Create, Destroy ); set_callbacks( Create, Destroy );
...@@ -165,6 +169,16 @@ static int Open( vlc_object_t *p_this, filter_sys_t *p_sys, ...@@ -165,6 +169,16 @@ static int Open( vlc_object_t *p_this, filter_sys_t *p_sys,
p_sys->b_dynrng = config_GetInt( p_this, "a52-dynrng" ); p_sys->b_dynrng = config_GetInt( p_this, "a52-dynrng" );
p_sys->b_dontwarn = 0; p_sys->b_dontwarn = 0;
/* No upmixing: it's not necessary and some other filters may want to do
* it themselves. */
if ( aout_FormatNbChannels( &output ) > aout_FormatNbChannels( &input ) )
{
if ( ! config_GetInt( p_this, "a52-upmix" ) )
{
return VLC_EGENERIC;
}
}
/* We'll do our own downmixing, thanks. */ /* We'll do our own downmixing, thanks. */
p_sys->i_nb_channels = aout_FormatNbChannels( &output ); p_sys->i_nb_channels = aout_FormatNbChannels( &output );
switch ( (output.i_physical_channels & AOUT_CHAN_PHYSMASK) switch ( (output.i_physical_channels & AOUT_CHAN_PHYSMASK)
......
...@@ -863,12 +863,12 @@ static aout_buffer_t *aout_new_buffer( decoder_t *p_dec, int i_samples ) ...@@ -863,12 +863,12 @@ static aout_buffer_t *aout_new_buffer( decoder_t *p_dec, int i_samples )
if ( i_force_dolby && (format.i_original_channels&AOUT_CHAN_PHYSMASK) if ( i_force_dolby && (format.i_original_channels&AOUT_CHAN_PHYSMASK)
== (AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT) ) == (AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT) )
{ {
if ( i_force_dolby > 0 ) if ( i_force_dolby == 1 )
{ {
format.i_original_channels = format.i_original_channels | format.i_original_channels = format.i_original_channels |
AOUT_CHAN_DOLBYSTEREO; AOUT_CHAN_DOLBYSTEREO;
} }
else else /* i_force_dolby == 2 */
{ {
format.i_original_channels = format.i_original_channels & format.i_original_channels = format.i_original_channels &
~AOUT_CHAN_DOLBYSTEREO; ~AOUT_CHAN_DOLBYSTEREO;
......
...@@ -161,9 +161,12 @@ static char *ppsz_snap_formats[] = ...@@ -161,9 +161,12 @@ static char *ppsz_snap_formats[] =
#define FORCE_DOLBY_TEXT N_("Force detection of Dolby Surround") #define FORCE_DOLBY_TEXT N_("Force detection of Dolby Surround")
#define FORCE_DOLBY_LONGTEXT N_( \ #define FORCE_DOLBY_LONGTEXT N_( \
"Use this when you know your stream is or is not encoded with Dolby Surround " \ "Use this when you know your stream is (or is not) encoded with Dolby "\
"but fails to be detected as such." ) "Surround but fails to be detected as such. And even if the stream is "\
static int pi_force_dolby_values[] = { 0, 1, -1 }; "not actually encoded with Dolby Surround, turning on this option might "\
"enhance your experience, especially when combined with the Headphone "\
"Channel Mixer." )
static int pi_force_dolby_values[] = { 0, 1, 2 };
static char *ppsz_force_dolby_descriptions[] = { N_("Auto"), N_("On"), N_("Off") }; static char *ppsz_force_dolby_descriptions[] = { N_("Auto"), N_("On"), N_("Off") };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment