Suggestion for AudioSourceChannelInfo replacement


#1

AudioSourceChannelInfo contains the value startSample, this can be a problem because the most times its zero, and when its later “not zero” you might have problems, you never detected before. (For example when doing complex envelope calculations)

I think in all cases AudioSourceChannelInfo can be replaced by a reference to a AudioSampleBuffer (float** dataToReferTo, int numChannels, int numSamples), where the pointers are directly pointing to the startPosition of the buffer (easier for the processing routine).
And then it would be useful add a flag to AudioSampleBuffer to prevent reallocating (it should assert when changing the size or its number of samples)


#2

Edit:

+for creating such a reference it would be nice to have a AudioSampleBuffer* AudioSampleBuffer::createClippedAudioBuffer(startposition, numSamples)


#3

I didn’t do it that way because it’d involve allocating an array of floats and setting all their values each time you make a call to process a subsection of the buffer…


#4

mhh i thought AudioSampleBuffer(float** dataToReferTo…) doesn’t reallocate the audio-data, but yes it may allocate the channel array…


#5

Yeah. I know it’d be nicer to have the array all set up nicely, but I just wanted to avoid doing any allocation in the audio routines if possible.


#6

I second that motion and I was alarmed that AudioSampleBuffer performed allocation until I saw that it has a constructor that lets me pass my own buffer.


#7

jules, in AudioSampleBuffer your are using a float* preallocatedChannelSpace [32]; as reservoir .
So in most cases (<=32 channels) it won’t malloc (or does a fixed size array malloc?),
i can see no structural difference to build AudioSourceChannelInfo or a AudioSampleBuffer on the stack (besides it uses a little little more memory) , or am i wrong?


#8

There are tricks that you can use, of course, but I never considered this to be important enough to be worth bothering.


#9

Here’s a utility class I wrote that makes working with these buffers a little more convenient

[code]// lightweight object to track an adjustable array of pointers to audio data.
template
class AudioSampleBufferArray
{
public:
// if AudioSampleBuffer ever becomes a template, we can
// move this typedef into the template parameters.
typedef float Sample;

AudioSampleBufferArray ()
: m_numSamples (0)
{
}

AudioSampleBufferArray (int numSamples, Sample* const* channels)
{
setFrom (numSamples, channels);
}

AudioSampleBufferArray (const AudioSampleBufferArray& other)
{
setFrom (other);
}

AudioSampleBufferArray (const AudioSampleBuffer& buffer, int offset = 0, int numSamples = -1)
{
setFrom (buffer, offset, numSamples);
}

AudioSampleBufferArray (const AudioSourceChannelInfo& bufferToFill)
{
setFrom (*bufferToFill.buffer, bufferToFill.startSample, bufferToFill.numSamples);
}

operator AudioSampleBuffer()
{
return AudioSampleBuffer (m_channels, Channels, m_numSamples);
}

operator const AudioSampleBuffer() const
{
return AudioSampleBuffer (m_channels, Channels, m_numSamples);
}

void setFrom (int numSamples, Sample* const* channels)
{
m_numSamples = numSamples;
for (int i=0; i<Channels; i++)
m_channels[i]=channels[i];
}

void setFrom (const AudioSampleBufferArray& other)
{
m_numSamples = other.m_numSamples;
for (int i=0; i<Channels; i++)
m_channels[i] = other.m_channels[i];
}

void setFrom (const AudioSampleBuffer& buffer, int offset = 0, int numSamples = -1)
{
jassert (buffer.getNumChannels() == Channels);
jassert (offset >= 0 && offset <= buffer.getNumSamples());
if (numSamples == -1)
numSamples = buffer.getNumSamples() - offset;
jassert (numSamples <= buffer.getNumSamples() - offset);
m_numSamples = numSamples;
for (int i = 0; i < Channels; ++i)
m_channels[i] = buffer.getArrayOfChannels()[i] + offset;
}

AudioSampleBufferArray& operator= (const AudioSampleBuffer& buffer)
{
setFrom (buffer);
return *this;
}

AudioSampleBufferArray& operator= (const AudioSampleBufferArray& other)
{
setFrom (other);
return *this;
}

AudioSampleBufferArray& operator= (const AudioSourceChannelInfo& bufferToFill)
{
setFrom (bufferToFill);
return *this;
}

AudioSampleBufferArray operator+ (int numSamples)
{
jassert (numSamples <= m_numSamples);
Sample* channels[Channels];
for (int i=0; i<Channels; i++)
channels[i] = m_channels[i] + numSamples;
return AudioSampleBufferArray (m_numSamples - numSamples, channels);
}

AudioSampleBufferArray operator- (int numSamples)
{
return operator+ (-numSamples);
}

AudioSampleBufferArray& operator+= (int numSamples)
{
*this = *this + numSamples;
return *this;
}

AudioSampleBufferArray& operator-= (int numSamples)
{
return operator+= (-numSamples);
}

bool isEmpty () const
{
return m_numSamples <= 0;
}

Sample* const* getArrayOfChannels() const
{
return m_channels;
}

operator Sample* const* () const
{
return m_channels;
}

Sample* const* operator()() const
{
return m_channels;
}

Sample*& operator[] (int index)
{
jassert (index >= 0 && index < Channels);
return m_channels[index];
}

const Sample* operator[] (int index) const
{
jassert (index >= 0 && index < Channels);
return m_channels[index];
}

int getNumSamples () const
{
return m_numSamples;
}

private:
int m_numSamples;
Sample* m_channels[Channels];
};

typedef AudioSampleBufferArray<2> StereoSampleBuffer;[/code]