ExPixel / miniaudio-rs

Rust bindings for miniaudio C library.
https://crates.io/crates/miniaudio
MIT License
49 stars 20 forks source link

Example fails with devide by zero #28

Closed jpochyla closed 4 years ago

jpochyla commented 4 years ago

On Mac, simple-playback-decoder example fails with 'attempt to divide by zero' because decoder.output_format() most probably returns Unknown, that has zero size_in_bytes(). Compilled with default futures, debug build.

Unfortunately I'm not sure how to go about fixing it right now.

Thanks for the library!

ExPixel commented 4 years ago

Decoders weren't being initialized properly but I'm not sure if that's the cause of this problem. If this continues to happen with version 0.9.0 does it start working if you change the example to use a specific format like this?

use miniaudio::{Decoder, DecoderConfig, Device, DeviceConfig, DeviceType, Format};

pub fn main() {
    let mut decoder = Decoder::from_file(
        "miniaudio/examples/assets/exit.wav",
        Some(&DecoderConfig::new(Format::S32, 2, 44100)),
    )
    .expect("failed to initialize decoder from file");

    let mut config = DeviceConfig::new(DeviceType::Playback);
    config.playback_mut().set_format(Format::S32);
    config
        .playback_mut()
        .set_channels(decoder.output_channels());
    config.set_sample_rate(decoder.output_sample_rate());

    // config.set_data_callback(move |_device, _output, _frames| {
    //     println!("ignored");
    // });

    // This stop callback can go on the config because it is cloneable.
    config.set_stop_callback(|_device| {
        println!("Device Stopped.");
    });

    let mut device = Device::new(None, &config).expect("failed to open playback device");

    // Unlike `SyncDecoder`, Decoder is not cloneable so we have to use a version of the data
    // callback that doesn't require everything that we pass into it to be cloneable. So here we
    // use a device specific data callback.
    device.set_data_callback(move |_device, output, _frames| {
        decoder.read_pcm_frames(output);
    });

    device.start().expect("failed to start device");

    println!("Device Backend: {:?}", device.context().backend());
    wait_for_enter();
    println!("Shutting Down...");
}

/// Shows a prompt and waits for input on stdin.
fn wait_for_enter() {
    use std::io::Write;

    print!("Press ENTER/RETURN to exit...");
    // Make sure the line above is displayed:
    std::io::stdout().flush().expect("failed to flush stdout");
    // Just read some random line off of stdin and discard it:
    std::io::stdin()
        .read_line(&mut String::new())
        .expect("failed to wait for line");
}
sagacity commented 4 years ago

I can confirm the issue, although I did get a different error, on the current master branch: output and decoder format did not match (output: Unknown, input: S16

Changing the player in the way you've described gives a different error: output and decoder format did not match (output: Unknown, input: S32

I did a little bit of searching through old commits, btw. The playback-decoder example in commit 99386d4edd9ee6be5131e3ed1d0054621936617e does give me a divide by zero error. f4a5f5d works fine. Perhaps the bump in miniaudio version in 5683423a082c6b28a6ea86b46609dbed53722c1c is causing the issue?

Anyway, perhaps the output: Unknown error is the same as the divide by zero error, it's just manifesting in a different way? Hopefully pinpointing the commit is a bit of a help for you.

I'm happy to test some more things for you, provided I can make the time.

skomski commented 4 years ago

You need to compile with the feature bindgen because the supplied bindings are not plattform independent but currently also the build.rs is borked. Some missing imports needst be fixed.

ExPixel commented 4 years ago

Yeah, for some reason I thought removing bindgen would be a good idea to reduce the dependencies but as it turns out this was not a good move because miniaudio places a lot of OS specific structures behind #ifdefs. I think my builds were even failing at one point because of alignment issues on GitHub Actions but I did the classic move and turned the tests off (lmao). I'll probably yank the versions with optional bindgen. Had some time Today so I've been working on tests using the Null device to prevent broken bindings.

sagacity commented 4 years ago

I can confirm that the master branch works fine now, on macOS CoreAudio.

ExPixel commented 4 years ago

Good to hear 👍. Thanks for taking the time to help me debug this.