Skip to main content

Notice

Please note that most of the software linked on this forum is likely to be safe to use. If you are unsure, feel free to ask in the relevant topics, or send a private message to an administrator or moderator. To help curb the problems of false positives, or in the event that you do find actual malware, you can contribute through the article linked here.
Topic: What is the best way to buffer the on_chunk chunks in a dsp plugin? (Read 1790 times) previous topic - next topic
0 Members and 1 Guest are viewing this topic.

What is the best way to buffer the on_chunk chunks in a dsp plugin?

Hi folks,

I'm trying to get my hands on DSP plugin development by writing a simple delay line of significant amount of time (say around 20s). Later I'll process those samples but first things first.

For now, I added a m_chunk attribute to my dsp_impl_base child.
Code: [Select]
audio_chunk_impl m_chunk;  // in member declaration 
And during each on_chunk call I append to it
Code: [Select]
bool on_chunk(audio_chunk * chunk,abort_callback &)
{
// ...
// output the buffered stuff (hen m_chunk big enough
audio_chunk * out = insert_chunk(buffer_size * m_ch);
audio_sample * src = m_chunk.get_data();
out->set_data(src, buffer_size, m_ch, m_rate, m_ch_mask);
m_chunk.skip_first_samples(buffer_size);

// ...

// buffer the input
m_chunk.grow_data_size((buffered + sample_count) * m_ch);
audio_sample * src2 = chunk->get_data();
audio_sample * dst2 = m_chunk.get_data();
dst2 += buffered * m_ch;
for (t_size i = 0, j = sample_count * m_ch; i < j; i++)
{
*dst2++ = *src2++;
}
}

I don't want you to solve everything, and there are probably some bugs in my code, but would like a few hints!
  • Is it a good idea to store input chunks in this big "audio_chunk_impl m_chunk member" ? Or would it better to instead copy each chunk to list of audio_chunk member? Or to save it in a pfc::array_t<audio_sample>? Or is it mandatory to use circular buffers (I'd like to avoid them in a first stage, and optimize that later)?
  • Any idea why when I call m_chunk.skip_first_samples(buffer_size); it seems to completely empty m_chunk and not only the few samples (buffer_size) I asked? I thought skip_first_samples would simply move the chunk starting address (and probably de-allocate the skipped ones).
  • Finally, a more general question, for the future steps: how often does on_chunk() method get called? Is it called at the playback speed and the chunk is then quickly sent to the hardware? Or could it go faster than the playback speed and then store somewhere the chunk (and the inserted one) until they are played? Hope this makes sense. I'm asking because I want to have a "lookahead" of ~20s of signal, but I will actually only process them only at the end of the file. Therefore, I don't need (nor want) to wait before the track starts for 20s. All I need is to have in advance the 20 last seconds of the track. (Assuming I only play tracks longer than 20s)

Please note that I'm no expert at all in c++.

Cheers!

Re: What is the best way to buffer the on_chunk chunks in a dsp plugin?

Reply #1
Is it a good idea to store input chunks in this big "audio_chunk_impl m_chunk member" ? Or would it better to instead copy each chunk to list of audio_chunk member? Or to save it in a pfc::array_t<audio_sample>? Or is it mandatory to use circular buffers (I'd like to avoid them in a first stage, and optimize that later)?
Just to get things running you can use pretty much any method. Circular buffer will of course be the fastest. The method you use now can involve a lot of reallocations and certainly involves a lot of moving memory contents around. The skip_first_samples function for example moves all the rest of the buffer contents to the beginning of the buffer. List would avoid that. Whether you use audio_chunk_impl or pfc::array_t or any other way to allocate memory shouldn't matter.

Any idea why when I call m_chunk.skip_first_samples(buffer_size); it seems to completely empty m_chunk and not only the few samples (buffer_size) I asked?
It should only empty the buffer when you request larger skip amount than there are samples in the buffer.

Finally, a more general question, for the future steps: how often does on_chunk() method get called? Is it called at the playback speed and the chunk is then quickly sent to the hardware?
The function is called as rapidly as possible when used outside audio playback and during audio playback when output buffer has room. So when playback starts you don't have to wait for 20 seconds to buffer 20 seconds worth of audio. It will be some milliseconds on modern machine and fast audio formats. Exception of course is if user plays steaming media. It won't arrive faster than realtime.

Re: What is the best way to buffer the on_chunk chunks in a dsp plugin?

Reply #2
It should only empty the buffer when you request larger skip amount than there are samples in the buffer.
I'll directly go with circular buffers then, as I can't make m_chunk.skip_first_samples do the expected thing..

The function is called as rapidly as possible when used outside audio playback and during audio playback when output buffer has room. So when playback starts you don't have to wait for 20 seconds to buffer 20 seconds worth of audio. It will be some milliseconds on modern machine and fast audio formats. Exception of course is if user plays steaming media. It won't arrive faster than realtime.
Makes sense, to rephrase it for future readers and future me, if I understand correctly, the on_chunk callbacks are actually triggered from the hardware (through drivers etc.) each time it needs some stuff to be played out.

Thanks!

Re: What is the best way to buffer the on_chunk chunks in a dsp plugin?

Reply #3
Such low level access is probably only needed in output component. In there audio driver can request more data which the component then provides from its internal buffers. The core polls output component every now and then and the component replies whether it can take more data or not.