void REM32(reg_t r1, reg_t r2, reg_t r3, reg_t scratch) { MOV32(scratch, r2); MOVIM32(r1, 0); EQ32(scratch+4, r3, R_ZERO); if (REG32(scratch+4)) { goto _end; } GTE32(scratch+4, scratch, r3, scratch+16); GT32(scratch+8, scratch, R_ZERO); LAND32(scratch+12, scratch+4, scratch+8); while (REG32(scratch+12)) { SUB32(scratch, scratch, r3); GTE32(scratch+4, scratch, r3, scratch+16); GT32(scratch+8, scratch, R_ZERO); LAND32(scratch+12, scratch+4, scratch+8); } MOV32(r1, scratch); _end: return; }
void MUL32(reg_t r1, reg_t r2, reg_t r3, reg_t scratch) { MOV32(scratch, r2); MOV32(scratch+4, r3); //make sure this initialization is after r2 and r3 are already saved // otherwise, if r1 = r2 or r1 = r3, then we will have problems MOVIM32(r1, 0); GT32(scratch+8, r2, r3); if (REG32(scratch+8)) { MOV32(scratch, r3); MOV32(scratch+4, r2); } GT32(scratch+8, scratch, R_ZERO); while (REG32(scratch+8)) { ADD32(r1, r1, scratch+4); DEC32(scratch); GT32(scratch+8, scratch, R_ZERO); } }
void LT32(reg_t r1, reg_t r2, reg_t r3) { GT32(r1, r3, r2); }
void GTE32(reg_t r1, reg_t r2, reg_t r3, reg_t scratch) { EQ32(r1, r2, r3); GT32(scratch, r2, r3); LOR32(r1, r1, scratch); }
/** Get one packet from the jitter buffer */ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_uint32_t *start_offset) { int i, j; float late_ratio_short; float late_ratio_long; float ontime_ratio_short; float ontime_ratio_long; float early_ratio_short; float early_ratio_long; int chunk_size; int incomplete = 0; if (LT32(jitter->current_timestamp+jitter->tick_size, jitter->pointer_timestamp)) { jitter->current_timestamp = jitter->pointer_timestamp; speex_warning("did you forget to call jitter_buffer_tick() by any chance?"); } /*fprintf (stderr, "get packet %d %d\n", jitter->pointer_timestamp, jitter->current_timestamp);*/ /* FIXME: This should be only what remaining of the current tick */ chunk_size = jitter->tick_size; /* Compiling arrival statistics */ late_ratio_short = 0; late_ratio_long = 0; for (i=0;i<LATE_BINS;i++) { late_ratio_short += jitter->shortterm_margin[i]; late_ratio_long += jitter->longterm_margin[i]; } ontime_ratio_short = jitter->shortterm_margin[LATE_BINS]; ontime_ratio_long = jitter->longterm_margin[LATE_BINS]; early_ratio_short = early_ratio_long = 0; for (i=LATE_BINS+1;i<MAX_MARGIN;i++) { early_ratio_short += jitter->shortterm_margin[i]; early_ratio_long += jitter->longterm_margin[i]; } if (0&&jitter->pointer_timestamp%1000==0) { /*fprintf (stderr, "%f %f %f %f %f %f\n", early_ratio_short, early_ratio_long, ontime_ratio_short, ontime_ratio_long, late_ratio_short, late_ratio_long);*/ /*fprintf (stderr, "%f %f\n", early_ratio_short + ontime_ratio_short + late_ratio_short, early_ratio_long + ontime_ratio_long + late_ratio_long);*/ } /* Adjusting the buffering */ if (late_ratio_short > .1 || late_ratio_long > .03) { /* If too many packets are arriving late */ jitter->shortterm_margin[MAX_MARGIN-1] += jitter->shortterm_margin[MAX_MARGIN-2]; jitter->longterm_margin[MAX_MARGIN-1] += jitter->longterm_margin[MAX_MARGIN-2]; for (i=MAX_MARGIN-3;i>=0;i--) { jitter->shortterm_margin[i+1] = jitter->shortterm_margin[i]; jitter->longterm_margin[i+1] = jitter->longterm_margin[i]; } jitter->shortterm_margin[0] = 0; jitter->longterm_margin[0] = 0; jitter->pointer_timestamp -= jitter->tick_size; jitter->current_timestamp -= jitter->tick_size; /*fprintf (stderr, "i");*/ /*fprintf (stderr, "interpolate (getting some slack)\n");*/ } else if (late_ratio_short + ontime_ratio_short < .005 && late_ratio_long + ontime_ratio_long < .01 && early_ratio_short > .8) { /* Many frames arriving early */ jitter->shortterm_margin[0] += jitter->shortterm_margin[1]; jitter->longterm_margin[0] += jitter->longterm_margin[1]; for (i=1;i<MAX_MARGIN-1;i++) { jitter->shortterm_margin[i] = jitter->shortterm_margin[i+1]; jitter->longterm_margin[i] = jitter->longterm_margin[i+1]; } jitter->shortterm_margin[MAX_MARGIN-1] = 0; jitter->longterm_margin[MAX_MARGIN-1] = 0; /*fprintf (stderr, "drop frame\n");*/ /*fprintf (stderr, "d");*/ jitter->pointer_timestamp += jitter->tick_size; jitter->current_timestamp += jitter->tick_size; /*fprintf (stderr, "dropping packet (getting more aggressive)\n");*/ } /* Searching for the packet that fits best */ /* Search the buffer for a packet with the right timestamp and spanning the whole current chunk */ for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) { if (jitter->buf[i] && jitter->timestamp[i]==jitter->pointer_timestamp && GE32(jitter->timestamp[i]+jitter->span[i],jitter->pointer_timestamp+chunk_size)) break; } /* If no match, try for an "older" packet that still spans (fully) the current chunk */ if (i==SPEEX_JITTER_MAX_BUFFER_SIZE) { for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) { if (jitter->buf[i] && jitter->timestamp[i]<=jitter->pointer_timestamp && GE32(jitter->timestamp[i]+jitter->span[i],jitter->pointer_timestamp+chunk_size)) break; } } /* If still no match, try for an "older" packet that spans part of the current chunk */ if (i==SPEEX_JITTER_MAX_BUFFER_SIZE) { for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) { if (jitter->buf[i] && jitter->timestamp[i]<=jitter->pointer_timestamp && GT32(jitter->timestamp[i]+jitter->span[i],jitter->pointer_timestamp)) break; } } /* If still no match, try for earliest packet possible */ if (i==SPEEX_JITTER_MAX_BUFFER_SIZE) { int found = 0; spx_uint32_t best_time=0; int best_span=0; int besti=0; for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) { /* check if packet starts within current chunk */ if (jitter->buf[i] && LT32(jitter->timestamp[i],jitter->pointer_timestamp+chunk_size) && GE32(jitter->timestamp[i],jitter->pointer_timestamp)) { if (!found || LT32(jitter->timestamp[i],best_time) || (jitter->timestamp[i]==best_time && GT32(jitter->span[i],best_span))) { best_time = jitter->timestamp[i]; best_span = jitter->span[i]; besti = i; found = 1; } } } if (found) { i=besti; incomplete = 1; /*fprintf (stderr, "incomplete: %d %d %d %d\n", jitter->timestamp[i], jitter->pointer_timestamp, chunk_size, jitter->span[i]);*/ } } /* If we find something */ if (i!=SPEEX_JITTER_MAX_BUFFER_SIZE) { /* We (obviously) haven't lost this packet */ jitter->lost_count = 0; jitter->loss_rate = .999*jitter->loss_rate; /* Check for potential overflow */ packet->len = jitter->len[i]; /* Copy packet */ for (j=0;j<(int)packet->len;j++) packet->data[j] = jitter->buf[i][j]; /* Remove packet */ speex_free(jitter->buf[i]); jitter->buf[i] = NULL; /* Set timestamp and span (if requested) */ if (start_offset) *start_offset = jitter->timestamp[i]-jitter->pointer_timestamp; packet->timestamp = jitter->timestamp[i]; packet->span = jitter->span[i]; /* Point at the end of the current packet */ jitter->pointer_timestamp = jitter->timestamp[i]+jitter->span[i]; if (incomplete) return JITTER_BUFFER_INCOMPLETE; else return JITTER_BUFFER_OK; } /* If we haven't found anything worth returning */ /*fprintf (stderr, "not found\n");*/ 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; packet->timestamp = jitter->pointer_timestamp; packet->span = jitter->tick_size; jitter->pointer_timestamp += chunk_size; packet->len = 0; return JITTER_BUFFER_MISSING; }
/** Get one packet from the jitter buffer */ EXPORT int jitter_buffer_get(JitterBuffer * jitter, JitterBufferPacket * packet, spx_int32_t desired_span, spx_int32_t * start_offset) { int i; unsigned int j; spx_int16_t opt; if (start_offset != NULL) *start_offset = 0; /* Syncing on the first call */ if (jitter->reset_state) { int found = 0; /* Find the oldest packet */ spx_uint32_t oldest = 0; for (i = 0; i < SPEEX_JITTER_MAX_BUFFER_SIZE; i++) { if (jitter->packets[i].data && (!found || LT32(jitter->packets[i].timestamp, oldest))) { oldest = jitter->packets[i].timestamp; found = 1; } } if (found) { jitter->reset_state = 0; jitter->pointer_timestamp = oldest; jitter->next_stop = oldest; } else { packet->timestamp = 0; packet->span = jitter->interp_requested; return JITTER_BUFFER_MISSING; } } jitter->last_returned_timestamp = jitter->pointer_timestamp; if (jitter->interp_requested != 0) { packet->timestamp = jitter->pointer_timestamp; packet->span = jitter->interp_requested; /* Increment the pointer because it got decremented in the delay update */ 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_INSERTION; } /* Searching for the packet that fits best */ /* Search the buffer for a packet with the right timestamp and spanning the whole current chunk */ for (i = 0; i < SPEEX_JITTER_MAX_BUFFER_SIZE; i++) { if (jitter->packets[i].data && jitter->packets[i].timestamp == jitter->pointer_timestamp && GE32(jitter->packets[i].timestamp + jitter->packets[i].span, jitter->pointer_timestamp + desired_span)) break; } /* If no match, try for an "older" packet that still spans (fully) the current chunk */ if (i == SPEEX_JITTER_MAX_BUFFER_SIZE) { for (i = 0; i < SPEEX_JITTER_MAX_BUFFER_SIZE; i++) { if (jitter->packets[i].data && LE32(jitter->packets[i].timestamp, jitter->pointer_timestamp) && GE32(jitter->packets[i].timestamp + jitter->packets[i].span, jitter->pointer_timestamp + desired_span)) break; } } /* If still no match, try for an "older" packet that spans part of the current chunk */ if (i == SPEEX_JITTER_MAX_BUFFER_SIZE) { for (i = 0; i < SPEEX_JITTER_MAX_BUFFER_SIZE; i++) { if (jitter->packets[i].data && LE32(jitter->packets[i].timestamp, jitter->pointer_timestamp) && GT32(jitter->packets[i].timestamp + jitter->packets[i].span, jitter->pointer_timestamp)) break; } } /* If still no match, try for earliest packet possible */ if (i == SPEEX_JITTER_MAX_BUFFER_SIZE) { int found = 0; spx_uint32_t best_time = 0; int best_span = 0; int besti = 0; for (i = 0; i < SPEEX_JITTER_MAX_BUFFER_SIZE; i++) { /* check if packet starts within current chunk */ if (jitter->packets[i].data && LT32(jitter->packets[i].timestamp, jitter->pointer_timestamp + desired_span) && GE32(jitter->packets[i].timestamp, jitter->pointer_timestamp)) { if (!found || LT32(jitter->packets[i].timestamp, best_time) || (jitter->packets[i].timestamp == best_time && GT32(jitter->packets[i].span, best_span))) { best_time = jitter->packets[i].timestamp; best_span = jitter->packets[i].span; besti = i; found = 1; } } } if (found) { i = besti; /*fprintf (stderr, "incomplete: %d %d %d %d\n", jitter->packets[i].timestamp, jitter->pointer_timestamp, chunk_size, jitter->packets[i].span); */ } } /* If we find something */ if (i != SPEEX_JITTER_MAX_BUFFER_SIZE) { spx_int32_t offset; /* We (obviously) haven't lost this packet */ jitter->lost_count = 0; /* In this case, 0 isn't as a valid timestamp */ if (jitter->arrival[i] != 0) { update_timings(jitter, ((spx_int32_t) jitter->packets[i]. timestamp) - ((spx_int32_t) jitter->arrival[i]) - jitter->buffer_margin); } /* Copy packet */ if (jitter->destroy) { packet->data = jitter->packets[i].data; packet->len = jitter->packets[i].len; } else { if (jitter->packets[i].len > packet->len) { speex_warning_int ("jitter_buffer_get(): packet too large to fit. Size is", jitter->packets[i].len); } else { packet->len = jitter->packets[i].len; } for (j = 0; j < packet->len; j++) packet->data[j] = jitter->packets[i].data[j]; /* Remove packet */ speex_free(jitter->packets[i].data); } jitter->packets[i].data = NULL; /* Set timestamp and span (if requested) */ offset = (spx_int32_t) jitter->packets[i].timestamp - (spx_int32_t) jitter->pointer_timestamp; if (start_offset != NULL) *start_offset = offset; else if (offset != 0) speex_warning_int ("jitter_buffer_get() discarding non-zero start_offset", offset); packet->timestamp = jitter->packets[i].timestamp; jitter->last_returned_timestamp = packet->timestamp; packet->span = jitter->packets[i].span; packet->sequence = jitter->packets[i].sequence; packet->user_data = jitter->packets[i].user_data; /* Point to the end of the current packet */ jitter->pointer_timestamp = jitter->packets[i].timestamp + jitter->packets[i].span; jitter->buffered = packet->span - desired_span; if (start_offset != NULL) jitter->buffered += *start_offset; return JITTER_BUFFER_OK; } /* If we haven't found anything worth returning */ /*fprintf (stderr, "not found\n"); */ jitter->lost_count++; /*fprintf (stderr, "m"); */ /*fprintf (stderr, "lost_count = %d\n", jitter->lost_count); */ opt = compute_opt_delay(jitter); /* Should we force an increase in the buffer or just do normal interpolation? */ if (opt < 0) { /* Need to increase buffering */ /* Shift histogram to compensate */ shift_timings(jitter, -opt); packet->timestamp = jitter->pointer_timestamp; packet->span = -opt; /* Don't move the pointer_timestamp forward */ packet->len = 0; jitter->buffered = packet->span - desired_span; return JITTER_BUFFER_INSERTION; /*jitter->pointer_timestamp -= jitter->delay_step; */ /*fprintf (stderr, "Forced to interpolate\n"); */ } 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; jitter->buffered = packet->span - desired_span; return JITTER_BUFFER_MISSING; /*fprintf (stderr, "Normal loss\n"); */ } }