headphone.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:25k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * headphone.c : headphone virtual spatialization channel mixer module
  3.  *               -> gives the feeling of a real room with a simple headphone
  4.  *****************************************************************************
  5.  * Copyright (C) 2002-2006 the VideoLAN team
  6.  * $Id: 42d1bcdb474e5e053ac78b9742f111418397074f $
  7.  *
  8.  * Authors: Boris Dorès <babal@via.ecp.fr>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  23.  *****************************************************************************/
  24. /*****************************************************************************
  25.  * Preamble
  26.  *****************************************************************************/
  27. #ifdef HAVE_CONFIG_H
  28. # include "config.h"
  29. #endif
  30. #include <math.h>                                        /* sqrt */
  31. #include <vlc_common.h>
  32. #include <vlc_plugin.h>
  33. #include <vlc_aout.h>
  34. #include <vlc_filter.h>
  35. #include <vlc_block.h>
  36. /*****************************************************************************
  37.  * Local prototypes
  38.  *****************************************************************************/
  39. static int  Create    ( vlc_object_t * );
  40. static void Destroy   ( vlc_object_t * );
  41. static void DoWork    ( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
  42.                         aout_buffer_t * );
  43. /* Audio filter2 */
  44. static int  OpenFilter ( vlc_object_t * );
  45. static void CloseFilter( vlc_object_t * );
  46. static block_t *Convert( filter_t *, block_t * );
  47. /*****************************************************************************
  48.  * Module descriptor
  49.  *****************************************************************************/
  50. #define MODULE_DESCRIPTION N_ ( 
  51.      "This effect gives you the feeling that you are standing in a room " 
  52.      "with a complete 7.1 speaker set when using only a headphone, " 
  53.      "providing a more realistic sound experience. It should also be " 
  54.      "more comfortable and less tiring when listening to music for " 
  55.      "long periods of time.nIt works with any source format from mono " 
  56.      "to 7.1.")
  57. #define HEADPHONE_DIM_TEXT N_("Characteristic dimension")
  58. #define HEADPHONE_DIM_LONGTEXT N_( 
  59.      "Distance between front left speaker and listener in meters.")
  60. #define HEADPHONE_COMPENSATE_TEXT N_("Compensate delay")
  61. #define HEADPHONE_COMPENSATE_LONGTEXT N_( 
  62.      "The delay which is introduced by the physical algorithm may "
  63.      "sometimes be disturbing for the synchronization between lips-movement "
  64.      "and speech. In case, turn this on to compensate.")
  65. #define HEADPHONE_DOLBY_TEXT N_("No decoding of Dolby Surround")
  66. #define HEADPHONE_DOLBY_LONGTEXT N_( 
  67.      "Dolby Surround encoded streams won't be decoded before being " 
  68.      "processed by this filter. Enabling this setting is not recommended.")
  69. vlc_module_begin ()
  70.     set_description( N_("Headphone virtual spatialization effect") )
  71.     set_shortname( N_("Headphone effect") )
  72.     set_help( MODULE_DESCRIPTION )
  73.     set_category( CAT_AUDIO )
  74.     set_subcategory( SUBCAT_AUDIO_AFILTER )
  75.     add_integer( "headphone-dim", 10, NULL, HEADPHONE_DIM_TEXT,
  76.                  HEADPHONE_DIM_LONGTEXT, false )
  77.     add_bool( "headphone-compensate", 0, NULL, HEADPHONE_COMPENSATE_TEXT,
  78.               HEADPHONE_COMPENSATE_LONGTEXT, true )
  79.     add_bool( "headphone-dolby", 0, NULL, HEADPHONE_DOLBY_TEXT,
  80.               HEADPHONE_DOLBY_LONGTEXT, true )
  81.     set_capability( "audio filter", 0 )
  82.     set_callbacks( Create, Destroy )
  83.     add_shortcut( "headphone" )
  84.     /* Audio filter 2 */
  85.     add_submodule ()
  86.     set_description( N_("Headphone virtual spatialization effect") )
  87.     set_capability( "audio filter2", 0 )
  88.     set_callbacks( OpenFilter, CloseFilter )
  89.     add_shortcut( "headphone" )
  90. vlc_module_end ()
  91. /*****************************************************************************
  92.  * Internal data structures
  93.  *****************************************************************************/
  94. struct atomic_operation_t
  95. {
  96.     int i_source_channel_offset;
  97.     int i_dest_channel_offset;
  98.     unsigned int i_delay;/* in sample unit */
  99.     double d_amplitude_factor;
  100. };
  101. struct aout_filter_sys_t
  102. {
  103.     size_t i_overflow_buffer_size;/* in bytes */
  104.     uint8_t * p_overflow_buffer;
  105.     unsigned int i_nb_atomic_operations;
  106.     struct atomic_operation_t * p_atomic_operations;
  107. };
  108. struct filter_sys_t
  109. {
  110.     size_t i_overflow_buffer_size;/* in bytes */
  111.     uint8_t * p_overflow_buffer;
  112.     unsigned int i_nb_atomic_operations;
  113.     struct atomic_operation_t * p_atomic_operations;
  114. };
  115. /*****************************************************************************
  116.  * Init: initialize internal data structures
  117.  * and computes the needed atomic operations
  118.  *****************************************************************************/
  119. /* x and z represent the coordinates of the virtual speaker
  120.  *  relatively to the center of the listener's head, measured in meters :
  121.  *
  122.  *  left              right
  123.  *Z
  124.  *-
  125.  *a          head
  126.  *x
  127.  *i
  128.  *s
  129.  *  rear left    rear right
  130.  *
  131.  *          x-axis
  132.  *  */
  133. static void ComputeChannelOperations( struct aout_filter_sys_t * p_data
  134.         , unsigned int i_rate, unsigned int i_next_atomic_operation
  135.         , int i_source_channel_offset, double d_x, double d_z
  136.         , double d_compensation_length, double d_channel_amplitude_factor )
  137. {
  138.     double d_c = 340; /*sound celerity (unit: m/s)*/
  139.     double d_compensation_delay = (d_compensation_length-0.1) / d_c * i_rate;
  140.     /* Left ear */
  141.     p_data->p_atomic_operations[i_next_atomic_operation]
  142.         .i_source_channel_offset = i_source_channel_offset;
  143.     p_data->p_atomic_operations[i_next_atomic_operation]
  144.         .i_dest_channel_offset = 0;/* left */
  145.     p_data->p_atomic_operations[i_next_atomic_operation]
  146.         .i_delay = (int)( sqrt( (-0.1-d_x)*(-0.1-d_x) + (0-d_z)*(0-d_z) )
  147.                           / d_c * i_rate - d_compensation_delay );
  148.     if( d_x < 0 )
  149.     {
  150.         p_data->p_atomic_operations[i_next_atomic_operation]
  151.             .d_amplitude_factor = d_channel_amplitude_factor * 1.1 / 2;
  152.     }
  153.     else if( d_x > 0 )
  154.     {
  155.         p_data->p_atomic_operations[i_next_atomic_operation]
  156.             .d_amplitude_factor = d_channel_amplitude_factor * 0.9 / 2;
  157.     }
  158.     else
  159.     {
  160.         p_data->p_atomic_operations[i_next_atomic_operation]
  161.             .d_amplitude_factor = d_channel_amplitude_factor / 2;
  162.     }
  163.     /* Right ear */
  164.     p_data->p_atomic_operations[i_next_atomic_operation + 1]
  165.         .i_source_channel_offset = i_source_channel_offset;
  166.     p_data->p_atomic_operations[i_next_atomic_operation + 1]
  167.         .i_dest_channel_offset = 1;/* right */
  168.     p_data->p_atomic_operations[i_next_atomic_operation + 1]
  169.         .i_delay = (int)( sqrt( (0.1-d_x)*(0.1-d_x) + (0-d_z)*(0-d_z) )
  170.                           / d_c * i_rate - d_compensation_delay );
  171.     if( d_x < 0 )
  172.     {
  173.         p_data->p_atomic_operations[i_next_atomic_operation + 1]
  174.             .d_amplitude_factor = d_channel_amplitude_factor * 0.9 / 2;
  175.     }
  176.     else if( d_x > 0 )
  177.     {
  178.         p_data->p_atomic_operations[i_next_atomic_operation + 1]
  179.             .d_amplitude_factor = d_channel_amplitude_factor * 1.1 / 2;
  180.     }
  181.     else
  182.     {
  183.         p_data->p_atomic_operations[i_next_atomic_operation + 1]
  184.             .d_amplitude_factor = d_channel_amplitude_factor / 2;
  185.     }
  186. }
  187. static int Init( vlc_object_t *p_this, struct aout_filter_sys_t * p_data
  188.         , unsigned int i_nb_channels, uint32_t i_physical_channels
  189.         , unsigned int i_rate )
  190. {
  191.     double d_x = config_GetInt( p_this, "headphone-dim" );
  192.     double d_z = d_x;
  193.     double d_z_rear = -d_x/3;
  194.     double d_min = 0;
  195.     unsigned int i_next_atomic_operation;
  196.     int i_source_channel_offset;
  197.     unsigned int i;
  198.     if( config_GetInt( p_this, "headphone-compensate" ) )
  199.     {
  200.         /* minimal distance to any speaker */
  201.         if( i_physical_channels & AOUT_CHAN_REARCENTER )
  202.         {
  203.             d_min = d_z_rear;
  204.         }
  205.         else
  206.         {
  207.             d_min = d_z;
  208.         }
  209.     }
  210.     /* Number of elementary operations */
  211.     p_data->i_nb_atomic_operations = i_nb_channels * 2;
  212.     if( i_physical_channels & AOUT_CHAN_CENTER )
  213.     {
  214.         p_data->i_nb_atomic_operations += 2;
  215.     }
  216.     p_data->p_atomic_operations = malloc( sizeof(struct atomic_operation_t)
  217.             * p_data->i_nb_atomic_operations );
  218.     if( p_data->p_atomic_operations == NULL )
  219.         return -1;
  220.     /* For each virtual speaker, computes elementary wave propagation time
  221.      * to each ear */
  222.     i_next_atomic_operation = 0;
  223.     i_source_channel_offset = 0;
  224.     if( i_physical_channels & AOUT_CHAN_LEFT )
  225.     {
  226.         ComputeChannelOperations( p_data , i_rate
  227.                 , i_next_atomic_operation , i_source_channel_offset
  228.                 , -d_x , d_z , d_min , 2.0 / i_nb_channels );
  229.         i_next_atomic_operation += 2;
  230.         i_source_channel_offset++;
  231.     }
  232.     if( i_physical_channels & AOUT_CHAN_RIGHT )
  233.     {
  234.         ComputeChannelOperations( p_data , i_rate
  235.                 , i_next_atomic_operation , i_source_channel_offset
  236.                 , d_x , d_z , d_min , 2.0 / i_nb_channels );
  237.         i_next_atomic_operation += 2;
  238.         i_source_channel_offset++;
  239.     }
  240.     if( i_physical_channels & AOUT_CHAN_MIDDLELEFT )
  241.     {
  242.         ComputeChannelOperations( p_data , i_rate
  243.                 , i_next_atomic_operation , i_source_channel_offset
  244.                 , -d_x , 0 , d_min , 1.5 / i_nb_channels );
  245.         i_next_atomic_operation += 2;
  246.         i_source_channel_offset++;
  247.     }
  248.     if( i_physical_channels & AOUT_CHAN_MIDDLERIGHT )
  249.     {
  250.         ComputeChannelOperations( p_data , i_rate
  251.                 , i_next_atomic_operation , i_source_channel_offset
  252.                 , d_x , 0 , d_min , 1.5 / i_nb_channels );
  253.         i_next_atomic_operation += 2;
  254.         i_source_channel_offset++;
  255.     }
  256.     if( i_physical_channels & AOUT_CHAN_REARLEFT )
  257.     {
  258.         ComputeChannelOperations( p_data , i_rate
  259.                 , i_next_atomic_operation , i_source_channel_offset
  260.                 , -d_x , d_z_rear , d_min , 1.5 / i_nb_channels );
  261.         i_next_atomic_operation += 2;
  262.         i_source_channel_offset++;
  263.     }
  264.     if( i_physical_channels & AOUT_CHAN_REARRIGHT )
  265.     {
  266.         ComputeChannelOperations( p_data , i_rate
  267.                 , i_next_atomic_operation , i_source_channel_offset
  268.                 , d_x , d_z_rear , d_min , 1.5 / i_nb_channels );
  269.         i_next_atomic_operation += 2;
  270.         i_source_channel_offset++;
  271.     }
  272.     if( i_physical_channels & AOUT_CHAN_REARCENTER )
  273.     {
  274.         ComputeChannelOperations( p_data , i_rate
  275.                 , i_next_atomic_operation , i_source_channel_offset
  276.                 , 0 , -d_z , d_min , 1.5 / i_nb_channels );
  277.         i_next_atomic_operation += 2;
  278.         i_source_channel_offset++;
  279.     }
  280.     if( i_physical_channels & AOUT_CHAN_CENTER )
  281.     {
  282.         /* having two center channels increases the spatialization effect */
  283.         ComputeChannelOperations( p_data , i_rate
  284.                 , i_next_atomic_operation , i_source_channel_offset
  285.                 , d_x / 5.0 , d_z , d_min , 0.75 / i_nb_channels );
  286.         i_next_atomic_operation += 2;
  287.         ComputeChannelOperations( p_data , i_rate
  288.                 , i_next_atomic_operation , i_source_channel_offset
  289.                 , -d_x / 5.0 , d_z , d_min , 0.75 / i_nb_channels );
  290.         i_next_atomic_operation += 2;
  291.         i_source_channel_offset++;
  292.     }
  293.     if( i_physical_channels & AOUT_CHAN_LFE )
  294.     {
  295.         ComputeChannelOperations( p_data , i_rate
  296.                 , i_next_atomic_operation , i_source_channel_offset
  297.                 , 0 , d_z_rear , d_min , 5.0 / i_nb_channels );
  298.         i_next_atomic_operation += 2;
  299.         i_source_channel_offset++;
  300.     }
  301.     /* Initialize the overflow buffer
  302.      * we need it because the process induce a delay in the samples */
  303.     p_data->i_overflow_buffer_size = 0;
  304.     for( i = 0 ; i < p_data->i_nb_atomic_operations ; i++ )
  305.     {
  306.         if( p_data->i_overflow_buffer_size
  307.                 < p_data->p_atomic_operations[i].i_delay * 2 * sizeof (float) )
  308.         {
  309.             p_data->i_overflow_buffer_size
  310.                 = p_data->p_atomic_operations[i].i_delay * 2 * sizeof (float);
  311.         }
  312.     }
  313.     p_data->p_overflow_buffer = malloc( p_data->i_overflow_buffer_size );
  314.     if( p_data->p_overflow_buffer == NULL )
  315.     {
  316.         free( p_data->p_atomic_operations );
  317.         return -1;
  318.     }
  319.     memset( p_data->p_overflow_buffer, 0 , p_data->i_overflow_buffer_size );
  320.     return 0;
  321. }
  322. /*****************************************************************************
  323.  * Create: allocate headphone downmixer
  324.  *****************************************************************************/
  325. static int Create( vlc_object_t *p_this )
  326. {
  327.     aout_filter_t * p_filter = (aout_filter_t *)p_this;
  328.     bool b_fit = true;
  329.     /* Activate this filter only with stereo devices */
  330.     if( p_filter->output.i_physical_channels
  331.             != (AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT) )
  332.     {
  333.         msg_Dbg( p_filter, "filter discarded (incompatible format)" );
  334.         return VLC_EGENERIC;
  335.     }
  336.     /* Request a specific format if not already compatible */
  337.     if( p_filter->input.i_original_channels
  338.             != p_filter->output.i_original_channels )
  339.     {
  340.         b_fit = false;
  341.         p_filter->input.i_original_channels =
  342.                                         p_filter->output.i_original_channels;
  343.     }
  344.     if( p_filter->input.i_format != VLC_FOURCC('f','l','3','2')
  345.           || p_filter->output.i_format != VLC_FOURCC('f','l','3','2') )
  346.     {
  347.         b_fit = false;
  348.         p_filter->input.i_format = VLC_FOURCC('f','l','3','2');
  349.         p_filter->output.i_format = VLC_FOURCC('f','l','3','2');
  350.     }
  351.     if( p_filter->input.i_rate != p_filter->output.i_rate )
  352.     {
  353.         b_fit = false;
  354.         p_filter->input.i_rate = p_filter->output.i_rate;
  355.     }
  356.     if( p_filter->input.i_physical_channels == (AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT)
  357.           && ( p_filter->input.i_original_channels & AOUT_CHAN_DOLBYSTEREO )
  358.           && ! config_GetInt ( p_filter , "headphone-dolby" ) )
  359.     {
  360.         b_fit = false;
  361.         p_filter->input.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
  362.                                               AOUT_CHAN_CENTER |
  363.                                               AOUT_CHAN_REARLEFT |
  364.                                               AOUT_CHAN_REARRIGHT;
  365.     }
  366.     if( !b_fit )
  367.     {
  368.         msg_Dbg( p_filter, "requesting specific format" );
  369.         return VLC_EGENERIC;
  370.     }
  371.     /* Allocate the memory needed to store the module's structure */
  372.     p_filter->p_sys = malloc( sizeof(struct aout_filter_sys_t) );
  373.     if( p_filter->p_sys == NULL )
  374.         return VLC_ENOMEM;
  375.     p_filter->p_sys->i_overflow_buffer_size = 0;
  376.     p_filter->p_sys->p_overflow_buffer = NULL;
  377.     p_filter->p_sys->i_nb_atomic_operations = 0;
  378.     p_filter->p_sys->p_atomic_operations = NULL;
  379.     if( Init( VLC_OBJECT(p_filter), p_filter->p_sys
  380.                 , aout_FormatNbChannels ( &p_filter->input )
  381.                 , p_filter->input.i_physical_channels
  382.                 , p_filter->input.i_rate ) < 0 )
  383.     {
  384.         free( p_filter->p_sys );
  385.         return VLC_EGENERIC;
  386.     }
  387.     p_filter->pf_do_work = DoWork;
  388.     p_filter->b_in_place = 0;
  389.     return VLC_SUCCESS;
  390. }
  391. /*****************************************************************************
  392.  * Destroy: deallocate resources associated with headphone downmixer
  393.  *****************************************************************************/
  394. static void Destroy( vlc_object_t *p_this )
  395. {
  396.     aout_filter_t * p_filter = (aout_filter_t *)p_this;
  397.     if( p_filter->p_sys != NULL )
  398.     {
  399.         free( p_filter->p_sys->p_overflow_buffer );
  400.         free( p_filter->p_sys->p_atomic_operations );
  401.         free( p_filter->p_sys );
  402.         p_filter->p_sys = NULL;
  403.     }
  404. }
  405. /*****************************************************************************
  406.  * DoWork: convert a buffer
  407.  *****************************************************************************/
  408. static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
  409.                     aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
  410. {
  411.     VLC_UNUSED(p_aout);
  412.     int i_input_nb = aout_FormatNbChannels( &p_filter->input );
  413.     int i_output_nb = aout_FormatNbChannels( &p_filter->output );
  414.     float * p_in = (float*) p_in_buf->p_buffer;
  415.     uint8_t * p_out;
  416.     uint8_t * p_overflow;
  417.     uint8_t * p_slide;
  418.     size_t i_overflow_size;     /* in bytes */
  419.     size_t i_out_size;          /* in bytes */
  420.     unsigned int i, j;
  421.     int i_source_channel_offset;
  422.     int i_dest_channel_offset;
  423.     unsigned int i_delay;
  424.     double d_amplitude_factor;
  425.     /* out buffer characterisitcs */
  426.     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
  427.     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes * i_output_nb / i_input_nb;
  428.     p_out = p_out_buf->p_buffer;
  429.     i_out_size = p_out_buf->i_nb_bytes;
  430.     if( p_filter->p_sys != NULL )
  431.     {
  432.         /* Slide the overflow buffer */
  433.         p_overflow = p_filter->p_sys->p_overflow_buffer;
  434.         i_overflow_size = p_filter->p_sys->i_overflow_buffer_size;
  435.         memset( p_out, 0, i_out_size );
  436.         if ( i_out_size > i_overflow_size )
  437.             memcpy( p_out, p_overflow, i_overflow_size );
  438.         else
  439.             memcpy( p_out, p_overflow, i_out_size );
  440.         p_slide = p_filter->p_sys->p_overflow_buffer;
  441.         while( p_slide < p_overflow + i_overflow_size )
  442.         {
  443.             if( p_slide + i_out_size < p_overflow + i_overflow_size )
  444.             {
  445.                 memset( p_slide, 0, i_out_size );
  446.                 if( p_slide + 2 * i_out_size < p_overflow + i_overflow_size )
  447.                     memcpy( p_slide, p_slide + i_out_size, i_out_size );
  448.                 else
  449.                     memcpy( p_slide, p_slide + i_out_size,
  450.                             p_overflow + i_overflow_size - ( p_slide + i_out_size ) );
  451.             }
  452.             else
  453.             {
  454.                 memset( p_slide, 0, p_overflow + i_overflow_size - p_slide );
  455.             }
  456.             p_slide += i_out_size;
  457.         }
  458.         /* apply the atomic operations */
  459.         for( i = 0; i < p_filter->p_sys->i_nb_atomic_operations; i++ )
  460.         {
  461.             /* shorter variable names */
  462.             i_source_channel_offset
  463.                 = p_filter->p_sys->p_atomic_operations[i].i_source_channel_offset;
  464.             i_dest_channel_offset
  465.                 = p_filter->p_sys->p_atomic_operations[i].i_dest_channel_offset;
  466.             i_delay = p_filter->p_sys->p_atomic_operations[i].i_delay;
  467.             d_amplitude_factor
  468.                 = p_filter->p_sys->p_atomic_operations[i].d_amplitude_factor;
  469.             if( p_out_buf->i_nb_samples > i_delay )
  470.             {
  471.                 /* current buffer coefficients */
  472.                 for( j = 0; j < p_out_buf->i_nb_samples - i_delay; j++ )
  473.                 {
  474.                     ((float*)p_out)[ (i_delay+j)*i_output_nb + i_dest_channel_offset ]
  475.                         += p_in[ j * i_input_nb + i_source_channel_offset ]
  476.                            * d_amplitude_factor;
  477.                 }
  478.                 /* overflow buffer coefficients */
  479.                 for( j = 0; j < i_delay; j++ )
  480.                 {
  481.                     ((float*)p_overflow)[ j*i_output_nb + i_dest_channel_offset ]
  482.                         += p_in[ (p_out_buf->i_nb_samples - i_delay + j)
  483.                            * i_input_nb + i_source_channel_offset ]
  484.                            * d_amplitude_factor;
  485.                 }
  486.             }
  487.             else
  488.             {
  489.                 /* overflow buffer coefficients only */
  490.                 for( j = 0; j < p_out_buf->i_nb_samples; j++ )
  491.                 {
  492.                     ((float*)p_overflow)[ (i_delay - p_out_buf->i_nb_samples + j)
  493.                         * i_output_nb + i_dest_channel_offset ]
  494.                         += p_in[ j * i_input_nb + i_source_channel_offset ]
  495.                            * d_amplitude_factor;
  496.                 }
  497.             }
  498.         }
  499.     }
  500.     else
  501.     {
  502.         memset( p_out, 0, i_out_size );
  503.     }
  504. }
  505. /*
  506.  * Audio filter 2
  507.  */
  508. /*****************************************************************************
  509.  * OpenFilter:
  510.  *****************************************************************************/
  511. static int OpenFilter( vlc_object_t *p_this )
  512. {
  513.     filter_t *p_filter = (filter_t *)p_this;
  514.     bool b_fit = true;
  515.     /* Activate this filter only with stereo devices */
  516.     if( p_filter->fmt_out.audio.i_physical_channels
  517.             != (AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT) )
  518.     {
  519.         msg_Dbg( p_filter, "filter discarded (incompatible format)" );
  520.         return VLC_EGENERIC;
  521.     }
  522.     /* Request a specific format if not already compatible */
  523.     if( p_filter->fmt_in.audio.i_original_channels
  524.             != p_filter->fmt_out.audio.i_original_channels )
  525.     {
  526.         b_fit = false;
  527.         p_filter->fmt_in.audio.i_original_channels =
  528.                                         p_filter->fmt_out.audio.i_original_channels;
  529.     }
  530.     if( p_filter->fmt_in.audio.i_format != VLC_FOURCC('f','l','3','2')
  531.           || p_filter->fmt_out.audio.i_format != VLC_FOURCC('f','l','3','2') )
  532.     {
  533.         b_fit = false;
  534.         p_filter->fmt_in.audio.i_format = VLC_FOURCC('f','l','3','2');
  535.         p_filter->fmt_out.audio.i_format = VLC_FOURCC('f','l','3','2');
  536.     }
  537.     if( p_filter->fmt_in.audio.i_rate != p_filter->fmt_out.audio.i_rate )
  538.     {
  539.         b_fit = false;
  540.         p_filter->fmt_in.audio.i_rate = p_filter->fmt_out.audio.i_rate;
  541.     }
  542.     if( p_filter->fmt_in.audio.i_physical_channels == (AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT)
  543.           && ( p_filter->fmt_in.audio.i_original_channels & AOUT_CHAN_DOLBYSTEREO )
  544.           && !config_GetInt( p_filter, "headphone-dolby" ) )
  545.     {
  546.         b_fit = false;
  547.         p_filter->fmt_in.audio.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
  548.                                               AOUT_CHAN_CENTER |
  549.                                               AOUT_CHAN_REARLEFT |
  550.                                               AOUT_CHAN_REARRIGHT;
  551.     }
  552.     if( !b_fit )
  553.     {
  554.         msg_Dbg( p_filter, "requesting specific format" );
  555.         return VLC_EGENERIC;
  556.     }
  557.     /* Allocate the memory needed to store the module's structure */
  558.     p_filter->p_sys = malloc( sizeof(struct filter_sys_t) );
  559.     if( p_filter->p_sys == NULL )
  560.         return VLC_ENOMEM;
  561.     p_filter->p_sys->i_overflow_buffer_size = 0;
  562.     p_filter->p_sys->p_overflow_buffer = NULL;
  563.     p_filter->p_sys->i_nb_atomic_operations = 0;
  564.     p_filter->p_sys->p_atomic_operations = NULL;
  565.     if( Init( VLC_OBJECT(p_filter), (struct aout_filter_sys_t *)p_filter->p_sys
  566.                 , aout_FormatNbChannels ( &(p_filter->fmt_in.audio) )
  567.                 , p_filter->fmt_in.audio.i_physical_channels
  568.                 , p_filter->fmt_in.audio.i_rate ) < 0 )
  569.     {
  570.         free( p_filter->p_sys );
  571.         return VLC_EGENERIC;
  572.     }
  573.     p_filter->pf_audio_filter = Convert;
  574.     p_filter->fmt_out.audio.i_rate = p_filter->fmt_in.audio.i_rate;
  575.     return VLC_SUCCESS;
  576. }
  577. /*****************************************************************************
  578.  * CloseFilter : deallocate data structures
  579.  *****************************************************************************/
  580. static void CloseFilter( vlc_object_t *p_this )
  581. {
  582.     filter_t *p_filter = (filter_t *)p_this;
  583.     if( p_filter->p_sys != NULL )
  584.     {
  585.         free( p_filter->p_sys->p_overflow_buffer );
  586.         free( p_filter->p_sys->p_atomic_operations );
  587.         free( p_filter->p_sys );
  588.         p_filter->p_sys = NULL;
  589.     }
  590. }
  591. static block_t *Convert( filter_t *p_filter, block_t *p_block )
  592. {
  593.     aout_filter_t aout_filter;
  594.     aout_buffer_t in_buf, out_buf;
  595.     block_t *p_out;
  596.     int i_out_size;
  597.     if( !p_block || !p_block->i_samples )
  598.     {
  599.         if( p_block )
  600.             block_Release( p_block );
  601.         return NULL;
  602.     }
  603.     i_out_size = p_block->i_samples *
  604.       p_filter->fmt_out.audio.i_bitspersample/8 *
  605.         aout_FormatNbChannels( &(p_filter->fmt_out.audio) );
  606.     p_out = p_filter->pf_audio_buffer_new( p_filter, i_out_size );
  607.     if( !p_out )
  608.     {
  609.         msg_Warn( p_filter, "can't get output buffer" );
  610.         block_Release( p_block );
  611.         return NULL;
  612.     }
  613.     p_out->i_samples = p_block->i_samples;
  614.     p_out->i_dts = p_block->i_dts;
  615.     p_out->i_pts = p_block->i_pts;
  616.     p_out->i_length = p_block->i_length;
  617.     aout_filter.p_sys = (struct aout_filter_sys_t *)p_filter->p_sys;
  618.     aout_filter.input = p_filter->fmt_in.audio;
  619.     aout_filter.input.i_format = p_filter->fmt_in.i_codec;
  620.     aout_filter.output = p_filter->fmt_out.audio;
  621.     aout_filter.output.i_format = p_filter->fmt_out.i_codec;
  622.     aout_filter.b_in_place = 0;
  623.     in_buf.p_buffer = p_block->p_buffer;
  624.     in_buf.i_nb_bytes = p_block->i_buffer;
  625.     in_buf.i_nb_samples = p_block->i_samples;
  626.     out_buf.p_buffer = p_out->p_buffer;
  627.     out_buf.i_nb_bytes = p_out->i_buffer;
  628.     out_buf.i_nb_samples = p_out->i_samples;
  629.     DoWork( (aout_instance_t *)p_filter, &aout_filter, &in_buf, &out_buf );
  630.     p_out->i_buffer = out_buf.i_nb_bytes;
  631.     p_out->i_samples = out_buf.i_nb_samples;
  632.     block_Release( p_block );
  633.     return p_out;
  634. }