1
0
Fork 0
forked from len0rd/rockbox

Sync Speex to SVN. Disable stereo compatibility hack since we don't needed it and it produced warnings. Remove unneeded math.h

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15613 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Thom Johansen 2007-11-14 02:15:56 +00:00
parent 91f618f1ba
commit 85b325fdb9
48 changed files with 698 additions and 481 deletions

View file

@ -51,7 +51,7 @@ struct kiss_fft_state{
C_ADDTO( res , a) : res += a C_ADDTO( res , a) : res += a
* */ * */
#ifdef FIXED_POINT #ifdef FIXED_POINT
#include "misc.h" #include "arch.h"
# define FRACBITS 15 # define FRACBITS 15
# define SAMPPROD spx_int32_t # define SAMPPROD spx_int32_t
#define SAMP_MAX 32767 #define SAMP_MAX 32767

View file

@ -35,6 +35,47 @@
#ifndef ARCH_H #ifndef ARCH_H
#define ARCH_H #define ARCH_H
#include "config-speex.h"
#ifndef SPEEX_VERSION
#define SPEEX_MAJOR_VERSION 1 /**< Major Speex version. */
#define SPEEX_MINOR_VERSION 1 /**< Minor Speex version. */
#define SPEEX_MICRO_VERSION 15 /**< Micro Speex version. */
#define SPEEX_EXTRA_VERSION "" /**< Extra Speex version. */
#define SPEEX_VERSION "speex-1.2beta3" /**< Speex version string. */
#endif
/* A couple test to catch stupid option combinations */
#ifdef FIXED_POINT
#ifdef FLOATING_POINT
#error You cannot compile as floating point and fixed point at the same time
#endif
#ifdef _USE_SSE
#error SSE is only for floating-point
#endif
#if ((defined (ARM4_ASM)||defined (ARM4_ASM)) && defined(BFIN_ASM)) || (defined (ARM4_ASM)&&defined(ARM5E_ASM))
#error Make up your mind. What CPU do you have?
#endif
#ifdef VORBIS_PSYCHO
#error Vorbis-psy model currently not implemented in fixed-point
#endif
#else
#ifndef FLOATING_POINT
#error You now need to define either FIXED_POINT or FLOATING_POINT
#endif
#if defined (ARM4_ASM) || defined(ARM5E_ASM) || defined(BFIN_ASM)
#error I suppose you can have a [ARM4/ARM5E/Blackfin] that has float instructions?
#endif
#ifdef FIXED_POINT_DEBUG
#error "Don't you think enabling fixed-point is a good thing to do if you want to debug that?"
#endif
#endif
#ifndef OUTSIDE_SPEEX #ifndef OUTSIDE_SPEEX
#include "speex/speex_types.h" #include "speex/speex_types.h"
#endif #endif
@ -192,4 +233,11 @@ typedef float spx_word32_t;
#endif #endif
#ifdef FIXED_DEBUG
long long spx_mips=0;
#endif
#endif #endif

View file

@ -37,7 +37,7 @@
#endif #endif
#include <speex/speex_bits.h> #include <speex/speex_bits.h>
#include "misc.h" #include "arch.h"
#include "os_support.h" #include "os_support.h"
/* Maximum size of the bit-stream (for fixed-size allocation) */ /* Maximum size of the bit-stream (for fixed-size allocation) */

View file

@ -37,7 +37,7 @@
#include "filters.h" #include "filters.h"
#include "stack_alloc.h" #include "stack_alloc.h"
#include "vq.h" #include "vq.h"
#include "misc.h" #include "arch.h"
#include "math_approx.h" #include "math_approx.h"
#include "os_support.h" #include "os_support.h"

View file

@ -36,7 +36,7 @@
#define CB_SEARCH_H #define CB_SEARCH_H
#include <speex/speex_bits.h> #include <speex/speex_bits.h>
#include "misc.h" #include "arch.h"
/** Split codebook parameters. */ /** Split codebook parameters. */
typedef struct split_cb_params { typedef struct split_cb_params {

View file

@ -40,7 +40,7 @@
#define USE_KISS_FFT #define USE_KISS_FFT
#include "misc.h" #include "arch.h"
#include "os_support.h" #include "os_support.h"
#define MAX_FFT_SIZE 2048 #define MAX_FFT_SIZE 2048

View file

@ -35,7 +35,7 @@
#ifndef FFTWRAP_H #ifndef FFTWRAP_H
#define FFTWRAP_H #define FFTWRAP_H
#include "misc.h" #include "arch.h"
/** Compute tables for an FFT */ /** Compute tables for an FFT */
void *spx_fft_init(int size); void *spx_fft_init(int size);

View file

@ -36,7 +36,7 @@
#endif #endif
#include "filterbank.h" #include "filterbank.h"
#include "misc.h" #include "arch.h"
#include <math.h> #include <math.h>
#include "math_approx.h" #include "math_approx.h"
#include "os_support.h" #include "os_support.h"

View file

@ -34,7 +34,7 @@
#ifndef FILTERBANK_H #ifndef FILTERBANK_H
#define FILTERBANK_H #define FILTERBANK_H
#include "misc.h" #include "arch.h"
typedef struct { typedef struct {
int *bank_left; int *bank_left;

View file

@ -36,7 +36,7 @@
#include "filters.h" #include "filters.h"
#include "stack_alloc.h" #include "stack_alloc.h"
#include "misc.h" #include "arch.h"
#include "math_approx.h" #include "math_approx.h"
#include "ltp.h" #include "ltp.h"
#include <math.h> #include <math.h>

View file

@ -35,7 +35,7 @@
#ifndef FILTERS_H #ifndef FILTERS_H
#define FILTERS_H #define FILTERS_H
#include "misc.h" #include "arch.h"
spx_word16_t compute_rms(const spx_sig_t *x, int len); spx_word16_t compute_rms(const spx_sig_t *x, int len);
spx_word16_t compute_rms16(const spx_word16_t *x, int len); spx_word16_t compute_rms16(const spx_word16_t *x, int len);

View file

@ -32,12 +32,27 @@
*/ */
/*
TODO:
- Write generic functions for computing stats and shifting the histogram
- Take into account the delay step when computing the stats and when shifting
- Linked list structure for holding the packets instead of the current fixed-size array
+ return memory to a pool
+ allow pre-allocation of the pool
+ optional max number of elements
- Statistics
+ drift
+ loss
+ late
+ jitter
+ buffering delay
*/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config-speex.h" #include "config-speex.h"
#endif #endif
#include "misc.h" #include "arch.h"
#include <speex/speex.h> #include <speex/speex.h>
#include <speex/speex_bits.h> #include <speex/speex_bits.h>
#include <speex/speex_jitter.h> #include <speex/speex_jitter.h>
@ -52,29 +67,157 @@
#define SPEEX_JITTER_MAX_BUFFER_SIZE 200 /**< Maximum number of packets in jitter buffer */ #define SPEEX_JITTER_MAX_BUFFER_SIZE 200 /**< Maximum number of packets in jitter buffer */
#define TSUB(a,b) ((spx_int32_t)((a)-(b)))
#define GT32(a,b) (((spx_int32_t)((a)-(b)))>0) #define GT32(a,b) (((spx_int32_t)((a)-(b)))>0)
#define GE32(a,b) (((spx_int32_t)((a)-(b)))>=0) #define GE32(a,b) (((spx_int32_t)((a)-(b)))>=0)
#define LT32(a,b) (((spx_int32_t)((a)-(b)))<0) #define LT32(a,b) (((spx_int32_t)((a)-(b)))<0)
#define LE32(a,b) (((spx_int32_t)((a)-(b)))<=0) #define LE32(a,b) (((spx_int32_t)((a)-(b)))<=0)
#define MAX_TIMINGS 20
#define MAX_BUFFERS 3
#define TOP_DELAY 25
#define WINDOW_SIZE 200
struct TimingBuffer {
int filled;
int curr_count;
spx_int16_t timing[MAX_TIMINGS];
spx_int16_t counts[MAX_TIMINGS];
};
static void tb_init(struct TimingBuffer *tb)
{
tb->filled = 0;
tb->curr_count = 0;
}
static void tb_add(struct TimingBuffer *tb, spx_int16_t timing)
{
int pos;
/*fprintf(stderr, "timing = %d\n", timing);*/
/*fprintf(stderr, "timing = %d, latest = %d, earliest = %d, filled = %d\n", timing, tb->timing[0], tb->timing[tb->filled-1], tb->filled);*/
if (tb->filled >= MAX_TIMINGS && timing >= tb->timing[tb->filled-1])
{
tb->curr_count++;
return;
}
pos = 0;
/* FIXME: Do bisection instead of linear search */
while (pos<tb->filled && timing >= tb->timing[pos])
{
pos++;
}
/*fprintf(stderr, "pos = %d filled = %d\n", pos, tb->filled);*/
speex_assert(pos <= tb->filled && pos < MAX_TIMINGS);
fprintf(stderr, "OK\n");
if (pos < tb->filled)
{
int move_size = tb->filled-pos;
if (tb->filled == MAX_TIMINGS)
move_size -= 1;
/*fprintf(stderr, "speex_move(%d %d %d)\n", pos+1, pos, move_size);*/
speex_move(&tb->timing[pos+1], &tb->timing[pos], move_size*sizeof(tb->timing[0]));
speex_move(&tb->counts[pos+1], &tb->counts[pos], move_size*sizeof(tb->counts[0]));
}
/*fprintf(stderr, "moved\n");*/
tb->timing[pos] = timing;
tb->counts[pos] = tb->curr_count;
/*{
int i;
for (i=0;i<MAX_TIMINGS;i++)
fprintf(stderr, "%d ", tb->timing[i]);
fprintf(stderr, "\n");
}*/
tb->curr_count++;
if (tb->filled<MAX_TIMINGS)
tb->filled++;
/*fprintf(stderr, "added\n");*/
}
/** Based on available data, this computes the optimal delay for the jitter buffer.
The optimised function is in timestamp units and is:
cost = delay + late_factor*[number of frames that would be late if we used that delay]
@param tb Array of buffers
@param late_factor Equivalent cost of a late frame (in timestamp units)
*/
static spx_int16_t tbs_get_opt_delay(struct TimingBuffer *tb, spx_int32_t late_factor)
{
int i;
spx_int16_t opt=0;
spx_int32_t best_cost=0x7fffffff;
int late = 0;
int pos[MAX_BUFFERS];
/*fprintf(stderr, "tbs_get_opt_delay\n");*/
for (i=0;i<MAX_BUFFERS;i++)
pos[i] = 0;
for (i=0;i<TOP_DELAY;i++)
{
int j;
int next=-1;
int latest = 32767;
for (j=0;j<MAX_BUFFERS;j++)
{
if (pos[j] < tb[j].filled && tb[j].timing[pos[j]] < latest)
{
next = j;
latest = tb[j].timing[pos[j]];
}
}
late++;
if (next != -1)
{
spx_int32_t cost;
pos[next]++;
/* When considering reducing delay, "on-time" frames could twice (this provides hysteresis) */
if (latest > 0)
late++;
cost = -latest + late_factor*late;
/*fprintf(stderr, "cost %d = -%d + %d * %d\n", cost, latest, late_factor, late);*/
if (cost < best_cost)
{
best_cost = cost;
opt = latest;
}
} else {
break;
}
}
return opt;
}
/** Jitter buffer structure */ /** Jitter buffer structure */
struct JitterBuffer_ { struct JitterBuffer_ {
spx_uint32_t pointer_timestamp; /**< Timestamp of what we will *get* next */ spx_uint32_t pointer_timestamp; /**< Timestamp of what we will *get* next */
spx_uint32_t current_timestamp; /**< Timestamp of the local clock (what we will *play* next) */ spx_uint32_t last_returned_timestamp;
spx_uint32_t next_stop;
char *buf[SPEEX_JITTER_MAX_BUFFER_SIZE]; /**< Buffer of packets (NULL if slot is free) */ JitterBufferPacket packets[SPEEX_JITTER_MAX_BUFFER_SIZE]; /**< Packets stored in the buffer */
spx_uint32_t timestamp[SPEEX_JITTER_MAX_BUFFER_SIZE]; /**< Timestamp of packet */ spx_uint32_t arrival[SPEEX_JITTER_MAX_BUFFER_SIZE]; /**< Packet arrival time (0 means it was late, even though it's a valid timestamp) */
int span[SPEEX_JITTER_MAX_BUFFER_SIZE]; /**< Timestamp of packet */
int len[SPEEX_JITTER_MAX_BUFFER_SIZE]; /**< Number of bytes in packet */
int tick_size; /**< Output granularity */ void (*destroy) (void *); /**< Callback for destroying a packet */
int resolution; /**< Time resolution for histogram (timestamp units) */
int delay_step; /**< Size of the steps when adjusting buffering (timestamp units) */
int res_delay_step; /**< Size of the steps when adjusting buffering (resolution units) */
int reset_state; /**< True if state was just reset */ 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 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 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 interp_requested; /**< An interpolation is requested by speex_jitter_update_delay() */
struct TimingBuffer _tb[MAX_BUFFERS]; /**< Don't use those directly */
struct TimingBuffer *timeBuffers[MAX_BUFFERS]; /**< Storing arrival time of latest frames so we can compute some stats */
float late_ratio_short;
float late_ratio_long;
float ontime_ratio_short;
float ontime_ratio_long;
float early_ratio_short;
float early_ratio_long;
int lost_count; /**< Number of consecutive lost packets */ int lost_count; /**< Number of consecutive lost packets */
float shortterm_margin[MAX_MARGIN]; /**< Short term margin histogram */ float shortterm_margin[MAX_MARGIN]; /**< Short term margin histogram */
float longterm_margin[MAX_MARGIN]; /**< Long term margin histogram */ float longterm_margin[MAX_MARGIN]; /**< Long term margin histogram */
@ -82,17 +225,21 @@ struct JitterBuffer_ {
}; };
/** Initialise jitter buffer */ /** Initialise jitter buffer */
JitterBuffer *jitter_buffer_init(int tick) JitterBuffer *jitter_buffer_init(int resolution)
{ {
JitterBuffer *jitter = (JitterBuffer*)speex_alloc(sizeof(JitterBuffer)); JitterBuffer *jitter = (JitterBuffer*)speex_alloc(sizeof(JitterBuffer));
if (jitter) if (jitter)
{ {
int i; int i;
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
jitter->buf[i]=NULL; jitter->packets[i].data=NULL;
jitter->tick_size = tick; jitter->resolution = resolution;
jitter->delay_step = resolution;
jitter->res_delay_step = 1;
/*FIXME: Should this be 0 or 1?*/
jitter->buffer_margin = 1; jitter->buffer_margin = 1;
jitter->late_cutoff = 50; jitter->late_cutoff = 50;
jitter->destroy = NULL;
jitter_buffer_reset(jitter); jitter_buffer_reset(jitter);
} }
return jitter; return jitter;
@ -104,15 +251,18 @@ void jitter_buffer_reset(JitterBuffer *jitter)
int i; int i;
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
{ {
if (jitter->buf[i]) if (jitter->packets[i].data)
{ {
speex_free(jitter->buf[i]); if (jitter->destroy)
jitter->buf[i] = NULL; jitter->destroy(jitter->packets[i].data);
else
speex_free(jitter->packets[i].data);
jitter->packets[i].data = NULL;
} }
} }
/* Timestamp is actually undefined at this point */ /* Timestamp is actually undefined at this point */
jitter->pointer_timestamp = 0; jitter->pointer_timestamp = 0;
jitter->current_timestamp = 0; jitter->next_stop = 0;
jitter->reset_state = 1; jitter->reset_state = 1;
jitter->lost_count = 0; jitter->lost_count = 0;
jitter->loss_rate = 0; jitter->loss_rate = 0;
@ -121,6 +271,12 @@ void jitter_buffer_reset(JitterBuffer *jitter)
jitter->shortterm_margin[i] = 0; jitter->shortterm_margin[i] = 0;
jitter->longterm_margin[i] = 0; jitter->longterm_margin[i] = 0;
} }
for (i=0;i<MAX_BUFFERS;i++)
{
tb_init(&jitter->_tb[i]);
jitter->timeBuffers[i] = &jitter->_tb[i];
}
/*fprintf (stderr, "reset\n");*/ /*fprintf (stderr, "reset\n");*/
} }
@ -131,79 +287,45 @@ void jitter_buffer_destroy(JitterBuffer *jitter)
speex_free(jitter); speex_free(jitter);
} }
/** Put one packet into the jitter buffer */ static void update_timings(JitterBuffer *jitter, spx_int32_t timing)
void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet)
{ {
int i,j; if (timing < -32767)
spx_int32_t arrival_margin; timing = -32767;
/*fprintf (stderr, "put packet %d %d\n", timestamp, span);*/ if (timing > 32767)
if (jitter->reset_state) timing = 32767;
if (jitter->timeBuffers[0]->curr_count >= WINDOW_SIZE)
{ {
jitter->reset_state=0; int i;
jitter->pointer_timestamp = packet->timestamp; /*fprintf(stderr, "Rotate buffer\n");*/
jitter->current_timestamp = packet->timestamp; struct TimingBuffer *tmp = jitter->timeBuffers[MAX_BUFFERS-1];
/*fprintf(stderr, "reset to %d\n", timestamp);*/ for (i=MAX_BUFFERS-1;i>=1;i--)
jitter->timeBuffers[i] = jitter->timeBuffers[i-1];
jitter->timeBuffers[0] = tmp;
tb_init(jitter->timeBuffers[0]);
} }
tb_add(jitter->timeBuffers[0], timing);
spx_int16_t opt = tbs_get_opt_delay(jitter->_tb, 2);
/*fprintf(stderr, "opt adjustment is %d\n", opt);*/
}
/* Cleanup buffer (remove old packets that weren't played) */ static void shift_timings(JitterBuffer *jitter, spx_int16_t amount)
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) {
int i, j;
for (i=0;i<MAX_BUFFERS;i++)
{ {
/* Make sure we don't discard a "just-late" packet in case we want to play it next (if we interpolate). */ for (j=0;j<jitter->timeBuffers[i]->filled;i++)
if (jitter->buf[i] && LE32(jitter->timestamp[i] + jitter->span[i], jitter->pointer_timestamp)) jitter->timeBuffers[i]->timing[j] += amount;
{
/*fprintf (stderr, "cleaned (not played)\n");*/
speex_free(jitter->buf[i]);
jitter->buf[i] = NULL;
}
} }
}
/*Find an empty slot in the buffer*/ static void update_histogram(JitterBuffer *jitter, spx_int32_t arrival_margin)
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) {
{ int i;
if (jitter->buf[i]==NULL)
break;
}
/*fprintf(stderr, "%d %d %f\n", timestamp, jitter->pointer_timestamp, jitter->drift_average);*/
/*No place left in the buffer*/
if (i==SPEEX_JITTER_MAX_BUFFER_SIZE)
{
int earliest=jitter->timestamp[0];
i=0;
for (j=1;j<SPEEX_JITTER_MAX_BUFFER_SIZE;j++)
{
if (!jitter->buf[i] || LT32(jitter->timestamp[j],earliest))
{
earliest = jitter->timestamp[j];
i=j;
}
}
speex_free(jitter->buf[i]);
jitter->buf[i]=NULL;
if (jitter->lost_count>20)
{
jitter_buffer_reset(jitter);
}
/*fprintf (stderr, "Buffer is full, discarding earliest frame %d (currently at %d)\n", timestamp, jitter->pointer_timestamp);*/
}
/* Copy packet in buffer */
jitter->buf[i]=(char*)speex_alloc(packet->len);
for (j=0;j<(int)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.
The arrival margin is how much in advance (or late) the packet it */
arrival_margin = (((spx_int32_t)packet->timestamp) - ((spx_int32_t)jitter->current_timestamp))/jitter->tick_size - jitter->buffer_margin;
if (arrival_margin >= -jitter->late_cutoff) if (arrival_margin >= -jitter->late_cutoff)
{ {
/* Here we compute the histogram based on the time of arrival of the packet. /* 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 This is based on a (first-order) recursive average. We keep both a short-term
histogram and a long-term histogram */ histogram and a long-term histogram */
spx_int32_t int_margin; spx_int32_t int_margin;
/* First, apply the "damping" of the recursive average to all bins */ /* First, apply the "damping" of the recursive average to all bins */
for (i=0;i<MAX_MARGIN;i++) for (i=0;i<MAX_MARGIN;i++)
@ -228,88 +350,215 @@ void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet)
jitter_buffer_reset(jitter); jitter_buffer_reset(jitter);
} }
} }
#if 0 /* Enable to check how much is being buffered */ }
if (rand()%1000==0)
static void shift_histogram(JitterBuffer *jitter, int amount)
{
int i, c;
if (amount == 0)
return;
if (amount > 0)
{ {
int count = 0; /* FIXME: This is terribly inefficient */
for (j=0;j<SPEEX_JITTER_MAX_BUFFER_SIZE;j++) for (c=0;c<amount;c++)
{ {
if (jitter->buf[j]) jitter->shortterm_margin[MAX_MARGIN-1] += jitter->shortterm_margin[MAX_MARGIN-2];
count++; 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;
}
} else {
/* FIXME: This is terribly inefficient */
for (c=0;c<-amount;c++)
{
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, "buffer_size = %d\n", count);
} }
#endif }
static void compute_statistics(JitterBuffer *jitter)
{
int i;
jitter->late_ratio_short = 0;
jitter->late_ratio_long = 0;
/* Count the proportion of packets that are late */
for (i=0;i<LATE_BINS;i++)
{
jitter->late_ratio_short += jitter->shortterm_margin[i];
jitter->late_ratio_long += jitter->longterm_margin[i];
}
/* Count the proportion of packets that are just on time */
jitter->ontime_ratio_short = 0;
jitter->ontime_ratio_long = 0;
for (;i<LATE_BINS+jitter->res_delay_step;i++)
{
jitter->ontime_ratio_short = jitter->shortterm_margin[i];
jitter->ontime_ratio_long = jitter->longterm_margin[i];
}
jitter->early_ratio_short = 0;
jitter->early_ratio_long = 0;
/* Count the proportion of packets that are early */
for (;i<MAX_MARGIN;i++)
{
jitter->early_ratio_short += jitter->shortterm_margin[i];
jitter->early_ratio_long += jitter->longterm_margin[i];
}
}
/** Put one packet into the jitter buffer */
void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet)
{
int i,j;
int late;
spx_int32_t arrival_margin;
spx_int32_t arrival_time;
/*fprintf (stderr, "put packet %d %d\n", timestamp, span);*/
/* Syncing on the first packet to arrive */
if (jitter->reset_state)
{
jitter->reset_state=0;
jitter->pointer_timestamp = packet->timestamp;
jitter->next_stop = packet->timestamp;
/*fprintf(stderr, "reset to %d\n", timestamp);*/
}
/* 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->packets[i].data && LE32(jitter->packets[i].timestamp + jitter->packets[i].span, jitter->pointer_timestamp))
{
/*fprintf (stderr, "cleaned (not played)\n");*/
if (jitter->destroy)
jitter->destroy(jitter->packets[i].data);
else
speex_free(jitter->packets[i].data);
jitter->packets[i].data = NULL;
}
}
/*fprintf(stderr, "arrival: %d %d %d\n", packet->timestamp, jitter->next_stop, jitter->pointer_timestamp);*/
/* Check if packet is late (could still be useful though) */
if (LT32(packet->timestamp, jitter->next_stop))
{
/*fprintf(stderr, "late by %d\n", jitter->next_stop - packet->timestamp);*/
/* The arrival margin is how much in advance (or in this case late) the packet it (in resolution units) */
arrival_margin = (((spx_int32_t)packet->timestamp) - ((spx_int32_t)jitter->next_stop))/jitter->resolution - jitter->buffer_margin;
/*fprintf(stderr, "put arrival_margin = %d\n", arrival_margin);*/
/*update_timings(jitter, ((spx_int32_t)packet->timestamp) - ((spx_int32_t)jitter->next_stop));*/
update_histogram(jitter, arrival_margin);
late = 1;
} else {
late = 0;
}
/* Only insert the packet if it's not hopelessly late (i.e. totally useless) */
if (GE32(packet->timestamp+packet->span+jitter->delay_step, jitter->pointer_timestamp))
{
/*Find an empty slot in the buffer*/
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
{
if (jitter->packets[i].data==NULL)
break;
}
/*No place left in the buffer, need to make room for it by discarding the oldest packet */
if (i==SPEEX_JITTER_MAX_BUFFER_SIZE)
{
int earliest=jitter->packets[0].timestamp;
i=0;
for (j=1;j<SPEEX_JITTER_MAX_BUFFER_SIZE;j++)
{
if (!jitter->packets[i].data || LT32(jitter->packets[j].timestamp,earliest))
{
earliest = jitter->packets[j].timestamp;
i=j;
}
}
if (jitter->destroy)
jitter->destroy(jitter->packets[i].data);
else
speex_free(jitter->packets[i].data);
jitter->packets[i].data=NULL;
if (jitter->lost_count>20)
{
jitter_buffer_reset(jitter);
}
/*fprintf (stderr, "Buffer is full, discarding earliest frame %d (currently at %d)\n", timestamp, jitter->pointer_timestamp);*/
}
/* Copy packet in buffer */
if (jitter->destroy)
{
jitter->packets[i].data = packet->data;
} else {
jitter->packets[i].data=(char*)speex_alloc(packet->len);
for (j=0;j<packet->len;j++)
jitter->packets[i].data[j]=packet->data[j];
}
jitter->packets[i].timestamp=packet->timestamp;
jitter->packets[i].span=packet->span;
jitter->packets[i].len=packet->len;
jitter->packets[i].user_data=packet->user_data;
if (late)
jitter->arrival[i] = 0;
else
jitter->arrival[i] = jitter->next_stop;
}
} }
/** Get one packet from the jitter buffer */ /** Get one packet from the jitter buffer */
int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t *start_offset) int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t desired_span, spx_int32_t *start_offset)
{ {
int i; int i;
unsigned int j; unsigned int j;
float late_ratio_short;
float late_ratio_long;
float ontime_ratio_short;
float ontime_ratio_long;
float early_ratio_short;
float early_ratio_long;
int chunk_size;
int incomplete = 0; int incomplete = 0;
jitter->last_returned_timestamp = jitter->pointer_timestamp;
if (jitter->interp_requested) if (jitter->interp_requested)
{ {
jitter->interp_requested = 0; jitter->interp_requested = 0;
if (start_offset) if (start_offset)
*start_offset = 0; *start_offset = 0;
packet->timestamp = jitter->pointer_timestamp; packet->timestamp = jitter->pointer_timestamp;
packet->span = jitter->tick_size; packet->span = jitter->delay_step;
jitter->pointer_timestamp += jitter->tick_size;
/* Increment the pointer because it got decremented in the delay update */
jitter->pointer_timestamp += jitter->delay_step;
packet->len = 0; packet->len = 0;
/*fprintf (stderr, "Deferred interpolate\n");*/
return JITTER_BUFFER_MISSING; return JITTER_BUFFER_MISSING;
} }
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 */
chunk_size = jitter->tick_size;
/* Compiling arrival statistics */
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];
}
if (0&&jitter->pointer_timestamp%1000==0)
{
/*fprintf (stderr, "%f %f %f %f %f %f\n", early_ratio_short, early_ratio_long, ontime_ratio_short, ontime_ratio_long, late_ratio_short, late_ratio_long);*/
/*fprintf (stderr, "%f %f\n", early_ratio_short + ontime_ratio_short + late_ratio_short, early_ratio_long + ontime_ratio_long + late_ratio_long);*/
}
/* Searching for the packet that fits best */ /* Searching for the packet that fits best */
/* Search the buffer for a packet with the right timestamp and spanning the whole current chunk */ /* Search the buffer for a packet with the right timestamp and spanning the whole current chunk */
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) 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->packets[i].data && jitter->packets[i].timestamp==jitter->pointer_timestamp && GE32(jitter->packets[i].timestamp+jitter->packets[i].span,jitter->pointer_timestamp+desired_span))
break; break;
} }
@ -318,7 +567,7 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int3
{ {
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
{ {
if (jitter->buf[i] && LE32(jitter->timestamp[i], jitter->pointer_timestamp) && GE32(jitter->timestamp[i]+jitter->span[i],jitter->pointer_timestamp+chunk_size)) if (jitter->packets[i].data && LE32(jitter->packets[i].timestamp, jitter->pointer_timestamp) && GE32(jitter->packets[i].timestamp+jitter->packets[i].span,jitter->pointer_timestamp+desired_span))
break; break;
} }
} }
@ -328,7 +577,7 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int3
{ {
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
{ {
if (jitter->buf[i] && LE32(jitter->timestamp[i], jitter->pointer_timestamp) && GT32(jitter->timestamp[i]+jitter->span[i],jitter->pointer_timestamp)) if (jitter->packets[i].data && LE32(jitter->packets[i].timestamp, jitter->pointer_timestamp) && GT32(jitter->packets[i].timestamp+jitter->packets[i].span,jitter->pointer_timestamp))
break; break;
} }
} }
@ -343,12 +592,12 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int3
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
{ {
/* check if packet starts within current chunk */ /* check if packet starts within current chunk */
if (jitter->buf[i] && LT32(jitter->timestamp[i],jitter->pointer_timestamp+chunk_size) && GE32(jitter->timestamp[i],jitter->pointer_timestamp)) if (jitter->packets[i].data && LT32(jitter->packets[i].timestamp,jitter->pointer_timestamp+desired_span) && GE32(jitter->packets[i].timestamp,jitter->pointer_timestamp))
{ {
if (!found || LT32(jitter->timestamp[i],best_time) || (jitter->timestamp[i]==best_time && GT32(jitter->span[i],best_span))) if (!found || LT32(jitter->packets[i].timestamp,best_time) || (jitter->packets[i].timestamp==best_time && GT32(jitter->packets[i].span,best_span)))
{ {
best_time = jitter->timestamp[i]; best_time = jitter->packets[i].timestamp;
best_span = jitter->span[i]; best_span = jitter->packets[i].span;
besti = i; besti = i;
found = 1; found = 1;
} }
@ -358,31 +607,62 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int3
{ {
i=besti; i=besti;
incomplete = 1; incomplete = 1;
/*fprintf (stderr, "incomplete: %d %d %d %d\n", jitter->timestamp[i], jitter->pointer_timestamp, chunk_size, jitter->span[i]);*/ /*fprintf (stderr, "incomplete: %d %d %d %d\n", jitter->packets[i].timestamp, jitter->pointer_timestamp, chunk_size, jitter->packets[i].span);*/
} }
} }
/* If we find something */ /* If we find something */
if (i!=SPEEX_JITTER_MAX_BUFFER_SIZE) if (i!=SPEEX_JITTER_MAX_BUFFER_SIZE)
{ {
/* We (obviously) haven't lost this packet */ /* We (obviously) haven't lost this packet */
jitter->lost_count = 0; jitter->lost_count = 0;
jitter->loss_rate = .999*jitter->loss_rate; jitter->loss_rate = .999*jitter->loss_rate;
/* Check for potential overflow */
packet->len = jitter->len[i]; /* In this case, 0 isn't as a valid timestamp */
if (jitter->arrival[i] != 0)
{
spx_int32_t arrival_margin;
/*fprintf(stderr, "early by %d\n", jitter->packets[i].timestamp - jitter->arrival[i]);*/
/* The arrival margin is how much in advance (or in this case late) the packet it (in resolution units) */
arrival_margin = (((spx_int32_t)jitter->packets[i].timestamp) - ((spx_int32_t)jitter->arrival[i]))/jitter->resolution - jitter->buffer_margin;
/*fprintf(stderr, "get arrival_margin = %d\n", arrival_margin);*/
/*update_timings(jitter, ((spx_int32_t)jitter->packets[i].timestamp) - ((spx_int32_t)jitter->arrival[i]));*/
update_histogram(jitter, arrival_margin);
}
/* FIXME: Check for potential overflow */
packet->len = jitter->packets[i].len;
/* Copy packet */ /* Copy packet */
for (j=0;j<packet->len;j++) if (jitter->destroy)
packet->data[j] = jitter->buf[i][j]; {
/* Remove packet */ packet->data = jitter->packets[i].data;
speex_free(jitter->buf[i]); } else {
jitter->buf[i] = NULL; for (j=0;j<packet->len;j++)
packet->data[j] = jitter->packets[i].data[j];
/* Remove packet */
speex_free(jitter->packets[i].data);
}
jitter->packets[i].data = NULL;
/* Set timestamp and span (if requested) */ /* Set timestamp and span (if requested) */
if (start_offset) if (start_offset)
*start_offset = (spx_int32_t)jitter->timestamp[i]-(spx_int32_t)jitter->pointer_timestamp; *start_offset = (spx_int32_t)jitter->packets[i].timestamp-(spx_int32_t)jitter->pointer_timestamp;
packet->timestamp = jitter->timestamp[i];
packet->span = jitter->span[i]; packet->timestamp = jitter->packets[i].timestamp;
/* Point at the end of the current packet */ jitter->last_returned_timestamp = packet->timestamp;
jitter->pointer_timestamp = jitter->timestamp[i]+jitter->span[i];
packet->span = jitter->packets[i].span;
packet->user_data = jitter->packets[i].user_data;
/* Point to the end of the current packet */
jitter->pointer_timestamp = jitter->packets[i].timestamp+jitter->packets[i].span;
if (incomplete) if (incomplete)
return JITTER_BUFFER_INCOMPLETE; return JITTER_BUFFER_INCOMPLETE;
else else
@ -391,6 +671,7 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int3
/* If we haven't found anything worth returning */ /* If we haven't found anything worth returning */
/*fprintf (stderr, "not found\n");*/ /*fprintf (stderr, "not found\n");*/
jitter->lost_count++; jitter->lost_count++;
/*fprintf (stderr, "m");*/ /*fprintf (stderr, "m");*/
@ -398,34 +679,71 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int3
jitter->loss_rate = .999*jitter->loss_rate + .001; jitter->loss_rate = .999*jitter->loss_rate + .001;
if (start_offset) if (start_offset)
*start_offset = 0; *start_offset = 0;
packet->timestamp = jitter->pointer_timestamp;
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 */ compute_statistics(jitter);
if (late_ratio_short > .1 || late_ratio_long > .03)
/* Should we force an increase in the buffer or just do normal interpolation? */
if (jitter->late_ratio_short > .1 || jitter->late_ratio_long > .03)
{ {
/* If too many packets are arriving late */ /* Increase buffering */
jitter->shortterm_margin[MAX_MARGIN-1] += jitter->shortterm_margin[MAX_MARGIN-2];
jitter->longterm_margin[MAX_MARGIN-1] += jitter->longterm_margin[MAX_MARGIN-2]; /* Shift histogram to compensate */
for (i=MAX_MARGIN-3;i>=0;i--) shift_histogram(jitter, jitter->res_delay_step);
{
jitter->shortterm_margin[i+1] = jitter->shortterm_margin[i]; packet->timestamp = jitter->pointer_timestamp;
jitter->longterm_margin[i+1] = jitter->longterm_margin[i]; packet->span = jitter->delay_step;
} /* Don't move the pointer_timestamp forward */
jitter->shortterm_margin[0] = 0; packet->len = 0;
jitter->longterm_margin[0] = 0;
jitter->pointer_timestamp -= jitter->tick_size; /*jitter->pointer_timestamp -= jitter->delay_step;*/
jitter->current_timestamp -= jitter->tick_size; /*fprintf (stderr, "Forced to interpolate\n");*/
/*fprintf (stderr, "i");*/ } else {
/*fprintf (stderr, "interpolate (getting some slack)\n");*/ /* Normal packet loss */
packet->timestamp = jitter->pointer_timestamp;
packet->span = desired_span;
jitter->pointer_timestamp += desired_span;
packet->len = 0;
/*fprintf (stderr, "Normal loss\n");*/
} }
return JITTER_BUFFER_MISSING; return JITTER_BUFFER_MISSING;
} }
int jitter_buffer_get_another(JitterBuffer *jitter, JitterBufferPacket *packet)
{
int i, j;
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
{
if (jitter->packets[i].data && jitter->packets[i].timestamp==jitter->last_returned_timestamp)
break;
}
if (i!=SPEEX_JITTER_MAX_BUFFER_SIZE)
{
/* Copy packet */
packet->len = jitter->packets[i].len;
if (jitter->destroy)
{
packet->data = jitter->packets[i].data;
} else {
for (j=0;j<packet->len;j++)
packet->data[j] = jitter->packets[i].data[j];
/* Remove packet */
speex_free(jitter->packets[i].data);
}
jitter->packets[i].data = NULL;
packet->timestamp = jitter->packets[i].timestamp;
packet->span = jitter->packets[i].span;
packet->user_data = jitter->packets[i].user_data;
return JITTER_BUFFER_OK;
} else {
packet->data = NULL;
packet->len = 0;
packet->span = 0;
return JITTER_BUFFER_MISSING;
}
}
/** Get pointer timestamp of jitter buffer */ /** Get pointer timestamp of jitter buffer */
int jitter_buffer_get_pointer_timestamp(JitterBuffer *jitter) int jitter_buffer_get_pointer_timestamp(JitterBuffer *jitter)
{ {
@ -434,81 +752,39 @@ int jitter_buffer_get_pointer_timestamp(JitterBuffer *jitter)
void jitter_buffer_tick(JitterBuffer *jitter) void jitter_buffer_tick(JitterBuffer *jitter)
{ {
jitter->current_timestamp += jitter->tick_size; jitter->next_stop = jitter->pointer_timestamp;
}
void jitter_buffer_remaining_span(JitterBuffer *jitter, spx_uint32_t rem)
{
jitter->next_stop = jitter->pointer_timestamp - rem;
} }
/* Let the jitter buffer know it's the right time to adjust the buffering delay to the network conditions */ /* 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_int32_t *start_offset) int jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t *start_offset)
{ {
int i; 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)) compute_statistics(jitter);
{
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 */ /* 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 (jitter->late_ratio_short > .1 || jitter->late_ratio_long > .03)
{ {
/* If too many packets are arriving late */ /* If too many packets are arriving late */
jitter->shortterm_margin[MAX_MARGIN-1] += jitter->shortterm_margin[MAX_MARGIN-2]; shift_histogram(jitter, jitter->res_delay_step);
jitter->longterm_margin[MAX_MARGIN-1] += jitter->longterm_margin[MAX_MARGIN-2];
for (i=MAX_MARGIN-3;i>=0;i--) jitter->pointer_timestamp -= jitter->delay_step;
{
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; jitter->interp_requested = 1;
/*fprintf (stderr, "Decision to interpolate\n");*/
return JITTER_BUFFER_ADJUST_INTERPOLATE; 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) } else if (jitter->late_ratio_short + jitter->ontime_ratio_short < .005 && jitter->late_ratio_long + jitter->ontime_ratio_long < .01 && jitter->early_ratio_short > .8)
{ {
/* Many frames arriving early */ /* Many frames arriving early */
jitter->shortterm_margin[0] += jitter->shortterm_margin[1]; shift_histogram(jitter, -jitter->res_delay_step);
jitter->longterm_margin[0] += jitter->longterm_margin[1];
for (i=1;i<MAX_MARGIN-1;i++) jitter->pointer_timestamp += jitter->delay_step;
{ /*fprintf (stderr, "Decision to drop\n");*/
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_DROP;
} }
@ -531,13 +807,26 @@ int jitter_buffer_ctl(JitterBuffer *jitter, int request, void *ptr)
count = 0; count = 0;
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
{ {
if (jitter->buf[i] && LE32(jitter->pointer_timestamp, jitter->timestamp[i])) if (jitter->packets[i].data && LE32(jitter->pointer_timestamp, jitter->packets[i].timestamp))
{ {
count++; count++;
} }
} }
*(spx_int32_t*)ptr = count; *(spx_int32_t*)ptr = count;
break; break;
case JITTER_BUFFER_SET_DESTROY_CALLBACK:
jitter->destroy = (void (*) (void *))ptr;
break;
case JITTER_BUFFER_GET_DESTROY_CALLBACK:
*(void (**) (void *))ptr = jitter->destroy;
break;
case JITTER_BUFFER_SET_DELAY_STEP:
jitter->delay_step = *(spx_int32_t*)ptr;
jitter->res_delay_step = jitter->delay_step/jitter->resolution;
break;
case JITTER_BUFFER_GET_DELAY_STEP:
*(spx_int32_t*)ptr = jitter->delay_step;
break;
default: default:
speex_warning_int("Unknown jitter_buffer_ctl request: ", request); speex_warning_int("Unknown jitter_buffer_ctl request: ", request);
return -1; return -1;

View file

@ -19,7 +19,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
#endif #endif
#include "_kiss_fft_guts.h" #include "_kiss_fft_guts.h"
#include "misc.h" #include "arch.h"
#include "os_support.h" #include "os_support.h"
/* The guts header contains all the multiplication and addition macros that are defined for /* The guts header contains all the multiplication and addition macros that are defined for

View file

@ -3,7 +3,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <math.h> #include <math.h>
#include "misc.h" #include "arch.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -32,7 +32,7 @@ extern "C" {
#ifdef FIXED_POINT #ifdef FIXED_POINT
#include "misc.h" #include "arch.h"
# define kiss_fft_scalar spx_int16_t # define kiss_fft_scalar spx_int16_t
#else #else
# ifndef kiss_fft_scalar # ifndef kiss_fft_scalar

View file

@ -35,7 +35,7 @@
#ifndef LPC_H #ifndef LPC_H
#define LPC_H #define LPC_H
#include "misc.h" #include "arch.h"
void _spx_autocorr( void _spx_autocorr(
const spx_word16_t * x, /* in: [0...n-1] samples x */ const spx_word16_t * x, /* in: [0...n-1] samples x */

View file

@ -51,7 +51,7 @@ Modified by Jean-Marc Valin
#ifndef __AK2LSPD__ #ifndef __AK2LSPD__
#define __AK2LSPD__ #define __AK2LSPD__
#include "misc.h" #include "arch.h"
int lpc_to_lsp (spx_coef_t *a, int lpcrdr, spx_lsp_t *freq, int nb, spx_word16_t delta, char *stack); int lpc_to_lsp (spx_coef_t *a, int lpcrdr, spx_lsp_t *freq, int nb, spx_word16_t delta, char *stack);
void lsp_to_lpc(spx_lsp_t *freq, spx_coef_t *ak, int lpcrdr, char *stack); void lsp_to_lpc(spx_lsp_t *freq, spx_coef_t *ak, int lpcrdr, char *stack);

View file

@ -33,7 +33,7 @@
*/ */
#include <speex/speex_bits.h> #include <speex/speex_bits.h>
#include "misc.h" #include "arch.h"
/** LTP parameters. */ /** LTP parameters. */
typedef struct { typedef struct {

View file

@ -1,32 +0,0 @@
/**************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
*
* Copyright (C) 2007 Dan Everton
*
* All files in this archive are subject to the GNU General Public License.
* See the file COPYING in the source tree root for full license agreement.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#ifndef MATH_H
#define MATH_H
float floor(float);
float exp(float);
float sqrt(float);
float fabs(float);
float log(float);
float pow(float, float);
float sin(float);
float cos(float);
#endif

View file

@ -35,7 +35,7 @@
#ifndef MATH_APPROX_H #ifndef MATH_APPROX_H
#define MATH_APPROX_H #define MATH_APPROX_H
#include "misc.h" #include "arch.h"
#ifndef FIXED_POINT #ifndef FIXED_POINT

View file

@ -69,7 +69,7 @@
#include "config-speex.h" #include "config-speex.h"
#endif #endif
#include "misc.h" #include "arch.h"
#include "speex/speex_echo.h" #include "speex/speex_echo.h"
#include "fftwrap.h" #include "fftwrap.h"
#include "pseudofloat.h" #include "pseudofloat.h"

View file

@ -37,7 +37,7 @@
#endif #endif
#include "medfilter.h" #include "medfilter.h"
#include "misc.h" #include "arch.h"
MedianFilter *median_filter_new(int N) MedianFilter *median_filter_new(int N)
{ {

View file

@ -1,99 +0,0 @@
/* Copyright (C) 2002 Jean-Marc Valin */
/**
@file misc.h
@brief Various compatibility routines for Speex
*/
/*
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 MISC_H
#define MISC_H
#include "config-speex.h"
#ifndef SPEEX_VERSION
#define SPEEX_MAJOR_VERSION 1 /**< Major Speex version. */
#define SPEEX_MINOR_VERSION 1 /**< Minor Speex version. */
#define SPEEX_MICRO_VERSION 15 /**< Micro Speex version. */
#define SPEEX_EXTRA_VERSION "" /**< Extra Speex version. */
#define SPEEX_VERSION "speex-1.2beta3" /**< Speex version string. */
#endif
/* A couple test to catch stupid option combinations */
#ifdef FIXED_POINT
#ifdef _USE_SSE
#error SSE is only for floating-point
#endif
#if ((defined (ARM4_ASM)||defined (ARM4_ASM)) && defined(BFIN_ASM)) || (defined (ARM4_ASM)&&defined(ARM5E_ASM))
#error Make up your mind. What CPU do you have?
#endif
#ifdef VORBIS_PSYCHO
#error Vorbis-psy model currently not implemented in fixed-point
#endif
#else
#if defined (ARM4_ASM) || defined(ARM5E_ASM) || defined(BFIN_ASM)
#error I suppose you can have a [ARM4/ARM5E/Blackfin] that has float instructions?
#endif
#ifdef FIXED_POINT_DEBUG
#error "Don't you think enabling fixed-point is a good thing to do if you want to debug that?"
#endif
#endif
#include "arch.h"
/** Convert little endian */
static inline spx_int32_t le_int(spx_int32_t i)
{
#if 1
return letoh32(i);
#elif !defined(__LITTLE_ENDIAN__) && ( defined(WORDS_BIGENDIAN) || defined(__BIG_ENDIAN__) )
spx_uint32_t ui, ret;
ui = i;
ret = ui>>24;
ret |= (ui>>8)&0x0000ff00;
ret |= (ui<<8)&0x00ff0000;
ret |= (ui<<24);
return ret;
#else
return i;
#endif
}
#ifdef FIXED_DEBUG
long long spx_mips=0;
#endif
#endif

View file

@ -43,7 +43,7 @@
#include "sb_celp.h" #include "sb_celp.h"
#include "nb_celp.h" #include "nb_celp.h"
#include "vbr.h" #include "vbr.h"
#include "misc.h" #include "arch.h"
#include <math.h> #include <math.h>
#ifndef NULL #ifndef NULL
@ -439,7 +439,6 @@ static const SpeexNBMode nb_mode = {
#else #else
0.9, 0.6, /* gamma1, gamma2 */ 0.9, 0.6, /* gamma1, gamma2 */
#endif #endif
.012, /*lag_factor*/
QCONST16(.0002,15), /*lpc_floor*/ QCONST16(.0002,15), /*lpc_floor*/
{NULL, &nb_submode1, &nb_submode2, &nb_submode3, &nb_submode4, &nb_submode5, &nb_submode6, &nb_submode7, {NULL, &nb_submode1, &nb_submode2, &nb_submode3, &nb_submode4, &nb_submode5, &nb_submode6, &nb_submode7,
&nb_submode8, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, &nb_submode8, NULL, NULL, NULL, NULL, NULL, NULL, NULL},

View file

@ -38,7 +38,7 @@
#include <speex/speex.h> #include <speex/speex.h>
#include <speex/speex_bits.h> #include <speex/speex_bits.h>
#include "misc.h" #include "arch.h"
#define NB_SUBMODES 16 #define NB_SUBMODES 16
#define NB_SUBMODE_BITS 4 #define NB_SUBMODE_BITS 4
@ -123,7 +123,6 @@ typedef struct SpeexNBMode {
spx_word16_t gamma1; /**< Perceptual filter parameter #1 */ spx_word16_t gamma1; /**< Perceptual filter parameter #1 */
spx_word16_t gamma2; /**< Perceptual filter parameter #2 */ spx_word16_t gamma2; /**< Perceptual filter parameter #2 */
float lag_factor; /**< Lag-windowing parameter */
spx_word16_t lpc_floor; /**< Noise floor for LPC analysis */ spx_word16_t lpc_floor; /**< Noise floor for LPC analysis */
const SpeexSubmode *submodes[NB_SUBMODES]; /**< Sub-mode data for the mode */ const SpeexSubmode *submodes[NB_SUBMODES]; /**< Sub-mode data for the mode */
@ -140,7 +139,6 @@ typedef struct SpeexSBMode {
int lpcSize; /**< Order of LPC filter */ int lpcSize; /**< Order of LPC filter */
spx_word16_t gamma1; /**< Perceptual filter parameter #1 */ spx_word16_t gamma1; /**< Perceptual filter parameter #1 */
spx_word16_t gamma2; /**< Perceptual filter parameter #1 */ spx_word16_t gamma2; /**< Perceptual filter parameter #1 */
float lag_factor; /**< Lag-windowing parameter */
spx_word16_t lpc_floor; /**< Noise floor for LPC analysis */ spx_word16_t lpc_floor; /**< Noise floor for LPC analysis */
spx_word16_t folding_gain; spx_word16_t folding_gain;

View file

@ -43,7 +43,7 @@
#include "sb_celp.h" #include "sb_celp.h"
#include "nb_celp.h" #include "nb_celp.h"
#include "vbr.h" #include "vbr.h"
#include "misc.h" #include "arch.h"
#include <math.h> #include <math.h>
#include "os_support.h" #include "os_support.h"
@ -231,7 +231,6 @@ static const SpeexSBMode sb_wb_mode = {
#else #else
0.9, 0.6, /* gamma1, gamma2 */ 0.9, 0.6, /* gamma1, gamma2 */
#endif #endif
.012, /*lag_factor*/
QCONST16(.0002,15), /*lpc_floor*/ QCONST16(.0002,15), /*lpc_floor*/
QCONST16(0.9f,15), QCONST16(0.9f,15),
{NULL, &wb_submode1, &wb_submode2, &wb_submode3, &wb_submode4, NULL, NULL, NULL}, {NULL, &wb_submode1, &wb_submode2, &wb_submode3, &wb_submode4, NULL, NULL, NULL},
@ -291,7 +290,6 @@ static const SpeexSBMode sb_uwb_mode = {
#else #else
0.9, 0.6, /* gamma1, gamma2 */ 0.9, 0.6, /* gamma1, gamma2 */
#endif #endif
.012, /*lag_factor*/
QCONST16(.0002,15), /*lpc_floor*/ QCONST16(.0002,15), /*lpc_floor*/
QCONST16(0.7f,15), QCONST16(0.7f,15),
{NULL, &wb_submode1, NULL, NULL, NULL, NULL, NULL, NULL}, {NULL, &wb_submode1, NULL, NULL, NULL, NULL, NULL, NULL},

View file

@ -45,7 +45,7 @@
#include "vq.h" #include "vq.h"
#include <speex/speex_bits.h> #include <speex/speex_bits.h>
#include "vbr.h" #include "vbr.h"
#include "misc.h" #include "arch.h"
#include "math_approx.h" #include "math_approx.h"
#include "os_support.h" #include "os_support.h"
#include <speex/speex_callbacks.h> #include <speex/speex_callbacks.h>
@ -108,6 +108,7 @@ const float exc_gain_quant_scal1[2]={0.70469f, 1.05127f};
#define sqr(x) ((x)*(x)) #define sqr(x) ((x)*(x))
extern const spx_word16_t lag_window[];
extern const spx_word16_t lpc_window[]; extern const spx_word16_t lpc_window[];
#ifndef SPEEX_DISABLE_ENCODER #ifndef SPEEX_DISABLE_ENCODER
void *nb_encoder_init(const SpeexMode *m) void *nb_encoder_init(const SpeexMode *m)
@ -137,7 +138,6 @@ void *nb_encoder_init(const SpeexMode *m)
st->gamma2=mode->gamma2; st->gamma2=mode->gamma2;
st->min_pitch=mode->pitchStart; st->min_pitch=mode->pitchStart;
st->max_pitch=mode->pitchEnd; st->max_pitch=mode->pitchEnd;
st->lag_factor=mode->lag_factor;
st->lpc_floor = mode->lpc_floor; st->lpc_floor = mode->lpc_floor;
st->submodes=mode->submodes; st->submodes=mode->submodes;
@ -166,17 +166,13 @@ void *nb_encoder_init(const SpeexMode *m)
st->window= lpc_window; st->window= lpc_window;
/* Create the window for autocorrelation (lag-windowing) */ /* Create the window for autocorrelation (lag-windowing) */
st->lagWindow = (spx_word16_t*)speex_alloc((st->lpcSize+1)*sizeof(spx_word16_t)); st->lagWindow = lag_window;
for (i=0;i<st->lpcSize+1;i++)
st->lagWindow[i]=16384*exp(-.5*sqr(2*M_PI*st->lag_factor*i));
st->old_lsp = (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->old_qlsp = (spx_lsp_t*)speex_alloc((st->lpcSize)*sizeof(spx_lsp_t));
st->first = 1; st->first = 1;
for (i=0;i<st->lpcSize;i++) for (i=0;i<st->lpcSize;i++)
{ st->old_lsp[i]= DIV32(MULT16_16(QCONST16(3.1415927f, LSP_SHIFT), i+1), st->lpcSize+1);
st->old_lsp[i]=LSP_SCALING*(M_PI*((float)(i+1)))/(st->lpcSize+1);
}
st->mem_sp = (spx_mem_t*)speex_alloc((st->lpcSize)*sizeof(spx_mem_t)); st->mem_sp = (spx_mem_t*)speex_alloc((st->lpcSize)*sizeof(spx_mem_t));
st->mem_sw = (spx_mem_t*)speex_alloc((st->lpcSize)*sizeof(spx_mem_t)); st->mem_sw = (spx_mem_t*)speex_alloc((st->lpcSize)*sizeof(spx_mem_t));
@ -225,8 +221,6 @@ void nb_encoder_destroy(void *state)
speex_free (st->old_qlsp); speex_free (st->old_qlsp);
speex_free (st->swBuf); speex_free (st->swBuf);
speex_free (st->lagWindow);
speex_free (st->old_lsp); speex_free (st->old_lsp);
speex_free (st->mem_sp); speex_free (st->mem_sp);
speex_free (st->mem_sw); speex_free (st->mem_sw);
@ -591,6 +585,8 @@ int nb_encode(void *state, void *vin, SpeexBits *bits)
if (SUBMODE(forced_pitch_gain)) if (SUBMODE(forced_pitch_gain))
{ {
int quant; int quant;
/* This just damps the pitch a bit, because it tends to be too aggressive when forced */
ol_pitch_coef = MULT16_16_Q15(QCONST16(.9,15), ol_pitch_coef);
#ifdef FIXED_POINT #ifdef FIXED_POINT
quant = PSHR16(MULT16_16_16(15, ol_pitch_coef),GAIN_SHIFT); quant = PSHR16(MULT16_16_16(15, ol_pitch_coef),GAIN_SHIFT);
#else #else
@ -1724,7 +1720,7 @@ int nb_encoder_ctl(void *state, int request, void *ptr)
st->bounded_pitch = 1; st->bounded_pitch = 1;
st->first = 1; st->first = 1;
for (i=0;i<st->lpcSize;i++) for (i=0;i<st->lpcSize;i++)
st->old_lsp[i]=(M_PI*((float)(i+1)))/(st->lpcSize+1); st->old_lsp[i]= DIV32(MULT16_16(QCONST16(3.1415927f, LSP_SHIFT), i+1), st->lpcSize+1);
for (i=0;i<st->lpcSize;i++) for (i=0;i<st->lpcSize;i++)
st->mem_sw[i]=st->mem_sw_whole[i]=st->mem_sp[i]=st->mem_exc[i]=0; st->mem_sw[i]=st->mem_sw_whole[i]=st->mem_sp[i]=st->mem_exc[i]=0;
for (i=0;i<st->frameSize+st->max_pitch+1;i++) for (i=0;i<st->frameSize+st->max_pitch+1;i++)

View file

@ -73,7 +73,6 @@ typedef struct EncState {
spx_word16_t gamma1; /**< Perceptual filter: A(z/gamma1) */ spx_word16_t gamma1; /**< Perceptual filter: A(z/gamma1) */
spx_word16_t gamma2; /**< Perceptual filter: A(z/gamma2) */ spx_word16_t gamma2; /**< Perceptual filter: A(z/gamma2) */
float lag_factor; /**< Lag windowing Gaussian width */
spx_word16_t lpc_floor; /**< Noise floor multiplier for A[0] in LPC analysis*/ spx_word16_t lpc_floor; /**< Noise floor multiplier for A[0] in LPC analysis*/
char *stack; /**< Pseudo-stack allocation for temporary memory */ char *stack; /**< Pseudo-stack allocation for temporary memory */
spx_word16_t *winBuf; /**< Input buffer (original signal) */ spx_word16_t *winBuf; /**< Input buffer (original signal) */
@ -82,7 +81,7 @@ typedef struct EncState {
spx_word16_t *swBuf; /**< Weighted signal buffer */ spx_word16_t *swBuf; /**< Weighted signal buffer */
spx_word16_t *sw; /**< Start of weighted signal frame */ spx_word16_t *sw; /**< Start of weighted signal frame */
const spx_word16_t *window; /**< Temporary (Hanning) window */ const spx_word16_t *window; /**< Temporary (Hanning) window */
spx_word16_t *lagWindow; /**< Window applied to auto-correlation */ const spx_word16_t *lagWindow; /**< Window applied to auto-correlation */
spx_lsp_t *old_lsp; /**< LSPs for previous frame */ spx_lsp_t *old_lsp; /**< LSPs for previous frame */
spx_lsp_t *old_qlsp; /**< Quantized LSPs for previous frame */ spx_lsp_t *old_qlsp; /**< Quantized LSPs for previous frame */
spx_mem_t *mem_sp; /**< Filter memory for signal synthesis */ spx_mem_t *mem_sp; /**< Filter memory for signal synthesis */

View file

@ -23,7 +23,7 @@
//#include "config-tremor.h" //#include "config-tremor.h"
#include <string.h> #include <string.h>
#include "speex/ogg.h" #include "speex/ogg.h"
#include "misc.h" #include "arch.h"
/* A complete description of Ogg framing exists in docs/framing.html */ /* A complete description of Ogg framing exists in docs/framing.html */

View file

@ -41,10 +41,14 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
/** Speex wrapper for calloc. To do your own dynamic allocation, all you need to do is replace this function, speex_realloc and speex_free */ /** Speex wrapper for calloc. To do your own dynamic allocation, all you need to do is replace this function, speex_realloc and speex_free
NOTE: speex_alloc needs to CLEAR THE MEMORY */
#ifndef OVERRIDE_SPEEX_ALLOC #ifndef OVERRIDE_SPEEX_ALLOC
static inline void *speex_alloc (int size) static inline void *speex_alloc (int size)
{ {
/* WARNING: this is not equivalent to malloc(). If you want to use malloc()
or your own allocator, YOU NEED TO CLEAR THE MEMORY ALLOCATED. Otherwise
you will experience strange bugs */
return calloc(size,1); return calloc(size,1);
} }
#endif #endif
@ -53,6 +57,7 @@ static inline void *speex_alloc (int size)
#ifndef OVERRIDE_SPEEX_ALLOC_SCRATCH #ifndef OVERRIDE_SPEEX_ALLOC_SCRATCH
static inline void *speex_alloc_scratch (int size) static inline void *speex_alloc_scratch (int size)
{ {
/* Scratch space doesn't need to be cleared */
return calloc(size,1); return calloc(size,1);
} }
#endif #endif

View file

@ -62,7 +62,7 @@
#include <math.h> #include <math.h>
#include "speex/speex_preprocess.h" #include "speex/speex_preprocess.h"
#include "speex/speex_echo.h" #include "speex/speex_echo.h"
#include "misc.h" #include "arch.h"
#include "fftwrap.h" #include "fftwrap.h"
#include "filterbank.h" #include "filterbank.h"
#include "math_approx.h" #include "math_approx.h"
@ -1127,16 +1127,16 @@ int speex_preprocess_ctl(SpeexPreprocessState *state, int request, void *ptr)
break; break;
case SPEEX_PREPROCESS_SET_PROB_START: case SPEEX_PREPROCESS_SET_PROB_START:
*(spx_int32_t*)ptr = MIN32(Q15_ONE,MAX32(0, *(spx_int32_t*)ptr)); *(spx_int32_t*)ptr = MIN32(100,MAX32(0, *(spx_int32_t*)ptr));
st->speech_prob_start = DIV32_16(MULT16_16(32767,*(spx_int32_t*)ptr), 100); st->speech_prob_start = DIV32_16(MULT16_16(Q15ONE,*(spx_int32_t*)ptr), 100);
break; break;
case SPEEX_PREPROCESS_GET_PROB_START: case SPEEX_PREPROCESS_GET_PROB_START:
(*(spx_int32_t*)ptr) = MULT16_16_Q15(st->speech_prob_start, 100); (*(spx_int32_t*)ptr) = MULT16_16_Q15(st->speech_prob_start, 100);
break; break;
case SPEEX_PREPROCESS_SET_PROB_CONTINUE: case SPEEX_PREPROCESS_SET_PROB_CONTINUE:
*(spx_int32_t*)ptr = MIN32(Q15_ONE,MAX32(0, *(spx_int32_t*)ptr)); *(spx_int32_t*)ptr = MIN32(100,MAX32(0, *(spx_int32_t*)ptr));
st->speech_prob_continue = DIV32_16(MULT16_16(32767,*(spx_int32_t*)ptr), 100); st->speech_prob_continue = DIV32_16(MULT16_16(Q15ONE,*(spx_int32_t*)ptr), 100);
break; break;
case SPEEX_PREPROCESS_GET_PROB_CONTINUE: case SPEEX_PREPROCESS_GET_PROB_CONTINUE:
(*(spx_int32_t*)ptr) = MULT16_16_Q15(st->speech_prob_continue, 100); (*(spx_int32_t*)ptr) = MULT16_16_Q15(st->speech_prob_continue, 100);
@ -1166,6 +1166,11 @@ int speex_preprocess_ctl(SpeexPreprocessState *state, int request, void *ptr)
case SPEEX_PREPROCESS_GET_ECHO_STATE: case SPEEX_PREPROCESS_GET_ECHO_STATE:
ptr = (void*)st->echo_state; ptr = (void*)st->echo_state;
break; break;
#ifndef FIXED_POINT
case SPEEX_PREPROCESS_GET_AGC_LOUDNESS:
(*(spx_int32_t*)ptr) = pow(st->loudness, 1.0/LOUDNESS_EXP);
break;
#endif
default: default:
speex_warning_int("Unknown speex_preprocess_ctl request: ", request); speex_warning_int("Unknown speex_preprocess_ctl request: ", request);

View file

@ -44,7 +44,7 @@
#ifndef PSEUDOFLOAT_H #ifndef PSEUDOFLOAT_H
#define PSEUDOFLOAT_H #define PSEUDOFLOAT_H
#include "misc.h" #include "arch.h"
#include "os_support.h" #include "os_support.h"
#include "math_approx.h" #include "math_approx.h"
#include <math.h> #include <math.h>

View file

@ -41,7 +41,7 @@
#define M_PI 3.14159265358979323846 #define M_PI 3.14159265358979323846
#endif #endif
#include "misc.h" #include "arch.h"
#ifdef BFIN_ASM #ifdef BFIN_ASM
#include "quant_lsp_bfin.h" #include "quant_lsp_bfin.h"

View file

@ -36,7 +36,7 @@
#define QUANT_LSP_H #define QUANT_LSP_H
#include <speex/speex_bits.h> #include <speex/speex_bits.h>
#include "misc.h" #include "arch.h"
#define MAX_LSP_SIZE 20 #define MAX_LSP_SIZE 20

View file

@ -70,7 +70,7 @@ static void speex_free (void *ptr) {free(ptr);}
#else /* OUTSIDE_SPEEX */ #else /* OUTSIDE_SPEEX */
#include "speex/speex_resampler.h" #include "speex/speex_resampler.h"
#include "misc.h" #include "arch.h"
#include "os_support.h" #include "os_support.h"
#endif /* OUTSIDE_SPEEX */ #endif /* OUTSIDE_SPEEX */

View file

@ -43,7 +43,7 @@
#include "quant_lsp.h" #include "quant_lsp.h"
#include "vq.h" #include "vq.h"
#include "ltp.h" #include "ltp.h"
#include "misc.h" #include "arch.h"
#include "math_approx.h" #include "math_approx.h"
#include "os_support.h" #include "os_support.h"
@ -183,6 +183,7 @@ static const float h0[64] = {
#endif #endif
extern const spx_word16_t lag_window[];
extern const spx_word16_t lpc_window[]; extern const spx_word16_t lpc_window[];
#ifndef SPEEX_DISABLE_ENCODER #ifndef SPEEX_DISABLE_ENCODER
@ -224,7 +225,6 @@ void *sb_encoder_init(const SpeexMode *m)
tmp=1; tmp=1;
speex_encoder_ctl(st->st_low, SPEEX_SET_WIDEBAND, &tmp); speex_encoder_ctl(st->st_low, SPEEX_SET_WIDEBAND, &tmp);
st->lag_factor = mode->lag_factor;
st->lpc_floor = mode->lpc_floor; st->lpc_floor = mode->lpc_floor;
st->gamma1=mode->gamma1; st->gamma1=mode->gamma1;
st->gamma2=mode->gamma2; st->gamma2=mode->gamma2;
@ -237,9 +237,7 @@ void *sb_encoder_init(const SpeexMode *m)
st->window= lpc_window; st->window= lpc_window;
st->lagWindow = (spx_word16_t*)speex_alloc((st->lpcSize+1)*sizeof(spx_word16_t)); st->lagWindow = lag_window;
for (i=0;i<st->lpcSize+1;i++)
st->lagWindow[i]=16384*exp(-.5*sqr(2*M_PI*st->lag_factor*i));
st->old_lsp = (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->old_qlsp = (spx_lsp_t*)speex_alloc(st->lpcSize*sizeof(spx_lsp_t));
@ -253,9 +251,7 @@ void *sb_encoder_init(const SpeexMode *m)
st->mem_sw = (spx_mem_t*)speex_alloc((st->lpcSize)*sizeof(spx_mem_t)); st->mem_sw = (spx_mem_t*)speex_alloc((st->lpcSize)*sizeof(spx_mem_t));
for (i=0;i<st->lpcSize;i++) for (i=0;i<st->lpcSize;i++)
{ st->old_lsp[i]= DIV32(MULT16_16(QCONST16(3.1415927f, LSP_SHIFT), i+1), st->lpcSize+1);
st->old_lsp[i]=LSP_SCALING*(M_PI*((float)(i+1)))/(st->lpcSize+1);
}
st->vbr_quality = 8; st->vbr_quality = 8;
st->vbr_enabled = 0; st->vbr_enabled = 0;
@ -288,8 +284,6 @@ void sb_encoder_destroy(void *state)
speex_free(st->h0_mem); speex_free(st->h0_mem);
speex_free(st->h1_mem); speex_free(st->h1_mem);
speex_free(st->lagWindow);
speex_free(st->old_lsp); speex_free(st->old_lsp);
speex_free(st->old_qlsp); speex_free(st->old_qlsp);
speex_free(st->interp_qlpc); speex_free(st->interp_qlpc);
@ -1271,7 +1265,7 @@ int sb_encoder_ctl(void *state, int request, void *ptr)
int i; int i;
st->first = 1; st->first = 1;
for (i=0;i<st->lpcSize;i++) for (i=0;i<st->lpcSize;i++)
st->old_lsp[i]=(M_PI*((float)(i+1)))/(st->lpcSize+1); st->old_lsp[i]= DIV32(MULT16_16(QCONST16(3.1415927f, LSP_SHIFT), i+1), st->lpcSize+1);
for (i=0;i<st->lpcSize;i++) for (i=0;i<st->lpcSize;i++)
st->mem_sw[i]=st->mem_sp[i]=st->mem_sp2[i]=0; st->mem_sw[i]=st->mem_sp[i]=st->mem_sp2[i]=0;
for (i=0;i<QMF_ORDER;i++) for (i=0;i<QMF_ORDER;i++)

View file

@ -51,7 +51,6 @@ typedef struct SBEncState {
int windowSize; /**< Length of high-band LPC window*/ int windowSize; /**< Length of high-band LPC window*/
int lpcSize; /**< Order of high-band LPC analysis */ int lpcSize; /**< Order of high-band LPC analysis */
int first; /**< First frame? */ int first; /**< First frame? */
float lag_factor; /**< Lag-windowing control parameter */
spx_word16_t lpc_floor; /**< Controls LPC analysis noise floor */ spx_word16_t lpc_floor; /**< Controls LPC analysis noise floor */
spx_word16_t gamma1; /**< Perceptual weighting coef 1 */ spx_word16_t gamma1; /**< Perceptual weighting coef 1 */
spx_word16_t gamma2; /**< Perceptual weighting coef 2 */ spx_word16_t gamma2; /**< Perceptual weighting coef 2 */
@ -61,7 +60,7 @@ typedef struct SBEncState {
spx_word16_t *h0_mem, *h1_mem; spx_word16_t *h0_mem, *h1_mem;
const spx_word16_t *window; /**< LPC analysis window */ const spx_word16_t *window; /**< LPC analysis window */
spx_word16_t *lagWindow; /**< Auto-correlation window */ const spx_word16_t *lagWindow; /**< Auto-correlation window */
spx_lsp_t *old_lsp; /**< LSPs of previous frame */ spx_lsp_t *old_lsp; /**< LSPs of previous frame */
spx_lsp_t *old_qlsp; /**< Quantized LSPs of previous frame */ spx_lsp_t *old_qlsp; /**< Quantized LSPs of previous frame */
spx_coef_t *interp_qlpc; /**< Interpolated quantized LPCs for current sub-frame */ spx_coef_t *interp_qlpc; /**< Interpolated quantized LPCs for current sub-frame */

View file

@ -34,7 +34,7 @@
#include <math.h> #include <math.h>
#include "smallft.h" #include "smallft.h"
#include "misc.h" #include "arch.h"
#include "os_support.h" #include "os_support.h"
static void drfti1(int n, float *wa, int *ifac){ static void drfti1(int n, float *wa, int *ifac){

View file

@ -41,8 +41,7 @@
* @{ * @{
*/ */
#include "speex.h" #include "speex_types.h"
#include "speex_bits.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -63,6 +62,7 @@ struct _JitterBufferPacket {
spx_uint32_t len; /**< Length of the packet in bytes */ spx_uint32_t len; /**< Length of the packet in bytes */
spx_uint32_t timestamp; /**< Timestamp for the packet */ spx_uint32_t timestamp; /**< Timestamp for the packet */
spx_uint32_t span; /**< Time covered by the packet (same units as timestamp) */ spx_uint32_t span; /**< Time covered by the packet (same units as timestamp) */
spx_uint32_t user_data; /**< Put whatever data you like here (it's ignored by the jitter buffer) */
}; };
/** Packet has been retrieved */ /** Packet has been retrieved */
@ -82,11 +82,21 @@ struct _JitterBufferPacket {
/** Get minimum amount of extra buffering required (margin) */ /** Get minimum amount of extra buffering required (margin) */
#define JITTER_BUFFER_GET_MARGIN 1 #define JITTER_BUFFER_GET_MARGIN 1
/* JITTER_BUFFER_SET_AVAILABLE_COUNT wouldn't make sense */ /* JITTER_BUFFER_SET_AVAILABLE_COUNT wouldn't make sense */
/** Get the amount of available packets currently buffered */ /** Get the amount of available packets currently buffered */
#define JITTER_BUFFER_GET_AVAILABLE_COUNT 3 #define JITTER_BUFFER_GET_AVAILABLE_COUNT 3
/** Included because of an early misspelling (will remove in next release) */ /** Included because of an early misspelling (will remove in next release) */
#define JITTER_BUFFER_GET_AVALIABLE_COUNT 3 #define JITTER_BUFFER_GET_AVALIABLE_COUNT 3
/** */
#define JITTER_BUFFER_SET_DESTROY_CALLBACK 4
/** */
#define JITTER_BUFFER_GET_DESTROY_CALLBACK 5
/** */
#define JITTER_BUFFER_SET_DELAY_STEP 6
/** */
#define JITTER_BUFFER_GET_DELAY_STEP 7
#define JITTER_BUFFER_ADJUST_INTERPOLATE -1 #define JITTER_BUFFER_ADJUST_INTERPOLATE -1
@ -123,9 +133,18 @@ void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet);
* *
* @param jitter Jitter buffer state * @param jitter Jitter buffer state
* @param packet Returned packet * @param packet Returned packet
* @param desired_span Number of samples (or units) we wish to get from the buffer (no guarantee)
* @param current_timestamp Timestamp for the returned packet * @param current_timestamp Timestamp for the returned packet
*/ */
int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t *start_offset); int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t desired_span, spx_int32_t *start_offset);
/** Used right after jitter_buffer_get() to obtain another packet that would have the same timestamp.
* This is mainly useful for media where a single "frame" can be split into several packets.
*
* @param jitter Jitter buffer state
* @param packet Returned packet
*/
int jitter_buffer_get_another(JitterBuffer *jitter, JitterBufferPacket *packet);
/** Get pointer timestamp of jitter buffer /** Get pointer timestamp of jitter buffer
* *
@ -139,6 +158,12 @@ int jitter_buffer_get_pointer_timestamp(JitterBuffer *jitter);
*/ */
void jitter_buffer_tick(JitterBuffer *jitter); void jitter_buffer_tick(JitterBuffer *jitter);
/** Telling the jitter buffer about the remaining data in the application buffer
* @param jitter Jitter buffer state
* @param rem Amount of data buffered by the application (timestamp units)
*/
void jitter_buffer_remaining_span(JitterBuffer *jitter, spx_uint32_t rem);
/** Used like the ioctl function to control the jitter buffer parameters /** Used like the ioctl function to control the jitter buffer parameters
* *
* @param jitter Jitter buffer state * @param jitter Jitter buffer state
@ -152,45 +177,8 @@ int jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet,
/* @} */ /* @} */
/** @defgroup SpeexJitter SpeexJitter: Adaptive jitter buffer specifically for Speex
* This is the jitter buffer that reorders UDP/RTP packets and adjusts the buffer size
* to maintain good quality and low latency. This is a simplified version that works only
* with Speex, but is much easier to use.
* @{
*/
/** Speex jitter-buffer state. Never use it directly! */
typedef struct SpeexJitter {
SpeexBits current_packet; /**< Current Speex packet */
int valid_bits; /**< True if Speex bits are valid */
JitterBuffer *packets; /**< Generic jitter buffer state */
void *dec; /**< Pointer to Speex decoder */
spx_int32_t frame_size; /**< Frame size of Speex decoder */
} SpeexJitter;
/** Initialise jitter buffer
*
* @param jitter State of the Speex jitter buffer
* @param decoder Speex decoder to call
* @param sampling_rate Sampling rate used by the decoder
*/
void speex_jitter_init(SpeexJitter *jitter, void *decoder, int sampling_rate);
/** Destroy jitter buffer */
void speex_jitter_destroy(SpeexJitter *jitter);
/** Put one packet into the jitter buffer */
void speex_jitter_put(SpeexJitter *jitter, char *packet, int len, int timestamp);
/** Get one packet from the jitter buffer */
void speex_jitter_get(SpeexJitter *jitter, spx_int16_t *out, int *start_offset);
/** Get pointer timestamp of jitter buffer */
int speex_jitter_get_pointer_timestamp(SpeexJitter *jitter);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
/* @} */
#endif #endif

View file

@ -178,6 +178,10 @@ int speex_preprocess_ctl(SpeexPreprocessState *st, int request, void *ptr);
/** Get maximal gain in dB (int32) */ /** Get maximal gain in dB (int32) */
#define SPEEX_PREPROCESS_GET_AGC_MAX_GAIN 31 #define SPEEX_PREPROCESS_GET_AGC_MAX_GAIN 31
/* Can't set loudness */
/** Get loudness */
#define SPEEX_PREPROCESS_GET_AGC_LOUDNESS 33
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -60,7 +60,7 @@ typedef struct SpeexStereoState {
#define SPEEX_STEREO_STATE_INIT {1,.5,1,1,0,0} #define SPEEX_STEREO_STATE_INIT {1,.5,1,1,0,0}
/** Initialise/create a stereo stereo state */ /** Initialise/create a stereo stereo state */
SpeexStereoState *speex_stereo_state_init(); SpeexStereoState *speex_stereo_state_init(void);
/** Reset/re-initialise an already allocated stereo state */ /** Reset/re-initialise an already allocated stereo state */
void speex_stereo_state_reset(SpeexStereoState *stereo); void speex_stereo_state_reset(SpeexStereoState *stereo);

View file

@ -37,7 +37,7 @@
#endif #endif
#include <speex/speex_callbacks.h> #include <speex/speex_callbacks.h>
#include "misc.h" #include "arch.h"
#include "os_support.h" #include "os_support.h"
int speex_inband_handler(SpeexBits *bits, SpeexCallback *callback_list, void *state) int speex_inband_handler(SpeexBits *bits, SpeexCallback *callback_list, void *state)

View file

@ -35,7 +35,7 @@
#include "config-speex.h" #include "config-speex.h"
#endif #endif
#include "misc.h" #include "arch.h"
#include <speex/speex_header.h> #include <speex/speex_header.h>
#include <speex/speex.h> #include <speex/speex.h>
#include "os_support.h" #include "os_support.h"
@ -44,6 +44,24 @@
#define NULL 0 #define NULL 0
#endif #endif
/** Convert little endian */
static inline spx_int32_t le_int(spx_int32_t i)
{
#if 1
return letoh32(i);
#elif !defined(__LITTLE_ENDIAN__) && ( defined(WORDS_BIGENDIAN) || defined(__BIG_ENDIAN__) )
spx_uint32_t ui, ret;
ui = i;
ret = ui>>24;
ret |= (ui>>8)&0x0000ff00;
ret |= (ui<<8)&0x00ff0000;
ret |= (ui<<24);
return ret;
#else
return i;
#endif
}
#define ENDIAN_SWITCH(x) {x=le_int(x);} #define ENDIAN_SWITCH(x) {x=le_int(x);}

View file

@ -213,7 +213,7 @@ void speex_decode_stereo_int(spx_int16_t *data, int frame_size, SpeexStereoState
spx_word16_t e_left, e_right, e_ratio; spx_word16_t e_left, e_right, e_ratio;
RealSpeexStereoState *stereo = (RealSpeexStereoState*)_stereo; RealSpeexStereoState *stereo = (RealSpeexStereoState*)_stereo;
COMPATIBILITY_HACK(stereo); /* COMPATIBILITY_HACK(stereo); */
balance=stereo->balance; balance=stereo->balance;
e_ratio=stereo->e_ratio; e_ratio=stereo->e_ratio;
@ -240,7 +240,7 @@ int speex_std_stereo_request_handler(SpeexBits *bits, void *state, void *data)
stereo = (RealSpeexStereoState*)data; stereo = (RealSpeexStereoState*)data;
COMPATIBILITY_HACK(stereo); /* COMPATIBILITY_HACK(stereo); */
if (speex_bits_unpack_unsigned(bits, 1)) if (speex_bits_unpack_unsigned(bits, 1))
sign=-1; sign=-1;

View file

@ -37,7 +37,7 @@
#ifndef VBR_H #ifndef VBR_H
#define VBR_H #define VBR_H
#include "misc.h" #include "arch.h"
#define VBR_MEMORY_SIZE 5 #define VBR_MEMORY_SIZE 5

View file

@ -35,7 +35,7 @@
#ifdef VORBIS_PSYCHO #ifdef VORBIS_PSYCHO
#include "misc.h" #include "arch.h"
#include "smallft.h" #include "smallft.h"
#include "lpc.h" #include "lpc.h"
#include "vorbis_psy.h" #include "vorbis_psy.h"

View file

@ -36,7 +36,7 @@
#include "vq.h" #include "vq.h"
#include "stack_alloc.h" #include "stack_alloc.h"
#include "misc.h" #include "arch.h"
#ifdef _USE_SSE #ifdef _USE_SSE
#include <xmmintrin.h> #include <xmmintrin.h>

View file

@ -35,7 +35,7 @@
#ifndef VQ_H #ifndef VQ_H
#define VQ_H #define VQ_H
#include "misc.h" #include "arch.h"
int scal_quant(spx_word16_t in, const spx_word16_t *boundary, int entries); int scal_quant(spx_word16_t in, const spx_word16_t *boundary, int entries);
int scal_quant32(spx_word32_t in, const spx_word32_t *boundary, int entries); int scal_quant32(spx_word32_t in, const spx_word32_t *boundary, int entries);

View file

@ -33,9 +33,13 @@
#include "config-speex.h" #include "config-speex.h"
#endif #endif
#include "misc.h" #include "arch.h"
#ifdef FIXED_POINT #ifdef FIXED_POINT
const spx_word16_t lag_window[11] ICONST_ATTR = {
16384, 16337, 16199, 15970, 15656, 15260, 14790, 14254, 13659, 13015, 12330
};
const spx_word16_t lpc_window[200] ICONST_ATTR = { const spx_word16_t lpc_window[200] ICONST_ATTR = {
1310, 1313, 1321, 1333, 1352, 1375, 1403, 1436, 1310, 1313, 1321, 1333, 1352, 1375, 1403, 1436,
1475, 1518, 1567, 1621, 1679, 1743, 1811, 1884, 1475, 1518, 1567, 1621, 1679, 1743, 1811, 1884,
@ -64,6 +68,10 @@ const spx_word16_t lpc_window[200] ICONST_ATTR = {
6797, 6028, 5251, 4470, 3695, 2943, 2248, 1696 6797, 6028, 5251, 4470, 3695, 2943, 2248, 1696
}; };
#else #else
const spx_word16_t lag_window[11] = {
1.00000, 0.99716, 0.98869, 0.97474, 0.95554, 0.93140, 0.90273, 0.86998, 0.83367, 0.79434, 0.75258
};
const spx_word16_t lpc_window[200] = { const spx_word16_t lpc_window[200] = {
0.080000f, 0.080158f, 0.080630f, 0.081418f, 0.082520f, 0.083935f, 0.085663f, 0.087703f, 0.080000f, 0.080158f, 0.080630f, 0.081418f, 0.082520f, 0.083935f, 0.085663f, 0.087703f,
0.090052f, 0.092710f, 0.095674f, 0.098943f, 0.102514f, 0.106385f, 0.110553f, 0.115015f, 0.090052f, 0.092710f, 0.095674f, 0.098943f, 0.102514f, 0.106385f, 0.110553f, 0.115015f,