summaryrefslogtreecommitdiff
path: root/apps/codecs/libspeex/resample.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs/libspeex/resample.c')
-rw-r--r--apps/codecs/libspeex/resample.c49
1 files changed, 35 insertions, 14 deletions
diff --git a/apps/codecs/libspeex/resample.c b/apps/codecs/libspeex/resample.c
index 2dfe2dd5f3..51270c572d 100644
--- a/apps/codecs/libspeex/resample.c
+++ b/apps/codecs/libspeex/resample.c
@@ -37,17 +37,23 @@
37 - Low memory requirement 37 - Low memory requirement
38 - Good *perceptual* quality (and not best SNR) 38 - Good *perceptual* quality (and not best SNR)
39 39
40 The code is working, but it's in a very early stage, so it may have 40 Warning: This resampler is relatively new. Although I think I got rid of
41 artifacts, noise or subliminal messages from satan. Also, the API 41 all the major bugs and I don't expect the API to change anymore, there
42 isn't stable and I can actually promise that I *will* change the API 42 may be something I've missed. So use with caution.
43 some time in the future.
44 43
45TODO list: 44 This algorithm is based on this original resampling algorithm:
46 - Variable calculation resolution depending on quality setting 45 Smith, Julius O. Digital Audio Resampling Home Page
47 - Single vs double in float mode 46 Center for Computer Research in Music and Acoustics (CCRMA),
48 - 16-bit vs 32-bit (sinc only) in fixed-point mode 47 Stanford University, 2007.
49 - Make sure the filter update works even when changing params 48 Web published at http://www-ccrma.stanford.edu/~jos/resample/.
50 after only a few samples procesed 49
50 There is one main difference, though. This resampler uses cubic
51 interpolation instead of linear interpolation in the above paper. This
52 makes the table much smaller and makes it possible to compute that table
53 on a per-stream basis. In turn, being able to tweak the table for each
54 stream makes it possible to both reduce complexity on simple ratios
55 (e.g. 2/3), and get rid of the rounding operations in the inner loop.
56 The latter both reduces CPU time and makes the algorithm more SIMD-friendly.
51*/ 57*/
52 58
53#ifdef HAVE_CONFIG_H 59#ifdef HAVE_CONFIG_H
@@ -84,6 +90,7 @@ static void speex_free (void *ptr) {free(ptr);}
84#define OVERSAMPLE 8 90#define OVERSAMPLE 8
85 91
86#define IMAX(a,b) ((a) > (b) ? (a) : (b)) 92#define IMAX(a,b) ((a) > (b) ? (a) : (b))
93#define IMIN(a,b) ((a) < (b) ? (a) : (b))
87 94
88#ifndef NULL 95#ifndef NULL
89#define NULL 0 96#define NULL 0
@@ -576,10 +583,10 @@ static void update_filter(SpeexResamplerState *st)
576 } 583 }
577 for (i=0;i<st->den_rate;i++) 584 for (i=0;i<st->den_rate;i++)
578 { 585 {
579 spx_uint32_t j; 586 spx_int32_t j;
580 for (j=0;j<st->filt_len;j++) 587 for (j=0;j<st->filt_len;j++)
581 { 588 {
582 st->sinc_table[i*st->filt_len+j] = sinc(st->cutoff,((j-st->filt_len/2+1)-((float)i)/st->den_rate), st->filt_len, quality_map[st->quality].window_func); 589 st->sinc_table[i*st->filt_len+j] = sinc(st->cutoff,((j-(spx_int32_t)st->filt_len/2+1)-((float)i)/st->den_rate), st->filt_len, quality_map[st->quality].window_func);
583 } 590 }
584 } 591 }
585#ifdef FIXED_POINT 592#ifdef FIXED_POINT
@@ -997,16 +1004,19 @@ void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_rate, sp
997 1004
998int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate) 1005int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate)
999{ 1006{
1000 int fact; 1007 spx_uint32_t fact;
1008 spx_uint32_t old_den;
1009 spx_uint32_t i;
1001 if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den) 1010 if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den)
1002 return RESAMPLER_ERR_SUCCESS; 1011 return RESAMPLER_ERR_SUCCESS;
1003 1012
1013 old_den = st->den_rate;
1004 st->in_rate = in_rate; 1014 st->in_rate = in_rate;
1005 st->out_rate = out_rate; 1015 st->out_rate = out_rate;
1006 st->num_rate = ratio_num; 1016 st->num_rate = ratio_num;
1007 st->den_rate = ratio_den; 1017 st->den_rate = ratio_den;
1008 /* FIXME: This is terribly inefficient, but who cares (at least for now)? */ 1018 /* FIXME: This is terribly inefficient, but who cares (at least for now)? */
1009 for (fact=2;fact<=sqrt(IMAX(in_rate, out_rate));fact++) 1019 for (fact=2;fact<=IMIN(st->num_rate, st->den_rate);fact++)
1010 { 1020 {
1011 while ((st->num_rate % fact == 0) && (st->den_rate % fact == 0)) 1021 while ((st->num_rate % fact == 0) && (st->den_rate % fact == 0))
1012 { 1022 {
@@ -1015,6 +1025,17 @@ int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t ratio_nu
1015 } 1025 }
1016 } 1026 }
1017 1027
1028 if (old_den > 0)
1029 {
1030 for (i=0;i<st->nb_channels;i++)
1031 {
1032 st->samp_frac_num[i]=st->samp_frac_num[i]*st->den_rate/old_den;
1033 /* Safety net */
1034 if (st->samp_frac_num[i] >= st->den_rate)
1035 st->samp_frac_num[i] = st->den_rate-1;
1036 }
1037 }
1038
1018 if (st->initialised) 1039 if (st->initialised)
1019 update_filter(st); 1040 update_filter(st);
1020 return RESAMPLER_ERR_SUCCESS; 1041 return RESAMPLER_ERR_SUCCESS;