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

BufferView adding template deduction guides #456

Merged
merged 4 commits into from
Sep 21, 2023
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
109 changes: 109 additions & 0 deletions modules/dsp/chowdsp_buffers/Buffers/chowdsp_BufferView.h
Original file line number Diff line number Diff line change
Expand Up @@ -261,4 +261,113 @@ class BufferView
static constexpr int maxNumChannels = CHOWDSP_BUFFER_MAX_NUM_CHANNELS;
std::array<SampleType*, (size_t) maxNumChannels> channelPointers {};
};

#ifndef DOXYGEN
namespace detail
{
template <typename BufferType, typename SampleType>
struct is_static_buffer
{
static constexpr bool value = false;
};

template <typename T, int nChannels, int nSamples>
struct is_static_buffer<StaticBuffer<T, nChannels, nSamples>, T>
{
static constexpr bool value = true;
};

template <typename BufferType, typename SampleType>
constexpr auto is_static_buffer_v = is_static_buffer<BufferType, SampleType>::value;

static_assert (is_static_buffer_v<StaticBuffer<float, 1, 1>, float> == true);
static_assert (is_static_buffer_v<StaticBuffer<float, 1, 1>, double> != true);
} // namespace detail
#endif // DOXYGEN

/** Template deduction guide for Buffer<float> -> BufferView<float> */
template <typename BufferType,
typename... Ts,
typename = std::enable_if_t<
std::is_same_v<BufferType, Buffer<float>> || detail::is_static_buffer_v<BufferType, float>
#if CHOWDSP_USING_JUCE
|| std::is_same_v<BufferType, juce::AudioBuffer<float>>
#if JUCE_MODULE_AVAILABLE_juce_dsp
|| std::is_same_v<BufferType, juce::dsp::AudioBlock<float>>
#endif
#endif
>>
BufferView (BufferType&, Ts...) -> BufferView<float>;

/** Template deduction guide for const Buffer<float> -> BufferView<const float> */
template <typename BufferType,
typename... Ts,
typename = std::enable_if_t<
std::is_same_v<BufferType, const Buffer<float>> || (std::is_const_v<BufferType> && detail::is_static_buffer_v<std::remove_const_t<BufferType>, float>)
#if CHOWDSP_USING_JUCE
|| std::is_same_v<BufferType, const juce::AudioBuffer<float>>
#if JUCE_MODULE_AVAILABLE_juce_dsp
|| std::is_same_v<std::remove_const_t<BufferType>, juce::dsp::AudioBlock<const float>>
#endif
#endif
>>
BufferView (BufferType&, Ts...) -> BufferView<const float>;

/** Template deduction guide for Buffer<double> -> BufferView<const double> */
template <typename BufferType,
typename... Ts,
typename = std::enable_if_t<
std::is_same_v<BufferType, Buffer<double>> || detail::is_static_buffer_v<BufferType, double>
#if CHOWDSP_USING_JUCE
|| std::is_same_v<BufferType, juce::AudioBuffer<double>>
#if JUCE_MODULE_AVAILABLE_juce_dsp
|| std::is_same_v<BufferType, juce::dsp::AudioBlock<double>>
#endif
#endif
>>
BufferView (BufferType&, Ts...) -> BufferView<double>;

/** Template deduction guide for const Buffer<double> -> BufferView<const double> */
template <typename BufferType,
typename... Ts,
typename = std::enable_if_t<
std::is_same_v<BufferType, const Buffer<double>> || (std::is_const_v<BufferType> && detail::is_static_buffer_v<std::remove_const_t<BufferType>, double>)
#if CHOWDSP_USING_JUCE
|| std::is_same_v<BufferType, const juce::AudioBuffer<double>>
#if JUCE_MODULE_AVAILABLE_juce_dsp
|| std::is_same_v<std::remove_const_t<BufferType>, juce::dsp::AudioBlock<const double>>
#endif
#endif
>>
BufferView (BufferType&, Ts...) -> BufferView<const double>;

#if ! CHOWDSP_NO_XSIMD
/** Template deduction guide for Buffer<xsimd::batch<float>> -> BufferView<const xsimd::batch<float>> */
template <typename BufferType,
typename... Ts,
typename = std::enable_if_t<
std::is_same_v<BufferType, Buffer<xsimd::batch<float>>> || detail::is_static_buffer_v<BufferType, xsimd::batch<float>>>>
BufferView (BufferType&, Ts...) -> BufferView<xsimd::batch<float>>;

/** Template deduction guide for const Buffer<xsimd::batch<float>> -> BufferView<const xsimd::batch<float>> */
template <typename BufferType,
typename... Ts,
typename = std::enable_if_t<
std::is_same_v<BufferType, const Buffer<xsimd::batch<float>>> || (std::is_const_v<BufferType> && detail::is_static_buffer_v<std::remove_const_t<BufferType>, xsimd::batch<float>>)>>
BufferView (BufferType&, Ts...) -> BufferView<const xsimd::batch<float>>;

