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

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * coreaudio.c resampler based on CoreAudio's AudioConverter
  3.  *****************************************************************************
  4.  * Copyright (C) 2003 VideoLAN
  5.  * $Id: coreaudio.c 6961 2004-03-05 17:34:23Z sam $
  6.  *
  7.  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  8.  *          Jon Lech Johansen <jon-vl@nanocrew.net>
  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 <AudioToolbox/AudioConverter.h>
  30. #include <vlc/vlc.h>
  31. #include "audio_output.h"
  32. #include "aout_internal.h"
  33. /*****************************************************************************
  34.  * Local prototypes
  35.  *****************************************************************************/
  36. static int  Create    ( vlc_object_t * );
  37. static void Close     ( vlc_object_t * );
  38. static void DoWork    ( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
  39.                         aout_buffer_t * );
  40. /*****************************************************************************
  41.  * Local structures
  42.  *****************************************************************************/
  43. struct aout_filter_sys_t
  44. {
  45.     aout_filter_t * p_secondary_resampler;
  46.     aout_alloc_t alloc;
  47.     AudioStreamBasicDescription s_src_stream_format;
  48.     AudioStreamBasicDescription s_dst_stream_format;
  49.     AudioConverterRef   s_converter;
  50.     unsigned int i_remainder;
  51.     unsigned int i_first_rate;
  52. };
  53. /*****************************************************************************
  54.  * Module descriptor
  55.  *****************************************************************************/
  56. vlc_module_begin();
  57.     set_description( _("audio filter using CoreAudio for resampling") );
  58.     set_capability( "audio filter", 40 );
  59.     set_callbacks( Create, Close );
  60. vlc_module_end();
  61. /*****************************************************************************
  62.  * Create: allocate resampler
  63.  *****************************************************************************/
  64. static int Create( vlc_object_t *p_this )
  65. {
  66.     aout_filter_t * p_filter = (aout_filter_t *)p_this;
  67.     struct aout_filter_sys_t * p_sys = p_filter->p_sys;
  68.     unsigned int i_nb_channels;
  69.     OSStatus err;
  70.     uint32_t i_prop;
  71.     unsigned int i_first_rate;
  72.     if ( p_filter->input.i_rate == p_filter->output.i_rate
  73.           || p_filter->input.i_format != p_filter->output.i_format
  74.           || p_filter->input.i_physical_channels
  75.               != p_filter->output.i_physical_channels
  76.           || p_filter->input.i_original_channels
  77.               != p_filter->output.i_original_channels
  78.           || p_filter->input.i_format != VLC_FOURCC('f','l','3','2') )
  79.     {
  80.         return VLC_EGENERIC;
  81.     }
  82.     if ( p_filter->input.i_rate >= 48000 * (100 + AOUT_MAX_RESAMPLING) / 100 )
  83.         i_first_rate = 48000;
  84.     else
  85.         i_first_rate = 44100;
  86.     if ( p_filter->output.i_rate == i_first_rate )
  87.     {
  88.         return VLC_EGENERIC;
  89.     }
  90.     i_nb_channels = aout_FormatNbChannels( &p_filter->input );
  91.     /* Allocate the memory needed to store the module's structure */
  92.     p_sys = p_filter->p_sys = malloc( sizeof(struct aout_filter_sys_t) );
  93.     if( p_filter->p_sys == NULL )
  94.     {
  95.         msg_Err( p_filter, "out of memory" );
  96.         return VLC_ENOMEM;
  97.     }
  98.     memset( p_filter->p_sys, 0, sizeof(struct aout_filter_sys_t) );
  99.     p_sys->i_first_rate = i_first_rate;
  100.     p_sys->i_remainder = 0;
  101.     p_sys->s_src_stream_format.mFormatID = kAudioFormatLinearPCM;
  102.     p_sys->s_src_stream_format.mFormatFlags
  103.         = kLinearPCMFormatFlagIsFloat | kAudioFormatFlagsNativeEndian
  104.           | kAudioFormatFlagIsPacked;
  105.     p_sys->s_src_stream_format.mBytesPerPacket = i_nb_channels * 4;
  106.     p_sys->s_src_stream_format.mFramesPerPacket = 1;
  107.     p_sys->s_src_stream_format.mBytesPerFrame = i_nb_channels * 4;
  108.     p_sys->s_src_stream_format.mChannelsPerFrame = i_nb_channels;
  109.     p_sys->s_src_stream_format.mBitsPerChannel = 32;
  110.     memcpy( &p_sys->s_dst_stream_format, &p_sys->s_src_stream_format,
  111.             sizeof(AudioStreamBasicDescription) );
  112.     p_sys->s_src_stream_format.mSampleRate = p_sys->i_first_rate;
  113.     p_sys->s_dst_stream_format.mSampleRate = p_filter->output.i_rate;
  114.     err = AudioConverterNew( &p_sys->s_src_stream_format,
  115.                              &p_sys->s_dst_stream_format,
  116.                              &p_sys->s_converter );
  117.     if( err != noErr )
  118.     {
  119.         msg_Err( p_filter, "AudioConverterNew failed: [%4.4s]",
  120.                  (char *)&err );
  121.         free(p_sys);
  122.         return VLC_EGENERIC;
  123.     }
  124.     i_prop = kConverterPrimeMethod_None;
  125.     err = AudioConverterSetProperty( p_sys->s_converter,
  126.             kAudioConverterPrimeMethod, sizeof(i_prop), &i_prop );
  127.     if( err != noErr )
  128.     {
  129.         msg_Err( p_filter, "AudioConverterSetProperty failed: [%4.4s]",
  130.                  (char *)&err );
  131.         free(p_sys);
  132.         return VLC_EGENERIC;
  133.     }
  134.     /* Allocate a secondary resampler for the remainder. */
  135.     p_sys->p_secondary_resampler = vlc_object_create( p_filter,
  136.                                                   sizeof(aout_filter_t) );     
  137.     if ( p_sys->p_secondary_resampler == NULL )
  138.     {
  139.         free(p_sys);
  140.         return VLC_EGENERIC;
  141.     }
  142.     vlc_object_attach( p_sys->p_secondary_resampler, p_filter );
  143.     memcpy( &p_sys->p_secondary_resampler->input, &p_filter->input, 
  144.             sizeof(audio_sample_format_t) );
  145.     memcpy( &p_sys->p_secondary_resampler->output, &p_filter->output, 
  146.             sizeof(audio_sample_format_t) );
  147.     p_sys->p_secondary_resampler->p_module
  148.         = module_Need( p_sys->p_secondary_resampler, "audio filter",
  149.                        "ugly_resampler", VLC_TRUE );
  150.     if ( p_sys->p_secondary_resampler->p_module == NULL )
  151.     {
  152.         vlc_object_detach( p_sys->p_secondary_resampler );
  153.         vlc_object_destroy( p_sys->p_secondary_resampler );
  154.         free(p_sys);
  155.         return VLC_EGENERIC;
  156.     }
  157.     p_sys->p_secondary_resampler->b_continuity = VLC_FALSE;
  158.     p_sys->alloc.i_alloc_type = AOUT_ALLOC_STACK;
  159.     p_sys->alloc.i_bytes_per_sec = p_filter->output.i_bytes_per_frame
  160.                              * p_filter->output.i_rate
  161.                              / p_filter->output.i_frame_length;
  162.     p_filter->pf_do_work = DoWork;
  163.     /* We don't want a new buffer to be created because we're not sure we'll
  164.      * actually need to resample anything. */
  165.     p_filter->b_in_place = VLC_FALSE;
  166.     return VLC_SUCCESS;
  167. }
  168. /*****************************************************************************
  169.  * Close: free our resources
  170.  *****************************************************************************/
  171. static void Close( vlc_object_t * p_this )
  172. {
  173.     aout_filter_t * p_filter = (aout_filter_t *)p_this;
  174.     struct aout_filter_sys_t * p_sys = p_filter->p_sys;
  175.     OSErr err;
  176.     module_Unneed( p_sys->p_secondary_resampler,
  177.                    p_sys->p_secondary_resampler->p_module );
  178.     vlc_object_detach( p_sys->p_secondary_resampler );
  179.     vlc_object_destroy( p_sys->p_secondary_resampler );
  180.     /* Destroy the AudioConverter */
  181.     err = AudioConverterDispose( p_sys->s_converter );
  182.     if( err != noErr )
  183.     {
  184.         msg_Err( p_this, "AudioConverterDispose failed: %u", err );
  185.     }
  186.     free( p_filter->p_sys );
  187. }
  188. /*****************************************************************************
  189.  * DoWork: convert a buffer
  190.  *****************************************************************************/
  191. static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
  192.                     aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
  193. {
  194.     struct aout_filter_sys_t * p_sys = p_filter->p_sys;
  195.     int32_t *p_in = (int32_t *)p_in_buf->p_buffer;
  196.     int32_t *p_out;
  197.     UInt32 i_output_size;
  198.     unsigned int i_out_nb, i_wanted_nb, i_new_rate;
  199.     OSErr err;
  200.     aout_buffer_t * p_middle_buf;
  201.     unsigned int i_nb_channels = aout_FormatNbChannels( &p_filter->input );
  202. #if 1
  203.     if ( !p_filter->b_continuity )
  204.     {
  205.         err = AudioConverterReset( p_sys->s_converter );
  206.         if( err != noErr )
  207.         {
  208.             msg_Err( p_filter, "AudioConverterReset failed: [%4.4s]",
  209.                      (char *)&err );
  210.         }
  211.         p_filter->b_continuity = VLC_TRUE;
  212.         p_sys->i_remainder = 0;
  213.     }
  214. #endif
  215.     i_out_nb = (p_in_buf->i_nb_samples * p_filter->output.i_rate
  216.                  + p_sys->i_remainder) / p_sys->i_first_rate;
  217.     p_sys->i_remainder = (p_in_buf->i_nb_samples * p_filter->output.i_rate
  218.                  + p_sys->i_remainder) % p_sys->i_first_rate;
  219.     i_output_size = i_out_nb * 4 * i_nb_channels;
  220.     if ( i_output_size > p_out_buf->i_size )
  221.     {
  222.         aout_BufferAlloc( &p_sys->alloc,
  223.             i_out_nb * 1000000 / p_filter->output.i_rate,
  224.             NULL, p_middle_buf );
  225.     }
  226.     else
  227.     {
  228.         p_middle_buf = p_out_buf;
  229.     }
  230.     p_out = (int32_t*)p_middle_buf->p_buffer;
  231.     err = AudioConverterConvertBuffer( p_sys->s_converter,
  232.         p_in_buf->i_nb_samples * 4 * i_nb_channels, p_in,
  233.         &i_output_size, p_out );
  234.     if( err != noErr )
  235.     {
  236.         msg_Warn( p_filter, "AudioConverterConvertBuffer failed: [%4.4s] (%u:%u)",
  237.                  (char *)&err, i_out_nb * 4 * i_nb_channels, i_output_size );
  238.         i_output_size = i_out_nb * 4 * i_nb_channels;
  239.         memset( p_out, 0, i_output_size );
  240.     }
  241.     p_middle_buf->i_nb_samples = i_output_size / 4 / i_nb_channels;
  242.     p_middle_buf->i_nb_bytes = i_output_size;
  243.     p_middle_buf->start_date = p_in_buf->start_date;
  244.     p_middle_buf->end_date = p_middle_buf->start_date + p_middle_buf->i_nb_samples *
  245.         1000000 / p_filter->output.i_rate;
  246.     i_wanted_nb = p_in_buf->i_nb_samples * p_filter->output.i_rate
  247.                                         / p_filter->input.i_rate;
  248.     i_new_rate = p_middle_buf->i_nb_samples * p_filter->output.i_rate
  249.                                         / i_wanted_nb;
  250.     p_sys->p_secondary_resampler->input.i_rate = i_new_rate;
  251.     p_sys->p_secondary_resampler->pf_do_work( p_aout,
  252.         p_sys->p_secondary_resampler, p_middle_buf, p_out_buf );
  253.     if ( p_middle_buf != p_out_buf )
  254.     {
  255.         aout_BufferFree( p_middle_buf );
  256.     }
  257. }