Module audio

Source
Expand description

Trait and types for allowing Engine to play and capture audio.

There are several methods for playing audio in your application:

You can also record audio from a capture device using PixState::open_capture.

§Examples

§Audio Queue

use pix_engine::{prelude::*, math::PI};

struct MyApp;

impl PixEngine for MyApp {
    fn on_start(&mut self, s: &mut PixState) -> PixResult<()> {
        s.resume_audio();
        Ok(())
    }

    fn on_update(&mut self, s: &mut PixState) -> PixResult<()> {
        // Some square wave samples of audio
        let volume = 0.2;
        let sample_rate = s.audio_sample_rate() as f32;
        let sample_count = 4 * sample_rate as usize;
        let frequency = 440.0; // A4 note
        let mut samples = Vec::with_capacity(sample_count);
        for x in 0..sample_count {
            let s = (2.0 * PI as f32 * frequency * x as f32 / sample_rate).sin();
            samples.push(if s <= 0.0 { -volume } else { volume });
        }
        // Add samples to audio queue for playback
        s.enqueue_audio(&samples)?;
        Ok(())
    }
}

§Audio Callback

use pix_engine::prelude::*;
use std::time::Duration;

struct SquareWave {
    phase_inc: f32,
    phase: f32,
    volume: f32,
}

impl AudioCallback for SquareWave {
    type Channel = f32;

    fn callback(&mut self, out: &mut [Self::Channel]) {
        // Generate a square wave
        for x in out.iter_mut() {
            *x = if self.phase <= 0.5 {
                self.volume
            } else {
                -self.volume
            };
            self.phase = (self.phase + self.phase_inc) % 1.0;
        }
    }
}

struct MyApp;

impl PixEngine for MyApp {
    fn on_update(&mut self, s: &mut PixState) -> PixResult<()> {
        let desired_spec = AudioSpecDesired {
            freq: Some(44_100), // 44,100 HZ
            channels: Some(1),  // mono audio
            samples: None,      // default sample size
        };
        let mut device = s.open_playback(None, &desired_spec, |spec| {
            SquareWave {
                phase_inc: 440.0 / spec.freq as f32,
                phase: 0.0,
                volume: 0.25,
            }
        })?;

        // Start playback
        device.resume();

        // Play for 2 seconds then quit.
        std::thread::sleep(Duration::from_millis(2000));
        s.quit();

        // Device stops playback when dropped.
        Ok(())
    }
}

§Audio Capture

For a more complete example, see audio_capture_and_replay in the examples/ directory.

use pix_engine::prelude::*;
use std::{sync::mpsc, time::Duration};

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

impl AudioCallback for Recording {
    type Channel = f32;

    fn callback(&mut self, input: &mut [Self::Channel]) {
        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.tx
                   .send(self.record_buffer.clone())
                   .expect("could not send record buffer");
               break;
           }
        }
    }
}

struct MyApp;

const RECORDING_LENGTH_SECONDS: usize = 3;

impl PixEngine for MyApp {
    fn on_update(&mut self, s: &mut PixState) -> PixResult<()> {
        let desired_spec = AudioSpecDesired {
            freq: None,     // default device frequency
            channels: None, // default device channels
            samples: None,  // default sample size
        };

        let (tx, rx) = mpsc::channel();
        let capture_device = s.open_capture(None, &desired_spec, |spec| {
            Recording {
                record_buffer: vec![
                    0.0;
                    spec.freq as usize
                        * RECORDING_LENGTH_SECONDS
                        * spec.channels as usize
                ],
                pos: 0,
                tx,
                done: false,
            }
        })?;

        // Start playback
        capture_device.resume();

        // Wait for recording to finish
        let recorded_samples = rx.recv()?;
        capture_device.pause();

        // Handle recorded_samples

        // Device stops playback when dropped.
        Ok(())
    }
}

Re-exports§

pub use crate::renderer::sdl::AudioDevice;

Structs§

AudioSpec
Audio device specification.
AudioSpecDesired
Desired audio device specification.

Enums§

AudioFormat
Audio number and endianness format for the given audio device.
AudioStatus
Playback status of an audio device.

Traits§

AudioCallback
Trait for allowing Engine to request audio samples from your application.
AudioDeviceDriver
Provides access to audio device driver properties and controlling playback.
AudioFormatNum
A phantom type for retrieving the SDL_AudioFormat of a given generic type. All format types are returned as native-endian.