Module pix_engine::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

Structs

Enums

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

Traits

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