static int tdav_speex_jitterbuffer_open(tmedia_jitterbuffer_t* self, uint32_t frame_duration, uint32_t rate, uint32_t channels) { tdav_speex_jitterbuffer_t *jitterbuffer = (tdav_speex_jitterbuffer_t *)self; spx_int32_t tmp; TSK_DEBUG_INFO("Open speex jb (ptime=%u, rate=%u)", frame_duration, rate); if(!(jitterbuffer->state = jitter_buffer_init((int)frame_duration))){ TSK_DEBUG_ERROR("jitter_buffer_init() failed"); return -2; } jitterbuffer->rate = rate; jitterbuffer->frame_duration = frame_duration; jitterbuffer->channels = channels; jitterbuffer->x_data_size = ((frame_duration * jitterbuffer->rate) / 500) << (channels == 2 ? 1 : 0); jitter_buffer_ctl(jitterbuffer->state, JITTER_BUFFER_GET_MARGIN, &tmp); TSK_DEBUG_INFO("Default Jitter buffer margin=%d", tmp); jitter_buffer_ctl(jitterbuffer->state, JITTER_BUFFER_GET_MAX_LATE_RATE, &tmp); TSK_DEBUG_INFO("Default Jitter max late rate=%d", tmp); if((tmp = tmedia_defaults_get_jb_margin()) >= 0){ jitter_buffer_ctl(jitterbuffer->state, JITTER_BUFFER_SET_MARGIN, &tmp); TSK_DEBUG_INFO("New Jitter buffer margin=%d", tmp); } if((tmp = tmedia_defaults_get_jb_max_late_rate()) >= 0){ jitter_buffer_ctl(jitterbuffer->state, JITTER_BUFFER_SET_MAX_LATE_RATE, &tmp); TSK_DEBUG_INFO("New Jitter buffer max late rate=%d", tmp); } return 0; }
JNIEXPORT jint JNICALL Native_NATIVE(jitter_1buffer_1ctl) (JNIEnv *env, jclass that, jlong arg0, jint arg1, jintArray arg2) { jint *lparg2=NULL; jint rc = 0; Native_NATIVE_ENTER(env, that, Native_jitter_1buffer_1ctl_FUNC); if (arg2) if ((lparg2 = (*env)->GetIntArrayElements(env, arg2, NULL)) == NULL) goto fail; rc = jitter_buffer_ctl((JitterBuffer *)(intptr_t)arg0, arg1, lparg2); fail: if (arg2 && lparg2) (*env)->ReleaseIntArrayElements(env, arg2, lparg2, 0); Native_NATIVE_EXIT(env, that, Native_jitter_1buffer_1ctl_FUNC); return rc; }
/** 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; }
AudioOutputSpeech::AudioOutputSpeech(ClientUser *user, unsigned int freq, MessageHandler::UDPMessageType type) : AudioOutputUser(user->qsName) { int err; p = user; umtType = type; iMixerFreq = freq; cCodec = NULL; cdDecoder = NULL; dsSpeex = NULL; opusState = NULL; bStereo = false; iSampleRate = SAMPLE_RATE; iFrameSize = iSampleRate / 100; iAudioBufferSize = iFrameSize; if (umtType == MessageHandler::UDPVoiceOpus) { #ifdef USE_OPUS iAudioBufferSize *= 12; opusState = opus_decoder_create(iSampleRate, bStereo ? 2 : 1, NULL); #endif } else if (umtType == MessageHandler::UDPVoiceSpeex) { speex_bits_init(&sbBits); dsSpeex = speex_decoder_init(speex_lib_get_mode(SPEEX_MODEID_UWB)); int iArg=1; speex_decoder_ctl(dsSpeex, SPEEX_SET_ENH, &iArg); speex_decoder_ctl(dsSpeex, SPEEX_GET_FRAME_SIZE, &iFrameSize); speex_decoder_ctl(dsSpeex, SPEEX_GET_SAMPLING_RATE, &iSampleRate); iAudioBufferSize = iFrameSize; } iOutputSize = static_cast<unsigned int>(ceilf(static_cast<float>(iAudioBufferSize * iMixerFreq) / static_cast<float>(iSampleRate))); if (bStereo) { iAudioBufferSize *= 2; iOutputSize *= 2; } srs = NULL; fResamplerBuffer = NULL; if (iMixerFreq != iSampleRate) { srs = speex_resampler_init(bStereo ? 2 : 1, iSampleRate, iMixerFreq, 3, &err); fResamplerBuffer = new float[iAudioBufferSize]; } iBufferOffset = iBufferFilled = iLastConsume = 0; bLastAlive = true; iMissCount = 0; iMissedFrames = 0; ucFlags = 0xFF; jbJitter = jitter_buffer_init(iFrameSize); int margin = g.s.iJitterBufferSize * iFrameSize; jitter_buffer_ctl(jbJitter, JITTER_BUFFER_SET_MARGIN, &margin); fFadeIn = new float[iFrameSize]; fFadeOut = new float[iFrameSize]; float mul = static_cast<float>(M_PI / (2.0 * static_cast<double>(iFrameSize))); for (unsigned int i=0;i<iFrameSize;++i) fFadeIn[i] = fFadeOut[iFrameSize-i-1] = sinf(static_cast<float>(i) * mul); }
bool AudioOutputSpeech::needSamples(unsigned int snum) { for (unsigned int i=iLastConsume;i<iBufferFilled;++i) pfBuffer[i-iLastConsume]=pfBuffer[i]; iBufferFilled -= iLastConsume; iLastConsume = snum; if (iBufferFilled >= snum) return bLastAlive; float *pOut; STACKVAR(float, fOut, iFrameSize + 4096); bool nextalive = bLastAlive; while (iBufferFilled < snum) { resizeBuffer(iBufferFilled + iOutputSize); pOut = (srs) ? fOut : (pfBuffer + iBufferFilled); if (! bLastAlive) { memset(pOut, 0, iFrameSize * sizeof(float)); } else { if (p == LoopUser::lpLoopy) { LoopUser::lpLoopy->fetchFrames(); } int avail = 0; int ts = jitter_buffer_get_pointer_timestamp(jbJitter); jitter_buffer_ctl(jbJitter, JITTER_BUFFER_GET_AVAILABLE_COUNT, &avail); if (p && (ts == 0)) { int want = iroundf(p->fAverageAvailable); if (avail < want) { ++iMissCount; if (iMissCount < 20) { memset(pOut, 0, iFrameSize * sizeof(float)); goto nextframe; } } } if (qlFrames.isEmpty()) { QMutexLocker lock(&qmJitter); char data[4096]; JitterBufferPacket jbp; jbp.data = data; jbp.len = 4096; spx_int32_t startofs = 0; if (jitter_buffer_get(jbJitter, &jbp, iFrameSize, &startofs) == JITTER_BUFFER_OK) { PacketDataStream pds(jbp.data, jbp.len); iMissCount = 0; ucFlags = static_cast<unsigned char>(pds.next()); bHasTerminator = false; unsigned int header = 0; do { header = static_cast<unsigned int>(pds.next()); if (header) qlFrames << pds.dataBlock(header & 0x7f); else bHasTerminator = true; } while ((header & 0x80) && pds.isValid()); if (pds.left()) { pds >> fPos[0]; pds >> fPos[1]; pds >> fPos[2]; } else { fPos[0] = fPos[1] = fPos[2] = 0.0f; } if (p) { float a = static_cast<float>(avail); if (avail >= p->fAverageAvailable) p->fAverageAvailable = a; else p->fAverageAvailable *= 0.99f; } } else {
int main(int argc, char **argv) { int sd, rc, n, tmp; char msg[MAX_MSG]; int nfds; int send_timestamp = 0; int recv_started = 0; struct pollfd *pfds; struct alsa_dev *dev; CELTEncoder *enc_state; CELTDecoder *dec_state; CELTMode *mode; struct sched_param param; JitterBuffer *jitter; SpeexEchoState *echo_state; char mac_own[6], mac_remote[6]; if (argc != 4) panic("Usage %s plughw:0,0 <lmac in xx:xx:xx:xx:xx:xx> <rmac>\n", argv[0]); register_signal(SIGINT, sighandler); hack_mac(mac_own, argv[2], strlen(argv[2])); hack_mac(mac_remote, argv[3], strlen(argv[3])); sd = socket(AF_LANA, SOCK_RAW, 0); if (sd < 0) panic("%s: cannot open socket \n", argv[0]); printf("If ready hit key!\n"); //user must do binding getchar(); dev = alsa_open(argv[1], SAMPLING_RATE, CHANNELS, FRAME_SIZE); mode = celt_mode_create(SAMPLING_RATE, FRAME_SIZE, NULL); enc_state = celt_encoder_create(mode, CHANNELS, NULL); dec_state = celt_decoder_create(mode, CHANNELS, NULL); param.sched_priority = sched_get_priority_min(SCHED_FIFO); if (sched_setscheduler(0, SCHED_FIFO, ¶m)) whine("sched_setscheduler error!\n"); /* Setup all file descriptors for poll()ing */ nfds = alsa_nfds(dev); pfds = xmalloc(sizeof(*pfds) * (nfds + 1)); alsa_getfds(dev, pfds, nfds); pfds[nfds].fd = sd; pfds[nfds].events = POLLIN; /* Setup jitter buffer using decoder */ jitter = jitter_buffer_init(FRAME_SIZE); tmp = FRAME_SIZE; jitter_buffer_ctl(jitter, JITTER_BUFFER_SET_MARGIN, &tmp); /* Echo canceller with 200 ms tail length */ echo_state = speex_echo_state_init(FRAME_SIZE, 10 * FRAME_SIZE); tmp = SAMPLING_RATE; speex_echo_ctl(echo_state, SPEEX_ECHO_SET_SAMPLING_RATE, &tmp); register_signal_f(SIGALRM, timer_elapsed, SA_SIGINFO); alsa_start(dev); printf("ALSA started!\n"); itimer.it_interval.tv_sec = 0; itimer.it_interval.tv_usec = interval; itimer.it_value.tv_sec = 0; itimer.it_value.tv_usec = interval; setitimer(ITIMER_REAL, &itimer, NULL); while (!sigint) { poll(pfds, nfds + 1, -1); /* Received packets */ if (pfds[nfds].revents & POLLIN) { memset(msg, 0, MAX_MSG); n = recv(sd, msg, MAX_MSG, 0); if (n <= 0) goto do_alsa; pkts_in++; int recv_timestamp; memcpy(&recv_timestamp, msg, sizeof(recv_timestamp)); JitterBufferPacket packet; packet.data = msg+4/*+6+6+2*/; packet.len = n-4/*-6-6-2*/; packet.timestamp = recv_timestamp; packet.span = FRAME_SIZE; packet.sequence = 0; /* Put content of the packet into the jitter buffer, except for the pseudo-header */ jitter_buffer_put(jitter, &packet); recv_started = 1; } do_alsa: /* Ready to play a frame (playback) */ if (alsa_play_ready(dev, pfds, nfds)) { short pcm[FRAME_SIZE * CHANNELS] = {0}; if (recv_started) { JitterBufferPacket packet; /* Get audio from the jitter buffer */ packet.data = msg; packet.len = MAX_MSG; jitter_buffer_tick(jitter); jitter_buffer_get(jitter, &packet, FRAME_SIZE, NULL); if (packet.len == 0) packet.data=NULL; celt_decode(dec_state, (const unsigned char *) packet.data, packet.len, pcm); } /* Playback the audio and reset the echo canceller if we got an underrun */ alsa_write(dev, pcm, FRAME_SIZE); // if (alsa_write(dev, pcm, FRAME_SIZE)) // speex_echo_state_reset(echo_state); /* Put frame into playback buffer */ // speex_echo_playback(echo_state, pcm); } /* Audio available from the soundcard (capture) */ if (alsa_cap_ready(dev, pfds, nfds)) { short pcm[FRAME_SIZE * CHANNELS]; //pcm2[FRAME_SIZE * CHANNELS]; char outpacket[MAX_MSG]; alsa_read(dev, pcm, FRAME_SIZE); /* Perform echo cancellation */ // speex_echo_capture(echo_state, pcm, pcm2); // for (i = 0; i < FRAME_SIZE * CHANNELS; ++i) // pcm[i] = pcm2[i]; celt_encode(enc_state, pcm, NULL, (unsigned char *) (outpacket+4+6+6+2), PACKETSIZE); /* Pseudo header: four null bytes and a 32-bit timestamp; XXX hack */ memcpy(outpacket,mac_remote,6); memcpy(outpacket+6,mac_own,6); outpacket[6+6] = (uint8_t) 0xac; outpacket[6+6+1] = (uint8_t) 0xdc; memcpy(outpacket+6+6+2, &send_timestamp, sizeof(send_timestamp)); send_timestamp += FRAME_SIZE; rc = sendto(sd, outpacket, PACKETSIZE+4+6+6+2, 0, NULL, 0); if (rc < 0) panic("cannot send to socket"); pkts_out++; } } itimer.it_interval.tv_sec = 0; itimer.it_interval.tv_usec = 0; itimer.it_value.tv_sec = 0; itimer.it_value.tv_usec = 0; setitimer(ITIMER_REAL, &itimer, NULL); close(sd); return 0; }
AudioOutputSpeech::AudioOutputSpeech(boost::shared_ptr<ClientUser> user, MessageHandler::UDPMessageType type) : AudioOutputUser(user->qsName) { int err; p = user; umtType = type; unsigned int srate = 0; cCodec = NULL; cdDecoder = NULL; if (umtType != MessageHandler::UDPVoiceSpeex) { srate = SAMPLE_RATE; iFrameSize = srate / 100; dsSpeex = NULL; } else { speex_bits_init(&sbBits); dsSpeex = speex_decoder_init(speex_lib_get_mode(SPEEX_MODEID_UWB)); int iArg=1; speex_decoder_ctl(dsSpeex, SPEEX_SET_ENH, &iArg); speex_decoder_ctl(dsSpeex, SPEEX_GET_FRAME_SIZE, &iFrameSize); speex_decoder_ctl(dsSpeex, SPEEX_GET_SAMPLING_RATE, &srate); } if (srate != SAMPLE_RATE) srs = speex_resampler_init(1, srate, SAMPLE_RATE, 3, &err); else srs = NULL; iOutputSize = static_cast<unsigned int>(ceilf(static_cast<float>(iFrameSize * SAMPLE_RATE) / static_cast<float>(SAMPLE_RATE))); iBufferOffset = iBufferFilled = iLastConsume = 0; bLastAlive = true; iMissCount = 0; iMissedFrames = 0; ucFlags = 0xFF; jbJitter = jitter_buffer_init(iFrameSize); int margin = g.s.iJitterBufferSize * iFrameSize; jitter_buffer_ctl(jbJitter, JITTER_BUFFER_SET_MARGIN, &margin); fFadeIn = new float[iFrameSize]; fFadeOut = new float[iFrameSize]; float mul = static_cast<float>(M_PI / (2.0 * static_cast<double>(iFrameSize))); for (unsigned int i=0;i<iFrameSize;++i) fFadeIn[i] = fFadeOut[iFrameSize-i-1] = sinf(static_cast<float>(i) * mul); }