this post was submitted on 03 Sep 2023
17 points (100.0% liked)

Rust Programming

8134 readers
4 users here now

founded 5 years ago
MODERATORS
 

Hello, I really need help figuring out Rodio audio playback for a rust project. I need to play a short audio clip of a casino wheel turning a certain amount of times in a loop. When I run the main function, the program plays the audio clip once and then stops completely. If anybody who has used Rodio can give me help it would be greatly appreciated. Also, I have tried using a longer duration in the play_sound function but it doesn't change anything. Thank you

you are viewing a single comment's thread
view the rest of the comments
[–] uncle_agrey@lemmy.ml 1 points 1 year ago (1 children)

I dont want to pause/play the source. I simply want to replay it over and over again but with a delay in between. The audio is a click of a game wheel spinning, its duration is somewhere in the low milliseconds. I have an exponential function which tells the program how much time to sleep until the next click on the wheel. I just want to play the sound each time the wheel clicks. Do you think appending the sound to a sink and removing it once Sink.sleep_until_end() finishes would produce that outcome.

[–] TehPers@beehaw.org 3 points 1 year ago (1 children)

In this case, I don't think Sink will let you selectively remove sources (although you can clear the sink if you want), but whenever you want to play a click you could clear the sink and append the clicking source to it. Alternatively, you could create a source that chains the clicking sound with something like Zero and have it repeat indefinitely, but have the Zero source play until you receive a new signal to play the click audio (and stop the source once you're done clicking).

I think how you should approach this depends on your architecture, so I'll give a couple approaches I would consider if I were trying to do this myself:

  1. For a blocking approach: I'd play the click sound once (using .append on the sink, for example), then use Instant::now() - last_instant and pass whatever duration is left to wait off to thread::sleep. This would look something like this (pseudo-ish code):

    let mut audio_started = Instant::now();
    for _click_idx in 0..num_clicks {
        sink.append(click_sound.clone()); // you can buffer the click_sound source and clone the buffer using .buffered() if needed
        let remaining = Instant::now() - audio_started;
        if remaining > Duration::ZERO {
            std::thread::sleep(remaining);
        }
    }
    
  2. For a non-blocking approach where you have a separate thread managing the audio, I'd use a channel or similar as a signal for when to play the click. Your thread could then wait until that signal is received and append the click sound to the sink. You'd basically have a thread dedicated to managing the audio in this case. If you want a more complicated version this as an example, here's a project where we used rodio with tauri (like you) to queue up audio sources to be played on demand whenever the user clicks certain buttons in the UI. The general architecture is the same - just a for loop listening for events from a channel, and then using those events to add sources to our output stream (though you can just use a Sink I believe to keep things simple).

[–] uncle_agrey@lemmy.ml 1 points 1 year ago

Man I implemented something like the Sink option and it is playing the audio clips at inputted intervals just as I wanted. The only thing missing for me now is just the intervals, which means i just need to tinker with my exponential time functions. Thank you so much for your help.