From AudioBlock<float> to AudioBuffer<float>


#1

i know that this may sound very dumb question, but as i can easily create an AudioBlock type from a buffer:

dsp::AudioBlock<float> myAudioBlock (myAudioBuffer);

is there something to do the exact opposite? to have an AudioBuffer from an AudioBlock?
thx as always in advance


#2

An AudioBlock doesn’t own any data, it only points to data, so your question doesn’t make sense. Maybe reform the question with what it is you are looking to do, instead of how you want to do it.


#3

Thx for answering, sorry if my question is non sense, for example i’m in the ProcessBlock function of DspModuleDemo where i have:

dsp::AudioBlock<float> block (inoutBuffer);

process(dsp::ProcessContextReplacing<float>(block));

now inside the process function

void DspModulePluginDemoAudioProcessor::process (dsp::ProcessContextReplacing<float> context) noexcept

inputVolume.process (context);

highPassFilter.process (context);;

//other processing Functions down here.....

i assume what i’m processing in the process function is the inoutBuffer of the ProcessBlock function, i need a copy in another Audiobuffer the inoutBuffer partially processed, so inside the process function i would want to access inoutBuffer and copy it to another buffer after processing the Input and the highPassFilter for example, so when back in the processBlock function there will be inoutBuffer fully processed plus i will have another AudioBuffer with a copy of inoutBuffer but only with inputVolume and highPassFilter processed, this is i thought to get an audioBlock from context and put it into an AudioBuffer, hope it make sense


#4

I haven’t used the dsp functions yet, and I still don’t understand your need for a copy. I will let someone familiar with the dsp classed answer you.


#5

i think i got it:

auto audioBufferBlock = context.getOutputBlock();

audioBufferCopy.setSize(audioBufferBlock.getNumChannels(), audioBufferBlock.getNumSamples(), false, false, true);

for (int channel = 0; channel < audioBufferBlock.getNumChannels(); ++channel) audioBufferCopy.copyFrom(channel, 0, audioBufferBlock.getChannelPointer(channel), audioBufferBlock.getNumSamples());

i think that should give me in audioBufferCopy the state of the audio buffer processed untill that moment, before it get processed with the next processing functions (or at least i hope :smiley: )

thx for your time and explanation about the audioblock


#6

I just learned today at the workshop, that the AudioBlock also can own data, using this constructor: dsp::AudioBlock< SampleType >::AudioBlock (HeapBlock< char > & heapBlockToUseForAllocation, size_t numberOfChannels, size_t numberOfSamples).

So you can create a copy AudioBlock as well:

HeapBlock<char> data;
AudioBlock<Type> copyBlock (data, context.getNumChannels(), context.getNumSamples());

Alternatively to copying you could use the ProcessorContextNonReplacing, processing the first part of your processing chain into the allocated one, and the second chain from that one back into the block from your call, so you don’t have to copy anything…

Hope that makes sense…

P.S. don’t forget, never allocate in the processBlock!


#7

Interesting solution, i will try this also and let you to know, did not allocate the buffer in the processBlock, but why would it be bad?


#8

The documentation says what I said: “This class doesn’t own any of the data which it points to, it’s simply a view into data that is owned elsewhere.” (https://juce.com/doc/classdsp_1_1AudioBlock#details). And, In the constructor you linked to the memory is owned by the HeapBlock, not the AudioBlock.


#9

Technically you are correct, the HeapBlock owns the data. The allocation of the data is done in the constructor of the AudioBlock though…
I think the dsp module is still in flux, so the comment in the docs can be argued with.

Because allocating memory is not guaranteed to return fast enough to be real time safe. If memory gets low, it might swap to slower memory, copy to different memory pages or other things. So this would block your audio thread and the stream would be interrupted.


#10

Well, ‘technically’ is all we have in talking about how software works, yes? Regardless of where the memory is allocated, it belongs to the HeapBlock, and the HeapBlock is not owned by the AudioBlock. And, unless I am misunderstanding something, the code you posted doesn’t copy an AudioBlock, it just creates an AudioBlock that points to a HeapBlock that will be the same size/config of the context. At which point you could copy the contents of the context into the HeapBlock.

I’ll assume you have some other information that informs your comment about the ‘docs can be argued with’, because the current main branch code adheres to the docs.


#11

I am sorry, I am leaving it with that, I wasn’t about to argue with you, I think the OP got his problem solved, that’s what matters to me.
Cheers,
Daniel


#12

I didn’t think we were arguing. I thought we were discussing a difference of opinions regarding the AudioBlock class. I apologize if it felt like I was arguing by stating where I thought you were incorrect. This message board is a great resource for people to find information about the library, and making sure the information is correct is important. And the details are important, so I was just trying to iron those details out. I want to be able to use the library to it’s fullest, and after reading your initial post I thought it was possible I misunderstood the AudioBlock class. I went and read the source code and came back to update the discussion with that information. I had hoped to get consensus on the understanding of the class, instead of an exit from the conversation. But, fair enough. :slight_smile:


#13

No worries, I don’t feel bad at all, and I realise, that my comment was a bit wobbly. It was a side note at the workshop, that you can give the AudioBlock a HeapBlock, that it will use. And in the constructor I read, that there the allocation happens to hold the actual number of samples/channels/sampletype. So I summed that up like I did. But you are correct, there is no ownership in the AudioBlock of the data.
I just wanted to show the OP a way, how he can use the AudioBlock without switching between AudioBlock and AudioBuffer, which is possible by creating the AudioBlock with the two lines I posted. I missed out the actual copy command as I thought it was obvious.

Anyway, no worries. All good from my side. Good to have you here, thanks for your contributions!

Cheers


#14

I got way more than expected from this post, i got it solved, i got an alternative way to do it that i didn’t know it existed and i learned more about the AudioBlock class which i visualized totally in the wrong way before hear you guys discussing about it, so i thank you so much both, as you can notice from this and also my other newbie posts i’m still on the basics but the forum is helping me a lot to catch up and hopefully i don’t make people bored with such stupid questions :stuck_out_tongue: so like said this i thank you guys so much for not only having my problem solved, but way more :slight_smile:


#15

Another way to do it is to use AudioBlock::copy() instead of iterating the buffer channels, so:

AudioBuffer<SampleType> audioBufferCopy(audioBufferBlock.getNumChannels(), audioBufferBlock.getNumSamples());     // Allocate storage
AudioBlock<SampleType> audioBlockCopy(audioBufferCopy);
audioBlockCopy.copy(audioBufferBlock);    // Copy the data

Now audioBufferCopy is a copy of audioBufferBlock and audioBlockCopy refers to audioBufferCopy.