Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Buffer to have a custom channel alignment #492

Merged
merged 2 commits into from
Feb 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 28 additions & 28 deletions modules/dsp/chowdsp_buffers/Buffers/chowdsp_Buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

namespace chowdsp
{
template <typename SampleType>
Buffer<SampleType>::Buffer (int numChannels, int numSamples)
template <typename SampleType, size_t alignment>
Buffer<SampleType, alignment>::Buffer (int numChannels, int numSamples)
{
setMaxSize (numChannels, numSamples);
}

template <typename SampleType>
void Buffer<SampleType>::setMaxSize (int numChannels, int numSamples)
template <typename SampleType, size_t alignment>
void Buffer<SampleType, alignment>::setMaxSize (int numChannels, int numSamples)
{
// Make sure we don't have any null internal buffers
jassert (juce::isPositiveAndNotGreaterThan (numChannels, maxNumChannels));
Expand Down Expand Up @@ -37,8 +37,8 @@ void Buffer<SampleType>::setMaxSize (int numChannels, int numSamples)
setCurrentSize (numChannels, numSamples);
}

template <typename SampleType>
void Buffer<SampleType>::setCurrentSize (int numChannels, int numSamples) noexcept
template <typename SampleType, size_t alignment>
void Buffer<SampleType, alignment>::setCurrentSize (int numChannels, int numSamples) noexcept
{
// trying to set a current size, but we don't have enough memory allocated!
jassert (numSamples * numChannels <= (int) rawData.size());
Expand All @@ -56,79 +56,79 @@ void Buffer<SampleType>::setCurrentSize (int numChannels, int numSamples) noexce
currentNumSamples = numSamples;
}

template <typename SampleType>
SampleType* Buffer<SampleType>::getWritePointer (int channel) noexcept
template <typename SampleType, size_t alignment>
SampleType* Buffer<SampleType, alignment>::getWritePointer (int channel) noexcept
{
hasBeenCleared = false;
return channelPointers[(size_t) channel];
}

template <typename SampleType>
const SampleType* Buffer<SampleType>::getReadPointer (int channel) const noexcept
template <typename SampleType, size_t alignment>
const SampleType* Buffer<SampleType, alignment>::getReadPointer (int channel) const noexcept
{
return channelPointers[(size_t) channel];
}

template <typename SampleType>
nonstd::span<SampleType> Buffer<SampleType>::getWriteSpan (int channel) noexcept
template <typename SampleType, size_t alignment>
nonstd::span<SampleType> Buffer<SampleType, alignment>::getWriteSpan (int channel) noexcept
{
hasBeenCleared = false;
return { channelPointers[(size_t) channel], (size_t) currentNumSamples };
}

template <typename SampleType>
nonstd::span<const SampleType> Buffer<SampleType>::getReadSpan (int channel) const noexcept
template <typename SampleType, size_t alignment>
nonstd::span<const SampleType> Buffer<SampleType, alignment>::getReadSpan (int channel) const noexcept
{
return { channelPointers[(size_t) channel], (size_t) currentNumSamples };
}

template <typename SampleType>
SampleType** Buffer<SampleType>::getArrayOfWritePointers() noexcept
template <typename SampleType, size_t alignment>
SampleType** Buffer<SampleType, alignment>::getArrayOfWritePointers() noexcept
{
hasBeenCleared = false;
return channelPointers.data();
}

template <typename SampleType>
const SampleType** Buffer<SampleType>::getArrayOfReadPointers() const noexcept
template <typename SampleType, size_t alignment>
const SampleType** Buffer<SampleType, alignment>::getArrayOfReadPointers() const noexcept
{
return const_cast<const SampleType**> (channelPointers.data()); // NOSONAR (using const_cast to be more strict)
}

#if CHOWDSP_USING_JUCE
template <typename SampleType>
template <typename SampleType, size_t alignment>
template <typename T>
std::enable_if_t<buffer_detail::IsFloatOrDouble<T>, juce::AudioBuffer<SampleType>> Buffer<SampleType>::toAudioBuffer()
std::enable_if_t<buffer_detail::IsFloatOrDouble<T>, juce::AudioBuffer<SampleType>> Buffer<SampleType, alignment>::toAudioBuffer()
{
return { getArrayOfWritePointers(), currentNumChannels, currentNumSamples };
}

template <typename SampleType>
template <typename SampleType, size_t alignment>
template <typename T>
std::enable_if_t<buffer_detail::IsFloatOrDouble<T>, juce::AudioBuffer<SampleType>> Buffer<SampleType>::toAudioBuffer() const
std::enable_if_t<buffer_detail::IsFloatOrDouble<T>, juce::AudioBuffer<SampleType>> Buffer<SampleType, alignment>::toAudioBuffer() const
{
return { const_cast<SampleType* const*> (getArrayOfReadPointers()), currentNumChannels, currentNumSamples }; // NOSONAR
}

#if JUCE_MODULE_AVAILABLE_juce_dsp
template <typename SampleType>
template <typename SampleType, size_t alignment>
template <typename T>
std::enable_if_t<buffer_detail::IsFloatOrDouble<T>, AudioBlock<SampleType>> Buffer<SampleType>::toAudioBlock()
std::enable_if_t<buffer_detail::IsFloatOrDouble<T>, AudioBlock<SampleType>> Buffer<SampleType, alignment>::toAudioBlock()
{
return { getArrayOfWritePointers(), (size_t) currentNumChannels, (size_t) currentNumSamples };
}

template <typename SampleType>
template <typename SampleType, size_t alignment>
template <typename T>
std::enable_if_t<buffer_detail::IsFloatOrDouble<T>, AudioBlock<const SampleType>> Buffer<SampleType>::toAudioBlock() const
std::enable_if_t<buffer_detail::IsFloatOrDouble<T>, AudioBlock<const SampleType>> Buffer<SampleType, alignment>::toAudioBlock() const
{
return { getArrayOfReadPointers(), (size_t) currentNumChannels, (size_t) currentNumSamples };
}
#endif
#endif

template <typename SampleType>
void Buffer<SampleType>::clear() noexcept
template <typename SampleType, size_t alignment>
void Buffer<SampleType, alignment>::clear() noexcept
{
if (hasBeenCleared)
return;
Expand Down
17 changes: 12 additions & 5 deletions modules/dsp/chowdsp_buffers/Buffers/chowdsp_Buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,13 @@ namespace buffer_detail

/**
* An audio sample buffer that allocates its own memory.
*
* By default each buffer channel will be aligned to the appropriate SIMD
* byte boundary, unless CHOWDSP_NO_XSIMD is enabled. If you would like to
* provide a custom alignment, you can specify the alignment as the second
* template argument.
*/
template <typename SampleType>
template <typename SampleType, size_t alignment = 0>
class Buffer
{
public:
Expand All @@ -43,10 +48,10 @@ class Buffer
Buffer (int numChannels, int numSamples);

/** Move constructor */
Buffer (Buffer<SampleType>&&) noexcept = default;
Buffer (Buffer&&) noexcept = default;

/** Move assignment */
Buffer<SampleType>& operator= (Buffer<SampleType>&&) noexcept = default;
Buffer& operator= (Buffer&&) noexcept = default;

/**
* Sets the maximum size that this buffer can have, and sets the current size as well.
Expand Down Expand Up @@ -116,11 +121,13 @@ class Buffer

private:
#if ! CHOWDSP_NO_XSIMD
using Allocator = xsimd::default_allocator<SampleType>;
using Allocator = std::conditional_t<alignment == 0,
xsimd::default_allocator<SampleType>,
xsimd::aligned_allocator<SampleType, alignment>>;
#else
using Allocator = std::allocator<SampleType>;
#endif
std::vector<SampleType, Allocator> rawData;
std::vector<SampleType, Allocator> rawData {};

int currentNumChannels = 0;
int currentNumSamples = 0;
Expand Down
3 changes: 2 additions & 1 deletion modules/dsp/chowdsp_simd/chowdsp_simd.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wcast-align",
"-Wc++98-compat-extra-semi",
"-Wshorten-64-to-32",
"-Wfloat-equal",
"-Woverflow")
"-Woverflow",
"-Wdeprecated")
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4244)
#include "third_party/xsimd/include/xsimd/xsimd.hpp"
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
Expand Down
5 changes: 4 additions & 1 deletion tests/dsp_tests/chowdsp_buffers_test/BufferTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wfloat-equal")

template class chowdsp::Buffer<int>;

template <typename T>
using TestBuffer = chowdsp::Buffer<T>;

template <typename T>
using TestStaticBuffer = chowdsp::StaticBuffer<T, 2, 128>;

TEMPLATE_PRODUCT_TEST_CASE ("Buffer Test", "[dsp][buffers][simd]", (chowdsp::Buffer, TestStaticBuffer), (float, double, xsimd::batch<float>, xsimd::batch<double>, int, std::string))
TEMPLATE_PRODUCT_TEST_CASE ("Buffer Test", "[dsp][buffers][simd]", (TestBuffer, TestStaticBuffer), (float, double, xsimd::batch<float>, xsimd::batch<double>, int, std::string))
{
using BufferType = TestType;
using SampleType = typename BufferType::Type;
Expand Down
Loading