format.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:7k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * format.c : PCM format converter
  3.  *****************************************************************************
  4.  * Copyright (C) 2002 VideoLAN
  5.  * $Id: format.c 8677 2004-09-09 21:45:38Z gbazin $
  6.  *
  7.  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  8.  *          Gildas Bazin <gbazin@videolan.org>
  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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  23.  *****************************************************************************/
  24. /*****************************************************************************
  25.  * Preamble
  26.  *****************************************************************************/
  27. #include <stdlib.h>                                      /* malloc(), free() */
  28. #include <string.h>
  29. #include <vlc/vlc.h>
  30. #include <vlc/decoder.h>
  31. #include "vlc_filter.h"
  32. /*****************************************************************************
  33.  * Local prototypes
  34.  *****************************************************************************/
  35. static int  Open ( vlc_object_t * );
  36. static block_t *Float32toS16( filter_t *, block_t * );
  37. static block_t *Float32toU16( filter_t *, block_t * );
  38. static block_t *S16toFloat32( filter_t *, block_t * );
  39. static block_t *S16Invert   ( filter_t *, block_t * );
  40. /*****************************************************************************
  41.  * Module descriptor
  42.  *****************************************************************************/
  43. vlc_module_begin();
  44.     set_description( _("audio filter for PCM format conversion") );
  45.     set_capability( "audio filter2", 1 );
  46.     set_callbacks( Open, NULL );
  47. vlc_module_end();
  48. /*****************************************************************************
  49.  * Open:
  50.  *****************************************************************************/
  51. static int Open( vlc_object_t *p_this )
  52. {
  53.     filter_t *p_filter = (filter_t *)p_this;
  54.     if( p_filter->fmt_in.i_codec == VLC_FOURCC('f','l','3','2') &&
  55.         p_filter->fmt_out.i_codec == AUDIO_FMT_S16_NE )
  56.     {
  57.         p_filter->pf_audio_filter = Float32toS16;
  58.     }
  59.     else if( p_filter->fmt_in.i_codec == VLC_FOURCC('f','l','3','2') &&
  60.              p_filter->fmt_out.i_codec == AUDIO_FMT_U16_NE )
  61.     {
  62.         p_filter->pf_audio_filter = Float32toU16;
  63.     }
  64.     else if( p_filter->fmt_in.i_codec == AUDIO_FMT_S16_NE &&
  65.              p_filter->fmt_out.i_codec == VLC_FOURCC('f','l','3','2') )
  66.     {
  67.         p_filter->pf_audio_filter = S16toFloat32;
  68.     }
  69.     else if( ( p_filter->fmt_in.i_codec == VLC_FOURCC('s','1','6','l') &&
  70.                p_filter->fmt_out.i_codec == VLC_FOURCC('s','1','6','b') ) ||
  71.              ( p_filter->fmt_in.i_codec == VLC_FOURCC('s','1','6','b') &&
  72.                p_filter->fmt_out.i_codec == VLC_FOURCC('s','1','6','l') ) )
  73.     {
  74.         p_filter->pf_audio_filter = S16Invert;
  75.     }
  76.     else return VLC_EGENERIC;
  77.     
  78.     msg_Dbg( p_this, "%4.4s->%4.4s, bits per sample: %i",
  79.              (char *)&p_filter->fmt_in.i_codec,
  80.              (char *)&p_filter->fmt_out.i_codec,
  81.              p_filter->fmt_in.audio.i_bitspersample );
  82.     return VLC_SUCCESS;
  83. }
  84. /*****************************************************************************
  85.  * Convert a buffer
  86.  *****************************************************************************/
  87. static block_t *Float32toS16( filter_t *p_filter, block_t *p_block )
  88. {
  89.     int i;
  90.     float *p_in = (float *)p_block->p_buffer;
  91.     int16_t *p_out = (int16_t *)p_in;
  92.     for( i = p_block->i_buffer*8/p_filter->fmt_in.audio.i_bitspersample; i--; )
  93.     {
  94. #if 0
  95.         /* Slow version. */
  96.         if ( *p_in >= 1.0 ) *p_out = 32767;
  97.         else if ( *p_in < -1.0 ) *p_out = -32768;
  98.         else *p_out = *p_in * 32768.0;
  99. #else
  100.         /* This is walken's trick based on IEEE float format. */
  101.         union { float f; int32_t i; } u;
  102.         u.f = *p_in + 384.0;
  103.         if ( u.i > 0x43c07fff ) *p_out = 32767;
  104.         else if ( u.i < 0x43bf8000 ) *p_out = -32768;
  105.         else *p_out = u.i - 0x43c00000;
  106. #endif
  107.         p_in++; p_out++;
  108.     }
  109.     p_block->i_buffer /= 2;
  110.     return p_block;
  111. }
  112. static block_t *Float32toU16( filter_t *p_filter, block_t *p_block )
  113. {
  114.     int i;
  115.     float *p_in = (float *)p_block->p_buffer;
  116.     uint16_t *p_out = (uint16_t *)p_in;
  117.     for( i = p_block->i_buffer*8/p_filter->fmt_in.audio.i_bitspersample; i--; )
  118.     {
  119.         if ( *p_in >= 1.0 ) *p_out = 65535;
  120.         else if ( *p_in < -1.0 ) *p_out = 0;
  121.         else *p_out = (uint16_t)(32768 + *p_in * 32768);
  122.         p_in++; p_out++;
  123.     }
  124.     p_block->i_buffer /= 2;
  125.     return p_block;
  126. }
  127. static block_t *S16toFloat32( filter_t *p_filter, block_t *p_block )
  128. {
  129.     block_t *p_block_out;
  130.     int16_t *p_in;
  131.     float *p_out;
  132.     int i;
  133.     p_block_out =
  134.         p_filter->pf_audio_buffer_new( p_filter, p_block->i_buffer*2 );
  135.     if( !p_block_out )
  136.     {
  137.         msg_Warn( p_filter, "can't get output buffer" );
  138.         return NULL;
  139.     }
  140.     p_in = (int16_t *)p_block->p_buffer;
  141.     p_out = (float *)p_block_out->p_buffer;
  142.     for( i = p_block->i_buffer*8/p_filter->fmt_in.audio.i_bitspersample; i--; )
  143.     {
  144. #if 0
  145.         /* Slow version */
  146.         *p_out = (float)*p_in / 32768.0;
  147. #else
  148.         /* This is walken's trick based on IEEE float format. On my PIII
  149.          * this takes 16 seconds to perform one billion conversions, instead
  150.          * of 19 seconds for the above division. */
  151.         union { float f; int32_t i; } u;
  152.         u.i = *p_in + 0x43c00000;
  153.         *p_out = u.f - 384.0;
  154. #endif
  155.         p_in++; p_out++;
  156.     }
  157.     p_block_out->i_samples = p_block->i_samples;
  158.     p_block_out->i_dts = p_block->i_dts;
  159.     p_block_out->i_pts = p_block->i_pts;
  160.     p_block_out->i_length = p_block->i_length;
  161.     p_block_out->i_rate = p_block->i_rate;
  162.     p_block->pf_release( p_block );
  163.     return p_block_out;
  164. }
  165. static block_t *S16Invert( filter_t *p_filter, block_t *p_block )
  166. {
  167.     int i;
  168.     uint8_t *p_in = (uint8_t *)p_block->p_buffer;
  169.     uint8_t tmp;
  170.     for( i = 0; i < p_block->i_buffer / 2; i++ )
  171.     {
  172.         tmp = p_in[0];
  173.         p_in[0] = p_in[1];
  174.         p_in[1] = tmp;
  175.         p_in += 2;
  176.     }
  177.     return p_block;
  178. }