summaryrefslogtreecommitdiff
path: root/apps/codecs/libspeex/resample.c
diff options
context:
space:
mode:
authorDan Everton <dan@iocaine.org>2007-05-22 09:50:31 +0000
committerDan Everton <dan@iocaine.org>2007-05-22 09:50:31 +0000
commitdf6f2f9a3c88a7a4a8ad0382ee4ee7c9a3ee3256 (patch)
treed9862e5d04f4014def5911bb4ff8206c85636fb7 /apps/codecs/libspeex/resample.c
parent8970055ec107a2387eedbb373889d0f540745121 (diff)
downloadrockbox-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.c380
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>
59void *speex_alloc (int size) {return calloc(size,1);} 59static void *speex_alloc (int size) {return calloc(size,1);}
60void *speex_realloc (void *ptr, int size) {return realloc(ptr, size);} 60static void *speex_realloc (void *ptr, int size) {return realloc(ptr, size);}
61void speex_free (void *ptr) {free(ptr);} 61static 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
87typedef int (*resampler_basic_func)(SpeexResamplerState *, int , const spx_word16_t *, int *, spx_word16_t *, int *); 92typedef int (*resampler_basic_func)(SpeexResamplerState *, spx_uint32_t , const spx_word16_t *, spx_uint32_t *, spx_word16_t *, spx_uint32_t *);
88 93
89struct SpeexResamplerState_ { 94struct 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*/
214static double compute_func(float x, struct FuncDef *func) 219static 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
305static 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) 310static 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 */
353static 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) 358static 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
399static 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) 404static 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 */
468static 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) 473static 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
530static void update_filter(SpeexResamplerState *st) 535static 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
656SpeexResamplerState *speex_resampler_init(int nb_channels, int in_rate, int out_rate, int quality) 703SpeexResamplerState *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
661SpeexResamplerState *speex_resampler_init_frac(int nb_channels, int ratio_num, int ratio_den, int in_rate, int out_rate, int quality) 708SpeexResamplerState *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
716static 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) 773static 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
766void speex_resampler_process_float(SpeexResamplerState *st, int channel_index, const float *in, int *in_len, float *out, int *out_len) 831int 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}
783void speex_resampler_process_int(SpeexResamplerState *st, int channel_index, const spx_int16_t *in, int *in_len, spx_int16_t *out, int *out_len) 885int 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
788void speex_resampler_process_float(SpeexResamplerState *st, int channel_index, const float *in, int *in_len, float *out, int *out_len) 890int 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}
792void speex_resampler_process_int(SpeexResamplerState *st, int channel_index, const spx_int16_t *in, int *in_len, spx_int16_t *out, int *out_len) 894int 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
811void speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, int *in_len, float *out, int *out_len) 950int 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
826void speex_resampler_process_interleaved_int(SpeexResamplerState *st, const spx_int16_t *in, int *in_len, spx_int16_t *out, int *out_len) 968
969int 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
841void speex_resampler_set_rate(SpeexResamplerState *st, int in_rate, int out_rate) 987int 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
846void speex_resampler_get_rate(SpeexResamplerState *st, int *in_rate, int *out_rate) 992void 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
852void speex_resampler_set_rate_frac(SpeexResamplerState *st, int ratio_num, int ratio_den, int in_rate, int out_rate) 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)
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
876void speex_resampler_get_ratio(SpeexResamplerState *st, int *ratio_num, int *ratio_den) 1023void 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
882void speex_resampler_set_quality(SpeexResamplerState *st, int quality) 1029int 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
895void speex_resampler_get_quality(SpeexResamplerState *st, int *quality) 1041void 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
900void speex_resampler_set_input_stride(SpeexResamplerState *st, int stride) 1046void 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
905void speex_resampler_get_input_stride(SpeexResamplerState *st, int *stride) 1051void 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
910void speex_resampler_set_output_stride(SpeexResamplerState *st, int stride) 1056void 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
915void speex_resampler_get_output_stride(SpeexResamplerState *st, int *stride) 1061void 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
920void speex_resampler_skip_zeros(SpeexResamplerState *st) 1066int 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
927void speex_resampler_reset_mem(SpeexResamplerState *st) 1074int 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
1082const 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}