diff options
author | Dan Everton <dan@iocaine.org> | 2007-05-22 09:50:31 +0000 |
---|---|---|
committer | Dan Everton <dan@iocaine.org> | 2007-05-22 09:50:31 +0000 |
commit | df6f2f9a3c88a7a4a8ad0382ee4ee7c9a3ee3256 (patch) | |
tree | d9862e5d04f4014def5911bb4ff8206c85636fb7 /apps/codecs/libspeex/resample.c | |
parent | 8970055ec107a2387eedbb373889d0f540745121 (diff) | |
download | rockbox-df6f2f9a3c88a7a4a8ad0382ee4ee7c9a3ee3256.tar.gz rockbox-df6f2f9a3c88a7a4a8ad0382ee4ee7c9a3ee3256.zip |
Upgrade to libspeex 1.2beta2. Very minor performance increase (0.6% on coldfire).
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13461 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs/libspeex/resample.c')
-rw-r--r-- | apps/codecs/libspeex/resample.c | 380 |
1 files changed, 273 insertions, 107 deletions
diff --git a/apps/codecs/libspeex/resample.c b/apps/codecs/libspeex/resample.c index 22ed21c64a..2dfe2dd5f3 100644 --- a/apps/codecs/libspeex/resample.c +++ b/apps/codecs/libspeex/resample.c | |||
@@ -56,14 +56,16 @@ TODO list: | |||
56 | 56 | ||
57 | #ifdef OUTSIDE_SPEEX | 57 | #ifdef OUTSIDE_SPEEX |
58 | #include <stdlib.h> | 58 | #include <stdlib.h> |
59 | void *speex_alloc (int size) {return calloc(size,1);} | 59 | static void *speex_alloc (int size) {return calloc(size,1);} |
60 | void *speex_realloc (void *ptr, int size) {return realloc(ptr, size);} | 60 | static void *speex_realloc (void *ptr, int size) {return realloc(ptr, size);} |
61 | void speex_free (void *ptr) {free(ptr);} | 61 | static void speex_free (void *ptr) {free(ptr);} |
62 | #include "speex_resampler.h" | 62 | #include "speex_resampler.h" |
63 | #else | 63 | #include "arch.h" |
64 | #else /* OUTSIDE_SPEEX */ | ||
65 | |||
64 | #include "speex/speex_resampler.h" | 66 | #include "speex/speex_resampler.h" |
65 | #include "misc.h" | 67 | #include "misc.h" |
66 | #endif | 68 | #endif /* OUTSIDE_SPEEX */ |
67 | 69 | ||
68 | #include <math.h> | 70 | #include <math.h> |
69 | 71 | ||
@@ -83,34 +85,37 @@ void speex_free (void *ptr) {free(ptr);} | |||
83 | 85 | ||
84 | #define IMAX(a,b) ((a) > (b) ? (a) : (b)) | 86 | #define IMAX(a,b) ((a) > (b) ? (a) : (b)) |
85 | 87 | ||
88 | #ifndef NULL | ||
89 | #define NULL 0 | ||
90 | #endif | ||
86 | 91 | ||
87 | typedef int (*resampler_basic_func)(SpeexResamplerState *, int , const spx_word16_t *, int *, spx_word16_t *, int *); | 92 | typedef int (*resampler_basic_func)(SpeexResamplerState *, spx_uint32_t , const spx_word16_t *, spx_uint32_t *, spx_word16_t *, spx_uint32_t *); |
88 | 93 | ||
89 | struct SpeexResamplerState_ { | 94 | struct SpeexResamplerState_ { |
90 | int in_rate; | 95 | spx_uint32_t in_rate; |
91 | int out_rate; | 96 | spx_uint32_t out_rate; |
92 | int num_rate; | 97 | spx_uint32_t num_rate; |
93 | int den_rate; | 98 | spx_uint32_t den_rate; |
94 | 99 | ||
95 | int quality; | 100 | int quality; |
96 | int nb_channels; | 101 | spx_uint32_t nb_channels; |
97 | int filt_len; | 102 | spx_uint32_t filt_len; |
98 | int mem_alloc_size; | 103 | spx_uint32_t mem_alloc_size; |
99 | int int_advance; | 104 | int int_advance; |
100 | int frac_advance; | 105 | int frac_advance; |
101 | float cutoff; | 106 | float cutoff; |
102 | int oversample; | 107 | spx_uint32_t oversample; |
103 | int initialised; | 108 | int initialised; |
104 | int started; | 109 | int started; |
105 | 110 | ||
106 | /* These are per-channel */ | 111 | /* These are per-channel */ |
107 | int *last_sample; | 112 | spx_int32_t *last_sample; |
108 | int *samp_frac_num; | 113 | spx_uint32_t *samp_frac_num; |
109 | int *magic_samples; | 114 | spx_uint32_t *magic_samples; |
110 | 115 | ||
111 | spx_word16_t *mem; | 116 | spx_word16_t *mem; |
112 | spx_word16_t *sinc_table; | 117 | spx_word16_t *sinc_table; |
113 | int sinc_table_length; | 118 | spx_uint32_t sinc_table_length; |
114 | resampler_basic_func resampler_ptr; | 119 | resampler_basic_func resampler_ptr; |
115 | 120 | ||
116 | int in_stride; | 121 | int in_stride; |
@@ -203,12 +208,12 @@ static const struct QualityMapping quality_map[11] = { | |||
203 | { 32, 4, 0.882f, 0.910f, KAISER6 }, /* Q2 */ /* 82.3% cutoff ( ~60 dB stop) 6 */ | 208 | { 32, 4, 0.882f, 0.910f, KAISER6 }, /* Q2 */ /* 82.3% cutoff ( ~60 dB stop) 6 */ |
204 | { 48, 8, 0.895f, 0.917f, KAISER8 }, /* Q3 */ /* 84.9% cutoff ( ~80 dB stop) 8 */ | 209 | { 48, 8, 0.895f, 0.917f, KAISER8 }, /* Q3 */ /* 84.9% cutoff ( ~80 dB stop) 8 */ |
205 | { 64, 8, 0.921f, 0.940f, KAISER8 }, /* Q4 */ /* 88.7% cutoff ( ~80 dB stop) 8 */ | 210 | { 64, 8, 0.921f, 0.940f, KAISER8 }, /* Q4 */ /* 88.7% cutoff ( ~80 dB stop) 8 */ |
206 | { 80, 8, 0.922f, 0.940f, KAISER10}, /* Q5 */ /* 89.1% cutoff (~100 dB stop) 10 */ | 211 | { 80, 16, 0.922f, 0.940f, KAISER10}, /* Q5 */ /* 89.1% cutoff (~100 dB stop) 10 */ |
207 | { 96, 8, 0.940f, 0.945f, KAISER10}, /* Q6 */ /* 91.5% cutoff (~100 dB stop) 10 */ | 212 | { 96, 16, 0.940f, 0.945f, KAISER10}, /* Q6 */ /* 91.5% cutoff (~100 dB stop) 10 */ |
208 | {128, 16, 0.950f, 0.950f, KAISER10}, /* Q7 */ /* 93.1% cutoff (~100 dB stop) 10 */ | 213 | {128, 16, 0.950f, 0.950f, KAISER10}, /* Q7 */ /* 93.1% cutoff (~100 dB stop) 10 */ |
209 | {160, 16, 0.960f, 0.960f, KAISER10}, /* Q8 */ /* 94.5% cutoff (~100 dB stop) 10 */ | 214 | {160, 16, 0.960f, 0.960f, KAISER10}, /* Q8 */ /* 94.5% cutoff (~100 dB stop) 10 */ |
210 | {192, 16, 0.968f, 0.968f, KAISER12}, /* Q9 */ /* 95.5% cutoff (~100 dB stop) 10 */ | 215 | {192, 32, 0.968f, 0.968f, KAISER12}, /* Q9 */ /* 95.5% cutoff (~100 dB stop) 10 */ |
211 | {256, 16, 0.975f, 0.975f, KAISER12}, /* Q10 */ /* 96.6% cutoff (~100 dB stop) 10 */ | 216 | {256, 32, 0.975f, 0.975f, KAISER12}, /* Q10 */ /* 96.6% cutoff (~100 dB stop) 10 */ |
212 | }; | 217 | }; |
213 | /*8,24,40,56,80,104,128,160,200,256,320*/ | 218 | /*8,24,40,56,80,104,128,160,200,256,320*/ |
214 | static double compute_func(float x, struct FuncDef *func) | 219 | static double compute_func(float x, struct FuncDef *func) |
@@ -302,15 +307,15 @@ static void cubic_coef(spx_word16_t frac, spx_word16_t interp[4]) | |||
302 | } | 307 | } |
303 | #endif | 308 | #endif |
304 | 309 | ||
305 | static int resampler_basic_direct_single(SpeexResamplerState *st, int channel_index, const spx_word16_t *in, int *in_len, spx_word16_t *out, int *out_len) | 310 | static int resampler_basic_direct_single(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) |
306 | { | 311 | { |
307 | int N = st->filt_len; | 312 | int N = st->filt_len; |
308 | int out_sample = 0; | 313 | int out_sample = 0; |
309 | spx_word16_t *mem; | 314 | spx_word16_t *mem; |
310 | int last_sample = st->last_sample[channel_index]; | 315 | int last_sample = st->last_sample[channel_index]; |
311 | int samp_frac_num = st->samp_frac_num[channel_index]; | 316 | spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; |
312 | mem = st->mem + channel_index * st->mem_alloc_size; | 317 | mem = st->mem + channel_index * st->mem_alloc_size; |
313 | while (!(last_sample >= *in_len || out_sample >= *out_len)) | 318 | while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) |
314 | { | 319 | { |
315 | int j; | 320 | int j; |
316 | spx_word32_t sum=0; | 321 | spx_word32_t sum=0; |
@@ -350,15 +355,15 @@ static int resampler_basic_direct_single(SpeexResamplerState *st, int channel_in | |||
350 | #ifdef FIXED_POINT | 355 | #ifdef FIXED_POINT |
351 | #else | 356 | #else |
352 | /* This is the same as the previous function, except with a double-precision accumulator */ | 357 | /* This is the same as the previous function, except with a double-precision accumulator */ |
353 | static int resampler_basic_direct_double(SpeexResamplerState *st, int channel_index, const spx_word16_t *in, int *in_len, spx_word16_t *out, int *out_len) | 358 | static int resampler_basic_direct_double(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) |
354 | { | 359 | { |
355 | int N = st->filt_len; | 360 | int N = st->filt_len; |
356 | int out_sample = 0; | 361 | int out_sample = 0; |
357 | spx_word16_t *mem; | 362 | spx_word16_t *mem; |
358 | int last_sample = st->last_sample[channel_index]; | 363 | int last_sample = st->last_sample[channel_index]; |
359 | int samp_frac_num = st->samp_frac_num[channel_index]; | 364 | spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; |
360 | mem = st->mem + channel_index * st->mem_alloc_size; | 365 | mem = st->mem + channel_index * st->mem_alloc_size; |
361 | while (!(last_sample >= *in_len || out_sample >= *out_len)) | 366 | while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) |
362 | { | 367 | { |
363 | int j; | 368 | int j; |
364 | double sum=0; | 369 | double sum=0; |
@@ -396,15 +401,15 @@ static int resampler_basic_direct_double(SpeexResamplerState *st, int channel_in | |||
396 | } | 401 | } |
397 | #endif | 402 | #endif |
398 | 403 | ||
399 | static int resampler_basic_interpolate_single(SpeexResamplerState *st, int channel_index, const spx_word16_t *in, int *in_len, spx_word16_t *out, int *out_len) | 404 | static int resampler_basic_interpolate_single(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) |
400 | { | 405 | { |
401 | int N = st->filt_len; | 406 | int N = st->filt_len; |
402 | int out_sample = 0; | 407 | int out_sample = 0; |
403 | spx_word16_t *mem; | 408 | spx_word16_t *mem; |
404 | int last_sample = st->last_sample[channel_index]; | 409 | int last_sample = st->last_sample[channel_index]; |
405 | int samp_frac_num = st->samp_frac_num[channel_index]; | 410 | spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; |
406 | mem = st->mem + channel_index * st->mem_alloc_size; | 411 | mem = st->mem + channel_index * st->mem_alloc_size; |
407 | while (!(last_sample >= *in_len || out_sample >= *out_len)) | 412 | while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) |
408 | { | 413 | { |
409 | int j; | 414 | int j; |
410 | spx_word32_t sum=0; | 415 | spx_word32_t sum=0; |
@@ -465,15 +470,15 @@ static int resampler_basic_interpolate_single(SpeexResamplerState *st, int chann | |||
465 | #ifdef FIXED_POINT | 470 | #ifdef FIXED_POINT |
466 | #else | 471 | #else |
467 | /* This is the same as the previous function, except with a double-precision accumulator */ | 472 | /* This is the same as the previous function, except with a double-precision accumulator */ |
468 | static int resampler_basic_interpolate_double(SpeexResamplerState *st, int channel_index, const spx_word16_t *in, int *in_len, spx_word16_t *out, int *out_len) | 473 | static int resampler_basic_interpolate_double(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) |
469 | { | 474 | { |
470 | int N = st->filt_len; | 475 | int N = st->filt_len; |
471 | int out_sample = 0; | 476 | int out_sample = 0; |
472 | spx_word16_t *mem; | 477 | spx_word16_t *mem; |
473 | int last_sample = st->last_sample[channel_index]; | 478 | int last_sample = st->last_sample[channel_index]; |
474 | int samp_frac_num = st->samp_frac_num[channel_index]; | 479 | spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; |
475 | mem = st->mem + channel_index * st->mem_alloc_size; | 480 | mem = st->mem + channel_index * st->mem_alloc_size; |
476 | while (!(last_sample >= *in_len || out_sample >= *out_len)) | 481 | while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) |
477 | { | 482 | { |
478 | int j; | 483 | int j; |
479 | spx_word32_t sum=0; | 484 | spx_word32_t sum=0; |
@@ -529,8 +534,7 @@ static int resampler_basic_interpolate_double(SpeexResamplerState *st, int chann | |||
529 | 534 | ||
530 | static void update_filter(SpeexResamplerState *st) | 535 | static void update_filter(SpeexResamplerState *st) |
531 | { | 536 | { |
532 | int i; | 537 | spx_uint32_t old_length; |
533 | int old_length; | ||
534 | 538 | ||
535 | old_length = st->filt_len; | 539 | old_length = st->filt_len; |
536 | st->oversample = quality_map[st->quality].oversample; | 540 | st->oversample = quality_map[st->quality].oversample; |
@@ -544,6 +548,16 @@ static void update_filter(SpeexResamplerState *st) | |||
544 | st->filt_len = st->filt_len*st->num_rate / st->den_rate; | 548 | st->filt_len = st->filt_len*st->num_rate / st->den_rate; |
545 | /* Round down to make sure we have a multiple of 4 */ | 549 | /* Round down to make sure we have a multiple of 4 */ |
546 | st->filt_len &= (~0x3); | 550 | st->filt_len &= (~0x3); |
551 | if (2*st->den_rate < st->num_rate) | ||
552 | st->oversample >>= 1; | ||
553 | if (4*st->den_rate < st->num_rate) | ||
554 | st->oversample >>= 1; | ||
555 | if (8*st->den_rate < st->num_rate) | ||
556 | st->oversample >>= 1; | ||
557 | if (16*st->den_rate < st->num_rate) | ||
558 | st->oversample >>= 1; | ||
559 | if (st->oversample < 1) | ||
560 | st->oversample = 1; | ||
547 | } else { | 561 | } else { |
548 | /* up-sampling */ | 562 | /* up-sampling */ |
549 | st->cutoff = quality_map[st->quality].upsample_bandwidth; | 563 | st->cutoff = quality_map[st->quality].upsample_bandwidth; |
@@ -552,6 +566,7 @@ static void update_filter(SpeexResamplerState *st) | |||
552 | /* Choose the resampling type that requires the least amount of memory */ | 566 | /* Choose the resampling type that requires the least amount of memory */ |
553 | if (st->den_rate <= st->oversample) | 567 | if (st->den_rate <= st->oversample) |
554 | { | 568 | { |
569 | spx_uint32_t i; | ||
555 | if (!st->sinc_table) | 570 | if (!st->sinc_table) |
556 | st->sinc_table = (spx_word16_t *)speex_alloc(st->filt_len*st->den_rate*sizeof(spx_word16_t)); | 571 | st->sinc_table = (spx_word16_t *)speex_alloc(st->filt_len*st->den_rate*sizeof(spx_word16_t)); |
557 | else if (st->sinc_table_length < st->filt_len*st->den_rate) | 572 | else if (st->sinc_table_length < st->filt_len*st->den_rate) |
@@ -561,7 +576,7 @@ static void update_filter(SpeexResamplerState *st) | |||
561 | } | 576 | } |
562 | for (i=0;i<st->den_rate;i++) | 577 | for (i=0;i<st->den_rate;i++) |
563 | { | 578 | { |
564 | int j; | 579 | spx_uint32_t j; |
565 | for (j=0;j<st->filt_len;j++) | 580 | for (j=0;j<st->filt_len;j++) |
566 | { | 581 | { |
567 | 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); | 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); |
@@ -577,6 +592,7 @@ static void update_filter(SpeexResamplerState *st) | |||
577 | #endif | 592 | #endif |
578 | /*fprintf (stderr, "resampler uses direct sinc table and normalised cutoff %f\n", cutoff);*/ | 593 | /*fprintf (stderr, "resampler uses direct sinc table and normalised cutoff %f\n", cutoff);*/ |
579 | } else { | 594 | } else { |
595 | spx_int32_t i; | ||
580 | if (!st->sinc_table) | 596 | if (!st->sinc_table) |
581 | st->sinc_table = (spx_word16_t *)speex_alloc((st->filt_len*st->oversample+8)*sizeof(spx_word16_t)); | 597 | st->sinc_table = (spx_word16_t *)speex_alloc((st->filt_len*st->oversample+8)*sizeof(spx_word16_t)); |
582 | else if (st->sinc_table_length < st->filt_len*st->oversample+8) | 598 | else if (st->sinc_table_length < st->filt_len*st->oversample+8) |
@@ -584,7 +600,7 @@ static void update_filter(SpeexResamplerState *st) | |||
584 | st->sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,(st->filt_len*st->oversample+8)*sizeof(spx_word16_t)); | 600 | st->sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,(st->filt_len*st->oversample+8)*sizeof(spx_word16_t)); |
585 | st->sinc_table_length = st->filt_len*st->oversample+8; | 601 | st->sinc_table_length = st->filt_len*st->oversample+8; |
586 | } | 602 | } |
587 | for (i=-4;i<st->oversample*st->filt_len+4;i++) | 603 | for (i=-4;i<(spx_int32_t)(st->oversample*st->filt_len+4);i++) |
588 | st->sinc_table[i+4] = sinc(st->cutoff,(i/(float)st->oversample - st->filt_len/2), st->filt_len, quality_map[st->quality].window_func); | 604 | st->sinc_table[i+4] = sinc(st->cutoff,(i/(float)st->oversample - st->filt_len/2), st->filt_len, quality_map[st->quality].window_func); |
589 | #ifdef FIXED_POINT | 605 | #ifdef FIXED_POINT |
590 | st->resampler_ptr = resampler_basic_interpolate_single; | 606 | st->resampler_ptr = resampler_basic_interpolate_single; |
@@ -599,8 +615,13 @@ static void update_filter(SpeexResamplerState *st) | |||
599 | st->int_advance = st->num_rate/st->den_rate; | 615 | st->int_advance = st->num_rate/st->den_rate; |
600 | st->frac_advance = st->num_rate%st->den_rate; | 616 | st->frac_advance = st->num_rate%st->den_rate; |
601 | 617 | ||
618 | |||
619 | /* Here's the place where we update the filter memory to take into account | ||
620 | the change in filter length. It's probably the messiest part of the code | ||
621 | due to handling of lots of corner cases. */ | ||
602 | if (!st->mem) | 622 | if (!st->mem) |
603 | { | 623 | { |
624 | spx_uint32_t i; | ||
604 | st->mem = (spx_word16_t*)speex_alloc(st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t)); | 625 | st->mem = (spx_word16_t*)speex_alloc(st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t)); |
605 | for (i=0;i<st->nb_channels*(st->filt_len-1);i++) | 626 | for (i=0;i<st->nb_channels*(st->filt_len-1);i++) |
606 | st->mem[i] = 0; | 627 | st->mem[i] = 0; |
@@ -608,6 +629,7 @@ static void update_filter(SpeexResamplerState *st) | |||
608 | /*speex_warning("init filter");*/ | 629 | /*speex_warning("init filter");*/ |
609 | } else if (!st->started) | 630 | } else if (!st->started) |
610 | { | 631 | { |
632 | spx_uint32_t i; | ||
611 | st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t)); | 633 | st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t)); |
612 | for (i=0;i<st->nb_channels*(st->filt_len-1);i++) | 634 | for (i=0;i<st->nb_channels*(st->filt_len-1);i++) |
613 | st->mem[i] = 0; | 635 | st->mem[i] = 0; |
@@ -615,6 +637,7 @@ static void update_filter(SpeexResamplerState *st) | |||
615 | /*speex_warning("reinit filter");*/ | 637 | /*speex_warning("reinit filter");*/ |
616 | } else if (st->filt_len > old_length) | 638 | } else if (st->filt_len > old_length) |
617 | { | 639 | { |
640 | spx_int32_t i; | ||
618 | /* Increase the filter length */ | 641 | /* Increase the filter length */ |
619 | /*speex_warning("increase filter size");*/ | 642 | /*speex_warning("increase filter size");*/ |
620 | int old_alloc_size = st->mem_alloc_size; | 643 | int old_alloc_size = st->mem_alloc_size; |
@@ -623,45 +646,76 @@ static void update_filter(SpeexResamplerState *st) | |||
623 | st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t)); | 646 | st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t)); |
624 | st->mem_alloc_size = st->filt_len-1; | 647 | st->mem_alloc_size = st->filt_len-1; |
625 | } | 648 | } |
626 | for (i=0;i<st->nb_channels;i++) | 649 | for (i=st->nb_channels-1;i>=0;i--) |
627 | { | 650 | { |
628 | int j; | 651 | spx_int32_t j; |
629 | /* Copy data going backward */ | 652 | spx_uint32_t olen = old_length; |
630 | for (j=0;j<old_length-1;j++) | 653 | /*if (st->magic_samples[i])*/ |
631 | st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = st->mem[i*old_alloc_size+(old_length-2-j)]; | 654 | { |
632 | /* Then put zeros for lack of anything better */ | 655 | /* Try and remove the magic samples as if nothing had happened */ |
633 | for (;j<st->filt_len-1;j++) | 656 | |
634 | st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = 0; | 657 | /* FIXME: This is wrong but for now we need it to avoid going over the array bounds */ |
635 | /* Adjust last_sample */ | 658 | olen = old_length + 2*st->magic_samples[i]; |
636 | st->last_sample[i] += (st->filt_len - old_length)/2; | 659 | for (j=old_length-2+st->magic_samples[i];j>=0;j--) |
660 | st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]] = st->mem[i*old_alloc_size+j]; | ||
661 | for (j=0;j<st->magic_samples[i];j++) | ||
662 | st->mem[i*st->mem_alloc_size+j] = 0; | ||
663 | st->magic_samples[i] = 0; | ||
664 | } | ||
665 | if (st->filt_len > olen) | ||
666 | { | ||
667 | /* If the new filter length is still bigger than the "augmented" length */ | ||
668 | /* Copy data going backward */ | ||
669 | for (j=0;j<olen-1;j++) | ||
670 | st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = st->mem[i*st->mem_alloc_size+(olen-2-j)]; | ||
671 | /* Then put zeros for lack of anything better */ | ||
672 | for (;j<st->filt_len-1;j++) | ||
673 | st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = 0; | ||
674 | /* Adjust last_sample */ | ||
675 | st->last_sample[i] += (st->filt_len - olen)/2; | ||
676 | } else { | ||
677 | /* Put back some of the magic! */ | ||
678 | st->magic_samples[i] = (olen - st->filt_len)/2; | ||
679 | for (j=0;j<st->filt_len-1+st->magic_samples[i];j++) | ||
680 | st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]]; | ||
681 | } | ||
637 | } | 682 | } |
638 | } else if (st->filt_len < old_length) | 683 | } else if (st->filt_len < old_length) |
639 | { | 684 | { |
640 | /* Reduce filter length, this a bit tricky */ | 685 | spx_uint32_t i; |
641 | /*speex_warning("decrease filter size (unimplemented)");*/ | 686 | /* Reduce filter length, this a bit tricky. We need to store some of the memory as "magic" |
642 | /* Adjust last_sample (which will likely end up negative) */ | 687 | samples so they can be used directly as input the next time(s) */ |
643 | /*st->last_sample += (st->filt_len - old_length)/2;*/ | ||
644 | for (i=0;i<st->nb_channels;i++) | 688 | for (i=0;i<st->nb_channels;i++) |
645 | { | 689 | { |
646 | int j; | 690 | spx_uint32_t j; |
691 | spx_uint32_t old_magic = st->magic_samples[i]; | ||
647 | st->magic_samples[i] = (old_length - st->filt_len)/2; | 692 | st->magic_samples[i] = (old_length - st->filt_len)/2; |
693 | /* We must copy some of the memory that's no longer used */ | ||
648 | /* Copy data going backward */ | 694 | /* Copy data going backward */ |
649 | for (j=0;j<st->filt_len-1+st->magic_samples[i];j++) | 695 | for (j=0;j<st->filt_len-1+st->magic_samples[i]+old_magic;j++) |
650 | st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]]; | 696 | st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]]; |
697 | st->magic_samples[i] += old_magic; | ||
651 | } | 698 | } |
652 | } | 699 | } |
653 | 700 | ||
654 | } | 701 | } |
655 | 702 | ||
656 | SpeexResamplerState *speex_resampler_init(int nb_channels, int in_rate, int out_rate, int quality) | 703 | SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err) |
657 | { | 704 | { |
658 | return speex_resampler_init_frac(nb_channels, in_rate, out_rate, in_rate, out_rate, quality); | 705 | return speex_resampler_init_frac(nb_channels, in_rate, out_rate, in_rate, out_rate, quality, err); |
659 | } | 706 | } |
660 | 707 | ||
661 | SpeexResamplerState *speex_resampler_init_frac(int nb_channels, int ratio_num, int ratio_den, int in_rate, int out_rate, int quality) | 708 | SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err) |
662 | { | 709 | { |
663 | int i; | 710 | spx_uint32_t i; |
664 | SpeexResamplerState *st = (SpeexResamplerState *)speex_alloc(sizeof(SpeexResamplerState)); | 711 | SpeexResamplerState *st; |
712 | if (quality > 10 || quality < 0) | ||
713 | { | ||
714 | if (err) | ||
715 | *err = RESAMPLER_ERR_INVALID_ARG; | ||
716 | return NULL; | ||
717 | } | ||
718 | st = (SpeexResamplerState *)speex_alloc(sizeof(SpeexResamplerState)); | ||
665 | st->initialised = 0; | 719 | st->initialised = 0; |
666 | st->started = 0; | 720 | st->started = 0; |
667 | st->in_rate = 0; | 721 | st->in_rate = 0; |
@@ -681,9 +735,9 @@ SpeexResamplerState *speex_resampler_init_frac(int nb_channels, int ratio_num, i | |||
681 | st->out_stride = 1; | 735 | st->out_stride = 1; |
682 | 736 | ||
683 | /* Per channel data */ | 737 | /* Per channel data */ |
684 | st->last_sample = (int*)speex_alloc(nb_channels*sizeof(int)); | 738 | st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(int)); |
685 | st->magic_samples = (int*)speex_alloc(nb_channels*sizeof(int)); | 739 | st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int)); |
686 | st->samp_frac_num = (int*)speex_alloc(nb_channels*sizeof(int)); | 740 | st->samp_frac_num = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int)); |
687 | for (i=0;i<nb_channels;i++) | 741 | for (i=0;i<nb_channels;i++) |
688 | { | 742 | { |
689 | st->last_sample[i] = 0; | 743 | st->last_sample[i] = 0; |
@@ -698,6 +752,9 @@ SpeexResamplerState *speex_resampler_init_frac(int nb_channels, int ratio_num, i | |||
698 | update_filter(st); | 752 | update_filter(st); |
699 | 753 | ||
700 | st->initialised = 1; | 754 | st->initialised = 1; |
755 | if (err) | ||
756 | *err = RESAMPLER_ERR_SUCCESS; | ||
757 | |||
701 | return st; | 758 | return st; |
702 | } | 759 | } |
703 | 760 | ||
@@ -713,62 +770,75 @@ void speex_resampler_destroy(SpeexResamplerState *st) | |||
713 | 770 | ||
714 | 771 | ||
715 | 772 | ||
716 | static void speex_resampler_process_native(SpeexResamplerState *st, int channel_index, const spx_word16_t *in, int *in_len, spx_word16_t *out, int *out_len) | 773 | static int speex_resampler_process_native(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) |
717 | { | 774 | { |
718 | int j=0; | 775 | int j=0; |
719 | int N = st->filt_len; | 776 | int N = st->filt_len; |
720 | int out_sample = 0; | 777 | int out_sample = 0; |
721 | spx_word16_t *mem; | 778 | spx_word16_t *mem; |
722 | int tmp_out_len = 0; | 779 | spx_uint32_t tmp_out_len = 0; |
723 | mem = st->mem + channel_index * st->mem_alloc_size; | 780 | mem = st->mem + channel_index * st->mem_alloc_size; |
724 | st->started = 1; | 781 | st->started = 1; |
725 | 782 | ||
726 | /* Handle the case where we have samples left from a reduction in filter length */ | 783 | /* Handle the case where we have samples left from a reduction in filter length */ |
727 | if (st->magic_samples[channel_index]) | 784 | if (st->magic_samples[channel_index]) |
728 | { | 785 | { |
729 | int tmp_in_len; | 786 | int istride_save; |
730 | int tmp_magic; | 787 | spx_uint32_t tmp_in_len; |
788 | spx_uint32_t tmp_magic; | ||
789 | |||
790 | istride_save = st->in_stride; | ||
731 | tmp_in_len = st->magic_samples[channel_index]; | 791 | tmp_in_len = st->magic_samples[channel_index]; |
732 | tmp_out_len = *out_len; | 792 | tmp_out_len = *out_len; |
733 | /* FIXME: Need to handle the case where the out array is too small */ | ||
734 | /* magic_samples needs to be set to zero to avoid infinite recursion */ | 793 | /* magic_samples needs to be set to zero to avoid infinite recursion */ |
735 | tmp_magic = st->magic_samples[channel_index]; | 794 | tmp_magic = st->magic_samples[channel_index]; |
736 | st->magic_samples[channel_index] = 0; | 795 | st->magic_samples[channel_index] = 0; |
796 | st->in_stride = 1; | ||
737 | speex_resampler_process_native(st, channel_index, mem+N-1, &tmp_in_len, out, &tmp_out_len); | 797 | speex_resampler_process_native(st, channel_index, mem+N-1, &tmp_in_len, out, &tmp_out_len); |
798 | st->in_stride = istride_save; | ||
738 | /*speex_warning_int("extra samples:", tmp_out_len);*/ | 799 | /*speex_warning_int("extra samples:", tmp_out_len);*/ |
739 | /* If we couldn't process all "magic" input samples, save the rest for next time */ | 800 | /* If we couldn't process all "magic" input samples, save the rest for next time */ |
740 | if (tmp_in_len < tmp_magic) | 801 | if (tmp_in_len < tmp_magic) |
741 | { | 802 | { |
742 | int i; | 803 | spx_uint32_t i; |
743 | st->magic_samples[channel_index] = tmp_magic-tmp_in_len; | 804 | st->magic_samples[channel_index] = tmp_magic-tmp_in_len; |
744 | for (i=0;i<st->magic_samples[channel_index];i++) | 805 | for (i=0;i<st->magic_samples[channel_index];i++) |
745 | mem[N-1+i]=mem[N-1+i+tmp_in_len]; | 806 | mem[N-1+i]=mem[N-1+i+tmp_in_len]; |
746 | } | 807 | } |
747 | out += tmp_out_len; | 808 | out += tmp_out_len*st->out_stride; |
809 | *out_len -= tmp_out_len; | ||
748 | } | 810 | } |
749 | 811 | ||
750 | /* Call the right resampler through the function ptr */ | 812 | /* Call the right resampler through the function ptr */ |
751 | out_sample = st->resampler_ptr(st, channel_index, in, in_len, out, out_len); | 813 | out_sample = st->resampler_ptr(st, channel_index, in, in_len, out, out_len); |
752 | 814 | ||
753 | if (st->last_sample[channel_index] < *in_len) | 815 | if (st->last_sample[channel_index] < (spx_int32_t)*in_len) |
754 | *in_len = st->last_sample[channel_index]; | 816 | *in_len = st->last_sample[channel_index]; |
755 | *out_len = out_sample+tmp_out_len; | 817 | *out_len = out_sample+tmp_out_len; |
756 | st->last_sample[channel_index] -= *in_len; | 818 | st->last_sample[channel_index] -= *in_len; |
757 | 819 | ||
758 | for (j=0;j<N-1-*in_len;j++) | 820 | for (j=0;j<N-1-(spx_int32_t)*in_len;j++) |
759 | mem[j] = mem[j+*in_len]; | 821 | mem[j] = mem[j+*in_len]; |
760 | for (;j<N-1;j++) | 822 | for (;j<N-1;j++) |
761 | mem[j] = in[st->in_stride*(j+*in_len-N+1)]; | 823 | mem[j] = in[st->in_stride*(j+*in_len-N+1)]; |
762 | 824 | ||
825 | return RESAMPLER_ERR_SUCCESS; | ||
763 | } | 826 | } |
764 | 827 | ||
828 | #define FIXED_STACK_ALLOC 1024 | ||
829 | |||
765 | #ifdef FIXED_POINT | 830 | #ifdef FIXED_POINT |
766 | void speex_resampler_process_float(SpeexResamplerState *st, int channel_index, const float *in, int *in_len, float *out, int *out_len) | 831 | int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len) |
767 | { | 832 | { |
768 | int i; | 833 | spx_uint32_t i; |
769 | int istride_save, ostride_save; | 834 | int istride_save, ostride_save; |
835 | #ifdef VAR_ARRAYS | ||
770 | spx_word16_t x[*in_len]; | 836 | spx_word16_t x[*in_len]; |
771 | spx_word16_t y[*out_len]; | 837 | spx_word16_t y[*out_len]; |
838 | /*VARDECL(spx_word16_t *x); | ||
839 | VARDECL(spx_word16_t *y); | ||
840 | ALLOC(x, *in_len, spx_word16_t); | ||
841 | ALLOC(y, *out_len, spx_word16_t);*/ | ||
772 | istride_save = st->in_stride; | 842 | istride_save = st->in_stride; |
773 | ostride_save = st->out_stride; | 843 | ostride_save = st->out_stride; |
774 | for (i=0;i<*in_len;i++) | 844 | for (i=0;i<*in_len;i++) |
@@ -779,22 +849,59 @@ void speex_resampler_process_float(SpeexResamplerState *st, int channel_index, c | |||
779 | st->out_stride = ostride_save; | 849 | st->out_stride = ostride_save; |
780 | for (i=0;i<*out_len;i++) | 850 | for (i=0;i<*out_len;i++) |
781 | out[i*st->out_stride] = y[i]; | 851 | out[i*st->out_stride] = y[i]; |
852 | #else | ||
853 | spx_word16_t x[FIXED_STACK_ALLOC]; | ||
854 | spx_word16_t y[FIXED_STACK_ALLOC]; | ||
855 | spx_uint32_t ilen=*in_len, olen=*out_len; | ||
856 | istride_save = st->in_stride; | ||
857 | ostride_save = st->out_stride; | ||
858 | while (ilen && olen) | ||
859 | { | ||
860 | spx_uint32_t ichunk, ochunk; | ||
861 | ichunk = ilen; | ||
862 | ochunk = olen; | ||
863 | if (ichunk>FIXED_STACK_ALLOC) | ||
864 | ichunk=FIXED_STACK_ALLOC; | ||
865 | if (ochunk>FIXED_STACK_ALLOC) | ||
866 | ochunk=FIXED_STACK_ALLOC; | ||
867 | for (i=0;i<ichunk;i++) | ||
868 | x[i] = WORD2INT(in[i*st->in_stride]); | ||
869 | st->in_stride = st->out_stride = 1; | ||
870 | speex_resampler_process_native(st, channel_index, x, &ichunk, y, &ochunk); | ||
871 | st->in_stride = istride_save; | ||
872 | st->out_stride = ostride_save; | ||
873 | for (i=0;i<ochunk;i++) | ||
874 | out[i*st->out_stride] = y[i]; | ||
875 | out += ochunk; | ||
876 | in += ichunk; | ||
877 | ilen -= ichunk; | ||
878 | olen -= ochunk; | ||
879 | } | ||
880 | *in_len -= ilen; | ||
881 | *out_len -= olen; | ||
882 | #endif | ||
883 | return RESAMPLER_ERR_SUCCESS; | ||
782 | } | 884 | } |
783 | void speex_resampler_process_int(SpeexResamplerState *st, int channel_index, const spx_int16_t *in, int *in_len, spx_int16_t *out, int *out_len) | 885 | int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len) |
784 | { | 886 | { |
785 | speex_resampler_process_native(st, channel_index, in, in_len, out, out_len); | 887 | return speex_resampler_process_native(st, channel_index, in, in_len, out, out_len); |
786 | } | 888 | } |
787 | #else | 889 | #else |
788 | void speex_resampler_process_float(SpeexResamplerState *st, int channel_index, const float *in, int *in_len, float *out, int *out_len) | 890 | int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len) |
789 | { | 891 | { |
790 | speex_resampler_process_native(st, channel_index, in, in_len, out, out_len); | 892 | return speex_resampler_process_native(st, channel_index, in, in_len, out, out_len); |
791 | } | 893 | } |
792 | void speex_resampler_process_int(SpeexResamplerState *st, int channel_index, const spx_int16_t *in, int *in_len, spx_int16_t *out, int *out_len) | 894 | int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len) |
793 | { | 895 | { |
794 | int i; | 896 | spx_uint32_t i; |
795 | int istride_save, ostride_save; | 897 | int istride_save, ostride_save; |
898 | #ifdef VAR_ARRAYS | ||
796 | spx_word16_t x[*in_len]; | 899 | spx_word16_t x[*in_len]; |
797 | spx_word16_t y[*out_len]; | 900 | spx_word16_t y[*out_len]; |
901 | /*VARDECL(spx_word16_t *x); | ||
902 | VARDECL(spx_word16_t *y); | ||
903 | ALLOC(x, *in_len, spx_word16_t); | ||
904 | ALLOC(y, *out_len, spx_word16_t);*/ | ||
798 | istride_save = st->in_stride; | 905 | istride_save = st->in_stride; |
799 | ostride_save = st->out_stride; | 906 | ostride_save = st->out_stride; |
800 | for (i=0;i<*in_len;i++) | 907 | for (i=0;i<*in_len;i++) |
@@ -805,55 +912,94 @@ void speex_resampler_process_int(SpeexResamplerState *st, int channel_index, con | |||
805 | st->out_stride = ostride_save; | 912 | st->out_stride = ostride_save; |
806 | for (i=0;i<*out_len;i++) | 913 | for (i=0;i<*out_len;i++) |
807 | out[i*st->out_stride] = WORD2INT(y[i]); | 914 | out[i*st->out_stride] = WORD2INT(y[i]); |
915 | #else | ||
916 | spx_word16_t x[FIXED_STACK_ALLOC]; | ||
917 | spx_word16_t y[FIXED_STACK_ALLOC]; | ||
918 | spx_uint32_t ilen=*in_len, olen=*out_len; | ||
919 | istride_save = st->in_stride; | ||
920 | ostride_save = st->out_stride; | ||
921 | while (ilen && olen) | ||
922 | { | ||
923 | spx_uint32_t ichunk, ochunk; | ||
924 | ichunk = ilen; | ||
925 | ochunk = olen; | ||
926 | if (ichunk>FIXED_STACK_ALLOC) | ||
927 | ichunk=FIXED_STACK_ALLOC; | ||
928 | if (ochunk>FIXED_STACK_ALLOC) | ||
929 | ochunk=FIXED_STACK_ALLOC; | ||
930 | for (i=0;i<ichunk;i++) | ||
931 | x[i] = in[i*st->in_stride]; | ||
932 | st->in_stride = st->out_stride = 1; | ||
933 | speex_resampler_process_native(st, channel_index, x, &ichunk, y, &ochunk); | ||
934 | st->in_stride = istride_save; | ||
935 | st->out_stride = ostride_save; | ||
936 | for (i=0;i<ochunk;i++) | ||
937 | out[i*st->out_stride] = WORD2INT(y[i]); | ||
938 | out += ochunk; | ||
939 | in += ichunk; | ||
940 | ilen -= ichunk; | ||
941 | olen -= ochunk; | ||
942 | } | ||
943 | *in_len -= ilen; | ||
944 | *out_len -= olen; | ||
945 | #endif | ||
946 | return RESAMPLER_ERR_SUCCESS; | ||
808 | } | 947 | } |
809 | #endif | 948 | #endif |
810 | 949 | ||
811 | void speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, int *in_len, float *out, int *out_len) | 950 | int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len) |
812 | { | 951 | { |
813 | int i; | 952 | spx_uint32_t i; |
814 | int istride_save, ostride_save; | 953 | int istride_save, ostride_save; |
954 | spx_uint32_t bak_len = *out_len; | ||
815 | istride_save = st->in_stride; | 955 | istride_save = st->in_stride; |
816 | ostride_save = st->out_stride; | 956 | ostride_save = st->out_stride; |
817 | st->in_stride = st->out_stride = st->nb_channels; | 957 | st->in_stride = st->out_stride = st->nb_channels; |
818 | for (i=0;i<st->nb_channels;i++) | 958 | for (i=0;i<st->nb_channels;i++) |
819 | { | 959 | { |
960 | *out_len = bak_len; | ||
820 | speex_resampler_process_float(st, i, in+i, in_len, out+i, out_len); | 961 | speex_resampler_process_float(st, i, in+i, in_len, out+i, out_len); |
821 | } | 962 | } |
822 | st->in_stride = istride_save; | 963 | st->in_stride = istride_save; |
823 | st->out_stride = ostride_save; | 964 | st->out_stride = ostride_save; |
965 | return RESAMPLER_ERR_SUCCESS; | ||
824 | } | 966 | } |
825 | 967 | ||
826 | void speex_resampler_process_interleaved_int(SpeexResamplerState *st, const spx_int16_t *in, int *in_len, spx_int16_t *out, int *out_len) | 968 | |
969 | int speex_resampler_process_interleaved_int(SpeexResamplerState *st, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len) | ||
827 | { | 970 | { |
828 | int i; | 971 | spx_uint32_t i; |
829 | int istride_save, ostride_save; | 972 | int istride_save, ostride_save; |
973 | spx_uint32_t bak_len = *out_len; | ||
830 | istride_save = st->in_stride; | 974 | istride_save = st->in_stride; |
831 | ostride_save = st->out_stride; | 975 | ostride_save = st->out_stride; |
832 | st->in_stride = st->out_stride = st->nb_channels; | 976 | st->in_stride = st->out_stride = st->nb_channels; |
833 | for (i=0;i<st->nb_channels;i++) | 977 | for (i=0;i<st->nb_channels;i++) |
834 | { | 978 | { |
979 | *out_len = bak_len; | ||
835 | speex_resampler_process_int(st, i, in+i, in_len, out+i, out_len); | 980 | speex_resampler_process_int(st, i, in+i, in_len, out+i, out_len); |
836 | } | 981 | } |
837 | st->in_stride = istride_save; | 982 | st->in_stride = istride_save; |
838 | st->out_stride = ostride_save; | 983 | st->out_stride = ostride_save; |
984 | return RESAMPLER_ERR_SUCCESS; | ||
839 | } | 985 | } |
840 | 986 | ||
841 | void speex_resampler_set_rate(SpeexResamplerState *st, int in_rate, int out_rate) | 987 | int speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate) |
842 | { | 988 | { |
843 | speex_resampler_set_rate_frac(st, in_rate, out_rate, in_rate, out_rate); | 989 | return speex_resampler_set_rate_frac(st, in_rate, out_rate, in_rate, out_rate); |
844 | } | 990 | } |
845 | 991 | ||
846 | void speex_resampler_get_rate(SpeexResamplerState *st, int *in_rate, int *out_rate) | 992 | void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_rate, spx_uint32_t *out_rate) |
847 | { | 993 | { |
848 | *in_rate = st->in_rate; | 994 | *in_rate = st->in_rate; |
849 | *out_rate = st->out_rate; | 995 | *out_rate = st->out_rate; |
850 | } | 996 | } |
851 | 997 | ||
852 | void speex_resampler_set_rate_frac(SpeexResamplerState *st, int ratio_num, int ratio_den, int in_rate, int out_rate) | 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) |
853 | { | 999 | { |
854 | int fact; | 1000 | int fact; |
855 | if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den) | 1001 | if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den) |
856 | return; | 1002 | return RESAMPLER_ERR_SUCCESS; |
857 | 1003 | ||
858 | st->in_rate = in_rate; | 1004 | st->in_rate = in_rate; |
859 | st->out_rate = out_rate; | 1005 | st->out_rate = out_rate; |
@@ -871,25 +1017,25 @@ void speex_resampler_set_rate_frac(SpeexResamplerState *st, int ratio_num, int r | |||
871 | 1017 | ||
872 | if (st->initialised) | 1018 | if (st->initialised) |
873 | update_filter(st); | 1019 | update_filter(st); |
1020 | return RESAMPLER_ERR_SUCCESS; | ||
874 | } | 1021 | } |
875 | 1022 | ||
876 | void speex_resampler_get_ratio(SpeexResamplerState *st, int *ratio_num, int *ratio_den) | 1023 | void speex_resampler_get_ratio(SpeexResamplerState *st, spx_uint32_t *ratio_num, spx_uint32_t *ratio_den) |
877 | { | 1024 | { |
878 | *ratio_num = st->num_rate; | 1025 | *ratio_num = st->num_rate; |
879 | *ratio_den = st->den_rate; | 1026 | *ratio_den = st->den_rate; |
880 | } | 1027 | } |
881 | 1028 | ||
882 | void speex_resampler_set_quality(SpeexResamplerState *st, int quality) | 1029 | int speex_resampler_set_quality(SpeexResamplerState *st, int quality) |
883 | { | 1030 | { |
884 | if (quality < 0) | 1031 | if (quality > 10 || quality < 0) |
885 | quality = 0; | 1032 | return RESAMPLER_ERR_INVALID_ARG; |
886 | if (quality > 10) | ||
887 | quality = 10; | ||
888 | if (st->quality == quality) | 1033 | if (st->quality == quality) |
889 | return; | 1034 | return RESAMPLER_ERR_SUCCESS; |
890 | st->quality = quality; | 1035 | st->quality = quality; |
891 | if (st->initialised) | 1036 | if (st->initialised) |
892 | update_filter(st); | 1037 | update_filter(st); |
1038 | return RESAMPLER_ERR_SUCCESS; | ||
893 | } | 1039 | } |
894 | 1040 | ||
895 | void speex_resampler_get_quality(SpeexResamplerState *st, int *quality) | 1041 | void speex_resampler_get_quality(SpeexResamplerState *st, int *quality) |
@@ -897,37 +1043,57 @@ void speex_resampler_get_quality(SpeexResamplerState *st, int *quality) | |||
897 | *quality = st->quality; | 1043 | *quality = st->quality; |
898 | } | 1044 | } |
899 | 1045 | ||
900 | void speex_resampler_set_input_stride(SpeexResamplerState *st, int stride) | 1046 | void speex_resampler_set_input_stride(SpeexResamplerState *st, spx_uint32_t stride) |
901 | { | 1047 | { |
902 | st->in_stride = stride; | 1048 | st->in_stride = stride; |
903 | } | 1049 | } |
904 | 1050 | ||
905 | void speex_resampler_get_input_stride(SpeexResamplerState *st, int *stride) | 1051 | void speex_resampler_get_input_stride(SpeexResamplerState *st, spx_uint32_t *stride) |
906 | { | 1052 | { |
907 | *stride = st->in_stride; | 1053 | *stride = st->in_stride; |
908 | } | 1054 | } |
909 | 1055 | ||
910 | void speex_resampler_set_output_stride(SpeexResamplerState *st, int stride) | 1056 | void speex_resampler_set_output_stride(SpeexResamplerState *st, spx_uint32_t stride) |
911 | { | 1057 | { |
912 | st->out_stride = stride; | 1058 | st->out_stride = stride; |
913 | } | 1059 | } |
914 | 1060 | ||
915 | void speex_resampler_get_output_stride(SpeexResamplerState *st, int *stride) | 1061 | void speex_resampler_get_output_stride(SpeexResamplerState *st, spx_uint32_t *stride) |
916 | { | 1062 | { |
917 | *stride = st->out_stride; | 1063 | *stride = st->out_stride; |
918 | } | 1064 | } |
919 | 1065 | ||
920 | void speex_resampler_skip_zeros(SpeexResamplerState *st) | 1066 | int speex_resampler_skip_zeros(SpeexResamplerState *st) |
921 | { | 1067 | { |
922 | int i; | 1068 | spx_uint32_t i; |
923 | for (i=0;i<st->nb_channels;i++) | 1069 | for (i=0;i<st->nb_channels;i++) |
924 | st->last_sample[i] = st->filt_len/2; | 1070 | st->last_sample[i] = st->filt_len/2; |
1071 | return RESAMPLER_ERR_SUCCESS; | ||
925 | } | 1072 | } |
926 | 1073 | ||
927 | void speex_resampler_reset_mem(SpeexResamplerState *st) | 1074 | int speex_resampler_reset_mem(SpeexResamplerState *st) |
928 | { | 1075 | { |
929 | int i; | 1076 | spx_uint32_t i; |
930 | for (i=0;i<st->nb_channels*(st->filt_len-1);i++) | 1077 | for (i=0;i<st->nb_channels*(st->filt_len-1);i++) |
931 | st->mem[i] = 0; | 1078 | st->mem[i] = 0; |
1079 | return RESAMPLER_ERR_SUCCESS; | ||
932 | } | 1080 | } |
933 | 1081 | ||
1082 | const char *speex_resampler_strerror(int err) | ||
1083 | { | ||
1084 | switch (err) | ||
1085 | { | ||
1086 | case RESAMPLER_ERR_SUCCESS: | ||
1087 | return "Success."; | ||
1088 | case RESAMPLER_ERR_ALLOC_FAILED: | ||
1089 | return "Memory allocation failed."; | ||
1090 | case RESAMPLER_ERR_BAD_STATE: | ||
1091 | return "Bad resampler state."; | ||
1092 | case RESAMPLER_ERR_INVALID_ARG: | ||
1093 | return "Invalid argument."; | ||
1094 | case RESAMPLER_ERR_PTR_OVERLAP: | ||
1095 | return "Input and output buffers overlap."; | ||
1096 | default: | ||
1097 | return "Unknown error. Bad error code or strange version mismatch."; | ||
1098 | } | ||
1099 | } | ||