diff options
Diffstat (limited to 'apps/codecs/libspeex/resample.c')
-rw-r--r-- | apps/codecs/libspeex/resample.c | 49 |
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 | ||
45 | TODO 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 | ||
998 | int 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) | 1005 | int 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; |