/*** Encodes 8 kHz-sampled narrowband speech at a bit rate of or 16 kbit/s, uses 5 ms frames. The encoder receives 10 ms speech => 160 bytes. ***/ static void enc_process (MSFilter *f){ EncState *s=(EncState*)f->data; struct BV16_Bit_Stream bs; short *buf= NULL; mblk_t *inputMessage = NULL, *outputMessage = NULL; int frame_per_packet=s->ptime/5; int in_rcvd_bytes = 0; in_rcvd_bytes = SIGNAL_FRAME_SIZE * frame_per_packet; buf=(short*)alloca(in_rcvd_bytes); memset((void*)buf,0, in_rcvd_bytes ); while((inputMessage=ms_queue_get(f->inputs[0]))!=NULL){ ms_bufferizer_put(s->bufferizer,inputMessage); } /* process ptimes ms of data : (ptime in ms)/1000->ptime is seconds * 8000(sample rate) * 2(byte per sample) */ while(ms_bufferizer_get_avail(s->bufferizer)>= in_rcvd_bytes){ int bufferIndex; outputMessage = allocb(BITSTREAM_FRAME_SIZE*frame_per_packet,0); /* output bitStream is 80 bits long * number of samples */ /* process buffer in 5 ms frames but read everything first*/ ms_bufferizer_read(s->bufferizer,(uint8_t*)buf,in_rcvd_bytes); for (bufferIndex=0; bufferIndex<frame_per_packet; bufferIndex++) { BV16_Encode(&bs, &s->state, (short*)&buf[bufferIndex*FRSZ]); BV16_BitPack( (UWord8*)outputMessage->b_wptr, &bs ); outputMessage->b_wptr+=BITSTREAM_FRAME_SIZE; } mblk_set_timestamp_info(outputMessage,s->ts); ms_bufferizer_fill_current_metas(s->bufferizer, outputMessage); ms_queue_put(f->outputs[0],outputMessage); s->ts += FRSZ * frame_per_packet; } }
static void detector_process(MSFilter *f) { DetectorState *s=(DetectorState *)f->data; mblk_t *m; while ((m=ms_queue_get(f->inputs[0]))!=NULL) { ms_queue_put(f->outputs[0],m); if (s->tone_def->frequency!=0) { ms_bufferizer_put(s->buf,dupmsg(m)); } } if (s->tone_def->frequency!=0) { uint8_t *buf=_alloca(s->framesize); while(ms_bufferizer_read(s->buf,buf,s->framesize)!=0) { float en=compute_energy((int16_t*)buf,s->framesize/2); if (en>energy_min) { float freq_en=goertzel_state_run(&s->tone_gs,(int16_t*)buf,s->framesize/2,en); if (freq_en>=s->tone_def->min_amplitude) { if (s->dur==0) s->starttime=f->ticker->time; s->dur+=s->frame_ms; if (s->dur>s->tone_def->min_duration && !s->event_sent) { MSToneDetectorEvent event; strncpy(event.tone_name,s->tone_def->tone_name,sizeof(event.tone_name)); event.tone_start_time=s->starttime; ms_filter_notify(f,MS_TONE_DETECTOR_EVENT,&event); s->event_sent=TRUE; } } else end_tone(s); } else end_tone(s); } } }
static void speex_ec_preprocess(MSFilter *f){ SpeexECState *s=(SpeexECState*)f->data; int delay_samples=0; mblk_t *m; s->echostarted=FALSE; s->filterlength=(s->tail_length_ms*s->samplerate)/1000; s->framesize=adjust_framesize(s->framesize_at_8000,s->samplerate); delay_samples=s->delay_ms*s->samplerate/1000; ms_message("Initializing speex echo canceler with framesize=%i, filterlength=%i, delay_samples=%i", s->framesize,s->filterlength,delay_samples); s->ecstate=speex_echo_state_init(s->framesize,s->filterlength); s->den = speex_preprocess_state_init(s->framesize, s->samplerate); speex_echo_ctl(s->ecstate, SPEEX_ECHO_SET_SAMPLING_RATE, &s->samplerate); speex_preprocess_ctl(s->den, SPEEX_PREPROCESS_SET_ECHO_STATE, s->ecstate); /* fill with zeroes for the time of the delay*/ m=allocb(delay_samples*2,0); m->b_wptr+=delay_samples*2; ms_bufferizer_put (&s->delayed_ref,m); s->min_ref_samples=-1; s->nominal_ref_samples=delay_samples; audio_flow_controller_init(&s->afc); s->flow_control_time = f->ticker->time; #ifdef SPEEX_ECHO_GET_BLOB apply_config(s); #else if (s->state_str) ms_warning("This version of speex doesn't support echo canceller restoration state. Rebuild speex and mediatreamer2 if you want to use this feature."); #endif }
static void enc_process(MSFilter *f){ EncState *s=(EncState*)f->data; mblk_t *im; unsigned int unitary_buff_size = sizeof(int16_t)*160; unsigned int buff_size = unitary_buff_size*s->ptime/20; int16_t* buff; int offset; while((im=ms_queue_get(f->inputs[0]))!=NULL){ ms_bufferizer_put(s->bufferizer,im); } while(ms_bufferizer_get_avail(s->bufferizer) >= buff_size) { mblk_t *om=allocb(33*s->ptime/20,0); buff = (int16_t *)alloca(buff_size); ms_bufferizer_read(s->bufferizer,(uint8_t*)buff,buff_size); for (offset=0;offset<buff_size;offset+=unitary_buff_size) { gsm_encode(s->state,(gsm_signal*)&buff[offset/sizeof(int16_t)],(gsm_byte*)om->b_wptr); om->b_wptr+=33; } mblk_set_timestamp_info(om,s->ts); ms_queue_put(f->outputs[0],om); s->ts+=buff_size/sizeof(int16_t)/*sizeof(buf)/2*/; } }
static void enc_process(MSFilter *f){ static const int nsamples=160; EncState *s=(EncState*)f->data; mblk_t *im,*om; int16_t samples[nsamples]; while((im=ms_queue_get(f->inputs[0]))!=NULL){ ms_bufferizer_put (s->mb,im); } while((ms_bufferizer_read(s->mb,(uint8_t*)samples,nsamples*2))>=nsamples*2){ int ret; om=allocb(33,0); *om->b_wptr=0xf0; om->b_wptr++; ret=Encoder_Interface_Encode(s->enc,MR122,samples,om->b_wptr,0); if (ret<=0){ ms_warning("Encoder returned %i",ret); freemsg(om); continue; } om->b_wptr+=ret; mblk_set_timestamp_info(om,s->ts); s->ts+=nsamples; ms_queue_put(f->outputs[0],om); } }
static void filter_process ( MSFilter *f ) { isac_encoder_struct_t* obj = (isac_encoder_struct_t*)f->data; mblk_t *im; mblk_t *om=NULL; u_int8_t* input_buf = NULL; WebRtc_Word16 ret; static int out_count = 0; // get the input data and put it into our buffered input while( (im = ms_queue_get( f->inputs[0] ) ) != NULL ) { ms_bufferizer_put( obj->bufferizer, im ); } // feed the encoder with 160 16bit samples, until it has reached enough data // to produce a packet while( ms_bufferizer_get_avail(obj->bufferizer) > ISAC_SAMPLES_PER_ENCODE*2 ){ om = allocb( WebRtcIsacfix_GetNewFrameLen(obj->isac), 0 ); if(!input_buf) input_buf = ms_malloc( ISAC_SAMPLES_PER_ENCODE*2 ); ms_bufferizer_read(obj->bufferizer, input_buf, ISAC_SAMPLES_PER_ENCODE*2); ret = WebRtcIsacfix_Encode(obj->isac, (const WebRtc_Word16*)input_buf, (WebRtc_Word16*)om->b_wptr); if( ret < 0) { ms_error( "WebRtcIsacfix_Encode error: %d", WebRtcIsacfix_GetErrorCode(obj->isac) ); freeb(om); } else if( ret == 0 ) { // Encode() buffered the input, not yet able to produce a packet, continue feeding it // 160 samples per-call obj->ts += ISAC_SAMPLES_PER_ENCODE; freeb(om); } else { // a new packet has been encoded, send it obj->ts += ISAC_SAMPLES_PER_ENCODE; om->b_wptr += ret; out_count++; // ms_message("packet %d out, samples %d", out_count, obj->ts); mblk_set_timestamp_info( om, obj->ts ); ms_queue_put(f->outputs[0], om); om = NULL; } } if( input_buf ){ ms_free(input_buf); } }
static void au_write_process(MSFilter *f){ ms_debug("au_write_process"); mblk_t *m; AUData *d=(AUData*)((MSSndCard*)f->data)->data; while((m=ms_queue_get(f->inputs[0]))!=NULL){ ms_mutex_lock(&d->mutex); ms_bufferizer_put(d->bufferizer,m); ms_mutex_unlock(&d->mutex); } }
static void aq_put(MSFilter * f, mblk_t * m) { AQData *d = (AQData *) f->data; ms_mutex_lock(&d->mutex); ms_bufferizer_put(d->bufferizer, m); ms_mutex_unlock(&d->mutex); int len = (d->writeBufferByteSize * d->writeAudioFormat.mSampleRate / 1) / d->devicewriteFormat.mSampleRate / d->devicewriteFormat.mChannelsPerFrame; if (d->write_started == FALSE && d->bufferizer->size >= len) { AudioQueueBufferRef curbuf = d->writeBuffers[d->curWriteBuffer]; #if 0 OSStatus err; UInt32 bsize = d->writeBufferByteSize; uint8_t *pData = ms_malloc(len); ms_bufferizer_read(d->bufferizer, pData, len); err = AudioConverterConvertBuffer(d->writeAudioConverter, len, pData, &bsize, curbuf->mAudioData); if (err != noErr) { ms_error("writeCallback: AudioConverterConvertBuffer %d", err); } ms_free(pData); if (bsize != d->writeBufferByteSize) ms_warning("d->writeBufferByteSize = %i len = %i bsize = %i", d->writeBufferByteSize, len, bsize); #else ms_bufferizer_read(d->bufferizer, curbuf->mAudioData, len); #endif curbuf->mAudioDataByteSize = d->writeBufferByteSize; putWriteAQ(d, d->curWriteBuffer); ++d->curWriteBuffer; } if (d->write_started == FALSE && d->curWriteBuffer == kNumberAudioOutDataBuffers - 1) { OSStatus err; err = AudioQueueStart(d->writeQueue, NULL // start time. NULL means ASAP. ); if (err != noErr) { ms_error("AudioQueueStart -write- %d", err); } d->write_started = TRUE; } }
static void* msandroid_read_cb(msandroid_sound_read_data* d) { mblk_t *m; int nread; jmethodID read_id=0; jmethodID record_id=0; set_high_prio(); //JNIEnv *jni_env = ms_get_jni_env(); JNIEnv *jni_env = NULL; JavaVM *jvm = ms_get_jvm(); if (jvm->AttachCurrentThread(&jni_env, NULL)!=0) { ms_fatal("AttachCurrentThread() failed !"); goto end; } record_id = jni_env->GetMethodID(d->audio_record_class,"startRecording", "()V"); if(record_id==0) { ms_error("cannot find AudioRecord.startRecording() method"); goto end; } //start recording ms_message("Start recording"); jni_env->CallVoidMethod(d->audio_record,record_id); // int read (byte[] audioData, int offsetInBytes, int sizeInBytes) read_id = jni_env->GetMethodID(d->audio_record_class,"read", "([BII)I"); if(read_id==0) { ms_error("cannot find AudioRecord.read() method"); goto end; } while (d->started && (nread=jni_env->CallIntMethod(d->audio_record,read_id,d->read_buff,0, d->read_chunk_size))>0) { m = allocb(nread,0); jni_env->GetByteArrayRegion(d->read_buff, 0,nread, (jbyte*)m->b_wptr); //ms_error("%i octets read",nread); m->b_wptr += nread; d->read_samples+=nread/(2*d->nchannels); compute_timespec(d); ms_mutex_lock(&d->mutex); ms_bufferizer_put (&d->rb,m); ms_mutex_unlock(&d->mutex); }; goto end; end: { jvm->DetachCurrentThread(); ms_thread_exit(NULL); return 0; } }
static void enc_process(MSFilter *f){ SpeexEncState *s=(SpeexEncState*)f->data; mblk_t *im; int nbytes; uint8_t *buf; int frame_per_packet=1; if (s->frame_size<=0) return; ms_filter_lock(f); if (s->ptime>=20) { frame_per_packet = s->ptime/20; } if (frame_per_packet<=0) frame_per_packet=1; if (frame_per_packet>7) /* 7*20 == 140 ms max */ frame_per_packet=7; nbytes=s->frame_size*2; buf=(uint8_t*)alloca(nbytes*frame_per_packet); while((im=ms_queue_get(f->inputs[0]))!=NULL){ ms_bufferizer_put(s->bufferizer,im); } while(ms_bufferizer_read(s->bufferizer,buf,nbytes*frame_per_packet)==nbytes*frame_per_packet){ mblk_t *om=allocb(nbytes*frame_per_packet,0);//too large... int k; SpeexBits bits; speex_bits_init(&bits); for (k=0;k<frame_per_packet;k++) { speex_encode_int(s->state,(int16_t*)(buf + (k*s->frame_size*2)),&bits); s->ts+=s->frame_size; } speex_bits_insert_terminator(&bits); k=speex_bits_write(&bits, (char*)om->b_wptr, nbytes*frame_per_packet); om->b_wptr+=k; mblk_set_timestamp_info(om,s->ts-s->frame_size); ms_bufferizer_fill_current_metas(s->bufferizer, om); ms_queue_put(f->outputs[0],om); speex_bits_destroy(&bits); } ms_filter_unlock(f); }
static void enc_process(MSFilter *f){ EncState *s=(EncState*)f->data; mblk_t *im; int16_t buf[160]; while((im=ms_queue_get(f->inputs[0]))!=NULL){ ms_bufferizer_put(s->bufferizer,im); } while(ms_bufferizer_read(s->bufferizer,(uint8_t*)buf,sizeof(buf))==sizeof(buf)) { mblk_t *om=allocb(33,0); gsm_encode(s->state,(gsm_signal*)buf,(gsm_byte*)om->b_wptr); om->b_wptr+=33; mblk_set_timestamp_info(om,s->ts); ms_queue_put(f->outputs[0],om); s->ts+=sizeof(buf)/2; } }
static void* msandroid_read_cb(msandroid_sound_read_data* d) { mblk_t *m; int nread; JNIEnv *jni_env = 0; jmethodID read_id=0; jmethodID record_id=0; jint result = d->jvm->AttachCurrentThread(&jni_env,NULL); if (result != 0) { ms_error("cannot attach VM\n"); goto end; } record_id = jni_env->GetMethodID(d->audio_record_class,"startRecording", "()V"); if(record_id==0) { ms_error("cannot find AudioRecord.startRecording() method"); goto end; } //start recording jni_env->CallVoidMethod(d->audio_record,record_id); // int read (byte[] audioData, int offsetInBytes, int sizeInBytes) read_id = jni_env->GetMethodID(d->audio_record_class,"read", "([BII)I"); if(read_id==0) { ms_error("cannot find AudioRecord.read() method"); goto end; } while (d->started && (nread=jni_env->CallIntMethod(d->audio_record,read_id,d->read_buff,0, d->read_chunk_size))>0) { m = allocb(nread,0); jni_env->GetByteArrayRegion(d->read_buff, 0,nread, (jbyte*)m->b_wptr); //ms_error("%i octets read",nread); m->b_wptr += nread; ms_mutex_lock(&d->mutex); ms_bufferizer_put (&d->rb,m); ms_mutex_unlock(&d->mutex); }; goto end; end: { d->jvm->DetachCurrentThread(); return 0; } }
static void detector_process(MSFilter *f){ DetectorState *s=(DetectorState *)f->data; mblk_t *m; while ((m=ms_queue_get(f->inputs[0]))!=NULL){ ms_queue_put(f->outputs[0],m); if (s->nscans>0){ ms_bufferizer_put(s->buf,dupmsg(m)); } } if (s->nscans>0){ uint8_t *buf=alloca(s->framesize); while(ms_bufferizer_read(s->buf,buf,s->framesize)!=0){ float en=compute_energy((int16_t*)buf,s->framesize/2); if (en>energy_min_threshold*(32767.0*32767.0*0.7)){ int i; for(i=0;i<s->nscans;++i){ GoertzelState *gs=&s->tone_gs[i]; MSToneDetectorDef *tone_def=&s->tone_def[i]; float freq_en=goertzel_state_run(gs,(int16_t*)buf,s->framesize/2,en); if (freq_en>=tone_def->min_amplitude){ if (gs->dur==0) gs->starttime=f->ticker->time; gs->dur+=s->frame_ms; if (gs->dur>=tone_def->min_duration && !gs->event_sent){ MSToneDetectorEvent event; strncpy(event.tone_name,tone_def->tone_name,sizeof(event.tone_name)); event.tone_start_time=gs->starttime; ms_filter_notify(f,MS_TONE_DETECTOR_EVENT,&event); gs->event_sent=TRUE; } }else{ gs->event_sent=FALSE; gs->dur=0; gs->starttime=0; } } }else end_all_tones(s); } } }
static void webrtc_aec_preprocess(MSFilter *f) { WebRTCAECState *s = (WebRTCAECState *) f->data; AecmConfig config; int delay_samples = 0; mblk_t *m; int error_code; s->echostarted = FALSE; delay_samples = s->delay_ms * s->samplerate / 1000; s->framesize=(framesize*s->samplerate)/8000; ms_message("Initializing WebRTC echo canceler with framesize=%i, delay_ms=%i, delay_samples=%i", s->framesize, s->delay_ms, delay_samples); if ((s->aecmInst = WebRtcAecm_Create()) == NULL) { s->bypass_mode = TRUE; ms_error("WebRtcAecm_Create(): error, entering bypass mode"); return; } if ((error_code = WebRtcAecm_Init(s->aecmInst, s->samplerate)) < 0) { if (error_code == AECM_BAD_PARAMETER_ERROR) { ms_error("WebRtcAecm_Init(): WebRTC echo canceller does not support %d samplerate", s->samplerate); } s->bypass_mode = TRUE; ms_error("Entering bypass mode"); return; } config.cngMode = TRUE; config.echoMode = 3; if (WebRtcAecm_set_config(s->aecmInst, config)!=0){ ms_error("WebRtcAecm_set_config(): failed."); } /* fill with zeroes for the time of the delay*/ m = allocb(delay_samples * 2, 0); m->b_wptr += delay_samples * 2; ms_bufferizer_put(&s->delayed_ref, m); s->min_ref_samples = -1; s->nominal_ref_samples = delay_samples; ms_audio_flow_controller_init(&s->afc); s->flow_control_time = f->ticker->time; }
static void enc_process(MSFilter *f) { EncState *s = (EncState*) f->data; unsigned int unitary_buff_size = sizeof (int16_t)*160; unsigned int buff_size = unitary_buff_size * s->ptime / 20; mblk_t *im; uint8_t tmp[OUT_MAX_SIZE]; int16_t samples[buff_size]; while ((im = ms_queue_get(f->inputs[0])) != NULL) { ms_bufferizer_put(s->mb, im); } while (ms_bufferizer_get_avail(s->mb) >= buff_size) { mblk_t *om = allocb(OUT_MAX_SIZE * buff_size / unitary_buff_size + 1, 0); ms_bufferizer_read(s->mb, (uint8_t*) samples, buff_size); *om->b_wptr = 0xf0; uint8_t *tocs = om->b_wptr++; om->b_wptr += buff_size / unitary_buff_size; int offset; for (offset = 0; offset < buff_size; offset += unitary_buff_size) { int ret = Encoder_Interface_Encode(s->enc, s->mode, &samples[offset / sizeof (int16_t)], tmp, s->dtx); if (ret <= 0 || ret > 32) { ms_warning("Encoder returned %i", ret); freemsg(om); continue; } memcpy(om->b_wptr, &tmp[1], ret - 1); om->b_wptr += ret - 1; *(++tocs) = tmp[0] | 0x80; // Not last payload } *tocs &= 0x7F; // last payload mblk_set_timestamp_info(om, s->ts); ms_queue_put(f->outputs[0], om); s->ts += buff_size / sizeof (int16_t)/*sizeof(buf)/2*/; } }
static void enc_process(MSFilter *f){ EncState *s=(EncState*)f->data; mblk_t *im,*om; int size=s->nsamples*2; int16_t samples[1610]; /* BLOCKL_MAX * 7 is the largest size for ptime == 140 */ float samples2[BLOCKL_MAX]; int i; int frame_per_packet=1; if (s->ptime>=20 && s->ms_per_frame>0 && s->ptime%s->ms_per_frame==0) { frame_per_packet = s->ptime/s->ms_per_frame; } if (frame_per_packet<=0) frame_per_packet=1; if (frame_per_packet>7) /* 7*20 == 140 ms max */ frame_per_packet=7; while((im=ms_queue_get(f->inputs[0]))!=NULL){ ms_bufferizer_put(s->bufferizer,im); } while(ms_bufferizer_read(s->bufferizer,(uint8_t*)samples,size*frame_per_packet)==(size*frame_per_packet)){ int k; om=allocb(s->nbytes*frame_per_packet,0); for (k=0;k<frame_per_packet;k++) { for (i=0;i<s->nsamples;i++){ samples2[i]=samples[i+(s->nsamples*k)]; } iLBC_encode((uint8_t*)om->b_wptr,samples2,&s->ilbc_enc); om->b_wptr+=s->nbytes; } s->ts+=s->nsamples*frame_per_packet; mblk_set_timestamp_info(om,s->ts); ms_bufferizer_fill_current_metas(s->bufferizer,om); ms_queue_put(f->outputs[0],om); } }
static void enc_process(MSFilter *f){ EncState *s=(EncState*)f->data; mblk_t *im; int size = BV16_CODE_SIZE *2; int i,frames; uint8_t buf[BV16_FRAME_SIZE * 2 * 4]; while((im=ms_queue_get(f->inputs[0]))!=NULL){ ms_bufferizer_put(s->bufferizer,im); } while(ms_bufferizer_read(s->bufferizer,(uint8_t*)buf,sizeof(buf))==sizeof(buf)) { mblk_t *om=allocb(BV16_CODE_SIZE*8,0); uint8_t *in_buf = (uint8_t *)buf; frames = sizeof(buf)/(BV16_FRAME_SIZE * 2); for(i=0;i<frames;i++) { //BV16_Encode(&s->ebs, &s->cs,(short *)in_buf); //BV16_BitPack((unsigned short *)om->b_wptr, &s->ebs); bv16_encode(s->enc, (uint8_t *)om->b_wptr, (int16_t *) in_buf, BV16_FRAME_SIZE); //ms_error("BV16_Encode frames %d",i); in_buf += 80; om->b_wptr += 10; } mblk_set_timestamp_info(om,s->ts); ms_queue_put(f->outputs[0],om); s->ts+=sizeof(buf)/2; } }
static void alaw_enc_process(MSFilter *obj){ AlawEncData *dt=(AlawEncData*)obj->data; MSBufferizer *bz=dt->bz; uint8_t buffer[2240]; int frame_per_packet=2; int size_of_pcm=320; mblk_t *m; if (dt->ptime>=10) { frame_per_packet = dt->ptime/10; } if (frame_per_packet<=0) frame_per_packet=1; if (frame_per_packet>14) /* 7*20 == 140 ms max */ frame_per_packet=14; size_of_pcm = 160*frame_per_packet; /* ex: for 20ms -> 160*2==320 */ while((m=ms_queue_get(obj->inputs[0]))!=NULL){ ms_bufferizer_put(bz,m); } while (ms_bufferizer_read(bz,buffer,size_of_pcm)==size_of_pcm){ mblk_t *o=allocb(size_of_pcm/2,0); int i; for (i=0;i<size_of_pcm/2;i++){ *o->b_wptr=Snack_Lin2Alaw(((int16_t*)buffer)[i]); o->b_wptr++; } ms_bufferizer_fill_current_metas(bz, o); mblk_set_timestamp_info(o,dt->ts); dt->ts+=size_of_pcm/2; ms_queue_put(obj->outputs[0],o); } }
/* inputs[0]= reference signal from far end (sent to soundcard) * inputs[1]= near speech & echo signal (read from soundcard) * outputs[0]= is a copy of inputs[0] to be sent to soundcard * outputs[1]= near end speech, echo removed - towards far end */ static void speex_ec_process(MSFilter *f){ SpeexECState *s=(SpeexECState*)f->data; int nbytes=s->framesize*2; mblk_t *refm; uint8_t *ref,*echo; if (s->bypass_mode) { while((refm=ms_queue_get(f->inputs[0]))!=NULL){ ms_queue_put(f->outputs[0],refm); } while((refm=ms_queue_get(f->inputs[1]))!=NULL){ ms_queue_put(f->outputs[1],refm); } return; } if (f->inputs[0]!=NULL){ if (s->echostarted){ while((refm=ms_queue_get(f->inputs[0]))!=NULL){ refm=audio_flow_controller_process(&s->afc,refm); if (refm){ mblk_t *cp=dupmsg(refm); ms_bufferizer_put(&s->delayed_ref,cp); ms_bufferizer_put(&s->ref,refm); } } }else{ ms_warning("Getting reference signal but no echo to synchronize on."); ms_queue_flush(f->inputs[0]); } } ms_bufferizer_put_from_queue(&s->echo,f->inputs[1]); ref=(uint8_t*)alloca(nbytes); echo=(uint8_t*)alloca(nbytes); while (ms_bufferizer_read(&s->echo,echo,nbytes)==nbytes){ mblk_t *oecho=allocb(nbytes,0); int avail; int avail_samples; if (!s->echostarted) s->echostarted=TRUE; if ((avail=ms_bufferizer_get_avail(&s->delayed_ref))<((s->nominal_ref_samples*2)+nbytes)){ /*we don't have enough to read in a reference signal buffer, inject silence instead*/ avail=nbytes; refm=allocb(nbytes,0); memset(refm->b_wptr,0,nbytes); refm->b_wptr+=nbytes; ms_bufferizer_put(&s->delayed_ref,refm); ms_queue_put(f->outputs[0],dupmsg(refm)); if (!s->using_zeroes){ ms_warning("Not enough ref samples, using zeroes"); s->using_zeroes=TRUE; } }else{ if (s->using_zeroes){ ms_message("Samples are back."); s->using_zeroes=FALSE; } /* read from our no-delay buffer and output */ refm=allocb(nbytes,0); if (ms_bufferizer_read(&s->ref,refm->b_wptr,nbytes)==0){ ms_fatal("Should never happen"); } refm->b_wptr+=nbytes; ms_queue_put(f->outputs[0],refm); } /*now read a valid buffer of delayed ref samples*/ if (ms_bufferizer_read(&s->delayed_ref,ref,nbytes)==0){ ms_fatal("Should never happen"); } avail-=nbytes; avail_samples=avail/2; /*ms_message("avail=%i",avail_samples);*/ if (avail_samples<s->min_ref_samples || s->min_ref_samples==-1){ s->min_ref_samples=avail_samples; } #ifdef EC_DUMP if (s->reffile) fwrite(ref,nbytes,1,s->reffile); if (s->echofile) fwrite(echo,nbytes,1,s->echofile); #endif speex_echo_cancellation(s->ecstate,(short*)echo,(short*)ref,(short*)oecho->b_wptr); speex_preprocess_run(s->den, (short*)oecho->b_wptr); #ifdef EC_DUMP if (s->cleanfile) fwrite(oecho->b_wptr,nbytes,1,s->cleanfile); #endif oecho->b_wptr+=nbytes; ms_queue_put(f->outputs[1],oecho); } /*verify our ref buffer does not become too big, meaning that we are receiving more samples than we are sending*/ if ((((uint32_t)(f->ticker->time - s->flow_control_time)) >= flow_control_interval_ms) && (s->min_ref_samples != -1)) { int diff=s->min_ref_samples-s->nominal_ref_samples; if (diff>(nbytes/2)){ int purge=diff-(nbytes/2); ms_warning("echo canceller: we are accumulating too much reference signal, need to throw out %i samples",purge); audio_flow_controller_set_target(&s->afc,purge,(flow_control_interval_ms*s->samplerate)/1000); } s->min_ref_samples=-1; s->flow_control_time = f->ticker->time; } }
static void ms_opus_enc_process(MSFilter *f) { OpusEncData *d = (OpusEncData *)f->data; mblk_t *im; mblk_t *om = NULL; int i; int frameNumber, packet_size; uint8_t *signalFrameBuffer = NULL; uint8_t *codedFrameBuffer[MAX_INPUT_FRAMES]; OpusRepacketizer *rp = opus_repacketizer_create(); opus_int32 ret = 0; opus_int32 totalLength = 0; int frame_size = d->samplerate * FRAME_LENGTH / 1000; /* in samples */ // lock the access while getting ptime ms_filter_lock(f); frameNumber = d->ptime/FRAME_LENGTH; /* encode 20ms frames, ptime is a multiple of 20ms */ packet_size = d->samplerate * d->ptime / 1000; /* in samples */ ms_filter_unlock(f); while ((im = ms_queue_get(f->inputs[0])) != NULL) { ms_bufferizer_put(d->bufferizer, im); } for (i=0; i<MAX_INPUT_FRAMES; i++) { codedFrameBuffer[i]=NULL; } while (ms_bufferizer_get_avail(d->bufferizer) >= (d->channels * packet_size * SIGNAL_SAMPLE_SIZE)) { totalLength = 0; opus_repacketizer_init(rp); for (i=0; i<frameNumber; i++) { /* encode 20ms by 20ms and repacketize all of them together */ if (!codedFrameBuffer[i]) codedFrameBuffer[i] = ms_malloc(MAX_BYTES_PER_FRAME); /* the repacketizer need the pointer to packet to remain valid, so we shall have a buffer for each coded frame */ if (!signalFrameBuffer) signalFrameBuffer = ms_malloc(frame_size * SIGNAL_SAMPLE_SIZE * d->channels); ms_bufferizer_read(d->bufferizer, signalFrameBuffer, frame_size * SIGNAL_SAMPLE_SIZE * d->channels); ret = opus_encode(d->state, (opus_int16 *)signalFrameBuffer, frame_size, codedFrameBuffer[i], MAX_BYTES_PER_FRAME); if (ret < 0) { ms_error("Opus encoder error: %s", opus_strerror(ret)); break; } if (ret > 0) { int err = opus_repacketizer_cat(rp, codedFrameBuffer[i], ret); /* add the encoded frame into the current packet */ if (err != OPUS_OK) { ms_error("Opus repacketizer error: %s", opus_strerror(err)); break; } totalLength += ret; } } if (ret > 0) { om = allocb(totalLength+frameNumber + 1, 0); /* opus repacktizer API: allocate at leat number of frame + size of all data added before */ ret = opus_repacketizer_out(rp, om->b_wptr, totalLength+frameNumber); om->b_wptr += ret; mblk_set_timestamp_info(om, d->ts); ms_queue_put(f->outputs[0], om); d->ts += packet_size*48000/d->samplerate; /* RFC payload RTP opus 03 - section 4: RTP timestamp multiplier : WARNING works only with sr at 48000 */ ret = 0; } } opus_repacketizer_destroy(rp); if (signalFrameBuffer != NULL) { ms_free(signalFrameBuffer); } for (i=0; i<frameNumber; i++) { if (codedFrameBuffer[i] != NULL) { ms_free(codedFrameBuffer[i]); } } }
static void ca_put(CAData *d, mblk_t *m){ ms_mutex_lock(&d->mutex); ms_bufferizer_put(d->bufferizer,m); ms_mutex_unlock(&d->mutex); }
static void * alsa_write_thread(void *p){ AlsaReadData *ad=(AlsaReadData*)p; int samples=(160*ad->rate)/8000; int err; int count=0; mblk_t *om=NULL; struct timeval timeout; if (ad->handle==NULL && ad->pcmdev!=NULL){ ad->handle=alsa_open_r(ad->pcmdev,16,ad->nchannels==2,ad->rate); } if (ad->handle==NULL) return NULL; while (ad->read_started) { count = alsa_can_read(ad->handle,samples); if (count==24) { /* keep this value for this driver */ } else if (count<=0) { count = samples; } else if (count>0) { //ms_warning("%i count", count); //count = samples; } int size=count*2; om=allocb(size,0); if ((err=alsa_read(ad->handle,om->b_wptr,count))<=0) { ms_warning("nothing to read"); //ms_warning("Fail to read samples %i", count); continue; } //ms_warning(" read %i", err); size=err*2; om->b_wptr+=size; ms_mutex_lock(&ad->mutex); ms_bufferizer_put(ad->bufferizer,om); ms_mutex_unlock(&ad->mutex); if (count==24) { timeout.tv_sec = 0; timeout.tv_usec = 2000; select(0, 0, NULL, NULL, &timeout ); } else { /* select will be less active than locking on "read" */ timeout.tv_sec = 0; timeout.tv_usec = 5000; select(0, 0, NULL, NULL, &timeout ); } } if (ad->handle!=NULL) snd_pcm_close(ad->handle); ad->handle=NULL; return NULL; }
static void au_write_put(AUWrite *d, mblk_t *m) { ms_mutex_lock(&d->common.mutex); ms_bufferizer_put(d->buffer,m); ms_mutex_unlock(&d->common.mutex); }
static void oss_put(MSSndCard *card, mblk_t *m){ OssData *d=(OssData*)card->data; ms_mutex_lock(&d->mutex); ms_bufferizer_put(d->bufferizer,m); ms_mutex_unlock(&d->mutex); }
static void winsnd_put(MSSndCard *card, mblk_t *m){ WinSndData *d=(WinSndData*)card->data; ms_mutex_lock(&d->mutex); ms_bufferizer_put(d->bufferizer,m); ms_mutex_unlock(&d->mutex); }