diff --git a/CMakeLists.txt b/CMakeLists.txt index cfc8a93..91bfa8c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,7 @@ set(FILES # Main src/viper/ViPER.cpp src/ViPER4Android.cpp + src/ViperContext.cpp # Effects src/viper/effects/AnalogX.cpp diff --git a/src/ViPER4Android.cpp b/src/ViPER4Android.cpp index 897ad67..4f5ec69 100644 --- a/src/ViPER4Android.cpp +++ b/src/ViPER4Android.cpp @@ -3,495 +3,75 @@ #include #include "viper/ViPER.h" #include "essential.h" -#include "log.h" #include "viper/constants.h" +#include "ViperContext.h" -#define VIPER_EFFECT_NAME "ViPER4Android" +struct ViperHandle { + const struct effect_interface_s *iface; // Always keep as first member + struct ViperContext *context; +}; -extern "C" { -static effect_descriptor_t viperDescriptor = { +static const effect_descriptor_t viperDescriptor = { .type = *EFFECT_UUID_NULL, .uuid = {0x90380da3, 0x8536, 0x4744, 0xa6a3, {0x57, 0x31, 0x97, 0x0e, 0x64, 0x0f}}, .apiVersion = EFFECT_CONTROL_API_VERSION, - .flags = EFFECT_FLAG_OUTPUT_DIRECT | EFFECT_FLAG_INPUT_DIRECT | EFFECT_FLAG_INSERT_LAST | EFFECT_FLAG_TYPE_INSERT, + .flags = EFFECT_FLAG_OUTPUT_DIRECT | EFFECT_FLAG_INPUT_DIRECT | EFFECT_FLAG_INSERT_LAST | + EFFECT_FLAG_TYPE_INSERT, .cpuLoad = 8, // In 0.1 MIPS units as estimated on an ARM9E core (ARMv5TE) with 0 WS .memoryUsage = 1, // In KB and includes only dynamically allocated memory - .name = VIPER_EFFECT_NAME, + .name = VIPER_NAME, .implementor = VIPER_AUTHORS }; -struct ViPERContext { - // Interface, MUST be the first member of the structure - const struct effect_interface_s *interface; +static int32_t viperInterfaceProcess(effect_handle_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) { + auto viperHandle = reinterpret_cast(self); + if (viperHandle == nullptr) return -EINVAL; - // Config - effect_config_t config; - bool isConfigValid; - - // Processing buffer - float *buffer; - size_t bufferFrameCount; - - // Viper - bool enabled; - ViPER *viper; -}; - -static void pcm16ToFloat(float *dst, const int16_t *src, size_t frameCount) { - for (size_t i = 0; i < frameCount * 2; i++) { - dst[i] = (float) src[i] / (float) (1 << 15); - } + return viperHandle->context->process(inBuffer, outBuffer); } -static void pcm32ToFloat(float *dst, const int32_t *src, size_t frameCount) { - for (size_t i = 0; i < frameCount * 2; i++) { - dst[i] = (float) src[i] / (float) (1 << 31); - } -} - -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]; - } - } 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] += (int16_t) round(src[i] * (float) (1 << 15)); - } - } else { - for (size_t i = 0; i < frameCount * 2; i++) { - dst[i] = (int16_t) round(src[i] * (float) (1 << 15)); - } - } -} - -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] += (int32_t) round(src[i] * (float) (1 << 31)); - } - } else { - for (size_t i = 0; i < frameCount * 2; i++) { - dst[i] = (int32_t) round(src[i] * (float) (1 << 31)); - } - } -} - -static audio_buffer_t *getBuffer(buffer_config_s *config, audio_buffer_t *buffer) { - if (buffer != nullptr) return buffer; - return &config->buffer; -} - -static int32_t ViPERInterfaceProcess(effect_handle_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) { - auto pContext = reinterpret_cast(self); - - if (pContext == nullptr || !pContext->isConfigValid) { - return -EINVAL; - } - - if (!pContext->enabled) { - return -ENODATA; - } - - inBuffer = getBuffer(&pContext->config.inputCfg, inBuffer); - outBuffer = getBuffer(&pContext->config.outputCfg, outBuffer); - if (inBuffer == nullptr || outBuffer == nullptr || - inBuffer->raw == nullptr || outBuffer->raw == nullptr || - inBuffer->frameCount != outBuffer->frameCount || - inBuffer->frameCount == 0) { - return -EINVAL; - } - - size_t frameCount = inBuffer->frameCount; - if (frameCount > pContext->bufferFrameCount) { - delete[] pContext->buffer; - pContext->buffer = new float[frameCount * 2]; - pContext->bufferFrameCount = frameCount; - } - float *buffer = pContext->buffer; - - switch (pContext->config.inputCfg.format) { - case AUDIO_FORMAT_PCM_16_BIT: - pcm16ToFloat(buffer, inBuffer->s16, frameCount); - break; - case AUDIO_FORMAT_PCM_32_BIT: - pcm32ToFloat(buffer, inBuffer->s32, frameCount); - break; - case AUDIO_FORMAT_PCM_FLOAT: - floatToFloat(buffer, inBuffer->f32, frameCount, false); - break; - default: - return -EINVAL; - } - - pContext->viper->processBuffer(buffer, frameCount); - - const bool accumulate = pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE; - switch (pContext->config.outputCfg.format) { - case AUDIO_FORMAT_PCM_16_BIT: - floatToPcm16(outBuffer->s16, buffer, frameCount, accumulate); - break; - case AUDIO_FORMAT_PCM_32_BIT: - floatToPcm32(outBuffer->s32, buffer, frameCount, accumulate); - break; - case AUDIO_FORMAT_PCM_FLOAT: - floatToFloat(outBuffer->f32, buffer, frameCount, accumulate); - break; - default: - return -EINVAL; - } - - return 0; -} - -static int handleSetConfig(ViPERContext *pContext, effect_config_t *newConfig) { - VIPER_LOGI("Checking input and output configuration ..."); - - VIPER_LOGI("Input buffer frame count: %ld", newConfig->inputCfg.buffer.frameCount); - VIPER_LOGI("Input sampling rate: %d", newConfig->inputCfg.samplingRate); - VIPER_LOGI("Input channels: %d", newConfig->inputCfg.channels); - VIPER_LOGI("Input format: %d", newConfig->inputCfg.format); - VIPER_LOGI("Input access mode: %d", newConfig->inputCfg.accessMode); - VIPER_LOGI("Output buffer frame count: %ld", newConfig->outputCfg.buffer.frameCount); - VIPER_LOGI("Output sampling rate: %d", newConfig->outputCfg.samplingRate); - VIPER_LOGI("Output channels: %d", newConfig->outputCfg.channels); - VIPER_LOGI("Output format: %d", newConfig->outputCfg.format); - VIPER_LOGI("Output access mode: %d", newConfig->outputCfg.accessMode); - - pContext->isConfigValid = false; - delete[] pContext->buffer; - pContext->buffer = nullptr; - - if (newConfig->inputCfg.buffer.frameCount != newConfig->outputCfg.buffer.frameCount) { - VIPER_LOGE("ViPER4Android disabled, reason [in.FC = %ld, out.FC = %ld]", - newConfig->inputCfg.buffer.frameCount, newConfig->outputCfg.buffer.frameCount); -// pContext->disableReason = "Invalid frame count"; - return 0; - } - - if (newConfig->inputCfg.samplingRate != newConfig->outputCfg.samplingRate) { - VIPER_LOGE("ViPER4Android disabled, reason [in.SR = %d, out.SR = %d]", - newConfig->inputCfg.samplingRate, newConfig->outputCfg.samplingRate); -// pContext->disableReason = "Invalid sampling rate"; - return 0; - } - - if (newConfig->inputCfg.samplingRate > 48000) { - VIPER_LOGE("ViPER4Android disabled, reason [SR out of range]"); -// pContext->disableReason = "Sampling rate out of range"; - return 0; - } - - if (newConfig->inputCfg.channels != newConfig->outputCfg.channels) { - VIPER_LOGE("ViPER4Android disabled, reason [in.CH = %d, out.CH = %d]", - newConfig->inputCfg.channels, newConfig->outputCfg.channels); -// pContext->disableReason = "Invalid channel count"; - return 0; - } - - if (newConfig->inputCfg.channels != AUDIO_CHANNEL_OUT_STEREO) { - VIPER_LOGE("ViPER4Android disabled, reason [CH != 2]"); -// pContext->disableReason = "Channel count != 2"; - return 0; - } - - if (newConfig->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT && - newConfig->inputCfg.format != AUDIO_FORMAT_PCM_32_BIT && - newConfig->inputCfg.format != AUDIO_FORMAT_PCM_FLOAT) { - VIPER_LOGE("ViPER4Android disabled, reason [in.FMT = %d]", newConfig->inputCfg.format); - VIPER_LOGE("We only accept AUDIO_FORMAT_PCM_16_BIT, AUDIO_FORMAT_PCM_32_BIT and AUDIO_FORMAT_PCM_FLOAT input format!"); -// pContext->disableReason = "Invalid input format"; - return 0; - } - - if (newConfig->outputCfg.format != AUDIO_FORMAT_PCM_16_BIT && - newConfig->outputCfg.format != AUDIO_FORMAT_PCM_32_BIT && - newConfig->outputCfg.format != AUDIO_FORMAT_PCM_FLOAT) { - VIPER_LOGE("ViPER4Android disabled, reason [out.FMT = %d]", newConfig->outputCfg.format); - VIPER_LOGE("We only accept AUDIO_FORMAT_PCM_16_BIT, AUDIO_FORMAT_PCM_32_BIT and AUDIO_FORMAT_PCM_FLOAT output format!"); -// pContext->disableReason = "Invalid output format"; - return 0; - } - - VIPER_LOGI("Input and output configuration checked."); - - // Config - pContext->config = *newConfig; - pContext->isConfigValid = true; -// pContext->disableReason = ""; - // Processing buffer - pContext->buffer = new float[newConfig->inputCfg.buffer.frameCount * 2]; - pContext->bufferFrameCount = newConfig->inputCfg.buffer.frameCount; - // ViPER - pContext->viper->samplingRate = newConfig->inputCfg.samplingRate; - pContext->viper->ResetAllEffects(); - - return 0; -} - -static int32_t handleSetParam(ViPERContext *pContext, effect_param_t *pCmdParam, void *pReplyData) { - // The value offset of an effect parameter is computed by rounding up - // the parameter size to the next 32 bit alignment. - uint32_t vOffset = ((pCmdParam->psize + sizeof(int32_t) - 1) / sizeof(int32_t)) * sizeof(int32_t); - - *(int *) pReplyData = 0; - - int param = *(int *) (pCmdParam->data); - int *intValues = (int *) (pCmdParam->data + vOffset); - switch (pCmdParam->vsize) { - case sizeof(int): { - pContext->viper->DispatchCommand(param, intValues[0], 0, 0, 0, 0, nullptr); - return 0; - } - case sizeof(int) * 2: { - pContext->viper->DispatchCommand(param, intValues[0], intValues[1], 0, 0, 0, nullptr); - return 0; - } - case sizeof(int) * 3: { - pContext->viper->DispatchCommand(param, intValues[0], intValues[1], intValues[2], 0, 0, nullptr); - return 0; - } - case sizeof(int) * 4: { - pContext->viper->DispatchCommand(param, intValues[0], intValues[1], intValues[2], intValues[3], 0, nullptr); - return 0; - } - case 256: - case 1024: { - uint32_t arrSize = *(uint32_t *) (pCmdParam->data + vOffset); - signed char *arr = (signed char *) (pCmdParam->data + vOffset + sizeof(uint32_t)); - pContext->viper->DispatchCommand(param, 0, 0, 0, 0, arrSize, arr); - return 0; - } - case 8192: { - int value1 = *(int *) (pCmdParam->data + vOffset); - uint32_t arrSize = *(uint32_t *) (pCmdParam->data + vOffset + sizeof(int)); - signed char *arr = (signed char *) (pCmdParam->data + vOffset + sizeof(int) + sizeof(uint32_t)); - pContext->viper->DispatchCommand(param, value1, 0, 0, 0, arrSize, arr); - return 0; - } - default: { - return -EINVAL; - } - } -} - -static int32_t handleGetParam(ViPERContext *pContext, effect_param_t *pCmdParam, effect_param_t *pReplyParam, uint32_t *pReplySize) { - // The value offset of an effect parameter is computed by rounding up - // the parameter size to the next 32 bit alignment. - uint32_t vOffset = ((pCmdParam->psize + sizeof(int32_t) - 1) / sizeof(int32_t)) * sizeof(int32_t); - - VIPER_LOGD("ViPERInterfaceCommand() EFFECT_CMD_GET_PARAM called with data = %d, psize = %d, vsize = %d", *(uint32_t *) pCmdParam->data, pCmdParam->psize, pCmdParam->vsize); - - memcpy(pReplyParam, pCmdParam, sizeof(effect_param_t) + pCmdParam->psize); - - switch (*(uint32_t *) pCmdParam->data) { - case PARAM_GET_ENABLED: { - pReplyParam->status = 0; - pReplyParam->vsize = sizeof(int32_t); - *(int32_t *) (pReplyParam->data + vOffset) = pContext->enabled; - *pReplySize = sizeof(effect_param_t) + pReplyParam->psize + vOffset + pReplyParam->vsize; - return 0; - } - case PARAM_GET_CONFIGURE: { - pReplyParam->status = 0; - pReplyParam->vsize = sizeof(int32_t); - *(int32_t *) (pReplyParam->data + vOffset) = pContext->isConfigValid; - *pReplySize = sizeof(effect_param_t) + pReplyParam->psize + vOffset + pReplyParam->vsize; - return 0; - } - case PARAM_GET_STREAMING: { // Is processing - struct timeval time{}; - gettimeofday(&time, nullptr); - - uint64_t currentMs = (uint64_t) (time.tv_sec * 1000) + (uint64_t) (time.tv_usec / 1000); - uint64_t lastProcessTime = pContext->viper->processTimeMs; - - uint64_t diff; - if (currentMs > lastProcessTime) { - diff = currentMs - lastProcessTime; - } else { - diff = lastProcessTime - currentMs; - } - - pReplyParam->status = 0; - pReplyParam->vsize = sizeof(int32_t); - *(int32_t *) (pReplyParam->data + vOffset) = diff > 5000 ? 0 : 1; - *pReplySize = sizeof(effect_param_t) + pReplyParam->psize + vOffset + pReplyParam->vsize; - return 0; - } - case PARAM_GET_SAMPLING_RATE: { - pReplyParam->status = 0; - pReplyParam->vsize = sizeof(uint32_t); - *(uint32_t *) (pReplyParam->data + vOffset) = pContext->viper->samplingRate; - *pReplySize = sizeof(effect_param_t) + pReplyParam->psize + vOffset + pReplyParam->vsize; - return 0; - } - case PARAM_GET_CONVOLUTION_KERNEL_ID: { - pReplyParam->status = 0; - pReplyParam->vsize = sizeof(uint32_t); - *(uint32_t *) (pReplyParam->data + vOffset) = pContext->viper->convolver->GetKernelID(); - *pReplySize = sizeof(effect_param_t) + pReplyParam->psize + vOffset + pReplyParam->vsize; - return 0; - } - case PARAM_GET_DRIVER_VERSION_CODE: { - pReplyParam->status = 0; - pReplyParam->vsize = sizeof(uint32_t); - *(int32_t *) (pReplyParam->data + vOffset) = VERSION_CODE; - *pReplySize = sizeof(effect_param_t) + pReplyParam->psize + vOffset + pReplyParam->vsize; - return 0; - } - case PARAM_GET_DRIVER_VERSION_NAME: { - pReplyParam->status = 0; - pReplyParam->vsize = strlen(VERSION_NAME); - memcpy(pReplyParam->data + vOffset, VERSION_NAME, pReplyParam->vsize); - *pReplySize = sizeof(effect_param_t) + pReplyParam->psize + vOffset + pReplyParam->vsize; - return 0; - } - default: { - return -EINVAL; - } - } -} - -#define SET_INT32(ptr, value) (*(int32_t *) (ptr) = (value)) -#define GET_REPLY_SIZE(ptr) (ptr == nullptr ? 0 : *ptr) - -static int32_t ViPERInterfaceCommand(effect_handle_t self, +static int32_t viperInterfaceCommand(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize, void *pCmdData, uint32_t *replySize, void *pReplyData) { - auto context = reinterpret_cast(self); - if (context == nullptr) return -EINVAL; - - switch (cmdCode) { - case EFFECT_CMD_INIT: { - if (GET_REPLY_SIZE(replySize) != sizeof(int32_t) || pReplyData == nullptr) { - VIPER_LOGE("EFFECT_CMD_INIT called with invalid replySize = %d, pReplyData = %p, expected replySize = %lu", GET_REPLY_SIZE(replySize), pReplyData, sizeof(int32_t)); - return -EINVAL; - } - SET_INT32(pReplyData, 0); - return 0; - } - case EFFECT_CMD_SET_CONFIG: { - if (cmdSize < sizeof(effect_config_t) || pCmdData == nullptr || GET_REPLY_SIZE(replySize) != sizeof(int32_t) || pReplyData == nullptr) { - VIPER_LOGE("EFFECT_CMD_SET_CONFIG called with invalid cmdSize = %d, pCmdData = %p, replySize = %d, pReplyData = %p, expected cmdSize = %lu, replySize = %lu", cmdSize, pCmdData, GET_REPLY_SIZE(replySize), pReplyData, sizeof(effect_config_t), sizeof(int32_t)); - return -EINVAL; - } - SET_INT32(pReplyData, handleSetConfig(context, (effect_config_t *) pCmdData)); - return 0; - } - case EFFECT_CMD_RESET: { - if (GET_REPLY_SIZE(replySize) != sizeof(int32_t) || pReplyData == nullptr) { - VIPER_LOGE("EFFECT_CMD_RESET called with invalid replySize = %d, pReplyData = %p, expected replySize = %lu", GET_REPLY_SIZE(replySize), pReplyData, sizeof(int32_t)); - return -EINVAL; - } - context->viper->ResetAllEffects(); - SET_INT32(pReplyData, 0); - return 0; - } - case EFFECT_CMD_ENABLE: { - if (GET_REPLY_SIZE(replySize) != sizeof(int32_t) || pReplyData == nullptr) { - VIPER_LOGE("EFFECT_CMD_ENABLE called with invalid replySize = %d, pReplyData = %p, expected replySize = %lu", GET_REPLY_SIZE(replySize), pReplyData, sizeof(int32_t)); - return -EINVAL; - } - context->viper->ResetAllEffects(); - context->enabled = true; - SET_INT32(pReplyData, 0); - return 0; - } - case EFFECT_CMD_DISABLE: { - if (GET_REPLY_SIZE(replySize) != sizeof(int32_t) || pReplyData == nullptr) { - VIPER_LOGE("EFFECT_CMD_DISABLE called with invalid replySize = %d, pReplyData = %p, expected replySize = %lu", GET_REPLY_SIZE(replySize), pReplyData, sizeof(int32_t)); - return -EINVAL; - } - context->enabled = false; - SET_INT32(pReplyData, 0); - return 0; - } - case EFFECT_CMD_SET_PARAM: { - if (cmdSize < sizeof(effect_param_t) || pCmdData == nullptr || GET_REPLY_SIZE(replySize) != sizeof(int32_t) || pReplyData == nullptr) { - VIPER_LOGE("EFFECT_CMD_SET_PARAM called with invalid cmdSize = %d, pCmdData = %p, replySize = %d, pReplyData = %p, expected cmdSize = %lu, replySize = %lu", cmdSize, pCmdData, GET_REPLY_SIZE(replySize), pReplyData, sizeof(effect_param_t), sizeof(int32_t)); - return -EINVAL; - } - return handleSetParam(context, (effect_param_t *) pCmdData, pReplyData); - } - case EFFECT_CMD_GET_PARAM: { - if (cmdSize < sizeof(effect_param_t) || pCmdData == nullptr || GET_REPLY_SIZE(replySize) < sizeof(effect_param_t) || pReplyData == nullptr) { - VIPER_LOGE("EFFECT_CMD_GET_PARAM called with invalid cmdSize = %d, pCmdData = %p, replySize = %d, pReplyData = %p, expected cmdSize = %lu, replySize = %lu", cmdSize, pCmdData, GET_REPLY_SIZE(replySize), pReplyData, sizeof(effect_param_t), sizeof(effect_param_t)); - return -EINVAL; - } - return handleGetParam(context, (effect_param_t *) pCmdData, (effect_param_t *) pReplyData, replySize); - } - case EFFECT_CMD_GET_CONFIG: { - if (GET_REPLY_SIZE(replySize) != sizeof(effect_config_t) || pReplyData == nullptr) { - VIPER_LOGE("EFFECT_CMD_GET_CONFIG called with invalid replySize = %d, pReplyData = %p, expected replySize = %lu", GET_REPLY_SIZE(replySize), pReplyData, sizeof(effect_config_t)); - return -EINVAL; - } - *(effect_config_t *) pReplyData = context->config; - return 0; - } - default: { - VIPER_LOGE("ViPERInterfaceCommand called with unknown command: %d", cmdCode); - return -EINVAL; - } - } + auto viperHandle = reinterpret_cast(self); + if (viperHandle == nullptr) return -EINVAL; + + return viperHandle->context->handleCommand(cmdCode, cmdSize, pCmdData, replySize, pReplyData); } -static int32_t ViPERInterfaceGetDescriptor(effect_handle_t self, effect_descriptor_t *pDescriptor) { - auto context = reinterpret_cast(self); - if (context == nullptr || pDescriptor == nullptr) return -EINVAL; - +static int32_t viperInterfaceGetDescriptor(effect_handle_t self, effect_descriptor_t *pDescriptor) { + if (pDescriptor == nullptr) return -EINVAL; *pDescriptor = viperDescriptor; return 0; } static const effect_interface_s viper_interface = { - .process = ViPERInterfaceProcess, - .command = ViPERInterfaceCommand, - .get_descriptor = ViPERInterfaceGetDescriptor + .process = viperInterfaceProcess, + .command = viperInterfaceCommand, + .get_descriptor = viperInterfaceGetDescriptor }; -static ViPERContext *createViPERContext() { - auto context = new ViPERContext(); - context->interface = &viper_interface; - context->viper = new ViPER(); - return context; -} - static int32_t -ViPERCreate(const effect_uuid_t *uuid, int32_t sessionId __unused, int32_t ioId __unused, effect_handle_t *pHandle) { +viperLibraryCreate(const effect_uuid_t *uuid, int32_t sessionId __unused, int32_t ioId __unused, effect_handle_t *pHandle) { if (uuid == nullptr || pHandle == nullptr) return -EINVAL; if (memcmp(uuid, &viperDescriptor.uuid, sizeof(effect_uuid_t)) != 0) return -ENOENT; - VIPER_LOGD("Creating ViPER"); - auto context = createViPERContext(); - *pHandle = reinterpret_cast(context); - + auto viperHandle = new ViperHandle(); + viperHandle->iface = &viper_interface; + viperHandle->context = new ViperContext(); + *pHandle = reinterpret_cast(viperHandle); return 0; } -static void deleteViPERContext(ViPERContext *context) { - delete[] context->buffer; - delete context->viper; - delete context; -} - -static int32_t ViPERRelease(effect_handle_t handle) { - auto context = reinterpret_cast(handle); - if (context == nullptr) return -EINVAL; - - VIPER_LOGD("Releasing ViPER"); - deleteViPERContext(context); +static int32_t viperLibraryRelease(effect_handle_t handle) { + auto viperHandle = reinterpret_cast(handle); + if (viperHandle == nullptr) return -EINVAL; + delete viperHandle->context; return 0; } -static int32_t ViPERGetDescriptor(const effect_uuid_t *uuid, effect_descriptor_t *pDescriptor) { +static int32_t viperLibraryGetDescriptor(const effect_uuid_t *uuid, effect_descriptor_t *pDescriptor) { if (uuid == nullptr || pDescriptor == nullptr) return -EINVAL; if (memcmp(uuid, &viperDescriptor.uuid, sizeof(effect_uuid_t)) != 0) return -ENOENT; @@ -499,15 +79,13 @@ static int32_t ViPERGetDescriptor(const effect_uuid_t *uuid, effect_descriptor_t return 0; } -__attribute__ ((visibility ("default"))) -audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = { +extern "C" __attribute__ ((visibility ("default"))) +const audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = { .tag = AUDIO_EFFECT_LIBRARY_TAG, .version = EFFECT_LIBRARY_API_VERSION, - .name = VIPER_EFFECT_NAME, + .name = VIPER_NAME, .implementor = VIPER_AUTHORS, - .create_effect = ViPERCreate, - .release_effect = ViPERRelease, - .get_descriptor = ViPERGetDescriptor, + .create_effect = viperLibraryCreate, + .release_effect = viperLibraryRelease, + .get_descriptor = viperLibraryGetDescriptor, }; - -} // extern "C" diff --git a/src/ViperContext.cpp b/src/ViperContext.cpp new file mode 100644 index 0000000..50d3fb3 --- /dev/null +++ b/src/ViperContext.cpp @@ -0,0 +1,409 @@ +#include +#include +#include +#include +#include "ViperContext.h" +#include "log.h" + +ViperContext::ViperContext() : + config({}), + isConfigValid(false), + buffer(std::vector()), + bufferFrameCount(0), + enabled(false) { + VIPER_LOGI("ViperContext created"); +} + +int ViperContext::handleSetConfig(effect_config_t *newConfig) { + VIPER_LOGI("Checking input and output configuration ..."); + + VIPER_LOGI("Input buffer frame count: %ld", newConfig->inputCfg.buffer.frameCount); + VIPER_LOGI("Input sampling rate: %d", newConfig->inputCfg.samplingRate); + VIPER_LOGI("Input channels: %d", newConfig->inputCfg.channels); + VIPER_LOGI("Input format: %d", newConfig->inputCfg.format); + VIPER_LOGI("Input access mode: %d", newConfig->inputCfg.accessMode); + VIPER_LOGI("Output buffer frame count: %ld", newConfig->outputCfg.buffer.frameCount); + VIPER_LOGI("Output sampling rate: %d", newConfig->outputCfg.samplingRate); + VIPER_LOGI("Output channels: %d", newConfig->outputCfg.channels); + VIPER_LOGI("Output format: %d", newConfig->outputCfg.format); + VIPER_LOGI("Output access mode: %d", newConfig->outputCfg.accessMode); + + isConfigValid = false; + + if (newConfig->inputCfg.buffer.frameCount != newConfig->outputCfg.buffer.frameCount) { + VIPER_LOGE("ViPER4Android disabled, reason [in.FC = %ld, out.FC = %ld]", + newConfig->inputCfg.buffer.frameCount, newConfig->outputCfg.buffer.frameCount); +// disableReason = "Invalid frame count"; + return 0; + } + + if (newConfig->inputCfg.samplingRate != newConfig->outputCfg.samplingRate) { + VIPER_LOGE("ViPER4Android disabled, reason [in.SR = %d, out.SR = %d]", + newConfig->inputCfg.samplingRate, newConfig->outputCfg.samplingRate); +// disableReason = "Invalid sampling rate"; + return 0; + } + + if (newConfig->inputCfg.samplingRate > 48000) { + VIPER_LOGE("ViPER4Android disabled, reason [SR out of range]"); +// disableReason = "Sampling rate out of range"; + return 0; + } + + if (newConfig->inputCfg.channels != newConfig->outputCfg.channels) { + VIPER_LOGE("ViPER4Android disabled, reason [in.CH = %d, out.CH = %d]", + newConfig->inputCfg.channels, newConfig->outputCfg.channels); +// disableReason = "Invalid channel count"; + return 0; + } + + if (newConfig->inputCfg.channels != AUDIO_CHANNEL_OUT_STEREO) { + VIPER_LOGE("ViPER4Android disabled, reason [CH != 2]"); +// disableReason = "Channel count != 2"; + return 0; + } + + if (newConfig->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT && + newConfig->inputCfg.format != AUDIO_FORMAT_PCM_32_BIT && + newConfig->inputCfg.format != AUDIO_FORMAT_PCM_FLOAT) { + VIPER_LOGE("ViPER4Android disabled, reason [in.FMT = %d]", newConfig->inputCfg.format); + VIPER_LOGE("We only accept AUDIO_FORMAT_PCM_16_BIT, AUDIO_FORMAT_PCM_32_BIT and AUDIO_FORMAT_PCM_FLOAT input format!"); +// disableReason = "Invalid input format"; + return 0; + } + + if (newConfig->outputCfg.format != AUDIO_FORMAT_PCM_16_BIT && + newConfig->outputCfg.format != AUDIO_FORMAT_PCM_32_BIT && + newConfig->outputCfg.format != AUDIO_FORMAT_PCM_FLOAT) { + VIPER_LOGE("ViPER4Android disabled, reason [out.FMT = %d]", newConfig->outputCfg.format); + VIPER_LOGE("We only accept AUDIO_FORMAT_PCM_16_BIT, AUDIO_FORMAT_PCM_32_BIT and AUDIO_FORMAT_PCM_FLOAT output format!"); +// disableReason = "Invalid output format"; + return 0; + } + + VIPER_LOGI("Input and output configuration checked."); + + // Config + config = *newConfig; + isConfigValid = true; +// disableReason = ""; + // Processing buffer + buffer.resize(newConfig->inputCfg.buffer.frameCount * 2); + bufferFrameCount = newConfig->inputCfg.buffer.frameCount; + // ViPER + viper.samplingRate = newConfig->inputCfg.samplingRate; + viper.ResetAllEffects(); + + return 0; +} + +int32_t ViperContext::handleSetParam(effect_param_t *pCmdParam, void *pReplyData) { + // The value offset of an effect parameter is computed by rounding up + // the parameter size to the next 32 bit alignment. + uint32_t vOffset = ((pCmdParam->psize + sizeof(int32_t) - 1) / sizeof(int32_t)) * sizeof(int32_t); + + *(int *) pReplyData = 0; + + int param = *(int *) (pCmdParam->data); + int *intValues = (int *) (pCmdParam->data + vOffset); + switch (pCmdParam->vsize) { + case sizeof(int): { + viper.DispatchCommand(param, intValues[0], 0, 0, 0, 0, nullptr); + return 0; + } + case sizeof(int) * 2: { + viper.DispatchCommand(param, intValues[0], intValues[1], 0, 0, 0, nullptr); + return 0; + } + case sizeof(int) * 3: { + viper.DispatchCommand(param, intValues[0], intValues[1], intValues[2], 0, 0, nullptr); + return 0; + } + case sizeof(int) * 4: { + viper.DispatchCommand(param, intValues[0], intValues[1], intValues[2], intValues[3], 0, nullptr); + return 0; + } + case 256: + case 1024: { + uint32_t arrSize = *(uint32_t *) (pCmdParam->data + vOffset); + signed char *arr = (signed char *) (pCmdParam->data + vOffset + sizeof(uint32_t)); + viper.DispatchCommand(param, 0, 0, 0, 0, arrSize, arr); + return 0; + } + case 8192: { + int value1 = *(int *) (pCmdParam->data + vOffset); + uint32_t arrSize = *(uint32_t *) (pCmdParam->data + vOffset + sizeof(int)); + signed char *arr = (signed char *) (pCmdParam->data + vOffset + sizeof(int) + sizeof(uint32_t)); + viper.DispatchCommand(param, value1, 0, 0, 0, arrSize, arr); + return 0; + } + default: { + return -EINVAL; + } + } +} + +int32_t ViperContext::handleGetParam(effect_param_t *pCmdParam, effect_param_t *pReplyParam, uint32_t *pReplySize) { + // The value offset of an effect parameter is computed by rounding up + // the parameter size to the next 32 bit alignment. + uint32_t vOffset = ((pCmdParam->psize + sizeof(int32_t) - 1) / sizeof(int32_t)) * sizeof(int32_t); + + VIPER_LOGD("viperInterfaceCommand() EFFECT_CMD_GET_PARAM called with data = %d, psize = %d, vsize = %d", *(uint32_t *) pCmdParam->data, pCmdParam->psize, pCmdParam->vsize); + + memcpy(pReplyParam, pCmdParam, sizeof(effect_param_t) + pCmdParam->psize); + + switch (*(uint32_t *) pCmdParam->data) { + case PARAM_GET_ENABLED: { + pReplyParam->status = 0; + pReplyParam->vsize = sizeof(int32_t); + *(int32_t *) (pReplyParam->data + vOffset) = enabled; + *pReplySize = sizeof(effect_param_t) + pReplyParam->psize + vOffset + pReplyParam->vsize; + return 0; + } + case PARAM_GET_CONFIGURE: { + pReplyParam->status = 0; + pReplyParam->vsize = sizeof(int32_t); + *(int32_t *) (pReplyParam->data + vOffset) = isConfigValid; + *pReplySize = sizeof(effect_param_t) + pReplyParam->psize + vOffset + pReplyParam->vsize; + return 0; + } + case PARAM_GET_STREAMING: { // Is processing + auto now = std::chrono::system_clock::now(); + auto now_ms = std::chrono::time_point_cast(now); + + uint64_t currentMs = now_ms.time_since_epoch().count(); + uint64_t lastProcessTime = viper.processTimeMs; + + uint64_t diff; + if (currentMs > lastProcessTime) { + diff = currentMs - lastProcessTime; + } else { + diff = lastProcessTime - currentMs; + } + + pReplyParam->status = 0; + pReplyParam->vsize = sizeof(int32_t); + *(int32_t *) (pReplyParam->data + vOffset) = diff > 5000 ? 0 : 1; + *pReplySize = sizeof(effect_param_t) + pReplyParam->psize + vOffset + pReplyParam->vsize; + return 0; + } + case PARAM_GET_SAMPLING_RATE: { + pReplyParam->status = 0; + pReplyParam->vsize = sizeof(uint32_t); + *(uint32_t *) (pReplyParam->data + vOffset) = viper.samplingRate; + *pReplySize = sizeof(effect_param_t) + pReplyParam->psize + vOffset + pReplyParam->vsize; + return 0; + } + case PARAM_GET_CONVOLUTION_KERNEL_ID: { + pReplyParam->status = 0; + pReplyParam->vsize = sizeof(uint32_t); + *(uint32_t *) (pReplyParam->data + vOffset) = viper.convolver->GetKernelID(); + *pReplySize = sizeof(effect_param_t) + pReplyParam->psize + vOffset + pReplyParam->vsize; + return 0; + } + case PARAM_GET_DRIVER_VERSION_CODE: { + pReplyParam->status = 0; + pReplyParam->vsize = sizeof(uint32_t); + *(int32_t *) (pReplyParam->data + vOffset) = VERSION_CODE; + *pReplySize = sizeof(effect_param_t) + pReplyParam->psize + vOffset + pReplyParam->vsize; + return 0; + } + case PARAM_GET_DRIVER_VERSION_NAME: { + pReplyParam->status = 0; + pReplyParam->vsize = strlen(VERSION_NAME); + memcpy(pReplyParam->data + vOffset, VERSION_NAME, pReplyParam->vsize); + *pReplySize = sizeof(effect_param_t) + pReplyParam->psize + vOffset + pReplyParam->vsize; + return 0; + } + default: { + return -EINVAL; + } + } +} + +#define SET_INT32(ptr, value) (*(int32_t *) (ptr) = (value)) +#define GET_REPLY_SIZE(ptr) (ptr == nullptr ? 0 : *ptr) + +int32_t ViperContext::handleCommand(uint32_t cmdCode, uint32_t cmdSize, void *pCmdData, uint32_t *replySize, void *pReplyData) { + switch (cmdCode) { + case EFFECT_CMD_INIT: { + if (GET_REPLY_SIZE(replySize) != sizeof(int32_t) || pReplyData == nullptr) { + VIPER_LOGE("EFFECT_CMD_INIT called with invalid replySize = %d, pReplyData = %p, expected replySize = %lu", GET_REPLY_SIZE(replySize), pReplyData, sizeof(int32_t)); + return -EINVAL; + } + SET_INT32(pReplyData, 0); + return 0; + } + case EFFECT_CMD_SET_CONFIG: { + if (cmdSize < sizeof(effect_config_t) || pCmdData == nullptr || GET_REPLY_SIZE(replySize) != sizeof(int32_t) || pReplyData == nullptr) { + VIPER_LOGE("EFFECT_CMD_SET_CONFIG called with invalid cmdSize = %d, pCmdData = %p, replySize = %d, pReplyData = %p, expected cmdSize = %lu, replySize = %lu", cmdSize, pCmdData, GET_REPLY_SIZE(replySize), pReplyData, sizeof(effect_config_t), sizeof(int32_t)); + return -EINVAL; + } + SET_INT32(pReplyData, handleSetConfig((effect_config_t *) pCmdData)); + return 0; + } + case EFFECT_CMD_RESET: { + if (GET_REPLY_SIZE(replySize) != sizeof(int32_t) || pReplyData == nullptr) { + VIPER_LOGE("EFFECT_CMD_RESET called with invalid replySize = %d, pReplyData = %p, expected replySize = %lu", GET_REPLY_SIZE(replySize), pReplyData, sizeof(int32_t)); + return -EINVAL; + } + viper.ResetAllEffects(); + SET_INT32(pReplyData, 0); + return 0; + } + case EFFECT_CMD_ENABLE: { + if (GET_REPLY_SIZE(replySize) != sizeof(int32_t) || pReplyData == nullptr) { + VIPER_LOGE("EFFECT_CMD_ENABLE called with invalid replySize = %d, pReplyData = %p, expected replySize = %lu", GET_REPLY_SIZE(replySize), pReplyData, sizeof(int32_t)); + return -EINVAL; + } + viper.ResetAllEffects(); + enabled = true; + SET_INT32(pReplyData, 0); + return 0; + } + case EFFECT_CMD_DISABLE: { + if (GET_REPLY_SIZE(replySize) != sizeof(int32_t) || pReplyData == nullptr) { + VIPER_LOGE("EFFECT_CMD_DISABLE called with invalid replySize = %d, pReplyData = %p, expected replySize = %lu", GET_REPLY_SIZE(replySize), pReplyData, sizeof(int32_t)); + return -EINVAL; + } + enabled = false; + SET_INT32(pReplyData, 0); + return 0; + } + case EFFECT_CMD_SET_PARAM: { + if (cmdSize < sizeof(effect_param_t) || pCmdData == nullptr || GET_REPLY_SIZE(replySize) != sizeof(int32_t) || pReplyData == nullptr) { + VIPER_LOGE("EFFECT_CMD_SET_PARAM called with invalid cmdSize = %d, pCmdData = %p, replySize = %d, pReplyData = %p, expected cmdSize = %lu, replySize = %lu", cmdSize, pCmdData, GET_REPLY_SIZE(replySize), pReplyData, sizeof(effect_param_t), sizeof(int32_t)); + return -EINVAL; + } + return handleSetParam((effect_param_t *) pCmdData, pReplyData); + } + case EFFECT_CMD_GET_PARAM: { + if (cmdSize < sizeof(effect_param_t) || pCmdData == nullptr || GET_REPLY_SIZE(replySize) < sizeof(effect_param_t) || pReplyData == nullptr) { + VIPER_LOGE("EFFECT_CMD_GET_PARAM called with invalid cmdSize = %d, pCmdData = %p, replySize = %d, pReplyData = %p, expected cmdSize = %lu, replySize = %lu", cmdSize, pCmdData, GET_REPLY_SIZE(replySize), pReplyData, sizeof(effect_param_t), sizeof(effect_param_t)); + return -EINVAL; + } + return handleGetParam((effect_param_t *) pCmdData, (effect_param_t *) pReplyData, replySize); + } + case EFFECT_CMD_GET_CONFIG: { + if (GET_REPLY_SIZE(replySize) != sizeof(effect_config_t) || pReplyData == nullptr) { + VIPER_LOGE("EFFECT_CMD_GET_CONFIG called with invalid replySize = %d, pReplyData = %p, expected replySize = %lu", GET_REPLY_SIZE(replySize), pReplyData, sizeof(effect_config_t)); + return -EINVAL; + } + *(effect_config_t *) pReplyData = config; + return 0; + } + default: { + VIPER_LOGE("viperInterfaceCommand called with unknown command: %d", cmdCode); + return -EINVAL; + } + } +} + +static void pcm16ToFloat(float *dst, const int16_t *src, size_t frameCount) { + for (size_t i = 0; i < frameCount * 2; i++) { + dst[i] = static_cast(src[i]) / static_cast(1 << 15); + } +} + +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); + } +} + +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]; + } + } 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::round(src[i] * static_cast(1 << 15))); + } + } else { + for (size_t i = 0; i < frameCount * 2; i++) { + dst[i] = static_cast(std::round(src[i] * static_cast(1 << 15))); + } + } +} + +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::round(src[i] * static_cast(1 << 31))); + } + } else { + for (size_t i = 0; i < frameCount * 2; i++) { + dst[i] = static_cast(std::round(src[i] * static_cast(1 << 31))); + } + } +} + +static audio_buffer_t *getBuffer(buffer_config_s *config, audio_buffer_t *buffer) { + if (buffer != nullptr) return buffer; + return &config->buffer; +} + +int32_t ViperContext::process(audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) { + if (!isConfigValid) { + return -EINVAL; + } + + if (!enabled) { + return -ENODATA; + } + + inBuffer = getBuffer(&config.inputCfg, inBuffer); + outBuffer = getBuffer(&config.outputCfg, outBuffer); + if (inBuffer == nullptr || outBuffer == nullptr || + inBuffer->raw == nullptr || outBuffer->raw == nullptr || + inBuffer->frameCount != outBuffer->frameCount || + inBuffer->frameCount == 0) { + return -EINVAL; + } + + size_t frameCount = inBuffer->frameCount; + if (frameCount > bufferFrameCount) { + buffer.resize(frameCount * 2); + bufferFrameCount = frameCount; + } + + switch (config.inputCfg.format) { + case AUDIO_FORMAT_PCM_16_BIT: + pcm16ToFloat(buffer.data(), inBuffer->s16, frameCount); + break; + case AUDIO_FORMAT_PCM_32_BIT: + pcm32ToFloat(buffer.data(), inBuffer->s32, frameCount); + break; + case AUDIO_FORMAT_PCM_FLOAT: + floatToFloat(buffer.data(), inBuffer->f32, frameCount, false); + break; + default: + return -EINVAL; + } + + viper.processBuffer(buffer.data(), frameCount); + + 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); + break; + case AUDIO_FORMAT_PCM_32_BIT: + floatToPcm32(outBuffer->s32, buffer.data(), frameCount, accumulate); + break; + case AUDIO_FORMAT_PCM_FLOAT: + floatToFloat(outBuffer->f32, buffer.data(), frameCount, accumulate); + break; + default: + return -EINVAL; + } + + return 0; +} diff --git a/src/ViperContext.h b/src/ViperContext.h new file mode 100644 index 0000000..0bf0e04 --- /dev/null +++ b/src/ViperContext.h @@ -0,0 +1,32 @@ +#pragma once + +#include +#include +#include "essential.h" +#include "viper/ViPER.h" + +class ViperContext { +public: + effect_config_t config; + bool isConfigValid; + + // Processing buffer + std::vector buffer; + size_t bufferFrameCount; + + // Viper + bool enabled; + ViPER viper; + + ViperContext(); + + int32_t handleCommand(uint32_t cmdCode, uint32_t cmdSize, void *pCmdData, uint32_t *replySize, void *pReplyData); + + int32_t process(audio_buffer_t *inBuffer, audio_buffer_t *outBuffer); + + int handleSetConfig(effect_config_t *newConfig); + + int32_t handleSetParam(effect_param_t *pCmdParam, void *pReplyData); + + int32_t handleGetParam(effect_param_t *pCmdParam, effect_param_t *pReplyParam, uint32_t *pReplySize); +}; diff --git a/src/viper/ViPER.cpp b/src/viper/ViPER.cpp index 4408c7e..6a841f2 100644 --- a/src/viper/ViPER.cpp +++ b/src/viper/ViPER.cpp @@ -1,6 +1,6 @@ #include "ViPER.h" -#include #include +#include #include "constants.h" ViPER::ViPER() { @@ -141,9 +141,9 @@ void ViPER::processBuffer(float *buffer, uint32_t size) { } if (this->updateProcessTime) { - struct timeval time{}; - gettimeofday(&time, nullptr); - this->processTimeMs = (uint64_t) (time.tv_sec * 1000) + (uint64_t) (time.tv_usec / 1000); + auto now = std::chrono::system_clock::now(); + auto now_ms = std::chrono::time_point_cast(now); + this->processTimeMs = now_ms.time_since_epoch().count(); } uint32_t ret; diff --git a/src/viper/constants.h b/src/viper/constants.h index 2a7711d..1650301 100644 --- a/src/viper/constants.h +++ b/src/viper/constants.h @@ -8,5 +8,6 @@ #include "../log.h" // TODO: Remove this dependency -#define VIPER_DEFAULT_SAMPLING_RATE 44100 -#define VIPER_AUTHORS "viper.WYF, Martmists, Iscle" \ No newline at end of file +#define VIPER_NAME "ViPER4Android" +#define VIPER_AUTHORS "viper.WYF, Martmists, Iscle" +#define VIPER_DEFAULT_SAMPLING_RATE 44100 \ No newline at end of file diff --git a/src/viper/effects/AnalogX.cpp b/src/viper/effects/AnalogX.cpp index 7c8c14e..0b57efa 100644 --- a/src/viper/effects/AnalogX.cpp +++ b/src/viper/effects/AnalogX.cpp @@ -19,6 +19,8 @@ AnalogX::AnalogX() { this->samplingRate = VIPER_DEFAULT_SAMPLING_RATE; this->processingModel = 0; this->enable = false; + this->gain = 0.0; + this->freqRange = 0; Reset(); } diff --git a/src/viper/effects/AnalogX.h b/src/viper/effects/AnalogX.h index 98e5ea2..8640cce 100644 --- a/src/viper/effects/AnalogX.h +++ b/src/viper/effects/AnalogX.h @@ -3,6 +3,7 @@ #include #include "../utils/Harmonic.h" #include "../utils/MultiBiquad.h" +#include class AnalogX { public: @@ -15,10 +16,10 @@ public: void SetSamplingRate(uint32_t samplingRate); private: - MultiBiquad highPass[2]; - Harmonic harmonic[2]; - MultiBiquad lowPass[2]; - MultiBiquad peak[2]; + std::array highPass; + std::array harmonic; + std::array lowPass; + std::array peak; float gain; uint32_t freqRange; diff --git a/src/viper/effects/DiffSurround.cpp b/src/viper/effects/DiffSurround.cpp index 49f36d3..d4d9583 100644 --- a/src/viper/effects/DiffSurround.cpp +++ b/src/viper/effects/DiffSurround.cpp @@ -2,51 +2,45 @@ #include "DiffSurround.h" #include "../constants.h" -DiffSurround::DiffSurround() { +DiffSurround::DiffSurround() : buffers({ + WaveBuffer(1, 0x1000), + WaveBuffer(1, 0x1000) +}) { this->samplingRate = VIPER_DEFAULT_SAMPLING_RATE; this->delayTime = 0.0f; this->enable = false; - for (auto &buffer : this->buffers) { - buffer = new WaveBuffer(1, 0x1000); - } Reset(); } -DiffSurround::~DiffSurround() { - for (auto &buffer : this->buffers) { - delete buffer; - } -} - void DiffSurround::Process(float *samples, uint32_t size) { if (!this->enable) return; float *bufs[2]; float *outbufs[2]; - bufs[0] = this->buffers[0]->PushZerosGetBuffer(size); - bufs[1] = this->buffers[1]->PushZerosGetBuffer(size); + bufs[0] = this->buffers[0].PushZerosGetBuffer(size); + bufs[1] = this->buffers[1].PushZerosGetBuffer(size); for (uint32_t i = 0; i < size * 2; i++) { bufs[i % 2][i / 2] = samples[i]; } - outbufs[0] = this->buffers[0]->GetBuffer(); - outbufs[1] = this->buffers[1]->GetBuffer(); + outbufs[0] = this->buffers[0].GetBuffer(); + outbufs[1] = this->buffers[1].GetBuffer(); for (uint32_t i = 0; i < size * 2; i++) { samples[i] = outbufs[i % 2][i / 2]; } - this->buffers[0]->PopSamples(size, false); - this->buffers[1]->PopSamples(size, false); + this->buffers[0].PopSamples(size, false); + this->buffers[1].PopSamples(size, false); } void DiffSurround::Reset() { - this->buffers[0]->Reset(); - this->buffers[1]->Reset(); + this->buffers[0].Reset(); + this->buffers[1].Reset(); - this->buffers[1]->PushZeros((uint32_t) ((double) this->delayTime / 1000.0 * (double) this->samplingRate)); + this->buffers[1].PushZeros((uint32_t) ((double) this->delayTime / 1000.0 * (double) this->samplingRate)); } void DiffSurround::SetDelayTime(float delayTime) { diff --git a/src/viper/effects/DiffSurround.h b/src/viper/effects/DiffSurround.h index eb10ac0..bb70c2a 100644 --- a/src/viper/effects/DiffSurround.h +++ b/src/viper/effects/DiffSurround.h @@ -2,11 +2,11 @@ #include #include "../utils/WaveBuffer.h" +#include class DiffSurround { public: DiffSurround(); - ~DiffSurround(); void Process(float *samples, uint32_t size); void Reset(); @@ -17,7 +17,7 @@ public: uint32_t samplingRate; bool enable; float delayTime; - WaveBuffer *buffers[2]; + std::array buffers; }; diff --git a/src/viper/effects/IIRFilter.h b/src/viper/effects/IIRFilter.h index 9653980..b104f74 100644 --- a/src/viper/effects/IIRFilter.h +++ b/src/viper/effects/IIRFilter.h @@ -2,6 +2,7 @@ #include #include "../utils/MinPhaseIIRCoeffs.h" +#include // Iscle: Verified with the latest version at 13/12/2022 @@ -24,7 +25,7 @@ private: uint32_t unknown2; uint32_t unknown3; uint32_t unknown4; - float bandLevelsWithQ[31]; + std::array bandLevelsWithQ; }; diff --git a/src/viper/effects/SoftwareLimiter.cpp b/src/viper/effects/SoftwareLimiter.cpp index ea2ba94..599db5d 100644 --- a/src/viper/effects/SoftwareLimiter.cpp +++ b/src/viper/effects/SoftwareLimiter.cpp @@ -2,6 +2,10 @@ #include #include "SoftwareLimiter.h" +#ifndef uint +#define uint unsigned int +#endif + SoftwareLimiter::SoftwareLimiter() { this->ready = false; this->unknown4 = 0; diff --git a/src/viper/effects/SpeakerCorrection.h b/src/viper/effects/SpeakerCorrection.h index 69fd961..50f6271 100644 --- a/src/viper/effects/SpeakerCorrection.h +++ b/src/viper/effects/SpeakerCorrection.h @@ -3,6 +3,7 @@ #include #include "../utils/MultiBiquad.h" #include "../utils/Biquad.h" +#include // Iscle: Verified with the latest version at 13/12/2022 @@ -18,7 +19,7 @@ public: private: uint32_t samplingRate; bool enable; - MultiBiquad highPass[2]; - Biquad lowPass[2]; - Biquad bandPass[2]; + std::array highPass; + std::array lowPass; + std::array bandPass; }; diff --git a/src/viper/effects/SpectrumExtend.cpp b/src/viper/effects/SpectrumExtend.cpp index 18c8ba9..bed768d 100644 --- a/src/viper/effects/SpectrumExtend.cpp +++ b/src/viper/effects/SpectrumExtend.cpp @@ -22,10 +22,6 @@ SpectrumExtend::SpectrumExtend() { Reset(); } -SpectrumExtend::~SpectrumExtend() { - // empty? -} - void SpectrumExtend::Process(float *samples, uint32_t size) { if (!this->enabled) return; diff --git a/src/viper/effects/SpectrumExtend.h b/src/viper/effects/SpectrumExtend.h index 852e557..ec41516 100644 --- a/src/viper/effects/SpectrumExtend.h +++ b/src/viper/effects/SpectrumExtend.h @@ -3,11 +3,11 @@ #include #include "../utils/Harmonic.h" #include "../utils/MultiBiquad.h" +#include class SpectrumExtend { public: SpectrumExtend(); - ~SpectrumExtend(); void Process(float *samples, uint32_t size); void Reset(); @@ -17,9 +17,9 @@ public: void SetSamplingRate(uint32_t samplingRate); private: - MultiBiquad highpass[2]; - MultiBiquad lowpass[2]; - Harmonic harmonics[2]; + std::array highpass; + std::array lowpass; + std::array harmonics; bool enabled; uint32_t samplingRate; uint32_t referenceFreq; diff --git a/src/viper/effects/TubeSimulator.cpp b/src/viper/effects/TubeSimulator.cpp index ed20dc0..e61482a 100644 --- a/src/viper/effects/TubeSimulator.cpp +++ b/src/viper/effects/TubeSimulator.cpp @@ -2,11 +2,11 @@ // Iscle: Verified with the latest version at 13/12/2022 -TubeSimulator::TubeSimulator() { - this->acc[0] = 0.0; - this->acc[1] = 0.0; - this->enable = false; -} +TubeSimulator::TubeSimulator() : + acc({ + 0.0, 0.0 + }), + enable(false) {} void TubeSimulator::Reset() { this->acc[0] = 0.0; diff --git a/src/viper/effects/TubeSimulator.h b/src/viper/effects/TubeSimulator.h index 6224a83..3bb6fec 100644 --- a/src/viper/effects/TubeSimulator.h +++ b/src/viper/effects/TubeSimulator.h @@ -1,6 +1,7 @@ #pragma once #include +#include // Iscle: Verified with the latest version at 13/12/2022 @@ -13,7 +14,7 @@ public: void TubeProcess(float *buffer, uint32_t size); private: - double acc[2]; + std::array acc; bool enable; }; diff --git a/src/viper/utils/TimeConstDelay.cpp b/src/viper/utils/TimeConstDelay.cpp index 0fe8d4c..12a6fee 100644 --- a/src/viper/utils/TimeConstDelay.cpp +++ b/src/viper/utils/TimeConstDelay.cpp @@ -1,5 +1,5 @@ #include "TimeConstDelay.h" -#include +#include TimeConstDelay::TimeConstDelay() { this->offset = 0; @@ -9,7 +9,7 @@ TimeConstDelay::TimeConstDelay() { float TimeConstDelay::ProcessSample(float sample) { float val = this->samples[this->offset]; this->samples[this->offset] = sample; - this->offset = (uint32_t) modf((float) this->offset + 1, (float *) &this->sampleCount); // TODO: check if this is correct + this->offset = (uint32_t) modff((float) this->offset + 1, (float *) &this->sampleCount); // TODO: check if this is correct return val; }