summaryrefslogtreecommitdiff
path: root/apps/codecs
diff options
context:
space:
mode:
authorDan Everton <dan@iocaine.org>2007-03-12 11:54:07 +0000
committerDan Everton <dan@iocaine.org>2007-03-12 11:54:07 +0000
commit879070f89e004be03cef53ad7f61610e02e7aa00 (patch)
treeeccbcce2722da50eb473c78cf9ce16fad6602c00 /apps/codecs
parent19bba742e789e669d4cfc15ed3a5cef4aa64199d (diff)
downloadrockbox-879070f89e004be03cef53ad7f61610e02e7aa00.zip
rockbox-879070f89e004be03cef53ad7f61610e02e7aa00.tar.gz
rockbox-879070f89e004be03cef53ad7f61610e02e7aa00.tar.bz2
rockbox-879070f89e004be03cef53ad7f61610e02e7aa00.tar.xz
* Clean up speex.c a little.
* Sync to Speex SVN 12735 which includes some of our warnings fixes. * Move decoder output to IRAM. Not much perfomance gain though. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12735 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs')
-rw-r--r--apps/codecs/libspeex/README.rockbox8
-rw-r--r--apps/codecs/libspeex/SOURCES1
-rw-r--r--apps/codecs/libspeex/_kiss_fft_guts.h7
-rw-r--r--apps/codecs/libspeex/fftwrap.c37
-rw-r--r--apps/codecs/libspeex/jitter.c209
-rw-r--r--apps/codecs/libspeex/kiss_fft.c329
-rw-r--r--apps/codecs/libspeex/kiss_fftr.c128
-rw-r--r--apps/codecs/libspeex/kiss_fftr.h5
-rw-r--r--apps/codecs/libspeex/mdf.c39
-rw-r--r--apps/codecs/libspeex/modes.h14
-rw-r--r--apps/codecs/libspeex/preprocess.c4
-rw-r--r--apps/codecs/libspeex/pseudofloat.h9
-rw-r--r--apps/codecs/libspeex/resample.c432
-rw-r--r--apps/codecs/libspeex/sb_celp.c122
-rw-r--r--apps/codecs/libspeex/sb_celp.h11
-rw-r--r--apps/codecs/libspeex/speex/speex.h18
-rw-r--r--apps/codecs/libspeex/speex/speex_jitter.h8
-rw-r--r--apps/codecs/libspeex/speex/speex_noglobals.h60
-rw-r--r--apps/codecs/libspeex/speex/speex_resampler.h221
-rw-r--r--apps/codecs/libspeex/testresample.c7
-rw-r--r--apps/codecs/speex.c188
21 files changed, 1299 insertions, 558 deletions
diff --git a/apps/codecs/libspeex/README.rockbox b/apps/codecs/libspeex/README.rockbox
index 4280df4..7f7f975 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 <math.h> 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 16168b0..df73565 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 43a3ba5..526a73b 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 a108640..35e2d05 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;i<t->N>>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;i<t->N>>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;i<t->N;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;i<t->N>>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 dc31c06..ae60f73 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;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
{
+ /* Make sure we don't discard a "just-late" packet in case we want to play it next (if we interpolate). */
if (jitter->buf[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)<packet->len;j++)
+ for (j=0;j<packet->len;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;i<MAX_MARGIN;i++)
{
jitter->shortterm_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;i<LATE_BINS;i++)
{
late_ratio_short += jitter->shortterm_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;i<MAX_MARGIN;i++)
{
early_ratio_short += jitter->shortterm_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;i<MAX_MARGIN-1;i++)
- {
- jitter->shortterm_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;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
{
- if (jitter->buf[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;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
{
- if (jitter->buf[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)<packet->len;j++)
+ for (j=0;j<packet->len;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;i<LATE_BINS;i++)
+ {
+ late_ratio_short += jitter->shortterm_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;i<MAX_MARGIN;i++)
+ {
+ early_ratio_short += jitter->shortterm_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;i<MAX_MARGIN-1;i++)
+ {
+ jitter->shortterm_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;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
+ {
+ if (jitter->buf[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 4ab31f2..449e7b8 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;i<N;i++)
+ {
+ Fout = Fout_beg + i*mm;
+ Fout2 = Fout + m;
+ tw1 = st->twiddles;
+ for(j=0;j<m;j++)
+ {
+ /* Almost the same as the code path below, except that we divide the input by two
+ (while keeping the best accuracy possible) */
+ spx_word32_t tr, ti;
+ tr = SHR32(SUB32(MULT16_16(Fout2->r , 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;i<N;i++)
{
- x[i].r = SHR16(x[i].r,1);
- x[i].i = SHR16(x[i].i,1);
+ Fout = Fout_beg + i*mm;
+ Fout2 = Fout + m;
+ tw1 = st->twiddles;
+ for(j=0;j<m;j++)
+ {
+ C_MUL (t, *Fout2 , *tw1);
+ tw1 += fstride;
+ C_SUB( *Fout2 , *Fout , t );
+ C_ADDTO( *Fout , t );
+ ++Fout2;
+ ++Fout;
+ }
}
}
-
- do{
- C_MUL (t, *Fout2 , *tw1);
- tw1 += fstride;
- C_SUB( *Fout2 , *Fout , t );
- C_ADDTO( *Fout , t );
- ++Fout2;
- ++Fout;
- }while (--m);
}
static void kf_bfly4(
kiss_fft_cpx * Fout,
const size_t fstride,
const kiss_fft_cfg st,
- const size_t m
+ const size_t m,
+ int N,
+ int mm
)
{
kiss_fft_cpx *tw1,*tw2,*tw3;
kiss_fft_cpx scratch[6];
- size_t k=m;
const size_t m2=2*m;
const size_t m3=3*m;
+ int i;
+ unsigned int j;
- tw3 = tw2 = tw1 = st->twiddles;
-
- 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;i<N;i++)
+ {
+ Fout = Fout_beg + i*mm;
+ tw3 = tw2 = tw1 = st->twiddles;
+ for (j=0;j<m;j++)
+ {
+ 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;
+ }
+ }
} else
{
- 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;i<N;i++)
+ {
+ Fout = Fout_beg + i*mm;
+ tw3 = tw2 = tw1 = st->twiddles;
+ for (j=0;j<m;j++)
+ {
+ C_MUL4(scratch[0],Fout[m] , *tw1 );
+ C_MUL4(scratch[1],Fout[m2] , *tw2 );
+ C_MUL4(scratch[2],Fout[m3] , *tw3 );
+
+ Fout->r = 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; u<m; ++u ) {
k=u;
for ( q1=0 ; q1<p ; ++q1 ) {
@@ -291,6 +317,39 @@ static void kf_bfly_generic(
}
}
}
+
+static
+void kf_shuffle(
+ kiss_fft_cpx * Fout,
+ const kiss_fft_cpx * f,
+ const size_t fstride,
+ int in_stride,
+ int * factors,
+ const kiss_fft_cfg st
+ )
+{
+ const int p=*factors++; /* the radix */
+ const int m=*factors++; /* stage's fft length/p */
+
+ /*printf ("fft %d %d %d %d %d %d\n", p*m, m, p, s2, fstride*in_stride, N);*/
+ if (m==1)
+ {
+ int j;
+ for (j=0;j<p;j++)
+ {
+ Fout[j] = *f;
+ f += fstride*in_stride;
+ }
+ } else {
+ int j;
+ for (j=0;j<p;j++)
+ {
+ kf_shuffle( Fout , f, fstride*p, in_stride, factors,st);
+ f += fstride*in_stride;
+ Fout += m;
+ }
+ }
+}
static
void kf_work(
@@ -299,24 +358,34 @@ void kf_work(
const size_t fstride,
int in_stride,
int * factors,
- const kiss_fft_cfg st
+ const kiss_fft_cfg st,
+ int N,
+ int s2,
+ int m2
)
{
+ int i;
kiss_fft_cpx * Fout_beg=Fout;
const int p=*factors++; /* the radix */
const int m=*factors++; /* stage's fft length/p */
- const kiss_fft_cpx * Fout_end = Fout + p*m;
-
- if (m==1) {
- do{
- *Fout = *f;
- f += fstride*in_stride;
- }while(++Fout != Fout_end );
- }else{
- do{
- kf_work( Fout , f, fstride*p, in_stride, factors,st);
- f += fstride*in_stride;
- }while( (Fout += m) != Fout_end );
+#if 0
+ /*printf ("fft %d %d %d %d %d %d\n", p*m, m, p, s2, fstride*in_stride, N);*/
+ if (m==1)
+ {
+ /* int j;
+ for (j=0;j<p;j++)
+ {
+ Fout[j] = *f;
+ f += fstride*in_stride;
+ }*/
+ } else {
+ int j;
+ for (j=0;j<p;j++)
+ {
+ kf_work( Fout , f, fstride*p, in_stride, factors,st, N*p, fstride*in_stride, m);
+ f += fstride*in_stride;
+ Fout += m;
+ }
}
Fout=Fout_beg;
@@ -328,6 +397,36 @@ void kf_work(
case 5: kf_bfly5(Fout,fstride,st,m); break;
default: kf_bfly_generic(Fout,fstride,st,m,p); break;
}
+#else
+ /*printf ("fft %d %d %d %d %d %d %d\n", p*m, m, p, s2, fstride*in_stride, N, m2);*/
+ if (m==1)
+ {
+ /*for (i=0;i<N;i++)
+ {
+ int j;
+ Fout = Fout_beg+i*m2;
+ const kiss_fft_cpx * f2 = f+i*s2;
+ for (j=0;j<p;j++)
+ {
+ *Fout++ = *f2;
+ f2 += fstride*in_stride;
+ }
+ }*/
+ }else{
+ kf_work( Fout , f, fstride*p, in_stride, factors,st, N*p, fstride*in_stride, m);
+ }
+
+
+
+
+ switch (p) {
+ case 2: kf_bfly2(Fout,fstride,st,m, N, m2); break;
+ case 3: for (i=0;i<N;i++){Fout=Fout_beg+i*m2; kf_bfly3(Fout,fstride,st,m);} break;
+ case 4: kf_bfly4(Fout,fstride,st,m, N, m2); break;
+ case 5: for (i=0;i<N;i++){Fout=Fout_beg+i*m2; kf_bfly5(Fout,fstride,st,m);} break;
+ default: for (i=0;i<N;i++){Fout=Fout_beg+i*m2; kf_bfly_generic(Fout,fstride,st,m,p);} break;
+ }
+#endif
}
/* facbuf is populated by p1,m1,p2,m2, ...
@@ -405,12 +504,15 @@ kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem
void kiss_fft_stride(kiss_fft_cfg st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int in_stride)
{
- if (fin == fout) {
- 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_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 95c4573..392945c 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 2e8351a..7bfb423 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 eac9f83..498dd39 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;j<M;j++)
+ {
+ tmp1 = MAC16_16(tmp1, X[j*N],Y[j*N]);
+ }
+ acc[0] = PSHR32(tmp1,WEIGHT_SHIFT);
+ for (i=1;i<N-1;i+=2)
+ {
+ tmp1 = tmp2 = 0;
+ for (j=0;j<M;j++)
+ {
+ tmp1 = SUB32(MAC16_16(tmp1, X[j*N+i],Y[j*N+i]), MULT16_16(X[j*N+i+1],Y[j*N+i+1]));
+ tmp2 = MAC16_16(MAC16_16(tmp2, X[j*N+i+1],Y[j*N+i]), X[j*N+i], Y[j*N+i+1]);
+ }
+ acc[i] = PSHR32(tmp1,WEIGHT_SHIFT);
+ acc[i+1] = PSHR32(tmp2,WEIGHT_SHIFT);
+ }
+ tmp1 = tmp2 = 0;
+ for (j=0;j<M;j++)
+ {
+ tmp1 = MAC16_16(tmp1, X[(j+1)*N-1],Y[(j+1)*N-1]);
+ }
+ acc[N-1] = PSHR32(tmp1,WEIGHT_SHIFT);
+}
+
#else
static inline void spectral_mul_accum(const spx_word16_t *X, const spx_word32_t *Y, spx_word16_t *acc, int N, int M)
{
@@ -281,6 +309,7 @@ static inline void spectral_mul_accum(const spx_word16_t *X, const spx_word32_t
Y += N;
}
}
+#define spectral_mul_accum16 spectral_mul_accum
#endif
/** Compute weighted cross-power spectrum of a half-complex (packed) vector with conjugate */
@@ -375,7 +404,7 @@ SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length)
st->E = (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;i<st->frame_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;i<N*M;i++)
- st->foreground[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;i<st->frame_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;i<N*M;i++)
- st->W[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;i<st->frame_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 819be70..385cec0 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 bd4f776..c4217f4 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<len;i++)
{
spx_word16_t tmp;
+#ifdef FIXED_POINT
+ spx_word16_t x = DIV32_16(MULT16_16(32767,i),len);
+#else
spx_word16_t x = DIV32_16(MULT16_16(QCONST16(4.f,13),i),len);
+#endif
int inv=0;
if (x<QCONST16(1.f,13))
{
diff --git a/apps/codecs/libspeex/pseudofloat.h b/apps/codecs/libspeex/pseudofloat.h
index 67f01b3..a6c4762 100644
--- a/apps/codecs/libspeex/pseudofloat.h
+++ b/apps/codecs/libspeex/pseudofloat.h
@@ -2,6 +2,15 @@
/**
@file pseudofloat.h
@brief Pseudo-floating point
+ * This header file provides a lightweight floating point type for
+ * use on fixed-point platforms when a large dynamic range is
+ * required. The new type is not compatible with the 32-bit IEEE format,
+ * it is not even remotely as accurate as 32-bit floats, and is not
+ * even guaranteed to produce even remotely correct results for code
+ * other than Speex. It makes all kinds of shortcuts that are acceptable
+ * for Speex, but may not be acceptable for your application. You're
+ * quite welcome to reuse this code and improve it, but don't assume
+ * it works out of the box. Most likely, it doesn't.
*/
/*
Redistribution and use in source and binary forms, with or without
diff --git a/apps/codecs/libspeex/resample.c b/apps/codecs/libspeex/resample.c
index d6bfa3e..74d5f40 100644
--- a/apps/codecs/libspeex/resample.c
+++ b/apps/codecs/libspeex/resample.c
@@ -59,12 +59,13 @@ TODO list:
void *speex_alloc (int size) {return calloc(size,1);}
void *speex_realloc (void *ptr, int size) {return realloc(ptr, size);}
void speex_free (void *ptr) {free(ptr);}
+#include "speex_resampler.h"
#else
+#include "speex/speex_resampler.h"
#include "misc.h"
#endif
#include <math.h>
-#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 <stdio.h>
+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 (;j<N;j++)
+ {
+ sum += MULT16_16(*ptr,(double)st->sinc_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,6 +411,75 @@ 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};
+ spx_word16_t interp[4];
+ const spx_word16_t *ptr;
+ 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 */
+ for (j=0;last_sample-N+1+j < 0;j++)
+ {
+ spx_word16_t 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 (;j<N;j++)
+ {
+ spx_word16_t curr_in = *ptr;
+ ptr += st->in_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 = 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;
+ 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;
+}
+
+#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;
@@ -246,7 +490,7 @@ static int resampler_basic_interpolate_single(SpeexResamplerState *st, int chann
have only two accumulators */
for (j=0;last_sample-N+1+j < 0;j++)
{
- spx_word16_t curr_mem = mem[last_sample+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]);
@@ -256,22 +500,14 @@ static int resampler_basic_interpolate_single(SpeexResamplerState *st, int chann
/* Do the new part */
for (;j<N;j++)
{
- spx_word16_t curr_in = *ptr;
+ double curr_in = *ptr;
ptr += st->in_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]);
}
- /* 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];*/
+ 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);
@@ -289,7 +525,7 @@ static int resampler_basic_interpolate_single(SpeexResamplerState *st, int chann
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;j<st->filt_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;i<st->oversample*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;i<st->magic_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;i<st->nb_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 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(SpeexResamplerState *st, int ratio_num, int ratio_den, int in_rate, int 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 61ca34e..b1159cd 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;i<st->lpcSize+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);
- }
- st->autocorr[0] = ADD16(st->autocorr[0],MULT16_16_Q15(st->autocorr[0],st->lpc_floor)); /* Noise floor in auto-correlation domain */
+ _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;i<st->lpcSize+1;i++)
- st->autocorr[i] = MULT16_16_Q14(st->autocorr[i],st->lagWindow[i]);
+ /* Lag windowing: equivalent to filtering in the power-spectrum domain */
+ for (i=0;i<st->lpcSize+1;i++)
+ autocorr[i] = MULT16_16_Q14(autocorr[i],st->lagWindow[i]);
- /* Levinson-Durbin */
- _spx_lpc(st->lpc, st->autocorr, st->lpcSize);
+ /* Levinson-Durbin */
+ _spx_lpc(lpc, 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;i<st->lpcSize;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;i<st->lpcSize;i++)
- st->old_lsp[i] = st->lsp[i];
+ st->old_lsp[i] = lsp[i];
for (i=0;i<st->lpcSize;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;i<st->lpcSize;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;i<st->lpcSize;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;i<st->subframeSize;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;i<st->subframeSize;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;i<st->lpcSize;i++)
- st->old_lsp[i] = st->lsp[i];
+ st->old_lsp[i] = lsp[i];
for (i=0;i<st->lpcSize;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;i<st->lpcSize;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;i<st->lpcSize;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;i<st->lpcSize;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;i<st->lpcSize;i++)
st->mem_sw[i]=st->mem_sp[i]=st->mem_sp2[i]=0;
for (i=0;i<QMF_ORDER;i++)
diff --git a/apps/codecs/libspeex/sb_celp.h b/apps/codecs/libspeex/sb_celp.h
index 35997cb..a0dc3af 100644
--- a/apps/codecs/libspeex/sb_celp.h
+++ b/apps/codecs/libspeex/sb_celp.h
@@ -63,18 +63,9 @@ typedef struct SBEncState {
const spx_word16_t *window; /**< LPC analysis window */
spx_word16_t *lagWindow; /**< Auto-correlation window */
- spx_word16_t *autocorr; /**< Auto-correlation (for LPC analysis) */
- spx_coef_t *lpc; /**< LPC coefficients */
- spx_lsp_t *lsp; /**< LSP coefficients */
- spx_lsp_t *qlsp; /**< Quantized LSPs */
spx_lsp_t *old_lsp; /**< LSPs of previous frame */
spx_lsp_t *old_qlsp; /**< Quantized LSPs of previous frame */
- spx_lsp_t *interp_lsp; /**< Interpolated LSPs for current sub-frame */
- spx_lsp_t *interp_qlsp; /**< Interpolated quantized LSPs for current sub-frame */
- spx_coef_t *interp_lpc; /**< Interpolated LPCs for current sub-frame */
spx_coef_t *interp_qlpc; /**< Interpolated quantized LPCs for current sub-frame */
- spx_coef_t *bw_lpc1; /**< Bandwidth-expanded version of LPCs (#1) */
- spx_coef_t *bw_lpc2; /**< Bandwidth-expanded version of LPCs (#2) */
spx_mem_t *mem_sp; /**< Synthesis signal memory */
spx_mem_t *mem_sp2;
@@ -121,9 +112,7 @@ typedef struct SBDecState {
spx_word32_t *g0_mem, *g1_mem;
spx_word16_t *excBuf;
- spx_lsp_t *qlsp;
spx_lsp_t *old_qlsp;
- spx_lsp_t *interp_qlsp;
spx_coef_t *interp_qlpc;
spx_mem_t *mem_sp;
diff --git a/apps/codecs/libspeex/speex/speex.h b/apps/codecs/libspeex/speex/speex.h
index 95facf4..0ae1aba 100644
--- a/apps/codecs/libspeex/speex/speex.h
+++ b/apps/codecs/libspeex/speex/speex.h
@@ -155,20 +155,6 @@ extern "C" {
/** Get status of input/output high-pass filtering */
#define SPEEX_GET_HIGHPASS 45
-/* 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
-
/* Preserving compatibility:*/
/** Equivalent to SPEEX_SET_ENH */
@@ -322,7 +308,9 @@ void speex_encoder_destroy(void *state);
/** Uses an existing encoder state to encode one frame of speech pointed to by
"in". The encoded bit-stream is saved in "bits".
@param state Encoder state
- @param in Frame that will be encoded with a +-2^15 range
+ @param in Frame that will be encoded with a +-2^15 range. This data MAY be
+ overwritten by the encoder and should be considered uninitialised
+ after the call.
@param bits Bit-stream where the data will be written
@return 0 if frame needs not be transmitted (DTX only), 1 otherwise
*/
diff --git a/apps/codecs/libspeex/speex/speex_jitter.h b/apps/codecs/libspeex/speex/speex_jitter.h
index b998a02..a5314d6 100644
--- a/apps/codecs/libspeex/speex/speex_jitter.h
+++ b/apps/codecs/libspeex/speex/speex_jitter.h
@@ -81,7 +81,13 @@ struct _JitterBufferPacket {
#define JITTER_BUFFER_SET_MARGIN 0
/** Get minimum amount of extra buffering required (margin) */
#define JITTER_BUFFER_GET_MARGIN 1
+/* JITTER_BUFFER_SET_AVALIABLE_COUNT wouldn't make sense */
+/** Get the amount of avaliable packets currently buffered */
+#define JITTER_BUFFER_GET_AVALIABLE_COUNT 3
+#define JITTER_BUFFER_ADJUST_INTERPOLATE -1
+#define JITTER_BUFFER_ADJUST_OK 0
+#define JITTER_BUFFER_ADJUST_DROP 1
/** Initialises jitter buffer
*
@@ -138,6 +144,8 @@ void jitter_buffer_tick(JitterBuffer *jitter);
*/
int jitter_buffer_ctl(JitterBuffer *jitter, int request, void *ptr);
+int jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet, spx_uint32_t *start_offset);
+
/* @} */
/** @defgroup SpeexJitter SpeexJitter: Adaptive jitter buffer specifically for Speex
diff --git a/apps/codecs/libspeex/speex/speex_noglobals.h b/apps/codecs/libspeex/speex/speex_noglobals.h
deleted file mode 100644
index 1d46993..0000000
--- a/apps/codecs/libspeex/speex/speex_noglobals.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* Copyright (C) 2004 CSIRO Australia */
-/* Copyright (C) 2002 Jean-Marc Valin*/
-/**
- @file speex_noglobals.h
- @brief Dynamically allocates the different modes of the codec
-*/
-/*
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- - Neither the name of the Xiph.org Foundation nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-*/
-
-#ifndef SPEEX_NOGLOBALS_H
-#define SPEEX_NOGLOBALS_H
-
-/* See README.symbian in the Speex source distribution for information
- * on using this API */
-
-typedef struct SpeexMode SpeexMode;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/** Instantiate a mode */
-const SpeexMode * speex_mode_new (int modeID);
-
-/** Destroy a mode */
-void speex_mode_destroy (const SpeexMode * mode);
-
-#ifdef __cplusplus
-}
-#endif
-
-
-#endif
diff --git a/apps/codecs/libspeex/speex/speex_resampler.h b/apps/codecs/libspeex/speex/speex_resampler.h
index 501fab8..93642ce 100644
--- a/apps/codecs/libspeex/speex/speex_resampler.h
+++ b/apps/codecs/libspeex/speex/speex_resampler.h
@@ -41,22 +41,59 @@
#ifdef OUTSIDE_SPEEX
+/********* WARNING: MENTAL SANITY ENDS HERE *************/
+
+/* If the resampler is defined outside of Speex, we change the symbol names so that
+ there won't be any clash if linking with Speex later on. */
+
+/* #define RANDOM_PREFIX your software name here */
+#ifndef RANDOM_PREFIX
+#error "Please define RANDOM_PREFIX (above) to something specific to your project to prevent symbol name clashes"
+#endif
+
+#define CAT_PREFIX2(a,b) a ## b
+#define CAT_PREFIX(a,b) CAT_PREFIX2(a, b)
+
+#define speex_resampler_init CAT_PREFIX(RANDOM_PREFIX,_resampler_init)
+#define speex_resampler_init_frac CAT_PREFIX(RANDOM_PREFIX,_resampler_init_frac)
+#define speex_resampler_destroy CAT_PREFIX(RANDOM_PREFIX,_resampler_destroy)
+#define speex_resampler_process_float CAT_PREFIX(RANDOM_PREFIX,_resampler_process_float)
+#define speex_resampler_process_int CAT_PREFIX(RANDOM_PREFIX,_resampler_process_int)
+#define speex_resampler_process_interleaved_float CAT_PREFIX(RANDOM_PREFIX,_resampler_process_interleaved_float)
+#define speex_resampler_process_interleaved_int CAT_PREFIX(RANDOM_PREFIX,_resampler_process_interleaved_int)
+#define speex_resampler_set_rate CAT_PREFIX(RANDOM_PREFIX,_resampler_set_rate)
+#define speex_resampler_get_rate CAT_PREFIX(RANDOM_PREFIX,_resampler_get_rate)
+#define speex_resampler_set_rate_frac CAT_PREFIX(RANDOM_PREFIX,_resampler_set_rate_frac)
+#define speex_resampler_get_ratio CAT_PREFIX(RANDOM_PREFIX,_resampler_get_ratio)
+#define speex_resampler_set_quality CAT_PREFIX(RANDOM_PREFIX,_resampler_set_quality)
+#define speex_resampler_get_quality CAT_PREFIX(RANDOM_PREFIX,_resampler_get_quality)
+#define speex_resampler_set_input_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_set_input_stride)
+#define speex_resampler_get_input_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_get_input_stride)
+#define speex_resample_set_output_stride CAT_PREFIX(RANDOM_PREFIX,_resample_set_output_stride)
+#define speex_resample_get_output_stride CAT_PREFIX(RANDOM_PREFIX,_resample_get_output_stride)
+#define speex_resampler_skip_zeros CAT_PREFIX(RANDOM_PREFIX,_resampler_skip_zeros)
+#define speex_resampler_reset_mem CAT_PREFIX(RANDOM_PREFIX,_resampler_reset_mem)
+
#define spx_int16_t short
+
#ifdef FIXED_POINT
#define spx_word16_t short
#define spx_word32_t int
-#else
+
+#else /* FIXED_POINT */
+
#define spx_word16_t float
#define spx_word32_t float
#define MULT16_16(a,b) ((a)*(b))
+#define MULT16_32_Q15(a,b) ((a)*(b))
#define PSHR32(a,b) (a)
-#endif
+#endif /* FIXED_POINT */
-#else
+#else /* OUTSIDE_SPEEX */
#include "speex_types.h"
-#endif
+#endif /* OUTSIDE_SPEEX */
#ifdef __cplusplus
extern "C" {
@@ -71,81 +108,201 @@ extern "C" {
struct SpeexResamplerState_;
typedef struct SpeexResamplerState_ SpeexResamplerState;
-/** Create a new resampler. The sampling rate ratio is an arbitrary rational number
- * with both the numerator and denominator being 32-bit integers.
+/** Create a new resampler with integer input and output rates.
+ * @param nb_channels Number of channels to be processed
+ * @param in_rate Input sampling rate (integer number of Hz).
+ * @param out_rate Output sampling rate (integer number of Hz).
+ * @param quality Resampling quality between 0 and 10, where 0 has poor quality
+ * and 10 has very high quality.
+ * @return Newly created resampler state
+ * @retval NULL Error: not enough memory
+ */
+SpeexResamplerState *speex_resampler_init(int nb_channels,
+ int in_rate,
+ int out_rate,
+ int quality);
+
+/** Create a new resampler with fractional input/output rates. The sampling
+ * rate ratio is an arbitrary rational number with both the numerator and
+ * denominator being 32-bit integers.
* @param nb_channels Number of channels to be processed
* @param ratio_num Numerator of the sampling rate ratio
* @param ratio_den Denominator of the sampling rate ratio
- * @param in_rate Nominal input sampling rate rounded to the nearest integer (in Hz). This does not need to be accurate.
- * @param out_rate Nominal output sampling rate rounded to the nearest integer (in Hz). This does not need to be accurate.
- * @param quality Resampling quality between 0 and 10, where 0 has poor quality and 10 has very high quality.
+ * @param in_rate Input sampling rate rounded to the nearest integer (in Hz).
+ * @param out_rate Output sampling rate rounded to the nearest integer (in Hz).
+ * @param quality Resampling quality between 0 and 10, where 0 has poor quality
+ * and 10 has very high quality.
* @return Newly created resampler state
+ * @retval NULL Error: not enough memory
*/
-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);
/** Destroy a resampler state.
* @param st Resampler state
*/
void speex_resampler_destroy(SpeexResamplerState *st);
-/** Resample a float array. The input and output may *not* alias.
+/** Resample a float array. The input and output buffers must *not* overlap.
* @param st Resampler state
- * @param channel_index Index of the channel to process for the multi-channel base (0 otherwise)
+ * @param channel_index Index of the channel to process for the multi-channel
+ * base (0 otherwise)
* @param in Input buffer
- * @param in_len Number of input samples in the input buffer. Returns the number of samples processed
+ * @param in_len Number of input samples in the input buffer. Returns the
+ * number of samples processed
* @param out Output buffer
* @param out_len Size of the output buffer. Returns the number of samples written
*/
-void speex_resampler_process_float(SpeexResamplerState *st, int channel_index, const float *in, int *in_len, float *out, int *out_len);
+void speex_resampler_process_float(SpeexResamplerState *st,
+ int channel_index,
+ const float *in,
+ int *in_len,
+ float *out,
+ int *out_len);
-/** Resample an int array. The input and output may *not* alias.
+/** Resample an int array. The input and output buffers must *not* overlap.
* @param st Resampler state
- * @param channel_index Index of the channel to process for the multi-channel base (0 otherwise)
+ * @param channel_index Index of the channel to process for the multi-channel
+ * base (0 otherwise)
* @param in Input buffer
- * @param in_len Number of input samples in the input buffer. Returns the number of samples processed
+ * @param in_len Number of input samples in the input buffer. Returns the number
+ * of samples processed
* @param out Output buffer
* @param out_len Size of the output buffer. Returns the number of samples written
*/
-void speex_resampler_process_int(SpeexResamplerState *st, int channel_index, const spx_int16_t *in, int *in_len, spx_int16_t *out, int *out_len);
+void speex_resampler_process_int(SpeexResamplerState *st,
+ int channel_index,
+ const spx_int16_t *in,
+ int *in_len,
+ spx_int16_t *out,
+ int *out_len);
+
+/** Resample an interleaved float array. The input and output buffers must *not* overlap.
+ * @param st Resampler state
+ * @param in Input buffer
+ * @param in_len Number of input samples in the input buffer. Returns the number
+ * of samples processed. This is all per-channel.
+ * @param out Output buffer
+ * @param out_len Size of the output buffer. Returns the number of samples written.
+ * This is all per-channel.
+ */
+void speex_resampler_process_interleaved_float(SpeexResamplerState *st,
+ const float *in,
+ int *in_len,
+ float *out,
+ int *out_len);
-/** Resample an interleaved float array. The input and output may *not* alias.
+/** Resample an interleaved int array. The input and output buffers must *not* overlap.
* @param st Resampler state
* @param in Input buffer
- * @param in_len Number of input samples in the input buffer. Returns the number of samples processed. This is all per-channel.
+ * @param in_len Number of input samples in the input buffer. Returns the number
+ * of samples processed. This is all per-channel.
* @param out Output buffer
- * @param out_len Size of the output buffer. Returns the number of samples written. This is all per-channel.
+ * @param out_len Size of the output buffer. Returns the number of samples written.
+ * This is all per-channel.
+ */
+void speex_resampler_process_interleaved_int(SpeexResamplerState *st,
+ const spx_int16_t *in,
+ int *in_len,
+ spx_int16_t *out,
+ int *out_len);
+
+/** Set (change) the input/output sampling rates (integer value).
+ * @param st Resampler state
+ * @param in_rate Input sampling rate (integer number of Hz).
+ * @param out_rate Output sampling rate (integer number of Hz).
+ */
+void speex_resampler_set_rate(SpeexResamplerState *st,
+ int in_rate,
+ int out_rate);
+
+/** Get the current input/output sampling rates (integer value).
+ * @param st Resampler state
+ * @param in_rate Input sampling rate (integer number of Hz) copied.
+ * @param out_rate Output sampling rate (integer number of Hz) copied.
*/
-void speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, int *in_len, float *out, int *out_len);
+void speex_resampler_get_rate(SpeexResamplerState *st,
+ int *in_rate,
+ int *out_rate);
-/** Set (change) the input/output sampling rates and resampling ratio.
+/** Set (change) the input/output sampling rates and resampling ratio
+ * (fractional values in Hz supported).
* @param st Resampler state
* @param ratio_num Numerator of the sampling rate ratio
* @param ratio_den Denominator of the sampling rate ratio
- * @param in_rate Nominal input sampling rate rounded to the nearest integer (in Hz). This does not need to be accurate.
- * @param out_rate Nominal output sampling rate rounded to the nearest integer (in Hz). This does not need to be accurate.
+ * @param in_rate Input sampling rate rounded to the nearest integer (in Hz).
+ * @param out_rate Output sampling rate rounded to the nearest integer (in Hz).
+ */
+void speex_resampler_set_rate_frac(SpeexResamplerState *st,
+ int ratio_num,
+ int ratio_den,
+ int in_rate,
+ int out_rate);
+
+/** Get the current resampling ratio. This will be reduced to the least
+ * common denominator.
+ * @param st Resampler state
+ * @param ratio_num Numerator of the sampling rate ratio copied
+ * @param ratio_den Denominator of the sampling rate ratio copied
*/
-void speex_resampler_set_rate(SpeexResamplerState *st, int ratio_num, int ratio_den, int in_rate, int out_rate);
+void speex_resampler_get_ratio(SpeexResamplerState *st,
+ int *ratio_num,
+ int *ratio_den);
/** Set (change) the conversion quality.
* @param st Resampler state
- * @param quality Resampling quality between 0 and 10, where 0 has poor quality and 10 has very high quality.
+ * @param quality Resampling quality between 0 and 10, where 0 has poor
+ * quality and 10 has very high quality.
*/
-void speex_resampler_set_quality(SpeexResamplerState *st, int quality);
+void speex_resampler_set_quality(SpeexResamplerState *st,
+ int quality);
+
+/** Get the conversion quality.
+ * @param st Resampler state
+ * @param quality Resampling quality between 0 and 10, where 0 has poor
+ * quality and 10 has very high quality.
+ */
+void speex_resampler_get_quality(SpeexResamplerState *st,
+ int *quality);
/** Set (change) the input stride.
* @param st Resampler state
* @param stride Input stride
*/
-void speex_resampler_set_input_stride(SpeexResamplerState *st, int stride);
+void speex_resampler_set_input_stride(SpeexResamplerState *st,
+ int stride);
+
+/** Get the input stride.
+ * @param st Resampler state
+ * @param stride Input stride copied
+ */
+void speex_resampler_get_input_stride(SpeexResamplerState *st,
+ int *stride);
/** Set (change) the output stride.
* @param st Resampler state
* @param stride Output stride
*/
-void speex_resample_set_output_stride(SpeexResamplerState *st, int stride);
+void speex_resample_set_output_stride(SpeexResamplerState *st,
+ int stride);
+
+/** Get the output stride.
+ * @param st Resampler state copied
+ * @param stride Output stride
+ */
+void speex_resample_get_output_stride(SpeexResamplerState *st,
+ int *stride);
-/** Make sure that the first samples to go out of the resamplers don't have leading zeros.
- * This is only useful before starting to use a newly created resampler.
+/** Make sure that the first samples to go out of the resamplers don't have
+ * leading zeros. This is only useful before starting to use a newly created
+ * resampler. It is recommended to use that when resampling an audio file, as
+ * it will generate a file with the same length. For real-time processing,
+ * it is probably easier not to use this call (so that the output duration
+ * is the same for the first frame).
* @param st Resampler state
*/
void speex_resampler_skip_zeros(SpeexResamplerState *st);
diff --git a/apps/codecs/libspeex/testresample.c b/apps/codecs/libspeex/testresample.c
index c54b113..5e02479 100644
--- a/apps/codecs/libspeex/testresample.c
+++ b/apps/codecs/libspeex/testresample.c
@@ -48,8 +48,8 @@ int main(int argc, char **argv)
short *out;
float *fin, *fout;
int count = 0;
- SpeexResamplerState *st = speex_resampler_init(1, 8000, 12000, 8000, 12000, 5);
- speex_resampler_set_rate(st, 16000, 8001, 8000, 15999);
+ SpeexResamplerState *st = speex_resampler_init(1, 8000, 12000, 10);
+ speex_resampler_set_rate(st, 8000, 15999);
speex_resampler_skip_zeros(st);
in = malloc(NN*sizeof(short));
@@ -67,9 +67,12 @@ int main(int argc, char **argv)
fin[i]=in[i];
in_len = NN;
out_len = 2*NN;
+ /*if (count==2)
+ speex_resampler_set_quality(st, 10);*/
speex_resampler_process_float(st, 0, fin, &in_len, fout, &out_len);
for (i=0;i<out_len;i++)
out[i]=floor(.5+fout[i]);
+ /*speex_warning_int("writing", out_len);*/
fwrite(out, sizeof(short), out_len, stdout);
count++;
}
diff --git a/apps/codecs/speex.c b/apps/codecs/speex.c
index a9b333b..8dd9f01 100644
--- a/apps/codecs/speex.c
+++ b/apps/codecs/speex.c
@@ -30,20 +30,18 @@
#define CHUNKSIZE 10000 /*2kb*/
#define SEEK_CHUNKSIZE 7*CHUNKSIZE
-//#define LOGF(...)
-
CODEC_HEADER
-struct codec_api *rb;
+spx_int16_t output[MAX_FRAME_SIZE] IBSS_ATTR;
-int get_more_data(spx_ogg_sync_state *oy,struct codec_api *rb)
+int get_more_data(spx_ogg_sync_state *oy)
{
int bytes;
char *buffer;
buffer = (char *)spx_ogg_sync_buffer(oy,CHUNKSIZE);
- bytes = rb->read_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);