Skip to content

Commit

Permalink
Make Rust sound work on Linux
Browse files Browse the repository at this point in the history
An odd bug here: the Rust version plays no audible sound on Linux, with
Pulseaudio.  When I run `strace -f ./target/debug/letters`, it works!  But
with `strace ./target/debug/letters` (no `-f`) it is again silent.

The current fix is to just sleep long enough after enqueueing each sound
for the sound to complete.  That's not great, but I'm going to commit this
mostly-working version.
  • Loading branch information
piki committed Jan 29, 2024
1 parent c370d7f commit 5e7b186
Showing 1 changed file with 17 additions and 16 deletions.
33 changes: 17 additions & 16 deletions src/main.rs → src/bin/letters.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::collections::HashMap;

use sdl2::{ttf::{self, Font}, pixels::Color, event::Event, keyboard::Mod, render::Canvas, video::Window, rect::{Rect, Point}, audio::{AudioSpecWAV, AudioSpecDesired, AudioQueue, AudioFormatNum}, Sdl};
use std::time::Duration;
use sdl2::{ttf::{self, Font}, pixels::Color, event::Event, keyboard::Mod, render::Canvas, video::Window, rect::{Rect, Point}, audio::{AudioSpecWAV, AudioSpecDesired}, Sdl};

fn main() {
let sdl = sdl2::init().unwrap();
Expand All @@ -9,7 +9,7 @@ fn main() {
let ttf = ttf::init().unwrap();
let font = ttf.load_font("font.ttf", 600).unwrap();

let (sounds, sound_queue) = init_audio(&sdl);
let sounds = init_audio();

canvas.set_draw_color(Color::WHITE);
canvas.clear();
Expand Down Expand Up @@ -38,8 +38,7 @@ fn main() {
// display and play sound for any letter or number
if c.is_alphanumeric() {
draw_letter(&mut canvas, &font, c);
sound_queue.clear();
sound_queue.queue_audio(sounds.get(&c.to_ascii_lowercase()).expect(&c.to_string()).buffer()).unwrap();
play_sound(&sdl, sounds.get(&c).unwrap());
}
}
}
Expand Down Expand Up @@ -75,25 +74,27 @@ fn init_video(sdl: &Sdl) -> Canvas<Window> {
window.into_canvas().build().unwrap()
}

fn init_audio<Channel>(sdl: &Sdl) -> (HashMap<char, AudioSpecWAV>, AudioQueue<Channel>)
where
Channel: AudioFormatNum
{
fn init_audio() -> HashMap<char, AudioSpecWAV> {
let mut sounds: HashMap<char, AudioSpecWAV> = HashMap::default();
for c in ('a'..='z').chain('0'..='9') {
let filename = format!("sounds/{c}.wav");
sounds.insert(c, AudioSpecWAV::load_wav(filename).unwrap());
}
let first_sound = sounds.values().next().unwrap();
println!("Loaded {} sounds", sounds.len());

sounds
}

fn play_sound(sdl: &Sdl, sound: &AudioSpecWAV) {
let desired = AudioSpecDesired{
freq: Some(first_sound.freq),
channels: Some(first_sound.channels),
samples: Some(first_sound.format as u16)
freq: Some(sound.freq),
channels: Some(sound.channels),
samples: Some(sound.format as u16)
};
let audio = sdl.audio().unwrap();
let sound_queue = audio.open_queue(None, &desired).unwrap();
sound_queue.queue_audio(sound.buffer()).unwrap();
sound_queue.resume();

(sounds, sound_queue)
}
let audio_len = sound.buffer().len(); // bytes
std::thread::sleep(Duration::from_millis(audio_len as u64 * 1000 / sound.freq as u64 / sound.channels as u64));
}

0 comments on commit 5e7b186

Please sign in to comment.