/* not really necessary to call, but if someone is doing in-place ffts, they may want to free the buffers from CHECKBUF */ void kiss_fft_cleanup(void) { speex_free(scratchbuf); scratchbuf = NULL; nscratchbuf=0; speex_free(tmpbuf); tmpbuf=NULL; ntmpbuf=0; }
void spx_drft_clear(struct drft_lookup *l) { if (l) { if (l->trigcache) speex_free(l->trigcache); if (l->splitcache) speex_free(l->splitcache); } }
void vorbis_psy_destroy(VorbisPsy *p) { if(p){ spx_drft_clear(&p->lookup); if(p->bark) speex_free(p->bark); if(p->noiseoffset) speex_free(p->noiseoffset); if(p->window) speex_free(p->window); memset(p,0,sizeof(*p)); speex_free(p); } }
EXPORT int jitter_buffer_get_another(JitterBuffer * jitter, JitterBufferPacket * packet) { int i, j; for (i = 0; i < SPEEX_JITTER_MAX_BUFFER_SIZE; i++) { if (jitter->packets[i].data && jitter->packets[i].timestamp == jitter->last_returned_timestamp) break; } if (i != SPEEX_JITTER_MAX_BUFFER_SIZE) { /* Copy packet */ packet->len = jitter->packets[i].len; if (jitter->destroy) { packet->data = jitter->packets[i].data; } else { for (j = 0; j < (int)packet->len; j++) packet->data[j] = jitter->packets[i].data[j]; /* Remove packet */ speex_free(jitter->packets[i].data); } jitter->packets[i].data = NULL; packet->timestamp = jitter->packets[i].timestamp; packet->span = jitter->packets[i].span; packet->sequence = jitter->packets[i].sequence; packet->user_data = jitter->packets[i].user_data; return JITTER_BUFFER_OK; } else { packet->data = NULL; packet->len = 0; packet->span = 0; return JITTER_BUFFER_MISSING; } }
EXPORT void speex_decorrelate_destroy(SpeexDecorrState *st) { #ifdef VORBIS_PSYCHO vorbis_psy_destroy(st->psy); speex_free(st->wola_mem); speex_free(st->curve); #endif speex_free(st->buff); speex_free(st->ring); speex_free(st->ringID); speex_free(st->alpha); speex_free(st->vorbis_win); speex_free(st->order); speex_free(st->y); speex_free(st); }
/** Reset jitter buffer */ EXPORT void jitter_buffer_reset(JitterBuffer * jitter) { int i; for (i = 0; i < SPEEX_JITTER_MAX_BUFFER_SIZE; i++) { if (jitter->packets[i].data) { if (jitter->destroy) jitter->destroy(jitter->packets[i].data); else speex_free(jitter->packets[i].data); jitter->packets[i].data = NULL; } } /* Timestamp is actually undefined at this point */ jitter->pointer_timestamp = 0; jitter->next_stop = 0; jitter->reset_state = 1; jitter->lost_count = 0; jitter->buffered = 0; jitter->auto_tradeoff = 32000; for (i = 0; i < MAX_BUFFERS; i++) { tb_init(&jitter->_tb[i]); jitter->timeBuffers[i] = &jitter->_tb[i]; } /*fprintf (stderr, "reset\n"); */ }
/** Destroy jitter buffer */ EXPORT void jitter_buffer_destroy(JitterBuffer *jitter) { if (jitter) { jitter_buffer_reset(jitter); speex_free(jitter); } }
EXPORT SpeexHeader *speex_packet_to_header(char *packet, int size) { int i; SpeexHeader *le_header; const char *h = "Speex "; /*FIXME: Do we allow larger headers?*/ if (size < (int)sizeof(SpeexHeader)) { speex_notify("Speex header too small"); return NULL; } for (i=0;i<8;i++) if (packet[i]!=h[i]) { /* This doesn't look like a Speex file */ return NULL; } le_header = (SpeexHeader*)speex_alloc(sizeof(SpeexHeader)); SPEEX_COPY(le_header, (SpeexHeader*)packet, 1); /*Make sure everything is converted correctly from little-endian*/ ENDIAN_SWITCH(le_header->speex_version_id); ENDIAN_SWITCH(le_header->header_size); ENDIAN_SWITCH(le_header->rate); ENDIAN_SWITCH(le_header->mode); ENDIAN_SWITCH(le_header->mode_bitstream_version); ENDIAN_SWITCH(le_header->nb_channels); ENDIAN_SWITCH(le_header->bitrate); ENDIAN_SWITCH(le_header->frame_size); ENDIAN_SWITCH(le_header->vbr); ENDIAN_SWITCH(le_header->frames_per_packet); ENDIAN_SWITCH(le_header->extra_headers); if (le_header->mode >= SPEEX_NB_MODES || le_header->mode < 0) { speex_notify("Invalid mode specified in Speex header"); speex_free (le_header); return NULL; } if (le_header->nb_channels>2) le_header->nb_channels = 2; if (le_header->nb_channels<1) le_header->nb_channels = 1; return le_header; }
void filterbank_destroy(FilterBank *bank) { speex_free(bank->bank_left); speex_free(bank->bank_right); speex_free(bank->filter_left); speex_free(bank->filter_right); #ifndef FIXED_POINT speex_free(bank->scaling); #endif speex_free(bank); }
/** Reset jitter buffer */ void jitter_buffer_reset(JitterBuffer *jitter) { int i; for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) { if (jitter->buf[i]) { speex_free(jitter->buf[i]); jitter->buf[i] = NULL; } } /* Timestamp is actually undefined at this point */ jitter->pointer_timestamp = 0; jitter->current_timestamp = 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; } /*fprintf (stderr, "reset\n");*/ }
EXPORT void speex_stereo_state_destroy(SpeexStereoState * stereo) { speex_free(stereo); }
/** Put one packet into the jitter buffer */ void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet) { int i,j; spx_int32_t arrival_margin; /*fprintf (stderr, "put packet %d %d\n", timestamp, span);*/ if (jitter->reset_state) { jitter->reset_state=0; jitter->pointer_timestamp = packet->timestamp; jitter->current_timestamp = packet->timestamp; /*fprintf(stderr, "reset to %d\n", timestamp);*/ } /* Cleanup buffer (remove old packets that weren't played) */ for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) { if (jitter->buf[i] && LE32(jitter->timestamp[i] + jitter->span[i], jitter->pointer_timestamp)) { /*fprintf (stderr, "cleaned (not played)\n");*/ speex_free(jitter->buf[i]); jitter->buf[i] = NULL; } } /*Find an empty slot in the buffer*/ for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) { if (jitter->buf[i]==NULL) break; } /*fprintf(stderr, "%d %d %f\n", timestamp, jitter->pointer_timestamp, jitter->drift_average);*/ /*No place left in the buffer*/ if (i==SPEEX_JITTER_MAX_BUFFER_SIZE) { int earliest=jitter->timestamp[0]; i=0; for (j=1;j<SPEEX_JITTER_MAX_BUFFER_SIZE;j++) { if (!jitter->buf[i] || LT32(jitter->timestamp[j],earliest)) { earliest = jitter->timestamp[j]; i=j; } } speex_free(jitter->buf[i]); jitter->buf[i]=NULL; if (jitter->lost_count>20) { jitter_buffer_reset(jitter); } /*fprintf (stderr, "Buffer is full, discarding earliest frame %d (currently at %d)\n", timestamp, jitter->pointer_timestamp);*/ } /* Copy packet in buffer */ jitter->buf[i]=(char*)speex_alloc(packet->len); for (j=0;j<(int)packet->len;j++) jitter->buf[i][j]=packet->data[j]; jitter->timestamp[i]=packet->timestamp; jitter->span[i]=packet->span; jitter->len[i]=packet->len; /* Adjust the buffer size depending on network conditions */ arrival_margin = (packet->timestamp - jitter->current_timestamp) - jitter->buffer_margin*jitter->tick_size; if (arrival_margin >= -LATE_BINS*jitter->tick_size) { spx_int32_t int_margin; for (i=0;i<MAX_MARGIN;i++) { jitter->shortterm_margin[i] *= .98; jitter->longterm_margin[i] *= .995; } int_margin = LATE_BINS + arrival_margin/jitter->tick_size; if (int_margin>MAX_MARGIN-1) int_margin = MAX_MARGIN-1; if (int_margin>=0) { jitter->shortterm_margin[int_margin] += .02; jitter->longterm_margin[int_margin] += .005; } } else { /*fprintf (stderr, "way too late = %d\n", arrival_margin);*/ if (jitter->lost_count>20) { jitter_buffer_reset(jitter); } } #if 0 /* Enable to check how much is being buffered */ if (rand()%1000==0) { int count = 0; for (j=0;j<SPEEX_JITTER_MAX_BUFFER_SIZE;j++) { if (jitter->buf[j]) count++; } fprintf (stderr, "buffer_size = %d\n", count); } #endif }
/** 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; }
void *AudioStreamPlaybackSpeex::process_header(ogg_packet *op, int *frame_size, int *rate, int *nframes, int *channels, int *extra_headers) { SpeexHeader *header; int modeID; header = speex_packet_to_header((char *)op->packet, op->bytes); if (!header) { OS::get_singleton()->printerr("Cannot read header\n"); return NULL; } if (header->mode >= SPEEX_NB_MODES) { OS::get_singleton()->printerr("Mode number %d does not (yet/any longer) exist in this version\n", header->mode); return NULL; } modeID = header->mode; const SpeexMode *mode = speex_lib_get_mode(modeID); if (header->speex_version_id > 1) { OS::get_singleton()->printerr("This file was encoded with Speex bit-stream version %d, which I don't know how to decode\n", header->speex_version_id); return NULL; } if (mode->bitstream_version < header->mode_bitstream_version) { OS::get_singleton()->printerr("The file was encoded with a newer version of Speex. You need to upgrade in order to play it.\n"); return NULL; } if (mode->bitstream_version > header->mode_bitstream_version) { OS::get_singleton()->printerr("The file was encoded with an older version of Speex. You would need to downgrade the version in order to play it.\n"); return NULL; } void *state = speex_decoder_init(mode); if (!state) { OS::get_singleton()->printerr("Decoder initialization failed.\n"); return NULL; } //speex_decoder_ctl(state, SPEEX_SET_ENH, &enh_enabled); speex_decoder_ctl(state, SPEEX_GET_FRAME_SIZE, frame_size); if (!*rate) *rate = header->rate; speex_decoder_ctl(state, SPEEX_SET_SAMPLING_RATE, rate); *nframes = header->frames_per_packet; *channels = header->nb_channels; if (*channels != 1) { OS::get_singleton()->printerr("Only MONO speex streams supported\n"); return NULL; } *extra_headers = header->extra_headers; speex_free(header); return state; }
void sb_encoder_destroy(void *state) { SBEncState *st=(SBEncState*)state; speex_encoder_destroy(st->st_low); #if !(defined(VAR_ARRAYS) || defined (USE_ALLOCA)) /*speex_free_scratch(st->stack);*/ #endif speex_free(st->high); speex_free(st->h0_mem); speex_free(st->h1_mem); speex_free(st->old_lsp); speex_free(st->old_qlsp); speex_free(st->interp_qlpc); speex_free(st->pi_gain); speex_free(st->exc_rms); speex_free(st->mem_sp); speex_free(st->mem_sp2); speex_free(st->mem_sw); speex_free(st); }
/** 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"); */ } }
/** Put one packet into the jitter buffer */ EXPORT void jitter_buffer_put(JitterBuffer * jitter, const JitterBufferPacket * packet) { int i, j; int late; /*fprintf (stderr, "put packet %d %d\n", timestamp, span); */ /* Cleanup buffer (remove old packets that weren't played) */ if (!jitter->reset_state) { for (i = 0; i < SPEEX_JITTER_MAX_BUFFER_SIZE; i++) { /* Make sure we don't discard a "just-late" packet in case we want to play it next (if we interpolate). */ if (jitter->packets[i].data && LE32(jitter->packets[i].timestamp + jitter->packets[i].span, jitter->pointer_timestamp)) { /*fprintf (stderr, "cleaned (not played)\n"); */ if (jitter->destroy) jitter->destroy(jitter->packets[i]. data); else speex_free(jitter->packets[i].data); jitter->packets[i].data = NULL; } } } /*fprintf(stderr, "arrival: %d %d %d\n", packet->timestamp, jitter->next_stop, jitter->pointer_timestamp); */ /* Check if packet is late (could still be useful though) */ if (!jitter->reset_state && LT32(packet->timestamp, jitter->next_stop)) { update_timings(jitter, ((spx_int32_t) packet->timestamp) - ((spx_int32_t) jitter->next_stop) - jitter->buffer_margin); late = 1; } else { late = 0; } /* For some reason, the consumer has failed the last 20 fetches. Make sure this packet is * used to resync. */ if (jitter->lost_count > 20) { jitter_buffer_reset(jitter); } /* Only insert the packet if it's not hopelessly late (i.e. totally useless) */ if (jitter->reset_state || GE32(packet->timestamp + packet->span + jitter->delay_step, jitter->pointer_timestamp)) { /*Find an empty slot in the buffer */ for (i = 0; i < SPEEX_JITTER_MAX_BUFFER_SIZE; i++) { if (jitter->packets[i].data == NULL) break; } /*No place left in the buffer, need to make room for it by discarding the oldest packet */ if (i == SPEEX_JITTER_MAX_BUFFER_SIZE) { int earliest = jitter->packets[0].timestamp; i = 0; for (j = 1; j < SPEEX_JITTER_MAX_BUFFER_SIZE; j++) { if (!jitter->packets[i].data || LT32(jitter->packets[j].timestamp, earliest)) { earliest = jitter->packets[j].timestamp; i = j; } } if (jitter->destroy) jitter->destroy(jitter->packets[i].data); else speex_free(jitter->packets[i].data); jitter->packets[i].data = NULL; /*fprintf (stderr, "Buffer is full, discarding earliest frame %d (currently at %d)\n", timestamp, jitter->pointer_timestamp); */ } /* Copy packet in buffer */ if (jitter->destroy) { jitter->packets[i].data = packet->data; } else { jitter->packets[i].data = (char *)speex_alloc(packet->len); for (j = 0; j < (int)packet->len; j++) jitter->packets[i].data[j] = packet->data[j]; } jitter->packets[i].timestamp = packet->timestamp; jitter->packets[i].span = packet->span; jitter->packets[i].len = packet->len; jitter->packets[i].sequence = packet->sequence; jitter->packets[i].user_data = packet->user_data; if (jitter->reset_state || late) jitter->arrival[i] = 0; else jitter->arrival[i] = jitter->next_stop; } }
EXPORT void speex_header_free(void *ptr) { speex_free(ptr); }
EXPORT void speex_buffer_destroy(SpeexBuffer *st) { speex_free(st->data); speex_free(st); }
void speex_preprocess_state_destroy(SpeexPreprocessState *st) { speex_free(st->frame); speex_free(st->ps); speex_free(st->gain2); speex_free(st->window); speex_free(st->noise); speex_free(st->reverb_estimate); speex_free(st->old_ps); speex_free(st->gain); speex_free(st->prior); speex_free(st->post); speex_free(st->loudness_weight); speex_free(st->echo_noise); speex_free(st->S); speex_free(st->Smin); speex_free(st->Stmp); speex_free(st->update_prob); speex_free(st->zeta); speex_free(st->noise_bands); speex_free(st->noise_bands2); speex_free(st->speech_bands); speex_free(st->speech_bands2); speex_free(st->inbuf); speex_free(st->outbuf); spx_drft_clear(st->fft_lookup); speex_free(st->fft_lookup); speex_free(st); }
/** Destroys an echo canceller state */ void speex_echo_state_destroy(SpeexEchoState *st) { spx_drft_clear(st->fft_lookup); speex_free(st->fft_lookup); speex_free(st->x); speex_free(st->d); speex_free(st->y); speex_free(st->last_y); speex_free(st->Yps); speex_free(st->Yf); speex_free(st->Rf); speex_free(st->Xf); speex_free(st->fratio); speex_free(st->regul); speex_free(st->X); speex_free(st->D); speex_free(st->Y); speex_free(st->E); speex_free(st->W); speex_free(st->PHI); speex_free(st->power); speex_free(st->power_1); speex_free(st->grad); speex_free(st); }
/** Destroys an echo canceller state */ EXPORT void speex_echo_state_destroy(SpeexEchoState *st) { spx_fft_destroy(st->fft_table); speex_free(st->e); speex_free(st->x); speex_free(st->input); speex_free(st->y); speex_free(st->last_y); speex_free(st->Yf); speex_free(st->Rf); speex_free(st->Xf); speex_free(st->Yh); speex_free(st->Eh); speex_free(st->X); speex_free(st->Y); speex_free(st->E); speex_free(st->W); #ifdef TWO_PATH speex_free(st->foreground); #endif speex_free(st->PHI); speex_free(st->power); speex_free(st->power_1); speex_free(st->window); speex_free(st->prop); speex_free(st->wtmp); #ifdef FIXED_POINT speex_free(st->wtmp2); #endif speex_free(st->memX); speex_free(st->memD); speex_free(st->memE); speex_free(st->notch_mem); speex_free(st->play_buf); speex_free(st); #ifdef DUMP_ECHO_CANCEL_DATA fclose(rFile); fclose(pFile); fclose(oFile); rFile = pFile = oFile = NULL; #endif }