Alignment for channels within an AudioBuffer

This commit is contained in:
Paul Ferrand 2019-07-30 18:07:02 +02:00
parent 844480fc1e
commit 5894b6cfb6
2 changed files with 118 additions and 35 deletions

View file

@ -9,7 +9,6 @@ class AudioBuffer
{
public:
AudioBuffer() = default;
AudioBuffer(int numFrames)
{
resize(numFrames);
@ -19,9 +18,13 @@ public:
{
// should have a positive number of frames...
ASSERT(numFrames >= 0);
if (buffer.resize(static_cast<size_t>(NumChannels * numFrames)))
padding = TypeAlignment - (numFrames & TypeAlignmentMask);
totalSize = NumChannels * (numFrames + padding);
if (buffer.resize(static_cast<size_t>(totalSize)))
{
this->numFrames = numFrames;
for (auto channelIndex = 0; channelIndex < NumChannels; ++channelIndex)
channels[channelIndex] = buffer.data() + channelIndex * (numFrames + padding);
return true;
}
@ -37,37 +40,19 @@ public:
Type* getChannel(int channelIndex) noexcept
{
ASSERT(channelIndex >= 0);
if (channelIndex < NumChannels)
return buffer.data() + numFrames * channelIndex;
else
return nullptr;
return channels[channelIndex];
}
Type* begin(int channelIndex) noexcept
{
ASSERT(channelIndex >= 0);
return buffer.data() + numFrames * channelIndex;
}
Type* end(int channelIndex) noexcept
{
ASSERT(channelIndex >= 0);
return buffer.data() + numFrames * (channelIndex + 1);
}
// const Type* cbegin(int channelIndex) noexcept
// {
// ASSERT(channelIndex >= 0);
// return buffer.data() + numFrames * channelIndex;
// }
// const Type* cend(int channelIndex) noexcept
// {
// ASSERT(channelIndex >= 0);
// return buffer.data() + numFrames * (channelIndex + 1);
// }
Type& operator()(int channelIndex, int sampleIndex) noexcept
{
return getSample(channelIndex, sampleIndex);
@ -78,7 +63,13 @@ public:
bool empty() const noexcept { return numFrames == 0; }
private:
static constexpr auto TypeAlignment { Alignment / sizeof(Type) };
static constexpr auto TypeAlignmentMask { TypeAlignment - 1 };
static_assert(TypeAlignment * sizeof(Type) == Alignment, "The alignment does not appear to be divided by the size of the Type");
int numFrames { 0 };
int totalSize { 0 };
int padding { 0 };
std::array<Type*, NumChannels> channels;
Buffer<Type, Alignment> buffer {};
};
@ -123,10 +114,7 @@ public:
Type* getChannel(int channelIndex) noexcept
{
if (channelIndex < NumChannels)
return &buffers[channelIndex].data();
else
return nullptr;
return buffers[channelIndex].data();
}
Type* begin(int channelIndex) noexcept
@ -139,16 +127,6 @@ public:
return buffers[channelIndex].end();
}
// const Type* cbegin(int channelIndex) noexcept
// {
// return buffers[channelIndex].cbegin();
// }
// const Type* cend(int channelIndex) noexcept
// {
// return buffers[channelIndex].cend();
// }
int getNumFrames() const noexcept { return numFrames; }
int getNumChannels() const noexcept { return NumChannels; }
bool empty() const noexcept { return numFrames == 0; }

View file

@ -110,4 +110,109 @@ TEST_CASE("[AudioBuffer/SplitBuffer] Iterators")
for (auto chanIdx = 0; chanIdx < splitBuffer.getNumChannels(); ++chanIdx)
REQUIRE( std::all_of(splitBuffer.begin(chanIdx), splitBuffer.end(chanIdx), [fillValue](auto value) { return value == fillValue; }) );
}
template<class Type, unsigned int NumChannels, unsigned int Alignment = 16>
void channelAlignmentTest(int size)
{
static constexpr auto AlignmentMask { Alignment - 1 };
const Type fillValue { 2 };
AudioBuffer<Type, NumChannels, Alignment> buffer(size);
for (auto chanIdx = 0; chanIdx < NumChannels; ++chanIdx)
REQUIRE( ((size_t)buffer.getChannel(chanIdx) & AlignmentMask) == 0 );
SplitAudioBuffer<Type, NumChannels, Alignment> splitBuffer(size);
for (auto chanIdx = 0; chanIdx < NumChannels; ++chanIdx)
REQUIRE( ((size_t)splitBuffer.getChannel(chanIdx) & AlignmentMask) == 0 );
}
TEST_CASE("[AudioBuffer/SplitBuffer] Channel alignments (floats)")
{
channelAlignmentTest<float, 1>(4);
channelAlignmentTest<float, 1>(5);
channelAlignmentTest<float, 1>(8);
channelAlignmentTest<float, 1>(256);
channelAlignmentTest<float, 1>(257);
channelAlignmentTest<float, 1>(1023);
channelAlignmentTest<float, 1>(1024);
channelAlignmentTest<float, 1>(65537);
channelAlignmentTest<float, 1>(65536);
channelAlignmentTest<float, 1>(65535);
channelAlignmentTest<float, 2>(4);
channelAlignmentTest<float, 2>(5);
channelAlignmentTest<float, 2>(8);
channelAlignmentTest<float, 2>(256);
channelAlignmentTest<float, 2>(257);
channelAlignmentTest<float, 2>(1023);
channelAlignmentTest<float, 2>(1024);
channelAlignmentTest<float, 2>(65537);
channelAlignmentTest<float, 2>(65536);
channelAlignmentTest<float, 2>(65535);
channelAlignmentTest<float, 3>(4);
channelAlignmentTest<float, 3>(5);
channelAlignmentTest<float, 3>(8);
channelAlignmentTest<float, 3>(256);
channelAlignmentTest<float, 3>(257);
channelAlignmentTest<float, 3>(1023);
channelAlignmentTest<float, 3>(1024);
channelAlignmentTest<float, 3>(65537);
channelAlignmentTest<float, 3>(65536);
channelAlignmentTest<float, 3>(65535);
channelAlignmentTest<float, 4>(4);
channelAlignmentTest<float, 4>(5);
channelAlignmentTest<float, 4>(8);
channelAlignmentTest<float, 4>(256);
channelAlignmentTest<float, 4>(257);
channelAlignmentTest<float, 4>(1023);
channelAlignmentTest<float, 4>(1024);
channelAlignmentTest<float, 4>(65537);
channelAlignmentTest<float, 4>(65536);
channelAlignmentTest<float, 4>(65535);
channelAlignmentTest<float, 1, 4>(4);
channelAlignmentTest<float, 1, 4>(5);
channelAlignmentTest<float, 1, 4>(8);
channelAlignmentTest<float, 1, 4>(256);
channelAlignmentTest<float, 1, 4>(257);
channelAlignmentTest<float, 1, 4>(1023);
channelAlignmentTest<float, 1, 4>(1024);
channelAlignmentTest<float, 1, 4>(65537);
channelAlignmentTest<float, 1, 4>(65536);
channelAlignmentTest<float, 1, 4>(65535);
channelAlignmentTest<float, 2, 4>(4);
channelAlignmentTest<float, 2, 4>(5);
channelAlignmentTest<float, 2, 4>(8);
channelAlignmentTest<float, 2, 4>(256);
channelAlignmentTest<float, 2, 4>(257);
channelAlignmentTest<float, 2, 4>(1023);
channelAlignmentTest<float, 2, 4>(1024);
channelAlignmentTest<float, 2, 4>(65537);
channelAlignmentTest<float, 2, 4>(65536);
channelAlignmentTest<float, 2, 4>(65535);
channelAlignmentTest<float, 1, 8>(4);
channelAlignmentTest<float, 1, 8>(5);
channelAlignmentTest<float, 1, 8>(8);
channelAlignmentTest<float, 1, 8>(256);
channelAlignmentTest<float, 1, 8>(257);
channelAlignmentTest<float, 1, 8>(1023);
channelAlignmentTest<float, 1, 8>(1024);
channelAlignmentTest<float, 1, 8>(65537);
channelAlignmentTest<float, 1, 8>(65536);
channelAlignmentTest<float, 1, 8>(65535);
channelAlignmentTest<float, 2, 8>(4);
channelAlignmentTest<float, 2, 8>(5);
channelAlignmentTest<float, 2, 8>(8);
channelAlignmentTest<float, 2, 8>(256);
channelAlignmentTest<float, 2, 8>(257);
channelAlignmentTest<float, 2, 8>(1023);
channelAlignmentTest<float, 2, 8>(1024);
channelAlignmentTest<float, 2, 8>(65537);
channelAlignmentTest<float, 2, 8>(65536);
channelAlignmentTest<float, 2, 8>(65535);
}