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

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * dolby.c : simple decoder for dolby surround encoded streams
  3.  *****************************************************************************
  4.  * Copyright (C) 2005, 2006 the VideoLAN team
  5.  * $Id: 3b54cae2c2105a372943cfe7ce5b3b98f599b306 $
  6.  *
  7.  * Authors: Boris Dorès <babal@via.ecp.fr>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #ifdef HAVE_CONFIG_H
  27. # include "config.h"
  28. #endif
  29. #include <vlc_common.h>
  30. #include <vlc_plugin.h>
  31. #include <vlc_aout.h>
  32. /*****************************************************************************
  33.  * Local prototypes
  34.  *****************************************************************************/
  35. static int  Create    ( vlc_object_t * );
  36. static void Destroy   ( vlc_object_t * );
  37. static void DoWork    ( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
  38.                         aout_buffer_t * );
  39. /*****************************************************************************
  40.  * Module descriptor
  41.  *****************************************************************************/
  42. vlc_module_begin ()
  43.     set_description( N_("Simple decoder for Dolby Surround encoded streams") )
  44.     set_shortname( N_("Dolby Surround decoder") )
  45.     set_category( CAT_INPUT )
  46.     set_subcategory( SUBCAT_INPUT_ACODEC )
  47.     set_capability( "audio filter", 5 )
  48.     set_callbacks( Create, Destroy )
  49. vlc_module_end ()
  50. /*****************************************************************************
  51.  * Internal data structures
  52.  *****************************************************************************/
  53. struct aout_filter_sys_t
  54. {
  55.     int i_left;
  56.     int i_center;
  57.     int i_right;
  58.     int i_rear_left;
  59.     int i_rear_center;
  60.     int i_rear_right;
  61. };
  62. /* our internal channel order (WG-4 order) */
  63. static const uint32_t pi_channels[] =
  64. { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_MIDDLERIGHT,
  65.   AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, AOUT_CHAN_REARCENTER,
  66.   AOUT_CHAN_CENTER, AOUT_CHAN_LFE, 0 };
  67. /*****************************************************************************
  68.  * Create: allocate headphone downmixer
  69.  *****************************************************************************/
  70. static int Create( vlc_object_t *p_this )
  71. {
  72.     int i = 0;
  73.     int i_offset = 0;
  74.     aout_filter_t * p_filter = (aout_filter_t *)p_this;
  75.     /* Validate audio filter format */
  76.     if ( p_filter->input.i_physical_channels != (AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT)
  77.        || ! ( p_filter->input.i_original_channels & AOUT_CHAN_DOLBYSTEREO )
  78.        || aout_FormatNbChannels( &p_filter->output ) <= 2
  79.        || ( p_filter->input.i_original_channels & ~AOUT_CHAN_DOLBYSTEREO )
  80.           != ( p_filter->output.i_original_channels & ~AOUT_CHAN_DOLBYSTEREO ) )
  81.     {
  82.         return VLC_EGENERIC;
  83.     }
  84.     if ( p_filter->input.i_rate != p_filter->output.i_rate )
  85.     {
  86.         return VLC_EGENERIC;
  87.     }
  88.     if ( p_filter->input.i_format != VLC_FOURCC('f','l','3','2')
  89.           || p_filter->output.i_format != VLC_FOURCC('f','l','3','2') )
  90.     {
  91.         return VLC_EGENERIC;
  92.     }
  93.     /* Allocate the memory needed to store the module's structure */
  94.     p_filter->p_sys = malloc( sizeof(struct aout_filter_sys_t) );
  95.     if ( p_filter->p_sys == NULL )
  96.         return VLC_ENOMEM;
  97.     p_filter->p_sys->i_left = -1;
  98.     p_filter->p_sys->i_center = -1;
  99.     p_filter->p_sys->i_right = -1;
  100.     p_filter->p_sys->i_rear_left = -1;
  101.     p_filter->p_sys->i_rear_center = -1;
  102.     p_filter->p_sys->i_rear_right = -1;
  103.     while ( pi_channels[i] )
  104.     {
  105.         if ( p_filter->output.i_physical_channels & pi_channels[i] )
  106.         {
  107.             switch ( pi_channels[i] )
  108.             {
  109.                 case AOUT_CHAN_LEFT:
  110.                     p_filter->p_sys->i_left = i_offset;
  111.                     break;
  112.                 case AOUT_CHAN_CENTER:
  113.                     p_filter->p_sys->i_center = i_offset;
  114.                     break;
  115.                 case AOUT_CHAN_RIGHT:
  116.                     p_filter->p_sys->i_right = i_offset;
  117.                     break;
  118.                 case AOUT_CHAN_REARLEFT:
  119.                     p_filter->p_sys->i_rear_left = i_offset;
  120.                     break;
  121.                 case AOUT_CHAN_REARCENTER:
  122.                     p_filter->p_sys->i_rear_center = i_offset;
  123.                     break;
  124.                 case AOUT_CHAN_REARRIGHT:
  125.                     p_filter->p_sys->i_rear_right = i_offset;
  126.                     break;
  127.             }
  128.             ++i_offset;
  129.         }
  130.         ++i;
  131.     }
  132.     p_filter->pf_do_work = DoWork;
  133.     p_filter->b_in_place = 0;
  134.     return VLC_SUCCESS;
  135. }
  136. /*****************************************************************************
  137.  * Destroy: deallocate resources associated with headphone downmixer
  138.  *****************************************************************************/
  139. static void Destroy( vlc_object_t *p_this )
  140. {
  141.     aout_filter_t * p_filter = (aout_filter_t *)p_this;
  142.     if ( p_filter->p_sys != NULL )
  143.     {
  144.         free ( p_filter->p_sys );
  145.         p_filter->p_sys = NULL;
  146.     }
  147. }
  148. /*****************************************************************************
  149.  * DoWork: convert a buffer
  150.  *****************************************************************************/
  151. static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
  152.                     aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
  153. {
  154.     VLC_UNUSED(p_aout);
  155.     float * p_in = (float*) p_in_buf->p_buffer;
  156.     float * p_out = (float*) p_out_buf->p_buffer;
  157.     size_t i_nb_samples = p_in_buf->i_nb_samples;
  158.     size_t i_nb_channels = aout_FormatNbChannels( &p_filter->output );
  159.     p_out_buf->i_nb_samples = i_nb_samples;
  160.     p_out_buf->i_nb_bytes = sizeof(float) * i_nb_samples
  161.                             * aout_FormatNbChannels( &p_filter->output );
  162.     memset ( p_out , 0 , p_out_buf->i_nb_bytes );
  163.     if ( p_filter->p_sys != NULL )
  164.     {
  165.         struct aout_filter_sys_t * p_sys = p_filter->p_sys;
  166.         size_t i_nb_rear = 0;
  167.         size_t i;
  168.         if ( p_sys->i_rear_left >= 0 )
  169.         {
  170.             ++i_nb_rear;
  171.         }
  172.         if ( p_sys->i_rear_center >= 0 )
  173.         {
  174.             ++i_nb_rear;
  175.         }
  176.         if ( p_sys->i_rear_right >= 0 )
  177.         {
  178.             ++i_nb_rear;
  179.         }
  180.         for ( i = 0; i < i_nb_samples; ++i )
  181.         {
  182.             float f_left = p_in[ i * 2 ];
  183.             float f_right = p_in[ i * 2 + 1 ];
  184.             float f_rear = ( f_left - f_right ) / i_nb_rear;
  185.             if ( p_sys->i_center >= 0 )
  186.             {
  187.                 float f_center = f_left + f_right;
  188.                 f_left -= f_center / 2;
  189.                 f_right -= f_center / 2;
  190.                 p_out[ i * i_nb_channels + p_sys->i_center ] = f_center;
  191.             }
  192.             if ( p_sys->i_left >= 0 )
  193.             {
  194.                 p_out[ i * i_nb_channels + p_sys->i_left ] = f_left;
  195.             }
  196.             if ( p_sys->i_right >= 0 )
  197.             {
  198.                 p_out[ i * i_nb_channels + p_sys->i_right ] = f_right;
  199.             }
  200.             if ( p_sys->i_rear_left >= 0 )
  201.             {
  202.                 p_out[ i * i_nb_channels + p_sys->i_rear_left ] = f_rear;
  203.             }
  204.             if ( p_sys->i_rear_center >= 0 )
  205.             {
  206.                 p_out[ i * i_nb_channels + p_sys->i_rear_center ] = f_rear;
  207.             }
  208.             if ( p_sys->i_rear_right >= 0 )
  209.             {
  210.                 p_out[ i * i_nb_channels + p_sys->i_rear_right ] = f_rear;
  211.             }
  212.         }
  213.     }
  214. }