-
Notifications
You must be signed in to change notification settings - Fork 57
Description
Hi @jamesmunns,
Awesome project! I am using BBQueue to shuffle audio data from a producer loop that is temporally unstable (some audio frames take longer to process than others) into a buffer and then reading that data at very critically timed intervals (inside an I2S interrupt) to pass it to a digital to analog converter. I've tried to distill the essence of this setup in the code below.
// runs forever
fn producer_task(producer: &mut Producer<'_, 1000>) {
loop {
match producer.grant_exact(100) {
Ok(mut grant) => {
grant.to_commit(100);
// get audio bytes and copy them into write grant
}
Err(_) => {
// Input queue full, this is normal
// the i2s interrupt firing should free up space
cortex_m::asm::wfi();
}
}
}
}
// fired by interrupt every 10 ms
fn consumer_task(previous_grant: GrantR<'_, 1000>, consumer: &mut Consumer<'_, 1000>) {
previous_grant.release(100);
match consumer.read() {
Ok(grant) => {
long_running_dma_copy(grant);
}
Err(_) => {
// no audio to play - play silence
}
}
}The long running consumer read operation holds the read grant for all the data available to read when it only really needs to read a small chunk here (100 bytes). This seems to put undue back-pressure on the producer resulting in the whole thing operating more like a turnstyle than a buffer.
My current solution to this problem is to use a double buffer and copy the data out of the BBQueue read grant and release the grant immediately. The double buffer is needed because there is only really enough time to switch pointers in this I2S interrupt handler or the audio will glitch.
My question is this, would it be possible to hold a read grant for only a small window of the data (say 100 bytes out of 1000) so that the producer can continue to write data to the queue elsewhere. Like a read_exact() function on the consumer. This may not be possible due to how read and write pointers work in bip buffers. However, if you think it is possible and worthwhile adding then I would like to attempt to implement it.
PS, I took a look at the framed stuff but that pesky frame length header messes up my alignment!