use sdl2::{ audio::{AudioCallback, AudioDevice, AudioSpecDesired}, AudioSubsystem, Sdl, }; pub struct AudioWave { phase_inc: f32, phase: f32, volume: f32, /// The relative amount of time (as a percentage decimal) the low level /// is going to be present during a period (cycle). /// From [Wikipedia](https://en.wikipedia.org/wiki/Duty_cycle). duty_cycle: f32, } impl AudioCallback for AudioWave { type Channel = f32; fn callback(&mut self, out: &mut [f32]) { for x in out.iter_mut() { *x = if self.phase < (1.0 - self.duty_cycle) { self.volume } else { -self.volume }; self.phase = (self.phase + self.phase_inc) % 1.0; } } } pub struct Audio { pub device: AudioDevice<AudioWave>, pub audio_subsystem: AudioSubsystem, } impl Audio { pub fn new(sdl: &Sdl) -> Self { let audio_subsystem = sdl.audio().unwrap(); let desired_spec = AudioSpecDesired { freq: Some(44100), channels: Some(1), samples: None, }; let device = audio_subsystem .open_playback(None, &desired_spec, |spec| AudioWave { phase_inc: 440.0 / spec.freq as f32, phase: 0.0, volume: 0.25, duty_cycle: 0.5, }) .unwrap(); // starts the playback by resuming the audio // device's activity device.resume(); Self { device, audio_subsystem, } } }