cycfi / q

C++ Library for Audio Digital Signal Processing
MIT License
1.17k stars 151 forks source link

Direct access to `audio_stream` samples #71

Open bandithedoge opened 3 months ago

bandithedoge commented 3 months ago

In short, I have an audio_stream doing some processing and I want to display a waveform in my GUI. Without copying the entire buffer somewhere else during each process() call, is there a way to read the current buffer of a running audio stream?

djowel commented 3 months ago

There currently is no way to do it. Take note that audio_stream is a thin wrapper over portaudio. Have a look at portaudio API. If portaudio API allows it, then it can be added to audio_stream. I'll welcome a PR in that case.

But look at it this way. audio_stream is real-time. It gets the samples as they come in. How would it know the audio samples that will happen in the future?

bandithedoge commented 3 months ago

I initially used Portaudio in my project directly and I'm in the middle of migrating it to Q. There were no fancy buffer types, just an array of floats so accessing sample data was trivial.

But look at it this way. audio_stream is real-time. It gets the samples as they come in. How would it know the audio samples that will happen in the future?

The waveform's size is equal to the current buffer size and refreshes every time a buffer finishes processing.

djowel commented 3 months ago

I initially used Portaudio in my project directly and I'm in the middle of migrating it to Q. There were no fancy buffer types, just an array of floats so accessing sample data was trivial.

In that case, you can access the contents of the buffer just fine. The mulli_buffer is just a wrapper over the buffer that Portaudio provides. See https://cycfi.github.io/q/q/v1.0_beta/reference/support/multi_buffer.html

djowel commented 3 months ago

Alternatively, we can provide access to the data in the form of T** (e.g. float**). Is that what you were asking for? It's an easy tweak. The data is already there. Would you be willing to do a PR and doc update?

bandithedoge commented 3 months ago

Yes, that's exactly it. I'm willing to open a PR for this.

bandithedoge commented 3 months ago

Portaudio doesn't allow you to read from a callback-based stream outside of the callback. Since audio_stream is always a callback stream, this might be impossible without significant changes to Q's API.

djowel commented 3 months ago

Portaudio doesn't allow you to read from a callback-based stream outside of the callback.

Yes, that is expected. It's a real-time system. All real-time audio systems have similar interfaces. You have to go through the callback.

bandithedoge commented 3 months ago

So from what I understand the only way to access sample data outside of the callback would be to copy the buffer somewhere else every time the callback is run, right?

djowel commented 3 months ago

So from what I understand the only way to access sample data outside of the callback would be to copy the buffer somewhere else every time the callback is run, right?

Correct. Just make sure you synchronize access to your buffer from multiple threads.