/** Template deduction guide for Buffer<xsimd::batch<double>> -> BufferView<const xsimd::batch<double>> */
template <typename BufferType,
typename... Ts,
typename = std::enable_if_t<
std::is_same_v<BufferType, Buffer<xsimd::batch<double>>> || detail::is_static_buffer_v<BufferType, xsimd::batch<double>>>>
BufferView (BufferType&, Ts...) -> BufferView<xsimd::batch<double>>;

/** Template deduction guide for const Buffer<xsimd::batch<double>> -> BufferView<const xsimd::batch<double>> */
template <typename BufferType,
typename... Ts,
typename = std::enable_if_t<
std::is_same_v<BufferType, const Buffer<xsimd::batch<double>>> || (std::is_const_v<BufferType> && detail::is_static_buffer_v<std::remove_const_t<BufferType>, xsimd::batch<double>>)>>
BufferView (BufferType&, Ts...) -> BufferView<const xsimd::batch<double>>;
#endif // ! CHOWDSP_NO_XSIMD
} // namespace chowdsp
70 changes: 70 additions & 0 deletions tests/dsp_tests/chowdsp_buffers_test/BufferViewTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,73 @@ TEMPLATE_TEST_CASE ("Buffer View Test", "[dsp][buffers][simd]", float, double, x
}
}
JUCE_END_IGNORE_WARNINGS_GCC_LIKE

TEMPLATE_TEST_CASE ("Buffer View Template Deduction Test", "[dsp][buffers][simd]", float, double, xsimd::batch<float>, xsimd::batch<double>)
{
SECTION ("1D Raw Data")
{
TestType* data = nullptr;
chowdsp::BufferView buffer_view { data, 0 };
STATIC_REQUIRE (std::is_same_v<decltype (buffer_view), chowdsp::BufferView<TestType>>);

const TestType* data_const = nullptr;
chowdsp::BufferView buffer_view_const { data_const, 0 };
STATIC_REQUIRE (std::is_same_v<decltype (buffer_view_const), chowdsp::BufferView<const TestType>>);
}

SECTION ("2D Raw Data")
{
TestType* const* data = nullptr;
chowdsp::BufferView buffer_view { data, 0, 0 };
STATIC_REQUIRE (std::is_same_v<decltype (buffer_view), chowdsp::BufferView<TestType>>);

const TestType* const* data_const = nullptr;
chowdsp::BufferView buffer_view_const { data_const, 0, 0 };
STATIC_REQUIRE (std::is_same_v<decltype (buffer_view_const), chowdsp::BufferView<const TestType>>);
}

SECTION ("chowdsp::Buffer")
{
chowdsp::Buffer<TestType> buffer;
chowdsp::BufferView buffer_view { buffer };
STATIC_REQUIRE (std::is_same_v<decltype (buffer_view), chowdsp::BufferView<TestType>>);

chowdsp::BufferView buffer_view_const { std::as_const (buffer), 0, -1, 0, -1 };
STATIC_REQUIRE (std::is_same_v<decltype (buffer_view_const), chowdsp::BufferView<const TestType>>);
}

SECTION ("chowdsp::StaticBuffer")
{
chowdsp::StaticBuffer<TestType, 1, 1> buffer;
chowdsp::BufferView buffer_view { buffer };
STATIC_REQUIRE (std::is_same_v<decltype (buffer_view), chowdsp::BufferView<TestType>>);

const chowdsp::StaticBuffer<TestType, 1, 1> buffer_const;
chowdsp::BufferView buffer_view_const { buffer_const };
STATIC_REQUIRE (std::is_same_v<decltype (buffer_view_const), chowdsp::BufferView<const TestType>>);
}

if constexpr (std::is_floating_point_v<TestType>)
{
SECTION ("juce::AudioBuffer")
{
juce::AudioBuffer<TestType> buffer;
chowdsp::BufferView buffer_view { buffer };
STATIC_REQUIRE (std::is_same_v<decltype (buffer_view), chowdsp::BufferView<TestType>>);

chowdsp::BufferView buffer_view_const { std::as_const (buffer), 0, -1, 0, -1 };
STATIC_REQUIRE (std::is_same_v<decltype (buffer_view_const), chowdsp::BufferView<const TestType>>);
}

SECTION ("juce::dsp::AudioBlock")
{
juce::dsp::AudioBlock<TestType> buffer;
chowdsp::BufferView buffer_view { buffer };
STATIC_REQUIRE (std::is_same_v<decltype (buffer_view), chowdsp::BufferView<TestType>>);

juce::dsp::AudioBlock<const TestType> buffer_const;
chowdsp::BufferView buffer_view_const { std::as_const (buffer_const), 0, -1, 0, -1 };
STATIC_REQUIRE (std::is_same_v<decltype (buffer_view_const), chowdsp::BufferView<const TestType>>);
}
}
}