#![allow(dead_code)] #![allow(unused_imports)] extern crate byteorder; extern crate speexdsp; extern crate structopt; use byteorder::{BigEndian, ByteOrder}; use std::fs::File; use std::io::{Read, Write}; use std::path::PathBuf; use structopt::StructOpt; #[derive(Debug, StructOpt)] struct CliArgs { #[structopt(parse(from_os_str))] echo_fd_path: PathBuf, #[structopt(parse(from_os_str))] ref_fd_path: PathBuf, #[structopt(parse(from_os_str))] e_fd_path: PathBuf, } #[cfg(feature = "sys")] fn main() -> std::io::Result<()> { use speexdsp::echo::SpeexEchoConst::*; use speexdsp::echo::*; use speexdsp::preprocess::SpeexPreprocessConst::*; use speexdsp::preprocess::*; const NN: usize = 160; const TAIL: usize = 1024; let sample_rate: usize = 8000; let mut echo_buf: [i16; NN] = [0; NN]; let mut echo_read_buf: [u8; NN * 2] = [0; NN * 2]; let mut ref_buf: [i16; NN] = [0; NN]; let mut ref_read_buf: [u8; NN * 2] = [0; NN * 2]; let mut e_buf: [i16; NN] = [0; NN]; let opts = CliArgs::from_args(); let mut ref_fd = File::open(opts.ref_fd_path)?; let mut echo_fd = File::open(opts.echo_fd_path)?; let mut e_fd = File::create(opts.e_fd_path)?; let mut st = SpeexEcho::new(NN, TAIL).unwrap(); let mut den = SpeexPreprocess::new(NN, sample_rate).unwrap(); st.echo_ctl(SPEEX_ECHO_SET_SAMPLING_RATE, sample_rate) .unwrap(); den.preprocess_ctl(SPEEX_PREPROCESS_SET_ECHO_STATE, &st) .unwrap(); loop { let n = echo_fd.read(&mut echo_read_buf)?; let nn = ref_fd.read(&mut ref_read_buf)?; if n == 0 && nn == 0 { break; } BigEndian::read_i16_into(&echo_read_buf, &mut echo_buf); BigEndian::read_i16_into(&ref_read_buf, &mut ref_buf); st.echo_cancellation(&ref_buf, &echo_buf, &mut e_buf); den.preprocess_run(&mut e_buf); BigEndian::write_i16_into(&e_buf, &mut ref_read_buf); e_fd.write_all(&ref_read_buf)?; } Ok(()) } #[cfg(not(feature = "sys"))] fn main() { unimplemented!(); }