Rust audio playback library

Overview

Audio playback library

Build Status

Rust playback library.

  • Playback is handled by cpal.
  • MP3 decoding is handled by minimp3.
  • WAV decoding is handled by hound.
  • Vorbis decoding is handled by lewton.
  • Flac decoding is handled by claxon.

Documentation

The documentation contains an introduction to the library.

License

Licensed under either of

at your option.

License of your contributions

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Comments
  • Add spatial audio

    Add spatial audio

    This addresses https://github.com/tomaka/rodio/issues/40

    Things done in this PR

    • Add ChannelVolume filter which allows a sound to be played to different channels at different volumes
    • Add cgmath dependency to make working in 3 dimensional space easier
    • Add Spatial sound filter, which is the back end for SpatialSink
    • Add SpatialSink, which is a special sink type with support for playing sounds in 3 dimensional space
    • Add spatial example for demonstration and testing purposes.

    @tomaka indicated in #40 that he wanted our system to be similar to this. I've made some modifications to that system, this implementation only has 1 sound fall-off algorithm and instead of azimuth with a single point in space this system uses multiple points in space to represent each "ear" and then applies the following formula:

    let left_diff_modifier = ((left_distance - right_distance) / max_diff + 1.0) / 4.0 + 0.5;
    let right_diff_modifier = ((right_distance - left_distance) / max_diff + 1.0) / 4.0 + 0.5;
    

    These modifiers are then multiplied into the final volume for each ear.

    The purpose of this is to amplify the difference between what the two ears hear, which was the purpose of the azimuth calculation in the system used by web-audio.

    opened by Xaeroxe 19
  • Relicense under dual MIT/Apache-2.0

    Relicense under dual MIT/Apache-2.0

    Why?

    The MIT license requires reproducing countless copies of the same copyright header with different names in the copyright field, for every MIT library in use. The Apache license does not have this drawback, and has protections from patent trolls and an explicit contribution licensing clause. However, the Apache license is incompatible with GPLv2. This is why Rust is dual-licensed as MIT/Apache (the "primary" license being Apache, MIT only for GPLv2 compat), and doing so would be wise for this project. This also makes this crate suitable for inclusion in the Rust standard distribution and other project using dual MIT/Apache.

    How?

    To do this, get explicit approval from each contributor of copyrightable work (as not all contributions qualify for copyright) and then add the following to your README:

    ## License
    
    Licensed under either of
     * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
     * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
    at your option.
    
    ### Contribution
    
    Unless you explicitly state otherwise, any contribution intentionally submitted
    for inclusion in the work by you shall be dual licensed as above, without any
    additional terms or conditions.
    

    and in your license headers, use the following boilerplate (based on that used in Rust):

    // Copyright (c) 2015 t developers
    // Licensed under the Apache License, Version 2.0
    // <LICENSE-APACHE or
    // http://www.apache.org/licenses/LICENSE-2.0> or the MIT
    // license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
    // at your option. All files in the project carrying such
    // notice may not be copied, modified, or distributed except
    // according to those terms.
    

    And don't forget to update the license metadata in your Cargo.toml!

    Contributor checkoff

    • [x] @tomaka
    opened by emberian 18
  • Force `queue` to play sources on frame boundaries

    Force `queue` to play sources on frame boundaries

    Purpose

    • Fixes #444
    • Fixes https://github.com/bevyengine/bevy/issues/6122

    Problem

    As I understand it, this is the issue:

    • Previously, when a queue has keep_alive_if_empty set to true, and it becomes empty, then it will push a silence lasting 10ms onto the queue.
    • This is an issue because current_frame_len would have returned the worst case, 512, and the silence lasts less than that.
    • This means that unless the source is added immediately to the queue, and so a silence is never played, then the first actual source could start playing at a frame that is not aligned to its channels, or play at the wrong sample rate.
    • This is only determined by when the source is added to the queue after its initialization. This explains why the issue was inconsistent, as it relied on the speed of execution of code which is basically random.

    Solution

    • Change the functionality of Zero to add a method to create a silence with a certain number of frames.
    • Replace the 10ms silence with a silence the length of THRESHOLD
    • Change queue's current_frame_len to return THRESHOLD if a silence will be played next.

    Other Changes

    At first, I could only reproduce this issue in the bevy game engine where the time a sink is created to when a source is appended can be long. The spatial example was the only example where stereo sound mattered, and so the issue was actually audible. However it had a bug where the right ear was at -1 and the left was at 1, so that combined with the inconsistency of the bug made it hard to reproduce.

    To hopefully prevent stereo bugs in the future, I fixed the spatial example and made it clearer what was happening, and added a stereoexample where the file is played in the right ear and then in the left.

    opened by dis-da-moe 14
  • Bad sound quality when upgrading to Rust 1.45

    Bad sound quality when upgrading to Rust 1.45

    I updated my toolchain to use Rust 1.45, this has broken the audio playback using Rodio 0.11.0. The sound comes out as somewhat muffled, like it was low-pass filtered. I can restore the correct audio by downgrading Rust back to 1.44.1, so clearly there is something going on with changes made in the compiler and how they interact with Rodio. Perhaps the changes in float-to-integer casts are to blame.

    I've attached a sound recording for comparison. First, two sound effects are heard from Rust 1.45, then the same two effects in Rust 1.44.1. (Yes, these are old Doom sound effects, if anyone is wondering :) )

    brokensound.ogg.zip

    To play this audio, I use a custom Source that reads its samples from an Arc<[i16]>, so that I can keep the buffer around after playing it. This is then wrapped in the ChannelVolume, Done and SamplesConverter sources, sent to another thread (to avoid the COM initialisation bug on Windows), where it is then played via rodio::play_raw.

    bug 
    opened by Rua 14
  • Docs example doesn't play sound on Windows

    Docs example doesn't play sound on Windows

    Hi y'all, I'm trying to run this example and it compiles but no sound plays.

    use rodio::Sink;
    
    fn main() {
        let device = rodio::default_output_device().unwrap();
        let sink = Sink::new(&device);
    
        let source = rodio::source::SineWave::new(440);
        sink.append(source);
    }
    

    I'm on this toolchain

    nightly-x86_64-pc-windows-msvc (default)
    rustc 1.46.0-nightly (feb3536eb 2020-06-09)
    

    And this Rodio version rodio = "0.11.0"

    How do you troubleshoot this?

    opened by vladinator1000 12
  • Default to Symphonia for MP3 decoding

    Default to Symphonia for MP3 decoding

    Symphonia is already a supported backend for MP3 decoding in rodio, but it is not the default. I believe Symphonia MP3 decoder has matured, and it's time to switch to using it by default.

    Currently rodio defaults to minimp3 for decoding, which is written in C and causes a number of issues:

    • Complicated cross-compilation
    • Potential security issues due to C code being entirely unsafe
    • iOS app store rejection (see #400)

    Symphonia has an MP3 decoder written in 100% safe Rust. The decoding performance is exactly on par with ffmpeg in my tests.

    I have tested the correctness of Symphonia's MP3 decoder on over 50,000 real-world files created by a variety of encoders to ensure correct decoding and compatibility with the files found in the wild, which resulted in multiple fixes (see https://github.com/pdeljanov/Symphonia/issues/72, https://github.com/pdeljanov/Symphonia/issues/78, https://github.com/pdeljanov/Symphonia/issues/99). These fixes are going to ship in the upcoming v0.5 along with support for gapless playback for MP3 files.

    With safety, performance and compatibility all being in great shape for Symphonia's MP3 decoder, I believe it is time to switch to using it by default instead of minimp3.

    opened by Shnatsel 10
  • skip_duration takes ~600ms to run

    skip_duration takes ~600ms to run

    Hi,

    I'm playing around with rodio for a project, and I noticed I got freeze lags when I was playing some sounds. After some digging it turned out that the culprit was calling skip_duration on a source. It seems like it gets worse the longer the skip is. This is in debug mode, but skipping 3secs takes 600ms to run for me which seems a bit extreme. This is on OSX.

    To repro, just take the first example in the docs and add skip_duration to it, like this:

    let file = File::open("sound.ogg").unwrap();
    let source = rodio::Decoder::new(BufReader::new(file)).unwrap();
    
    let now = Instant::now();
    stream_handle.play_raw(source.convert_samples().skip_duration(Duration::from_secs_f32(3.))).unwrap();
    println!("{}", now.elapsed().as_secs_f32() * 1000.);
    

    Results on my machine (in debug):

    • Without skip: 0.04ms
    • With skip: 658ms
    opened by FredrikNoren 10
  • Stack overflow on audio change

    Stack overflow on audio change

    Not sure what's up here (backtrace below). I don't see repeating pointer values in the first few pages, so not obviously a refcycle. But, you can see that we're way deep in a call stack here. The Arc::drop_slow is the set of frames seen over and over.

    #53678 0x00005642f4b1d23b in alloc::sync::Arc<T>::drop_slow (self=0x5642f52a9870) at /builddir/build/BUILD/rustc-1.42.0-src/src/liballoc/sync.rs:739
    #53679 0x00005642f4b1dfd6 in <alloc::sync::Arc<T> as core::ops::drop::Drop>::drop (self=0x5642f52a9870) at /builddir/build/BUILD/rustc-1.42.0-src/src/liballoc/sync.rs:1249
    #53680 0x00005642f4b27c0e in core::ptr::drop_in_place () at /builddir/build/BUILD/rustc-1.42.0-src/src/libcore/ptr/mod.rs:174
    #53681 0x00005642f4b27ebe in core::ptr::drop_in_place () at /builddir/build/BUILD/rustc-1.42.0-src/src/libcore/ptr/mod.rs:174
    #53682 0x00005642f4b29a79 in core::ptr::drop_in_place () at /builddir/build/BUILD/rustc-1.42.0-src/src/libcore/ptr/mod.rs:174
    #53683 0x00005642f4b28bce in core::ptr::drop_in_place () at /builddir/build/BUILD/rustc-1.42.0-src/src/libcore/ptr/mod.rs:174
    #53684 0x00005642f4b28212 in core::ptr::drop_in_place () at /builddir/build/BUILD/rustc-1.42.0-src/src/libcore/ptr/mod.rs:174
    #53685 0x00005642f4b1d23b in alloc::sync::Arc<T>::drop_slow (self=0x5642f51bcee0) at /builddir/build/BUILD/rustc-1.42.0-src/src/liballoc/sync.rs:739
    #53686 0x00005642f4b1dfd6 in <alloc::sync::Arc<T> as core::ops::drop::Drop>::drop (self=0x5642f51bcee0) at /builddir/build/BUILD/rustc-1.42.0-src/src/liballoc/sync.rs:1249
    #53687 0x00005642f4b27c0e in core::ptr::drop_in_place () at /builddir/build/BUILD/rustc-1.42.0-src/src/libcore/ptr/mod.rs:174
    #53688 0x00005642f4b27ebe in core::ptr::drop_in_place () at /builddir/build/BUILD/rustc-1.42.0-src/src/libcore/ptr/mod.rs:174
    #53689 0x00005642f4b29a79 in core::ptr::drop_in_place () at /builddir/build/BUILD/rustc-1.42.0-src/src/libcore/ptr/mod.rs:174
    #53690 0x00005642f4b28bce in core::ptr::drop_in_place () at /builddir/build/BUILD/rustc-1.42.0-src/src/libcore/ptr/mod.rs:174
    #53691 0x00005642f4b28212 in core::ptr::drop_in_place () at /builddir/build/BUILD/rustc-1.42.0-src/src/libcore/ptr/mod.rs:174
    #53692 0x00005642f4b1d23b in alloc::sync::Arc<T>::drop_slow (self=0x5642f539d668) at /builddir/build/BUILD/rustc-1.42.0-src/src/liballoc/sync.rs:739
    #53693 0x00005642f4b1dfd6 in <alloc::sync::Arc<T> as core::ops::drop::Drop>::drop (self=0x5642f539d668) at /builddir/build/BUILD/rustc-1.42.0-src/src/liballoc/sync.rs:1249
    #53694 0x00005642f4b27c0e in core::ptr::drop_in_place () at /builddir/build/BUILD/rustc-1.42.0-src/src/libcore/ptr/mod.rs:174
    #53695 0x00005642f4b2a2b1 in core::ptr::drop_in_place () at /builddir/build/BUILD/rustc-1.42.0-src/src/libcore/ptr/mod.rs:174
    #53696 0x00005642f4b2b0da in core::ptr::drop_in_place () at /builddir/build/BUILD/rustc-1.42.0-src/src/libcore/ptr/mod.rs:174
    #53697 0x00005642f4b29a11 in core::ptr::drop_in_place () at /builddir/build/BUILD/rustc-1.42.0-src/src/libcore/ptr/mod.rs:174
    #53698 0x00005642f4b29761 in core::ptr::drop_in_place () at /builddir/build/BUILD/rustc-1.42.0-src/src/libcore/ptr/mod.rs:174
    #53699 0x00005642f4b27ed1 in core::ptr::drop_in_place () at /builddir/build/BUILD/rustc-1.42.0-src/src/libcore/ptr/mod.rs:174
    #53700 0x00005642f4b2a851 in core::ptr::drop_in_place () at /builddir/build/BUILD/rustc-1.42.0-src/src/libcore/ptr/mod.rs:174
    #53701 0x00005642f4b28021 in core::ptr::drop_in_place () at /builddir/build/BUILD/rustc-1.42.0-src/src/libcore/ptr/mod.rs:174
    #53702 0x00005642f4b27ea1 in core::ptr::drop_in_place () at /builddir/build/BUILD/rustc-1.42.0-src/src/libcore/ptr/mod.rs:174
    #53703 0x00005642f4b291f1 in core::ptr::drop_in_place () at /builddir/build/BUILD/rustc-1.42.0-src/src/libcore/ptr/mod.rs:174
    #53704 0x00005642f4b748d8 in core::ptr::drop_in_place () at /builddir/build/BUILD/rustc-1.42.0-src/src/libcore/ptr/mod.rs:174
    #53705 0x00005642f4b2ab55 in core::ptr::drop_in_place () at /builddir/build/BUILD/rustc-1.42.0-src/src/libcore/ptr/mod.rs:174
    #53706 0x00005642f4b2a111 in core::ptr::drop_in_place () at /builddir/build/BUILD/rustc-1.42.0-src/src/libcore/ptr/mod.rs:174
    #53707 0x00005642f4b2a901 in core::ptr::drop_in_place () at /builddir/build/BUILD/rustc-1.42.0-src/src/libcore/ptr/mod.rs:174
    #53708 0x00005642f4b27e01 in core::ptr::drop_in_place () at /builddir/build/BUILD/rustc-1.42.0-src/src/libcore/ptr/mod.rs:174
    #53709 0x00005642f4b29d51 in core::ptr::drop_in_place () at /builddir/build/BUILD/rustc-1.42.0-src/src/libcore/ptr/mod.rs:174
    #53710 0x00005642f4b28a59 in core::ptr::drop_in_place () at /builddir/build/BUILD/rustc-1.42.0-src/src/libcore/ptr/mod.rs:174
    #53711 0x00005642f4b2b261 in core::ptr::drop_in_place () at /builddir/build/BUILD/rustc-1.42.0-src/src/libcore/ptr/mod.rs:174
    #53712 0x00005642f4b748d8 in core::ptr::drop_in_place () at /builddir/build/BUILD/rustc-1.42.0-src/src/libcore/ptr/mod.rs:174
    #53713 0x00005642f4b7657d in <rodio::dynamic_mixer::DynamicMixer<S> as core::iter::traits::iterator::Iterator>::next (self=0x5642f523ba00) at /home/boeckb/.cargo/registry/src/github.com-1ecc6299db9ec823/rodio-0.11.0/src/dynamic_mixer.rs:133
    #53714 0x00005642f4b7072d in rodio::engine::audio_callback (engine=0x7f9499cceaf8, stream_id=..., buffer=...) at /home/boeckb/.cargo/registry/src/github.com-1ecc6299db9ec823/rodio-0.11.0/src/engine.rs:95
    #53715 0x00005642f4b71319 in <rodio::engine::play_raw::ENGINE as core::ops::deref::Deref>::deref::__static_ref_initialize::{{closure}}::{{closure}} (stream_id=..., buffer=...) at /home/boeckb/.cargo/registry/src/github.com-1ecc6299db9ec823/rodio-0.11.0/src/engine.rs:42
    #53716 0x00005642f4b6cd36 in <cpal::platform::platform_impl::EventLoop as cpal::traits::EventLoopTrait>::run::{{closure}} (id=..., result=...) at /home/boeckb/.cargo/registry/src/github.com-1ecc6299db9ec823/cpal-0.11.0/src/platform/mod.rs:350
    #53717 0x00005642f4b80ef7 in cpal::host::alsa::EventLoop::run_inner (self=0x5642f523b430, callback=...) at /home/boeckb/.cargo/registry/src/github.com-1ecc6299db9ec823/cpal-0.11.0/src/host/alsa/mod.rs:702
    #53718 0x00005642f4b6c5c8 in cpal::host::alsa::EventLoop::run (self=0x5642f523b430, callback=...) at /home/boeckb/.cargo/registry/src/github.com-1ecc6299db9ec823/cpal-0.11.0/src/host/alsa/mod.rs:567
    #53719 0x00005642f4b6ca11 in <cpal::host::alsa::EventLoop as cpal::traits::EventLoopTrait>::run (self=0x5642f523b430, callback=...) at /home/boeckb/.cargo/registry/src/github.com-1ecc6299db9ec823/cpal-0.11.0/src/host/alsa/mod.rs:135
    #53720 0x00005642f4b6cc35 in <cpal::platform::platform_impl::EventLoop as cpal::traits::EventLoopTrait>::run (self=0x5642f523b430, callback=...) at /home/boeckb/.cargo/registry/src/github.com-1ecc6299db9ec823/cpal-0.11.0/src/platform/mod.rs:348
    #53721 0x00005642f4b713a9 in <rodio::engine::play_raw::ENGINE as core::ops::deref::Deref>::deref::__static_ref_initialize::{{closure}} () at /home/boeckb/.cargo/registry/src/github.com-1ecc6299db9ec823/rodio-0.11.0/src/engine.rs:40
    #53722 0x00005642f4b6a3ce in std::sys_common::backtrace::__rust_begin_short_backtrace (f=...) at /builddir/build/BUILD/rustc-1.42.0-src/src/libstd/sys_common/backtrace.rs:129
    #53723 0x00005642f4b7764f in std::thread::Builder::spawn_unchecked::{{closure}}::{{closure}} () at /builddir/build/BUILD/rustc-1.42.0-src/src/libstd/thread/mod.rs:475
    #53724 0x00005642f4b71464 in <std::panic::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once (self=..., _args=()) at /builddir/build/BUILD/rustc-1.42.0-src/src/libstd/panic.rs:318
    #53725 0x00005642f4b7780b in std::panicking::try::do_call (data=0x7f9499ccec18 " \264#\365BV\000") at /builddir/build/BUILD/rustc-1.42.0-src/src/libstd/panicking.rs:305
    #53726 0x00005642f4ce3b77 in __rust_maybe_catch_panic ()
    #53727 0x00005642f4b7773b in std::panicking::try (f=...) at /builddir/build/BUILD/rustc-1.42.0-src/src/libstd/panicking.rs:281
    #53728 0x00005642f4b714c4 in std::panic::catch_unwind (f=...) at /builddir/build/BUILD/rustc-1.42.0-src/src/libstd/panic.rs:394
    #53729 0x00005642f4b7745a in std::thread::Builder::spawn_unchecked::{{closure}} () at /builddir/build/BUILD/rustc-1.42.0-src/src/libstd/thread/mod.rs:474
    #53730 0x00005642f4b742b4 in core::ops::function::FnOnce::call_once{{vtable-shim}} () at /builddir/build/BUILD/rustc-1.42.0-src/src/libcore/ops/function.rs:232
    #53731 0x00005642f4cd79ff in <alloc::boxed::Box<F> as core::ops::function::FnOnce<A>>::call_once ()
    #53732 0x00005642f4ce3140 in std::sys::unix::thread::Thread::new::thread_start ()
    #53733 0x00007f949aba14e2 in start_thread () from /lib64/libpthread.so.0
    #53734 0x00007f949aab66d3 in clone () from /lib64/libc.so.6
    

    The bottom of the stack is interesting as well:

    #0  0x00007f949a9f1625 in raise () from /lib64/libc.so.6
    #1  0x00007f949a9da8d9 in abort () from /lib64/libc.so.6
    #2  0x00005642f4ce3687 in std::sys::unix::abort_internal ()
    #3  0x00005642f4ce03a5 in std::sys_common::util::abort ()
    #4  0x00005642f4ce2ac0 in std::sys::unix::stack_overflow::imp::signal_handler ()
    #5  <signal handler called>
    #6  0x00007f949aa3e332 in _int_free () from /lib64/libc.so.6
    #7  0x00007f949aa408bc in free_check () from /lib64/libc.so.6
    #8  0x00005642f4bddc43 in alloc::alloc::dealloc (ptr=0x5642f60a3700 "\333\377\247\374\265\377\241\373\322\377+\373\017\000", layout=...) at /builddir/build/BUILD/rustc-1.42.0-src/src/liballoc/alloc.rs:103
    #9  0x00005642f4bdda2a in <alloc::alloc::Global as core::alloc::Alloc>::dealloc (self=0x5642f60a0778, ptr=..., layout=...) at /builddir/build/BUILD/rustc-1.42.0-src/src/liballoc/alloc.rs:174
    #10 0x00005642f4c06c43 in alloc::raw_vec::RawVec<T,A>::dealloc_buffer (self=0x5642f60a0778) at /builddir/build/BUILD/rustc-1.42.0-src/src/liballoc/raw_vec.rs:709
    #11 0x00005642f4c105df in <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (self=0x5642f60a0778) at /builddir/build/BUILD/rustc-1.42.0-src/src/liballoc/raw_vec.rs:719
    

    That free_check makes me wonder if MALLOC_CHECK_=3 is involved here, but that only signals bugs elsewhere.

    opened by mathstuf 10
  • No sound output when using default Endpoint (ALSA)

    No sound output when using default Endpoint (ALSA)

    So this is a bit strange: when running the cpal's "beep" example (which uses get_default_endpoint) everything works as expected but running rodio's "basic" example (which also uses the re-exported get_default_endpoint) no sound is playing.

    Using the first endpoint from get_endpoints_list works as expected (in both examples).

    I tried changing the format selection to use the first format like in the cpal example but that didn't help.

    Apparently something's not right with the event loop because after I inserted a println here it's only printed exactly once.

    edit: (In both examples the default endpoint is named "default" and the first endpoint from get_endpoints_list is "pulse".)

    opened by Bobo1239 10
  • AAC tracks playing back at 2x speed

    AAC tracks playing back at 2x speed

    Using the new symphonia backends, playing back an AAC track in an MP4 container yields 2x speed playback through rodio. This behavior is not observed when playing the same track through the symphonia-play utility, nor is it observed when manually setting the rodio decoder to use redlux.

    This may be a mismatch in the sample rate being reported to rodio for these tracks, as they all use SBR, and some additionally use PS, to allow (but not require) upconversion from a lower base sample rate to a higher rate.

    bug 
    opened by compenguy 9
  • Better error handling for stream creation

    Better error handling for stream creation

    I am a contributor to Veloren (an open source game) and we have had players with different devices reaching the expects in stream.rs. This MR removes all the expects and replaces it with some error handling. Instead of panicking, this will allow the program to decide what to do with the error. You can ignore the changes in src/decoder/mod.rs, that was just a result of cargo fmt.

    opened by jiminycrick 9
  • [Question] Is there any good way to restart the sink?

    [Question] Is there any good way to restart the sink?

    image

    As above, I want to remove the existing sink playback and play the new audio.

    But it seems to me that only the Sink::stop method stops existing playback. However, if it is stopped, it cannot be restarted.

    Do you have any recommendations for how to do this?

    opened by myyrakle 0
  • Cannot get any better than 12-16 ms latency

    Cannot get any better than 12-16 ms latency

    #[allow(dead_code)]
    pub struct SamplePlayer {
        output_handle: OutputStreamHandle,
        stream: OutputStream,
    }
    
    impl SamplePlayer {
        pub fn new() -> Self {
            let (_stream, stream_handle) = OutputStream::try_default().unwrap();
            Self { output_handle: stream_handle, stream: _stream }
        }
    
        pub fn play_sample(&self, sample: &Sample) {
            let now = Instant::now();
            let _ = &self.output_handle.play_raw(sample.raw_audio.clone());
            println!("{}", now.elapsed().as_secs_f32() * 1000.);
        }
    }
    
    

    Sample:

    pub struct Sample {
        pub raw_audio: SamplesConverter<Buffered<Decoder<File>>, f32>,
    }
    
    impl Sample {
        pub fn new(file: File) -> Self {
            let source = Decoder::new(file).unwrap();
            let buffer = source.buffered();
    
            Self {
                raw_audio: buffer.convert_samples(),
            }
        }
    
        pub fn new_from_filepath(path: String) -> Self {
            let f = File::open(path).unwrap();
            Self::new(f)
        }
    }
    
    

    Hello everybody, I'm working on a simple drum machine. Since this is an instrument, it's latency must be lower than ~8 ms. But I cannot get any lower than 12-16 ms right now. And I know, this is a playback library and might not be the right way to create a low latency instrument, but I think 16 ms is still way too much for a playback library.

    This is the project link if you want to check the entire code. I can create a small test version of just the audio part if needed.

    opened by ramazanemreosmanoglu 0
  • MP3 current_ frame_ Len and total_ Duration will never change

    MP3 current_ frame_ Len and total_ Duration will never change

    MP3 source. current_ frame_ The value returned by len() is always Some (2304)

    source. total_ The value returned by duration is always None

    Several different music files have been tested. This cannot be a problem with the music file itself. Other music players can obtain it normally

    Or is there any other similar open source project recommended!!

    opened by yunfengwangluo 0
  • How to obtain the current playing time and position when rodio plays music files

    How to obtain the current playing time and position when rodio plays music files

    How to obtain the current playing time and position when rodio plays music files

    At present, I want to try to build a simple music playing software,

    Music playing software needs the most basic

    "Total duration" of music files

    Current play position "Play time position"

    Jump to the specified position "Time Position"

    I don't know how to get the "play time position" at present

    Thank you for your help

    opened by yunfengwangluo 0
  • Added a storing file example.

    Added a storing file example.

    This is an example of loading files and playing them several times after reading issue #423. It would not make a lot of sense for larger audio as it is not streaming.

    One downside of that is that, when adding operation to the saved file, the type becomes painfully long in rust as per the example : Buffered<TakeDuration<SkipDuration<Buffered<Decoder<BufReader<File>>>>>>.

    I'm not really sure how to address that for now.

    opened by Ownezx 0
  • Fix: Audio playback not working after stop on sink

    Fix: Audio playback not working after stop on sink

    Hi,

    I'm working on a project of my own in which I'm using rodio for audio playback, however I came across the issue that I am unable to play audio after I've called the .stop method on rodio::sink::Sink, in my project I've fixed this by changing the .play method on Sink to this:

        #[inline]
        pub fn play(&self) {
            self.controls.stopped.store(false, Ordering::SeqCst);
            self.controls.pause.store(false, Ordering::SeqCst);
        }
    

    At first I thought the documentation for .stop was wrong, but it turns out it does actually clear the queue but it completely prevents your Sink from doing any more audio playback (at least I wasn't able to figure out how to make it play anything after the fact).

    This fix works for me, and I'd like some feedback on whether this is a feasible solution, warning I'm pretty new to Rust.

    P.S. the tests ran fine

    opened by pixelafk 3
Owner
Free and useful Audio, DSP and music libraries written in Rust. Discourse https://rust-audio.discourse.group/ Discord https://discord.gg/b3hjnGw
null
Flutter crossplatform audio playback library powered by golang beep & oto

Rowdy Pure Rust based Dart/Flutter audio playback library Installation $ flutter pub add rowdy Configuration You'll need the Rust toolchain installed

Kingkor Roy Tirtho 3 Aug 31, 2022
A tool that switch default audio playback device on windows.

AudioSwitch A tool built by Rust that can switch default audio playback device on windows. How to use specify which device you want to use Execute it

null 2 Aug 28, 2022
Cross-platform audio I/O library in pure Rust

CPAL - Cross-Platform Audio Library Low-level library for audio input and output in pure Rust. This library currently supports the following: Enumerat

null 1.8k Jan 8, 2023
Rust bindings for the soloud audio engine library

soloud-rs A crossplatform Rust bindings for the soloud audio engine library. Supported formats: wav, mp3, ogg, flac. The library also comes with a spe

Mohammed Alyousef 38 Dec 8, 2022
Symphonia is a pure Rust audio decoding and media demuxing library supporting AAC, FLAC, MP3, MP4, OGG, Vorbis, and WAV.

Pure Rust multimedia format demuxing, tag reading, and audio decoding library

Philip Deljanov 1k Jan 2, 2023
A library and application for lossless, format-preserving, two-pass optimization and repair of Vorbis data, reducing its size without altering any audio information.

OptiVorbis A library and application for lossless, format-preserving, two-pass optimization and repair of Vorbis data, reducing its size without alter

OptiVorbis 27 Jan 3, 2023
TinyAudio is a cross-platform audio output library

TinyAudio TinyAudio is a cross-platform audio output library. Its main goal to provide unified access to a default sound output device of your operati

Dmitry Stepanov 39 Apr 4, 2023
Implements the free and open audio codec Opus in Rust.

opus-native Overview Implements the free and open audio codec Opus in Rust. Status This crate is under heavy development. Most functionality is not wo

Nils Hasenbanck 9 Nov 28, 2022
Rust - Augmented Audio Libraries

Augmented Audio Libraries In this repository I'll push some experiments trying to use Rust for audio programming. Goals Goal 1: Learn & have fun This

Pedro Tacla Yamada 116 Dec 18, 2022
CLI Rust Audio Visualizer

crav Console-based Rust Audio Visualizer It can run in the terminal but also has a 3D accelerated backend implemented in wgpu. demo compatibility The

null 20 Oct 16, 2022
Simple examples to demonstrate full-stack Rust audio plugin dev with baseplug and iced_audio

iced baseplug examples Simple examples to demonstrate full-stack Rust audio plugin dev with baseplug and iced_audio WIP (The GUI knobs do nothing curr

Billy Messenger 10 Sep 12, 2022
MVC audio plugin framework for rust

__ __ | |--.---.-.-----.-----.-----.| |.--.--.-----. | _ | _ |__ --| -__| _ || || | | _ | |

william light 93 Dec 23, 2022
simple-eq is a crate that implements a simple audio equalizer in Rust.

simple-eq A Simple Audio Equalizer simple-eq is a crate that implements a simple audio equalizer in Rust. It supports a maximum of 32 filter bands. Us

Mike Hilgendorf 11 Sep 17, 2022
A simple GUI audio player written in Rust with egui. Inspired by foobar2000.

Music Player A simple GUI music player inspired by foobar2000 written in Rust using egui. The goal of this project is to learn about making gui/ nativ

Ryan Blecher 5 Sep 16, 2022
Rust Audio Player Daemon

Rust Audio Player Daemon Cause mpd was annoying What rapd trys to do Rapd is not a spotify client, or an advanced music player. Its an audio/music dae

ash 3 Nov 1, 2022
API-agnostic audio plugin framework written in Rust

Because everything is better when you do it yourself - Rust VST3 and CLAP framework and plugins

Robbert van der Helm 415 Dec 27, 2022
Cross-platform audio for Rust

quad-snd High-level, light-weight, and opinionated audio library. Web: WebAudio Android: OpenSLES Linux: Alsa macOS: CoreAudio Windows: Wasapi iOS: Co

Fedor Logachev 86 Nov 7, 2022
DSP real time audio synthesis, effect algorithms and utilities for Rust

synfx-dsp synfx-dsp DSP real time audio synthesis, effect algorithms and utilities for Rust Most of the algorithms and implementations in this library

Weird Constructor 8 Nov 23, 2022
Quite OK Audio format in Rust.

QOA - The Quite Ok Audio Format This is a pure Rust (zero dependency) implementation of the QOA audio format. This code is based off the reference C i

Rafael CarĂ­cio 10 Apr 16, 2023