Skip to content

Commit bc68d5c

Browse files
authored
AudioStream locking support with Callback API (#138)
1 parent 606ae43 commit bc68d5c

File tree

5 files changed

+190
-221
lines changed

5 files changed

+190
-221
lines changed

examples/audio-capture-and-replay.rs

+19-29
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
extern crate sdl3;
22

3-
use sdl3::audio::{AudioCallback, AudioSpec};
3+
use sdl3::audio::{AudioCallback, AudioFormat, AudioRecordingCallback, AudioSpec, AudioStream};
44
use sdl3::AudioSubsystem;
55
use std::i16;
66
use std::sync::mpsc;
@@ -17,22 +17,21 @@ struct Recording {
1717

1818
// Append the input of the callback to the record_buffer.
1919
// When the record_buffer is full, send it to the main thread via done_sender.
20-
impl AudioCallback<i16> for Recording {
21-
fn callback(&mut self, input: &mut [i16]) {
20+
impl AudioRecordingCallback<i16> for Recording {
21+
fn callback(&mut self, stream: &mut AudioStream, _available: i32) {
2222
if self.done {
2323
return;
2424
}
2525

26-
for x in input {
27-
self.record_buffer[self.pos] = *x;
28-
self.pos += 1;
29-
if self.pos >= self.record_buffer.len() {
30-
self.done = true;
31-
self.done_sender
32-
.send(self.record_buffer.clone())
33-
.expect("could not send record buffer");
34-
break;
35-
}
26+
self.pos += stream
27+
.read_i16_samples(&mut self.record_buffer[self.pos..])
28+
.unwrap();
29+
30+
if self.pos >= self.record_buffer.len() {
31+
self.done = true;
32+
self.done_sender
33+
.send(self.record_buffer.clone())
34+
.expect("could not send record buffer");
3635
}
3736
}
3837
}
@@ -96,15 +95,11 @@ fn calculate_max_volume(recorded_vec: &[i16]) -> f32 {
9695

9796
struct SoundPlayback {
9897
data: Vec<i16>,
99-
pos: usize,
10098
}
10199

102100
impl AudioCallback<i16> for SoundPlayback {
103-
fn callback(&mut self, out: &mut [i16]) {
104-
for dst in out.iter_mut() {
105-
*dst = *self.data.get(self.pos).unwrap_or(&0);
106-
self.pos += 1;
107-
}
101+
fn callback(&mut self, stream: &mut AudioStream, _requested: i32) {
102+
stream.put_data_i16(&self.data).unwrap();
108103
}
109104
}
110105

@@ -115,13 +110,8 @@ fn replay_recorded_vec(
115110
) -> Result<(), Box<dyn std::error::Error>> {
116111
println!("Playing...");
117112

118-
let playback_device = audio_subsystem.open_playback_stream(
119-
desired_spec,
120-
SoundPlayback {
121-
data: recorded_vec,
122-
pos: 0,
123-
},
124-
)?;
113+
let playback_device =
114+
audio_subsystem.open_playback_stream(desired_spec, SoundPlayback { data: recorded_vec })?;
125115

126116
// Start playback
127117
playback_device.resume()?;
@@ -137,9 +127,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
137127
let audio_subsystem = sdl_context.audio()?;
138128

139129
let desired_spec = AudioSpec {
140-
freq: None,
141-
channels: None,
142-
format: None,
130+
freq: Some(48000),
131+
channels: Some(2),
132+
format: Some(AudioFormat::s16_sys()),
143133
};
144134

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

examples/audio-squarewave.rs

+11-5
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,30 @@
11
extern crate sdl3;
22

3-
use sdl3::audio::{AudioCallback, AudioSpec};
3+
use sdl3::audio::{AudioCallback, AudioFormat, AudioSpec, AudioStream};
44
use std::time::Duration;
55

66
struct SquareWave {
77
phase_inc: f32,
88
phase: f32,
99
volume: f32,
10+
buffer: Vec<f32>,
1011
}
1112

1213
impl AudioCallback<f32> for SquareWave {
13-
fn callback(&mut self, out: &mut [f32]) {
14+
fn callback(&mut self, stream: &mut AudioStream, requested: i32) {
15+
self.buffer.resize(requested as usize, 0.0);
16+
1417
// Generate a square wave
15-
for x in out.iter_mut() {
18+
for x in self.buffer.iter_mut() {
1619
*x = if self.phase <= 0.5 {
1720
self.volume
1821
} else {
1922
-self.volume
2023
};
2124
self.phase = (self.phase + self.phase_inc) % 1.0;
2225
}
26+
27+
stream.put_data_f32(&self.buffer).unwrap();
2328
}
2429
}
2530

@@ -28,9 +33,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
2833
let audio_subsystem = sdl_context.audio()?;
2934

3035
let desired_spec = AudioSpec {
31-
freq: Some(44_100),
36+
freq: Some(48000),
3237
channels: Some(1), // mono
33-
format: None,
38+
format: Some(AudioFormat::f32_sys()),
3439
};
3540

3641
let device = audio_subsystem.open_playback_stream(
@@ -39,6 +44,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
3944
phase_inc: 440.0 / desired_spec.freq.unwrap() as f32,
4045
phase: 0.0,
4146
volume: 0.25,
47+
buffer: Vec::new(),
4248
},
4349
)?;
4450

examples/audio-wav.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
extern crate sdl3;
22

3-
use sdl3::audio::{AudioCallback, AudioSpec, AudioSpecWAV};
3+
use sdl3::audio::{AudioCallback, AudioSpec, AudioSpecWAV, AudioStream};
44
use std::borrow::Cow;
55
use std::path::{Path, PathBuf};
66
use std::time::Duration;
@@ -14,8 +14,10 @@ struct Sound {
1414
pos: usize,
1515
}
1616

17+
// FIXME: Adapt to new playback api.
18+
#[cfg(feature = "")]
1719
impl AudioCallback<u8> for Sound {
18-
fn callback(&mut self, out: &mut [u8]) {
20+
fn callback(&mut self, out: &[u8]) {
1921
for dst in out.iter_mut() {
2022
// With channel type u8 the "silence" value is 128 (middle of the 0-2^8 range) so we need
2123
// to both fill in the silence and scale the wav data accordingly. Filling the silence

examples/audio-whitenoise.rs

+18-19
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,26 @@
11
extern crate rand;
22
extern crate sdl3;
33

4-
use sdl3::audio::{AudioCallback, AudioSpec};
5-
use std::{
6-
sync::{Arc, Mutex},
7-
time::Duration,
8-
};
4+
use sdl3::audio::{AudioCallback, AudioFormat, AudioSpec, AudioStream};
5+
use std::time::Duration;
96

107
struct MyCallback {
11-
volume: Arc<Mutex<f32>>, // it seems like AudioStreamWithCallback<> is supposed to have a lock() method which allows us to modify MyCallback, but that function no longer seems to exist
8+
volume: f32,
9+
buffer: Vec<f32>,
1210
}
1311
impl AudioCallback<f32> for MyCallback {
14-
fn callback(&mut self, out: &mut [f32]) {
12+
fn callback(&mut self, stream: &mut AudioStream, requested: i32) {
1513
use self::rand::{thread_rng, Rng};
1614
let mut rng = thread_rng();
1715

18-
let Ok(volume) = self.volume.lock() else {
19-
return;
20-
};
16+
self.buffer.resize(requested as usize, 0.0);
17+
2118
// Generate white noise
22-
for x in out.iter_mut() {
23-
*x = (rng.gen_range(0.0..=2.0) - 1.0) * *volume;
19+
for x in self.buffer.iter_mut() {
20+
*x = (rng.gen_range(0.0..=2.0) - 1.0) * self.volume;
2421
}
22+
23+
stream.put_data_f32(&self.buffer);
2524
}
2625
}
2726

@@ -30,19 +29,19 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
3029
let audio_subsystem = sdl_context.audio()?;
3130

3231
let desired_spec = AudioSpec {
33-
freq: Some(44_100),
32+
freq: Some(48000),
3433
channels: Some(1), // mono
35-
format: None,
34+
format: Some(AudioFormat::f32_sys()),
3635
};
3736
let device = audio_subsystem.open_playback_device(&desired_spec)?;
3837

3938
// None: use default device
40-
let volume = Arc::new(Mutex::new(0.5));
41-
let device = audio_subsystem.open_playback_stream_with_callback(
39+
let mut device = audio_subsystem.open_playback_stream_with_callback(
4240
&device,
4341
&desired_spec,
4442
MyCallback {
45-
volume: volume.clone(),
43+
volume: 0.0,
44+
buffer: Vec::new(),
4645
},
4746
)?;
4847

@@ -52,8 +51,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
5251
// Play for 1 second
5352
std::thread::sleep(Duration::from_millis(1_000));
5453

55-
if let Ok(mut volume) = volume.lock() {
56-
*volume = 0.25;
54+
if let Some(mut context) = device.lock() {
55+
context.volume = 0.25;
5756
}
5857

5958
// Play for another second

0 commit comments

Comments
 (0)