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

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * bandlimited.c : band-limited interpolation resampler
  3.  *****************************************************************************
  4.  * Copyright (C) 2002 VideoLAN
  5.  * $Id: bandlimited.c 7522 2004-04-27 16:35:15Z sam $
  6.  *
  7.  * Authors: Gildas Bazin <gbazin@netcourrier.com>
  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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble:
  25.  *
  26.  * This implementation of the band-limited interpolationis based on the
  27.  * following paper:
  28.  * http://ccrma-www.stanford.edu/~jos/resample/resample.html
  29.  *
  30.  * It uses a Kaiser-windowed sinc-function low-pass filter and the width of the
  31.  * filter is 13 samples.
  32.  *
  33.  *****************************************************************************/
  34. #include <stdlib.h>                                      /* malloc(), free() */
  35. #include <string.h>
  36. #include <vlc/vlc.h>
  37. #include "audio_output.h"
  38. #include "aout_internal.h"
  39. #include "bandlimited.h"
  40. /*****************************************************************************
  41.  * Local prototypes
  42.  *****************************************************************************/
  43. static int  Create    ( vlc_object_t * );
  44. static void Close     ( vlc_object_t * );
  45. static void DoWork    ( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
  46.                         aout_buffer_t * );
  47. static void FilterFloatUP( float Imp[], float ImpD[], uint16_t Nwing,
  48.                            float *f_in, float *f_out, uint32_t ui_remainder,
  49.                            uint32_t ui_output_rate, int16_t Inc,
  50.                            int i_nb_channels );
  51. static void FilterFloatUD( float Imp[], float ImpD[], uint16_t Nwing,
  52.                            float *f_in, float *f_out, uint32_t ui_remainder,
  53.                            uint32_t ui_output_rate, uint32_t ui_input_rate,
  54.                            int16_t Inc, int i_nb_channels );
  55. /*****************************************************************************
  56.  * Local structures
  57.  *****************************************************************************/
  58. struct aout_filter_sys_t
  59. {
  60.     int32_t *p_buf;                        /* this filter introduces a delay */
  61.     int i_buf_size;
  62.     int i_old_rate;
  63.     double d_old_factor;
  64.     int i_old_wing;
  65.     unsigned int i_remainder;                /* remainder of previous sample */
  66.     audio_date_t end_date;
  67. };
  68. /*****************************************************************************
  69.  * Module descriptor
  70.  *****************************************************************************/
  71. vlc_module_begin();
  72.     set_description( _("audio filter for band-limited interpolation resampling") );
  73.     set_capability( "audio filter", 20 );
  74.     set_callbacks( Create, Close );
  75. vlc_module_end();
  76. /*****************************************************************************
  77.  * Create: allocate linear resampler
  78.  *****************************************************************************/
  79. static int Create( vlc_object_t *p_this )
  80. {
  81.     aout_filter_t * p_filter = (aout_filter_t *)p_this;
  82.     double d_factor;
  83.     int i_filter_wing;
  84.     if ( p_filter->input.i_rate == p_filter->output.i_rate
  85.           || p_filter->input.i_format != p_filter->output.i_format
  86.           || p_filter->input.i_physical_channels
  87.               != p_filter->output.i_physical_channels
  88.           || p_filter->input.i_original_channels
  89.               != p_filter->output.i_original_channels
  90.           || p_filter->input.i_format != VLC_FOURCC('f','l','3','2') )
  91.     {
  92.         return VLC_EGENERIC;
  93.     }
  94. #if !defined( SYS_DARWIN )
  95.     if( !config_GetInt( p_this, "hq-resampling" ) )
  96.     {
  97.         return VLC_EGENERIC;
  98.     }
  99. #endif
  100.     /* Allocate the memory needed to store the module's structure */
  101.     p_filter->p_sys = malloc( sizeof(struct aout_filter_sys_t) );
  102.     if( p_filter->p_sys == NULL )
  103.     {
  104.         msg_Err( p_filter, "out of memory" );
  105.         return VLC_ENOMEM;
  106.     }
  107.     /* Calculate worst case for the length of the filter wing */
  108.     d_factor = (double)p_filter->output.i_rate
  109.                         / p_filter->input.i_rate;
  110.     i_filter_wing = ((SMALL_FILTER_NMULT + 1)/2.0)
  111.                       * __MAX(1.0, 1.0/d_factor) + 10;
  112.     p_filter->p_sys->i_buf_size = aout_FormatNbChannels( &p_filter->input ) *
  113.         sizeof(int32_t) * 2 * i_filter_wing;
  114.     /* Allocate enough memory to buffer previous samples */
  115.     p_filter->p_sys->p_buf = malloc( p_filter->p_sys->i_buf_size );
  116.     if( p_filter->p_sys->p_buf == NULL )
  117.     {
  118.         msg_Err( p_filter, "out of memory" );
  119.         return VLC_ENOMEM;
  120.     }
  121.     p_filter->p_sys->i_old_wing = 0;
  122.     p_filter->pf_do_work = DoWork;
  123.     /* We don't want a new buffer to be created because we're not sure we'll
  124.      * actually need to resample anything. */
  125.     p_filter->b_in_place = VLC_TRUE;
  126.     return VLC_SUCCESS;
  127. }
  128. /*****************************************************************************
  129.  * Close: free our resources
  130.  *****************************************************************************/
  131. static void Close( vlc_object_t * p_this )
  132. {
  133.     aout_filter_t * p_filter = (aout_filter_t *)p_this;
  134.     free( p_filter->p_sys->p_buf );
  135.     free( p_filter->p_sys );
  136. }
  137. /*****************************************************************************
  138.  * DoWork: convert a buffer
  139.  *****************************************************************************/
  140. static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
  141.                     aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
  142. {
  143.     float *p_in, *p_in_orig, *p_out = (float *)p_out_buf->p_buffer;
  144.     int i_nb_channels = aout_FormatNbChannels( &p_filter->input );
  145.     int i_in_nb = p_in_buf->i_nb_samples;
  146.     int i_in, i_out = 0;
  147.     double d_factor, d_scale_factor, d_old_scale_factor;
  148.     int i_filter_wing;
  149. #if 0
  150.     int i;
  151. #endif
  152.     /* Check if we really need to run the resampler */
  153.     if( p_aout->mixer.mixer.i_rate == p_filter->input.i_rate )
  154.     {
  155.         if( //p_filter->b_continuity && /* What difference does it make ? :) */
  156.             p_filter->p_sys->i_old_wing &&
  157.             p_in_buf->i_size >=
  158.               p_in_buf->i_nb_bytes + p_filter->p_sys->i_old_wing *
  159.               p_filter->input.i_bytes_per_frame )
  160.         {
  161.             /* output the whole thing with the samples from last time */
  162.             memmove( ((float *)(p_in_buf->p_buffer)) +
  163.                      i_nb_channels * p_filter->p_sys->i_old_wing,
  164.                      p_in_buf->p_buffer, p_in_buf->i_nb_bytes );
  165.             memcpy( p_in_buf->p_buffer, p_filter->p_sys->p_buf +
  166.                     i_nb_channels * p_filter->p_sys->i_old_wing,
  167.                     p_filter->p_sys->i_old_wing *
  168.                     p_filter->input.i_bytes_per_frame );
  169.             p_out_buf->i_nb_samples = p_in_buf->i_nb_samples +
  170.                 p_filter->p_sys->i_old_wing;
  171.             p_out_buf->start_date = aout_DateGet( &p_filter->p_sys->end_date );
  172.             p_out_buf->end_date =
  173.                 aout_DateIncrement( &p_filter->p_sys->end_date,
  174.                                     p_out_buf->i_nb_samples );
  175.             p_out_buf->i_nb_bytes = p_out_buf->i_nb_samples *
  176.                 p_filter->input.i_bytes_per_frame;
  177.         }
  178.         p_filter->b_continuity = VLC_FALSE;
  179.         p_filter->p_sys->i_old_wing = 0;
  180.         return;
  181.     }
  182.     if( !p_filter->b_continuity )
  183.     {
  184.         /* Continuity in sound samples has been broken, we'd better reset
  185.          * everything. */
  186.         p_filter->b_continuity = VLC_TRUE;
  187.         p_filter->p_sys->i_remainder = 0;
  188.         aout_DateInit( &p_filter->p_sys->end_date, p_filter->output.i_rate );
  189.         aout_DateSet( &p_filter->p_sys->end_date, p_in_buf->start_date );
  190.         p_filter->p_sys->i_old_rate   = p_filter->input.i_rate;
  191.         p_filter->p_sys->d_old_factor = 1;
  192.         p_filter->p_sys->i_old_wing   = 0;
  193.     }
  194. #if 0
  195.     msg_Err( p_filter, "old rate: %i, old factor: %f, old wing: %i, i_in: %i",
  196.              p_filter->p_sys->i_old_rate, p_filter->p_sys->d_old_factor,
  197.              p_filter->p_sys->i_old_wing, i_in_nb );
  198. #endif
  199.     /* Prepare the source buffer */
  200.     i_in_nb += (p_filter->p_sys->i_old_wing * 2);
  201. #ifdef HAVE_ALLOCA
  202.     p_in = p_in_orig = (float *)alloca( i_in_nb *
  203.                                         p_filter->input.i_bytes_per_frame );
  204. #else
  205.     p_in = p_in_orig = (float *)malloc( i_in_nb *
  206.                                         p_filter->input.i_bytes_per_frame );
  207. #endif
  208.     if( p_in == NULL )
  209.     {
  210.         return;
  211.     }
  212.     /* Copy all our samples in p_in */
  213.     if( p_filter->p_sys->i_old_wing )
  214.     {
  215.         p_aout->p_vlc->pf_memcpy( p_in, p_filter->p_sys->p_buf,
  216.                                   p_filter->p_sys->i_old_wing * 2 *
  217.                                   p_filter->input.i_bytes_per_frame );
  218.     }
  219.     p_aout->p_vlc->pf_memcpy( p_in + p_filter->p_sys->i_old_wing * 2 *
  220.                               i_nb_channels, p_in_buf->p_buffer,
  221.                               p_in_buf->i_nb_samples *
  222.                               p_filter->input.i_bytes_per_frame );
  223.     /* Make sure the output buffer is reset */
  224.     memset( p_out, 0, p_out_buf->i_size );
  225.     /* Calculate the new length of the filter wing */
  226.     d_factor = (double)p_aout->mixer.mixer.i_rate / p_filter->input.i_rate;
  227.     i_filter_wing = ((SMALL_FILTER_NMULT+1)/2.0) * __MAX(1.0,1.0/d_factor) + 1;
  228.     /* Account for increased filter gain when using factors less than 1 */
  229.     d_old_scale_factor = SMALL_FILTER_SCALE *
  230.         p_filter->p_sys->d_old_factor + 0.5;
  231.     d_scale_factor = SMALL_FILTER_SCALE * d_factor + 0.5;
  232.     /* Apply the old rate until we have enough samples for the new one */
  233.     i_in = p_filter->p_sys->i_old_wing;
  234.     p_in += p_filter->p_sys->i_old_wing * i_nb_channels;
  235.     for( ; i_in < i_filter_wing &&
  236.            (i_in + p_filter->p_sys->i_old_wing) < i_in_nb; i_in++ )
  237.     {
  238.         if( p_filter->p_sys->d_old_factor == 1 )
  239.         {
  240.             /* Just copy the samples */
  241.             memcpy( p_out, p_in, 
  242.                     p_filter->input.i_bytes_per_frame );          
  243.             p_in += i_nb_channels;
  244.             p_out += i_nb_channels;
  245.             i_out++;
  246.             continue;
  247.         }
  248.         while( p_filter->p_sys->i_remainder < p_filter->output.i_rate )
  249.         {
  250.             if( p_filter->p_sys->d_old_factor >= 1 )
  251.             {
  252.                 /* FilterFloatUP() is faster if we can use it */
  253.                 /* Perform left-wing inner product */
  254.                 FilterFloatUP( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
  255.                                SMALL_FILTER_NWING, p_in, p_out,
  256.                                p_filter->p_sys->i_remainder,
  257.                                p_filter->output.i_rate,
  258.                                -1, i_nb_channels );
  259.                 /* Perform right-wing inner product */
  260.                 FilterFloatUP( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
  261.                                SMALL_FILTER_NWING, p_in + i_nb_channels, p_out,
  262.                                p_filter->output.i_rate -
  263.                                p_filter->p_sys->i_remainder,
  264.                                p_filter->output.i_rate,
  265.                                1, i_nb_channels );
  266. #if 0
  267.                 /* Normalize for unity filter gain */
  268.                 for( i = 0; i < i_nb_channels; i++ )
  269.                 {
  270.                     *(p_out+i) *= d_old_scale_factor;
  271.                 }
  272. #endif
  273.                 /* Sanity check */
  274.                 if( p_out_buf->i_size/p_filter->input.i_bytes_per_frame
  275.                     <= (unsigned int)i_out+1 )
  276.                 {
  277.                     p_out += i_nb_channels;
  278.                     i_out++;
  279.                     p_filter->p_sys->i_remainder += p_filter->input.i_rate;
  280.                     break;
  281.                 }
  282.             }
  283.             else
  284.             {
  285.                 /* Perform left-wing inner product */
  286.                 FilterFloatUD( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
  287.                                SMALL_FILTER_NWING, p_in, p_out,
  288.                                p_filter->p_sys->i_remainder,
  289.                                p_filter->output.i_rate, p_filter->input.i_rate,
  290.                                -1, i_nb_channels );
  291.                 /* Perform right-wing inner product */
  292.                 FilterFloatUD( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
  293.                                SMALL_FILTER_NWING, p_in + i_nb_channels, p_out,
  294.                                p_filter->output.i_rate -
  295.                                p_filter->p_sys->i_remainder,
  296.                                p_filter->output.i_rate, p_filter->input.i_rate,
  297.                                1, i_nb_channels );
  298.             }
  299.             p_out += i_nb_channels;
  300.             i_out++;
  301.             p_filter->p_sys->i_remainder += p_filter->input.i_rate;
  302.         }
  303.         p_in += i_nb_channels;
  304.         p_filter->p_sys->i_remainder -= p_filter->output.i_rate;
  305.     }
  306.     /* Apply the new rate for the rest of the samples */
  307.     if( i_in < i_in_nb - i_filter_wing )
  308.     {
  309.         p_filter->p_sys->i_old_rate   = p_filter->input.i_rate;
  310.         p_filter->p_sys->d_old_factor = d_factor;
  311.         p_filter->p_sys->i_old_wing   = i_filter_wing;
  312.     }
  313.     for( ; i_in < i_in_nb - i_filter_wing; i_in++ )
  314.     {
  315.         while( p_filter->p_sys->i_remainder < p_filter->output.i_rate )
  316.         {
  317.             if( d_factor >= 1 )
  318.             {
  319.                 /* FilterFloatUP() is faster if we can use it */
  320.                 /* Perform left-wing inner product */
  321.                 FilterFloatUP( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
  322.                                SMALL_FILTER_NWING, p_in, p_out,
  323.                                p_filter->p_sys->i_remainder,
  324.                                p_filter->output.i_rate,
  325.                                -1, i_nb_channels );
  326.                 /* Perform right-wing inner product */
  327.                 FilterFloatUP( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
  328.                                SMALL_FILTER_NWING, p_in + i_nb_channels, p_out,
  329.                                p_filter->output.i_rate -
  330.                                p_filter->p_sys->i_remainder,
  331.                                p_filter->output.i_rate,
  332.                                1, i_nb_channels );
  333. #if 0
  334.                 /* Normalize for unity filter gain */
  335.                 for( i = 0; i < i_nb_channels; i++ )
  336.                 {
  337.                     *(p_out+i) *= d_old_scale_factor;
  338.                 }
  339. #endif
  340.                 /* Sanity check */
  341.                 if( p_out_buf->i_size/p_filter->input.i_bytes_per_frame
  342.                     <= (unsigned int)i_out+1 )
  343.                 {
  344.                     p_out += i_nb_channels;
  345.                     i_out++;
  346.                     p_filter->p_sys->i_remainder += p_filter->input.i_rate;
  347.                     break;
  348.                 }
  349.             }
  350.             else
  351.             {
  352.                 /* Perform left-wing inner product */
  353.                 FilterFloatUD( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
  354.                                SMALL_FILTER_NWING, p_in, p_out,
  355.                                p_filter->p_sys->i_remainder,
  356.                                p_filter->output.i_rate, p_filter->input.i_rate,
  357.                                -1, i_nb_channels );
  358.                 /* Perform right-wing inner product */
  359.                 FilterFloatUD( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
  360.                                SMALL_FILTER_NWING, p_in + i_nb_channels, p_out,
  361.                                p_filter->output.i_rate -
  362.                                p_filter->p_sys->i_remainder,
  363.                                p_filter->output.i_rate, p_filter->input.i_rate,
  364.                                1, i_nb_channels );
  365.             }
  366.             p_out += i_nb_channels;
  367.             i_out++;
  368.             p_filter->p_sys->i_remainder += p_filter->input.i_rate;
  369.         }
  370.         p_in += i_nb_channels;
  371.         p_filter->p_sys->i_remainder -= p_filter->output.i_rate;
  372.     }
  373.     /* Buffer i_filter_wing * 2 samples for next time */
  374.     if( p_filter->p_sys->i_old_wing )
  375.     {
  376.         memcpy( p_filter->p_sys->p_buf,
  377.                 p_in_orig + (i_in_nb - 2 * p_filter->p_sys->i_old_wing) *
  378.                 i_nb_channels, (2 * p_filter->p_sys->i_old_wing) *
  379.                 p_filter->input.i_bytes_per_frame );
  380.     }
  381. #if 0
  382.     msg_Err( p_filter, "p_out size: %i, nb bytes out: %i", p_out_buf->i_size,
  383.              i_out * p_filter->input.i_bytes_per_frame );
  384. #endif
  385.     /* Free the temp buffer */
  386. #ifndef HAVE_ALLOCA
  387.     free( p_in_orig );
  388. #endif
  389.     /* Finalize aout buffer */
  390.     p_out_buf->i_nb_samples = i_out;
  391.     p_out_buf->start_date = aout_DateGet( &p_filter->p_sys->end_date );
  392.     p_out_buf->end_date = aout_DateIncrement( &p_filter->p_sys->end_date,
  393.                                               p_out_buf->i_nb_samples );
  394.     p_out_buf->i_nb_bytes = p_out_buf->i_nb_samples *
  395.         i_nb_channels * sizeof(int32_t);
  396. }
  397. void FilterFloatUP( float Imp[], float ImpD[], uint16_t Nwing, float *p_in,
  398.                     float *p_out, uint32_t ui_remainder,
  399.                     uint32_t ui_output_rate, int16_t Inc, int i_nb_channels )
  400. {
  401.     float *Hp, *Hdp, *End;
  402.     float t, temp;
  403.     uint32_t ui_linear_remainder;
  404.     int i;
  405.     Hp = &Imp[(ui_remainder<<Nhc)/ui_output_rate];
  406.     Hdp = &ImpD[(ui_remainder<<Nhc)/ui_output_rate];
  407.     End = &Imp[Nwing];
  408.     ui_linear_remainder = (ui_remainder<<Nhc) -
  409.                             (ui_remainder<<Nhc)/ui_output_rate*ui_output_rate;
  410.     if (Inc == 1)               /* If doing right wing...              */
  411.     {                           /* ...drop extra coeff, so when Ph is  */
  412.         End--;                  /*    0.5, we don't do too many mult's */
  413.         if (ui_remainder == 0)  /* If the phase is zero...           */
  414.         {                       /* ...then we've already skipped the */
  415.             Hp += Npc;          /*    first sample, so we must also  */
  416.             Hdp += Npc;         /*    skip ahead in Imp[] and ImpD[] */
  417.         }
  418.     }
  419.     while (Hp < End) {
  420.         t = *Hp;                /* Get filter coeff */
  421.                                 /* t is now interp'd filter coeff */
  422.         t += *Hdp * ui_linear_remainder / ui_output_rate / Npc;
  423.         for( i = 0; i < i_nb_channels; i++ )
  424.         {
  425.             temp = t;
  426.             temp *= *(p_in+i);  /* Mult coeff by input sample */
  427.             *(p_out+i) += temp; /* The filter output */
  428.         }
  429.         Hdp += Npc;             /* Filter coeff differences step */
  430.         Hp += Npc;              /* Filter coeff step */
  431.         p_in += (Inc * i_nb_channels); /* Input signal step */
  432.     }
  433. }
  434. void FilterFloatUD( float Imp[], float ImpD[], uint16_t Nwing, float *p_in,
  435.                     float *p_out, uint32_t ui_remainder,
  436.                     uint32_t ui_output_rate, uint32_t ui_input_rate,
  437.                     int16_t Inc, int i_nb_channels )
  438. {
  439.     float *Hp, *Hdp, *End;
  440.     float t, temp;
  441.     uint32_t ui_linear_remainder;
  442.     int i, ui_counter = 0;
  443.     Hp = Imp + (ui_remainder<<Nhc) / ui_input_rate;
  444.     Hdp = ImpD  + (ui_remainder<<Nhc) / ui_input_rate;
  445.     End = &Imp[Nwing];
  446.     if (Inc == 1)               /* If doing right wing...              */
  447.     {                           /* ...drop extra coeff, so when Ph is  */
  448.         End--;                  /*    0.5, we don't do too many mult's */
  449.         if (ui_remainder == 0)  /* If the phase is zero...           */
  450.         {                       /* ...then we've already skipped the */
  451.             Hp = Imp +          /* first sample, so we must also  */
  452.                   (ui_output_rate << Nhc) / ui_input_rate;
  453.             Hdp = ImpD +        /* skip ahead in Imp[] and ImpD[] */
  454.                   (ui_output_rate << Nhc) / ui_input_rate;
  455.             ui_counter++;
  456.         }
  457.     }
  458.     while (Hp < End) {
  459.         t = *Hp;                /* Get filter coeff */
  460.                                 /* t is now interp'd filter coeff */
  461.         ui_linear_remainder =
  462.           ((ui_output_rate * ui_counter + ui_remainder)<< Nhc) -
  463.           ((ui_output_rate * ui_counter + ui_remainder)<< Nhc) /
  464.           ui_input_rate * ui_input_rate;
  465.         t += *Hdp * ui_linear_remainder / ui_input_rate / Npc;
  466.         for( i = 0; i < i_nb_channels; i++ )
  467.         {
  468.             temp = t;
  469.             temp *= *(p_in+i);  /* Mult coeff by input sample */
  470.             *(p_out+i) += temp; /* The filter output */
  471.         }
  472.         ui_counter++;
  473.         /* Filter coeff step */
  474.         Hp = Imp + ((ui_output_rate * ui_counter + ui_remainder)<< Nhc)
  475.                     / ui_input_rate;
  476.         /* Filter coeff differences step */
  477.         Hdp = ImpD + ((ui_output_rate * ui_counter + ui_remainder)<< Nhc)
  478.                      / ui_input_rate;
  479.         p_in += (Inc * i_nb_channels); /* Input signal step */
  480.     }
  481. }