Skip to content

Usage #41

Open
Open
@thewh1teagle

Description

@thewh1teagle

Hey
I'm trying to use this library for echo cancellation like this example in aec-rs crate:
https://github.com/thewh1teagle/aec-rs/blob/main/examples/wav.rs
But I don't understand how to use it that way.

I tried the following but it doesn't cancel the echo

/*
wget https://github.com/thewh1teagle/aec-rs/releases/download/audio-files/rec.wav
wget https://github.com/thewh1teagle/aec-rs/releases/download/audio-files/echo.wav
wget https://github.com/thewh1teagle/aec-rs/releases/download/audio-files/voice.wav
cargo run --example wav rec.wav echo.wav cancelled.wav
*/

use hound;
use webrtc_audio_processing::*;

const SAMPLE_RATE: f64 = 16_000.0; // 16kHz
const FRAMES_PER_BUFFER: u32 = 480; // 10ms per buffer

fn create_processor() -> Result<Processor, Box<dyn std::error::Error>> {
    let mut processor = Processor::new(&InitializationConfig {
        num_capture_channels: 1,
        num_render_channels: 1,
        ..InitializationConfig::default()
    })?;

    let config = Config {
        echo_cancellation: Some(EchoCancellation {
            suppression_level: EchoCancellationSuppressionLevel::High,
            stream_delay_ms: Some(0),
            enable_delay_agnostic: false,
            enable_extended_filter: false,
        }),
        enable_high_pass_filter: false,
        ..Config::default()
    };
    processor.set_config(config);

    Ok(processor)
}

fn main() {
    let rec_path = std::env::args().nth(1).expect("Please specify echo path");
    let echo_path = std::env::args().nth(2).expect("Please specify rec path");
    let out_path = std::env::args().nth(3).expect("Please specify out path");

    // Read echo samples
    let mut reader = hound::WavReader::open(echo_path).unwrap();
    let echo_samples: Vec<f32> = reader.samples::<i16>()
        .map(|s| s.unwrap() as f32 / i16::MAX as f32)  // Convert i16 to f32 (normalize)
        .collect();

    // Read recorded samples
    let mut reader = hound::WavReader::open(rec_path).unwrap();
    let rec_samples: Vec<f32> = reader.samples::<i16>()
        .map(|s| s.unwrap() as f32 / i16::MAX as f32)  // Convert i16 to f32 (normalize)
        .collect();

    let mut processor = create_processor().unwrap();

    let frame_size = FRAMES_PER_BUFFER as usize;

    // Prepare output WAV writer
    let spec = hound::WavSpec {
        channels: 1,
        sample_rate: SAMPLE_RATE as u32,
        bits_per_sample: 16,
        sample_format: hound::SampleFormat::Int,
    };
    let mut writer = hound::WavWriter::create(&out_path, spec).unwrap();

    let mut output_samples = Vec::new();
    let mut input_frame = vec![0f32; frame_size];
    let mut reference_frame = vec![0f32; frame_size];

    // Process samples frame by frame
    for i in (0..rec_samples.len()).step_by(frame_size) {
        let end = usize::min(i + frame_size, rec_samples.len());

        // Fill frames with input and reference samples
        input_frame[..end - i].copy_from_slice(&rec_samples[i..end]);
        reference_frame[..end - i].copy_from_slice(&echo_samples[i..end]);

        // Apply echo cancellation using webrtc-audio-processing
        processor.process_capture_frame(&mut input_frame).unwrap();
        processor.process_render_frame(&mut reference_frame).unwrap();

        // Convert the output back to i16 and write to the output file
        for &sample in &input_frame {
            writer.write_sample((sample * i16::MAX as f32) as i16).unwrap();
        }

        // Add to output_samples
        output_samples.extend_from_slice(&input_frame);
    }

    println!("Created {}", out_path);
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions