From 3f114fdbb45346237785261291e4804c9ce0cd03 Mon Sep 17 00:00:00 2001 From: Iscle Date: Wed, 17 May 2023 03:31:39 +0200 Subject: [PATCH] Improve buffer processing and pcm conversion --- src/ViperContext.cpp | 59 +++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/src/ViperContext.cpp b/src/ViperContext.cpp index 25c29fa..390c7e7 100644 --- a/src/ViperContext.cpp +++ b/src/ViperContext.cpp @@ -362,55 +362,51 @@ int32_t ViperContext::handleCommand(uint32_t cmdCode, uint32_t cmdSize, void *pC } } -static void pcm16ToFloat(float *dst, const int16_t *src, size_t frameCount) { +template +void pcmToFloat(float* dst, const T* src, size_t frameCount) { + constexpr float max_val = static_cast(std::numeric_limits::max()); for (size_t i = 0; i < frameCount * 2; i++) { - dst[i] = static_cast(src[i]) / static_cast(1 << 15); + dst[i] = static_cast(src[i]) / max_val; } } -static void pcm32ToFloat(float *dst, const int32_t *src, size_t frameCount) { - for (size_t i = 0; i < frameCount * 2; i++) { - dst[i] = static_cast(src[i]) / static_cast(1 << 31); - } +template +static const T& clamp(const T& v, const T& lo, const T& hi) { + return std::min(std::max(v, lo), hi); } static void floatToFloat(float *dst, const float *src, size_t frameCount, bool accumulate) { if (accumulate) { for (size_t i = 0; i < frameCount * 2; i++) { - dst[i] += src[i]; + dst[i] += clamp(src[i], -1.0f, 1.0f); } } else { memcpy(dst, src, frameCount * 2 * sizeof(float)); } } -static void floatToPcm16(int16_t *dst, const float *src, size_t frameCount, bool accumulate) { - if (accumulate) { - for (size_t i = 0; i < frameCount * 2; i++) { - dst[i] += static_cast(std::roundf(src[i] * static_cast(1 << 15))); - } - } else { - for (size_t i = 0; i < frameCount * 2; i++) { - dst[i] = static_cast(std::roundf(src[i] * static_cast(1 << 15))); - } - } -} +template +void floatToPcm(T *dst, const float *src, size_t frameCount, bool accumulate) { + constexpr T max_val = std::numeric_limits::max(); + constexpr T min_val = std::numeric_limits::min(); -static void floatToPcm32(int32_t *dst, const float *src, size_t frameCount, bool accumulate) { - if (accumulate) { - for (size_t i = 0; i < frameCount * 2; i++) { - dst[i] += static_cast(std::roundf(src[i] * static_cast(1 << 31))); - } - } else { - for (size_t i = 0; i < frameCount * 2; i++) { - dst[i] = static_cast(std::roundf(src[i] * static_cast(1 << 31))); + for (size_t i = 0; i < frameCount * 2; i++) { + float f = clamp(src[i], -1.0f, 1.0f); + T pcm = static_cast(f * static_cast(max_val)); + if (accumulate) { + U temp = static_cast(dst[i]) + pcm; + dst[i] = static_cast(clamp(temp, static_cast(min_val), static_cast(max_val))); + } else { + dst[i] = pcm; } } } static audio_buffer_t *getBuffer(buffer_config_s *config, audio_buffer_t *buffer) { if (buffer != nullptr) return buffer; - return &config->buffer; + if (config->mask & EFFECT_CONFIG_BUFFER) return &config->buffer; + // EFFECT_CONFIG_PROVIDER not implemented, it's not used by any known effect + return nullptr; } int32_t ViperContext::process(audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) { @@ -433,16 +429,17 @@ int32_t ViperContext::process(audio_buffer_t *inBuffer, audio_buffer_t *outBuffe size_t frameCount = inBuffer->frameCount; if (frameCount > bufferFrameCount) { + // This should never happen, but just in case buffer.resize(frameCount * 2); bufferFrameCount = frameCount; } switch (config.inputCfg.format) { case AUDIO_FORMAT_PCM_16_BIT: - pcm16ToFloat(buffer.data(), inBuffer->s16, frameCount); + pcmToFloat(buffer.data(), inBuffer->s16, frameCount); break; case AUDIO_FORMAT_PCM_32_BIT: - pcm32ToFloat(buffer.data(), inBuffer->s32, frameCount); + pcmToFloat(buffer.data(), inBuffer->s32, frameCount); break; case AUDIO_FORMAT_PCM_FLOAT: floatToFloat(buffer.data(), inBuffer->f32, frameCount, false); @@ -456,10 +453,10 @@ int32_t ViperContext::process(audio_buffer_t *inBuffer, audio_buffer_t *outBuffe const bool accumulate = config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE; switch (config.outputCfg.format) { case AUDIO_FORMAT_PCM_16_BIT: - floatToPcm16(outBuffer->s16, buffer.data(), frameCount, accumulate); + floatToPcm(outBuffer->s16, buffer.data(), frameCount, accumulate); break; case AUDIO_FORMAT_PCM_32_BIT: - floatToPcm32(outBuffer->s32, buffer.data(), frameCount, accumulate); + floatToPcm(outBuffer->s32, buffer.data(), frameCount, accumulate); break; case AUDIO_FORMAT_PCM_FLOAT: floatToFloat(outBuffer->f32, buffer.data(), frameCount, accumulate);