diff --git a/sources/AudioBuffer.h b/sources/AudioBuffer.h index df68625d..8011d58f 100644 --- a/sources/AudioBuffer.h +++ b/sources/AudioBuffer.h @@ -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(NumChannels * numFrames))) + padding = TypeAlignment - (numFrames & TypeAlignmentMask); + totalSize = NumChannels * (numFrames + padding); + if (buffer.resize(static_cast(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 channels; Buffer 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; } diff --git a/tests/AudioBuffer.cpp b/tests/AudioBuffer.cpp index 2e7f3c7c..774e057c 100644 --- a/tests/AudioBuffer.cpp +++ b/tests/AudioBuffer.cpp @@ -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 +void channelAlignmentTest(int size) +{ + static constexpr auto AlignmentMask { Alignment - 1 }; + const Type fillValue { 2 }; + AudioBuffer buffer(size); + for (auto chanIdx = 0; chanIdx < NumChannels; ++chanIdx) + REQUIRE( ((size_t)buffer.getChannel(chanIdx) & AlignmentMask) == 0 ); + + SplitAudioBuffer 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(4); + channelAlignmentTest(5); + channelAlignmentTest(8); + channelAlignmentTest(256); + channelAlignmentTest(257); + channelAlignmentTest(1023); + channelAlignmentTest(1024); + channelAlignmentTest(65537); + channelAlignmentTest(65536); + channelAlignmentTest(65535); + + channelAlignmentTest(4); + channelAlignmentTest(5); + channelAlignmentTest(8); + channelAlignmentTest(256); + channelAlignmentTest(257); + channelAlignmentTest(1023); + channelAlignmentTest(1024); + channelAlignmentTest(65537); + channelAlignmentTest(65536); + channelAlignmentTest(65535); + + channelAlignmentTest(4); + channelAlignmentTest(5); + channelAlignmentTest(8); + channelAlignmentTest(256); + channelAlignmentTest(257); + channelAlignmentTest(1023); + channelAlignmentTest(1024); + channelAlignmentTest(65537); + channelAlignmentTest(65536); + channelAlignmentTest(65535); + + channelAlignmentTest(4); + channelAlignmentTest(5); + channelAlignmentTest(8); + channelAlignmentTest(256); + channelAlignmentTest(257); + channelAlignmentTest(1023); + channelAlignmentTest(1024); + channelAlignmentTest(65537); + channelAlignmentTest(65536); + channelAlignmentTest(65535); + + channelAlignmentTest(4); + channelAlignmentTest(5); + channelAlignmentTest(8); + channelAlignmentTest(256); + channelAlignmentTest(257); + channelAlignmentTest(1023); + channelAlignmentTest(1024); + channelAlignmentTest(65537); + channelAlignmentTest(65536); + channelAlignmentTest(65535); + + channelAlignmentTest(4); + channelAlignmentTest(5); + channelAlignmentTest(8); + channelAlignmentTest(256); + channelAlignmentTest(257); + channelAlignmentTest(1023); + channelAlignmentTest(1024); + channelAlignmentTest(65537); + channelAlignmentTest(65536); + channelAlignmentTest(65535); + + channelAlignmentTest(4); + channelAlignmentTest(5); + channelAlignmentTest(8); + channelAlignmentTest(256); + channelAlignmentTest(257); + channelAlignmentTest(1023); + channelAlignmentTest(1024); + channelAlignmentTest(65537); + channelAlignmentTest(65536); + channelAlignmentTest(65535); + + channelAlignmentTest(4); + channelAlignmentTest(5); + channelAlignmentTest(8); + channelAlignmentTest(256); + channelAlignmentTest(257); + channelAlignmentTest(1023); + channelAlignmentTest(1024); + channelAlignmentTest(65537); + channelAlignmentTest(65536); + channelAlignmentTest(65535); } \ No newline at end of file