forked from len0rd/rockbox
Sync Speex to SVN.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15750 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
14ac7cafc8
commit
57a27c69a9
17 changed files with 375 additions and 328 deletions
|
|
@ -11,6 +11,10 @@
|
|||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
#ifndef ROCKBOX_VOICE_ENCODER
|
||||
|
||||
#define DISABLE_FLOAT_API
|
||||
#define DISABLE_VBR
|
||||
|
||||
/* Make use of ARM4E assembly optimizations */
|
||||
#if defined(CPU_ARM)
|
||||
#define ARM4_ASM
|
||||
|
|
|
|||
|
|
@ -34,8 +34,10 @@
|
|||
|
||||
/*
|
||||
TODO:
|
||||
- Write generic functions for computing stats and shifting the histogram
|
||||
- Take into account the delay step when computing the stats and when shifting
|
||||
- Add short-term estimate
|
||||
- Defensive programming
|
||||
+ warn when last returned < last desired (begative buffering)
|
||||
+ warn if update_delay not called between get() and tick() or is called twice in a row
|
||||
- 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
|
||||
|
|
@ -62,9 +64,6 @@ TODO:
|
|||
#define NULL 0
|
||||
#endif
|
||||
|
||||
#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 */
|
||||
|
||||
#define TSUB(a,b) ((spx_int32_t)((a)-(b)))
|
||||
|
|
@ -74,16 +73,18 @@ TODO:
|
|||
#define LT32(a,b) (((spx_int32_t)((a)-(b)))<0)
|
||||
#define LE32(a,b) (((spx_int32_t)((a)-(b)))<=0)
|
||||
|
||||
#define ROUND_DOWN(x, step) ((x)<0 ? ((x)-(step)+1)/(step)*(step) : (x)/(step)*(step))
|
||||
|
||||
#define MAX_TIMINGS 20
|
||||
#define MAX_BUFFERS 3
|
||||
#define TOP_DELAY 25
|
||||
#define WINDOW_SIZE 200
|
||||
#define TOP_DELAY 20
|
||||
|
||||
/** Buffer that keeps the time of arrival of the latest packets */
|
||||
struct TimingBuffer {
|
||||
int filled;
|
||||
int curr_count;
|
||||
spx_int16_t timing[MAX_TIMINGS];
|
||||
spx_int16_t counts[MAX_TIMINGS];
|
||||
int filled; /**< Number of entries occupied in "timing" and "counts"*/
|
||||
int curr_count; /**< Number of packet timings we got (including those we discarded) */
|
||||
spx_int16_t timing[MAX_TIMINGS]; /**< Sorted list of all timings ("latest" packets first) */
|
||||
spx_int16_t counts[MAX_TIMINGS]; /**< Order the packets were put in (will be used for short-term estimate) */
|
||||
};
|
||||
|
||||
static void tb_init(struct TimingBuffer *tb)
|
||||
|
|
@ -92,16 +93,18 @@ static void tb_init(struct TimingBuffer *tb)
|
|||
tb->curr_count = 0;
|
||||
}
|
||||
|
||||
/* Add the timing of a new packet to the TimingBuffer */
|
||||
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);*/
|
||||
/* Discard packet that won't make it into the list because they're too early */
|
||||
if (tb->filled >= MAX_TIMINGS && timing >= tb->timing[tb->filled-1])
|
||||
{
|
||||
tb->curr_count++;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Find where the timing info goes in the sorted list */
|
||||
pos = 0;
|
||||
/* FIXME: Do bisection instead of linear search */
|
||||
while (pos<tb->filled && timing >= tb->timing[pos])
|
||||
|
|
@ -109,56 +112,107 @@ static void tb_add(struct TimingBuffer *tb, spx_int16_t timing)
|
|||
pos++;
|
||||
}
|
||||
|
||||
/*fprintf(stderr, "pos = %d filled = %d\n", pos, tb->filled);*/
|
||||
speex_assert(pos <= tb->filled && pos < MAX_TIMINGS);
|
||||
fprintf(stderr, "OK\n");
|
||||
|
||||
/* Shift everything so we can perform the insertion */
|
||||
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");*/
|
||||
/* Insert */
|
||||
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");*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Jitter buffer structure */
|
||||
struct JitterBuffer_ {
|
||||
spx_uint32_t pointer_timestamp; /**< Timestamp of what we will *get* next */
|
||||
spx_uint32_t last_returned_timestamp; /**< Useful for getting the next packet with the same timestamp (for fragmented media) */
|
||||
spx_uint32_t next_stop; /**< Estimated time the next get() will be called */
|
||||
|
||||
spx_int32_t buffered; /**< Amount of data we think is still buffered by the application (timestamp units)*/
|
||||
|
||||
JitterBufferPacket packets[SPEEX_JITTER_MAX_BUFFER_SIZE]; /**< Packets stored in the buffer */
|
||||
spx_uint32_t arrival[SPEEX_JITTER_MAX_BUFFER_SIZE]; /**< Packet arrival time (0 means it was late, even though it's a valid timestamp) */
|
||||
|
||||
void (*destroy) (void *); /**< Callback for destroying a packet */
|
||||
|
||||
spx_int32_t delay_step; /**< Size of the steps when adjusting buffering (timestamp units) */
|
||||
spx_int32_t concealment_size; /**< Size of the packet loss concealment "units" */
|
||||
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() */
|
||||
|
||||
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 */
|
||||
int window_size; /**< Total window over which the late frames are counted */
|
||||
int subwindow_size; /**< Sub-window size for faster computation */
|
||||
int max_late_rate; /**< Absolute maximum amount of late packets tolerable (in percent) */
|
||||
int latency_tradeoff; /**< Latency equivalent of losing one percent of packets */
|
||||
int auto_tradeoff; /**< Latency equivalent of losing one percent of packets (automatic default) */
|
||||
|
||||
int lost_count; /**< Number of consecutive lost packets */
|
||||
};
|
||||
|
||||
/** 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)
|
||||
static spx_int16_t compute_opt_delay(JitterBuffer *jitter)
|
||||
{
|
||||
int i;
|
||||
spx_int16_t opt=0;
|
||||
spx_int32_t best_cost=0x7fffffff;
|
||||
int late = 0;
|
||||
int pos[MAX_BUFFERS];
|
||||
int tot_count;
|
||||
float late_factor;
|
||||
int penalty_taken = 0;
|
||||
int best = 0;
|
||||
int worst = 0;
|
||||
spx_int32_t deltaT;
|
||||
struct TimingBuffer *tb;
|
||||
|
||||
/*fprintf(stderr, "tbs_get_opt_delay\n");*/
|
||||
tb = jitter->_tb;
|
||||
|
||||
/* Number of packet timings we have received (including those we didn't keep) */
|
||||
tot_count = 0;
|
||||
for (i=0;i<MAX_BUFFERS;i++)
|
||||
tot_count += tb[i].curr_count;
|
||||
if (tot_count==0)
|
||||
return 0;
|
||||
|
||||
/* Compute cost for one lost packet */
|
||||
if (jitter->latency_tradeoff != 0)
|
||||
late_factor = jitter->latency_tradeoff * 100.0f / tot_count;
|
||||
else
|
||||
late_factor = jitter->auto_tradeoff * jitter->window_size/tot_count;
|
||||
|
||||
/*fprintf(stderr, "late_factor = %f\n", late_factor);*/
|
||||
for (i=0;i<MAX_BUFFERS;i++)
|
||||
pos[i] = 0;
|
||||
|
||||
/* Pick the TOP_DELAY "latest" packets (doesn't need to actually be late
|
||||
for the current settings) */
|
||||
for (i=0;i<TOP_DELAY;i++)
|
||||
{
|
||||
int j;
|
||||
int next=-1;
|
||||
int latest = 32767;
|
||||
/* Pick latest amoung all sub-windows */
|
||||
for (j=0;j<MAX_BUFFERS;j++)
|
||||
{
|
||||
if (pos[j] < tb[j].filled && tb[j].timing[pos[j]] < latest)
|
||||
|
|
@ -167,16 +221,19 @@ static spx_int16_t tbs_get_opt_delay(struct TimingBuffer *tb, spx_int32_t late_f
|
|||
latest = tb[j].timing[pos[j]];
|
||||
}
|
||||
}
|
||||
late++;
|
||||
if (next != -1)
|
||||
{
|
||||
spx_int32_t cost;
|
||||
|
||||
if (i==0)
|
||||
worst = latest;
|
||||
best = latest;
|
||||
latest = ROUND_DOWN(latest, jitter->delay_step);
|
||||
pos[next]++;
|
||||
/* When considering reducing delay, "on-time" frames could twice (this provides hysteresis) */
|
||||
if (latest > 0)
|
||||
late++;
|
||||
|
||||
/* Actual cost function that tells us how bad using this delay would be */
|
||||
cost = -latest + late_factor*late;
|
||||
/*fprintf(stderr, "cost %d = -%d + %d * %d\n", cost, latest, late_factor, late);*/
|
||||
/*fprintf(stderr, "cost %d = %d + %f * %d\n", cost, -latest, late_factor, late);*/
|
||||
if (cost < best_cost)
|
||||
{
|
||||
best_cost = cost;
|
||||
|
|
@ -185,61 +242,50 @@ static spx_int16_t tbs_get_opt_delay(struct TimingBuffer *tb, spx_int32_t late_f
|
|||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
/* For the next timing we will consider, there will be one more late packet to count */
|
||||
late++;
|
||||
/* Two-frame penalty if we're going to increase the amount of late frames (hysteresis) */
|
||||
if (latest >= 0 && !penalty_taken)
|
||||
{
|
||||
penalty_taken = 1;
|
||||
late+=2;
|
||||
}
|
||||
}
|
||||
|
||||
deltaT = best-worst;
|
||||
/* This is a default "automatic latency tradeoff" when none is provided */
|
||||
jitter->auto_tradeoff = 1 + deltaT/TOP_DELAY;
|
||||
/*fprintf(stderr, "auto_tradeoff = %d (%d %d %d)\n", jitter->auto_tradeoff, best, worst, i);*/
|
||||
|
||||
/* FIXME: Compute a short-term estimate too and combine with the long-term one */
|
||||
|
||||
/* Prevents reducing the buffer size when we haven't really had much data */
|
||||
if (tot_count < TOP_DELAY && opt > 0)
|
||||
return 0;
|
||||
return opt;
|
||||
}
|
||||
|
||||
/** Jitter buffer structure */
|
||||
struct JitterBuffer_ {
|
||||
spx_uint32_t pointer_timestamp; /**< Timestamp of what we will *get* next */
|
||||
spx_uint32_t last_returned_timestamp;
|
||||
spx_uint32_t next_stop;
|
||||
|
||||
JitterBufferPacket packets[SPEEX_JITTER_MAX_BUFFER_SIZE]; /**< Packets stored in the buffer */
|
||||
spx_uint32_t arrival[SPEEX_JITTER_MAX_BUFFER_SIZE]; /**< Packet arrival time (0 means it was late, even though it's a valid timestamp) */
|
||||
|
||||
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 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() */
|
||||
|
||||
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 */
|
||||
float shortterm_margin[MAX_MARGIN]; /**< Short term margin histogram */
|
||||
float longterm_margin[MAX_MARGIN]; /**< Long term margin histogram */
|
||||
float loss_rate; /**< Average loss rate */
|
||||
};
|
||||
|
||||
/** Initialise jitter buffer */
|
||||
JitterBuffer *jitter_buffer_init(int resolution)
|
||||
JitterBuffer *jitter_buffer_init(void)
|
||||
{
|
||||
JitterBuffer *jitter = (JitterBuffer*)speex_alloc(sizeof(JitterBuffer));
|
||||
if (jitter)
|
||||
{
|
||||
int i;
|
||||
spx_int32_t tmp;
|
||||
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
|
||||
jitter->packets[i].data=NULL;
|
||||
jitter->resolution = resolution;
|
||||
jitter->delay_step = resolution;
|
||||
jitter->res_delay_step = 1;
|
||||
jitter->delay_step = 1;
|
||||
jitter->concealment_size = 1;
|
||||
/*FIXME: Should this be 0 or 1?*/
|
||||
jitter->buffer_margin = 1;
|
||||
jitter->buffer_margin = 0;
|
||||
jitter->late_cutoff = 50;
|
||||
jitter->destroy = NULL;
|
||||
jitter->latency_tradeoff = 0;
|
||||
tmp = 4;
|
||||
jitter_buffer_ctl(jitter, JITTER_BUFFER_SET_MAX_LATE_RATE, &tmp);
|
||||
jitter_buffer_reset(jitter);
|
||||
}
|
||||
return jitter;
|
||||
|
|
@ -265,12 +311,8 @@ void jitter_buffer_reset(JitterBuffer *jitter)
|
|||
jitter->next_stop = 0;
|
||||
jitter->reset_state = 1;
|
||||
jitter->lost_count = 0;
|
||||
jitter->loss_rate = 0;
|
||||
for (i=0;i<MAX_MARGIN;i++)
|
||||
{
|
||||
jitter->shortterm_margin[i] = 0;
|
||||
jitter->longterm_margin[i] = 0;
|
||||
}
|
||||
jitter->buffered = 0;
|
||||
jitter->auto_tradeoff = 32000;
|
||||
|
||||
for (i=0;i<MAX_BUFFERS;i++)
|
||||
{
|
||||
|
|
@ -287,13 +329,15 @@ void jitter_buffer_destroy(JitterBuffer *jitter)
|
|||
speex_free(jitter);
|
||||
}
|
||||
|
||||
/** Take the following timing into consideration for future calculations */
|
||||
static void update_timings(JitterBuffer *jitter, spx_int32_t timing)
|
||||
{
|
||||
if (timing < -32767)
|
||||
timing = -32767;
|
||||
if (timing > 32767)
|
||||
timing = 32767;
|
||||
if (jitter->timeBuffers[0]->curr_count >= WINDOW_SIZE)
|
||||
/* If the current sub-window is full, perform a rotation and discard oldest sub-widow */
|
||||
if (jitter->timeBuffers[0]->curr_count >= jitter->subwindow_size)
|
||||
{
|
||||
int i;
|
||||
/*fprintf(stderr, "Rotate buffer\n");*/
|
||||
|
|
@ -304,129 +348,25 @@ static void update_timings(JitterBuffer *jitter, spx_int32_t timing)
|
|||
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);*/
|
||||
}
|
||||
|
||||
/** Compensate all timings when we do an adjustment of the buffering */
|
||||
static void shift_timings(JitterBuffer *jitter, spx_int16_t amount)
|
||||
{
|
||||
int i, j;
|
||||
for (i=0;i<MAX_BUFFERS;i++)
|
||||
{
|
||||
for (j=0;j<jitter->timeBuffers[i]->filled;i++)
|
||||
for (j=0;j<jitter->timeBuffers[i]->filled;j++)
|
||||
jitter->timeBuffers[i]->timing[j] += amount;
|
||||
}
|
||||
}
|
||||
|
||||
static void update_histogram(JitterBuffer *jitter, spx_int32_t arrival_margin)
|
||||
{
|
||||
int i;
|
||||
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;
|
||||
}
|
||||
/* 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)
|
||||
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)
|
||||
{
|
||||
jitter_buffer_reset(jitter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void shift_histogram(JitterBuffer *jitter, int amount)
|
||||
{
|
||||
int i, c;
|
||||
if (amount == 0)
|
||||
return;
|
||||
if (amount > 0)
|
||||
{
|
||||
/* FIXME: This is terribly inefficient */
|
||||
for (c=0;c<amount;c++)
|
||||
{
|
||||
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;
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 */
|
||||
|
|
@ -457,14 +397,7 @@ void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet)
|
|||
/* 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);
|
||||
update_timings(jitter, ((spx_int32_t)packet->timestamp) - ((spx_int32_t)jitter->next_stop) - jitter->buffer_margin);
|
||||
late = 1;
|
||||
} else {
|
||||
late = 0;
|
||||
|
|
@ -534,22 +467,26 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int3
|
|||
int i;
|
||||
unsigned int j;
|
||||
int incomplete = 0;
|
||||
spx_int16_t opt;
|
||||
|
||||
jitter->last_returned_timestamp = jitter->pointer_timestamp;
|
||||
|
||||
if (jitter->interp_requested)
|
||||
if (jitter->interp_requested != 0)
|
||||
{
|
||||
jitter->interp_requested = 0;
|
||||
if (start_offset)
|
||||
*start_offset = 0;
|
||||
packet->timestamp = jitter->pointer_timestamp;
|
||||
packet->span = jitter->delay_step;
|
||||
packet->span = jitter->interp_requested;
|
||||
|
||||
/* Increment the pointer because it got decremented in the delay update */
|
||||
jitter->pointer_timestamp += jitter->delay_step;
|
||||
jitter->pointer_timestamp += jitter->interp_requested;
|
||||
packet->len = 0;
|
||||
/*fprintf (stderr, "Deferred interpolate\n");*/
|
||||
|
||||
jitter->interp_requested = 0;
|
||||
|
||||
jitter->buffered = packet->span - desired_span;
|
||||
|
||||
return JITTER_BUFFER_MISSING;
|
||||
}
|
||||
|
||||
|
|
@ -618,23 +555,11 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int3
|
|||
|
||||
/* We (obviously) haven't lost this packet */
|
||||
jitter->lost_count = 0;
|
||||
jitter->loss_rate = .999*jitter->loss_rate;
|
||||
|
||||
/* 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);
|
||||
|
||||
update_timings(jitter, ((spx_int32_t)jitter->packets[i].timestamp) - ((spx_int32_t)jitter->arrival[i]) - jitter->buffer_margin);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -663,6 +588,8 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int3
|
|||
/* Point to the end of the current packet */
|
||||
jitter->pointer_timestamp = jitter->packets[i].timestamp+jitter->packets[i].span;
|
||||
|
||||
jitter->buffered = *start_offset + packet->span - desired_span;
|
||||
|
||||
if (incomplete)
|
||||
return JITTER_BUFFER_INCOMPLETE;
|
||||
else
|
||||
|
|
@ -676,22 +603,21 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int3
|
|||
jitter->lost_count++;
|
||||
/*fprintf (stderr, "m");*/
|
||||
/*fprintf (stderr, "lost_count = %d\n", jitter->lost_count);*/
|
||||
jitter->loss_rate = .999*jitter->loss_rate + .001;
|
||||
if (start_offset)
|
||||
*start_offset = 0;
|
||||
|
||||
compute_statistics(jitter);
|
||||
opt = compute_opt_delay(jitter);
|
||||
|
||||
/* 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 (opt < 0)
|
||||
{
|
||||
/* Increase buffering */
|
||||
/* Need to increase buffering */
|
||||
|
||||
/* Shift histogram to compensate */
|
||||
shift_histogram(jitter, jitter->res_delay_step);
|
||||
shift_timings(jitter, -opt);
|
||||
|
||||
packet->timestamp = jitter->pointer_timestamp;
|
||||
packet->span = jitter->delay_step;
|
||||
packet->span = -opt;
|
||||
/* Don't move the pointer_timestamp forward */
|
||||
packet->len = 0;
|
||||
|
||||
|
|
@ -700,12 +626,15 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int3
|
|||
} else {
|
||||
/* Normal packet loss */
|
||||
packet->timestamp = jitter->pointer_timestamp;
|
||||
|
||||
desired_span = ROUND_DOWN(desired_span, jitter->concealment_size);
|
||||
packet->span = desired_span;
|
||||
jitter->pointer_timestamp += desired_span;
|
||||
packet->len = 0;
|
||||
/*fprintf (stderr, "Normal loss\n");*/
|
||||
}
|
||||
|
||||
jitter->buffered = packet->span - desired_span;
|
||||
return JITTER_BUFFER_MISSING;
|
||||
|
||||
}
|
||||
|
|
@ -752,43 +681,44 @@ int jitter_buffer_get_pointer_timestamp(JitterBuffer *jitter)
|
|||
|
||||
void jitter_buffer_tick(JitterBuffer *jitter)
|
||||
{
|
||||
if (jitter->buffered >= 0)
|
||||
{
|
||||
jitter->next_stop = jitter->pointer_timestamp - jitter->buffered;
|
||||
} else {
|
||||
jitter->next_stop = jitter->pointer_timestamp;
|
||||
speex_warning_int("jitter buffer sees negative buffering, you code might be broken. Value is ", jitter->buffered);
|
||||
}
|
||||
jitter->buffered = 0;
|
||||
}
|
||||
|
||||
void jitter_buffer_remaining_span(JitterBuffer *jitter, spx_uint32_t rem)
|
||||
{
|
||||
if (jitter->buffered < 0)
|
||||
speex_warning_int("jitter buffer sees negative buffering, you code might be broken. Value is ", jitter->buffered);
|
||||
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 */
|
||||
int jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t *start_offset)
|
||||
{
|
||||
int i;
|
||||
spx_int16_t opt = compute_opt_delay(jitter);
|
||||
/*fprintf(stderr, "opt adjustment is %d ", opt);*/
|
||||
|
||||
compute_statistics(jitter);
|
||||
|
||||
/* Adjusting the buffering bssed on the amount of packets that are early/on time/late */
|
||||
if (jitter->late_ratio_short > .1 || jitter->late_ratio_long > .03)
|
||||
if (opt < 0)
|
||||
{
|
||||
/* If too many packets are arriving late */
|
||||
shift_histogram(jitter, jitter->res_delay_step);
|
||||
shift_timings(jitter, -opt);
|
||||
|
||||
jitter->pointer_timestamp -= jitter->delay_step;
|
||||
jitter->interp_requested = 1;
|
||||
/*fprintf (stderr, "Decision to interpolate\n");*/
|
||||
return JITTER_BUFFER_ADJUST_INTERPOLATE;
|
||||
|
||||
} 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)
|
||||
jitter->pointer_timestamp += opt;
|
||||
jitter->interp_requested = -opt;
|
||||
/*fprintf (stderr, "Decision to interpolate %d samples\n", -opt);*/
|
||||
} else if (opt > 0)
|
||||
{
|
||||
/* Many frames arriving early */
|
||||
shift_histogram(jitter, -jitter->res_delay_step);
|
||||
|
||||
jitter->pointer_timestamp += jitter->delay_step;
|
||||
/*fprintf (stderr, "Decision to drop\n");*/
|
||||
return JITTER_BUFFER_ADJUST_DROP;
|
||||
shift_timings(jitter, -opt);
|
||||
jitter->pointer_timestamp += opt;
|
||||
/*fprintf (stderr, "Decision to drop %d samples\n", opt);*/
|
||||
}
|
||||
|
||||
return JITTER_BUFFER_ADJUST_OK;
|
||||
return opt;
|
||||
}
|
||||
|
||||
/* Used like the ioctl function to control the jitter buffer parameters */
|
||||
|
|
@ -822,11 +752,30 @@ int jitter_buffer_ctl(JitterBuffer *jitter, int request, void *ptr)
|
|||
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;
|
||||
case JITTER_BUFFER_SET_CONCEALMENT_SIZE:
|
||||
jitter->concealment_size = *(spx_int32_t*)ptr;
|
||||
break;
|
||||
case JITTER_BUFFER_GET_CONCEALMENT_SIZE:
|
||||
*(spx_int32_t*)ptr = jitter->concealment_size;
|
||||
break;
|
||||
case JITTER_BUFFER_SET_MAX_LATE_RATE:
|
||||
jitter->max_late_rate = *(spx_int32_t*)ptr;
|
||||
jitter->window_size = 100*TOP_DELAY/jitter->max_late_rate;
|
||||
jitter->subwindow_size = jitter->window_size/MAX_BUFFERS;
|
||||
break;
|
||||
case JITTER_BUFFER_GET_MAX_LATE_RATE:
|
||||
*(spx_int32_t*)ptr = jitter->max_late_rate;
|
||||
break;
|
||||
case JITTER_BUFFER_SET_LATE_COST:
|
||||
jitter->latency_tradeoff = *(spx_int32_t*)ptr;
|
||||
break;
|
||||
case JITTER_BUFFER_GET_LATE_COST:
|
||||
*(spx_int32_t*)ptr = jitter->latency_tradeoff;
|
||||
break;
|
||||
default:
|
||||
speex_warning_int("Unknown jitter_buffer_ctl request: ", request);
|
||||
return -1;
|
||||
|
|
|
|||
|
|
@ -146,7 +146,9 @@ typedef struct SpeexSBMode {
|
|||
int defaultSubmode; /**< Default sub-mode to use when encoding */
|
||||
int low_quality_map[11]; /**< Mode corresponding to each quality setting */
|
||||
int quality_map[11]; /**< Mode corresponding to each quality setting */
|
||||
#ifndef DISABLE_VBR
|
||||
const float (*vbr_thresh)[11];
|
||||
#endif
|
||||
int nb_modes;
|
||||
} SpeexSBMode;
|
||||
|
||||
|
|
|
|||
|
|
@ -241,10 +241,8 @@ static const SpeexSBMode sb_wb_mode = {
|
|||
3,
|
||||
{1, 8, 2, 3, 4, 5, 5, 6, 6, 7, 7},
|
||||
{1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4},
|
||||
#ifndef SPEEX_DISABLE_ENCODER
|
||||
#ifndef DISABLE_VBR
|
||||
vbr_hb_thresh,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
5
|
||||
};
|
||||
|
|
@ -301,10 +299,8 @@ static const SpeexSBMode sb_uwb_mode = {
|
|||
1,
|
||||
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
|
||||
{0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
|
||||
#ifndef SPEEX_DISABLE_ENCODER
|
||||
#ifndef DISABLE_VBR
|
||||
vbr_uhb_thresh,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
2
|
||||
};
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@ const float exc_gain_quant_scal1[2]={0.70469f, 1.05127f};
|
|||
|
||||
extern const spx_word16_t lag_window[];
|
||||
extern const spx_word16_t lpc_window[];
|
||||
|
||||
#ifndef SPEEX_DISABLE_ENCODER
|
||||
void *nb_encoder_init(const SpeexMode *m)
|
||||
{
|
||||
|
|
@ -185,6 +186,7 @@ void *nb_encoder_init(const SpeexMode *m)
|
|||
|
||||
st->pitch = (int*)speex_alloc((st->nbSubframes)*sizeof(int));
|
||||
|
||||
#ifndef DISABLE_VBR
|
||||
st->vbr = (VBRState*)speex_alloc(sizeof(VBRState));
|
||||
vbr_init(st->vbr);
|
||||
st->vbr_quality = 8;
|
||||
|
|
@ -192,13 +194,15 @@ void *nb_encoder_init(const SpeexMode *m)
|
|||
st->vbr_max = 0;
|
||||
st->vad_enabled = 0;
|
||||
st->dtx_enabled = 0;
|
||||
st->dtx_count=0;
|
||||
st->abr_enabled = 0;
|
||||
st->abr_drift = 0;
|
||||
st->abr_drift2 = 0;
|
||||
#endif /* #ifndef DISABLE_VBR */
|
||||
|
||||
st->plc_tuning = 2;
|
||||
st->complexity=2;
|
||||
st->sampling_rate=8000;
|
||||
st->dtx_count=0;
|
||||
st->isWideband = 0;
|
||||
st->highpass_enabled = 1;
|
||||
|
||||
|
|
@ -230,8 +234,10 @@ void nb_encoder_destroy(void *state)
|
|||
speex_free (st->pi_gain);
|
||||
speex_free (st->pitch);
|
||||
|
||||
#ifndef DISABLE_VBR
|
||||
vbr_destroy(st->vbr);
|
||||
speex_free (st->vbr);
|
||||
#endif /* #ifndef DISABLE_VBR */
|
||||
|
||||
#ifdef VORBIS_PSYCHO
|
||||
vorbis_psy_destroy(st->psy);
|
||||
|
|
@ -344,8 +350,11 @@ int nb_encode(void *state, void *vin, SpeexBits *bits)
|
|||
|
||||
|
||||
/*Open-loop pitch*/
|
||||
if (!st->submodes[st->submodeID] || (st->complexity>2 && SUBMODE(have_subframe_gain)<3) || st->vbr_enabled || st->vad_enabled || SUBMODE(forced_pitch_gain) ||
|
||||
SUBMODE(lbr_pitch) != -1)
|
||||
if (!st->submodes[st->submodeID] || (st->complexity>2 && SUBMODE(have_subframe_gain)<3) || SUBMODE(forced_pitch_gain) || SUBMODE(lbr_pitch) != -1
|
||||
#ifndef DISABLE_VBR
|
||||
|| st->vbr_enabled || st->vad_enabled
|
||||
#endif
|
||||
)
|
||||
{
|
||||
int nol_pitch[6];
|
||||
spx_word16_t nol_pitch_coef[6];
|
||||
|
|
@ -418,6 +427,7 @@ int nb_encode(void *state, void *vin, SpeexBits *bits)
|
|||
#endif
|
||||
|
||||
/*VBR stuff*/
|
||||
#ifndef DISABLE_VBR
|
||||
if (st->vbr && (st->vbr_enabled||st->vad_enabled))
|
||||
{
|
||||
float lsp_dist=0;
|
||||
|
|
@ -529,6 +539,7 @@ int nb_encode(void *state, void *vin, SpeexBits *bits)
|
|||
} else {
|
||||
st->relative_quality = -1;
|
||||
}
|
||||
#endif /* #ifndef DISABLE_VBR */
|
||||
|
||||
if (st->encode_submode)
|
||||
{
|
||||
|
|
@ -694,8 +705,7 @@ int nb_encode(void *state, void *vin, SpeexBits *bits)
|
|||
bw_lpc(st->gamma2, interp_lpc, bw_lpc2, st->lpcSize);
|
||||
else
|
||||
{
|
||||
bw_lpc2[0]=1;
|
||||
for (i=1;i<=st->lpcSize;i++)
|
||||
for (i=0;i<st->lpcSize;i++)
|
||||
bw_lpc2[i]=0;
|
||||
}
|
||||
/*print_vec(st->bw_lpc1, 10, "bw_lpc");*/
|
||||
|
|
@ -907,9 +917,11 @@ int nb_encode(void *state, void *vin, SpeexBits *bits)
|
|||
|
||||
if (st->submodeID==1)
|
||||
{
|
||||
#ifndef DISABLE_VBR
|
||||
if (st->dtx_count)
|
||||
speex_bits_pack(bits, 15, 4);
|
||||
else
|
||||
#endif
|
||||
speex_bits_pack(bits, 0, 4);
|
||||
}
|
||||
|
||||
|
|
@ -1615,6 +1627,7 @@ int nb_encoder_ctl(void *state, int request, void *ptr)
|
|||
case SPEEX_GET_MODE:
|
||||
(*(spx_int32_t*)ptr) = st->submodeID;
|
||||
break;
|
||||
#ifndef DISABLE_VBR
|
||||
case SPEEX_SET_VBR:
|
||||
st->vbr_enabled = (*(spx_int32_t*)ptr);
|
||||
break;
|
||||
|
|
@ -1663,12 +1676,15 @@ int nb_encoder_ctl(void *state, int request, void *ptr)
|
|||
case SPEEX_GET_ABR:
|
||||
(*(spx_int32_t*)ptr) = st->abr_enabled;
|
||||
break;
|
||||
#endif /* #ifndef DISABLE_VBR */
|
||||
#if !defined(DISABLE_VBR) && !defined(DISABLE_FLOAT_API)
|
||||
case SPEEX_SET_VBR_QUALITY:
|
||||
st->vbr_quality = (*(float*)ptr);
|
||||
break;
|
||||
case SPEEX_GET_VBR_QUALITY:
|
||||
(*(float*)ptr) = st->vbr_quality;
|
||||
break;
|
||||
#endif /* !defined(DISABLE_VBR) && !defined(DISABLE_FLOAT_API) */
|
||||
case SPEEX_SET_QUALITY:
|
||||
{
|
||||
int quality = (*(spx_int32_t*)ptr);
|
||||
|
|
@ -1746,12 +1762,14 @@ int nb_encoder_ctl(void *state, int request, void *ptr)
|
|||
case SPEEX_GET_PLC_TUNING:
|
||||
(*(spx_int32_t*)ptr)=(st->plc_tuning);
|
||||
break;
|
||||
#ifndef DISABLE_VBR
|
||||
case SPEEX_SET_VBR_MAX_BITRATE:
|
||||
st->vbr_max = (*(spx_int32_t*)ptr);
|
||||
break;
|
||||
case SPEEX_GET_VBR_MAX_BITRATE:
|
||||
(*(spx_int32_t*)ptr) = st->vbr_max;
|
||||
break;
|
||||
#endif /* #ifndef DISABLE_VBR */
|
||||
case SPEEX_SET_HIGHPASS:
|
||||
st->highpass_enabled = (*(spx_int32_t*)ptr);
|
||||
break;
|
||||
|
|
@ -1775,9 +1793,11 @@ int nb_encoder_ctl(void *state, int request, void *ptr)
|
|||
((spx_word16_t*)ptr)[i] = compute_rms16(st->exc+i*st->subframeSize, st->subframeSize);
|
||||
}
|
||||
break;
|
||||
#ifndef DISABLE_VBR
|
||||
case SPEEX_GET_RELATIVE_QUALITY:
|
||||
(*(float*)ptr)=st->relative_quality;
|
||||
break;
|
||||
#endif /* #ifndef DISABLE_VBR */
|
||||
case SPEEX_SET_INNOVATION_SAVE:
|
||||
st->innov_rms_save = (spx_word16_t*)ptr;
|
||||
break;
|
||||
|
|
@ -1870,10 +1890,10 @@ int nb_decoder_ctl(void *state, int request, void *ptr)
|
|||
case SPEEX_GET_HIGHPASS:
|
||||
(*(spx_int32_t*)ptr) = st->highpass_enabled;
|
||||
break;
|
||||
/* FIXME: Convert to fixed-point and re-enable even when float API is disabled */
|
||||
#ifndef DISABLE_FLOAT_API
|
||||
case SPEEX_GET_ACTIVITY:
|
||||
{
|
||||
/* We don't use this, dummy it out to get rid of the float stuff */
|
||||
#if 0
|
||||
float ret;
|
||||
ret = log(st->level/st->min_level)/log(st->max_level/st->min_level);
|
||||
if (ret>1)
|
||||
|
|
@ -1883,11 +1903,9 @@ int nb_decoder_ctl(void *state, int request, void *ptr)
|
|||
ret = 0;
|
||||
/*printf ("%f %f %f %f\n", st->level, st->min_level, st->max_level, ret);*/
|
||||
(*(spx_int32_t*)ptr) = (int)(100*ret);
|
||||
#else
|
||||
(*(spx_int32_t*)ptr) = (int)(0);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case SPEEX_GET_PI_GAIN:
|
||||
{
|
||||
int i;
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ typedef struct EncState {
|
|||
spx_word32_t *pi_gain; /**< Gain of LPC filter at theta=pi (fe/2) */
|
||||
spx_word16_t *innov_rms_save; /**< If non-NULL, innovation RMS is copied here */
|
||||
|
||||
#ifndef DISABLE_VBR
|
||||
VBRState *vbr; /**< State of the VBR data */
|
||||
float vbr_quality; /**< Quality setting for VBR encoding */
|
||||
float relative_quality; /**< Relative quality that will be needed by VBR */
|
||||
|
|
@ -105,6 +106,8 @@ typedef struct EncState {
|
|||
float abr_drift;
|
||||
float abr_drift2;
|
||||
float abr_count;
|
||||
#endif /* #ifndef DISABLE_VBR */
|
||||
|
||||
int complexity; /**< Complexity setting (0-10 from least complex to most complex) */
|
||||
spx_int32_t sampling_rate;
|
||||
int plc_tuning;
|
||||
|
|
|
|||
|
|
@ -277,7 +277,7 @@ static void conj_window(spx_word16_t *w, int len)
|
|||
x=QCONST16(2.f,13)-x+QCONST16(2.f,13); /* 4 - x */
|
||||
}
|
||||
x = MULT16_16_Q14(QCONST16(1.271903f,14), x);
|
||||
tmp = SQR16_Q15(QCONST16(.5f,15)-MULT16_16_P15(QCONST16(.5f,15),spx_cos_norm(QCONST32(x,2))));
|
||||
tmp = SQR16_Q15(QCONST16(.5f,15)-MULT16_16_P15(QCONST16(.5f,15),spx_cos_norm(SHL32(EXTEND32(x),2))));
|
||||
if (inv)
|
||||
tmp=SUB16(Q15_ONE,tmp);
|
||||
w[i]=spx_sqrt(SHL32(EXTEND32(tmp),15));
|
||||
|
|
@ -1065,7 +1065,7 @@ int speex_preprocess_ctl(SpeexPreprocessState *state, int request, void *ptr)
|
|||
case SPEEX_PREPROCESS_GET_AGC:
|
||||
(*(spx_int32_t*)ptr) = st->agc_enabled;
|
||||
break;
|
||||
|
||||
#ifndef DISABLE_FLOAT_API
|
||||
case SPEEX_PREPROCESS_SET_AGC_LEVEL:
|
||||
st->agc_level = (*(float*)ptr);
|
||||
if (st->agc_level<1)
|
||||
|
|
@ -1076,6 +1076,7 @@ int speex_preprocess_ctl(SpeexPreprocessState *state, int request, void *ptr)
|
|||
case SPEEX_PREPROCESS_GET_AGC_LEVEL:
|
||||
(*(float*)ptr) = st->agc_level;
|
||||
break;
|
||||
#endif /* #ifndef DISABLE_FLOAT_API */
|
||||
case SPEEX_PREPROCESS_SET_AGC_INCREMENT:
|
||||
st->max_increase_step = exp(0.11513f * (*(spx_int32_t*)ptr)*st->frame_size / st->sampling_rate);
|
||||
break;
|
||||
|
|
@ -1113,17 +1114,21 @@ int speex_preprocess_ctl(SpeexPreprocessState *state, int request, void *ptr)
|
|||
break;
|
||||
|
||||
case SPEEX_PREPROCESS_SET_DEREVERB_LEVEL:
|
||||
st->reverb_level = (*(float*)ptr);
|
||||
/* FIXME: Re-enable when de-reverberation is actually enabled again */
|
||||
/*st->reverb_level = (*(float*)ptr);*/
|
||||
break;
|
||||
case SPEEX_PREPROCESS_GET_DEREVERB_LEVEL:
|
||||
(*(float*)ptr) = st->reverb_level;
|
||||
/* FIXME: Re-enable when de-reverberation is actually enabled again */
|
||||
/*(*(float*)ptr) = st->reverb_level;*/
|
||||
break;
|
||||
|
||||
case SPEEX_PREPROCESS_SET_DEREVERB_DECAY:
|
||||
st->reverb_decay = (*(float*)ptr);
|
||||
/* FIXME: Re-enable when de-reverberation is actually enabled again */
|
||||
/*st->reverb_decay = (*(float*)ptr);*/
|
||||
break;
|
||||
case SPEEX_PREPROCESS_GET_DEREVERB_DECAY:
|
||||
(*(float*)ptr) = st->reverb_decay;
|
||||
/* FIXME: Re-enable when de-reverberation is actually enabled again */
|
||||
/*(*(float*)ptr) = st->reverb_decay;*/
|
||||
break;
|
||||
|
||||
case SPEEX_PREPROCESS_SET_PROB_START:
|
||||
|
|
|
|||
|
|
@ -389,4 +389,3 @@ void lsp_unquant_high(spx_lsp_t *lsp, int order, SpeexBits *bits)
|
|||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -253,6 +253,7 @@ void *sb_encoder_init(const SpeexMode *m)
|
|||
for (i=0;i<st->lpcSize;i++)
|
||||
st->old_lsp[i]= DIV32(MULT16_16(QCONST16(3.1415927f, LSP_SHIFT), i+1), st->lpcSize+1);
|
||||
|
||||
#ifndef DISABLE_VBR
|
||||
st->vbr_quality = 8;
|
||||
st->vbr_enabled = 0;
|
||||
st->vbr_max = 0;
|
||||
|
|
@ -260,6 +261,7 @@ void *sb_encoder_init(const SpeexMode *m)
|
|||
st->vad_enabled = 0;
|
||||
st->abr_enabled = 0;
|
||||
st->relative_quality=0;
|
||||
#endif /* #ifndef DISABLE_VBR */
|
||||
|
||||
st->complexity=2;
|
||||
speex_encoder_ctl(st->st_low, SPEEX_GET_SAMPLING_RATE, &st->sampling_rate);
|
||||
|
|
@ -336,6 +338,7 @@ int sb_encode(void *state, void *vin, SpeexBits *bits)
|
|||
/* Compute the two sub-bands by filtering with QMF h0*/
|
||||
qmf_decomp(in, h0, low, high, st->full_frame_size, QMF_ORDER, st->h0_mem, stack);
|
||||
|
||||
#ifndef DISABLE_VBR
|
||||
if (st->vbr_enabled || st->vad_enabled)
|
||||
{
|
||||
/* Need to compute things here before the signal is trashed by the encoder */
|
||||
|
|
@ -343,6 +346,8 @@ int sb_encode(void *state, void *vin, SpeexBits *bits)
|
|||
e_low = compute_rms16(low, st->frame_size);
|
||||
e_high = compute_rms16(high, st->frame_size);
|
||||
}
|
||||
#endif /* #ifndef DISABLE_VBR */
|
||||
|
||||
ALLOC(low_innov_rms, st->nbSubframes, spx_word16_t);
|
||||
speex_encoder_ctl(st->st_low, SPEEX_SET_INNOVATION_SAVE, low_innov_rms);
|
||||
/* Encode the narrowband part*/
|
||||
|
|
@ -418,6 +423,7 @@ int sb_encode(void *state, void *vin, SpeexBits *bits)
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef DISABLE_VBR
|
||||
/* VBR code */
|
||||
if ((st->vbr_enabled || st->vad_enabled) && !dtx)
|
||||
{
|
||||
|
|
@ -494,6 +500,7 @@ int sb_encode(void *state, void *vin, SpeexBits *bits)
|
|||
}
|
||||
/*fprintf (stderr, "%f %f\n", ratio, low_qual);*/
|
||||
}
|
||||
#endif /* #ifndef DISABLE_VBR */
|
||||
|
||||
if (st->encode_submode)
|
||||
{
|
||||
|
|
@ -1146,6 +1153,7 @@ int sb_encoder_ctl(void *state, int request, void *ptr)
|
|||
case SPEEX_SET_MODE:
|
||||
speex_encoder_ctl(st, SPEEX_SET_QUALITY, ptr);
|
||||
break;
|
||||
#ifndef DISABLE_VBR
|
||||
case SPEEX_SET_VBR:
|
||||
st->vbr_enabled = (*(spx_int32_t*)ptr);
|
||||
speex_encoder_ctl(st->st_low, SPEEX_SET_VBR, ptr);
|
||||
|
|
@ -1160,6 +1168,8 @@ int sb_encoder_ctl(void *state, int request, void *ptr)
|
|||
case SPEEX_GET_VAD:
|
||||
(*(spx_int32_t*)ptr) = st->vad_enabled;
|
||||
break;
|
||||
#endif /* #ifndef DISABLE_VBR */
|
||||
#if !defined(DISABLE_VBR) && !defined(DISABLE_FLOAT_API)
|
||||
case SPEEX_SET_VBR_QUALITY:
|
||||
{
|
||||
spx_int32_t q;
|
||||
|
|
@ -1177,6 +1187,8 @@ int sb_encoder_ctl(void *state, int request, void *ptr)
|
|||
case SPEEX_GET_VBR_QUALITY:
|
||||
(*(float*)ptr) = st->vbr_quality;
|
||||
break;
|
||||
#endif /* #if !defined(DISABLE_VBR) && !defined(DISABLE_FLOAT_API) */
|
||||
#ifndef DISABLE_VBR
|
||||
case SPEEX_SET_ABR:
|
||||
st->abr_enabled = (*(spx_int32_t*)ptr);
|
||||
st->vbr_enabled = st->abr_enabled!=0;
|
||||
|
|
@ -1207,6 +1219,8 @@ int sb_encoder_ctl(void *state, int request, void *ptr)
|
|||
case SPEEX_GET_ABR:
|
||||
(*(spx_int32_t*)ptr) = st->abr_enabled;
|
||||
break;
|
||||
#endif /* #ifndef DISABLE_VBR */
|
||||
|
||||
case SPEEX_SET_QUALITY:
|
||||
{
|
||||
spx_int32_t nb_qual;
|
||||
|
|
@ -1293,6 +1307,7 @@ int sb_encoder_ctl(void *state, int request, void *ptr)
|
|||
case SPEEX_GET_PLC_TUNING:
|
||||
speex_encoder_ctl(st->st_low, SPEEX_GET_PLC_TUNING, ptr);
|
||||
break;
|
||||
#ifndef DISABLE_VBR
|
||||
case SPEEX_SET_VBR_MAX_BITRATE:
|
||||
{
|
||||
st->vbr_max = (*(spx_int32_t*)ptr);
|
||||
|
|
@ -1324,6 +1339,7 @@ int sb_encoder_ctl(void *state, int request, void *ptr)
|
|||
case SPEEX_GET_VBR_MAX_BITRATE:
|
||||
(*(spx_int32_t*)ptr) = st->vbr_max;
|
||||
break;
|
||||
#endif /* #ifndef DISABLE_VBR */
|
||||
case SPEEX_SET_HIGHPASS:
|
||||
speex_encoder_ctl(st->st_low, SPEEX_SET_HIGHPASS, ptr);
|
||||
break;
|
||||
|
|
@ -1348,9 +1364,11 @@ int sb_encoder_ctl(void *state, int request, void *ptr)
|
|||
((spx_word16_t*)ptr)[i] = st->exc_rms[i];
|
||||
}
|
||||
break;
|
||||
#ifndef DISABLE_VBR
|
||||
case SPEEX_GET_RELATIVE_QUALITY:
|
||||
(*(float*)ptr)=st->relative_quality;
|
||||
break;
|
||||
#endif /* #ifndef DISABLE_VBR */
|
||||
case SPEEX_SET_INNOVATION_SAVE:
|
||||
st->innov_rms_save = (spx_word16_t*)ptr;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ typedef struct SBEncState {
|
|||
spx_word16_t *exc_rms;
|
||||
spx_word16_t *innov_rms_save; /**< If non-NULL, innovation is copied here */
|
||||
|
||||
#ifndef DISABLE_VBR
|
||||
float vbr_quality; /**< Quality setting for VBR encoding */
|
||||
int vbr_enabled; /**< 1 for enabling VBR, 0 otherwise */
|
||||
spx_int32_t vbr_max; /**< Max bit-rate allowed in VBR mode (total) */
|
||||
|
|
@ -82,6 +83,7 @@ typedef struct SBEncState {
|
|||
float abr_count;
|
||||
int vad_enabled; /**< 1 for enabling VAD, 0 otherwise */
|
||||
float relative_quality;
|
||||
#endif /* #ifndef DISABLE_VBR */
|
||||
|
||||
int encode_submode;
|
||||
const SpeexSubmode * const *submodes;
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ int speex_decode_native(void *state, SpeexBits *bits, spx_word16_t *out)
|
|||
#ifdef FIXED_POINT
|
||||
|
||||
#ifndef SPEEX_DISABLE_ENCODER
|
||||
#ifndef DISABLE_FLOAT_API
|
||||
int speex_encode(void *state, float *in, SpeexBits *bits)
|
||||
{
|
||||
int i;
|
||||
|
|
@ -102,6 +103,7 @@ int speex_encode(void *state, float *in, SpeexBits *bits)
|
|||
}
|
||||
return (*((SpeexMode**)state))->enc(state, short_in, bits);
|
||||
}
|
||||
#endif /* #ifndef DISABLE_FLOAT_API */
|
||||
|
||||
int speex_encode_int(void *state, spx_int16_t *in, SpeexBits *bits)
|
||||
{
|
||||
|
|
@ -111,7 +113,7 @@ int speex_encode_int(void *state, spx_int16_t *in, SpeexBits *bits)
|
|||
}
|
||||
#endif /* SPEEX_DISABLE_ENCODER */
|
||||
|
||||
#if 0
|
||||
#ifndef DISABLE_FLOAT_API
|
||||
int speex_decode(void *state, SpeexBits *bits, float *out)
|
||||
{
|
||||
int i, ret;
|
||||
|
|
@ -123,7 +125,7 @@ int speex_decode(void *state, SpeexBits *bits, float *out)
|
|||
out[i] = short_out[i];
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
#endif /* #ifndef DISABLE_FLOAT_API */
|
||||
|
||||
int speex_decode_int(void *state, SpeexBits *bits, spx_int16_t *out)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -212,11 +212,6 @@ extern "C" {
|
|||
/** modeID for the defined ultra-wideband mode */
|
||||
#define SPEEX_MODEID_UWB 2
|
||||
|
||||
#ifdef EPIC_48K
|
||||
/** modeID for the Epic 48K mode */
|
||||
#define SPEEX_MODEID_NB_48K 1000
|
||||
#endif
|
||||
|
||||
struct SpeexMode;
|
||||
|
||||
|
||||
|
|
@ -410,19 +405,16 @@ extern const SpeexMode speex_wb_mode;
|
|||
/** Default "ultra-wideband" mode */
|
||||
extern const SpeexMode speex_uwb_mode;
|
||||
|
||||
#ifdef EPIC_48K
|
||||
/** 4.8 kbps narrowband mode */
|
||||
extern const SpeexMode speex_nb_48k_mode;
|
||||
#endif
|
||||
|
||||
/** List of all modes available */
|
||||
extern const SpeexMode * const speex_mode_list[SPEEX_NB_MODES];
|
||||
|
||||
/** Obtain one of the modes available */
|
||||
const SpeexMode * speex_lib_get_mode (int mode);
|
||||
|
||||
/* We actually override the fucntion in the narrowband case so that we can avoid linking in the wideband stuff */
|
||||
#ifndef WIN32
|
||||
/* We actually override the function in the narrowband case so that we can avoid linking in the wideband stuff */
|
||||
#define speex_lib_get_mode(mode) ((mode)==SPEEX_MODEID_NB ? &speex_nb_mode : speex_lib_get_mode (mode))
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,6 +62,8 @@ struct _JitterBufferPacket {
|
|||
spx_uint32_t len; /**< Length of the packet in bytes */
|
||||
spx_uint32_t timestamp; /**< Timestamp for the packet */
|
||||
spx_uint32_t span; /**< Time covered by the packet (same units as timestamp) */
|
||||
spx_uint16_t sequence; /**< RTP Sequence number if available (0 otherwise) */
|
||||
spx_uint16_t flags; /**< Info about the returned packet */
|
||||
spx_uint32_t user_data; /**< Put whatever data you like here (it's ignored by the jitter buffer) */
|
||||
};
|
||||
|
||||
|
|
@ -88,27 +90,37 @@ struct _JitterBufferPacket {
|
|||
/** Included because of an early misspelling (will remove in next release) */
|
||||
#define JITTER_BUFFER_GET_AVALIABLE_COUNT 3
|
||||
|
||||
/** */
|
||||
/** Assign a function to destroy unused packet. When setting that, the jitter
|
||||
buffer no longer copies packet data. */
|
||||
#define JITTER_BUFFER_SET_DESTROY_CALLBACK 4
|
||||
/** */
|
||||
#define JITTER_BUFFER_GET_DESTROY_CALLBACK 5
|
||||
|
||||
/** */
|
||||
/** Tell the jitter buffer to only adjust the delay in multiples of the step parameter provided */
|
||||
#define JITTER_BUFFER_SET_DELAY_STEP 6
|
||||
/** */
|
||||
#define JITTER_BUFFER_GET_DELAY_STEP 7
|
||||
|
||||
/** Tell the jitter buffer to only do concealment in multiples of the size parameter provided */
|
||||
#define JITTER_BUFFER_SET_CONCEALMENT_SIZE 8
|
||||
#define JITTER_BUFFER_GET_CONCEALMENT_SIZE 9
|
||||
|
||||
/** Absolute max amount of loss that can be tolerated regardless of the delay. Typical loss
|
||||
should be half of that or less. */
|
||||
#define JITTER_BUFFER_SET_MAX_LATE_RATE 10
|
||||
#define JITTER_BUFFER_GET_MAX_LATE_RATE 11
|
||||
|
||||
/** Equivalent cost of one percent late packet in timestamp units */
|
||||
#define JITTER_BUFFER_SET_LATE_COST 12
|
||||
#define JITTER_BUFFER_GET_LATE_COST 13
|
||||
|
||||
#define JITTER_BUFFER_ADJUST_INTERPOLATE -1
|
||||
#define JITTER_BUFFER_ADJUST_OK 0
|
||||
#define JITTER_BUFFER_ADJUST_DROP 1
|
||||
|
||||
/** Initialises jitter buffer
|
||||
*
|
||||
* @param tick Number of samples per "tick", i.e. the time period of the elements that will be retrieved
|
||||
* @return Newly created jitter buffer state
|
||||
*/
|
||||
JitterBuffer *jitter_buffer_init(int tick);
|
||||
JitterBuffer *jitter_buffer_init(void);
|
||||
|
||||
/** Restores jitter buffer to its original state
|
||||
*
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@ int speex_std_high_mode_request_handler(SpeexBits *bits, void *state, void *data
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_VBR
|
||||
int speex_std_vbr_request_handler(SpeexBits *bits, void *state, void *data)
|
||||
{
|
||||
spx_int32_t vbr;
|
||||
|
|
@ -103,6 +104,7 @@ int speex_std_vbr_request_handler(SpeexBits *bits, void *state, void *data)
|
|||
speex_encoder_ctl(data, SPEEX_SET_VBR, &vbr);
|
||||
return 0;
|
||||
}
|
||||
#endif /* #ifndef DISABLE_VBR */
|
||||
|
||||
int speex_std_enh_request_handler(SpeexBits *bits, void *state, void *data)
|
||||
{
|
||||
|
|
@ -112,17 +114,15 @@ int speex_std_enh_request_handler(SpeexBits *bits, void *state, void *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_VBR
|
||||
int speex_std_vbr_quality_request_handler(SpeexBits *bits, void *state, void *data)
|
||||
{
|
||||
/* We don't use this, get rid of the float reference */
|
||||
#if 0
|
||||
float qual;
|
||||
qual = speex_bits_unpack_unsigned(bits, 4);
|
||||
speex_encoder_ctl(data, SPEEX_SET_VBR_QUALITY, &qual);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* #ifndef DISABLE_VBR */
|
||||
|
||||
int speex_std_char_handler(SpeexBits *bits, void *state, void *data)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -57,6 +57,10 @@ static const float e_ratio_quant_bounds[3] = {0.2825f, 0.356f, 0.4485f};
|
|||
#else
|
||||
static const spx_word16_t e_ratio_quant[4] = {8192, 10332, 13009, 16384};
|
||||
static const spx_word16_t e_ratio_quant_bounds[3] = {9257, 11665, 14696};
|
||||
static const spx_word16_t balance_bounds[31] = {18, 23, 30, 38, 49, 63, 81, 104,
|
||||
134, 172, 221, 284, 364, 468, 600, 771,
|
||||
990, 1271, 1632, 2096, 2691, 3455, 4436, 5696,
|
||||
7314, 9392, 12059, 15484, 19882, 25529, 32766};
|
||||
#endif
|
||||
|
||||
/* This is an ugly compatibility hack that properly resets the stereo state
|
||||
|
|
@ -104,6 +108,7 @@ void speex_stereo_state_destroy(SpeexStereoState *stereo)
|
|||
}
|
||||
|
||||
#ifndef SPEEX_DISABLE_ENCODER
|
||||
#ifndef DISABLE_FLOAT_API
|
||||
void speex_encode_stereo(float *data, int frame_size, SpeexBits *bits)
|
||||
{
|
||||
int i, tmp;
|
||||
|
|
@ -137,50 +142,87 @@ void speex_encode_stereo(float *data, int frame_size, SpeexBits *bits)
|
|||
speex_bits_pack(bits, (int)balance, 5);
|
||||
|
||||
/* FIXME: this is a hack */
|
||||
tmp=scal_quant(e_ratio*Q15_ONE, e_ratio_quant_bounds, 3);
|
||||
tmp=scal_quant(e_ratio*Q15_ONE, e_ratio_quant_bounds, 4);
|
||||
speex_bits_pack(bits, tmp, 2);
|
||||
}
|
||||
#endif /* #ifndef DISABLE_FLOAT_API */
|
||||
|
||||
void speex_encode_stereo_int(spx_int16_t *data, int frame_size, SpeexBits *bits)
|
||||
{
|
||||
int i, tmp;
|
||||
float e_left=0, e_right=0, e_tot=0;
|
||||
float balance, e_ratio;
|
||||
for (i=0;i<frame_size;i++)
|
||||
{
|
||||
e_left += ((float)data[2*i])*data[2*i];
|
||||
e_right += ((float)data[2*i+1])*data[2*i+1];
|
||||
data[i] = .5*(((float)data[2*i])+data[2*i+1]);
|
||||
e_tot += ((float)data[i])*data[i];
|
||||
}
|
||||
balance=(e_left+1)/(e_right+1);
|
||||
e_ratio = e_tot/(1+e_left+e_right);
|
||||
spx_word32_t e_left=0, e_right=0, e_tot=0;
|
||||
spx_word32_t balance, e_ratio;
|
||||
spx_word32_t largest, smallest;
|
||||
int balance_id;
|
||||
#ifdef FIXED_POINT
|
||||
int shift;
|
||||
#endif
|
||||
|
||||
/*Quantization*/
|
||||
/* In band marker */
|
||||
speex_bits_pack(bits, 14, 5);
|
||||
/* Stereo marker */
|
||||
speex_bits_pack(bits, SPEEX_INBAND_STEREO, 4);
|
||||
|
||||
balance=4*log(balance);
|
||||
|
||||
/*Pack sign*/
|
||||
if (balance>0)
|
||||
for (i=0;i<frame_size;i++)
|
||||
{
|
||||
e_left += SHR32(MULT16_16(data[2*i],data[2*i]),8);
|
||||
e_right += SHR32(MULT16_16(data[2*i+1],data[2*i+1]),8);
|
||||
#ifdef FIXED_POINT
|
||||
/* I think this is actually unbiased */
|
||||
data[i] = SHR16(data[2*i],1)+PSHR16(data[2*i+1],1);
|
||||
#else
|
||||
data[i] = .5*(((float)data[2*i])+data[2*i+1]);
|
||||
#endif
|
||||
e_tot += SHR32(MULT16_16(data[i],data[i]),8);
|
||||
}
|
||||
if (e_left > e_right)
|
||||
{
|
||||
speex_bits_pack(bits, 0, 1);
|
||||
else
|
||||
largest = e_left;
|
||||
smallest = e_right;
|
||||
} else {
|
||||
speex_bits_pack(bits, 1, 1);
|
||||
balance=floor(.5+fabs(balance));
|
||||
if (balance>30)
|
||||
balance=31;
|
||||
largest = e_right;
|
||||
smallest = e_left;
|
||||
}
|
||||
|
||||
speex_bits_pack(bits, (int)balance, 5);
|
||||
/* Balance quantization */
|
||||
#ifdef FIXED_POINT
|
||||
shift = spx_ilog2(largest)-15;
|
||||
largest = VSHR32(largest, shift-4);
|
||||
smallest = VSHR32(smallest, shift);
|
||||
balance = DIV32(largest, ADD32(smallest, 1));
|
||||
if (balance > 32767)
|
||||
balance = 32767;
|
||||
balance_id = scal_quant(EXTRACT16(balance), balance_bounds, 32);
|
||||
#else
|
||||
balance=(largest+1.)/(smallest+1.);
|
||||
balance=4*log(balance);
|
||||
balance_id=floor(.5+fabs(balance));
|
||||
if (balance_id>30)
|
||||
balance_id=31;
|
||||
#endif
|
||||
|
||||
/* FIXME: this is a hack */
|
||||
tmp=scal_quant(e_ratio*Q15_ONE, e_ratio_quant_bounds, 3);
|
||||
speex_bits_pack(bits, balance_id, 5);
|
||||
|
||||
/* "coherence" quantisation */
|
||||
#ifdef FIXED_POINT
|
||||
shift = spx_ilog2(e_tot);
|
||||
e_tot = VSHR32(e_tot, shift-25);
|
||||
e_left = VSHR32(e_left, shift-10);
|
||||
e_right = VSHR32(e_right, shift-10);
|
||||
e_ratio = DIV32(e_tot, e_left+e_right+1);
|
||||
#else
|
||||
e_ratio = e_tot/(1.+e_left+e_right);
|
||||
#endif
|
||||
|
||||
tmp=scal_quant(EXTRACT16(e_ratio), e_ratio_quant_bounds, 4);
|
||||
/*fprintf (stderr, "%d %d %d %d\n", largest, smallest, balance_id, e_ratio);*/
|
||||
speex_bits_pack(bits, tmp, 2);
|
||||
}
|
||||
#endif /* SPEEX_DISABLE_ENCODER */
|
||||
|
||||
/* We don't want to decode to floats yet, disable */
|
||||
#if 0
|
||||
#ifndef DISABLE_FLOAT_API
|
||||
void speex_decode_stereo(float *data, int frame_size, SpeexStereoState *_stereo)
|
||||
{
|
||||
int i;
|
||||
|
|
@ -206,7 +248,7 @@ void speex_decode_stereo(float *data, int frame_size, SpeexStereoState *_stereo)
|
|||
data[2*i+1] = (float)MULT16_16_P14(stereo->smooth_right, tmp);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif /* #ifndef DISABLE_FLOAT_API */
|
||||
|
||||
void speex_decode_stereo_int(spx_int16_t *data, int frame_size, SpeexStereoState *_stereo)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@
|
|||
#define MIN_ENERGY 6000
|
||||
#define NOISE_POW .3
|
||||
|
||||
#ifndef DISABLE_VBR
|
||||
|
||||
const float vbr_nb_thresh[9][11]={
|
||||
{-1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f}, /* CNG */
|
||||
|
|
@ -270,3 +271,5 @@ float vbr_analysis(VBRState *vbr, spx_word16_t *sig, int len, int pitch, float p
|
|||
void vbr_destroy(VBRState *vbr)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* #ifndef DISABLE_VBR */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue