Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No way to create a non-interleaved non-blocking stream #139

Open
eeeeeta opened this issue Jul 5, 2016 · 2 comments
Open

No way to create a non-interleaved non-blocking stream #139

eeeeeta opened this issue Jul 5, 2016 · 2 comments

Comments

@eeeeeta
Copy link

eeeeeta commented Jul 5, 2016

As far as I can see (although I may have missed something); there's no way to create a non-interleaved non-blocking stream with safe code (i.e. not transmute()ing the callback arg to &mut [&mut [f32]]). Am I correct here, and what could be done to resolve this problem?

I will add that providing data in interleaved form, in my use case, requires significant extra processing in the audio thread to do (loop through non-interleaved buffers, which must be preallocated & write to interleaved buffer).

@eeeeeta
Copy link
Author

eeeeeta commented Jul 5, 2016

Workaround, for anyone else (warning: untested, probably very unsafe):

const CHANNELS: usize = 2;
let callback = move |pa::stream::OutputCallbackArgs { buffer, frames, .. }| {
    let buffr: &mut [*mut f32];
    unsafe {
        let buffer: *mut *mut f32 = ::std::mem::transmute(buffer.get_unchecked_mut(0));
        buffr = ::std::slice::from_raw_parts_mut(buffer, CHANNELS);
        let first_channel_buffer = ::std::slice::from_raw_parts_mut(buffr[0], frames);
        let second_channel_buffer = ::std::slice::from_raw_parts_mut(buffr[1], frames);
    }
    pa::Continue
};

@mitchmindtree
Copy link
Member

You're right, support for writing to non-interleaved buffers hasn't yet been added, though it would be a welcome addition!

Currently StreamParameters takes an is_interleaved bool at runtime (which is unhandled at the callback end as you've discovered). It would be nicer to have this moved to the type level so that the user receives errors about mis-use at compile time instead of runtime. I've been meaning to add something along the lines of a Buffer trait but haven't had time.

pub<S> trait Buffer<S> {
    fn is_interleaved() -> bool;
    // Other buffer handling methods.
}

impl<'a, S> Buffer<S> for [&'a [S]] {
    fn is_interleaved() -> bool {
        false
    }
    ...
}

impl<S> Buffer<S> for [S]  {
    fn is_interleaved() -> bool {
        true
    }
    ...
}

Something like this might allow the compiler to infer whether or not the buffer is interleaved by examining the buffer type used in the callback args at compile time. This way we might be able to get away with removing the need for a is_interleaved bool param altogether.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants