int speex_aec_init(AVFilterContext *avf) { SpeexAecContext *s = avf->priv_data; if (avf->echo_tail <= 0 || avf->echo_tail > 64000) { av_log(avf, AV_LOG_ERROR, "Speex aec error: echo tail is invalid (%d)\n", avf->echo_tail); return -1; } avf->specific = av_mallocz(sizeof(float) * avf->avctx->frame_size); avf->out = av_mallocz(sizeof(short) * avf->avctx->frame_size); avf->extra = av_mallocz(sizeof(short) * avf->avctx->frame_size); if (!avf->specific || !avf->out || !avf->extra) { av_log(avf, AV_LOG_ERROR, "Speex error: out of memory\n"); return -1; } s->aec = speex_echo_state_init(avf->avctx->frame_size, avf->echo_tail); av_log(avf, AV_LOG_INFO, "Speex aec: using echo cancellation (tail length: %d samples)\n", avf->echo_tail); #ifdef DUMP_PCM s->f=fopen("avcodec.speexaec.pcm","wb"); #endif // DUMP_PCM return 0; };
int main(int argc, char **argv) { int echo_fd, ref_fd, e_fd; spx_int32_t noise[NN+1]; short echo_buf[NN], ref_buf[NN], e_buf[NN]; SpeexEchoState *st; SpeexPreprocessState *den; if (argc != 4) { fprintf (stderr, "testecho mic_signal.sw speaker_signal.sw output.sw\n"); exit(1); } echo_fd = open (argv[2], O_RDONLY); ref_fd = open (argv[1], O_RDONLY); e_fd = open (argv[3], O_WRONLY | O_CREAT | O_TRUNC, 0644); st = speex_echo_state_init(NN, 8*NN); den = speex_preprocess_state_init(NN, 8000); while (read(ref_fd, ref_buf, NN*2)) { read(echo_fd, echo_buf, NN*2); speex_echo_cancel(st, ref_buf, echo_buf, e_buf, noise); /*speex_preprocess(den, e_buf, noise);*/ write(e_fd, e_buf, NN*2); } speex_echo_state_destroy(st); speex_preprocess_state_destroy(den); close(e_fd); close(echo_fd); close(ref_fd); return 0; }
int main() { int echo_fd, ref_fd, e_fd; float noise[NN+1]; short echo_buf[NN], ref_buf[NN], e_buf[NN]; SpeexEchoState *st; SpeexPreprocessState *den; echo_fd = open ("play.sw", O_RDONLY); ref_fd = open ("rec.sw", O_RDONLY); e_fd = open ("echo.sw", O_WRONLY | O_CREAT | O_TRUNC, 0644); st = speex_echo_state_init(NN, 8*NN); den = speex_preprocess_state_init(NN, 8000); while (read(ref_fd, ref_buf, NN*2)) { read(echo_fd, echo_buf, NN*2); speex_echo_cancel(st, ref_buf, echo_buf, e_buf, noise); speex_preprocess(den, e_buf, noise); write(e_fd, e_buf, NN*2); } speex_echo_state_destroy(st); speex_preprocess_state_destroy(den); close(e_fd); close(echo_fd); close(ref_fd); return 0; }
void CSpeexEC::Init(int frame_size, int filter_length, int sampling_rate) { Reset(); if (frame_size<=0 || filter_length<=0 || sampling_rate<=0) { m_nFrameSize =160; m_nFilterLen = 160*8; m_nSampleRate = 8000; } else { m_nFrameSize =frame_size; m_nFilterLen = filter_length; m_nSampleRate = sampling_rate; } m_pState = speex_echo_state_init(m_nFrameSize, m_nFilterLen); m_pPreprocessorState = speex_preprocess_state_init(m_nFrameSize, m_nSampleRate); m_pfNoise = new int[m_nFrameSize+1]; m_bHasInit = true; speex_echo_ctl(m_pState, SPEEX_ECHO_SET_SAMPLING_RATE, &m_nSampleRate); speex_preprocess_ctl(m_pPreprocessorState, SPEEX_PREPROCESS_SET_ECHO_STATE, m_pState); }
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 }
/* * Create the echo canceller. */ pjs_echo_canceller::pjs_echo_canceller(pj_pool_t *pool_, unsigned clock_rate, unsigned samples_per_frame_, unsigned tail_ms, unsigned latency_ms, unsigned options) { int sampling_rate = clock_rate; unsigned ptime, lat_cnt; unsigned delay_buf_opt = 0; lat_ready = PJ_FALSE; /* Create new pool and instantiate and init the EC */ pool = pj_pool_create(pool_->factory, "ec%p", 256, 256, NULL); lock = new PPJ_SemaphoreLock(pool, NULL, 1, 1); samples_per_frame = samples_per_frame_; frm_buf = (pj_int16_t*) pj_pool_alloc(pool, samples_per_frame << 1); state = speex_echo_state_init(samples_per_frame, clock_rate * tail_ms / 1000); speex_echo_ctl(state, SPEEX_ECHO_SET_SAMPLING_RATE, &sampling_rate); preprocess = speex_preprocess_state_init(samples_per_frame, clock_rate); tmp_frame = (pj_int16_t*) pj_pool_zalloc(pool, 2*samples_per_frame); speex_preprocess_ctl(preprocess, SPEEX_PREPROCESS_SET_ECHO_STATE, state); pj_list_init(&lat_buf); pj_list_init(&lat_free); PJ_LOG(5, (THIS_FILE, "Creating echo canceler")); /* Create latency buffers */ ptime = samples_per_frame * 1000 / clock_rate; if (latency_ms < ptime) { /* Give at least one frame delay to simplify programming */ latency_ms = ptime; } lat_cnt = latency_ms / ptime; while (lat_cnt--) { struct frame *frm; frm = (struct frame*) pj_pool_alloc(pool, (samples_per_frame << 1) + sizeof(struct frame)); pj_list_push_back(&lat_free, frm); } /* Create delay buffer to compensate drifts */ if (options & PJMEDIA_ECHO_USE_SIMPLE_FIFO) delay_buf_opt |= PJMEDIA_DELAY_BUF_SIMPLE_FIFO; pjmedia_delay_buf_create(pool, NULL, clock_rate, samples_per_frame, 1, (PJMEDIA_SOUND_BUFFER_COUNT + 1) * ptime, delay_buf_opt, &delay_buf); PJ_LOG(4, (THIS_FILE, "ECHO canceller created, clock_rate=%d, channel=%d, " "samples per frame=%d, tail length=%d ms, " "latency=%d ms", clock_rate, 1, samples_per_frame, tail_ms, latency_ms)); }
JNIEXPORT void JNICALL Java_com_pullmi_shanghai_TalkActivity_speex_1EchoCanceller_1open (JNIEnv *env, jobject jobj, jint jSampleRate, jint jBufSize, jint jTotalSize) { //init int sampleRate = jSampleRate; st = speex_echo_state_init(jBufSize, jTotalSize); den = speex_preprocess_state_init(jBufSize, sampleRate); speex_echo_ctl(st, SPEEX_ECHO_SET_SAMPLING_RATE, &sampleRate); speex_preprocess_ctl(den, SPEEX_PREPROCESS_SET_ECHO_STATE, st); }
RTC::ReturnCode_t EchoCanceler::onActivated(RTC::UniqueId ec_id) { RTC_DEBUG(("onActivated start")); is_active = true; BufferClr(); if ( mp_sest == NULL ) { int sampleRate = 16000; mp_sest = speex_echo_state_init(ECHOLEN, sampleRate * 2); speex_echo_ctl(mp_sest, SPEEX_ECHO_SET_SAMPLING_RATE, &sampleRate); } RTC_DEBUG(("onActivated finish")); return RTC::RTC_OK; }
static int aec_alloc(struct speex_st **stp, void **ctx, struct aufilt_prm *prm) { struct speex_st *st; uint32_t sampc; int err, tmp, fl; if (!stp || !ctx || !prm) return EINVAL; if (*ctx) { *stp = mem_ref(*ctx); return 0; } st = mem_zalloc(sizeof(*st), speex_aec_destructor); if (!st) return ENOMEM; sampc = prm->srate * prm->ch * prm->ptime / 1000; st->out = mem_alloc(2 * sampc, NULL); if (!st->out) { err = ENOMEM; goto out; } /* Echo canceller with 200 ms tail length */ fl = 10 * sampc; st->state = speex_echo_state_init(sampc, fl); if (!st->state) { err = ENOMEM; goto out; } tmp = prm->srate; err = speex_echo_ctl(st->state, SPEEX_ECHO_SET_SAMPLING_RATE, &tmp); if (err < 0) { warning("speex_aec: speex_echo_ctl: err=%d\n", err); } info("speex_aec: Speex AEC loaded: srate = %uHz\n", prm->srate); out: if (err) mem_deref(st); else *ctx = *stp = st; return err; }
extern "C" JNIEXPORT void Java_com_haitou_xiaoyoupai_imservice_support_audio_Speex_initEcho( JNIEnv *env, jobject jobj, jint frame_size, jint filter_length) { if (aec_status == AEC_OPENED) return; aec_status = AEC_OPENED; int frm_size; int f_length; frm_size = frame_size; f_length = filter_length; echoState = speex_echo_state_init(frame_size, filter_length); den = speex_preprocess_state_init(frame_size, sampleRate); speex_echo_ctl(echoState, SPEEX_ECHO_SET_SAMPLING_RATE, &sampleRate); speex_preprocess_ctl(den, SPEEX_PREPROCESS_SET_ECHO_STATE, echoState); }
void sound::start(){ const PaDeviceInfo * info = Pa_GetDeviceInfo(indexInputDevice); inputStreamParameters.device = indexInputDevice; inputStreamParameters.channelCount = 1; inputStreamParameters.hostApiSpecificStreamInfo = 0; inputStreamParameters.sampleFormat = paInt16; inputStreamParameters.suggestedLatency = info->defaultLowInputLatency; PaError err = Pa_OpenStream(&input, &inputStreamParameters, 0, info->defaultSampleRate, BUFF_LONG, paNoFlag, sound::inputcallback, this); if (err != paNoError){ throw std::exception("open stream err=%d", err); } err = Pa_StartStream(input); if (err != paNoError){ throw std::exception("start stream err=%d", err); } speexppstate = speex_preprocess_state_init(BUFF_LONG*inputStreamParameters.channelCount, (int)info->defaultSampleRate); spx_int32_t on = 1; speex_preprocess_ctl(speexppstate, SPEEX_PREPROCESS_SET_AGC, &on); float agcLevel = 24000; speex_preprocess_ctl(speexppstate, SPEEX_PREPROCESS_SET_AGC_LEVEL, &agcLevel); int denoise = 1; speex_preprocess_ctl(speexppstate, SPEEX_PREPROCESS_SET_DENOISE, &denoise); //½µÔë int noiseSuppress = -25; speex_preprocess_ctl(speexppstate, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, &noiseSuppress); //ÉèÖÃÔëÉùµÄdB speexechostate = speex_echo_state_init(BUFF_LONG*inputStreamParameters.channelCount, BUFF_LONG*inputStreamParameters.channelCount); info = Pa_GetDeviceInfo(indexOutputDevice); outputStreamParameters.device = indexOutputDevice; outputStreamParameters.channelCount = 1; outputStreamParameters.hostApiSpecificStreamInfo = 0; outputStreamParameters.sampleFormat = paInt16; outputStreamParameters.suggestedLatency = info->defaultLowOutputLatency; err = Pa_OpenStream(&output, 0, &outputStreamParameters, info->defaultSampleRate, BUFF_LONG, paNoFlag, sound::outputcallback, this); if (err != paNoError){ throw std::exception("open stream err=%d", err); } err = Pa_StartStream(output); if (err != paNoError){ throw std::exception("start stream err=%d", err); } }
int anti_echo_speex16(int16_t * buf, int16_t * aebuf, size_t len, struct roar_audio_info * info) { static SpeexEchoState * state = NULL; size_t samples = info->rate / TIMEDIV; static int16_t * obuf = NULL; if ( info->channels != 1 ) return -1; if (len != samples) return -1; ROAR_DBG("anti_echo_speex16(*) = ?"); if ( state == NULL ) { if ( (state = speex_echo_state_init(samples, 100*samples)) == NULL ) return -1; // todo: set sample rate. } ROAR_DBG("anti_echo_speex16(*) = ?"); if ( obuf == NULL ) { if ( (obuf = malloc(2*samples)) == NULL ) return -1; } ROAR_DBG("anti_echo_speex16(*) = ?"); /* speex_echo_cancellation(state, buf, aebuf, obuf); */ speex_echo_cancel(state, buf, aebuf, obuf, NULL); memcpy(buf, obuf, 2*samples); ROAR_DBG("anti_echo_speex16(*) = 0"); return 0; }
int main(int argc, char **argv) { FILE *echo_fd, *ref_fd, *e_fd; short echo_buf[NN], ref_buf[NN], e_buf[NN]; SpeexEchoState *st; SpeexPreprocessState *den; int sampleRate = 8000; if (argc != 4) { fprintf(stderr, "testecho mic_signal.sw speaker_signal.sw output.sw\n"); exit(1); } echo_fd = fopen(argv[2], "rb"); ref_fd = fopen(argv[1], "rb"); e_fd = fopen(argv[3], "wb"); st = speex_echo_state_init(NN, TAIL); den = speex_preprocess_state_init(NN, sampleRate); speex_echo_ctl(st, SPEEX_ECHO_SET_SAMPLING_RATE, &sampleRate); speex_preprocess_ctl(den, SPEEX_PREPROCESS_SET_ECHO_STATE, st); while (!feof(ref_fd) && !feof(echo_fd)) { fread(ref_buf, sizeof(short), NN, ref_fd); fread(echo_buf, sizeof(short), NN, echo_fd); speex_echo_cancellation(st, ref_buf, echo_buf, e_buf); speex_preprocess_run(den, e_buf); fwrite(e_buf, sizeof(short), NN, e_fd); } speex_echo_state_destroy(st); speex_preprocess_state_destroy(den); fclose(e_fd); fclose(echo_fd); fclose(ref_fd); return 0; }
void KotiAEC_init(int16_t frame_size, int32_t sample_freq, AEC_CORE aec_core, int speex_filter_length, int16_t agc_mode, int16_t compression_gain_db, uint8_t limiter_enable, float snd_amplification) { int32_t speex_agc = 0; float speex_agc_level = 24000, speex_agc_level_tmp = 3000; int32_t speex_noise_suppress = -15; aec_core_used = aec_core; output_sound_amplification = snd_amplification; switch(aec_core) { #ifdef WEBRTC_AEC_CORE_ENABLED case WEBRTC_AEC: if(webrtc_aec_pty.webrtc_aec == NULL) { webrtc_aec_pty.frame_size = frame_size; webrtc_aec_pty.sample_freq = sample_freq; webrtc_aec_pty.sndcard_sample_freq = sample_freq; webrtc_aec_pty.sndcard_delay_ms = ((float)speex_filter_length/sample_freq) * 1000; if( WebRtcAec_Create(&webrtc_aec_pty.webrtc_aec) == 0) WebRtcAec_Init(webrtc_aec_pty.webrtc_aec, webrtc_aec_pty.sample_freq, webrtc_aec_pty.sndcard_sample_freq); if( WebRtcNsx_Create((NsxHandle**)&webrtc_aec_pty.webrtc_ns) == 0) { WebRtcNsx_Init((NsxHandle*)webrtc_aec_pty.webrtc_ns, webrtc_aec_pty.sample_freq); WebRtcNsx_set_policy((NsxHandle*)webrtc_aec_pty.webrtc_ns, 1); } if( WebRtcAgc_Create(&webrtc_aec_pty.webrtc_agc) == 0) { WebRtcAgc_Init(webrtc_aec_pty.webrtc_agc, 0, 255, agc_mode/*kAgcModeFixedDigital*/, webrtc_aec_pty.sample_freq); WebRtcAgc_config_t conf = {0, compression_gain_db, limiter_enable}; WebRtcAgc_set_config(webrtc_aec_pty.webrtc_agc, conf); } } else { WebRtcAec_Init(webrtc_aec_pty.webrtc_aec, webrtc_aec_pty.sample_freq, webrtc_aec_pty.sndcard_sample_freq); } break; case WEBRTC_AECM: if(webrtc_aecm_pty.webrtc_aec == NULL) { webrtc_aecm_pty.frame_size = frame_size; webrtc_aecm_pty.sample_freq = sample_freq; webrtc_aecm_pty.sndcard_sample_freq = sample_freq; webrtc_aecm_pty.sndcard_delay_ms = ((float)speex_filter_length/sample_freq) * 1000; // webrtc_aecm_pty.sndcard_delay_ms = speex_filter_length/frame_size; if( WebRtcAecm_Create(&webrtc_aecm_pty.webrtc_aec) == 0) WebRtcAecm_Init(webrtc_aecm_pty.webrtc_aec, webrtc_aecm_pty.sample_freq); if( WebRtcNsx_Create((NsxHandle**)&webrtc_aecm_pty.webrtc_ns) == 0) { WebRtcNsx_Init((NsxHandle*)webrtc_aecm_pty.webrtc_ns, webrtc_aecm_pty.sample_freq); WebRtcNsx_set_policy((NsxHandle*)webrtc_aecm_pty.webrtc_ns, 1); } if( WebRtcAgc_Create(&webrtc_aecm_pty.webrtc_agc) == 0) { WebRtcAgc_Init(webrtc_aecm_pty.webrtc_agc, 0, 255, agc_mode/*kAgcModeFixedDigital*/, webrtc_aecm_pty.sample_freq); WebRtcAgc_config_t conf = {0, compression_gain_db, limiter_enable}; WebRtcAgc_set_config(webrtc_aecm_pty.webrtc_agc, conf); } } break; #endif case SPEEX_AEC: default: #ifdef OLD_SPEEX_AEC if(speex_aec_pty.speex_echo_state == NULL && speex_aec_pty.speex_preprocess_state == NULL) { speex_aec_pty.frame_size = frame_size; speex_aec_pty.sample_freq = sample_freq; speex_aec_pty.filter_length = speex_filter_length; if(speex_aec_pty.filter_length < frame_size) speex_aec_pty.filter_length = frame_size*FILTER_LENGTH_MULTIPLE_OF_FRAME_SIZE; speex_aec_pty.speex_echo_state = speex_echo_state_init(frame_size, speex_aec_pty.filter_length); speex_aec_pty.speex_preprocess_state = speex_preprocess_state_init(frame_size, sample_freq); speex_echo_ctl((SpeexEchoState*)speex_aec_pty.speex_echo_state, SPEEX_ECHO_SET_SAMPLING_RATE, &speex_aec_pty.sample_freq); speex_aec_pty.nosie = (int32_t*) malloc( (frame_size+1) * sizeof(int32_t) ); } #else if(speex_aec_pty.speex_echo_state == NULL && speex_aec_pty.speex_preprocess_state == NULL) { speex_aec_pty.frame_size = frame_size; speex_aec_pty.sample_freq = sample_freq; speex_aec_pty.filter_length = speex_filter_length; if(speex_aec_pty.filter_length < frame_size) speex_aec_pty.filter_length = frame_size*FILTER_LENGTH_MULTIPLE_OF_FRAME_SIZE; speex_aec_pty.speex_echo_state = speex_echo_state_init(frame_size, speex_aec_pty.filter_length); speex_aec_pty.speex_preprocess_state = speex_preprocess_state_init(frame_size, sample_freq); speex_echo_ctl((SpeexEchoState*)speex_aec_pty.speex_echo_state, SPEEX_ECHO_SET_SAMPLING_RATE, &speex_aec_pty.sample_freq); speex_preprocess_ctl((SpeexPreprocessState*)speex_aec_pty.speex_preprocess_state, SPEEX_PREPROCESS_SET_ECHO_STATE, speex_aec_pty.speex_echo_state); speex_aec_pty.nosie = (int32_t*) malloc( (frame_size+1) * sizeof(int32_t) ); speex_preprocess_ctl((SpeexPreprocessState*)speex_aec_pty.speex_preprocess_state, SPEEX_PREPROCESS_SET_AGC, &speex_agc); speex_preprocess_ctl((SpeexPreprocessState*)speex_aec_pty.speex_preprocess_state, SPEEX_PREPROCESS_SET_AGC_LEVEL, &speex_agc_level); speex_preprocess_ctl((SpeexPreprocessState*)speex_aec_pty.speex_preprocess_state, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, &speex_noise_suppress); speex_aec_pty.speex_preprocess_state_tmp = speex_preprocess_state_init(frame_size, sample_freq); speex_preprocess_ctl((SpeexPreprocessState*)speex_aec_pty.speex_preprocess_state_tmp, SPEEX_PREPROCESS_SET_AGC, &speex_agc); speex_preprocess_ctl((SpeexPreprocessState*)speex_aec_pty.speex_preprocess_state_tmp, SPEEX_PREPROCESS_SET_AGC_LEVEL, &speex_agc_level_tmp); speex_preprocess_ctl((SpeexPreprocessState*)speex_aec_pty.speex_preprocess_state_tmp, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, &speex_noise_suppress); // int32_t speex_vad = 1; // int32_t speex_vad_prob_start = 80; // int32_t speex_vad_prob_continue = 65; // speex_preprocess_ctl((SpeexPreprocessState*)speex_aec_pty.speex_preprocess_state, SPEEX_PREPROCESS_SET_VAD, &speex_vad); // speex_preprocess_ctl((SpeexPreprocessState*)speex_aec_pty.speex_preprocess_state, SPEEX_PREPROCESS_SET_PROB_START, // &speex_vad_prob_start); // speex_preprocess_ctl((SpeexPreprocessState*)speex_aec_pty.speex_preprocess_state, SPEEX_PREPROCESS_SET_PROB_CONTINUE, // &speex_vad_prob_continue); // int32_t tmp = -1; float tmp1 = 0.0f; // speex_preprocess_ctl((SpeexPreprocessState*)speex_aec_pty.speex_preprocess_state, SPEEX_PREPROCESS_GET_DENOISE, &tmp); // printf("SPEEX_PREPROCESS_GET_DENOISE: %d\n", tmp); // speex_preprocess_ctl((SpeexPreprocessState*)speex_aec_pty.speex_preprocess_state, SPEEX_PREPROCESS_GET_NOISE_SUPPRESS, &tmp); // printf("SPEEX_PREPROCESS_GET_NOISE_SUPPRESS: %d\n", tmp); // speex_preprocess_ctl((SpeexPreprocessState*)speex_aec_pty.speex_preprocess_state, SPEEX_PREPROCESS_GET_AGC, &tmp); // printf("SPEEX_PREPROCESS_GET_AGC: %d\n", tmp); // speex_preprocess_ctl((SpeexPreprocessState*)speex_aec_pty.speex_preprocess_state, SPEEX_PREPROCESS_GET_VAD, &tmp); // printf("SPEEX_PREPROCESS_GET_VAD: %d\n", tmp); // speex_preprocess_ctl((SpeexPreprocessState*)speex_aec_pty.speex_preprocess_state, SPEEX_PREPROCESS_GET_PROB_START, &tmp); // printf("SPEEX_PREPROCESS_GET_PROB_START: %d\n", tmp); // speex_preprocess_ctl((SpeexPreprocessState*)speex_aec_pty.speex_preprocess_state, SPEEX_PREPROCESS_GET_PROB_CONTINUE, &tmp); // printf("SPEEX_PREPROCESS_GET_PROB_CONTINUE: %d\n", tmp); // speex_preprocess_ctl((SpeexPreprocessState*)speex_aec_pty.speex_preprocess_state, SPEEX_PREPROCESS_GET_AGC_LEVEL, &tmp1); // printf("SPEEX_PREPROCESS_GET_AGC_LEVEL: %f\n", tmp1); // speex_preprocess_ctl((SpeexPreprocessState*)speex_aec_pty.speex_preprocess_state, SPEEX_PREPROCESS_GET_AGC_DECREMENT, &tmp); // printf("SPEEX_PREPROCESS_GET_AGC_DECREMENT: %d\n", tmp); // speex_preprocess_ctl((SpeexPreprocessState*)speex_aec_pty.speex_preprocess_state, SPEEX_PREPROCESS_GET_AGC_INCREMENT, &tmp); // printf("SPEEX_PREPROCESS_GET_AGC_INCREMENT: %d\n", tmp); // speex_preprocess_ctl((SpeexPreprocessState*)speex_aec_pty.speex_preprocess_state, SPEEX_PREPROCESS_GET_AGC_MAX_GAIN, &tmp); // printf("SPEEX_PREPROCESS_GET_AGC_MAX_GAIN: %d\n", tmp); // speex_preprocess_ctl((SpeexPreprocessState*)speex_aec_pty.speex_preprocess_state, SPEEX_PREPROCESS_GET_AGC_GAIN, &tmp); // printf("SPEEX_PREPROCESS_GET_AGC_GAIN: %d\n", tmp); // speex_preprocess_ctl((SpeexPreprocessState*)speex_aec_pty.speex_preprocess_state, SPEEX_PREPROCESS_GET_AGC_TARGET, &tmp); // printf("SPEEX_PREPROCESS_GET_AGC_TARGET: %d\n", tmp); // speex_preprocess_ctl((SpeexPreprocessState*)speex_aec_pty.speex_preprocess_state, SPEEX_PREPROCESS_GET_AGC_LOUDNESS, &tmp); // printf("SPEEX_PREPROCESS_GET_AGC_LOUDNESS: %d\n", tmp); // speex_preprocess_ctl((SpeexPreprocessState*)speex_aec_pty.speex_preprocess_state, SPEEX_PREPROCESS_GET_ECHO_SUPPRESS, &tmp); // printf("SPEEX_PREPROCESS_GET_ECHO_SUPPRESS: %d\n", tmp); // speex_preprocess_ctl((SpeexPreprocessState*)speex_aec_pty.speex_preprocess_state, SPEEX_PREPROCESS_GET_ECHO_SUPPRESS_ACTIVE, &tmp); // printf("SPEEX_PREPROCESS_GET_ECHO_SUPPRESS_ACTIVE: %d\n", tmp); } #endif break; } }
/* * Create the AEC. */ PJ_DEF(pj_status_t) speex_aec_create(pj_pool_t *pool, unsigned clock_rate, unsigned channel_count, unsigned samples_per_frame, unsigned tail_ms, unsigned options, void **p_echo ) { speex_ec *echo; int sampling_rate; *p_echo = NULL; echo = PJ_POOL_ZALLOC_T(pool, speex_ec); PJ_ASSERT_RETURN(echo != NULL, PJ_ENOMEM); echo->samples_per_frame = samples_per_frame; echo->options = options; #if 0 echo->state = speex_echo_state_init_mc(echo->samples_per_frame, clock_rate * tail_ms / 1000, channel_count, channel_count); #else if (channel_count != 1) { PJ_LOG(2,("echo_speex.c", "Multichannel EC is not supported by this " "echo canceller. It may not work.")); } echo->state = speex_echo_state_init(echo->samples_per_frame, clock_rate * tail_ms / 1000); #endif if (echo->state == NULL) { return PJ_ENOMEM; } /* Set sampling rate */ sampling_rate = clock_rate; speex_echo_ctl(echo->state, SPEEX_ECHO_SET_SAMPLING_RATE, &sampling_rate); echo->preprocess = speex_preprocess_state_init(echo->samples_per_frame, clock_rate); if (echo->preprocess == NULL) { speex_echo_state_destroy(echo->state); return PJ_ENOMEM; } /* Disable all preprocessing, we only want echo cancellation */ #if 0 disabled = 0; enabled = 1; speex_preprocess_ctl(echo->preprocess, SPEEX_PREPROCESS_SET_DENOISE, &enabled); speex_preprocess_ctl(echo->preprocess, SPEEX_PREPROCESS_SET_AGC, &disabled); speex_preprocess_ctl(echo->preprocess, SPEEX_PREPROCESS_SET_VAD, &disabled); speex_preprocess_ctl(echo->preprocess, SPEEX_PREPROCESS_SET_DEREVERB, &enabled); #endif /* Control echo cancellation in the preprocessor */ speex_preprocess_ctl(echo->preprocess, SPEEX_PREPROCESS_SET_ECHO_STATE, echo->state); /* Create temporary frame for echo cancellation */ echo->tmp_frame = (pj_int16_t*) pj_pool_zalloc(pool, 2*samples_per_frame); PJ_ASSERT_RETURN(echo->tmp_frame != NULL, PJ_ENOMEM); /* Done */ *p_echo = echo; return PJ_SUCCESS; }
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(); }
static int tdav_speex_denoise_open(tmedia_denoise_t* self, uint32_t frame_size, uint32_t sampling_rate) { tdav_speex_denoise_t *denoiser = (tdav_speex_denoise_t *)self; float f; int i; if(!denoiser->echo_state && TMEDIA_DENOISE(denoiser)->echo_supp_enabled){ TSK_DEBUG_INFO("Init Aec frame_size[%u] filter_length[%u] SampleRate[%u]", (uint32_t)(frame_size* sizeof(spx_int16_t)),TMEDIA_DENOISE(denoiser)->echo_tail*frame_size,sampling_rate); if((denoiser->echo_state = speex_echo_state_init(frame_size, TMEDIA_DENOISE(denoiser)->echo_tail))){ speex_echo_ctl(denoiser->echo_state, SPEEX_ECHO_SET_SAMPLING_RATE, &sampling_rate); } } if(!denoiser->preprocess_state_record && !denoiser->preprocess_state_playback){ denoiser->frame_size = frame_size; if((denoiser->preprocess_state_record = speex_preprocess_state_init(frame_size, sampling_rate)) && (denoiser->preprocess_state_playback = speex_preprocess_state_init(frame_size, sampling_rate)) ){ // Echo suppression if(denoiser->echo_state){ int echo_supp , echo_supp_active = 0; speex_preprocess_ctl(denoiser->preprocess_state_record, SPEEX_PREPROCESS_SET_ECHO_STATE, denoiser->echo_state); TSK_FREE(denoiser->echo_output_frame); denoiser->echo_output_frame = tsk_calloc(denoiser->frame_size, sizeof(spx_int16_t)); speex_preprocess_ctl(denoiser->preprocess_state_record, SPEEX_PREPROCESS_GET_ECHO_SUPPRESS , &echo_supp ); speex_preprocess_ctl(denoiser->preprocess_state_record, SPEEX_PREPROCESS_GET_ECHO_SUPPRESS_ACTIVE , &echo_supp_active ); TSK_DEBUG_INFO("AEC echo_supp level [%d] echo_supp_active level[%d] ", echo_supp , echo_supp_active); echo_supp = -60 ; echo_supp_active = -60 ; speex_preprocess_ctl(denoiser->preprocess_state_record, SPEEX_PREPROCESS_SET_ECHO_SUPPRESS , &echo_supp ); speex_preprocess_ctl(denoiser->preprocess_state_record, SPEEX_PREPROCESS_SET_ECHO_SUPPRESS_ACTIVE , &echo_supp_active ); // TRACES speex_preprocess_ctl(denoiser->preprocess_state_record, SPEEX_PREPROCESS_GET_ECHO_SUPPRESS , &echo_supp ); speex_preprocess_ctl(denoiser->preprocess_state_record, SPEEX_PREPROCESS_GET_ECHO_SUPPRESS_ACTIVE , &echo_supp_active ); TSK_DEBUG_INFO("New aec echo_supp level [%d] echo_supp_active level[%d] ", echo_supp , echo_supp_active); } // Noise suppression if(TMEDIA_DENOISE(denoiser)->noise_supp_enabled){ TSK_DEBUG_INFO("SpeexDSP: Noise supp enabled"); i = 1; speex_preprocess_ctl(denoiser->preprocess_state_record, SPEEX_PREPROCESS_SET_DENOISE, &i); speex_preprocess_ctl(denoiser->preprocess_state_playback, SPEEX_PREPROCESS_SET_DENOISE, &i); i = TMEDIA_DENOISE(denoiser)->noise_supp_level; speex_preprocess_ctl(denoiser->preprocess_state_record, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, &i); speex_preprocess_ctl(denoiser->preprocess_state_playback, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, &i); } else{ i = 0; speex_preprocess_ctl(denoiser->preprocess_state_record, SPEEX_PREPROCESS_SET_DENOISE, &i); speex_preprocess_ctl(denoiser->preprocess_state_playback, SPEEX_PREPROCESS_SET_DENOISE, &i); } // Automatic gain control if(TMEDIA_DENOISE(denoiser)->agc_enabled){ float agc_level = TMEDIA_DENOISE(denoiser)->agc_level; TSK_DEBUG_INFO("SpeexDSP: AGC enabled"); i = 1; speex_preprocess_ctl(denoiser->preprocess_state_record, SPEEX_PREPROCESS_SET_AGC, &i); speex_preprocess_ctl(denoiser->preprocess_state_record, SPEEX_PREPROCESS_SET_AGC_LEVEL, &agc_level); } else{ i = 0, f = 8000.0f; speex_preprocess_ctl(denoiser->preprocess_state_record, SPEEX_PREPROCESS_SET_AGC, &i); speex_preprocess_ctl(denoiser->preprocess_state_record, SPEEX_PREPROCESS_SET_AGC_LEVEL, &f); } // Voice Activity detection i = TMEDIA_DENOISE(denoiser)->vad_enabled ? 1 : 0; speex_preprocess_ctl(denoiser->preprocess_state_record, SPEEX_PREPROCESS_SET_VAD, &i); return 0; } else{ TSK_DEBUG_ERROR("Failed to create Speex preprocessor state"); return -2; } } return 0; }
int main(int argc, char *argv[]) { int sd, rc, n; int i; struct sockaddr_in cliAddr, remoteAddr; char msg[MAX_MSG]; struct hostent *h; int local_port, remote_port; int nfds; struct pollfd *pfds; SpeexPreprocessState *preprocess; AlsaDevice *audio_dev; int tmp; if (argc != 5) { fprintf(stderr, "wrong options\n"); exit(1); } h = gethostbyname(argv[2]); if(h==NULL) { fprintf(stderr, "%s: unknown host '%s' \n", argv[0], argv[1]); exit(1); } local_port = atoi(argv[3]); remote_port = atoi(argv[4]); printf("%s: sending data to '%s' (IP : %s) \n", argv[0], h->h_name, inet_ntoa(*(struct in_addr *)h->h_addr_list[0])); { remoteAddr.sin_family = h->h_addrtype; memcpy((char *) &remoteAddr.sin_addr.s_addr, h->h_addr_list[0], h->h_length); remoteAddr.sin_port = htons(remote_port); } /* socket creation */ sd=socket(AF_INET, SOCK_DGRAM, 0); if(sd<0) { printf("%s: cannot open socket \n",argv[0]); exit(1); } /* bind any port */ cliAddr.sin_family = AF_INET; cliAddr.sin_addr.s_addr = htonl(INADDR_ANY); cliAddr.sin_port = htons(local_port); rc = bind(sd, (struct sockaddr *) &cliAddr, sizeof(cliAddr)); if(rc<0) { printf("%s: cannot bind port\n", argv[0]); exit(1); } /* Setup audio device */ audio_dev = alsa_device_open(argv[1], SAMPLING_RATE, 1, FRAME_SIZE); /* Setup the encoder and decoder in wideband */ void *enc_state, *dec_state; enc_state = speex_encoder_init(&speex_wb_mode); tmp = 8; speex_encoder_ctl(enc_state, SPEEX_SET_QUALITY, &tmp); tmp = 2; speex_encoder_ctl(enc_state, SPEEX_SET_COMPLEXITY, &tmp); dec_state = speex_decoder_init(&speex_wb_mode); tmp = 1; speex_decoder_ctl(dec_state, SPEEX_SET_ENH, &tmp); SpeexBits enc_bits, dec_bits; speex_bits_init(&enc_bits); speex_bits_init(&dec_bits); struct sched_param param; /*param.sched_priority = 40; */ param.sched_priority = sched_get_priority_min(SCHED_FIFO); if (sched_setscheduler(0,SCHED_FIFO,¶m)) perror("sched_setscheduler"); int send_timestamp = 0; int recv_started=0; /* Setup all file descriptors for poll()ing */ nfds = alsa_device_nfds(audio_dev); pfds = malloc(sizeof(*pfds)*(nfds+1)); alsa_device_getfds(audio_dev, pfds, nfds); pfds[nfds].fd = sd; pfds[nfds].events = POLLIN; /* Setup jitter buffer using decoder */ SpeexJitter jitter; speex_jitter_init(&jitter, dec_state, SAMPLING_RATE); /* Echo canceller with 200 ms tail length */ SpeexEchoState *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); /* Setup preprocessor and associate with echo canceller for residual echo suppression */ preprocess = speex_preprocess_state_init(FRAME_SIZE, SAMPLING_RATE); speex_preprocess_ctl(preprocess, SPEEX_PREPROCESS_SET_ECHO_STATE, echo_state); alsa_device_start(audio_dev); /* Infinite loop on capture, playback and receiving packets */ while (1) { /* Wait for either 1) capture 2) playback 3) socket data */ poll(pfds, nfds+1, -1); /* Received packets */ if (pfds[nfds].revents & POLLIN) { /*fprintf (stderr, "x");*/ n = recv(sd, msg, MAX_MSG, 0); int recv_timestamp = ((int*)msg)[1]; int payload = ((int*)msg)[0]; if ((payload & 0x80000000) == 0) { /* Put content of the packet into the jitter buffer, except for the pseudo-header */ speex_jitter_put(&jitter, msg+8, n-8, recv_timestamp); recv_started = 1; } } /* Ready to play a frame (playback) */ if (alsa_device_playback_ready(audio_dev, pfds, nfds)) { short pcm[FRAME_SIZE]; if (recv_started) { /* Get audio from the jitter buffer */ speex_jitter_get(&jitter, pcm, NULL); } else { for (i=0; i<FRAME_SIZE; i++) pcm[i] = 0; } /* Playback the audio and reset the echo canceller if we got an underrun */ if (alsa_device_write(audio_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_device_capture_ready(audio_dev, pfds, nfds)) { short pcm[FRAME_SIZE], pcm2[FRAME_SIZE]; char outpacket[MAX_MSG]; /* Get audio from the soundcard */ alsa_device_read(audio_dev, pcm, FRAME_SIZE); /* Perform echo cancellation */ speex_echo_capture(echo_state, pcm, pcm2); for (i=0; i<FRAME_SIZE; i++) pcm[i] = pcm2[i]; speex_bits_reset(&enc_bits); /* Apply noise/echo suppression */ speex_preprocess_run(preprocess, pcm); /* Encode */ speex_encode_int(enc_state, pcm, &enc_bits); int packetSize = speex_bits_write(&enc_bits, outpacket+8, MAX_MSG); /* Pseudo header: four null bytes and a 32-bit timestamp */ ((int*)outpacket)[0] = htonl(0); ((int*)outpacket)[1] = send_timestamp; send_timestamp += FRAME_SIZE; rc = sendto(sd, outpacket, packetSize+8, 0, (struct sockaddr *) &remoteAddr, sizeof(remoteAddr)); if(rc<0) { printf("cannot send audio data\n"); close(sd); exit(1); } } } return 0; }
JNIEXPORT jint JNICALL Java_com_speex_Speex_open(JNIEnv *env, jobject obj, jint compression, jint speexModeId) { int tmp; if (codec_open++ != 0) return (jint) 0; // default 5 if (compression < 1 || compression > 10) { compression = 5; } { // 编码参数设置init de ebits et encoder speex_bits_init(&ebits); // 在xx窄宽模式下的编码状态 enc_state = speex_encoder_init(speex_lib_get_mode(speexModeId)); tmp = compression; // 设定编码的质量 speex_encoder_ctl(enc_state, SPEEX_SET_QUALITY, &tmp); tmp = 3; speex_encoder_ctl(enc_state, SPEEX_SET_COMPLEXITY, &tmp); tmp = 1; speex_encoder_ctl(enc_state, SPEEX_SET_HIGHPASS, &tmp); // 获取编码的帧大小 speex_encoder_ctl(enc_state, SPEEX_GET_FRAME_SIZE, &enc_frame_size); } { // 解码参数设置 init de dbits et decoder speex_bits_init(&dbits); // 在xx窄宽模式下的编码状态 dec_state = speex_decoder_init(speex_lib_get_mode(speexModeId)); tmp = 1; speex_decoder_ctl(dec_state, SPEEX_SET_ENH, &tmp); tmp = 1; speex_decoder_ctl(dec_state, SPEEX_SET_HIGHPASS, &tmp); // 设定解码的帧大小 speex_decoder_ctl(dec_state, SPEEX_GET_FRAME_SIZE, &dec_frame_size); } { // get delay time during coding and decoding int skip_group_delay = 0; speex_encoder_ctl(enc_state, SPEEX_GET_LOOKAHEAD, &skip_group_delay); speex_decoder_ctl(dec_state, SPEEX_GET_LOOKAHEAD, &tmp); skip_group_delay += tmp; } // TODO // 预处理初始化 SpeexPreprocessState *m_st; SpeexEchoState *echo_state; m_st = speex_preprocess_state_init(enc_frame_size, 8000); echo_state = speex_echo_state_init(enc_frame_size, 8000); int denoise = 1; int noiseSuppress = -25; { // 降噪 speex_preprocess_ctl(m_st, SPEEX_PREPROCESS_SET_DENOISE, &denoise); speex_preprocess_ctl(m_st, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, &noiseSuppress); } int agc = 1; float level = 24000; { // 增益 speex_preprocess_ctl(m_st, SPEEX_PREPROCESS_SET_AGC, &agc); speex_preprocess_ctl(m_st, SPEEX_PREPROCESS_SET_AGC_LEVEL, &level); } int vad = 1; int vadProbStart = 80; int vadProbContinue = 65; {// 静音检测 speex_preprocess_ctl(m_st, SPEEX_PREPROCESS_SET_VAD, &vad); speex_preprocess_ctl(m_st, SPEEX_PREPROCESS_SET_PROB_START , &vadProbStart); speex_preprocess_ctl(m_st, SPEEX_PREPROCESS_SET_PROB_CONTINUE, &vadProbContinue); } return (jint) 0; }
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; }
static void AudioQualityImprovement_updatePreprocess(AudioQualityImprovement *aqi) { if (aqi->echo) { int frameSize = 0; if ((aqi->echoFilterLengthInMillis > 0) && (aqi->sampleRate > 0) && speex_echo_ctl( aqi->echo, SPEEX_ECHO_GET_FRAME_SIZE, &frameSize)) frameSize = 0; if (frameSize && (aqi->frameSize == (frameSize * (16 /* sampleSizeInBits */ / 8)))) { int echoFilterLength = (int) ((aqi->sampleRate * aqi->echoFilterLengthInMillis) / 1000); if (aqi->filterLengthOfEcho != echoFilterLength) frameSize = 0; } else frameSize = 0; if (frameSize < 1) { if (aqi->preprocess) { speex_preprocess_ctl( aqi->preprocess, SPEEX_PREPROCESS_SET_ECHO_STATE, NULL); } speex_echo_state_destroy(aqi->echo); aqi->echo = NULL; } } if (aqi->preprocess && ((aqi->frameSize != aqi->frameSizeOfPreprocess) || (aqi->sampleRate != aqi->sampleRateOfPreprocess))) { speex_preprocess_state_destroy(aqi->preprocess); aqi->preprocess = NULL; } if ((aqi->frameSize > 0) && (aqi->sampleRate > 0)) { if (aqi->echoFilterLengthInMillis > 0) { if (!(aqi->echo)) { int echoFrameSize = aqi->frameSize / (16 /* sampleSizeInBits */ / 8); int echoFilterLength = (int) ((aqi->sampleRate * aqi->echoFilterLengthInMillis) / 1000); aqi->echo = speex_echo_state_init(echoFrameSize, echoFilterLength); aqi->filterLengthOfEcho = echoFilterLength; /* * Since echo has just been (re)created, make sure that the * delay in play will happen again taking into consideration the * latest frameSize. */ if (aqi->play) AudioQualityImprovement_updatePlayIsDelaying(aqi); } if (aqi->echo) { speex_echo_ctl( aqi->echo, SPEEX_ECHO_SET_SAMPLING_RATE, &(aqi->sampleRate)); } } if (aqi->denoise || aqi->echo) { if (!(aqi->preprocess)) { aqi->preprocess = speex_preprocess_state_init( aqi->frameSize / (16 /* sampleSizeInBits */ / 8), aqi->sampleRate); aqi->frameSizeOfPreprocess = aqi->frameSize; aqi->sampleRateOfPreprocess = aqi->sampleRate; if (aqi->preprocess) { int on = 1; speex_preprocess_ctl( aqi->preprocess, SPEEX_PREPROCESS_SET_DEREVERB, &on); speex_preprocess_ctl( aqi->preprocess, SPEEX_PREPROCESS_SET_VAD, &on); } } if (aqi->preprocess) { int denoise = (aqi->denoise == JNI_TRUE) ? 1 : 0; speex_preprocess_ctl( aqi->preprocess, SPEEX_PREPROCESS_SET_DENOISE, &denoise); if (aqi->echo) { speex_preprocess_ctl( aqi->preprocess, SPEEX_PREPROCESS_SET_ECHO_STATE, aqi->echo); } } } } }