static int tdav_speex_jitterbuffer_reset(tmedia_jitterbuffer_t* self) { tdav_speex_jitterbuffer_t *jitterbuffer = (tdav_speex_jitterbuffer_t *)self; if(jitterbuffer->state){ jitter_buffer_reset(jitterbuffer->state); } return 0; }
/** Destroy jitter buffer */ EXPORT void jitter_buffer_destroy(JitterBuffer *jitter) { if (jitter) { jitter_buffer_reset(jitter); speex_free(jitter); } }
static int tdav_speex_jitterbuffer_reset(tmedia_jitterbuffer_t* self) { tdav_speex_jitterbuffer_t *jb = (tdav_speex_jitterbuffer_t *)self; if (jb->state) { jitter_buffer_reset(jb->state); } jb->num_pkt_in = 0; jb->num_pkt_miss = 0; return 0; }
/** Initialise jitter buffer */ JitterBuffer *jitter_buffer_init(int tick) { JitterBuffer *jitter = (JitterBuffer*)speex_alloc(sizeof(JitterBuffer)); if (jitter) { int i; for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) jitter->buf[i]=NULL; jitter->tick_size = tick; jitter->buffer_margin = 1; jitter_buffer_reset(jitter); } return jitter; }
/** Initialise jitter buffer */ EXPORT JitterBuffer *jitter_buffer_init(int step_size) { 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->delay_step = step_size; jitter->concealment_size = step_size; /*FIXME: Should this be 0 or 1?*/ jitter->buffer_margin = 0; jitter->late_cutoff = 50; jitter->destroy = NULL; jitter->latency_tradeoff = 0; jitter->auto_adjust = 1; tmp = 4; jitter_buffer_ctl(jitter, JITTER_BUFFER_SET_MAX_LATE_RATE, &tmp); jitter_buffer_reset(jitter); } return jitter; }
void jitterFill(JitterBuffer *jb) { char buffer[65536]; JitterBufferPacket in, out; int i; out.data = buffer; jitter_buffer_reset(jb); for(i=0;i<100;++i) { synthIn(&in, i, 1); jitter_buffer_put(jb, &in); out.len = 65536; if (jitter_buffer_get(jb, &out, 10, NULL) != JITTER_BUFFER_OK) { printf("Fill test failed iteration %d\n", i); } if (out.timestamp != i * 10) { printf("Fill test expected %d got %d\n", i*10, out.timestamp); } jitter_buffer_tick(jb); } }
/** 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 }
/** 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; } }
/** Destroy jitter buffer */ void jitter_buffer_destroy(JitterBuffer *jitter) { jitter_buffer_reset(jitter); free(jitter); }
void AudioInput::encodeAudioFrame() { int iArg; ClientPlayer *p=ClientPlayer::get(g.uiSession); int i; float sum; short max; short *psSource; iFrameCounter++; if (! bRunning) { return; } sum=1.0f; for (i=0;i<iFrameSize;i++) sum += static_cast<float>(psMic[i] * psMic[i]); dPeakMic=20.0f*log10f(sqrtf(sum / static_cast<float>(iFrameSize)) / 32768.0f); if (dPeakMic < -96.0f) dPeakMic = -96.0f; max = 1; for (i=0;i<iFrameSize;i++) max = static_cast<short>(abs(psMic[i]) > max ? abs(psMic[i]) : max); dMaxMic = max; if (g.bEchoTest) { STACKVAR(float, fft, iFrameSize); STACKVAR(float, power, iFrameSize); float scale = 1.f / static_cast<float>(iFrameSize); for (i=0;i<iFrameSize;i++) fft[i] = static_cast<float>(psMic[i]) * scale; mumble_drft_forward(&fftTable, fft); float mp = 0.0f; int bin = 0; power[0]=power[1]=0.0f; for (i=2;i < iFrameSize / 2;i++) { power[i] = sqrtf(fft[2*i]*fft[2*i]+fft[2*i-1]*fft[2*i-1]); if (power[i] > mp) { bin = i; mp = power[i]; } } for (i=2;i< iFrameSize / 2;i++) { if (power[i] * 2 > mp) { if (i != bin) bin = 0; } } iBestBin = bin * 2; } if (iEchoChannels > 0) { sum=1.0f; for (i=0;i<iFrameSize;i++) sum += static_cast<float>(psSpeaker[i] * psSpeaker[i]); dPeakSpeaker=20.0f*log10f(sqrtf(sum / static_cast<float>(iFrameSize)) / 32768.0f); if (dPeakSpeaker < -96.0f) dPeakSpeaker = -96.0f; } else { dPeakSpeaker = 0.0; } QMutexLocker l(&qmSpeex); if (bResetProcessor) { if (sppPreprocess) speex_preprocess_state_destroy(sppPreprocess); if (sesEcho) speex_echo_state_destroy(sesEcho); sppPreprocess = speex_preprocess_state_init(iFrameSize, SAMPLE_RATE); iArg = 1; speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_VAD, &iArg); speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_DENOISE, &iArg); speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_AGC, &iArg); speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_DEREVERB, &iArg); iArg = 30000; speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_AGC_TARGET, &iArg); float v = 30000.0f / static_cast<float>(g.s.iMinLoudness); iArg = lroundf(floorf(20.0f * log10f(v))); speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_AGC_MAX_GAIN, &iArg); iArg = g.s.iNoiseSuppress; speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, &iArg); if (iEchoChannels > 0) { sesEcho = speex_echo_state_init(iFrameSize, iFrameSize*10); iArg = SAMPLE_RATE; speex_echo_ctl(sesEcho, SPEEX_SET_SAMPLING_RATE, &iArg); speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_ECHO_STATE, sesEcho); jitter_buffer_reset(jb); qWarning("AudioInput: ECHO CANCELLER ACTIVE"); } else { sesEcho = NULL; } iFrames = 0; speex_bits_reset(&sbBits); bResetProcessor = false; } int iIsSpeech; if (sesEcho) { speex_echo_cancellation(sesEcho, psMic, psSpeaker, psClean); iIsSpeech=speex_preprocess_run(sppPreprocess, psClean); psSource = psClean; } else { iIsSpeech=speex_preprocess_run(sppPreprocess, psMic); psSource = psMic; } sum=1.0f; for (i=0;i<iFrameSize;i++) sum += static_cast<float>(psSource[i] * psSource[i]); float micLevel = sqrtf(sum / static_cast<float>(iFrameSize)); dPeakSignal=20.0f*log10f(micLevel / 32768.0f); if (dPeakSignal < -96.0f) dPeakSignal = -96.0f; spx_int32_t prob = 0; speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_GET_PROB, &prob); fSpeechProb = static_cast<float>(prob) / 100.0f; float level = (g.s.vsVAD == Settings::SignalToNoise) ? fSpeechProb : (1.0f + dPeakMic / 96.0f); if (level > g.s.fVADmax) iIsSpeech = 1; else if (level > g.s.fVADmin && bPreviousVoice) iIsSpeech = 1; else iIsSpeech = 0; if (! iIsSpeech) { iHoldFrames++; if (iHoldFrames < g.s.iVoiceHold) iIsSpeech=1; } else { iHoldFrames = 0; } if (g.s.atTransmit == Settings::Continous) iIsSpeech = 1; else if (g.s.atTransmit == Settings::PushToTalk) iIsSpeech = g.s.uiDoublePush && ((g.uiDoublePush < g.s.uiDoublePush) || (g.tDoublePush.elapsed() < g.s.uiDoublePush)); iIsSpeech = iIsSpeech || (g.iPushToTalk > 0) || (g.iAltSpeak > 0); if (g.s.bMute || ((g.s.lmLoopMode != Settings::Local) && p && p->bMute) || g.bPushToMute) { iIsSpeech = 0; } if (iIsSpeech) { iSilentFrames = 0; } else { iSilentFrames++; if (iSilentFrames > 200) iFrameCounter = 0; } if (p) p->setTalking(iIsSpeech, (g.iAltSpeak > 0)); if (g.s.bPushClick && (g.s.atTransmit == Settings::PushToTalk)) { AudioOutputPtr ao = g.ao; if (iIsSpeech && ! bPreviousVoice && ao) ao->playSine(400.0f,1200.0f,5); else if (ao && !iIsSpeech && bPreviousVoice && ao) ao->playSine(620.0f,-1200.0f,5); } if (! iIsSpeech && ! bPreviousVoice) { iBitrate = 0; if (g.s.iIdleTime && ! g.s.bMute && ((tIdle.elapsed() / 1000000ULL) > g.s.iIdleTime)) { emit doMute(); tIdle.restart(); } return; } bPreviousVoice = iIsSpeech; tIdle.restart(); if (! iIsSpeech) { memset(psMic, 0, sizeof(short) * iFrameSize); } if (g.s.bTransmitPosition && g.p && ! g.bCenterPosition && (iFrames == 0) && g.p->fetch()) { QByteArray q; QDataStream ds(&q, QIODevice::WriteOnly); ds << g.p->fPosition[0]; ds << g.p->fPosition[1]; ds << g.p->fPosition[2]; speex_bits_pack(&sbBits, 13, 5); speex_bits_pack(&sbBits, q.size(), 4); const unsigned char *d=reinterpret_cast<const unsigned char*>(q.data()); for (i=0;i<q.size();i++) { speex_bits_pack(&sbBits, d[i], 8); } } speex_encode_int(esEncState, psSource, &sbBits); iFrames++; speex_encoder_ctl(esEncState, SPEEX_GET_BITRATE, &iBitrate); flushCheck(); }
PJ_DEF(void) jitter_buffer_flush(Jitter_Buffer *jitter_buffer) { jitter_buffer_reset(jitter_buffer); }