diff --git a/apps/codecs/libspeex/README.rockbox b/apps/codecs/libspeex/README.rockbox index 4280df4f02..7f7f975eb1 100644 --- a/apps/codecs/libspeex/README.rockbox +++ b/apps/codecs/libspeex/README.rockbox @@ -1,5 +1,5 @@ -Library: libspeex-1.2beta1 (SVN version 12449) -Imported: 2007-02-10 by Dan Everton +Library: libspeex-1.2beta1 (SVN version 12735) +Imported: 2007-03-12 by Dan Everton This directory contains a local version of libspeex for decoding Ogg/Speex @@ -16,7 +16,8 @@ license is described in the COPYING file in this directory. IMPORT DETAILS The .[ch] files from speex/libspeex/ and speex/include/ were imported -into Rockbox. This includes the test files. +into Rockbox. This includes the test files. Some hackery was done to +the include files so that they #include properly when built in Rockbox. A simple config.h file was added to enable libspeex's fixed-point integer-only mode and to specify the endianness of the target CPU. Also, @@ -26,3 +27,4 @@ Since some parts of Speex still rely on functions, a simple include was created to get these parts to compile. Stub functions can be found in rockbox.c in this directory. + diff --git a/apps/codecs/libspeex/SOURCES b/apps/codecs/libspeex/SOURCES index 16168b0277..df73565734 100644 --- a/apps/codecs/libspeex/SOURCES +++ b/apps/codecs/libspeex/SOURCES @@ -31,7 +31,6 @@ nb_celp.c oggframing.c preprocess.c quant_lsp.c -resample.c rockbox.c sb_celp.c smallft.c diff --git a/apps/codecs/libspeex/_kiss_fft_guts.h b/apps/codecs/libspeex/_kiss_fft_guts.h index 43a3ba57f9..526a73b701 100644 --- a/apps/codecs/libspeex/_kiss_fft_guts.h +++ b/apps/codecs/libspeex/_kiss_fft_guts.h @@ -68,6 +68,10 @@ struct kiss_fft_state{ do{ (m).r = sround( smul((a).r,(b).r) - smul((a).i,(b).i) ); \ (m).i = sround( smul((a).r,(b).i) + smul((a).i,(b).r) ); }while(0) +# define C_MUL4(m,a,b) \ + do{ (m).r = PSHR32( smul((a).r,(b).r) - smul((a).i,(b).i),17 ); \ + (m).i = PSHR32( smul((a).r,(b).i) + smul((a).i,(b).r),17 ); }while(0) + # define DIVSCALAR(x,k) \ (x) = sround( smul( x, SAMP_MAX/k ) ) @@ -85,6 +89,9 @@ struct kiss_fft_state{ #define C_MUL(m,a,b) \ do{ (m).r = (a).r*(b).r - (a).i*(b).i;\ (m).i = (a).r*(b).i + (a).i*(b).r; }while(0) + +#define C_MUL4(m,a,b) C_MUL(m,a,b) + # define C_FIXDIV(c,div) /* NOOP */ # define C_MULBYSCALAR( c, s ) \ do{ (c).r *= (s);\ diff --git a/apps/codecs/libspeex/fftwrap.c b/apps/codecs/libspeex/fftwrap.c index a1086408ed..35e2d05ab6 100644 --- a/apps/codecs/libspeex/fftwrap.c +++ b/apps/codecs/libspeex/fftwrap.c @@ -137,7 +137,6 @@ void spx_ifft(void *table, float *in, float *out) struct kiss_config { kiss_fftr_cfg forward; kiss_fftr_cfg backward; - kiss_fft_cpx *freq_data; int N; }; @@ -145,7 +144,6 @@ void *spx_fft_init(int size) { struct kiss_config *table; table = (struct kiss_config*)speex_alloc(sizeof(struct kiss_config)); - table->freq_data = (kiss_fft_cpx*)speex_alloc(sizeof(kiss_fft_cpx)*((size>>1)+1)); table->forward = kiss_fftr_alloc(size,0,NULL,NULL); table->backward = kiss_fftr_alloc(size,1,NULL,NULL); table->N = size; @@ -157,7 +155,6 @@ void spx_fft_destroy(void *table) struct kiss_config *t = (struct kiss_config *)table; kiss_fftr_free(t->forward); kiss_fftr_free(t->backward); - speex_free(t->freq_data); speex_free(table); } @@ -165,18 +162,10 @@ void spx_fft_destroy(void *table) void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out) { - int i; int shift; struct kiss_config *t = (struct kiss_config *)table; shift = maximize_range(in, in, 32000, t->N); - kiss_fftr(t->forward, in, t->freq_data); - out[0] = t->freq_data[0].r; - for (i=1;iN>>1;i++) - { - out[(i<<1)-1] = t->freq_data[i].r; - out[(i<<1)] = t->freq_data[i].i; - } - out[(i<<1)-1] = t->freq_data[i].r; + kiss_fftr2(t->forward, in, out); renorm_range(in, in, shift, t->N); renorm_range(out, out, shift, t->N); } @@ -189,32 +178,16 @@ void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out) float scale; struct kiss_config *t = (struct kiss_config *)table; scale = 1./t->N; - kiss_fftr(t->forward, in, t->freq_data); - out[0] = scale*t->freq_data[0].r; - for (i=1;iN>>1;i++) - { - out[(i<<1)-1] = scale*t->freq_data[i].r; - out[(i<<1)] = scale*t->freq_data[i].i; - } - out[(i<<1)-1] = scale*t->freq_data[i].r; + kiss_fftr2(t->forward, in, out); + for (i=0;iN;i++) + out[i] *= scale; } #endif void spx_ifft(void *table, spx_word16_t *in, spx_word16_t *out) { - int i; struct kiss_config *t = (struct kiss_config *)table; - t->freq_data[0].r = in[0]; - t->freq_data[0].i = 0; - for (i=1;iN>>1;i++) - { - t->freq_data[i].r = in[(i<<1)-1]; - t->freq_data[i].i = in[(i<<1)]; - } - t->freq_data[i].r = in[(i<<1)-1]; - t->freq_data[i].i = 0; - - kiss_fftri(t->backward, t->freq_data, out); + kiss_fftri2(t->backward, in, out); } diff --git a/apps/codecs/libspeex/jitter.c b/apps/codecs/libspeex/jitter.c index dc31c06407..ae60f73d1e 100644 --- a/apps/codecs/libspeex/jitter.c +++ b/apps/codecs/libspeex/jitter.c @@ -46,7 +46,7 @@ #define NULL 0 #endif -#define LATE_BINS 10 +#define LATE_BINS 15 #define MAX_MARGIN 30 /**< Number of bins in margin histogram */ #define SPEEX_JITTER_MAX_BUFFER_SIZE 200 /**< Maximum number of packets in jitter buffer */ @@ -71,7 +71,9 @@ struct JitterBuffer_ { int tick_size; /**< Output granularity */ int reset_state; /**< True if state was just reset */ int buffer_margin; /**< How many frames we want to keep in the buffer (lower bound) */ - + int late_cutoff; /**< How late must a packet be for it not to be considered at all */ + int interp_requested; /**< An interpolation is requested by speex_jitter_update_delay() */ + int lost_count; /**< Number of consecutive lost packets */ float shortterm_margin[MAX_MARGIN]; /**< Short term margin histogram */ float longterm_margin[MAX_MARGIN]; /**< Long term margin histogram */ @@ -89,6 +91,7 @@ JitterBuffer *jitter_buffer_init(int tick) jitter->buf[i]=NULL; jitter->tick_size = tick; jitter->buffer_margin = 1; + jitter->late_cutoff = 50; jitter_buffer_reset(jitter); } return jitter; @@ -130,7 +133,8 @@ void jitter_buffer_destroy(JitterBuffer *jitter) /** Put one packet into the jitter buffer */ void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet) { - int i,j; + int i; + unsigned int j; spx_int32_t arrival_margin; /*fprintf (stderr, "put packet %d %d\n", timestamp, span);*/ if (jitter->reset_state) @@ -144,6 +148,7 @@ void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet) /* Cleanup buffer (remove old packets that weren't played) */ for (i=0;ibuf[i] && LE32(jitter->timestamp[i] + jitter->span[i], jitter->pointer_timestamp)) { /*fprintf (stderr, "cleaned (not played)\n");*/ @@ -184,33 +189,39 @@ void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet) /* Copy packet in buffer */ jitter->buf[i]=(char*)speex_alloc(packet->len); - for (j=0;((unsigned)j)len;j++) + for (j=0;jlen;j++) jitter->buf[i][j]=packet->data[j]; jitter->timestamp[i]=packet->timestamp; jitter->span[i]=packet->span; jitter->len[i]=packet->len; - /* Adjust the buffer size depending on network conditions */ - arrival_margin = (packet->timestamp - jitter->current_timestamp) - jitter->buffer_margin*jitter->tick_size; + /* Adjust the buffer size depending on network conditions. + The arrival margin is how much in advance (or late) the packet it */ + arrival_margin = (packet->timestamp - jitter->current_timestamp)/jitter->tick_size - jitter->buffer_margin; - if (arrival_margin >= -LATE_BINS*jitter->tick_size) + if (arrival_margin >= -jitter->late_cutoff) { + /* Here we compute the histogram based on the time of arrival of the packet. + This is based on a (first-order) recursive average. We keep both a short-term + histogram and a long-term histogram */ spx_int32_t int_margin; + /* First, apply the "damping" of the recursive average to all bins */ for (i=0;ishortterm_margin[i] *= .98; jitter->longterm_margin[i] *= .995; } - int_margin = LATE_BINS + arrival_margin/jitter->tick_size; + /* What histogram bin the packet should be counted in */ + int_margin = LATE_BINS + arrival_margin; if (int_margin>MAX_MARGIN-1) int_margin = MAX_MARGIN-1; - if (int_margin>=0) - { - jitter->shortterm_margin[int_margin] += .02; - jitter->longterm_margin[int_margin] += .005; - } + if (int_margin<0) + int_margin = 0; + /* Add the packet to the right bin */ + jitter->shortterm_margin[int_margin] += .02; + jitter->longterm_margin[int_margin] += .005; } else { - + /* Packet has arrived *way* too late, we pretty much consider it lost and not take it into account in the histogram */ /*fprintf (stderr, "way too late = %d\n", arrival_margin);*/ if (jitter->lost_count>20) { @@ -234,7 +245,8 @@ void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet) /** Get one packet from the jitter buffer */ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_uint32_t *start_offset) { - int i, j; + int i; + unsigned int j; float late_ratio_short; float late_ratio_long; float ontime_ratio_short; @@ -244,6 +256,17 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_uint int chunk_size; int incomplete = 0; + if (jitter->interp_requested) + { + jitter->interp_requested = 0; + if (start_offset) + *start_offset = 0; + packet->timestamp = jitter->pointer_timestamp; + packet->span = jitter->tick_size; + jitter->pointer_timestamp += jitter->tick_size; + packet->len = 0; + return JITTER_BUFFER_MISSING; + } if (LT32(jitter->current_timestamp+jitter->tick_size, jitter->pointer_timestamp)) { jitter->current_timestamp = jitter->pointer_timestamp; @@ -258,14 +281,17 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_uint late_ratio_short = 0; late_ratio_long = 0; + /* Count the proportion of packets that are late */ for (i=0;ishortterm_margin[i]; late_ratio_long += jitter->longterm_margin[i]; } + /* Count the proportion of packets that are just on time */ ontime_ratio_short = jitter->shortterm_margin[LATE_BINS]; ontime_ratio_long = jitter->longterm_margin[LATE_BINS]; early_ratio_short = early_ratio_long = 0; + /* Count the proportion of packets that are early */ for (i=LATE_BINS+1;ishortterm_margin[i]; @@ -277,42 +303,6 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_uint /*fprintf (stderr, "%f %f\n", early_ratio_short + ontime_ratio_short + late_ratio_short, early_ratio_long + ontime_ratio_long + late_ratio_long);*/ } - /* Adjusting the buffering */ - - if (late_ratio_short > .1 || late_ratio_long > .03) - { - /* If too many packets are arriving late */ - jitter->shortterm_margin[MAX_MARGIN-1] += jitter->shortterm_margin[MAX_MARGIN-2]; - jitter->longterm_margin[MAX_MARGIN-1] += jitter->longterm_margin[MAX_MARGIN-2]; - for (i=MAX_MARGIN-3;i>=0;i--) - { - jitter->shortterm_margin[i+1] = jitter->shortterm_margin[i]; - jitter->longterm_margin[i+1] = jitter->longterm_margin[i]; - } - jitter->shortterm_margin[0] = 0; - jitter->longterm_margin[0] = 0; - jitter->pointer_timestamp -= jitter->tick_size; - jitter->current_timestamp -= jitter->tick_size; - /*fprintf (stderr, "i");*/ - /*fprintf (stderr, "interpolate (getting some slack)\n");*/ - } else if (late_ratio_short + ontime_ratio_short < .005 && late_ratio_long + ontime_ratio_long < .01 && early_ratio_short > .8) - { - /* Many frames arriving early */ - jitter->shortterm_margin[0] += jitter->shortterm_margin[1]; - jitter->longterm_margin[0] += jitter->longterm_margin[1]; - for (i=1;ishortterm_margin[i] = jitter->shortterm_margin[i+1]; - jitter->longterm_margin[i] = jitter->longterm_margin[i+1]; - } - jitter->shortterm_margin[MAX_MARGIN-1] = 0; - jitter->longterm_margin[MAX_MARGIN-1] = 0; - /*fprintf (stderr, "drop frame\n");*/ - /*fprintf (stderr, "d");*/ - jitter->pointer_timestamp += jitter->tick_size; - jitter->current_timestamp += jitter->tick_size; - /*fprintf (stderr, "dropping packet (getting more aggressive)\n");*/ - } /* Searching for the packet that fits best */ @@ -328,7 +318,7 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_uint { for (i=0;ibuf[i] && jitter->timestamp[i]<=jitter->pointer_timestamp && GE32(jitter->timestamp[i]+jitter->span[i],jitter->pointer_timestamp+chunk_size)) + if (jitter->buf[i] && LE32(jitter->timestamp[i], jitter->pointer_timestamp) && GE32(jitter->timestamp[i]+jitter->span[i],jitter->pointer_timestamp+chunk_size)) break; } } @@ -338,7 +328,7 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_uint { for (i=0;ibuf[i] && jitter->timestamp[i]<=jitter->pointer_timestamp && GT32(jitter->timestamp[i]+jitter->span[i],jitter->pointer_timestamp)) + if (jitter->buf[i] && LE32(jitter->timestamp[i], jitter->pointer_timestamp) && GT32(jitter->timestamp[i]+jitter->span[i],jitter->pointer_timestamp)) break; } } @@ -381,7 +371,7 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_uint /* Check for potential overflow */ packet->len = jitter->len[i]; /* Copy packet */ - for (j=0;((unsigned)j)len;j++) + for (j=0;jlen;j++) packet->data[j] = jitter->buf[i][j]; /* Remove packet */ speex_free(jitter->buf[i]); @@ -412,6 +402,26 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_uint packet->span = jitter->tick_size; jitter->pointer_timestamp += chunk_size; packet->len = 0; + + /* Adjusting the buffering bssed on the amount of packets that are early/on time/late */ + if (late_ratio_short > .1 || late_ratio_long > .03) + { + /* If too many packets are arriving late */ + jitter->shortterm_margin[MAX_MARGIN-1] += jitter->shortterm_margin[MAX_MARGIN-2]; + jitter->longterm_margin[MAX_MARGIN-1] += jitter->longterm_margin[MAX_MARGIN-2]; + for (i=MAX_MARGIN-3;i>=0;i--) + { + jitter->shortterm_margin[i+1] = jitter->shortterm_margin[i]; + jitter->longterm_margin[i+1] = jitter->longterm_margin[i]; + } + jitter->shortterm_margin[0] = 0; + jitter->longterm_margin[0] = 0; + jitter->pointer_timestamp -= jitter->tick_size; + jitter->current_timestamp -= jitter->tick_size; + /*fprintf (stderr, "i");*/ + /*fprintf (stderr, "interpolate (getting some slack)\n");*/ + } + return JITTER_BUFFER_MISSING; } @@ -427,9 +437,88 @@ void jitter_buffer_tick(JitterBuffer *jitter) jitter->current_timestamp += jitter->tick_size; } +/* Let the jitter buffer know it's the right time to adjust the buffering delay to the network conditions */ +int jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet, spx_uint32_t *start_offset) +{ + int i; + float late_ratio_short; + float late_ratio_long; + float ontime_ratio_short; + float ontime_ratio_long; + float early_ratio_short; + float early_ratio_long; + + if (LT32(jitter->current_timestamp+jitter->tick_size, jitter->pointer_timestamp)) + { + jitter->current_timestamp = jitter->pointer_timestamp; + speex_warning("did you forget to call jitter_buffer_tick() by any chance?"); + } + /*fprintf (stderr, "get packet %d %d\n", jitter->pointer_timestamp, jitter->current_timestamp);*/ + + /* FIXME: This should be only what remaining of the current tick */ + late_ratio_short = 0; + late_ratio_long = 0; + /* Count the proportion of packets that are late */ + for (i=0;ishortterm_margin[i]; + late_ratio_long += jitter->longterm_margin[i]; + } + /* Count the proportion of packets that are just on time */ + ontime_ratio_short = jitter->shortterm_margin[LATE_BINS]; + ontime_ratio_long = jitter->longterm_margin[LATE_BINS]; + early_ratio_short = early_ratio_long = 0; + /* Count the proportion of packets that are early */ + for (i=LATE_BINS+1;ishortterm_margin[i]; + early_ratio_long += jitter->longterm_margin[i]; + } + + /* Adjusting the buffering bssed on the amount of packets that are early/on time/late */ + if (late_ratio_short > .1 || late_ratio_long > .03) + { + /* If too many packets are arriving late */ + jitter->shortterm_margin[MAX_MARGIN-1] += jitter->shortterm_margin[MAX_MARGIN-2]; + jitter->longterm_margin[MAX_MARGIN-1] += jitter->longterm_margin[MAX_MARGIN-2]; + for (i=MAX_MARGIN-3;i>=0;i--) + { + jitter->shortterm_margin[i+1] = jitter->shortterm_margin[i]; + jitter->longterm_margin[i+1] = jitter->longterm_margin[i]; + } + jitter->shortterm_margin[0] = 0; + jitter->longterm_margin[0] = 0; + jitter->pointer_timestamp -= jitter->tick_size; + jitter->current_timestamp -= jitter->tick_size; + jitter->interp_requested = 1; + return JITTER_BUFFER_ADJUST_INTERPOLATE; + + } else if (late_ratio_short + ontime_ratio_short < .005 && late_ratio_long + ontime_ratio_long < .01 && early_ratio_short > .8) + { + /* Many frames arriving early */ + jitter->shortterm_margin[0] += jitter->shortterm_margin[1]; + jitter->longterm_margin[0] += jitter->longterm_margin[1]; + for (i=1;ishortterm_margin[i] = jitter->shortterm_margin[i+1]; + jitter->longterm_margin[i] = jitter->longterm_margin[i+1]; + } + jitter->shortterm_margin[MAX_MARGIN-1] = 0; + jitter->longterm_margin[MAX_MARGIN-1] = 0; + /*fprintf (stderr, "drop frame\n");*/ + /*fprintf (stderr, "d");*/ + jitter->pointer_timestamp += jitter->tick_size; + jitter->current_timestamp += jitter->tick_size; + return JITTER_BUFFER_ADJUST_DROP; + } + + return JITTER_BUFFER_ADJUST_OK; +} + /* Used like the ioctl function to control the jitter buffer parameters */ int jitter_buffer_ctl(JitterBuffer *jitter, int request, void *ptr) { + int count, i; switch(request) { case JITTER_BUFFER_SET_MARGIN: @@ -438,6 +527,17 @@ int jitter_buffer_ctl(JitterBuffer *jitter, int request, void *ptr) case JITTER_BUFFER_GET_MARGIN: *(spx_int32_t*)ptr = jitter->buffer_margin; break; + case JITTER_BUFFER_GET_AVALIABLE_COUNT: + count = 0; + for (i=0;ibuf[i] && LE32(jitter->pointer_timestamp, jitter->timestamp[i])) + { + count++; + } + } + *(spx_int32_t*)ptr = count; + break; default: speex_warning_int("Unknown jitter_buffer_ctl request: ", request); return -1; @@ -518,6 +618,7 @@ void speex_jitter_get(SpeexJitter *jitter, short *out, int *current_timestamp) out[i]=0; } } + jitter_buffer_update_delay(jitter->packets, &packet, NULL); jitter_buffer_tick(jitter->packets); } diff --git a/apps/codecs/libspeex/kiss_fft.c b/apps/codecs/libspeex/kiss_fft.c index 4ab31f26fb..449e7b8fa7 100644 --- a/apps/codecs/libspeex/kiss_fft.c +++ b/apps/codecs/libspeex/kiss_fft.c @@ -1,5 +1,6 @@ /* Copyright (c) 2003-2004, Mark Borgerding +Copyright (c) 2005-2007, Jean-Marc Valin All rights reserved. @@ -24,121 +25,143 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND fixed or floating point complex numbers. It also delares the kf_ internal functions. */ -static kiss_fft_cpx *scratchbuf=NULL; -static size_t nscratchbuf=0; -static kiss_fft_cpx *tmpbuf=NULL; -static size_t ntmpbuf=0; - -#define CHECKBUF(buf,nbuf,n) \ - do { \ - if ( nbuf < (size_t)(n) ) {\ - speex_free(buf); \ - buf = (kiss_fft_cpx*)KISS_FFT_MALLOC(sizeof(kiss_fft_cpx)*(n)); \ - nbuf = (size_t)(n); \ - } \ - }while(0) - static void kf_bfly2( kiss_fft_cpx * Fout, const size_t fstride, const kiss_fft_cfg st, - int m + int m, + int N, + int mm ) { kiss_fft_cpx * Fout2; - kiss_fft_cpx * tw1 = st->twiddles; + kiss_fft_cpx * tw1; kiss_fft_cpx t; - Fout2 = Fout + m; if (!st->inverse) { - int i; - kiss_fft_cpx *x=Fout; - for (i=0;i<2*m;i++) + int i,j; + kiss_fft_cpx * Fout_beg = Fout; + for (i=0;itwiddles; + for(j=0;jr , tw1->r),MULT16_16(Fout2->i , tw1->i)), 1); + ti = SHR32(ADD32(MULT16_16(Fout2->i , tw1->r),MULT16_16(Fout2->r , tw1->i)), 1); + tw1 += fstride; + Fout2->r = PSHR32(SUB32(SHL32(EXTEND32(Fout->r), 14), tr), 15); + Fout2->i = PSHR32(SUB32(SHL32(EXTEND32(Fout->i), 14), ti), 15); + Fout->r = PSHR32(ADD32(SHL32(EXTEND32(Fout->r), 14), tr), 15); + Fout->i = PSHR32(ADD32(SHL32(EXTEND32(Fout->i), 14), ti), 15); + ++Fout2; + ++Fout; + } + } + } else { + int i,j; + kiss_fft_cpx * Fout_beg = Fout; + for (i=0;itwiddles; + for(j=0;jtwiddles; - - if (!st->inverse) { - unsigned int i; - kiss_fft_cpx *x=Fout; - for (i=0;i<4*m;i++) - { - x[i].r = PSHR16(x[i].r,2); - x[i].i = PSHR16(x[i].i,2); - } - } if (st->inverse) { - do { - C_MUL(scratch[0],Fout[m] , *tw1 ); - C_MUL(scratch[1],Fout[m2] , *tw2 ); - C_MUL(scratch[2],Fout[m3] , *tw3 ); - - C_SUB( scratch[5] , *Fout, scratch[1] ); - C_ADDTO(*Fout, scratch[1]); - C_ADD( scratch[3] , scratch[0] , scratch[2] ); - C_SUB( scratch[4] , scratch[0] , scratch[2] ); - C_SUB( Fout[m2], *Fout, scratch[3] ); - tw1 += fstride; - tw2 += fstride*2; - tw3 += fstride*3; - C_ADDTO( *Fout , scratch[3] ); - - Fout[m].r = scratch[5].r - scratch[4].i; - Fout[m].i = scratch[5].i + scratch[4].r; - Fout[m3].r = scratch[5].r + scratch[4].i; - Fout[m3].i = scratch[5].i - scratch[4].r; - ++Fout; - } while(--k); + kiss_fft_cpx * Fout_beg = Fout; + for (i=0;itwiddles; + for (j=0;jtwiddles; + for (j=0;jr = PSHR16(Fout->r, 2); + Fout->i = PSHR16(Fout->i, 2); + C_SUB( scratch[5] , *Fout, scratch[1] ); + C_ADDTO(*Fout, scratch[1]); + C_ADD( scratch[3] , scratch[0] , scratch[2] ); + C_SUB( scratch[4] , scratch[0] , scratch[2] ); + Fout[m2].r = PSHR16(Fout[m2].r, 2); + Fout[m2].i = PSHR16(Fout[m2].i, 2); + C_SUB( Fout[m2], *Fout, scratch[3] ); + tw1 += fstride; + tw2 += fstride*2; + tw3 += fstride*3; + C_ADDTO( *Fout , scratch[3] ); + + Fout[m].r = scratch[5].r + scratch[4].i; + Fout[m].i = scratch[5].i - scratch[4].r; + Fout[m3].r = scratch[5].r - scratch[4].i; + Fout[m3].i = scratch[5].i + scratch[4].r; + ++Fout; + } + } } } @@ -263,10 +286,13 @@ static void kf_bfly_generic( int u,k,q1,q; kiss_fft_cpx * twiddles = st->twiddles; kiss_fft_cpx t; + kiss_fft_cpx scratchbuf[17]; int Norig = st->nfft; - CHECKBUF(scratchbuf,nscratchbuf,p); - + /*CHECKBUF(scratchbuf,nscratchbuf,p);*/ + if (p>17) + speex_error("KissFFT: max radix supported is 17"); + for ( u=0; unfft); - kf_work(tmpbuf,fin,1,in_stride, st->factors,st); - speex_move(fout,tmpbuf,sizeof(kiss_fft_cpx)*st->nfft); - }else{ - kf_work( fout, fin, 1,in_stride, st->factors,st ); + if (fin == fout) + { + speex_error("In-place FFT not supported"); + /*CHECKBUF(tmpbuf,ntmpbuf,st->nfft); + kf_work(tmpbuf,fin,1,in_stride, st->factors,st); + speex_move(fout,tmpbuf,sizeof(kiss_fft_cpx)*st->nfft);*/ + } else { + kf_shuffle( fout, fin, 1,in_stride, st->factors,st); + kf_work( fout, fin, 1,in_stride, st->factors,st, 1, in_stride, 1); } } @@ -419,16 +521,3 @@ void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout) kiss_fft_stride(cfg,fin,fout,1); } - -/* not really necessary to call, but if someone is doing in-place ffts, they may want to free the - buffers from CHECKBUF - */ -void kiss_fft_cleanup(void) -{ - speex_free(scratchbuf); - scratchbuf = NULL; - nscratchbuf=0; - speex_free(tmpbuf); - tmpbuf=NULL; - ntmpbuf=0; -} diff --git a/apps/codecs/libspeex/kiss_fftr.c b/apps/codecs/libspeex/kiss_fftr.c index 95c4573326..392945cb81 100644 --- a/apps/codecs/libspeex/kiss_fftr.c +++ b/apps/codecs/libspeex/kiss_fftr.c @@ -132,7 +132,7 @@ void kiss_fftr(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_cpx *fr } } -void kiss_fftri(kiss_fftr_cfg st,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata) +void kiss_fftri(kiss_fftr_cfg st,const kiss_fft_cpx *freqdata, kiss_fft_scalar *timedata) { /* input buffer timedata is stored row-wise */ int k, ncfft; @@ -168,3 +168,129 @@ void kiss_fftri(kiss_fftr_cfg st,const kiss_fft_cpx *freqdata,kiss_fft_scalar *t } kiss_fft (st->substate, st->tmpbuf, (kiss_fft_cpx *) timedata); } + +void kiss_fftr2(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_scalar *freqdata) +{ + /* input buffer timedata is stored row-wise */ + int k,ncfft; + kiss_fft_cpx f2k,tdc; + spx_word32_t f1kr, f1ki, twr, twi; + + if ( st->substate->inverse) { + speex_error("kiss fft usage error: improper alloc\n"); + } + + ncfft = st->substate->nfft; + + /*perform the parallel fft of two real signals packed in real,imag*/ + kiss_fft( st->substate , (const kiss_fft_cpx*)timedata, st->tmpbuf ); + /* The real part of the DC element of the frequency spectrum in st->tmpbuf + * contains the sum of the even-numbered elements of the input time sequence + * The imag part is the sum of the odd-numbered elements + * + * The sum of tdc.r and tdc.i is the sum of the input time sequence. + * yielding DC of input time sequence + * The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1... + * yielding Nyquist bin of input time sequence + */ + + tdc.r = st->tmpbuf[0].r; + tdc.i = st->tmpbuf[0].i; + C_FIXDIV(tdc,2); + CHECK_OVERFLOW_OP(tdc.r ,+, tdc.i); + CHECK_OVERFLOW_OP(tdc.r ,-, tdc.i); + freqdata[0] = tdc.r + tdc.i; + freqdata[2*ncfft-1] = tdc.r - tdc.i; + + for ( k=1;k <= ncfft/2 ; ++k ) + { + /*fpk = st->tmpbuf[k]; + fpnk.r = st->tmpbuf[ncfft-k].r; + fpnk.i = - st->tmpbuf[ncfft-k].i; + C_FIXDIV(fpk,2); + C_FIXDIV(fpnk,2); + + C_ADD( f1k, fpk , fpnk ); + C_SUB( f2k, fpk , fpnk ); + + C_MUL( tw , f2k , st->super_twiddles[k]); + + freqdata[2*k-1] = HALF_OF(f1k.r + tw.r); + freqdata[2*k] = HALF_OF(f1k.i + tw.i); + freqdata[2*(ncfft-k)-1] = HALF_OF(f1k.r - tw.r); + freqdata[2*(ncfft-k)] = HALF_OF(tw.i - f1k.i); + */ + + /*f1k.r = PSHR32(ADD32(EXTEND32(st->tmpbuf[k].r), EXTEND32(st->tmpbuf[ncfft-k].r)),1); + f1k.i = PSHR32(SUB32(EXTEND32(st->tmpbuf[k].i), EXTEND32(st->tmpbuf[ncfft-k].i)),1); + f2k.r = PSHR32(SUB32(EXTEND32(st->tmpbuf[k].r), EXTEND32(st->tmpbuf[ncfft-k].r)),1); + f2k.i = SHR32(ADD32(EXTEND32(st->tmpbuf[k].i), EXTEND32(st->tmpbuf[ncfft-k].i)),1); + + C_MUL( tw , f2k , st->super_twiddles[k]); + + freqdata[2*k-1] = HALF_OF(f1k.r + tw.r); + freqdata[2*k] = HALF_OF(f1k.i + tw.i); + freqdata[2*(ncfft-k)-1] = HALF_OF(f1k.r - tw.r); + freqdata[2*(ncfft-k)] = HALF_OF(tw.i - f1k.i); + */ + f2k.r = SHR32(SUB32(EXTEND32(st->tmpbuf[k].r), EXTEND32(st->tmpbuf[ncfft-k].r)),1); + f2k.i = PSHR32(ADD32(EXTEND32(st->tmpbuf[k].i), EXTEND32(st->tmpbuf[ncfft-k].i)),1); + + f1kr = SHL32(ADD32(EXTEND32(st->tmpbuf[k].r), EXTEND32(st->tmpbuf[ncfft-k].r)),13); + f1ki = SHL32(SUB32(EXTEND32(st->tmpbuf[k].i), EXTEND32(st->tmpbuf[ncfft-k].i)),13); + + twr = SHR32(SUB32(MULT16_16(f2k.r,st->super_twiddles[k].r),MULT16_16(f2k.i,st->super_twiddles[k].i)), 1); + twi = SHR32(ADD32(MULT16_16(f2k.i,st->super_twiddles[k].r),MULT16_16(f2k.r,st->super_twiddles[k].i)), 1); + +#ifdef FIXED_POINT + freqdata[2*k-1] = PSHR32(f1kr + twr, 15); + freqdata[2*k] = PSHR32(f1ki + twi, 15); + freqdata[2*(ncfft-k)-1] = PSHR32(f1kr - twr, 15); + freqdata[2*(ncfft-k)] = PSHR32(twi - f1ki, 15); +#else + freqdata[2*k-1] = .5f*(f1kr + twr); + freqdata[2*k] = .5f*(f1ki + twi); + freqdata[2*(ncfft-k)-1] = .5f*(f1kr - twr); + freqdata[2*(ncfft-k)] = .5f*(twi - f1ki); + +#endif + } +} + +void kiss_fftri2(kiss_fftr_cfg st,const kiss_fft_scalar *freqdata,kiss_fft_scalar *timedata) +{ + /* input buffer timedata is stored row-wise */ + int k, ncfft; + + if (st->substate->inverse == 0) { + speex_error ("kiss fft usage error: improper alloc\n"); + } + + ncfft = st->substate->nfft; + + st->tmpbuf[0].r = freqdata[0] + freqdata[2*ncfft-1]; + st->tmpbuf[0].i = freqdata[0] - freqdata[2*ncfft-1]; + /*C_FIXDIV(st->tmpbuf[0],2);*/ + + for (k = 1; k <= ncfft / 2; ++k) { + kiss_fft_cpx fk, fnkc, fek, fok, tmp; + fk.r = freqdata[2*k-1]; + fk.i = freqdata[2*k]; + fnkc.r = freqdata[2*(ncfft - k)-1]; + fnkc.i = -freqdata[2*(ncfft - k)]; + /*C_FIXDIV( fk , 2 ); + C_FIXDIV( fnkc , 2 );*/ + + C_ADD (fek, fk, fnkc); + C_SUB (tmp, fk, fnkc); + C_MUL (fok, tmp, st->super_twiddles[k]); + C_ADD (st->tmpbuf[k], fek, fok); + C_SUB (st->tmpbuf[ncfft - k], fek, fok); +#ifdef USE_SIMD + st->tmpbuf[ncfft - k].i *= _mm_set1_ps(-1.0); +#else + st->tmpbuf[ncfft - k].i *= -1; +#endif + } + kiss_fft (st->substate, st->tmpbuf, (kiss_fft_cpx *) timedata); +} diff --git a/apps/codecs/libspeex/kiss_fftr.h b/apps/codecs/libspeex/kiss_fftr.h index 2e8351a640..7bfb423340 100644 --- a/apps/codecs/libspeex/kiss_fftr.h +++ b/apps/codecs/libspeex/kiss_fftr.h @@ -32,7 +32,12 @@ void kiss_fftr(kiss_fftr_cfg cfg,const kiss_fft_scalar *timedata,kiss_fft_cpx *f output freqdata has nfft/2+1 complex points */ +void kiss_fftr2(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_scalar *freqdata); + void kiss_fftri(kiss_fftr_cfg cfg,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata); + +void kiss_fftri2(kiss_fftr_cfg st,const kiss_fft_scalar *freqdata, kiss_fft_scalar *timedata); + /* input freqdata has nfft/2+1 complex points output timedata has nfft scalar points diff --git a/apps/codecs/libspeex/mdf.c b/apps/codecs/libspeex/mdf.c index eac9f83588..498dd3908f 100644 --- a/apps/codecs/libspeex/mdf.c +++ b/apps/codecs/libspeex/mdf.c @@ -148,7 +148,7 @@ struct SpeexEchoState_ { spx_word32_t *PHI; /* scratch */ spx_word32_t *W; /* (Background) filter weights */ #ifdef TWO_PATH - spx_word32_t *foreground; /* Foreground filter weights */ + spx_word16_t *foreground; /* Foreground filter weights */ spx_word32_t Davg1; /* 1st recursive average of the residual power difference */ spx_word32_t Davg2; /* 2nd recursive average of the residual power difference */ spx_float_t Dvar1; /* Estimated variance of 1st estimator */ @@ -262,6 +262,34 @@ static inline void spectral_mul_accum(const spx_word16_t *X, const spx_word32_t } acc[N-1] = PSHR32(tmp1,WEIGHT_SHIFT); } +static inline void spectral_mul_accum16(const spx_word16_t *X, const spx_word16_t *Y, spx_word16_t *acc, int N, int M) +{ + int i,j; + spx_word32_t tmp1=0,tmp2=0; + for (j=0;jE = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t)); st->W = (spx_word32_t*)speex_alloc(M*N*sizeof(spx_word32_t)); #ifdef TWO_PATH - st->foreground = (spx_word32_t*)speex_alloc(M*N*sizeof(spx_word32_t)); + st->foreground = (spx_word16_t*)speex_alloc(M*N*sizeof(spx_word16_t)); #endif st->PHI = (spx_word32_t*)speex_alloc(N*sizeof(spx_word32_t)); st->power = (spx_word32_t*)speex_alloc((frame_size+1)*sizeof(spx_word32_t)); @@ -669,7 +698,7 @@ void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const sp #ifdef TWO_PATH /* Compute foreground filter */ - spectral_mul_accum(st->X, st->foreground, st->Y, N, M); + spectral_mul_accum16(st->X, st->foreground, st->Y, N, M); spx_ifft(st->fft_table, st->Y, st->e); for (i=0;iframe_size;i++) st->x[i+st->frame_size] = SUB16(st->input[i], st->e[i+st->frame_size]); @@ -777,7 +806,7 @@ void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const sp st->Dvar1 = st->Dvar2 = FLOAT_ZERO; /* Copy background filter to foreground filter */ for (i=0;iforeground[i] = st->W[i]; + st->foreground[i] = EXTRACT16(PSHR32(st->W[i],16)); /* Apply a smooth transition so as to not introduce blocking artifacts */ for (i=0;iframe_size;i++) st->e[i+st->frame_size] = MULT16_16_Q15(st->window[i+st->frame_size],st->e[i+st->frame_size]) + MULT16_16_Q15(st->window[i],st->y[i+st->frame_size]); @@ -794,7 +823,7 @@ void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const sp { /* Copy foreground filter to background filter */ for (i=0;iW[i] = st->foreground[i]; + st->W[i] = SHL32(EXTEND32(st->foreground[i]),16); /* We also need to copy the output so as to get correct adaptation */ for (i=0;iframe_size;i++) st->y[i+st->frame_size] = st->e[i+st->frame_size]; diff --git a/apps/codecs/libspeex/modes.h b/apps/codecs/libspeex/modes.h index 819be70e23..385cec007d 100644 --- a/apps/codecs/libspeex/modes.h +++ b/apps/codecs/libspeex/modes.h @@ -46,6 +46,20 @@ #define SB_SUBMODES 8 #define SB_SUBMODE_BITS 3 +/* Used internally, NOT TO BE USED in applications */ +/** Used internally*/ +#define SPEEX_GET_PI_GAIN 100 +/** Used internally*/ +#define SPEEX_GET_EXC 101 +/** Used internally*/ +#define SPEEX_GET_INNOV 102 +/** Used internally*/ +#define SPEEX_GET_DTX_STATUS 103 +/** Used internally*/ +#define SPEEX_SET_INNOVATION_SAVE 104 +/** Used internally*/ +#define SPEEX_SET_WIDEBAND 105 + /** Quantizes LSPs */ typedef void (*lsp_quant_func)(spx_lsp_t *, spx_lsp_t *, int, SpeexBits *); diff --git a/apps/codecs/libspeex/preprocess.c b/apps/codecs/libspeex/preprocess.c index bd4f776fd2..c4217f4ab3 100644 --- a/apps/codecs/libspeex/preprocess.c +++ b/apps/codecs/libspeex/preprocess.c @@ -255,7 +255,11 @@ static void conj_window(spx_word16_t *w, int len) for (i=0;i -#include "speex/speex_resampler.h" #ifndef M_PI #define M_PI 3.14159263 @@ -82,37 +83,6 @@ void speex_free (void *ptr) {free(ptr);} #define IMAX(a,b) ((a) > (b) ? (a) : (b)) -struct QualityMapping { - int base_length; - int oversample; - float downsample_bandwidth; - float upsample_bandwidth; -}; - -/* This table maps conversion quality to internal parameters. There are two - reasons that explain why the up-sampling bandwidth is larger than the - down-sampling bandwidth: - 1) When up-sampling, we can assume that the spectrum is already attenuated - close to the Nyquist rate (from an A/D or a previous resampling filter) - 2) Any aliasing that occurs very close to the Nyquist rate will be masked - by the sinusoids/noise just below the Nyquist rate (guaranteed only for - up-sampling). -*/ -const struct QualityMapping quality_map[11] = { - { 8, 4, 0.70f, 0.80f}, /* 0 */ - { 16, 4, 0.74f, 0.83f}, /* 1 */ - { 32, 4, 0.77f, 0.87f}, /* 2 */ - { 48, 8, 0.84f, 0.90f}, /* 3 */ - { 64, 8, 0.88f, 0.92f}, /* 4 */ - { 80, 8, 0.90f, 0.94f}, /* 5 */ - { 96, 8, 0.91f, 0.94f}, /* 6 */ - {128, 16, 0.93f, 0.95f}, /* 7 */ - {160, 16, 0.94f, 0.96f}, /* 8 */ - {192, 16, 0.95f, 0.96f}, /* 9 */ - {256, 16, 0.96f, 0.97f}, /* 10 */ -}; - -typedef enum {SPEEX_RESAMPLER_DIRECT_SINGLE=0, SPEEX_RESAMPLER_INTERPOLATE_SINGLE=1} SpeexSincType; typedef int (*resampler_basic_func)(SpeexResamplerState *, int , const spx_word16_t *, int *, spx_word16_t *, int *); @@ -145,34 +115,190 @@ struct SpeexResamplerState_ { int in_stride; int out_stride; - SpeexSincType type; } ; +static double kaiser12_table[68] = { + 0.99859849, 1.00000000, 0.99859849, 0.99440475, 0.98745105, 0.97779076, + 0.96549770, 0.95066529, 0.93340547, 0.91384741, 0.89213598, 0.86843014, + 0.84290116, 0.81573067, 0.78710866, 0.75723148, 0.72629970, 0.69451601, + 0.66208321, 0.62920216, 0.59606986, 0.56287762, 0.52980938, 0.49704014, + 0.46473455, 0.43304576, 0.40211431, 0.37206735, 0.34301800, 0.31506490, + 0.28829195, 0.26276832, 0.23854851, 0.21567274, 0.19416736, 0.17404546, + 0.15530766, 0.13794294, 0.12192957, 0.10723616, 0.09382272, 0.08164178, + 0.07063950, 0.06075685, 0.05193064, 0.04409466, 0.03718069, 0.03111947, + 0.02584161, 0.02127838, 0.01736250, 0.01402878, 0.01121463, 0.00886058, + 0.00691064, 0.00531256, 0.00401805, 0.00298291, 0.00216702, 0.00153438, + 0.00105297, 0.00069463, 0.00043489, 0.00025272, 0.00013031, 0.0000527734, + 0.00001000, 0.00000000}; +/* +static double kaiser12_table[36] = { + 0.99440475, 1.00000000, 0.99440475, 0.97779076, 0.95066529, 0.91384741, + 0.86843014, 0.81573067, 0.75723148, 0.69451601, 0.62920216, 0.56287762, + 0.49704014, 0.43304576, 0.37206735, 0.31506490, 0.26276832, 0.21567274, + 0.17404546, 0.13794294, 0.10723616, 0.08164178, 0.06075685, 0.04409466, + 0.03111947, 0.02127838, 0.01402878, 0.00886058, 0.00531256, 0.00298291, + 0.00153438, 0.00069463, 0.00025272, 0.0000527734, 0.00000500, 0.00000000}; +*/ +static double kaiser10_table[36] = { + 0.99537781, 1.00000000, 0.99537781, 0.98162644, 0.95908712, 0.92831446, + 0.89005583, 0.84522401, 0.79486424, 0.74011713, 0.68217934, 0.62226347, + 0.56155915, 0.50119680, 0.44221549, 0.38553619, 0.33194107, 0.28205962, + 0.23636152, 0.19515633, 0.15859932, 0.12670280, 0.09935205, 0.07632451, + 0.05731132, 0.04193980, 0.02979584, 0.02044510, 0.01345224, 0.00839739, + 0.00488951, 0.00257636, 0.00115101, 0.00035515, 0.00000000, 0.00000000}; + +static double kaiser8_table[36] = { + 0.99635258, 1.00000000, 0.99635258, 0.98548012, 0.96759014, 0.94302200, + 0.91223751, 0.87580811, 0.83439927, 0.78875245, 0.73966538, 0.68797126, + 0.63451750, 0.58014482, 0.52566725, 0.47185369, 0.41941150, 0.36897272, + 0.32108304, 0.27619388, 0.23465776, 0.19672670, 0.16255380, 0.13219758, + 0.10562887, 0.08273982, 0.06335451, 0.04724088, 0.03412321, 0.02369490, + 0.01563093, 0.00959968, 0.00527363, 0.00233883, 0.00050000, 0.00000000}; + +static double kaiser6_table[36] = { + 0.99733006, 1.00000000, 0.99733006, 0.98935595, 0.97618418, 0.95799003, + 0.93501423, 0.90755855, 0.87598009, 0.84068475, 0.80211977, 0.76076565, + 0.71712752, 0.67172623, 0.62508937, 0.57774224, 0.53019925, 0.48295561, + 0.43647969, 0.39120616, 0.34752997, 0.30580127, 0.26632152, 0.22934058, + 0.19505503, 0.16360756, 0.13508755, 0.10953262, 0.08693120, 0.06722600, + 0.05031820, 0.03607231, 0.02432151, 0.01487334, 0.00752000, 0.00000000}; + +struct FuncDef { + double *table; + int oversample; +}; + +static struct FuncDef _KAISER12 = {kaiser12_table, 64}; +#define KAISER12 (&_KAISER12) +/*static struct FuncDef _KAISER12 = {kaiser12_table, 32}; +#define KAISER12 (&_KAISER12)*/ +static struct FuncDef _KAISER10 = {kaiser10_table, 32}; +#define KAISER10 (&_KAISER10) +static struct FuncDef _KAISER8 = {kaiser8_table, 32}; +#define KAISER8 (&_KAISER8) +static struct FuncDef _KAISER6 = {kaiser6_table, 32}; +#define KAISER6 (&_KAISER6) + +struct QualityMapping { + int base_length; + int oversample; + float downsample_bandwidth; + float upsample_bandwidth; + struct FuncDef *window_func; +}; + + +/* This table maps conversion quality to internal parameters. There are two + reasons that explain why the up-sampling bandwidth is larger than the + down-sampling bandwidth: + 1) When up-sampling, we can assume that the spectrum is already attenuated + close to the Nyquist rate (from an A/D or a previous resampling filter) + 2) Any aliasing that occurs very close to the Nyquist rate will be masked + by the sinusoids/noise just below the Nyquist rate (guaranteed only for + up-sampling). +*/ +static const struct QualityMapping quality_map[11] = { + { 8, 4, 0.830f, 0.860f, KAISER6 }, /* Q0 */ + { 16, 4, 0.850f, 0.880f, KAISER6 }, /* Q1 */ + { 32, 4, 0.882f, 0.910f, KAISER6 }, /* Q2 */ /* 82.3% cutoff ( ~60 dB stop) 6 */ + { 48, 8, 0.895f, 0.917f, KAISER8 }, /* Q3 */ /* 84.9% cutoff ( ~80 dB stop) 8 */ + { 64, 8, 0.921f, 0.940f, KAISER8 }, /* Q4 */ /* 88.7% cutoff ( ~80 dB stop) 8 */ + { 80, 8, 0.922f, 0.940f, KAISER10}, /* Q5 */ /* 89.1% cutoff (~100 dB stop) 10 */ + { 96, 8, 0.940f, 0.945f, KAISER10}, /* Q6 */ /* 91.5% cutoff (~100 dB stop) 10 */ + {128, 16, 0.950f, 0.950f, KAISER10}, /* Q7 */ /* 93.1% cutoff (~100 dB stop) 10 */ + {160, 16, 0.960f, 0.960f, KAISER10}, /* Q8 */ /* 94.5% cutoff (~100 dB stop) 10 */ + {192, 16, 0.968f, 0.968f, KAISER12}, /* Q9 */ /* 95.5% cutoff (~100 dB stop) 10 */ + {256, 16, 0.975f, 0.975f, KAISER12}, /* Q10 */ /* 96.6% cutoff (~100 dB stop) 10 */ +}; +/*8,24,40,56,80,104,128,160,200,256,320*/ +static double compute_func(float x, struct FuncDef *func) +{ + float y, frac; + double interp[4]; + int ind; + y = x*func->oversample; + ind = (int)floor(y); + frac = (y-ind); + /* CSE with handle the repeated powers */ + interp[3] = -0.1666666667*frac + 0.1666666667*(frac*frac*frac); + interp[2] = frac + 0.5*(frac*frac) - 0.5*(frac*frac*frac); + /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac;*/ + interp[0] = -0.3333333333*frac + 0.5*(frac*frac) - 0.1666666667*(frac*frac*frac); + /* Just to make sure we don't have rounding problems */ + interp[1] = 1.f-interp[3]-interp[2]-interp[0]; + + /*sum = frac*accum[1] + (1-frac)*accum[2];*/ + return interp[0]*func->table[ind] + interp[1]*func->table[ind+1] + interp[2]*func->table[ind+2] + interp[3]*func->table[ind+3]; +} + +#if 0 +#include +int main(int argc, char **argv) +{ + int i; + for (i=0;i<256;i++) + { + printf ("%f\n", compute_func(i/256., KAISER12)); + } + return 0; +} +#endif + #ifdef FIXED_POINT /* The slow way of computing a sinc for the table. Should improve that some day */ -static spx_word16_t sinc(float cutoff, float x, int N) +static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func) { /*fprintf (stderr, "%f ", x);*/ - x *= cutoff; + float xx = x * cutoff; if (fabs(x)<1e-6f) return WORD2INT(32768.*cutoff); else if (fabs(x) > .5f*N) return 0; /*FIXME: Can it really be any slower than this? */ - return WORD2INT(32768.*cutoff*sin(M_PI*x)/(M_PI*x) * (.42+.5*cos(2*x*M_PI/N)+.08*cos(4*x*M_PI/N))); + return WORD2INT(32768.*cutoff*sin(M_PI*xx)/(M_PI*xx) * compute_func(fabs(2.*x/N), window_func)); } #else /* The slow way of computing a sinc for the table. Should improve that some day */ -static spx_word16_t sinc(float cutoff, float x, int N) +static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func) { /*fprintf (stderr, "%f ", x);*/ - x *= cutoff; + float xx = x * cutoff; if (fabs(x)<1e-6) return cutoff; else if (fabs(x) > .5*N) return 0; /*FIXME: Can it really be any slower than this? */ - return cutoff*sin(M_PI*x)/(M_PI*x) * (.42+.5*cos(2*x*M_PI/N)+.08*cos(4*x*M_PI/N)); + return cutoff*sin(M_PI*xx)/(M_PI*xx) * compute_func(fabs(2.*x/N), window_func); +} +#endif + +#ifdef FIXED_POINT +static void cubic_coef(spx_word16_t x, spx_word16_t interp[4]) +{ + /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation + but I know it's MMSE-optimal on a sinc */ + spx_word16_t x2, x3; + x2 = MULT16_16_P15(x, x); + x3 = MULT16_16_P15(x, x2); + interp[0] = PSHR32(MULT16_16(QCONST16(-0.16667f, 15),x) + MULT16_16(QCONST16(0.16667f, 15),x3),15); + interp[1] = EXTRACT16(EXTEND32(x) + SHR32(SUB32(EXTEND32(x2),EXTEND32(x3)),1)); + interp[3] = PSHR32(MULT16_16(QCONST16(-0.33333f, 15),x) + MULT16_16(QCONST16(.5f,15),x2) - MULT16_16(QCONST16(0.16667f, 15),x3),15); + /* Just to make sure we don't have rounding problems */ + interp[2] = Q15_ONE-interp[0]-interp[1]-interp[3]; + if (interp[2]<32767) + interp[2]+=1; +} +#else +static void cubic_coef(spx_word16_t frac, spx_word16_t interp[4]) +{ + /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation + but I know it's MMSE-optimal on a sinc */ + interp[0] = -0.16667f*frac + 0.16667f*frac*frac*frac; + interp[1] = frac + 0.5f*frac*frac - 0.5f*frac*frac*frac; + /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac;*/ + interp[3] = -0.33333f*frac + 0.5f*frac*frac - 0.16667f*frac*frac*frac; + /* Just to make sure we don't have rounding problems */ + interp[2] = 1.-interp[0]-interp[1]-interp[3]; } #endif @@ -221,6 +347,55 @@ static int resampler_basic_direct_single(SpeexResamplerState *st, int channel_in return out_sample; } +#ifdef FIXED_POINT +#else +/* This is the same as the previous function, except with a double-precision accumulator */ +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) +{ + int N = st->filt_len; + int out_sample = 0; + spx_word16_t *mem; + int last_sample = st->last_sample[channel_index]; + int samp_frac_num = st->samp_frac_num[channel_index]; + mem = st->mem + channel_index * st->mem_alloc_size; + while (!(last_sample >= *in_len || out_sample >= *out_len)) + { + int j; + double sum=0; + + /* We already have all the filter coefficients pre-computed in the table */ + const spx_word16_t *ptr; + /* Do the memory part */ + for (j=0;last_sample-N+1+j < 0;j++) + { + sum += MULT16_16(mem[last_sample+j],(double)st->sinc_table[samp_frac_num*st->filt_len+j]); + } + + /* Do the new part */ + ptr = in+st->in_stride*(last_sample-N+1+j); + for (;jsinc_table[samp_frac_num*st->filt_len+j]); + ptr += st->in_stride; + } + + *out = sum; + out += st->out_stride; + out_sample++; + last_sample += st->int_advance; + samp_frac_num += st->frac_advance; + if (samp_frac_num >= st->den_rate) + { + samp_frac_num -= st->den_rate; + last_sample++; + } + } + st->last_sample[channel_index] = last_sample; + st->samp_frac_num[channel_index] = samp_frac_num; + return out_sample; +} +#endif + 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) { int N = st->filt_len; @@ -236,11 +411,16 @@ static int resampler_basic_interpolate_single(SpeexResamplerState *st, int chann /* We need to interpolate the sinc filter */ spx_word32_t accum[4] = {0.f,0.f, 0.f, 0.f}; - float interp[4]; + spx_word16_t interp[4]; const spx_word16_t *ptr; - float alpha = ((float)samp_frac_num)/st->den_rate; - int offset = samp_frac_num*st->oversample/st->den_rate; - float frac = alpha*st->oversample - offset; + int offset; + spx_word16_t frac; + offset = samp_frac_num*st->oversample/st->den_rate; +#ifdef FIXED_POINT + frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate); +#else + frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate; +#endif /* This code is written like this to make it easy to optimise with SIMD. For most DSPs, it would be best to split the loops in two because most DSPs have only two accumulators */ @@ -263,16 +443,8 @@ static int resampler_basic_interpolate_single(SpeexResamplerState *st, int chann accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]); accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]); } - /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation - but I know it's MMSE-optimal on a sinc */ - interp[0] = -0.16667f*frac + 0.16667f*frac*frac*frac; - interp[1] = frac + 0.5f*frac*frac - 0.5f*frac*frac*frac; - /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac;*/ - interp[3] = -0.33333f*frac + 0.5f*frac*frac - 0.16667f*frac*frac*frac; - /* Just to make sure we don't have rounding problems */ - interp[2] = 1.f-interp[0]-interp[1]-interp[3]; - /*sum = frac*accum[1] + (1-frac)*accum[2];*/ - sum = interp[0]*accum[0] + interp[1]*accum[1] + interp[2]*accum[2] + interp[3]*accum[3]; + cubic_coef(frac, interp); + sum = MULT16_32_Q15(interp[0],accum[0]) + MULT16_32_Q15(interp[1],accum[1]) + MULT16_32_Q15(interp[2],accum[2]) + MULT16_32_Q15(interp[3],accum[3]); *out = PSHR32(sum,15); out += st->out_stride; @@ -290,6 +462,70 @@ static int resampler_basic_interpolate_single(SpeexResamplerState *st, int chann return out_sample; } +#ifdef FIXED_POINT +#else +/* This is the same as the previous function, except with a double-precision accumulator */ +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) +{ + int N = st->filt_len; + int out_sample = 0; + spx_word16_t *mem; + int last_sample = st->last_sample[channel_index]; + int samp_frac_num = st->samp_frac_num[channel_index]; + mem = st->mem + channel_index * st->mem_alloc_size; + while (!(last_sample >= *in_len || out_sample >= *out_len)) + { + int j; + spx_word32_t sum=0; + + /* We need to interpolate the sinc filter */ + double accum[4] = {0.f,0.f, 0.f, 0.f}; + float interp[4]; + const spx_word16_t *ptr; + float alpha = ((float)samp_frac_num)/st->den_rate; + int offset = samp_frac_num*st->oversample/st->den_rate; + float frac = alpha*st->oversample - offset; + /* This code is written like this to make it easy to optimise with SIMD. + For most DSPs, it would be best to split the loops in two because most DSPs + have only two accumulators */ + for (j=0;last_sample-N+1+j < 0;j++) + { + double curr_mem = mem[last_sample+j]; + accum[0] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-2]); + accum[1] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-1]); + accum[2] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset]); + accum[3] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset+1]); + } + ptr = in+st->in_stride*(last_sample-N+1+j); + /* Do the new part */ + for (;jin_stride; + accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]); + accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]); + accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]); + accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]); + } + cubic_coef(frac, interp); + sum = interp[0]*accum[0] + interp[1]*accum[1] + interp[2]*accum[2] + interp[3]*accum[3]; + + *out = PSHR32(sum,15); + out += st->out_stride; + out_sample++; + last_sample += st->int_advance; + samp_frac_num += st->frac_advance; + if (samp_frac_num >= st->den_rate) + { + samp_frac_num -= st->den_rate; + last_sample++; + } + } + st->last_sample[channel_index] = last_sample; + st->samp_frac_num[channel_index] = samp_frac_num; + return out_sample; +} +#endif static void update_filter(SpeexResamplerState *st) { @@ -328,11 +564,17 @@ static void update_filter(SpeexResamplerState *st) int j; for (j=0;jfilt_len;j++) { - 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); + 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); } } - st->type = SPEEX_RESAMPLER_DIRECT_SINGLE; +#ifdef FIXED_POINT st->resampler_ptr = resampler_basic_direct_single; +#else + if (st->quality>8) + st->resampler_ptr = resampler_basic_direct_double; + else + st->resampler_ptr = resampler_basic_direct_single; +#endif /*fprintf (stderr, "resampler uses direct sinc table and normalised cutoff %f\n", cutoff);*/ } else { if (!st->sinc_table) @@ -343,9 +585,15 @@ static void update_filter(SpeexResamplerState *st) st->sinc_table_length = st->filt_len*st->oversample+8; } for (i=-4;ioversample*st->filt_len+4;i++) - st->sinc_table[i+4] = sinc(st->cutoff,(i/(float)st->oversample - st->filt_len/2), st->filt_len); - st->type = SPEEX_RESAMPLER_INTERPOLATE_SINGLE; + 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); +#ifdef FIXED_POINT st->resampler_ptr = resampler_basic_interpolate_single; +#else + if (st->quality>8) + st->resampler_ptr = resampler_basic_interpolate_double; + else + st->resampler_ptr = resampler_basic_interpolate_single; +#endif /*fprintf (stderr, "resampler uses interpolated sinc table and normalised cutoff %f\n", cutoff);*/ } st->int_advance = st->num_rate/st->den_rate; @@ -405,8 +653,12 @@ static void update_filter(SpeexResamplerState *st) } +SpeexResamplerState *speex_resampler_init(int nb_channels, int in_rate, int out_rate, int quality) +{ + return speex_resampler_init_frac(nb_channels, in_rate, out_rate, in_rate, out_rate, quality); +} -SpeexResamplerState *speex_resampler_init(int nb_channels, int ratio_num, int ratio_den, int in_rate, int out_rate, int quality) +SpeexResamplerState *speex_resampler_init_frac(int nb_channels, int ratio_num, int ratio_den, int in_rate, int out_rate, int quality) { int i; SpeexResamplerState *st = (SpeexResamplerState *)speex_alloc(sizeof(SpeexResamplerState)); @@ -440,7 +692,7 @@ SpeexResamplerState *speex_resampler_init(int nb_channels, int ratio_num, int ra } speex_resampler_set_quality(st, quality); - speex_resampler_set_rate(st, ratio_num, ratio_den, in_rate, out_rate); + speex_resampler_set_rate_frac(st, ratio_num, ratio_den, in_rate, out_rate); update_filter(st); @@ -472,16 +724,26 @@ static void speex_resampler_process_native(SpeexResamplerState *st, int channel_ st->started = 1; /* Handle the case where we have samples left from a reduction in filter length */ - if (st->magic_samples) + if (st->magic_samples[channel_index]) { int tmp_in_len; + int tmp_magic; tmp_in_len = st->magic_samples[channel_index]; tmp_out_len = *out_len; /* FIXME: Need to handle the case where the out array is too small */ /* magic_samples needs to be set to zero to avoid infinite recursion */ - st->magic_samples = 0; + tmp_magic = st->magic_samples[channel_index]; + st->magic_samples[channel_index] = 0; speex_resampler_process_native(st, channel_index, mem+N-1, &tmp_in_len, out, &tmp_out_len); /*speex_warning_int("extra samples:", tmp_out_len);*/ + /* If we couldn't process all "magic" input samples, save the rest for next time */ + if (tmp_in_len < tmp_magic) + { + int i; + st->magic_samples[channel_index] = tmp_magic-tmp_in_len; + for (i=0;imagic_samples[channel_index];i++) + mem[N-1+i]=mem[N-1+i+tmp_in_len]; + } out += tmp_out_len; } @@ -536,13 +798,13 @@ void speex_resampler_process_int(SpeexResamplerState *st, int channel_index, con istride_save = st->in_stride; ostride_save = st->out_stride; for (i=0;i<*in_len;i++) - x[i] = in[i+st->in_stride]; + x[i] = in[i*st->in_stride]; st->in_stride = st->out_stride = 1; speex_resampler_process_native(st, channel_index, x, in_len, y, out_len); st->in_stride = istride_save; st->out_stride = ostride_save; for (i=0;i<*out_len;i++) - out[i+st->out_stride] = WORD2INT(y[i]); + out[i*st->out_stride] = WORD2INT(y[i]); } #endif @@ -561,8 +823,33 @@ void speex_resampler_process_interleaved_float(SpeexResamplerState *st, const fl st->out_stride = ostride_save; } +void speex_resampler_process_interleaved_int(SpeexResamplerState *st, const spx_int16_t *in, int *in_len, spx_int16_t *out, int *out_len) +{ + int i; + int istride_save, ostride_save; + istride_save = st->in_stride; + ostride_save = st->out_stride; + st->in_stride = st->out_stride = st->nb_channels; + for (i=0;inb_channels;i++) + { + speex_resampler_process_int(st, i, in+i, in_len, out+i, out_len); + } + st->in_stride = istride_save; + st->out_stride = ostride_save; +} -void speex_resampler_set_rate(SpeexResamplerState *st, int ratio_num, int ratio_den, int in_rate, int out_rate) +void speex_resampler_set_rate(SpeexResamplerState *st, int in_rate, int out_rate) +{ + speex_resampler_set_rate_frac(st, in_rate, out_rate, in_rate, out_rate); +} + +void speex_resampler_get_rate(SpeexResamplerState *st, int *in_rate, int *out_rate) +{ + *in_rate = st->in_rate; + *out_rate = st->out_rate; +} + +void speex_resampler_set_rate_frac(SpeexResamplerState *st, int ratio_num, int ratio_den, int in_rate, int out_rate) { int fact; if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den) @@ -586,6 +873,12 @@ void speex_resampler_set_rate(SpeexResamplerState *st, int ratio_num, int ratio_ update_filter(st); } +void speex_resampler_get_ratio(SpeexResamplerState *st, int *ratio_num, int *ratio_den) +{ + *ratio_num = st->num_rate; + *ratio_den = st->den_rate; +} + void speex_resampler_set_quality(SpeexResamplerState *st, int quality) { if (quality < 0) @@ -599,16 +892,31 @@ void speex_resampler_set_quality(SpeexResamplerState *st, int quality) update_filter(st); } +void speex_resampler_get_quality(SpeexResamplerState *st, int *quality) +{ + *quality = st->quality; +} + void speex_resampler_set_input_stride(SpeexResamplerState *st, int stride) { st->in_stride = stride; } +void speex_resampler_get_input_stride(SpeexResamplerState *st, int *stride) +{ + *stride = st->in_stride; +} + void speex_resampler_set_output_stride(SpeexResamplerState *st, int stride) { st->out_stride = stride; } +void speex_resampler_get_output_stride(SpeexResamplerState *st, int *stride) +{ + *stride = st->out_stride; +} + void speex_resampler_skip_zeros(SpeexResamplerState *st) { int i; diff --git a/apps/codecs/libspeex/sb_celp.c b/apps/codecs/libspeex/sb_celp.c index 61ca34efca..b1159cd687 100644 --- a/apps/codecs/libspeex/sb_celp.c +++ b/apps/codecs/libspeex/sb_celp.c @@ -236,17 +236,8 @@ void *sb_encoder_init(const SpeexMode *m) for (i=0;ilpcSize+1;i++) st->lagWindow[i]=16384*exp(-.5*sqr(2*M_PI*st->lag_factor*i)); - st->autocorr = (spx_word16_t*)speex_alloc((st->lpcSize+1)*sizeof(spx_word16_t)); - st->lpc = (spx_coef_t*)speex_alloc(st->lpcSize*sizeof(spx_coef_t)); - st->bw_lpc1 = (spx_coef_t*)speex_alloc(st->lpcSize*sizeof(spx_coef_t)); - st->bw_lpc2 = (spx_coef_t*)speex_alloc(st->lpcSize*sizeof(spx_coef_t)); - st->lsp = (spx_lsp_t*)speex_alloc(st->lpcSize*sizeof(spx_lsp_t)); - st->qlsp = (spx_lsp_t*)speex_alloc(st->lpcSize*sizeof(spx_lsp_t)); st->old_lsp = (spx_lsp_t*)speex_alloc(st->lpcSize*sizeof(spx_lsp_t)); st->old_qlsp = (spx_lsp_t*)speex_alloc(st->lpcSize*sizeof(spx_lsp_t)); - st->interp_lsp = (spx_lsp_t*)speex_alloc(st->lpcSize*sizeof(spx_lsp_t)); - st->interp_qlsp = (spx_lsp_t*)speex_alloc(st->lpcSize*sizeof(spx_lsp_t)); - st->interp_lpc = (spx_coef_t*)speex_alloc(st->lpcSize*sizeof(spx_coef_t)); st->interp_qlpc = (spx_coef_t*)speex_alloc(st->lpcSize*sizeof(spx_coef_t)); st->pi_gain = (spx_word32_t*)speex_alloc((st->nbSubframes)*sizeof(spx_word32_t)); st->exc_rms = (spx_word16_t*)speex_alloc((st->nbSubframes)*sizeof(spx_word16_t)); @@ -294,17 +285,8 @@ void sb_encoder_destroy(void *state) speex_free(st->lagWindow); - speex_free(st->autocorr); - speex_free(st->lpc); - speex_free(st->bw_lpc1); - speex_free(st->bw_lpc2); - speex_free(st->lsp); - speex_free(st->qlsp); speex_free(st->old_lsp); speex_free(st->old_qlsp); - speex_free(st->interp_lsp); - speex_free(st->interp_qlsp); - speex_free(st->interp_lpc); speex_free(st->interp_qlpc); speex_free(st->pi_gain); speex_free(st->exc_rms); @@ -336,7 +318,15 @@ int sb_encode(void *state, void *vin, SpeexBits *bits) spx_int32_t dtx; spx_word16_t *in = (spx_word16_t*)vin; spx_word16_t e_low=0, e_high=0; - + VARDECL(spx_coef_t *lpc); + VARDECL(spx_coef_t *interp_lpc); + VARDECL(spx_coef_t *bw_lpc1); + VARDECL(spx_coef_t *bw_lpc2); + VARDECL(spx_lsp_t *lsp); + VARDECL(spx_lsp_t *qlsp); + VARDECL(spx_lsp_t *interp_lsp); + VARDECL(spx_lsp_t *interp_qlsp); + st = (SBEncState*)state; stack=st->stack; mode = (const SpeexSBMode*)(st->mode->mode); @@ -378,8 +368,20 @@ int sb_encode(void *state, void *vin, SpeexBits *bits) else dtx=0; + ALLOC(lpc, st->lpcSize, spx_coef_t); + ALLOC(interp_lpc, st->lpcSize, spx_coef_t); + ALLOC(bw_lpc1, st->lpcSize, spx_coef_t); + ALLOC(bw_lpc2, st->lpcSize, spx_coef_t); + + ALLOC(lsp, st->lpcSize, spx_lsp_t); + ALLOC(qlsp, st->lpcSize, spx_lsp_t); + ALLOC(interp_lsp, st->lpcSize, spx_lsp_t); + ALLOC(interp_qlsp, st->lpcSize, spx_lsp_t); + { + VARDECL(spx_word16_t *autocorr); VARDECL(spx_word16_t *w_sig); + ALLOC(autocorr, st->lpcSize+1, spx_word16_t); ALLOC(w_sig, st->windowSize, spx_word16_t); /* Window for analysis */ /* FIXME: This is a kludge */ @@ -392,27 +394,27 @@ int sb_encode(void *state, void *vin, SpeexBits *bits) w_sig[i] = EXTRACT16(SHR32(MULT16_16(high[i],st->window[i]),SIG_SHIFT)); } /* Compute auto-correlation */ - _spx_autocorr(w_sig, st->autocorr, st->lpcSize+1, st->windowSize); + _spx_autocorr(w_sig, autocorr, st->lpcSize+1, st->windowSize); + autocorr[0] = ADD16(autocorr[0],MULT16_16_Q15(autocorr[0],st->lpc_floor)); /* Noise floor in auto-correlation domain */ + + /* Lag windowing: equivalent to filtering in the power-spectrum domain */ + for (i=0;ilpcSize+1;i++) + autocorr[i] = MULT16_16_Q14(autocorr[i],st->lagWindow[i]); + + /* Levinson-Durbin */ + _spx_lpc(lpc, autocorr, st->lpcSize); } - st->autocorr[0] = ADD16(st->autocorr[0],MULT16_16_Q15(st->autocorr[0],st->lpc_floor)); /* Noise floor in auto-correlation domain */ - - /* Lag windowing: equivalent to filtering in the power-spectrum domain */ - for (i=0;ilpcSize+1;i++) - st->autocorr[i] = MULT16_16_Q14(st->autocorr[i],st->lagWindow[i]); - - /* Levinson-Durbin */ - _spx_lpc(st->lpc, st->autocorr, st->lpcSize); /* LPC to LSPs (x-domain) transform */ - roots=lpc_to_lsp (st->lpc, st->lpcSize, st->lsp, 10, LSP_DELTA1, stack); + roots=lpc_to_lsp (lpc, st->lpcSize, lsp, 10, LSP_DELTA1, stack); if (roots!=st->lpcSize) { - roots = lpc_to_lsp (st->lpc, st->lpcSize, st->lsp, 10, LSP_DELTA2, stack); + roots = lpc_to_lsp (lpc, st->lpcSize, lsp, 10, LSP_DELTA2, stack); if (roots!=st->lpcSize) { /*If we can't find all LSP's, do some damage control and use a flat filter*/ for (i=0;ilpcSize;i++) { - st->lsp[i]=st->old_lsp[i]; + lsp[i]=st->old_lsp[i]; } } } @@ -524,14 +526,14 @@ int sb_encode(void *state, void *vin, SpeexBits *bits) /* LSP quantization */ - SUBMODE(lsp_quant)(st->lsp, st->qlsp, st->lpcSize, bits); + SUBMODE(lsp_quant)(lsp, qlsp, st->lpcSize, bits); if (st->first) { for (i=0;ilpcSize;i++) - st->old_lsp[i] = st->lsp[i]; + st->old_lsp[i] = lsp[i]; for (i=0;ilpcSize;i++) - st->old_qlsp[i] = st->qlsp[i]; + st->old_qlsp[i] = qlsp[i]; } ALLOC(mem, st->lpcSize, spx_mem_t); @@ -557,17 +559,17 @@ int sb_encode(void *state, void *vin, SpeexBits *bits) ALLOC(sw, st->subframeSize, spx_word16_t); /* LSP interpolation (quantized and unquantized) */ - lsp_interpolate(st->old_lsp, st->lsp, st->interp_lsp, st->lpcSize, sub, st->nbSubframes); - lsp_interpolate(st->old_qlsp, st->qlsp, st->interp_qlsp, st->lpcSize, sub, st->nbSubframes); + lsp_interpolate(st->old_lsp, lsp, interp_lsp, st->lpcSize, sub, st->nbSubframes); + lsp_interpolate(st->old_qlsp, qlsp, interp_qlsp, st->lpcSize, sub, st->nbSubframes); - lsp_enforce_margin(st->interp_lsp, st->lpcSize, LSP_MARGIN); - lsp_enforce_margin(st->interp_qlsp, st->lpcSize, LSP_MARGIN); + lsp_enforce_margin(interp_lsp, st->lpcSize, LSP_MARGIN); + lsp_enforce_margin(interp_qlsp, st->lpcSize, LSP_MARGIN); - lsp_to_lpc(st->interp_lsp, st->interp_lpc, st->lpcSize,stack); - lsp_to_lpc(st->interp_qlsp, st->interp_qlpc, st->lpcSize, stack); + lsp_to_lpc(interp_lsp, interp_lpc, st->lpcSize,stack); + lsp_to_lpc(interp_qlsp, st->interp_qlpc, st->lpcSize, stack); - bw_lpc(st->gamma1, st->interp_lpc, st->bw_lpc1, st->lpcSize); - bw_lpc(st->gamma2, st->interp_lpc, st->bw_lpc2, st->lpcSize); + bw_lpc(st->gamma1, interp_lpc, bw_lpc1, st->lpcSize); + bw_lpc(st->gamma2, interp_lpc, bw_lpc2, st->lpcSize); /* Compute mid-band (4000 Hz for wideband) response of low-band and high-band filters */ @@ -650,7 +652,7 @@ int sb_encode(void *state, void *vin, SpeexBits *bits) scale = SHL32(MULT16_16(PDIV32_16(SHL32(EXTEND32(gc),SIG_SHIFT-6),filter_ratio),(1+el)),6); - compute_impulse_response(st->interp_qlpc, st->bw_lpc1, st->bw_lpc2, syn_resp, st->subframeSize, st->lpcSize, stack); + compute_impulse_response(st->interp_qlpc, bw_lpc1, bw_lpc2, syn_resp, st->subframeSize, st->lpcSize, stack); /* Reset excitation */ @@ -664,12 +666,12 @@ int sb_encode(void *state, void *vin, SpeexBits *bits) for (i=0;ilpcSize;i++) mem[i]=st->mem_sw[i]; - filter_mem16(res, st->bw_lpc1, st->bw_lpc2, res, st->subframeSize, st->lpcSize, mem, stack); + filter_mem16(res, bw_lpc1, bw_lpc2, res, st->subframeSize, st->lpcSize, mem, stack); /* Compute weighted signal */ for (i=0;ilpcSize;i++) mem[i]=st->mem_sw[i]; - filter_mem16(sp, st->bw_lpc1, st->bw_lpc2, sw, st->subframeSize, st->lpcSize, mem, stack); + filter_mem16(sp, bw_lpc1, bw_lpc2, sw, st->subframeSize, st->lpcSize, mem, stack); /* Compute target signal */ for (i=0;isubframeSize;i++) @@ -682,7 +684,7 @@ int sb_encode(void *state, void *vin, SpeexBits *bits) innov[i]=0; /*print_vec(target, st->subframeSize, "\ntarget");*/ - SUBMODE(innovation_quant)(target, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2, + SUBMODE(innovation_quant)(target, st->interp_qlpc, bw_lpc1, bw_lpc2, SUBMODE(innovation_params), st->lpcSize, st->subframeSize, innov, syn_resp, bits, stack, st->complexity, SUBMODE(double_codebook)); /*print_vec(target, st->subframeSize, "after");*/ @@ -698,7 +700,7 @@ int sb_encode(void *state, void *vin, SpeexBits *bits) for (i=0;isubframeSize;i++) target[i]=MULT16_16_P13(QCONST16(2.5f,13), target[i]); - SUBMODE(innovation_quant)(target, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2, + SUBMODE(innovation_quant)(target, st->interp_qlpc, bw_lpc1, bw_lpc2, SUBMODE(innovation_params), st->lpcSize, st->subframeSize, innov2, syn_resp, bits, stack, st->complexity, 0); signal_mul(innov2, innov2, MULT16_32_P15(QCONST16(0.4f,15),scale), st->subframeSize); @@ -727,13 +729,13 @@ int sb_encode(void *state, void *vin, SpeexBits *bits) iir_mem16(exc, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, st->mem_sp, stack); /* Compute weighted signal again, from synthesized speech (not sure it's the right thing) */ - filter_mem16(sp, st->bw_lpc1, st->bw_lpc2, sw, st->subframeSize, st->lpcSize, st->mem_sw, stack); + filter_mem16(sp, bw_lpc1, bw_lpc2, sw, st->subframeSize, st->lpcSize, st->mem_sw, stack); } for (i=0;ilpcSize;i++) - st->old_lsp[i] = st->lsp[i]; + st->old_lsp[i] = lsp[i]; for (i=0;ilpcSize;i++) - st->old_qlsp[i] = st->qlsp[i]; + st->old_qlsp[i] = qlsp[i]; st->first=0; @@ -786,9 +788,7 @@ void *sb_decoder_init(const SpeexMode *m) st->excBuf = (spx_word16_t*)speex_alloc((st->subframeSize)*sizeof(spx_word16_t)); - st->qlsp = (spx_lsp_t*)speex_alloc((st->lpcSize)*sizeof(spx_lsp_t)); st->old_qlsp = (spx_lsp_t*)speex_alloc((st->lpcSize)*sizeof(spx_lsp_t)); - st->interp_qlsp = (spx_lsp_t*)speex_alloc(st->lpcSize*sizeof(spx_lsp_t)); st->interp_qlpc = (spx_coef_t*)speex_alloc(st->lpcSize*sizeof(spx_coef_t)); st->pi_gain = (spx_word32_t*)speex_alloc((st->nbSubframes)*sizeof(spx_word32_t)); @@ -819,9 +819,7 @@ void sb_decoder_destroy(void *state) speex_free(st->g0_mem); speex_free(st->g1_mem); speex_free(st->excBuf); - speex_free(st->qlsp); speex_free(st->old_qlsp); - speex_free(st->interp_qlsp); speex_free(st->interp_qlpc); speex_free(st->pi_gain); speex_free(st->exc_rms); @@ -878,6 +876,8 @@ int sb_decode(void *state, SpeexBits *bits, void *vout) VARDECL(spx_word32_t *low_pi_gain); VARDECL(spx_word16_t *low_exc_rms); VARDECL(spx_coef_t *ak); + VARDECL(spx_lsp_t *qlsp); + VARDECL(spx_lsp_t *interp_qlsp); spx_int32_t dtx; const SpeexSBMode *mode; spx_word16_t *out = (spx_word16_t*)vout; @@ -958,12 +958,14 @@ int sb_decode(void *state, SpeexBits *bits, void *vout) speex_decoder_ctl(st->st_low, SPEEX_GET_PI_GAIN, low_pi_gain); speex_decoder_ctl(st->st_low, SPEEX_GET_EXC, low_exc_rms); - SUBMODE(lsp_unquant)(st->qlsp, st->lpcSize, bits); + ALLOC(qlsp, st->lpcSize, spx_lsp_t); + ALLOC(interp_qlsp, st->lpcSize, spx_lsp_t); + SUBMODE(lsp_unquant)(qlsp, st->lpcSize, bits); if (st->first) { for (i=0;ilpcSize;i++) - st->old_qlsp[i] = st->qlsp[i]; + st->old_qlsp[i] = qlsp[i]; } ALLOC(ak, st->lpcSize, spx_coef_t); @@ -990,12 +992,12 @@ int sb_decode(void *state, SpeexBits *bits, void *vout) } /* LSP interpolation */ - lsp_interpolate(st->old_qlsp, st->qlsp, st->interp_qlsp, st->lpcSize, sub, st->nbSubframes); + lsp_interpolate(st->old_qlsp, qlsp, interp_qlsp, st->lpcSize, sub, st->nbSubframes); - lsp_enforce_margin(st->interp_qlsp, st->lpcSize, LSP_MARGIN); + lsp_enforce_margin(interp_qlsp, st->lpcSize, LSP_MARGIN); /* LSP to LPC */ - lsp_to_lpc(st->interp_qlsp, ak, st->lpcSize, stack); + lsp_to_lpc(interp_qlsp, ak, st->lpcSize, stack); /* Calculate reponse ratio between the low and high filter in the middle of the band (4000 Hz) */ @@ -1087,7 +1089,7 @@ int sb_decode(void *state, SpeexBits *bits, void *vout) qmf_synth(out, out+st->frame_size, h0, out, st->full_frame_size, QMF_ORDER, st->g0_mem, st->g1_mem, stack); for (i=0;ilpcSize;i++) - st->old_qlsp[i] = st->qlsp[i]; + st->old_qlsp[i] = qlsp[i]; st->first=0; @@ -1245,7 +1247,7 @@ int sb_encoder_ctl(void *state, int request, void *ptr) int i; st->first = 1; for (i=0;ilpcSize;i++) - st->lsp[i]=(M_PI*((float)(i+1)))/(st->lpcSize+1); + st->old_lsp[i]=(M_PI*((float)(i+1)))/(st->lpcSize+1); for (i=0;ilpcSize;i++) st->mem_sw[i]=st->mem_sp[i]=st->mem_sp2[i]=0; for (i=0;iread_filebuf(buffer, sizeof(char)*CHUNKSIZE); + bytes = ci->read_filebuf(buffer, sizeof(char)*CHUNKSIZE); spx_ogg_sync_wrote(oy,bytes); @@ -53,14 +51,14 @@ int get_more_data(spx_ogg_sync_state *oy,struct codec_api *rb) /* The read/seek functions track absolute position within the stream */ static spx_int64_t get_next_page(spx_ogg_sync_state *oy,spx_ogg_page *og, - spx_int64_t boundary,struct codec_api *rb) + spx_int64_t boundary) { - spx_int64_t localoffset = rb->curpos; + spx_int64_t localoffset = ci->curpos; long more; long ret; if (boundary > 0) - boundary += rb->curpos; + boundary += ci->curpos; while (1) { more = spx_ogg_sync_pageseek(oy,og); @@ -73,7 +71,7 @@ static spx_int64_t get_next_page(spx_ogg_sync_state *oy,spx_ogg_page *og, /* send more paramedics */ if(!boundary)return(-1); { - ret = get_more_data(oy,rb); + ret = get_more_data(oy); if (ret == 0) return(-2); @@ -93,12 +91,11 @@ static spx_int64_t get_next_page(spx_ogg_sync_state *oy,spx_ogg_page *og, } static spx_int64_t seek_backwards(spx_ogg_sync_state *oy, spx_ogg_page *og, - spx_int64_t wantedpos, - struct codec_api *rb) + spx_int64_t wantedpos) { spx_int64_t crofs; spx_int64_t *curoffset=&crofs; - *curoffset=rb->curpos; + *curoffset=ci->curpos; spx_int64_t begin=*curoffset; spx_int64_t end=begin; spx_int64_t ret; @@ -124,14 +121,14 @@ static spx_int64_t seek_backwards(spx_ogg_sync_state *oy, spx_ogg_page *og, *curoffset = begin; - rb->seek_buffer(*curoffset); + ci->seek_buffer(*curoffset); spx_ogg_sync_reset(oy); lastgranule = -1; while (*curoffset < end) { - ret = get_next_page(oy,og,end-*curoffset,rb); + ret = get_next_page(oy,og,end-*curoffset); if (ret > 0) { if (lastgranule != -1) { @@ -184,8 +181,7 @@ static spx_int64_t seek_backwards(spx_ogg_sync_state *oy, spx_ogg_page *og, int speex_seek_page_granule(spx_int64_t pos, spx_int64_t curpos, spx_ogg_sync_state *oy, - spx_int64_t headerssize, - struct codec_api *rb) + spx_int64_t headerssize) { /* TODO: Someone may want to try to implement seek to packet, instead of just to page (should be more accurate, not be any @@ -193,7 +189,7 @@ int speex_seek_page_granule(spx_int64_t pos, spx_int64_t curpos, spx_int64_t crofs; spx_int64_t *curbyteoffset = &crofs; - *curbyteoffset = rb->curpos; + *curbyteoffset = ci->curpos; spx_int64_t curoffset; curoffset = *curbyteoffset; spx_int64_t offset = 0; @@ -217,31 +213,31 @@ int speex_seek_page_granule(spx_int64_t pos, spx_int64_t curpos, //spx_int64_t toffset=curoffset; - rb->seek_buffer(curoffset); + ci->seek_buffer(curoffset); spx_ogg_sync_reset(oy); - offset = get_next_page(oy,&og,-1,rb); + offset = get_next_page(oy,&og,-1); if (offset < 0) { /* could not find new page,use old offset */ LOGF("Seek/guess/fault:%d->-<-%d,%d:%d,%d,%d\n", curpos,0,pos,offset,0, - rb->curpos,/*stream_length*/0); + ci->curpos,/*stream_length*/0); curoffset = *curbyteoffset; - rb->seek_buffer(curoffset); + ci->seek_buffer(curoffset); spx_ogg_sync_reset(oy); } else { if (spx_ogg_page_granulepos(&og) == 0 && pos > 5000) { LOGF("SEEK/guess/fault:%d->-<-%d,%d:%d,%d,%d\n", curpos,spx_ogg_page_granulepos(&og),pos, - offset,0,rb->curpos,/*stream_length*/0); + offset,0,ci->curpos,/*stream_length*/0); curoffset = *curbyteoffset; - rb->seek_buffer(curoffset); + ci->seek_buffer(curoffset); spx_ogg_sync_reset(oy); } else { @@ -254,7 +250,7 @@ int speex_seek_page_granule(spx_int64_t pos, spx_int64_t curpos, /* which way do we want to seek? */ if (curpos > pos) { /* backwards */ - offset = seek_backwards(oy,&og,pos,rb); + offset = seek_backwards(oy,&og,pos); if (offset > 0) { *curbyteoffset = curoffset; @@ -262,7 +258,7 @@ int speex_seek_page_granule(spx_int64_t pos, spx_int64_t curpos, } } else { /* forwards */ - while ( (offset = get_next_page(oy,&og,-1,rb)) > 0) { + while ( (offset = get_next_page(oy,&og,-1)) > 0) { if (lastgranule != -1) { if (avgpagelen < 0) avgpagelen = (spx_ogg_page_granulepos(&og) - lastgranule); @@ -286,13 +282,13 @@ int speex_seek_page_granule(spx_int64_t pos, spx_int64_t curpos, } } - rb->seek_buffer(*curbyteoffset); + ci->seek_buffer(*curbyteoffset); spx_ogg_sync_reset(oy); LOGF("Seek failed:%d\n", offset); - rb->splash(HZ*2, true, "Seek failed"); + ci->splash(HZ*2, true, "Seek failed"); return -1; } @@ -327,7 +323,7 @@ static void *process_header(spx_ogg_packet *op, modeID = header->mode; - mode = speex_lib_get_mode (modeID); + mode = speex_lib_get_mode(modeID); if (header->speex_version_id > 1) { DEBUGF("Undecodeable bitstream"); @@ -352,9 +348,6 @@ static void *process_header(spx_ogg_packet *op, speex_decoder_ctl(st, SPEEX_SET_ENH, &enh_enabled); speex_decoder_ctl(st, SPEEX_GET_FRAME_SIZE, frame_size); - if (*channels==-1) - *channels = header->nb_channels; - if (!(*channels==1)){ callback.callback_id = SPEEX_INBAND_STEREO; callback.func = speex_std_stereo_request_handler; @@ -368,11 +361,8 @@ static void *process_header(spx_ogg_packet *op, *nframes = header->frames_per_packet; - if (*channels == 2) { - rb->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED); - } else if (*channels == 1) { - rb->configure(DSP_SET_STEREO_MODE, STEREO_MONO); - } + if (*channels == -1) + *channels = header->nb_channels; *extra_headers = header->extra_headers; @@ -383,35 +373,28 @@ static void *process_header(spx_ogg_packet *op, /* this is the codec entry point */ enum codec_status codec_main(void) { - SpeexBits vf; - int error; - int eof; + SpeexBits bits; + int error = 0; + int eof = 0; spx_ogg_sync_state oy; spx_ogg_page og; spx_ogg_packet op; spx_ogg_stream_state os; - spx_int64_t page_granule=0, cur_granule=0; - int enh_enabled; - int nframes=2; - int eos=0; + spx_int64_t page_granule = 0, cur_granule = 0; + int enh_enabled = 1; + int nframes = 2; + int eos = 0; SpeexStereoState stereo = SPEEX_STEREO_STATE_INIT; - int channels=-1; - int rate=0,samplerate=0; - int extra_headers; - int stream_init=0; - int page_nb_packets,frame_size,packet_count=0; - int lookahead; - int headerssize=-1; - unsigned long strtoffset; - short output[MAX_FRAME_SIZE]; - enh_enabled = 1; - void *st=0; - int j; - rb = ci; - - //rb->configure(CODEC_SET_FILEBUF_CHUNKSIZE, CHUNKSIZE*128); - //rb->configure(DSP_DITHER, false); - rb->configure(DSP_SET_SAMPLE_DEPTH, 16); + int channels = -1; + int rate = 0, samplerate = 0; + int extra_headers = 0; + int stream_init = 0; + int page_nb_packets, frame_size, packet_count = 0; + int lookahead = 0; + int headerssize = -1; + unsigned long strtoffset = 0; + void *st = NULL; + int j = 0; /* We need to flush reserver memory every track load. */ next_track: @@ -421,44 +404,44 @@ next_track: goto exit; } - strtoffset=rb->id3->offset; + strtoffset = ci->id3->offset; - while (!*rb->taginfo_ready && !rb->stop_codec) - rb->sleep(1); + while (!*ci->taginfo_ready && !ci->stop_codec) + ci->sleep(1); spx_ogg_sync_init(&oy); spx_ogg_alloc_buffer(&oy,2*CHUNKSIZE); - samplerate = rb->id3->frequency; - codec_set_replaygain(rb->id3); + samplerate = ci->id3->frequency; + codec_set_replaygain(ci->id3); - speex_bits_init(&vf); + speex_bits_init(&bits); eof = 0; while (!eof) { - rb->yield(); - if (rb->stop_codec || rb->new_track) + ci->yield(); + if (ci->stop_codec || ci->new_track) break; /*seek (seeks to the page before the position) */ - if (rb->seek_time) { + if (ci->seek_time) { if(samplerate!=0&&packet_count>1){ LOGF("Speex seek page:%d,%d,%d,%d\n", - ((spx_int64_t)rb->seek_time/1000) * + ((spx_int64_t)ci->seek_time/1000) * (spx_int64_t)samplerate, - page_granule, rb->seek_time, + page_granule, ci->seek_time, (page_granule/samplerate)*1000, samplerate); - speex_seek_page_granule(((spx_int64_t)rb->seek_time/1000) * + speex_seek_page_granule(((spx_int64_t)ci->seek_time/1000) * (spx_int64_t)samplerate, - page_granule, &oy, headerssize, rb); - rb->seek_complete(); + page_granule, &oy, headerssize); + ci->seek_complete(); } } next_page: /*Get the ogg buffer for writing*/ - if(get_more_data(&oy,rb)<1){/*read error*/ + if(get_more_data(&oy)<1){/*read error*/ error=CODEC_ERROR; goto done; } @@ -467,7 +450,7 @@ next_page: while (spx_ogg_sync_pageout(&oy, &og) == 1) { int packet_no; if (stream_init == 0) { - spx_ogg_stream_init(&os,spx_ogg_page_serialno(&og)); + spx_ogg_stream_init(&os, spx_ogg_page_serialno(&og)); stream_init = 1; } @@ -486,7 +469,7 @@ next_page: /* If first packet, process as Speex header */ if (packet_count==0){ st = process_header(&op, enh_enabled, &frame_size, - &samplerate,&nframes, &channels, + &samplerate, &nframes, &channels, &stereo, &extra_headers); speex_decoder_ctl(st, SPEEX_GET_LOOKAHEAD, &lookahead); @@ -499,13 +482,19 @@ next_page: goto exit; } - rb->id3->vbr = true; - rb->id3->frequency = samplerate; - rb->configure(DSP_SET_FREQUENCY, rb->id3->frequency); + ci->id3->vbr = true; + ci->id3->frequency = samplerate; + ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency); + ci->configure(DSP_SET_SAMPLE_DEPTH, 16); + if (channels == 2) { + ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED); + } else if (channels == 1) { + ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); + } /* Speex header in its own page, add the whole page headersize */ - headerssize+=og.header_len+og.body_len; + headerssize += og.header_len+og.body_len; } else if (packet_count<=1+extra_headers){ /* add packet to headersize */ @@ -515,7 +504,7 @@ next_page: } else { if (packet_count <= 2+extra_headers) { if (strtoffset) { - rb->seek_buffer(strtoffset); + ci->seek_buffer(strtoffset); spx_ogg_sync_reset(&oy); packet_count++; goto next_page; @@ -528,21 +517,21 @@ next_page: /* Copy Ogg packet to Speex bitstream */ - speex_bits_read_from(&vf, (char*)op.packet, op.bytes); + speex_bits_read_from(&bits, (char*)op.packet, op.bytes); for (j = 0; j != nframes; j++){ int ret; /* Decode frame */ - ret = speex_decode_int(st, &vf, output); + ret = speex_decode_int(st, &bits, output); - if (ret==-1) + if (ret == -1) break; - if (ret==-2) + if (ret == -2) break; - if (speex_bits_remaining(&vf) < 0) + if (speex_bits_remaining(&bits) < 0) break; if (channels == 2) @@ -550,17 +539,16 @@ next_page: int new_frame_size = frame_size; - if (new_frame_size>0){ - rb->pcmbuf_insert((const char*)output, NULL, - new_frame_size); + if (new_frame_size > 0) { + ci->pcmbuf_insert(output, NULL, new_frame_size); /* 2 bytes/sample */ cur_granule += new_frame_size / 2; - rb->set_offset((long)rb->curpos); + ci->set_offset((long) ci->curpos); - rb->set_elapsed( (samplerate==0) ? 0 : - cur_granule*1000/samplerate); + ci->set_elapsed((samplerate == 0) ? 0 : + cur_granule * 1000 / samplerate); } } } @@ -570,24 +558,24 @@ next_page: } done: - if (rb->request_next_track()) { + if (ci->request_next_track()) { /* Clean things up for the next track */ speex_decoder_destroy(st); - speex_bits_reset(&vf); + speex_bits_reset(&bits); - if (stream_init==1) + if (stream_init == 1) spx_ogg_stream_reset(&os); spx_ogg_sync_reset(&oy); cur_granule = stream_init = rate = samplerate = headerssize - = packet_count = eos = 0; + = packet_count = eos = 0; - stereo.balance =stereo.smooth_left = stereo.smooth_right = 1; + stereo.balance = stereo.smooth_left = stereo.smooth_right = 1; stereo.e_ratio = .5; - stereo.reserved1=stereo.reserved2= 0; + stereo.reserved1 = stereo.reserved2 = 0; goto next_track; } @@ -595,7 +583,7 @@ done: error = CODEC_OK; exit: - speex_bits_destroy(&vf); + speex_bits_destroy(&bits); if (stream_init) spx_ogg_stream_destroy(&os);