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:
- Queuing pre-recorded or generated audio samples by calling
PixState::enqueue_audio
. - Having
Engine
request pre-recorded or generated audio samples by implementing theAudioCallback
trait on a type and callingPixState::open_playback
. - Loading and playing a
.wav
or.mp3
file. (Coming soon!).
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
- Audio device specification.
- Desired audio device specification.
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.