ExPixel / miniaudio-rs

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

Cannot get full device info #2

Closed blueneogeo closed 4 years ago

blueneogeo commented 4 years ago

Hi, apologies in advance if I am using the library wrong, I am a beginner Rustian.

I am using your device detection example code on a Mac and also wanted to check for the channels, samplerate and formats, like this:

context
        .with_devices(|playback_devices, _| {
            println!("Playback Devices:");
            for (idx, device) in playback_devices.iter().enumerate() {
                println!("\t{}: {}", idx, device.name());
                println!("max channels {}", device.max_channels());
                println!("max sample rate {}", device.max_sample_rate());
                for format in device.formats().iter() {
                    println!("format {:?} bytes supported", format);
                }
            }
        })
        .expect("failed to get devices");

However I get this output, where max channels, samplerate and formatting all seem empty. However there do seem to be 6 supported empty formats...:

Playback Devices:
    0: Built-in Output
max channels 0
max sample rate 0
format Unknown bytes supported
format Unknown bytes supported
format Unknown bytes supported
format Unknown bytes supported
format Unknown bytes supported
format Unknown bytes supported
Capture Devices:
    0: Built-in Microphone
Device Backend: CoreAudio
Press ENTER/RETURN to exit...
ExPixel commented 4 years ago

That's really odd, but I can't reproduce it as I don't have access to a Mac at the moment. It might be an issue with the types being generated by bindgen. If you have time, it would help a lot if you posted the results you get from running this code:

use miniaudio::{Context, Device, DeviceInfo, DeviceType};

pub fn main() {
    println!("sizeof(device) = {} bytes", std::mem::size_of::<Device>());
    println!(
        "sizeof(device_info) = {} bytes",
        std::mem::size_of::<DeviceInfo>()
    );
    println!("sizeof(context) = {} bytes", std::mem::size_of::<Context>());

    let context = Context::alloc(None, None).expect("failed to create context");

    println!("Devices:");
    context
        .enumerate_devices(|_, device_type, device_info| {
            let device_type_str = match device_type {
                DeviceType::Playback => "Playback",
                DeviceType::Capture => "Capture",
                DeviceType::Duplex => "Duplex",
                DeviceType::Loopback => "Loopback",
            };

            println!("\t[{}] {}", device_type_str, device_info.name());
            print_device_info_bytes(device_info);

            true
        })
        .expect("failed to enumerate devices");
}

fn print_device_info_bytes(device_info: &DeviceInfo) {
    let size = std::mem::size_of::<DeviceInfo>();
    let ptr = device_info as *const DeviceInfo as *const u8;
    unsafe {
        let mut row = 0;
        let slice = std::slice::from_raw_parts(ptr, size);
        println!("Device Info Bytes:");
        for byte in slice.iter() {
            print!("{:02X} ", *byte);
            row += 1;
            if row >= 32 {
                row = 0;
                println!();
            }
        }
        println!("\n");
    }
}

Just so I can get an idea of what types are being generated and where the 0's are coming from.

blueneogeo commented 4 years ago

I got the following output:

sizeof(device) = 21776 bytes
sizeof(device_info) = 560 bytes
sizeof(context) = 616 bytes
Devices:
        [Capture] Built-in Microphone
Device Info Bytes:
41 70 70 6C 65 48 44 41 45 6E 67 69 6E 65 49 6E 70 75 74 3A 31 42 2C 30 2C 31 2C 30 3A 31 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
42 75 69 6C 74 2D 69 6E 20 4D 69 63 72 6F 70 68 6F 6E 65 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 

        [Playback] Built-in Output
Device Info Bytes:
41 70 70 6C 65 48 44 41 45 6E 67 69 6E 65 4F 75 74 70 75 74 3A 31 42 2C 30 2C 31 2C 31 3A 30 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
42 75 69 6C 74 2D 69 6E 20 4F 75 74 70 75 74 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
blueneogeo commented 4 years ago

I have a macbook pro 15 inch 2013, without any other audio devices connected.

ExPixel commented 4 years ago

So, turns out this output is actually correct. Miniaudio sets those to 0 when enumerate devices or get_device_info is called. I should add a way to query that information though.

typedef struct
{
    /* Basic info. This is the only information guaranteed to be filled in during device enumeration. */
    ma_device_id id;
    char name[256];

    /*
    Detailed info. As much of this is filled as possible with ma_context_get_device_info(). Note that you are allowed to initialize
    a device with settings outside of this range, but it just means the data will be converted using miniaudio's data conversion
    pipeline before sending the data to/from the device. Most programs will need to not worry about these values, but it's provided
    here mainly for informational purposes or in the rare case that someone might find it useful.

    These will be set to 0 when returned by ma_context_enumerate_devices() or ma_context_get_devices().
    */
    ma_uint32 formatCount;
    ma_format formats[ma_format_count];
    ma_uint32 minChannels;
    ma_uint32 maxChannels;
    ma_uint32 minSampleRate;
    ma_uint32 maxSampleRate;

    struct
    {
        ma_bool32 isDefault;
    } _private;
} ma_device_info;
blueneogeo commented 4 years ago

Great, thank you for the quick response

ExPixel commented 4 years ago

Alright I changed the API a bit so that that information available is clearer and added a way to get sample rate and formats. New version will be available on crates.io in a bit.

Also extended the enumeration example: https://github.com/ExPixel/miniaudio-rs/blob/93d00d2baeb211dacef638b1cb8d317f35f89efb/miniaudio/examples/simple-enumeration.rs#L1-L46