* headphone.c : headphone virtual spatialization channel mixer module
* -> gives the feeling of a real room with a simple headphone
*****************************************************************************
- * Copyright (C) 2002 the VideoLAN team
+ * Copyright (C) 2002-2005 the VideoLAN team
* $Id$
*
* Authors: Boris Dorès <babal@via.ecp.fr>
*****************************************************************************/
#define MODULE_DESCRIPTION N_ ( \
"This effect gives you the feeling that you are standing in a room " \
- "with a complete 5.1 speaker set when using only a headphone, " \
+ "with a complete 7.1 speaker set when using only a headphone, " \
"providing a more realistic sound experience. It should also be " \
"more comfortable and less tiring when listening to music for " \
"long periods of time.\nIt works with any source format from mono " \
- "to 5.1.")
+ "to 7.1.")
#define HEADPHONE_DIM_TEXT N_("Characteristic dimension")
#define HEADPHONE_DIM_LONGTEXT N_( \
/* Number of elementary operations */
p_data->i_nb_atomic_operations = i_nb_channels * 2;
+ if ( i_physical_channels & AOUT_CHAN_CENTER )
+ {
+ p_data->i_nb_atomic_operations += 2;
+ }
p_data->p_atomic_operations = malloc ( sizeof(struct atomic_operation_t)
* p_data->i_nb_atomic_operations );
if ( p_data->p_atomic_operations == NULL )
i_next_atomic_operation += 2;
i_source_channel_offset++;
}
- if ( i_physical_channels & AOUT_CHAN_REARLEFT )
+ if ( i_physical_channels & AOUT_CHAN_MIDDLELEFT )
{
ComputeChannelOperations ( p_data , i_rate
, i_next_atomic_operation , i_source_channel_offset
- , -d_x , d_z_rear , 1.5 / i_nb_channels );
+ , -d_x , 0 , 1.5 / i_nb_channels );
i_next_atomic_operation += 2;
i_source_channel_offset++;
}
- if ( i_physical_channels & AOUT_CHAN_REARRIGHT )
+ if ( i_physical_channels & AOUT_CHAN_MIDDLERIGHT )
{
ComputeChannelOperations ( p_data , i_rate
, i_next_atomic_operation , i_source_channel_offset
- , d_x , d_z_rear , 1.5 / i_nb_channels );
+ , d_x , 0 , 1.5 / i_nb_channels );
i_next_atomic_operation += 2;
i_source_channel_offset++;
}
- if ( i_physical_channels & AOUT_CHAN_REARCENTER )
+ if ( i_physical_channels & AOUT_CHAN_REARLEFT )
{
ComputeChannelOperations ( p_data , i_rate
, i_next_atomic_operation , i_source_channel_offset
- , 0 , -d_z , 1.5 / i_nb_channels );
+ , -d_x , d_z_rear , 1.5 / i_nb_channels );
i_next_atomic_operation += 2;
i_source_channel_offset++;
}
- if ( i_physical_channels & AOUT_CHAN_CENTER )
+ if ( i_physical_channels & AOUT_CHAN_REARRIGHT )
{
ComputeChannelOperations ( p_data , i_rate
, i_next_atomic_operation , i_source_channel_offset
- , 0 , d_z , 1.5 / i_nb_channels );
+ , d_x , d_z_rear , 1.5 / i_nb_channels );
i_next_atomic_operation += 2;
i_source_channel_offset++;
}
- if ( i_physical_channels & AOUT_CHAN_LFE )
+ if ( i_physical_channels & AOUT_CHAN_REARCENTER )
{
ComputeChannelOperations ( p_data , i_rate
, i_next_atomic_operation , i_source_channel_offset
- , 0 , d_z_rear , 5.0 / i_nb_channels );
+ , 0 , -d_z , 1.5 / i_nb_channels );
i_next_atomic_operation += 2;
i_source_channel_offset++;
}
- if ( i_physical_channels & AOUT_CHAN_MIDDLELEFT )
+ if ( i_physical_channels & AOUT_CHAN_CENTER )
{
+ /* having two center channels increases the spatialization effect */
ComputeChannelOperations ( p_data , i_rate
, i_next_atomic_operation , i_source_channel_offset
- , -d_x , 0 , 1.5 / i_nb_channels );
+ , d_x / 5.0 , d_z , 0.75 / i_nb_channels );
+ i_next_atomic_operation += 2;
+ ComputeChannelOperations ( p_data , i_rate
+ , i_next_atomic_operation , i_source_channel_offset
+ , -d_x / 5.0 , d_z , 0.75 / i_nb_channels );
i_next_atomic_operation += 2;
i_source_channel_offset++;
}
- if ( i_physical_channels & AOUT_CHAN_MIDDLERIGHT )
+ if ( i_physical_channels & AOUT_CHAN_LFE )
{
ComputeChannelOperations ( p_data , i_rate
, i_next_atomic_operation , i_source_channel_offset
- , d_x , 0 , 1.5 / i_nb_channels );
+ , 0 , d_z_rear , 5.0 / i_nb_channels );
i_next_atomic_operation += 2;
i_source_channel_offset++;
}
static int Create( vlc_object_t *p_this )
{
aout_filter_t * p_filter = (aout_filter_t *)p_this;
+ vlc_bool_t b_fit = VLC_TRUE;
+
+ /* Activate this filter only with stereo devices */
+ if ( p_filter->output.i_physical_channels != (AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT)
+ || p_filter->output.i_physical_channels
+ != ( p_filter->output.i_original_channels & AOUT_CHAN_PHYSMASK )
+ || p_filter->input.i_physical_channels
+ != ( p_filter->input.i_original_channels & AOUT_CHAN_PHYSMASK ) )
+ {
+ msg_Dbg( p_filter, "Filter discarded (incompatible format)" );
+ return VLC_EGENERIC;
+ }
- if ( p_filter->output.i_physical_channels != ( AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT )
- || p_filter->input.i_format != p_filter->output.i_format
- || p_filter->input.i_rate != p_filter->output.i_rate
- || (p_filter->input.i_format != VLC_FOURCC('f','l','3','2')
- && p_filter->input.i_format != VLC_FOURCC('f','i','3','2')) )
+ /* Request a specific format if not already compatible */
+ if ( p_filter->input.i_format != VLC_FOURCC('f','l','3','2')
+ || p_filter->output.i_format != VLC_FOURCC('f','l','3','2') )
{
- msg_Dbg( p_filter, "Filter discarded (invalid format)" );
- return -1;
+ b_fit = VLC_FALSE;
+ p_filter->input.i_format = VLC_FOURCC('f','l','3','2');
+ p_filter->output.i_format = VLC_FOURCC('f','l','3','2');
+ }
+ if ( p_filter->input.i_rate != p_filter->output.i_rate )
+ {
+ b_fit = VLC_FALSE;
+ p_filter->input.i_rate = p_filter->output.i_rate;
+ }
+ if ( p_filter->input.i_physical_channels == (AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT)
+ && ( p_filter->input.i_original_channels & AOUT_CHAN_DOLBYSTEREO ) )
+ {
+ b_fit = VLC_FALSE;
+ p_filter->input.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
+ AOUT_CHAN_CENTER |
+ AOUT_CHAN_REARLEFT |
+ AOUT_CHAN_REARRIGHT;
+ p_filter->input.i_original_channels = p_filter->input.i_physical_channels;
+ }
+ if ( ! b_fit )
+ {
+ msg_Dbg( p_filter, "Requesting specific format" );
+ return VLC_EGENERIC;
}
/* Allocate the memory needed to store the module's structure */
p_filter->p_sys = malloc( sizeof(struct aout_filter_sys_t) );
if ( p_filter->p_sys == NULL )
{
- msg_Err( p_filter, "out of memory" );
- return -1;
+ msg_Err( p_filter, "Out of memory" );
+ return VLC_EGENERIC;
}
p_filter->p_sys->i_overflow_buffer_size = 0;
p_filter->p_sys->p_overflow_buffer = NULL;
, p_filter->input.i_physical_channels
, p_filter->input.i_rate ) < 0 )
{
- return -1;
+ return VLC_EGENERIC;
}
p_filter->pf_do_work = DoWork;
p_filter->b_in_place = 0;
- return 0;
+ return VLC_SUCCESS;
}
/*****************************************************************************