sdl2 0.38.0

SDL2 bindings for Rust
Documentation
extern crate sdl2;

use sdl2::audio::{AudioCallback, AudioSpecDesired};
use sdl2::AudioSubsystem;
use std::sync::mpsc;
use std::time::Duration;

const RECORDING_LENGTH_SECONDS: usize = 3;

struct Recording {
    record_buffer: Vec<i16>,
    pos: usize,
    done_sender: mpsc::Sender<Vec<i16>>,
    done: bool,
}

// Append the input of the callback to the record_buffer.
// When the record_buffer is full, send it to the main thread via done_sender.
impl AudioCallback for Recording {
    type Channel = i16;

    fn callback(&mut self, input: &mut [i16]) {
        if self.done {
            return;
        }

        for x in input {
            self.record_buffer[self.pos] = *x;
            self.pos += 1;
            if self.pos >= self.record_buffer.len() {
                self.done = true;
                self.done_sender
                    .send(self.record_buffer.clone())
                    .expect("could not send record buffer");
                break;
            }
        }
    }
}

fn record(
    audio_subsystem: &AudioSubsystem,
    desired_spec: &AudioSpecDesired,
) -> Result<Vec<i16>, String> {
    println!(
        "Capturing {:} seconds... Please rock!",
        RECORDING_LENGTH_SECONDS
    );

    let (done_sender, done_receiver) = mpsc::channel();

    let capture_device = audio_subsystem.open_capture(None, desired_spec, |spec| {
        println!("Capture Spec = {:?}", spec);
        Recording {
            record_buffer: vec![
                0;
                spec.freq as usize
                    * RECORDING_LENGTH_SECONDS
                    * spec.channels as usize
            ],
            pos: 0,
            done_sender,
            done: false,
        }
    })?;

    println!(
        "AudioDriver: {:?}",
        capture_device.subsystem().current_audio_driver()
    );
    capture_device.resume();

    // Wait until the recording is done.
    let recorded_vec = done_receiver.recv().map_err(|e| e.to_string())?;

    capture_device.pause();

    // Device is automatically closed when dropped.
    // Depending on your system it might be even important that the capture_device is dropped
    // before the playback starts.

    Ok(recorded_vec)
}

/// Returns a percent value
fn calculate_average_volume(recorded_vec: &[i16]) -> f32 {
    let sum: i64 = recorded_vec.iter().map(|&x| (x as i64).abs()).sum();
    (sum as f32) / (recorded_vec.len() as f32) / (i16::MAX as f32) * 100.0
}

/// Returns a percent value
fn calculate_max_volume(recorded_vec: &[i16]) -> f32 {
    let max: i64 = recorded_vec
        .iter()
        .map(|&x| (x as i64).abs())
        .max()
        .expect("expected at least one value in recorded_vec");
    (max as f32) / (i16::MAX as f32) * 100.0
}

struct SoundPlayback {
    data: Vec<i16>,
    pos: usize,
}

impl AudioCallback for SoundPlayback {
    type Channel = i16;

    fn callback(&mut self, out: &mut [i16]) {
        for dst in out.iter_mut() {
            *dst = *self.data.get(self.pos).unwrap_or(&0);
            self.pos += 1;
        }
    }
}

fn replay_recorded_vec(
    audio_subsystem: &AudioSubsystem,
    desired_spec: &AudioSpecDesired,
    recorded_vec: Vec<i16>,
) -> Result<(), String> {
    println!("Playing...");

    let playback_device = audio_subsystem.open_playback(None, desired_spec, |spec| {
        println!("Playback Spec = {:?}", spec);
        SoundPlayback {
            data: recorded_vec,
            pos: 0,
        }
    })?;

    // Start playback
    playback_device.resume();

    std::thread::sleep(Duration::from_secs(RECORDING_LENGTH_SECONDS as u64));
    // Device is automatically closed when dropped

    Ok(())
}

fn main() -> Result<(), String> {
    let sdl_context = sdl2::init()?;
    let audio_subsystem = sdl_context.audio()?;

    let desired_spec = AudioSpecDesired {
        freq: None,
        channels: None,
        samples: None,
    };

    let recorded_vec = record(&audio_subsystem, &desired_spec)?;

    println!(
        "Average Volume of your Recording = {:?}%",
        calculate_average_volume(&recorded_vec)
    );
    println!(
        "Max Volume of your Recording = {:?}%",
        calculate_max_volume(&recorded_vec)
    );

    replay_recorded_vec(&audio_subsystem, &desired_spec, recorded_vec)?;

    Ok(())
}