From a7c0b0a8b45183e2fbd66057d32adeb576cea724 Mon Sep 17 00:00:00 2001 From: Johannes Lorenz <1042576+JohannesLorenz@users.noreply.github.com> Date: Mon, 21 Sep 2020 09:04:44 +0200 Subject: [PATCH] basics: Change sampleFrame to use `std::array` (#5536) ... in order to make standard containers be able to store it. Required for #5532 (#4899) and the recording PR. This includes: * removing the `LocklessRingBuffer` specialization * passing samplerame in `StereoDelay::tick` as a reference Additional cleanups: * removing already unused typedef `sampleFrameA` * add some `const_cast` to make code more readable --- include/LocklessRingBuffer.h | 66 +++++----------------------------- include/lmms_basics.h | 8 ++--- plugins/Delay/StereoDelay.cpp | 2 +- plugins/Delay/StereoDelay.h | 2 +- src/core/Effect.cpp | 4 +-- src/core/SampleBuffer.cpp | 8 ++--- src/core/audio/AudioDevice.cpp | 4 +-- 7 files changed, 22 insertions(+), 72 deletions(-) diff --git a/include/LocklessRingBuffer.h b/include/LocklessRingBuffer.h index d313fd72288..617f7727a89 100644 --- a/include/LocklessRingBuffer.h +++ b/include/LocklessRingBuffer.h @@ -28,84 +28,36 @@ #include #include -#include "lmms_basics.h" -#include "lmms_export.h" #include "../src/3rdparty/ringbuffer/include/ringbuffer/ringbuffer.h" -//! A convenience layer for a realtime-safe and thread-safe multi-reader ring buffer library. +//! A convenience layer for a realtime-safe and thread-safe multi-reader ringbuffer template -class LocklessRingBufferBase +class LocklessRingBuffer { template friend class LocklessRingBufferReader; public: - LocklessRingBufferBase(std::size_t sz) : m_buffer(sz) + LocklessRingBuffer(std::size_t sz) : m_buffer(sz) { m_buffer.touch(); // reserve storage space before realtime operation starts } - ~LocklessRingBufferBase() {}; + ~LocklessRingBuffer() {}; std::size_t capacity() const {return m_buffer.maximum_eventual_write_space();} std::size_t free() const {return m_buffer.write_space();} void wakeAll() {m_notifier.wakeAll();} - -protected: - ringbuffer_t m_buffer; - QWaitCondition m_notifier; -}; - - -// The SampleFrameCopier is required because sampleFrame is just a two-element -// array and therefore does not have a copy constructor needed by std::copy. -class SampleFrameCopier -{ - const sampleFrame* m_src; -public: - SampleFrameCopier(const sampleFrame* src) : m_src(src) {} - void operator()(std::size_t src_offset, std::size_t count, sampleFrame* dest) - { - for (std::size_t i = src_offset; i < src_offset + count; i++, dest++) - { - (*dest)[0] = m_src[i][0]; - (*dest)[1] = m_src[i][1]; - } - } -}; - - -//! Standard ring buffer template for data types with copy constructor. -template -class LocklessRingBuffer : public LocklessRingBufferBase -{ -public: - LocklessRingBuffer(std::size_t sz) : LocklessRingBufferBase(sz) {}; - std::size_t write(const sampleFrame *src, std::size_t cnt, bool notify = false) { - std::size_t written = LocklessRingBufferBase::m_buffer.write(src, cnt); + std::size_t written = LocklessRingBuffer::m_buffer.write(src, cnt); // Let all waiting readers know new data are available. - if (notify) {LocklessRingBufferBase::m_notifier.wakeAll();} + if (notify) {LocklessRingBuffer::m_notifier.wakeAll();} return written; } -}; - -//! Specialized ring buffer template with write function modified to support sampleFrame. -template <> -class LocklessRingBuffer : public LocklessRingBufferBase -{ -public: - LocklessRingBuffer(std::size_t sz) : LocklessRingBufferBase(sz) {}; - - std::size_t write(const sampleFrame *src, std::size_t cnt, bool notify = false) - { - SampleFrameCopier copier(src); - std::size_t written = LocklessRingBufferBase::m_buffer.write_func(copier, cnt); - // Let all waiting readers know new data are available. - if (notify) {LocklessRingBufferBase::m_notifier.wakeAll();} - return written; - } +protected: + ringbuffer_t m_buffer; + QWaitCondition m_notifier; }; diff --git a/include/lmms_basics.h b/include/lmms_basics.h index 77a24649820..f114f362c15 100644 --- a/include/lmms_basics.h +++ b/include/lmms_basics.h @@ -32,6 +32,7 @@ #ifdef LMMS_HAVE_STDINT_H #include +#include #endif @@ -127,12 +128,9 @@ const ch_cnt_t SURROUND_CHANNELS = -typedef sample_t sampleFrame[DEFAULT_CHANNELS]; -typedef sample_t surroundSampleFrame[SURROUND_CHANNELS]; +using sampleFrame = std::array; +using surroundSampleFrame = std::array; #define ALIGN_SIZE 16 -#if __GNUC__ -typedef sample_t sampleFrameA[DEFAULT_CHANNELS] __attribute__((__aligned__(ALIGN_SIZE))); -#endif #define STRINGIFY(s) STR(s) diff --git a/plugins/Delay/StereoDelay.cpp b/plugins/Delay/StereoDelay.cpp index d25f6b52b18..f240b93547b 100644 --- a/plugins/Delay/StereoDelay.cpp +++ b/plugins/Delay/StereoDelay.cpp @@ -55,7 +55,7 @@ StereoDelay::~StereoDelay() -void StereoDelay::tick( sampleFrame frame ) +void StereoDelay::tick( sampleFrame& frame ) { m_writeIndex = ( m_writeIndex + 1 ) % ( int )m_maxLength; int readIndex = m_writeIndex - m_length; diff --git a/plugins/Delay/StereoDelay.h b/plugins/Delay/StereoDelay.h index a0dbdc22064..afea59b9af1 100644 --- a/plugins/Delay/StereoDelay.h +++ b/plugins/Delay/StereoDelay.h @@ -45,7 +45,7 @@ class StereoDelay m_feedback = feedback; } - void tick( sampleFrame frame ); + void tick( sampleFrame& frame ); void setSampleRate( int sampleRate ); private: diff --git a/src/core/Effect.cpp b/src/core/Effect.cpp index c842977532f..f1e32669e4f 100644 --- a/src/core/Effect.cpp +++ b/src/core/Effect.cpp @@ -203,8 +203,8 @@ void Effect::resample( int _i, const sampleFrame * _src_buf, } m_srcData[_i].input_frames = _frames; m_srcData[_i].output_frames = Engine::mixer()->framesPerPeriod(); - m_srcData[_i].data_in = (float *) _src_buf[0]; - m_srcData[_i].data_out = _dst_buf[0]; + m_srcData[_i].data_in = const_cast(_src_buf[0].data()); + m_srcData[_i].data_out = _dst_buf[0].data (); m_srcData[_i].src_ratio = (double) _dst_sr / _src_sr; m_srcData[_i].end_of_input = 0; int error; diff --git a/src/core/SampleBuffer.cpp b/src/core/SampleBuffer.cpp index cd943638d4f..368600752f0 100644 --- a/src/core/SampleBuffer.cpp +++ b/src/core/SampleBuffer.cpp @@ -693,8 +693,8 @@ bool SampleBuffer::play( sampleFrame * _ab, handleState * _state, // Generate output src_data.data_in = getSampleFragment( play_frame, fragment_size, _loopmode, &tmp, &is_backwards, - loopStartFrame, loopEndFrame, endFrame )[0]; - src_data.data_out = _ab[0]; + loopStartFrame, loopEndFrame, endFrame )->data (); + src_data.data_out = _ab->data (); src_data.input_frames = fragment_size; src_data.output_frames = _frames; src_data.src_ratio = 1.0 / freq_factor; @@ -1196,8 +1196,8 @@ SampleBuffer * SampleBuffer::resample( const sample_rate_t _src_sr, { SRC_DATA src_data; src_data.end_of_input = 1; - src_data.data_in = data[0]; - src_data.data_out = dst_buf[0]; + src_data.data_in = data->data (); + src_data.data_out = dst_buf->data (); src_data.input_frames = frames; src_data.output_frames = dst_frames; src_data.src_ratio = (double) _dst_sr / _src_sr; diff --git a/src/core/audio/AudioDevice.cpp b/src/core/audio/AudioDevice.cpp index f794602299b..a57fa2bd636 100644 --- a/src/core/audio/AudioDevice.cpp +++ b/src/core/audio/AudioDevice.cpp @@ -194,8 +194,8 @@ fpp_t AudioDevice::resample( const surroundSampleFrame * _src, } m_srcData.input_frames = _frames; m_srcData.output_frames = _frames; - m_srcData.data_in = (float *) _src[0]; - m_srcData.data_out = _dst[0]; + m_srcData.data_in = const_cast(_src[0].data()); + m_srcData.data_out = _dst[0].data (); m_srcData.src_ratio = (double) _dst_sr / _src_sr; m_srcData.end_of_input = 0; int error;