ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

src_sinc.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
00003 **
00004 ** This program is free software; you can redistribute it and/or modify
00005 ** it under the terms of the GNU General Public License as published by
00006 ** the Free Software Foundation; either version 2 of the License, or
00007 ** (at your option) any later version.
00008 **
00009 ** This program is distributed in the hope that it will be useful,
00010 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 ** GNU General Public License for more details.
00013 **
00014 ** You should have received a copy of the GNU General Public License
00015 ** along with this program; if not, write to the Free Software
00016 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00017 */
00018 
00019 /*
00020 ** This code is part of Secret Rabbit Code aka libsamplerate. A commercial
00021 ** use license for this code is available, please see:
00022 **      http://www.mega-nerd.com/SRC/procedure.html
00023 */
00024 
00025 #include <stdio.h>
00026 #include <stdlib.h>
00027 #include <string.h>
00028 
00029 #include "config.h"
00030 #include "float_cast.h"
00031 #include "common.h"
00032 
00033 #define SINC_MAGIC_MARKER   MAKE_MAGIC (' ', 's', 'i', 'n', 'c', ' ')
00034 
00035 /*========================================================================================
00036 */
00037 
00038 #define MAKE_INCREMENT_T(x)     ((increment_t) (x))
00039 
00040 #define SHIFT_BITS              12
00041 #define FP_ONE                  ((double) (((increment_t) 1) << SHIFT_BITS))
00042 #define INV_FP_ONE              (1.0 / FP_ONE)
00043 
00044 /*========================================================================================
00045 */
00046 
00047 typedef int32_t increment_t ;
00048 typedef float   coeff_t ;
00049 
00050 #include "fastest_coeffs.h"
00051 #include "mid_qual_coeffs.h"
00052 #include "high_qual_coeffs.h"
00053 
00054 typedef struct
00055 {   int     sinc_magic_marker ;
00056 
00057     int     channels ;
00058     long    in_count, in_used ;
00059     long    out_count, out_gen ;
00060 
00061     int     coeff_half_len, index_inc ;
00062 
00063     double  src_ratio, input_index ;
00064 
00065     coeff_t const   *coeffs ;
00066 
00067     int     b_current, b_end, b_real_end, b_len ;
00068 
00069     /* Sure hope noone does more than 128 channels at once. */
00070     double left_calc [128], right_calc [128] ;
00071 
00072     /* C99 struct flexible array. */
00073     float   buffer [] ;
00074 } SINC_FILTER ;
00075 
00076 static int sinc_multichan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
00077 static int sinc_hex_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
00078 static int sinc_quad_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
00079 static int sinc_stereo_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
00080 static int sinc_mono_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
00081 
00082 static int prepare_data (SINC_FILTER *filter, SRC_DATA *data, int half_filter_chan_len) WARN_UNUSED ;
00083 
00084 static void sinc_reset (SRC_PRIVATE *psrc) ;
00085 
00086 static inline increment_t
00087 double_to_fp (double x)
00088 {   return (lrint ((x) * FP_ONE)) ;
00089 } /* double_to_fp */
00090 
00091 static inline increment_t
00092 int_to_fp (int x)
00093 {   return (((increment_t) (x)) << SHIFT_BITS) ;
00094 } /* int_to_fp */
00095 
00096 static inline int
00097 fp_to_int (increment_t x)
00098 {   return (((x) >> SHIFT_BITS)) ;
00099 } /* fp_to_int */
00100 
00101 static inline increment_t
00102 fp_fraction_part (increment_t x)
00103 {   return ((x) & ((((increment_t) 1) << SHIFT_BITS) - 1)) ;
00104 } /* fp_fraction_part */
00105 
00106 static inline double
00107 fp_to_double (increment_t x)
00108 {   return fp_fraction_part (x) * INV_FP_ONE ;
00109 } /* fp_to_double */
00110 
00111 
00112 /*----------------------------------------------------------------------------------------
00113 */
00114 
00115 const char*
00116 sinc_get_name (int src_enum)
00117 {
00118     switch (src_enum)
00119     {   case SRC_SINC_BEST_QUALITY :
00120             return "Best Sinc Interpolator" ;
00121 
00122         case SRC_SINC_MEDIUM_QUALITY :
00123             return "Medium Sinc Interpolator" ;
00124 
00125         case SRC_SINC_FASTEST :
00126             return "Fastest Sinc Interpolator" ;
00127 
00128         default: break ;
00129         } ;
00130 
00131     return NULL ;
00132 } /* sinc_get_descrition */
00133 
00134 const char*
00135 sinc_get_description (int src_enum)
00136 {
00137     switch (src_enum)
00138     {   case SRC_SINC_FASTEST :
00139             return "Band limited sinc interpolation, fastest, 97dB SNR, 80% BW." ;
00140 
00141         case SRC_SINC_MEDIUM_QUALITY :
00142             return "Band limited sinc interpolation, medium quality, 121dB SNR, 90% BW." ;
00143 
00144         case SRC_SINC_BEST_QUALITY :
00145             return "Band limited sinc interpolation, best quality, 145dB SNR, 96% BW." ;
00146 
00147         default :
00148             break ;
00149         } ;
00150 
00151     return NULL ;
00152 } /* sinc_get_descrition */
00153 
00154 int
00155 sinc_set_converter (SRC_PRIVATE *psrc, int src_enum)
00156 {   SINC_FILTER *filter, temp_filter ;
00157     increment_t count ;
00158     int bits ;
00159 
00160     /* Quick sanity check. */
00161     if (SHIFT_BITS >= sizeof (increment_t) * 8 - 1)
00162         return SRC_ERR_SHIFT_BITS ;
00163 
00164     if (psrc->private_data != NULL)
00165     {   free (psrc->private_data) ;
00166         psrc->private_data = NULL ;
00167         } ;
00168 
00169     memset (&temp_filter, 0, sizeof (temp_filter)) ;
00170 
00171     temp_filter.sinc_magic_marker = SINC_MAGIC_MARKER ;
00172     temp_filter.channels = psrc->channels ;
00173 
00174     if (psrc->channels > ARRAY_LEN (temp_filter.left_calc))
00175         return SRC_ERR_BAD_CHANNEL_COUNT ;
00176     else if (psrc->channels == 1)
00177     {   psrc->const_process = sinc_mono_vari_process ;
00178         psrc->vari_process = sinc_mono_vari_process ;
00179         }
00180     else
00181     if (psrc->channels == 2)
00182     {   psrc->const_process = sinc_stereo_vari_process ;
00183         psrc->vari_process = sinc_stereo_vari_process ;
00184         }
00185     else
00186     if (psrc->channels == 4)
00187     {   psrc->const_process = sinc_quad_vari_process ;
00188         psrc->vari_process = sinc_quad_vari_process ;
00189         }
00190     else
00191     if (psrc->channels == 6)
00192     {   psrc->const_process = sinc_hex_vari_process ;
00193         psrc->vari_process = sinc_hex_vari_process ;
00194         }
00195     else
00196     {   psrc->const_process = sinc_multichan_vari_process ;
00197         psrc->vari_process = sinc_multichan_vari_process ;
00198         } ;
00199     psrc->reset = sinc_reset ;
00200 
00201     switch (src_enum)
00202     {   case SRC_SINC_FASTEST :
00203                 temp_filter.coeffs = fastest_coeffs.coeffs ;
00204                 temp_filter.coeff_half_len = ARRAY_LEN (fastest_coeffs.coeffs) - 1 ;
00205                 temp_filter.index_inc = fastest_coeffs.increment ;
00206                 break ;
00207 
00208         case SRC_SINC_MEDIUM_QUALITY :
00209                 temp_filter.coeffs = slow_mid_qual_coeffs.coeffs ;
00210                 temp_filter.coeff_half_len = ARRAY_LEN (slow_mid_qual_coeffs.coeffs) - 1 ;
00211                 temp_filter.index_inc = slow_mid_qual_coeffs.increment ;
00212                 break ;
00213 
00214         case SRC_SINC_BEST_QUALITY :
00215                 temp_filter.coeffs = slow_high_qual_coeffs.coeffs ;
00216                 temp_filter.coeff_half_len = ARRAY_LEN (slow_high_qual_coeffs.coeffs) - 1 ;
00217                 temp_filter.index_inc = slow_high_qual_coeffs.increment ;
00218                 break ;
00219 
00220         default :
00221                 return SRC_ERR_BAD_CONVERTER ;
00222         } ;
00223 
00224     /*
00225     ** FIXME : This needs to be looked at more closely to see if there is
00226     ** a better way. Need to look at prepare_data () at the same time.
00227     */
00228 
00229     temp_filter.b_len = lrint (2.5 * temp_filter.coeff_half_len / (temp_filter.index_inc * 1.0) * SRC_MAX_RATIO) ;
00230     temp_filter.b_len = MAX (temp_filter.b_len, 4096) ;
00231     temp_filter.b_len *= temp_filter.channels ;
00232 
00233     if ((filter = calloc (1, sizeof (SINC_FILTER) + sizeof (filter->buffer [0]) * (temp_filter.b_len + temp_filter.channels))) == NULL)
00234         return SRC_ERR_MALLOC_FAILED ;
00235 
00236     *filter = temp_filter ;
00237     memset (&temp_filter, 0xEE, sizeof (temp_filter)) ;
00238 
00239     psrc->private_data = filter ;
00240 
00241     sinc_reset (psrc) ;
00242 
00243     count = filter->coeff_half_len ;
00244     for (bits = 0 ; (MAKE_INCREMENT_T (1) << bits) < count ; bits++)
00245         count |= (MAKE_INCREMENT_T (1) << bits) ;
00246 
00247     if (bits + SHIFT_BITS - 1 >= (int) (sizeof (increment_t) * 8))
00248         return SRC_ERR_FILTER_LEN ;
00249 
00250     return SRC_ERR_NO_ERROR ;
00251 } /* sinc_set_converter */
00252 
00253 static void
00254 sinc_reset (SRC_PRIVATE *psrc)
00255 {   SINC_FILTER *filter ;
00256 
00257     filter = (SINC_FILTER*) psrc->private_data ;
00258     if (filter == NULL)
00259         return ;
00260 
00261     filter->b_current = filter->b_end = 0 ;
00262     filter->b_real_end = -1 ;
00263 
00264     filter->src_ratio = filter->input_index = 0.0 ;
00265 
00266     memset (filter->buffer, 0, filter->b_len * sizeof (filter->buffer [0])) ;
00267 
00268     /* Set this for a sanity check */
00269     memset (filter->buffer + filter->b_len, 0xAA, filter->channels * sizeof (filter->buffer [0])) ;
00270 } /* sinc_reset */
00271 
00272 /*========================================================================================
00273 **  Beware all ye who dare pass this point. There be dragons here.
00274 */
00275 
00276 static inline double
00277 calc_output_single (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index)
00278 {   double      fraction, left, right, icoeff ;
00279     increment_t filter_index, max_filter_index ;
00280     int         data_index, coeff_count, indx ;
00281 
00282     /* Convert input parameters into fixed point. */
00283     max_filter_index = int_to_fp (filter->coeff_half_len) ;
00284 
00285     /* First apply the left half of the filter. */
00286     filter_index = start_filter_index ;
00287     coeff_count = (max_filter_index - filter_index) / increment ;
00288     filter_index = filter_index + coeff_count * increment ;
00289     data_index = filter->b_current - coeff_count ;
00290 
00291     left = 0.0 ;
00292     do
00293     {   fraction = fp_to_double (filter_index) ;
00294         indx = fp_to_int (filter_index) ;
00295 
00296         icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
00297 
00298         left += icoeff * filter->buffer [data_index] ;
00299 
00300         filter_index -= increment ;
00301         data_index = data_index + 1 ;
00302         }
00303     while (filter_index >= MAKE_INCREMENT_T (0)) ;
00304 
00305     /* Now apply the right half of the filter. */
00306     filter_index = increment - start_filter_index ;
00307     coeff_count = (max_filter_index - filter_index) / increment ;
00308     filter_index = filter_index + coeff_count * increment ;
00309     data_index = filter->b_current + 1 + coeff_count ;
00310 
00311     right = 0.0 ;
00312     do
00313     {   fraction = fp_to_double (filter_index) ;
00314         indx = fp_to_int (filter_index) ;
00315 
00316         icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
00317 
00318         right += icoeff * filter->buffer [data_index] ;
00319 
00320         filter_index -= increment ;
00321         data_index = data_index - 1 ;
00322         }
00323     while (filter_index > MAKE_INCREMENT_T (0)) ;
00324 
00325     return (left + right) ;
00326 } /* calc_output_single */
00327 
00328 static int
00329 sinc_mono_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
00330 {   SINC_FILTER *filter ;
00331     double      input_index, src_ratio, count, float_increment, terminate, rem ;
00332     increment_t increment, start_filter_index ;
00333     int         half_filter_chan_len, samples_in_hand ;
00334 
00335     if (psrc->private_data == NULL)
00336         return SRC_ERR_NO_PRIVATE ;
00337 
00338     filter = (SINC_FILTER*) psrc->private_data ;
00339 
00340     /* If there is not a problem, this will be optimised out. */
00341     if (sizeof (filter->buffer [0]) != sizeof (data->data_in [0]))
00342         return SRC_ERR_SIZE_INCOMPATIBILITY ;
00343 
00344     filter->in_count = data->input_frames * filter->channels ;
00345     filter->out_count = data->output_frames * filter->channels ;
00346     filter->in_used = filter->out_gen = 0 ;
00347 
00348     src_ratio = psrc->last_ratio ;
00349 
00350     /* Check the sample rate ratio wrt the buffer len. */
00351     count = (filter->coeff_half_len + 2.0) / filter->index_inc ;
00352     if (MIN (psrc->last_ratio, data->src_ratio) < 1.0)
00353         count /= MIN (psrc->last_ratio, data->src_ratio) ;
00354 
00355     /* Maximum coefficientson either side of center point. */
00356     half_filter_chan_len = filter->channels * (lrint (count) + 1) ;
00357 
00358     input_index = psrc->last_position ;
00359     float_increment = filter->index_inc ;
00360 
00361     rem = fmod_one (input_index) ;
00362     filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
00363     input_index = rem ;
00364 
00365     terminate = 1.0 / src_ratio + 1e-20 ;
00366 
00367     /* Main processing loop. */
00368     while (filter->out_gen < filter->out_count)
00369     {
00370         /* Need to reload buffer? */
00371         samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
00372 
00373         if (samples_in_hand <= half_filter_chan_len)
00374         {   if ((psrc->error = prepare_data (filter, data, half_filter_chan_len)) != 0)
00375                 return psrc->error ;
00376 
00377             samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
00378             if (samples_in_hand <= half_filter_chan_len)
00379                 break ;
00380             } ;
00381 
00382         /* This is the termination condition. */
00383         if (filter->b_real_end >= 0)
00384         {   if (filter->b_current + input_index + terminate >= filter->b_real_end)
00385                 break ;
00386             } ;
00387 
00388         if (filter->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > 1e-10)
00389             src_ratio = psrc->last_ratio + filter->out_gen * (data->src_ratio - psrc->last_ratio) / filter->out_count ;
00390 
00391         float_increment = filter->index_inc * 1.0 ;
00392         if (src_ratio < 1.0)
00393             float_increment = filter->index_inc * src_ratio ;
00394 
00395         increment = double_to_fp (float_increment) ;
00396 
00397         start_filter_index = double_to_fp (input_index * float_increment) ;
00398 
00399         data->data_out [filter->out_gen] = (float) ((float_increment / filter->index_inc) *
00400                                         calc_output_single (filter, increment, start_filter_index)) ;
00401         filter->out_gen ++ ;
00402 
00403         /* Figure out the next index. */
00404         input_index += 1.0 / src_ratio ;
00405         rem = fmod_one (input_index) ;
00406 
00407         filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
00408         input_index = rem ;
00409         } ;
00410 
00411     psrc->last_position = input_index ;
00412 
00413     /* Save current ratio rather then target ratio. */
00414     psrc->last_ratio = src_ratio ;
00415 
00416     data->input_frames_used = filter->in_used / filter->channels ;
00417     data->output_frames_gen = filter->out_gen / filter->channels ;
00418 
00419     return SRC_ERR_NO_ERROR ;
00420 } /* sinc_mono_vari_process */
00421 
00422 static inline void
00423 calc_output_stereo (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index, double scale, float * output)
00424 {   double      fraction, left [2], right [2], icoeff ;
00425     increment_t filter_index, max_filter_index ;
00426     int         data_index, coeff_count, indx ;
00427 
00428     /* Convert input parameters into fixed point. */
00429     max_filter_index = int_to_fp (filter->coeff_half_len) ;
00430 
00431     /* First apply the left half of the filter. */
00432     filter_index = start_filter_index ;
00433     coeff_count = (max_filter_index - filter_index) / increment ;
00434     filter_index = filter_index + coeff_count * increment ;
00435     data_index = filter->b_current - filter->channels * coeff_count ;
00436 
00437     left [0] = left [1] = 0.0 ;
00438     do
00439     {   fraction = fp_to_double (filter_index) ;
00440         indx = fp_to_int (filter_index) ;
00441 
00442         icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
00443 
00444         left [0] += icoeff * filter->buffer [data_index] ;
00445         left [1] += icoeff * filter->buffer [data_index + 1] ;
00446 
00447         filter_index -= increment ;
00448         data_index = data_index + 2 ;
00449         }
00450     while (filter_index >= MAKE_INCREMENT_T (0)) ;
00451 
00452     /* Now apply the right half of the filter. */
00453     filter_index = increment - start_filter_index ;
00454     coeff_count = (max_filter_index - filter_index) / increment ;
00455     filter_index = filter_index + coeff_count * increment ;
00456     data_index = filter->b_current + filter->channels * (1 + coeff_count) ;
00457 
00458     right [0] = right [1] = 0.0 ;
00459     do
00460     {   fraction = fp_to_double (filter_index) ;
00461         indx = fp_to_int (filter_index) ;
00462 
00463         icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
00464 
00465         right [0] += icoeff * filter->buffer [data_index] ;
00466         right [1] += icoeff * filter->buffer [data_index + 1] ;
00467 
00468         filter_index -= increment ;
00469         data_index = data_index - 2 ;
00470         }
00471     while (filter_index > MAKE_INCREMENT_T (0)) ;
00472 
00473     output [0] = scale * (left [0] + right [0]) ;
00474     output [1] = scale * (left [1] + right [1]) ;
00475 } /* calc_output_stereo */
00476 
00477 static int
00478 sinc_stereo_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
00479 {   SINC_FILTER *filter ;
00480     double      input_index, src_ratio, count, float_increment, terminate, rem ;
00481     increment_t increment, start_filter_index ;
00482     int         half_filter_chan_len, samples_in_hand ;
00483 
00484     if (psrc->private_data == NULL)
00485         return SRC_ERR_NO_PRIVATE ;
00486 
00487     filter = (SINC_FILTER*) psrc->private_data ;
00488 
00489     /* If there is not a problem, this will be optimised out. */
00490     if (sizeof (filter->buffer [0]) != sizeof (data->data_in [0]))
00491         return SRC_ERR_SIZE_INCOMPATIBILITY ;
00492 
00493     filter->in_count = data->input_frames * filter->channels ;
00494     filter->out_count = data->output_frames * filter->channels ;
00495     filter->in_used = filter->out_gen = 0 ;
00496 
00497     src_ratio = psrc->last_ratio ;
00498 
00499     /* Check the sample rate ratio wrt the buffer len. */
00500     count = (filter->coeff_half_len + 2.0) / filter->index_inc ;
00501     if (MIN (psrc->last_ratio, data->src_ratio) < 1.0)
00502         count /= MIN (psrc->last_ratio, data->src_ratio) ;
00503 
00504     /* Maximum coefficientson either side of center point. */
00505     half_filter_chan_len = filter->channels * (lrint (count) + 1) ;
00506 
00507     input_index = psrc->last_position ;
00508     float_increment = filter->index_inc ;
00509 
00510     rem = fmod_one (input_index) ;
00511     filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
00512     input_index = rem ;
00513 
00514     terminate = 1.0 / src_ratio + 1e-20 ;
00515 
00516     /* Main processing loop. */
00517     while (filter->out_gen < filter->out_count)
00518     {
00519         /* Need to reload buffer? */
00520         samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
00521 
00522         if (samples_in_hand <= half_filter_chan_len)
00523         {   if ((psrc->error = prepare_data (filter, data, half_filter_chan_len)) != 0)
00524                 return psrc->error ;
00525 
00526             samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
00527             if (samples_in_hand <= half_filter_chan_len)
00528                 break ;
00529             } ;
00530 
00531         /* This is the termination condition. */
00532         if (filter->b_real_end >= 0)
00533         {   if (filter->b_current + input_index + terminate >= filter->b_real_end)
00534                 break ;
00535             } ;
00536 
00537         if (filter->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > 1e-10)
00538             src_ratio = psrc->last_ratio + filter->out_gen * (data->src_ratio - psrc->last_ratio) / filter->out_count ;
00539 
00540         float_increment = filter->index_inc * 1.0 ;
00541         if (src_ratio < 1.0)
00542             float_increment = filter->index_inc * src_ratio ;
00543 
00544         increment = double_to_fp (float_increment) ;
00545 
00546         start_filter_index = double_to_fp (input_index * float_increment) ;
00547 
00548         calc_output_stereo (filter, increment, start_filter_index, float_increment / filter->index_inc, data->data_out + filter->out_gen) ;
00549         filter->out_gen += 2 ;
00550 
00551         /* Figure out the next index. */
00552         input_index += 1.0 / src_ratio ;
00553         rem = fmod_one (input_index) ;
00554 
00555         filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
00556         input_index = rem ;
00557         } ;
00558 
00559     psrc->last_position = input_index ;
00560 
00561     /* Save current ratio rather then target ratio. */
00562     psrc->last_ratio = src_ratio ;
00563 
00564     data->input_frames_used = filter->in_used / filter->channels ;
00565     data->output_frames_gen = filter->out_gen / filter->channels ;
00566 
00567     return SRC_ERR_NO_ERROR ;
00568 } /* sinc_stereo_vari_process */
00569 
00570 static inline void
00571 calc_output_quad (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index, double scale, float * output)
00572 {   double      fraction, left [4], right [4], icoeff ;
00573     increment_t filter_index, max_filter_index ;
00574     int         data_index, coeff_count, indx ;
00575 
00576     /* Convert input parameters into fixed point. */
00577     max_filter_index = int_to_fp (filter->coeff_half_len) ;
00578 
00579     /* First apply the left half of the filter. */
00580     filter_index = start_filter_index ;
00581     coeff_count = (max_filter_index - filter_index) / increment ;
00582     filter_index = filter_index + coeff_count * increment ;
00583     data_index = filter->b_current - filter->channels * coeff_count ;
00584 
00585     left [0] = left [1] = left [2] = left [3] = 0.0 ;
00586     do
00587     {   fraction = fp_to_double (filter_index) ;
00588         indx = fp_to_int (filter_index) ;
00589 
00590         icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
00591 
00592         left [0] += icoeff * filter->buffer [data_index] ;
00593         left [1] += icoeff * filter->buffer [data_index + 1] ;
00594         left [2] += icoeff * filter->buffer [data_index + 2] ;
00595         left [3] += icoeff * filter->buffer [data_index + 3] ;
00596 
00597         filter_index -= increment ;
00598         data_index = data_index + 4 ;
00599         }
00600     while (filter_index >= MAKE_INCREMENT_T (0)) ;
00601 
00602     /* Now apply the right half of the filter. */
00603     filter_index = increment - start_filter_index ;
00604     coeff_count = (max_filter_index - filter_index) / increment ;
00605     filter_index = filter_index + coeff_count * increment ;
00606     data_index = filter->b_current + filter->channels * (1 + coeff_count) ;
00607 
00608     right [0] = right [1] = right [2] = right [3] = 0.0 ;
00609     do
00610     {   fraction = fp_to_double (filter_index) ;
00611         indx = fp_to_int (filter_index) ;
00612 
00613         icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
00614 
00615         right [0] += icoeff * filter->buffer [data_index] ;
00616         right [1] += icoeff * filter->buffer [data_index + 1] ;
00617         right [2] += icoeff * filter->buffer [data_index + 2] ;
00618         right [3] += icoeff * filter->buffer [data_index + 3] ;
00619 
00620         filter_index -= increment ;
00621         data_index = data_index - 4 ;
00622         }
00623     while (filter_index > MAKE_INCREMENT_T (0)) ;
00624 
00625     output [0] = scale * (left [0] + right [0]) ;
00626     output [1] = scale * (left [1] + right [1]) ;
00627     output [2] = scale * (left [2] + right [2]) ;
00628     output [3] = scale * (left [3] + right [3]) ;
00629 } /* calc_output_quad */
00630 
00631 static int
00632 sinc_quad_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
00633 {   SINC_FILTER *filter ;
00634     double      input_index, src_ratio, count, float_increment, terminate, rem ;
00635     increment_t increment, start_filter_index ;
00636     int         half_filter_chan_len, samples_in_hand ;
00637 
00638     if (psrc->private_data == NULL)
00639         return SRC_ERR_NO_PRIVATE ;
00640 
00641     filter = (SINC_FILTER*) psrc->private_data ;
00642 
00643     /* If there is not a problem, this will be optimised out. */
00644     if (sizeof (filter->buffer [0]) != sizeof (data->data_in [0]))
00645         return SRC_ERR_SIZE_INCOMPATIBILITY ;
00646 
00647     filter->in_count = data->input_frames * filter->channels ;
00648     filter->out_count = data->output_frames * filter->channels ;
00649     filter->in_used = filter->out_gen = 0 ;
00650 
00651     src_ratio = psrc->last_ratio ;
00652 
00653     /* Check the sample rate ratio wrt the buffer len. */
00654     count = (filter->coeff_half_len + 2.0) / filter->index_inc ;
00655     if (MIN (psrc->last_ratio, data->src_ratio) < 1.0)
00656         count /= MIN (psrc->last_ratio, data->src_ratio) ;
00657 
00658     /* Maximum coefficientson either side of center point. */
00659     half_filter_chan_len = filter->channels * (lrint (count) + 1) ;
00660 
00661     input_index = psrc->last_position ;
00662     float_increment = filter->index_inc ;
00663 
00664     rem = fmod_one (input_index) ;
00665     filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
00666     input_index = rem ;
00667 
00668     terminate = 1.0 / src_ratio + 1e-20 ;
00669 
00670     /* Main processing loop. */
00671     while (filter->out_gen < filter->out_count)
00672     {
00673         /* Need to reload buffer? */
00674         samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
00675 
00676         if (samples_in_hand <= half_filter_chan_len)
00677         {   if ((psrc->error = prepare_data (filter, data, half_filter_chan_len)) != 0)
00678                 return psrc->error ;
00679 
00680             samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
00681             if (samples_in_hand <= half_filter_chan_len)
00682                 break ;
00683             } ;
00684 
00685         /* This is the termination condition. */
00686         if (filter->b_real_end >= 0)
00687         {   if (filter->b_current + input_index + terminate >= filter->b_real_end)
00688                 break ;
00689             } ;
00690 
00691         if (filter->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > 1e-10)
00692             src_ratio = psrc->last_ratio + filter->out_gen * (data->src_ratio - psrc->last_ratio) / filter->out_count ;
00693 
00694         float_increment = filter->index_inc * 1.0 ;
00695         if (src_ratio < 1.0)
00696             float_increment = filter->index_inc * src_ratio ;
00697 
00698         increment = double_to_fp (float_increment) ;
00699 
00700         start_filter_index = double_to_fp (input_index * float_increment) ;
00701 
00702         calc_output_quad (filter, increment, start_filter_index, float_increment / filter->index_inc, data->data_out + filter->out_gen) ;
00703         filter->out_gen += 4 ;
00704 
00705         /* Figure out the next index. */
00706         input_index += 1.0 / src_ratio ;
00707         rem = fmod_one (input_index) ;
00708 
00709         filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
00710         input_index = rem ;
00711         } ;
00712 
00713     psrc->last_position = input_index ;
00714 
00715     /* Save current ratio rather then target ratio. */
00716     psrc->last_ratio = src_ratio ;
00717 
00718     data->input_frames_used = filter->in_used / filter->channels ;
00719     data->output_frames_gen = filter->out_gen / filter->channels ;
00720 
00721     return SRC_ERR_NO_ERROR ;
00722 } /* sinc_quad_vari_process */
00723 
00724 static inline void
00725 calc_output_hex (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index, double scale, float * output)
00726 {   double      fraction, left [6], right [6], icoeff ;
00727     increment_t filter_index, max_filter_index ;
00728     int         data_index, coeff_count, indx ;
00729 
00730     /* Convert input parameters into fixed point. */
00731     max_filter_index = int_to_fp (filter->coeff_half_len) ;
00732 
00733     /* First apply the left half of the filter. */
00734     filter_index = start_filter_index ;
00735     coeff_count = (max_filter_index - filter_index) / increment ;
00736     filter_index = filter_index + coeff_count * increment ;
00737     data_index = filter->b_current - filter->channels * coeff_count ;
00738 
00739     left [0] = left [1] = left [2] = left [3] = left [4] = left [5] = 0.0 ;
00740     do
00741     {   fraction = fp_to_double (filter_index) ;
00742         indx = fp_to_int (filter_index) ;
00743 
00744         icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
00745 
00746         left [0] += icoeff * filter->buffer [data_index] ;
00747         left [1] += icoeff * filter->buffer [data_index + 1] ;
00748         left [2] += icoeff * filter->buffer [data_index + 2] ;
00749         left [3] += icoeff * filter->buffer [data_index + 3] ;
00750         left [4] += icoeff * filter->buffer [data_index + 4] ;
00751         left [5] += icoeff * filter->buffer [data_index + 5] ;
00752 
00753         filter_index -= increment ;
00754         data_index = data_index + 6 ;
00755         }
00756     while (filter_index >= MAKE_INCREMENT_T (0)) ;
00757 
00758     /* Now apply the right half of the filter. */
00759     filter_index = increment - start_filter_index ;
00760     coeff_count = (max_filter_index - filter_index) / increment ;
00761     filter_index = filter_index + coeff_count * increment ;
00762     data_index = filter->b_current + filter->channels * (1 + coeff_count) ;
00763 
00764     right [0] = right [1] = right [2] = right [3] = right [4] = right [5] = 0.0 ;
00765     do
00766     {   fraction = fp_to_double (filter_index) ;
00767         indx = fp_to_int (filter_index) ;
00768 
00769         icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
00770 
00771         right [0] += icoeff * filter->buffer [data_index] ;
00772         right [1] += icoeff * filter->buffer [data_index + 1] ;
00773         right [2] += icoeff * filter->buffer [data_index + 2] ;
00774         right [3] += icoeff * filter->buffer [data_index + 3] ;
00775         right [4] += icoeff * filter->buffer [data_index + 4] ;
00776         right [5] += icoeff * filter->buffer [data_index + 5] ;
00777 
00778         filter_index -= increment ;
00779         data_index = data_index - 6 ;
00780         }
00781     while (filter_index > MAKE_INCREMENT_T (0)) ;
00782 
00783     output [0] = scale * (left [0] + right [0]) ;
00784     output [1] = scale * (left [1] + right [1]) ;
00785     output [2] = scale * (left [2] + right [2]) ;
00786     output [3] = scale * (left [3] + right [3]) ;
00787     output [4] = scale * (left [4] + right [4]) ;
00788     output [5] = scale * (left [5] + right [5]) ;
00789 } /* calc_output_hex */
00790 
00791 static int
00792 sinc_hex_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
00793 {   SINC_FILTER *filter ;
00794     double      input_index, src_ratio, count, float_increment, terminate, rem ;
00795     increment_t increment, start_filter_index ;
00796     int         half_filter_chan_len, samples_in_hand ;
00797 
00798     if (psrc->private_data == NULL)
00799         return SRC_ERR_NO_PRIVATE ;
00800 
00801     filter = (SINC_FILTER*) psrc->private_data ;
00802 
00803     /* If there is not a problem, this will be optimised out. */
00804     if (sizeof (filter->buffer [0]) != sizeof (data->data_in [0]))
00805         return SRC_ERR_SIZE_INCOMPATIBILITY ;
00806 
00807     filter->in_count = data->input_frames * filter->channels ;
00808     filter->out_count = data->output_frames * filter->channels ;
00809     filter->in_used = filter->out_gen = 0 ;
00810 
00811     src_ratio = psrc->last_ratio ;
00812 
00813     /* Check the sample rate ratio wrt the buffer len. */
00814     count = (filter->coeff_half_len + 2.0) / filter->index_inc ;
00815     if (MIN (psrc->last_ratio, data->src_ratio) < 1.0)
00816         count /= MIN (psrc->last_ratio, data->src_ratio) ;
00817 
00818     /* Maximum coefficientson either side of center point. */
00819     half_filter_chan_len = filter->channels * (lrint (count) + 1) ;
00820 
00821     input_index = psrc->last_position ;
00822     float_increment = filter->index_inc ;
00823 
00824     rem = fmod_one (input_index) ;
00825     filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
00826     input_index = rem ;
00827 
00828     terminate = 1.0 / src_ratio + 1e-20 ;
00829 
00830     /* Main processing loop. */
00831     while (filter->out_gen < filter->out_count)
00832     {
00833         /* Need to reload buffer? */
00834         samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
00835 
00836         if (samples_in_hand <= half_filter_chan_len)
00837         {   if ((psrc->error = prepare_data (filter, data, half_filter_chan_len)) != 0)
00838                 return psrc->error ;
00839 
00840             samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
00841             if (samples_in_hand <= half_filter_chan_len)
00842                 break ;
00843             } ;
00844 
00845         /* This is the termination condition. */
00846         if (filter->b_real_end >= 0)
00847         {   if (filter->b_current + input_index + terminate >= filter->b_real_end)
00848                 break ;
00849             } ;
00850 
00851         if (filter->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > 1e-10)
00852             src_ratio = psrc->last_ratio + filter->out_gen * (data->src_ratio - psrc->last_ratio) / filter->out_count ;
00853 
00854         float_increment = filter->index_inc * 1.0 ;
00855         if (src_ratio < 1.0)
00856             float_increment = filter->index_inc * src_ratio ;
00857 
00858         increment = double_to_fp (float_increment) ;
00859 
00860         start_filter_index = double_to_fp (input_index * float_increment) ;
00861 
00862         calc_output_hex (filter, increment, start_filter_index, float_increment / filter->index_inc, data->data_out + filter->out_gen) ;
00863         filter->out_gen += 6 ;
00864 
00865         /* Figure out the next index. */
00866         input_index += 1.0 / src_ratio ;
00867         rem = fmod_one (input_index) ;
00868 
00869         filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
00870         input_index = rem ;
00871         } ;
00872 
00873     psrc->last_position = input_index ;
00874 
00875     /* Save current ratio rather then target ratio. */
00876     psrc->last_ratio = src_ratio ;
00877 
00878     data->input_frames_used = filter->in_used / filter->channels ;
00879     data->output_frames_gen = filter->out_gen / filter->channels ;
00880 
00881     return SRC_ERR_NO_ERROR ;
00882 } /* sinc_hex_vari_process */
00883 
00884 static inline void
00885 calc_output_multi (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index, int channels, double scale, float * output)
00886 {   double      fraction, icoeff ;
00887     /* The following line is 1999 ISO Standard C. If your compiler complains, get a better compiler. */
00888     double      *left, *right ;
00889     increment_t filter_index, max_filter_index ;
00890     int         data_index, coeff_count, indx, ch ;
00891 
00892     left = filter->left_calc ;
00893     right = filter->right_calc ;
00894 
00895     /* Convert input parameters into fixed point. */
00896     max_filter_index = int_to_fp (filter->coeff_half_len) ;
00897 
00898     /* First apply the left half of the filter. */
00899     filter_index = start_filter_index ;
00900     coeff_count = (max_filter_index - filter_index) / increment ;
00901     filter_index = filter_index + coeff_count * increment ;
00902     data_index = filter->b_current - channels * coeff_count ;
00903 
00904     memset (left, 0, sizeof (left [0]) * channels) ;
00905 
00906     do
00907     {   fraction = fp_to_double (filter_index) ;
00908         indx = fp_to_int (filter_index) ;
00909 
00910         icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
00911 
00912         /*
00913         **  Duff's Device.
00914         **  See : http://en.wikipedia.org/wiki/Duff's_device
00915         */
00916         ch = channels ;
00917         do
00918         {
00919             switch (ch % 8)
00920             {   default :
00921                     ch -- ;
00922                     left [ch] += icoeff * filter->buffer [data_index + ch] ;
00923                 case 7 :
00924                     ch -- ;
00925                     left [ch] += icoeff * filter->buffer [data_index + ch] ;
00926                 case 6 :
00927                     ch -- ;
00928                     left [ch] += icoeff * filter->buffer [data_index + ch] ;
00929                 case 5 :
00930                     ch -- ;
00931                     left [ch] += icoeff * filter->buffer [data_index + ch] ;
00932                 case 4 :
00933                     ch -- ;
00934                     left [ch] += icoeff * filter->buffer [data_index + ch] ;
00935                 case 3 :
00936                     ch -- ;
00937                     left [ch] += icoeff * filter->buffer [data_index + ch] ;
00938                 case 2 :
00939                     ch -- ;
00940                     left [ch] += icoeff * filter->buffer [data_index + ch] ;
00941                 case 1 :
00942                     ch -- ;
00943                     left [ch] += icoeff * filter->buffer [data_index + ch] ;
00944                 } ;
00945             }
00946         while (ch > 0) ;
00947 
00948         filter_index -= increment ;
00949         data_index = data_index + channels ;
00950         }
00951     while (filter_index >= MAKE_INCREMENT_T (0)) ;
00952 
00953     /* Now apply the right half of the filter. */
00954     filter_index = increment - start_filter_index ;
00955     coeff_count = (max_filter_index - filter_index) / increment ;
00956     filter_index = filter_index + coeff_count * increment ;
00957     data_index = filter->b_current + channels * (1 + coeff_count) ;
00958 
00959     memset (right, 0, sizeof (right [0]) * channels) ;
00960     do
00961     {   fraction = fp_to_double (filter_index) ;
00962         indx = fp_to_int (filter_index) ;
00963 
00964         icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
00965 
00966         ch = channels ;
00967         do
00968         {
00969             switch (ch % 8)
00970             {   default :
00971                     ch -- ;
00972                     right [ch] += icoeff * filter->buffer [data_index + ch] ;
00973                 case 7 :
00974                     ch -- ;
00975                     right [ch] += icoeff * filter->buffer [data_index + ch] ;
00976                 case 6 :
00977                     ch -- ;
00978                     right [ch] += icoeff * filter->buffer [data_index + ch] ;
00979                 case 5 :
00980                     ch -- ;
00981                     right [ch] += icoeff * filter->buffer [data_index + ch] ;
00982                 case 4 :
00983                     ch -- ;
00984                     right [ch] += icoeff * filter->buffer [data_index + ch] ;
00985                 case 3 :
00986                     ch -- ;
00987                     right [ch] += icoeff * filter->buffer [data_index + ch] ;
00988                 case 2 :
00989                     ch -- ;
00990                     right [ch] += icoeff * filter->buffer [data_index + ch] ;
00991                 case 1 :
00992                     ch -- ;
00993                     right [ch] += icoeff * filter->buffer [data_index + ch] ;
00994                 } ;
00995             }
00996         while (ch > 0) ;
00997 
00998         filter_index -= increment ;
00999         data_index = data_index - channels ;
01000         }
01001     while (filter_index > MAKE_INCREMENT_T (0)) ;
01002 
01003     ch = channels ;
01004     do
01005     {
01006         switch (ch % 8)
01007         {   default :
01008                 ch -- ;
01009                 output [ch] = scale * (left [ch] + right [ch]) ;
01010             case 7 :
01011                 ch -- ;
01012                 output [ch] = scale * (left [ch] + right [ch]) ;
01013             case 6 :
01014                 ch -- ;
01015                 output [ch] = scale * (left [ch] + right [ch]) ;
01016             case 5 :
01017                 ch -- ;
01018                 output [ch] = scale * (left [ch] + right [ch]) ;
01019             case 4 :
01020                 ch -- ;
01021                 output [ch] = scale * (left [ch] + right [ch]) ;
01022             case 3 :
01023                 ch -- ;
01024                 output [ch] = scale * (left [ch] + right [ch]) ;
01025             case 2 :
01026                 ch -- ;
01027                 output [ch] = scale * (left [ch] + right [ch]) ;
01028             case 1 :
01029                 ch -- ;
01030                 output [ch] = scale * (left [ch] + right [ch]) ;
01031             } ;
01032         }
01033     while (ch > 0) ;
01034 
01035     return ;
01036 } /* calc_output_multi */
01037 
01038 static int
01039 sinc_multichan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
01040 {   SINC_FILTER *filter ;
01041     double      input_index, src_ratio, count, float_increment, terminate, rem ;
01042     increment_t increment, start_filter_index ;
01043     int         half_filter_chan_len, samples_in_hand ;
01044 
01045     if (psrc->private_data == NULL)
01046         return SRC_ERR_NO_PRIVATE ;
01047 
01048     filter = (SINC_FILTER*) psrc->private_data ;
01049 
01050     /* If there is not a problem, this will be optimised out. */
01051     if (sizeof (filter->buffer [0]) != sizeof (data->data_in [0]))
01052         return SRC_ERR_SIZE_INCOMPATIBILITY ;
01053 
01054     filter->in_count = data->input_frames * filter->channels ;
01055     filter->out_count = data->output_frames * filter->channels ;
01056     filter->in_used = filter->out_gen = 0 ;
01057 
01058     src_ratio = psrc->last_ratio ;
01059 
01060     /* Check the sample rate ratio wrt the buffer len. */
01061     count = (filter->coeff_half_len + 2.0) / filter->index_inc ;
01062     if (MIN (psrc->last_ratio, data->src_ratio) < 1.0)
01063         count /= MIN (psrc->last_ratio, data->src_ratio) ;
01064 
01065     /* Maximum coefficientson either side of center point. */
01066     half_filter_chan_len = filter->channels * (lrint (count) + 1) ;
01067 
01068     input_index = psrc->last_position ;
01069     float_increment = filter->index_inc ;
01070 
01071     rem = fmod_one (input_index) ;
01072     filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
01073     input_index = rem ;
01074 
01075     terminate = 1.0 / src_ratio + 1e-20 ;
01076 
01077     /* Main processing loop. */
01078     while (filter->out_gen < filter->out_count)
01079     {
01080         /* Need to reload buffer? */
01081         samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
01082 
01083         if (samples_in_hand <= half_filter_chan_len)
01084         {   if ((psrc->error = prepare_data (filter, data, half_filter_chan_len)) != 0)
01085                 return psrc->error ;
01086 
01087             samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
01088             if (samples_in_hand <= half_filter_chan_len)
01089                 break ;
01090             } ;
01091 
01092         /* This is the termination condition. */
01093         if (filter->b_real_end >= 0)
01094         {   if (filter->b_current + input_index + terminate >= filter->b_real_end)
01095                 break ;
01096             } ;
01097 
01098         if (filter->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > 1e-10)
01099             src_ratio = psrc->last_ratio + filter->out_gen * (data->src_ratio - psrc->last_ratio) / filter->out_count ;
01100 
01101         float_increment = filter->index_inc * 1.0 ;
01102         if (src_ratio < 1.0)
01103             float_increment = filter->index_inc * src_ratio ;
01104 
01105         increment = double_to_fp (float_increment) ;
01106 
01107         start_filter_index = double_to_fp (input_index * float_increment) ;
01108 
01109         calc_output_multi (filter, increment, start_filter_index, filter->channels, float_increment / filter->index_inc, data->data_out + filter->out_gen) ;
01110         filter->out_gen += psrc->channels ;
01111 
01112         /* Figure out the next index. */
01113         input_index += 1.0 / src_ratio ;
01114         rem = fmod_one (input_index) ;
01115 
01116         filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
01117         input_index = rem ;
01118         } ;
01119 
01120     psrc->last_position = input_index ;
01121 
01122     /* Save current ratio rather then target ratio. */
01123     psrc->last_ratio = src_ratio ;
01124 
01125     data->input_frames_used = filter->in_used / filter->channels ;
01126     data->output_frames_gen = filter->out_gen / filter->channels ;
01127 
01128     return SRC_ERR_NO_ERROR ;
01129 } /* sinc_multichan_vari_process */
01130 
01131 /*----------------------------------------------------------------------------------------
01132 */
01133 
01134 static int
01135 prepare_data (SINC_FILTER *filter, SRC_DATA *data, int half_filter_chan_len)
01136 {   int len = 0 ;
01137 
01138     if (filter->b_real_end >= 0)
01139         return 0 ;  /* Should be terminating. Just return. */
01140 
01141     if (filter->b_current == 0)
01142     {   /* Initial state. Set up zeros at the start of the buffer and
01143         ** then load new data after that.
01144         */
01145         len = filter->b_len - 2 * half_filter_chan_len ;
01146 
01147         filter->b_current = filter->b_end = half_filter_chan_len ;
01148         }
01149     else if (filter->b_end + half_filter_chan_len + filter->channels < filter->b_len)
01150     {   /*  Load data at current end position. */
01151         len = MAX (filter->b_len - filter->b_current - half_filter_chan_len, 0) ;
01152         }
01153     else
01154     {   /* Move data at end of buffer back to the start of the buffer. */
01155         len = filter->b_end - filter->b_current ;
01156         memmove (filter->buffer, filter->buffer + filter->b_current - half_filter_chan_len,
01157                         (half_filter_chan_len + len) * sizeof (filter->buffer [0])) ;
01158 
01159         filter->b_current = half_filter_chan_len ;
01160         filter->b_end = filter->b_current + len ;
01161 
01162         /* Now load data at current end of buffer. */
01163         len = MAX (filter->b_len - filter->b_current - half_filter_chan_len, 0) ;
01164         } ;
01165 
01166     len = MIN (filter->in_count - filter->in_used, len) ;
01167     len -= (len % filter->channels) ;
01168 
01169     if (len < 0 || filter->b_end + len > filter->b_len)
01170         return SRC_ERR_SINC_PREPARE_DATA_BAD_LEN ;
01171 
01172     memcpy (filter->buffer + filter->b_end, data->data_in + filter->in_used,
01173                         len * sizeof (filter->buffer [0])) ;
01174 
01175     filter->b_end += len ;
01176     filter->in_used += len ;
01177 
01178     if (filter->in_used == filter->in_count &&
01179             filter->b_end - filter->b_current < 2 * half_filter_chan_len && data->end_of_input)
01180     {   /* Handle the case where all data in the current buffer has been
01181         ** consumed and this is the last buffer.
01182         */
01183 
01184         if (filter->b_len - filter->b_end < half_filter_chan_len + 5)
01185         {   /* If necessary, move data down to the start of the buffer. */
01186             len = filter->b_end - filter->b_current ;
01187             memmove (filter->buffer, filter->buffer + filter->b_current - half_filter_chan_len,
01188                             (half_filter_chan_len + len) * sizeof (filter->buffer [0])) ;
01189 
01190             filter->b_current = half_filter_chan_len ;
01191             filter->b_end = filter->b_current + len ;
01192             } ;
01193 
01194         filter->b_real_end = filter->b_end ;
01195         len = half_filter_chan_len + 5 ;
01196 
01197         if (len < 0 || filter->b_end + len > filter->b_len)
01198             len = filter->b_len - filter->b_end ;
01199 
01200         memset (filter->buffer + filter->b_end, 0, len * sizeof (filter->buffer [0])) ;
01201         filter->b_end += len ;
01202         } ;
01203 
01204     return 0 ;
01205 } /* prepare_data */
01206 
01207 

Generated on Sat May 26 2012 04:33:05 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.