1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
//! Decode an audio file with oxiaudio and play it back through oxisound.
//!
//! Usage: cargo run --example decode_play --features pure -- /path/to/audio.wav
//! Without a path argument: plays a synthetic 440 Hz sine tone instead.
fn main() {
let args: Vec<String> = std::env::args().collect();
if args.len() > 1 {
let path = &args[1];
// Decode the file using oxiaudio — returns AudioBuffer<f32> with interleaved samples.
let buffer = match oxiaudio::decode_file(std::path::Path::new(path)) {
Ok(b) => b,
Err(e) => {
println!("Failed to decode {path}: {e}");
return;
}
};
// ChannelLayout is an enum, not a u16 — use channel_count() to get the numeric count.
let n_channels = buffer.channels.channel_count() as u16;
println!(
"Decoded: {} frames, {} ch, {} Hz",
buffer.frame_count(),
n_channels,
buffer.sample_rate
);
// Build a StreamConfig whose sample rate and channel count match the decoded audio.
// The device must support these exact values; a mismatch will surface as open_output Err.
let config = oxisound::StreamConfig {
sample_rate: buffer.sample_rate,
channels: n_channels,
..oxisound::StreamConfig::STEREO_48K
};
let mut output = match oxisound::open_output(config) {
Ok(o) => o,
Err(e) => {
println!("Failed to open output: {e}");
return;
}
};
// Write the complete decoded sample block into the ring buffer.
// The ring buffer streams to the hardware asynchronously.
if let Err(e) = output.write(&buffer.samples) {
println!("Write error: {e}");
return;
}
// Sleep just past the audio duration so the ring buffer drains fully before exit.
let duration_secs = buffer.duration_secs();
std::thread::sleep(std::time::Duration::from_secs_f64(duration_secs + 0.5));
println!("Playback complete.");
} else {
// No file argument supplied — synthesise a 440 Hz sine tone so the example runs standalone.
println!("No file argument. Playing 440 Hz sine tone for 2 seconds.");
println!("Usage: cargo run --example decode_play --features pure -- <audio_file>");
let config = oxisound::StreamConfig::stereo_48k();
let mut output = match oxisound::open_output(config.clone()) {
Ok(o) => o,
Err(e) => {
println!("Failed to open output: {e}");
return;
}
};
// Use the facade's built-in sine generator — no oxiaudio dependency needed.
let samples = oxisound::sine_test_tone(440.0, 2.0, config);
if let Err(e) = output.write(&samples) {
println!("Write error: {e}");
return;
}
// 2 s of audio + 0.5 s tail to let the ring buffer drain before the stream is dropped.
std::thread::sleep(std::time::Duration::from_secs_f64(2.5));
println!("Sine tone complete.");
}
}