diff options
author | Thom Johansen <thomj@rockbox.org> | 2007-11-22 01:29:14 +0000 |
---|---|---|
committer | Thom Johansen <thomj@rockbox.org> | 2007-11-22 01:29:14 +0000 |
commit | 57a27c69a9f3b9b69aff9360c09f7298ffd7b670 (patch) | |
tree | 252dcf43c2ed5058047d1aac98c00ff24e97f067 /apps | |
parent | 14ac7cafc81940f5f389515cb5134e6c52f37813 (diff) | |
download | rockbox-57a27c69a9f3b9b69aff9360c09f7298ffd7b670.tar.gz rockbox-57a27c69a9f3b9b69aff9360c09f7298ffd7b670.zip |
Sync Speex to SVN.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15750 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r-- | apps/codecs/libspeex/config-speex.h | 4 | ||||
-rw-r--r-- | apps/codecs/libspeex/jitter.c | 423 | ||||
-rw-r--r-- | apps/codecs/libspeex/modes.h | 2 | ||||
-rw-r--r-- | apps/codecs/libspeex/modes_wb.c | 36 | ||||
-rw-r--r-- | apps/codecs/libspeex/nb_celp.c | 40 | ||||
-rw-r--r-- | apps/codecs/libspeex/nb_celp.h | 5 | ||||
-rw-r--r-- | apps/codecs/libspeex/preprocess.c | 17 | ||||
-rw-r--r-- | apps/codecs/libspeex/quant_lsp.c | 1 | ||||
-rw-r--r-- | apps/codecs/libspeex/sb_celp.c | 18 | ||||
-rw-r--r-- | apps/codecs/libspeex/sb_celp.h | 4 | ||||
-rw-r--r-- | apps/codecs/libspeex/speex.c | 6 | ||||
-rw-r--r-- | apps/codecs/libspeex/speex/speex.h | 14 | ||||
-rw-r--r-- | apps/codecs/libspeex/speex/speex_jitter.h | 24 | ||||
-rw-r--r-- | apps/codecs/libspeex/speex_callbacks.c | 8 | ||||
-rw-r--r-- | apps/codecs/libspeex/speex_header.c | 2 | ||||
-rw-r--r-- | apps/codecs/libspeex/stereo.c | 96 | ||||
-rw-r--r-- | apps/codecs/libspeex/vbr.c | 3 |
17 files changed, 375 insertions, 328 deletions
diff --git a/apps/codecs/libspeex/config-speex.h b/apps/codecs/libspeex/config-speex.h index 70d86f6299..db15948330 100644 --- a/apps/codecs/libspeex/config-speex.h +++ b/apps/codecs/libspeex/config-speex.h @@ -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 diff --git a/apps/codecs/libspeex/jitter.c b/apps/codecs/libspeex/jitter.c index e31a131bba..710e36272c 100644 --- a/apps/codecs/libspeex/jitter.c +++ b/apps/codecs/libspeex/jitter.c @@ -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; + + 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, "tbs_get_opt_delay\n");*/ + /*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) { - jitter->next_stop = jitter->pointer_timestamp; + 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; diff --git a/apps/codecs/libspeex/modes.h b/apps/codecs/libspeex/modes.h index d0ff842ffa..26e2d86180 100644 --- a/apps/codecs/libspeex/modes.h +++ b/apps/codecs/libspeex/modes.h @@ -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; diff --git a/apps/codecs/libspeex/modes_wb.c b/apps/codecs/libspeex/modes_wb.c index 8e351db60d..7fac15b852 100644 --- a/apps/codecs/libspeex/modes_wb.c +++ b/apps/codecs/libspeex/modes_wb.c @@ -236,17 +236,15 @@ static const SpeexSBMode sb_wb_mode = { 0.9, 0.6, /* gamma1, gamma2 */ #endif QCONST16(.0002,15), /*lpc_floor*/ - QCONST16(0.9f,15), - {NULL, &wb_submode1, &wb_submode2, &wb_submode3, &wb_submode4, NULL, NULL, NULL}, - 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 - vbr_hb_thresh, -#else - NULL, + QCONST16(0.9f,15), + {NULL, &wb_submode1, &wb_submode2, &wb_submode3, &wb_submode4, NULL, NULL, NULL}, + 3, + {1, 8, 2, 3, 4, 5, 5, 6, 6, 7, 7}, + {1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4}, +#ifndef DISABLE_VBR + vbr_hb_thresh, #endif - 5 + 5 }; @@ -296,17 +294,15 @@ static const SpeexSBMode sb_uwb_mode = { 0.9, 0.6, /* gamma1, gamma2 */ #endif QCONST16(.0002,15), /*lpc_floor*/ - QCONST16(0.7f,15), - {NULL, &wb_submode1, NULL, NULL, NULL, NULL, NULL, NULL}, - 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 - vbr_uhb_thresh, -#else - NULL, + QCONST16(0.7f,15), + {NULL, &wb_submode1, NULL, NULL, NULL, NULL, NULL, NULL}, + 1, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, + {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, +#ifndef DISABLE_VBR + vbr_uhb_thresh, #endif - 2 + 2 }; #endif diff --git a/apps/codecs/libspeex/nb_celp.c b/apps/codecs/libspeex/nb_celp.c index d1e8caed09..84cf1bb6d7 100644 --- a/apps/codecs/libspeex/nb_celp.c +++ b/apps/codecs/libspeex/nb_celp.c @@ -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,7 +1627,8 @@ int nb_encoder_ctl(void *state, int request, void *ptr) case SPEEX_GET_MODE: (*(spx_int32_t*)ptr) = st->submodeID; break; - case SPEEX_SET_VBR: +#ifndef DISABLE_VBR + case SPEEX_SET_VBR: st->vbr_enabled = (*(spx_int32_t*)ptr); break; case SPEEX_GET_VBR: @@ -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; diff --git a/apps/codecs/libspeex/nb_celp.h b/apps/codecs/libspeex/nb_celp.h index 7f90f7c05c..30abdee842 100644 --- a/apps/codecs/libspeex/nb_celp.h +++ b/apps/codecs/libspeex/nb_celp.h @@ -92,7 +92,8 @@ typedef struct EncState { spx_mem_t mem_hp[2]; /**< High-pass filter memory */ 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; diff --git a/apps/codecs/libspeex/preprocess.c b/apps/codecs/libspeex/preprocess.c index 5d5befe736..07a2ad3479 100644 --- a/apps/codecs/libspeex/preprocess.c +++ b/apps/codecs/libspeex/preprocess.c @@ -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: diff --git a/apps/codecs/libspeex/quant_lsp.c b/apps/codecs/libspeex/quant_lsp.c index 441a257a49..9b9104c842 100644 --- a/apps/codecs/libspeex/quant_lsp.c +++ b/apps/codecs/libspeex/quant_lsp.c @@ -389,4 +389,3 @@ void lsp_unquant_high(spx_lsp_t *lsp, int order, SpeexBits *bits) #endif - diff --git a/apps/codecs/libspeex/sb_celp.c b/apps/codecs/libspeex/sb_celp.c index 17cfc73a4e..313a62e93f 100644 --- a/apps/codecs/libspeex/sb_celp.c +++ b/apps/codecs/libspeex/sb_celp.c @@ -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; diff --git a/apps/codecs/libspeex/sb_celp.h b/apps/codecs/libspeex/sb_celp.h index 0d171b3f8b..51aa3d0e13 100644 --- a/apps/codecs/libspeex/sb_celp.h +++ b/apps/codecs/libspeex/sb_celp.h @@ -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,7 +83,8 @@ 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; int submodeID; diff --git a/apps/codecs/libspeex/speex.c b/apps/codecs/libspeex/speex.c index 6bf362edbb..a77653f21a 100644 --- a/apps/codecs/libspeex/speex.c +++ b/apps/codecs/libspeex/speex.c @@ -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) { diff --git a/apps/codecs/libspeex/speex/speex.h b/apps/codecs/libspeex/speex/speex.h index 05123d21b2..ffb0714f1c 100644 --- a/apps/codecs/libspeex/speex/speex.h +++ b/apps/codecs/libspeex/speex/speex.h @@ -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 } diff --git a/apps/codecs/libspeex/speex/speex_jitter.h b/apps/codecs/libspeex/speex/speex_jitter.h index 7c948d474e..d1af5b0210 100644 --- a/apps/codecs/libspeex/speex/speex_jitter.h +++ b/apps/codecs/libspeex/speex/speex_jitter.h @@ -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 * diff --git a/apps/codecs/libspeex/speex_callbacks.c b/apps/codecs/libspeex/speex_callbacks.c index 252bc90f6f..58d7b7b92a 100644 --- a/apps/codecs/libspeex/speex_callbacks.c +++ b/apps/codecs/libspeex/speex_callbacks.c @@ -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) { diff --git a/apps/codecs/libspeex/speex_header.c b/apps/codecs/libspeex/speex_header.c index 30f47206c4..a96e2a24c5 100644 --- a/apps/codecs/libspeex/speex_header.c +++ b/apps/codecs/libspeex/speex_header.c @@ -48,7 +48,7 @@ static inline spx_int32_t le_int(spx_int32_t i) { #ifdef ROCKBOX - return letoh32(i); + return letoh32(i); #elif !defined(__LITTLE_ENDIAN__) && ( defined(WORDS_BIGENDIAN) || defined(__BIG_ENDIAN__) ) spx_uint32_t ui, ret; ui = i; diff --git a/apps/codecs/libspeex/stereo.c b/apps/codecs/libspeex/stereo.c index 5f74197054..2dce283ac3 100644 --- a/apps/codecs/libspeex/stereo.c +++ b/apps/codecs/libspeex/stereo.c @@ -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; + 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 + + /* In band marker */ + speex_bits_pack(bits, 14, 5); + /* Stereo marker */ + speex_bits_pack(bits, SPEEX_INBAND_STEREO, 4); + 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]; + 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]); - e_tot += ((float)data[i])*data[i]; +#endif + e_tot += SHR32(MULT16_16(data[i],data[i]),8); } - balance=(e_left+1)/(e_right+1); - e_ratio = e_tot/(1+e_left+e_right); - - /*Quantization*/ - speex_bits_pack(bits, 14, 5); - speex_bits_pack(bits, SPEEX_INBAND_STEREO, 4); - - balance=4*log(balance); - - /*Pack sign*/ - if (balance>0) + 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; + } + + /* 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 - speex_bits_pack(bits, (int)balance, 5); + speex_bits_pack(bits, balance_id, 5); - /* FIXME: this is a hack */ - tmp=scal_quant(e_ratio*Q15_ONE, e_ratio_quant_bounds, 3); + /* "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) { diff --git a/apps/codecs/libspeex/vbr.c b/apps/codecs/libspeex/vbr.c index cc538b3fe9..32b33bc10e 100644 --- a/apps/codecs/libspeex/vbr.c +++ b/apps/codecs/libspeex/vbr.c @@ -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 */ |