This commit is contained in:
Iscle 2022-10-11 00:36:38 +02:00
parent 9d54379bd8
commit 39aef22062
21 changed files with 407 additions and 529 deletions

View File

@ -1,7 +1,5 @@
#include <cstring> #include <cstring>
#include <cerrno>
#include <ctime> #include <ctime>
#include "viper/ViPER.h" #include "viper/ViPER.h"
#include "essential.h" #include "essential.h"
#include "log.h" #include "log.h"
@ -10,7 +8,6 @@
#define VIPER_EFFECT_NAME "ViPER4Android" #define VIPER_EFFECT_NAME "ViPER4Android"
static effect_descriptor_t viper_descriptor = { static effect_descriptor_t viper_descriptor = {
// ee48cf24-9221-4095-2cb9-40faa133111b
.type = EFFECT_UUID_INITIALIZER, .type = EFFECT_UUID_INITIALIZER,
// 41d3c987-e6cf-11e3-a88a-11aba5d5c51b // 41d3c987-e6cf-11e3-a88a-11aba5d5c51b
// Original: {0x41d3c987, 0xe6cf, 0x11e3, 0xa88a, {0x11, 0xab, 0xa5, 0xd5, 0xc5, 0x1b}} // Original: {0x41d3c987, 0xe6cf, 0x11e3, 0xa88a, {0x11, 0xab, 0xa5, 0xd5, 0xc5, 0x1b}}
@ -28,18 +25,13 @@ extern "C" {
struct ViperContext { struct ViperContext {
const struct effect_interface_s *interface; // Should always be the first struct member const struct effect_interface_s *interface; // Should always be the first struct member
effect_config_t config; effect_config_t config;
bool isConfigValid;
ViPER *viper; ViPER *viper;
}; };
static int32_t Viper_IProcess(effect_handle_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) { static int32_t Viper_IProcess(effect_handle_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) {
auto pContext = reinterpret_cast<ViperContext *>(self); auto pContext = reinterpret_cast<ViperContext *>(self);
static uint32_t tmp = 0;
if (tmp % 50 == 0) {
VIPER_LOGD("Viper_IProcess called!");
}
tmp++;
if (pContext == nullptr || if (pContext == nullptr ||
inBuffer == nullptr || outBuffer == nullptr || inBuffer == nullptr || outBuffer == nullptr ||
inBuffer->raw == nullptr || outBuffer->raw == nullptr || inBuffer->raw == nullptr || outBuffer->raw == nullptr ||
@ -55,12 +47,12 @@ static int32_t Viper_IProcess(effect_handle_t self, audio_buffer_t *inBuffer, au
memcpy(outBufferPtr, inBufferPtr, outBuffer->frameCount * 2 * sizeof(float)); memcpy(outBufferPtr, inBufferPtr, outBuffer->frameCount * 2 * sizeof(float));
} }
/*return */pContext->viper->processBuffer(outBufferPtr, outBuffer->frameCount); pContext->viper->processBuffer(outBufferPtr, outBuffer->frameCount);
return 0; // TODO: Return code from processBuffer() return 0;
} }
static int configure(ViperContext *pContext, effect_config_t *newConfig) { static int handleSetConfig(ViperContext *pContext, effect_config_t *newConfig) {
VIPER_LOGI("Begin audio configure ..."); VIPER_LOGI("Begin handleSetConfig ...");
VIPER_LOGI("Checking input and output configuration ..."); VIPER_LOGI("Checking input and output configuration ...");
VIPER_LOGD("Input sampling rate: %d", newConfig->inputCfg.samplingRate); VIPER_LOGD("Input sampling rate: %d", newConfig->inputCfg.samplingRate);
@ -70,6 +62,8 @@ static int configure(ViperContext *pContext, effect_config_t *newConfig) {
VIPER_LOGD("Output channels: %d", newConfig->outputCfg.channels); VIPER_LOGD("Output channels: %d", newConfig->outputCfg.channels);
VIPER_LOGD("Output format: %d", newConfig->outputCfg.format); VIPER_LOGD("Output format: %d", newConfig->outputCfg.format);
pContext->isConfigValid = false;
if (newConfig->inputCfg.samplingRate != newConfig->outputCfg.samplingRate) { if (newConfig->inputCfg.samplingRate != newConfig->outputCfg.samplingRate) {
VIPER_LOGE("ViPER4Android disabled, reason [in.SR = %d, out.SR = %d]", VIPER_LOGE("ViPER4Android disabled, reason [in.SR = %d, out.SR = %d]",
newConfig->inputCfg.samplingRate, newConfig->outputCfg.samplingRate); newConfig->inputCfg.samplingRate, newConfig->outputCfg.samplingRate);
@ -109,65 +103,23 @@ static int configure(ViperContext *pContext, effect_config_t *newConfig) {
VIPER_LOGI("Input and output configuration checked."); VIPER_LOGI("Input and output configuration checked.");
pContext->config = *newConfig; pContext->config = *newConfig;
pContext->viper->samplingRate = newConfig->inputCfg.samplingRate;
pContext->viper->ResetAllEffects();
pContext->isConfigValid = true;
VIPER_LOGI("Audio configure finished"); VIPER_LOGI("Audio handleSetConfig finished");
return 0; return 0;
} }
static int32_t Viper_ICommand(effect_handle_t self, static int32_t handleSetParam(ViperContext *pContext, effect_param_t *pCmdParam, void *pReplyData) {
uint32_t cmdCode, uint32_t cmdSize, void *pCmdData,
uint32_t *replySize, void *pReplyData) {
auto pContext = reinterpret_cast<ViperContext *>(self);
if (pContext == nullptr || pContext->viper == nullptr) {
VIPER_LOGE("Viper_ICommand: pContext or pContext->viper is null!");
return -EINVAL;
}
VIPER_LOGD("Viper_ICommand() called with cmdCode = %d", cmdCode);
switch (cmdCode) {
case EFFECT_CMD_INIT:
*((int *) pReplyData) = 0;
return 0;
case EFFECT_CMD_SET_CONFIG: {
auto currentSampleRate = pContext->viper->samplingRate;
*(int *) pReplyData = configure(pContext, (effect_config_t *) pCmdData);
if (*(int *) pReplyData == 0) {
if (currentSampleRate != pContext->viper->samplingRate) {
pContext->viper->ResetAllEffects();
}
}
return 0;
}
case EFFECT_CMD_RESET: {
pContext->viper->ResetAllEffects();
break;
}
case EFFECT_CMD_ENABLE: {
if (!pContext->viper->enabled) {
pContext->viper->ResetAllEffects();
}
pContext->viper->enabled = true;
*((int *) pReplyData) = 0;
return 0;
}
case EFFECT_CMD_DISABLE: {
pContext->viper->enabled = false;
*((int *) pReplyData) = 0;
return 0;
}
case EFFECT_CMD_SET_PARAM: {
auto *pCmdParam = reinterpret_cast<effect_param_t *>(pCmdData);
// The value offset of an effect parameter is computed by rounding up // The value offset of an effect parameter is computed by rounding up
// the parameter size to the next 32 bit alignment. // the parameter size to the next 32 bit alignment.
uint32_t vOffset = ((pCmdParam->psize + sizeof(int32_t) - 1) / sizeof(int32_t)) * sizeof(int32_t); uint32_t vOffset = ((pCmdParam->psize + sizeof(int32_t) - 1) / sizeof(int32_t)) * sizeof(int32_t);
int param = *(int *) (pCmdParam->data);
*(int *) pReplyData = 0; *(int *) pReplyData = 0;
int param = *(int *) (pCmdParam->data);
int *intValues = (int *) (pCmdParam->data + vOffset); int *intValues = (int *) (pCmdParam->data + vOffset);
if (pCmdParam->vsize == sizeof(int)) { if (pCmdParam->vsize == sizeof(int)) {
pContext->viper->DispatchCommand(param, intValues[0], 0, 0, 0, 0, nullptr); pContext->viper->DispatchCommand(param, intValues[0], 0, 0, 0, 0, nullptr);
@ -193,38 +145,39 @@ static int32_t Viper_ICommand(effect_handle_t self,
pContext->viper->DispatchCommand(param, value1, 0, 0, 0, arrSize, arr); pContext->viper->DispatchCommand(param, value1, 0, 0, 0, arrSize, arr);
return 0; return 0;
} }
}
case EFFECT_CMD_GET_PARAM: { return -EINVAL;
auto *pCmdParam = reinterpret_cast<effect_param_t *>(pCmdData); }
auto *pReplyParam = reinterpret_cast<effect_param_t *>(pReplyData);
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 value offset of an effect parameter is computed by rounding up
// the parameter size to the next 32 bit alignment. // the parameter size to the next 32 bit alignment.
uint32_t vOffset = ((pCmdParam->psize + sizeof(int32_t) - 1) / sizeof(int32_t)) * sizeof(int32_t); uint32_t vOffset = ((pCmdParam->psize + sizeof(int32_t) - 1) / sizeof(int32_t)) * sizeof(int32_t);
VIPER_LOGD("Viper_ICommand() EFFECT_CMD_GET_PARAM called with data = %d, psize = %d, vsize = %d", *(uint32_t *) pCmdParam->data, pCmdParam->psize, pCmdParam->vsize); VIPER_LOGD("Viper_ICommand() 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); memcpy(pReplyParam, pCmdParam, sizeof(effect_param_t) + pCmdParam->psize);
switch (*(uint32_t *) pCmdParam->data) { switch (*(uint32_t *) pCmdParam->data) {
case PARAM_GET_DRIVER_VERSION: { case PARAM_GET_DRIVER_VERSION: {
pReplyParam->status = 0; pReplyParam->status = 0;
pReplyParam->vsize = sizeof(uint32_t); pReplyParam->vsize = sizeof(uint32_t);
*(uint32_t *) (pReplyParam->data + vOffset) = 0x2050005; // As original, change as needed *(uint32_t *) (pReplyParam->data + vOffset) = 0x2050005; // As original, change as needed
*replySize = sizeof(effect_param_t) + pReplyParam->psize + vOffset + pReplyParam->vsize; *pReplySize = sizeof(effect_param_t) + pReplyParam->psize + vOffset + pReplyParam->vsize;
return 0; return 0;
} }
case PARAM_GET_ENABLED: { case PARAM_GET_ENABLED: {
pReplyParam->status = 0; pReplyParam->status = 0;
pReplyParam->vsize = sizeof(int32_t); pReplyParam->vsize = sizeof(int32_t);
*(int32_t *) (pReplyParam->data + vOffset) = pContext->viper->enabled; *(int32_t *) (pReplyParam->data + vOffset) = pContext->viper->enabled;
*replySize = sizeof(effect_param_t) + pReplyParam->psize + vOffset + pReplyParam->vsize; *pReplySize = sizeof(effect_param_t) + pReplyParam->psize + vOffset + pReplyParam->vsize;
return 0; return 0;
} }
case PARAM_GET_CONFIGURE: { case PARAM_GET_CONFIGURE: {
pReplyParam->status = 0; pReplyParam->status = 0;
pReplyParam->vsize = sizeof(int32_t); pReplyParam->vsize = sizeof(int32_t);
*(int32_t *) (pReplyParam->data + vOffset) = 1; // TODO? *(int32_t *) (pReplyParam->data + vOffset) = pContext->isConfigValid;
*replySize = sizeof(effect_param_t) + pReplyParam->psize + vOffset + pReplyParam->vsize; *pReplySize = sizeof(effect_param_t) + pReplyParam->psize + vOffset + pReplyParam->vsize;
return 0; return 0;
} }
case PARAM_GET_STREAMING: { // Is processing case PARAM_GET_STREAMING: { // Is processing
@ -232,7 +185,7 @@ static int32_t Viper_ICommand(effect_handle_t self,
gettimeofday(&time, nullptr); gettimeofday(&time, nullptr);
uint64_t currentMs = (time.tv_sec * 1000) + (time.tv_usec / 1000); uint64_t currentMs = (time.tv_sec * 1000) + (time.tv_usec / 1000);
uint64_t lastProcessTime = pContext->viper->process_time_ms; uint64_t lastProcessTime = pContext->viper->processTimeMs;
uint64_t diff; uint64_t diff;
if (currentMs > lastProcessTime) { if (currentMs > lastProcessTime) {
@ -244,24 +197,66 @@ static int32_t Viper_ICommand(effect_handle_t self,
pReplyParam->status = 0; pReplyParam->status = 0;
pReplyParam->vsize = sizeof(int32_t); pReplyParam->vsize = sizeof(int32_t);
*(int32_t *) (pReplyParam->data + vOffset) = diff > 5000 ? 0 : 1; *(int32_t *) (pReplyParam->data + vOffset) = diff > 5000 ? 0 : 1;
*replySize = sizeof(effect_param_t) + pReplyParam->psize + vOffset + pReplyParam->vsize; *pReplySize = sizeof(effect_param_t) + pReplyParam->psize + vOffset + pReplyParam->vsize;
return 0; return 0;
} }
case PARAM_GET_SAMPLINGRATE: { case PARAM_GET_SAMPLING_RATE: {
pReplyParam->status = 0; pReplyParam->status = 0;
pReplyParam->vsize = sizeof(uint32_t); pReplyParam->vsize = sizeof(uint32_t);
*(uint32_t *) (pReplyParam->data + vOffset) = pContext->viper->samplingRate; *(uint32_t *) (pReplyParam->data + vOffset) = pContext->viper->samplingRate;
*replySize = sizeof(effect_param_t) + pReplyParam->psize + vOffset + pReplyParam->vsize; *pReplySize = sizeof(effect_param_t) + pReplyParam->psize + vOffset + pReplyParam->vsize;
return 0; return 0;
} }
case PARAM_GET_CONVKNLID: { case PARAM_GET_CONVOLUTION_KERNEL_ID: {
pReplyParam->status = 0; pReplyParam->status = 0;
pReplyParam->vsize = sizeof(uint32_t); pReplyParam->vsize = sizeof(uint32_t);
*(uint32_t *) (pReplyParam->data + vOffset) = pContext->viper->convolver->GetKernelID(); *(uint32_t *) (pReplyParam->data + vOffset) = pContext->viper->convolver->GetKernelID();
*replySize = sizeof(effect_param_t) + pReplyParam->psize + vOffset + pReplyParam->vsize; *pReplySize = sizeof(effect_param_t) + pReplyParam->psize + vOffset + pReplyParam->vsize;
return 0; return 0;
} }
} }
return 0;
}
static int32_t Viper_ICommand(effect_handle_t self,
uint32_t cmdCode, uint32_t cmdSize, void *pCmdData,
uint32_t *replySize, void *pReplyData) {
auto pContext = reinterpret_cast<ViperContext *>(self);
if (pContext == nullptr || pContext->viper == nullptr) {
return -EINVAL;
}
VIPER_LOGD("Viper_ICommand() called with cmdCode = %d", cmdCode);
switch (cmdCode) {
case EFFECT_CMD_INIT:
*((int *) pReplyData) = 0;
return 0;
case EFFECT_CMD_SET_CONFIG: {
*(int *) pReplyData = handleSetConfig(pContext, (effect_config_t *) pCmdData);
return 0;
}
case EFFECT_CMD_RESET: {
pContext->viper->ResetAllEffects();
*((int *) pReplyData) = 0;
return 0;
}
case EFFECT_CMD_ENABLE: {
pContext->viper->ResetAllEffects();
pContext->viper->enabled = true;
*((int *) pReplyData) = 0;
return 0;
}
case EFFECT_CMD_DISABLE: {
pContext->viper->enabled = false;
*((int *) pReplyData) = 0;
return 0;
}
case EFFECT_CMD_SET_PARAM: {
return handleSetParam(pContext, (effect_param_t *) pCmdData, pReplyData);
}
case EFFECT_CMD_GET_PARAM: {
return handleGetParam(pContext, (effect_param_t *) pCmdData, (effect_param_t *) pReplyData, replySize);
} }
case EFFECT_CMD_GET_CONFIG: { case EFFECT_CMD_GET_CONFIG: {
*(effect_config_t *) pReplyData = pContext->config; *(effect_config_t *) pReplyData = pContext->config;
@ -275,10 +270,7 @@ static int32_t Viper_ICommand(effect_handle_t self,
static int32_t Viper_IGetDescriptor(effect_handle_t self, effect_descriptor_t *pDescriptor) { static int32_t Viper_IGetDescriptor(effect_handle_t self, effect_descriptor_t *pDescriptor) {
auto pContext = reinterpret_cast<ViperContext *>(self); auto pContext = reinterpret_cast<ViperContext *>(self);
VIPER_LOGD("Viper_IGetDescriptor called");
if (pContext == nullptr || pDescriptor == nullptr) { if (pContext == nullptr || pDescriptor == nullptr) {
VIPER_LOGE("Viper_IGetDescriptor: pContext or pDescriptor is null!");
return -EINVAL; return -EINVAL;
} }
@ -295,40 +287,21 @@ static const effect_interface_s viper_interface = {
static void Viper_Init(ViperContext *pContext) { static void Viper_Init(ViperContext *pContext) {
pContext->interface = &viper_interface; pContext->interface = &viper_interface;
memset(&pContext->config, 0, sizeof(effect_config_t)); memset(&pContext->config, 0, sizeof(effect_config_t));
pContext->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
pContext->config.inputCfg.format = AUDIO_FORMAT_PCM_FLOAT;
pContext->config.inputCfg.samplingRate = DEFAULT_SAMPLERATE;
pContext->config.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
pContext->config.inputCfg.mask = AUDIO_PORT_CONFIG_ALL;
pContext->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
pContext->config.outputCfg.format = AUDIO_FORMAT_PCM_FLOAT;
pContext->config.outputCfg.samplingRate = DEFAULT_SAMPLERATE;
pContext->config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
pContext->config.outputCfg.mask = AUDIO_PORT_CONFIG_ALL;
pContext->viper = new ViPER(); pContext->viper = new ViPER();
} }
static int32_t static int32_t
Viper_Create(const effect_uuid_t *uuid, int32_t sessionId __unused, int32_t ioId __unused, effect_handle_t *pHandle) { Viper_Create(const effect_uuid_t *uuid, int32_t sessionId __unused, int32_t ioId __unused, effect_handle_t *pHandle) {
VIPER_LOGI("Enter Viper_Create()");
if (uuid == nullptr || pHandle == nullptr) { if (uuid == nullptr || pHandle == nullptr) {
VIPER_LOGE("Viper_Create: uuid or pHandle is null!");
return -EINVAL; return -EINVAL;
} }
if (memcmp(uuid, &viper_descriptor.uuid, sizeof(effect_uuid_t)) != 0) { if (memcmp(uuid, &viper_descriptor.uuid, sizeof(effect_uuid_t)) != 0) {
VIPER_LOGE("Viper_Create: uuid is not viper_descriptor.uuid!");
return -EINVAL; return -EINVAL;
} }
VIPER_LOGI("Viper_Create: uuid matches, creating viper..."); VIPER_LOGD("Creating new ViPER instance");
auto *pContext = new ViperContext; auto *pContext = new ViperContext;
Viper_Init(pContext); Viper_Init(pContext);
*pHandle = reinterpret_cast<effect_handle_t>(pContext); *pHandle = reinterpret_cast<effect_handle_t>(pContext);
@ -339,15 +312,11 @@ Viper_Create(const effect_uuid_t *uuid, int32_t sessionId __unused, int32_t ioId
static int32_t Viper_Release(effect_handle_t handle) { static int32_t Viper_Release(effect_handle_t handle) {
auto pContext = reinterpret_cast<ViperContext *>(handle); auto pContext = reinterpret_cast<ViperContext *>(handle);
VIPER_LOGI("Enter Viper_Release()");
if (pContext == nullptr) { if (pContext == nullptr) {
VIPER_LOGE("Viper_Release: pContext is null!");
return -EINVAL; return -EINVAL;
} }
VIPER_LOGI("Viper_Release: deleting viper..."); VIPER_LOGD("Releasing ViPER instance");
delete pContext->viper; delete pContext->viper;
delete pContext; delete pContext;
@ -355,20 +324,14 @@ static int32_t Viper_Release(effect_handle_t handle) {
} }
static int32_t Viper_GetDescriptor(const effect_uuid_t *uuid, effect_descriptor_t *pDescriptor) { static int32_t Viper_GetDescriptor(const effect_uuid_t *uuid, effect_descriptor_t *pDescriptor) {
VIPER_LOGI("Enter Viper_GetDescriptor()");
if (uuid == nullptr || pDescriptor == nullptr) { if (uuid == nullptr || pDescriptor == nullptr) {
VIPER_LOGE("Viper_GetDescriptor: uuid or pDescriptor is null!");
return -EINVAL; return -EINVAL;
} }
if (memcmp(uuid, &viper_descriptor.uuid, sizeof(effect_uuid_t)) != 0) { if (memcmp(uuid, &viper_descriptor.uuid, sizeof(effect_uuid_t)) != 0) {
VIPER_LOGE("Viper_GetDescriptor: uuid is not viper_descriptor.uuid!");
return -EINVAL; return -EINVAL;
} }
VIPER_LOGI("Viper_GetDescriptor: uuid matches, returning descriptor...");
*pDescriptor = viper_descriptor; *pDescriptor = viper_descriptor;
return 0; return 0;

View File

@ -4,35 +4,24 @@
// Updated parameters source: https://github.com/vipersaudio/viper4android_fx/blob/master/android_4.x/src/com/vipercn/viper4android_v2/service/ViPER4AndroidService.java // Updated parameters source: https://github.com/vipersaudio/viper4android_fx/blob/master/android_4.x/src/com/vipercn/viper4android_v2/service/ViPER4AndroidService.java
extern "C" { extern "C" {
enum ParamsMode { // Command code
COMMAND_CODE_GET = 0x01, #define COMMAND_CODE_GET 0x01
COMMAND_CODE_SET, #define COMMAND_CODE_SET 0x02
};
enum ParamsGet { // Param get
PARAM_GET_DRIVER_VERSION = 0, #define PARAM_GET_DRIVER_VERSION 0
PARAM_GET_ENABLED, #define PARAM_GET_ENABLED 1
PARAM_GET_CONFIGURE, #define PARAM_GET_CONFIGURE 2
PARAM_GET_STREAMING, #define PARAM_GET_STREAMING 3
PARAM_GET_SAMPLINGRATE, #define PARAM_GET_SAMPLING_RATE 4
PARAM_GET_CONVKNLID #define PARAM_GET_CONVOLUTION_KERNEL_ID 5
};
// Param set
#define PARAM_SET_UPDATE_STATUS 0x9002
#define PARAM_SET_RESET_STATUS 0x9003
enum ParamsSet { enum ParamsSet {
PARAM_SET_STATUS_BEGIN = 0x9000, PARAM_FX_TYPE_SWITCH = 0x10001, // 0x10001
PARAM_SET_UNKNOWN,
PARAM_SET_UPDATE_STATUS,
PARAM_SET_RESET_STATUS,
PARAM_SET_DOPROCESS_STATUS,
PARAM_SET_FORCEENABLE_STATUS,
PARAM_SET_SELFDIAGNOSE_STATUS,
PARAM_SET_STATUS_END
};
enum ParamsConfigure {
PARAM_PROCESSUNIT_FX_BEGIN = 0x10000,
PARAM_FX_TYPE_SWITCH, // 0x10001
PARAM_HPFX_CONV_PROCESS_ENABLED, // 0x10002 PARAM_HPFX_CONV_PROCESS_ENABLED, // 0x10002
PARAM_HPFX_CONV_UPDATEKERNEL, // 0x10003 PARAM_HPFX_CONV_UPDATEKERNEL, // 0x10003
/*****************************************/ /*****************************************/
@ -87,26 +76,7 @@ enum ParamsConfigure {
PARAM_HPFX_OUTPUT_VOLUME, // 0x10032 PARAM_HPFX_OUTPUT_VOLUME, // 0x10032
PARAM_HPFX_OUTPUT_PAN, // 0x10033 PARAM_HPFX_OUTPUT_PAN, // 0x10033
PARAM_HPFX_LIMITER_THRESHOLD, // 0x10034 PARAM_HPFX_LIMITER_THRESHOLD, // 0x10034
PARAM_SPKFX_CONV_PROCESS_ENABLED, // 0x10035
PARAM_SPKFX_CONV_UPDATEKERNEL, // 0x10036
PARAM_SPKFX_CONV_PREPAREBUFFER, // 0x10037
PARAM_SPKFX_CONV_SETBUFFER, // 0x10038
PARAM_SPKFX_CONV_COMMITBUFFER, // 0x10039
PARAM_SPKFX_CONV_CROSSCHANNEL, // 0x1003A
PARAM_SPKFX_FIREQ_PROCESS_ENABLED, // 0x1003B
PARAM_SPKFX_FIREQ_BANDLEVEL, // 0x1003C
PARAM_SPKFX_REVB_PROCESS_ENABLED, // 0x1003D
PARAM_SPKFX_REVB_ROOMSIZE, // 0x1003E
PARAM_SPKFX_REVB_WIDTH, // 0x1003F
PARAM_SPKFX_REVB_DAMP, // 0x10040
PARAM_SPKFX_REVB_WET, // 0x10041
PARAM_SPKFX_REVB_DRY, // 0x10042
PARAM_SPKFX_AGC_PROCESS_ENABLED, // 0x10043 PARAM_SPKFX_AGC_PROCESS_ENABLED, // 0x10043
PARAM_SPKFX_AGC_RATIO, // 0x10044
PARAM_SPKFX_AGC_VOLUME, // 0x10045
PARAM_SPKFX_AGC_MAXSCALER, // 0x10046
PARAM_SPKFX_OUTPUT_VOLUME, // 0x10047
PARAM_SPKFX_LIMITER_THRESHOLD, // 0x10048
PARAM_HPFX_FETCOMP_PROCESS_ENABLED, // 0x10049 PARAM_HPFX_FETCOMP_PROCESS_ENABLED, // 0x10049
PARAM_HPFX_FETCOMP_THRESHOLD, // 0x1004A PARAM_HPFX_FETCOMP_THRESHOLD, // 0x1004A
PARAM_HPFX_FETCOMP_RATIO, // 0x1004B PARAM_HPFX_FETCOMP_RATIO, // 0x1004B
@ -124,25 +94,6 @@ enum ParamsConfigure {
PARAM_HPFX_FETCOMP_META_CREST, // 0x10057 PARAM_HPFX_FETCOMP_META_CREST, // 0x10057
PARAM_HPFX_FETCOMP_META_ADAPT, // 0x10058 PARAM_HPFX_FETCOMP_META_ADAPT, // 0x10058
PARAM_HPFX_FETCOMP_META_NOCLIP_ENABLED, // 0x10059 PARAM_HPFX_FETCOMP_META_NOCLIP_ENABLED, // 0x10059
PARAM_SPKFX_FETCOMP_PROCESS_ENABLED, // 0x1005A
PARAM_SPKFX_FETCOMP_THRESHOLD, // 0x1005B
PARAM_SPKFX_FETCOMP_RATIO, // 0x1005C
PARAM_SPKFX_FETCOMP_KNEEWIDTH, // 0x1005D
PARAM_SPKFX_FETCOMP_AUTOKNEE_ENABLED, // 0x1005E
PARAM_SPKFX_FETCOMP_GAIN, // 0x1005F
PARAM_SPKFX_FETCOMP_AUTOGAIN_ENABLED, // 0x10060
PARAM_SPKFX_FETCOMP_ATTACK, // 0x10061
PARAM_SPKFX_FETCOMP_AUTOATTACK_ENABLED, // 0x10062
PARAM_SPKFX_FETCOMP_RELEASE, // 0x10063
PARAM_SPKFX_FETCOMP_AUTORELEASE_ENABLED, // 0x10064
PARAM_SPKFX_FETCOMP_META_KNEEMULTI, // 0x10065
PARAM_SPKFX_FETCOMP_META_MAXATTACK, // 0x10066
PARAM_SPKFX_FETCOMP_META_MAXRELEASE, // 0x10067
PARAM_SPKFX_FETCOMP_META_CREST, // 0x10068
PARAM_SPKFX_FETCOMP_META_ADAPT, // 0x10069
PARAM_SPKFX_FETCOMP_META_NOCLIP_ENABLED, // 0x1006A
PARAM_PROCESSUNIT_FX_END
}; };
} }

View File

@ -7,6 +7,8 @@ ViPER::ViPER() {
VIPER_LOGI("Welcome to ViPER FX"); VIPER_LOGI("Welcome to ViPER FX");
VIPER_LOGI("Current version is %s %s", VERSION_STRING, VERSION_CODENAME); VIPER_LOGI("Current version is %s %s", VERSION_STRING, VERSION_CODENAME);
this->samplingRate = DEFAULT_SAMPLERATE;
this->adaptiveBuffer = new AdaptiveBuffer(2, 4096); this->adaptiveBuffer = new AdaptiveBuffer(2, 4096);
this->waveBuffer = new WaveBuffer(2, 4096); this->waveBuffer = new WaveBuffer(2, 4096);
@ -81,11 +83,11 @@ ViPER::ViPER() {
this->cure->Reset(); this->cure->Reset();
this->tubeSimulator = new TubeSimulator(); this->tubeSimulator = new TubeSimulator();
this->tubeSimulator->enabled = false; //SetEnable(false); this->tubeSimulator->SetEnable(false);
this->tubeSimulator->Reset(); this->tubeSimulator->Reset();
this->analogX = new AnalogX(); this->analogX = new AnalogX();
// this->analogX->SetEnable(false); this->analogX->SetEnable(false);
this->analogX->SetSamplingRate(this->samplingRate); this->analogX->SetSamplingRate(this->samplingRate);
this->analogX->SetProcessingModel(0); this->analogX->SetProcessingModel(0);
this->analogX->Reset(); this->analogX->Reset();
@ -100,12 +102,12 @@ ViPER::ViPER() {
softwareLimiter->ResetLimiter(); softwareLimiter->ResetLimiter();
} }
this->frame_scale = 1.0; this->frameScale = 1.0;
this->left_pan = 1.0; this->leftPan = 1.0;
this->process_time_ms = 0; this->rightPan = 1.0;
this->right_pan = 1.0; this->updateProcessTime = false;
this->processTimeMs = 0;
this->enabled = false; this->enabled = false;
this->update_status = false;
} }
ViPER::~ViPER() { ViPER::~ViPER() {
@ -144,10 +146,10 @@ void ViPER::processBuffer(float *buffer, uint32_t size) {
return; return;
} }
if (this->update_status) { if (this->updateProcessTime) {
struct timeval time{}; struct timeval time{};
gettimeofday(&time, nullptr); gettimeofday(&time, nullptr);
this->process_time_ms = time.tv_sec * 1000 + time.tv_usec / 1000; this->processTimeMs = time.tv_sec * 1000 + time.tv_usec / 1000;
} }
uint32_t ret; uint32_t ret;
@ -155,6 +157,8 @@ void ViPER::processBuffer(float *buffer, uint32_t size) {
uint32_t tmpBufSize; uint32_t tmpBufSize;
if (this->convolver->GetEnabled() || this->vhe->GetEnabled()) { if (this->convolver->GetEnabled() || this->vhe->GetEnabled()) {
VIPER_LOGD("Convolver or VHE is enable, use wave buffer");
if (!this->waveBuffer->PushSamples(buffer, size)) { if (!this->waveBuffer->PushSamples(buffer, size)) {
this->waveBuffer->Reset(); this->waveBuffer->Reset();
return; return;
@ -178,6 +182,8 @@ void ViPER::processBuffer(float *buffer, uint32_t size) {
tmpBuf = ptr; tmpBuf = ptr;
tmpBufSize = ret; tmpBufSize = ret;
} else { } else {
VIPER_LOGD("Convolver and VHE are disabled, use adaptive buffer");
if (this->adaptiveBuffer->PushFrames(buffer, size)) { if (this->adaptiveBuffer->PushFrames(buffer, size)) {
this->adaptiveBuffer->SetBufferOffset(size); this->adaptiveBuffer->SetBufferOffset(size);
@ -189,6 +195,7 @@ void ViPER::processBuffer(float *buffer, uint32_t size) {
} }
} }
// VIPER_LOGD("Process buffer size: %d", tmpBufSize);
if (tmpBufSize != 0) { if (tmpBufSize != 0) {
this->viperDdc->Process(tmpBuf, size); this->viperDdc->Process(tmpBuf, size);
this->spectrumExtend->Process(tmpBuf, size); this->spectrumExtend->Process(tmpBuf, size);
@ -206,12 +213,12 @@ void ViPER::processBuffer(float *buffer, uint32_t size) {
this->tubeSimulator->TubeProcess(tmpBuf, size); this->tubeSimulator->TubeProcess(tmpBuf, size);
this->analogX->Process(tmpBuf, tmpBufSize); this->analogX->Process(tmpBuf, tmpBufSize);
if (this->frame_scale != 1.0) { if (this->frameScale != 1.0) {
this->adaptiveBuffer->ScaleFrames(this->frame_scale); this->adaptiveBuffer->ScaleFrames(this->frameScale);
} }
if (this->left_pan < 1.0 || this->right_pan < 1.0) { if (this->leftPan < 1.0 || this->rightPan < 1.0) {
this->adaptiveBuffer->PanFrames(this->left_pan, this->right_pan); this->adaptiveBuffer->PanFrames(this->leftPan, this->rightPan);
} }
for (uint32_t i = 0; i < tmpBufSize * 2; i += 2) { for (uint32_t i = 0; i < tmpBufSize * 2; i += 2) {
@ -235,41 +242,26 @@ void ViPER::processBuffer(float *buffer, uint32_t size) {
void ViPER::DispatchCommand(int param, int val1, int val2, int val3, int val4, uint32_t arrSize, void ViPER::DispatchCommand(int param, int val1, int val2, int val3, int val4, uint32_t arrSize,
signed char *arr) { signed char *arr) {
VIPER_LOGD("Dispatch command: %d, %d, %d, %d, %d, %d, %p", param, val1, val2, val3, val4, arrSize, arr);
switch (param) { switch (param) {
case PARAM_SET_UNKNOWN: {
break;
}
case PARAM_SET_UPDATE_STATUS: { case PARAM_SET_UPDATE_STATUS: {
this->updateProcessTime = val1 != 0;
break; break;
} }
case PARAM_SET_RESET_STATUS: { case PARAM_SET_RESET_STATUS: {
this->ResetAllEffects();
break; break;
} }
case PARAM_SET_DOPROCESS_STATUS: {
break;
}
case PARAM_SET_FORCEENABLE_STATUS: {
break;
}
case PARAM_SET_SELFDIAGNOSE_STATUS: {
break;
}
case PARAM_FX_TYPE_SWITCH: {
// Unused
// TODO: Remove
break;
} // 0x10001
case PARAM_HPFX_CONV_PROCESS_ENABLED: { case PARAM_HPFX_CONV_PROCESS_ENABLED: {
// this->convolver->SetEnabled(val1 != 0);
break; break;
} // 0x10002 } // 0x10002
case PARAM_HPFX_CONV_UPDATEKERNEL: {
break;
} // 0x10003
case PARAM_HPFX_CONV_PREPAREBUFFER: { case PARAM_HPFX_CONV_PREPAREBUFFER: {
this->convolver->PrepareKernelBuffer(val1, val2, val3); this->convolver->PrepareKernelBuffer(val1, val2, val3);
break; break;
} // 0x10004 } // 0x10004
case PARAM_HPFX_CONV_SETBUFFER: { case PARAM_HPFX_CONV_SETBUFFER: {
this->convolver->SetKernelBuffer(val1, (float *) arr, arrSize);
break; break;
} // 0x10005 } // 0x10005
case PARAM_HPFX_CONV_COMMITBUFFER: { case PARAM_HPFX_CONV_COMMITBUFFER: {
@ -277,6 +269,7 @@ void ViPER::DispatchCommand(int param, int val1, int val2, int val3, int val4, u
break; break;
} // 0x10006 } // 0x10006
case PARAM_HPFX_CONV_CROSSCHANNEL: { case PARAM_HPFX_CONV_CROSSCHANNEL: {
this->convolver->SetCrossChannel((float) val1 / 100.0f);
break; break;
} // 0x10007 } // 0x10007
case PARAM_HPFX_VHE_PROCESS_ENABLED: { case PARAM_HPFX_VHE_PROCESS_ENABLED: {
@ -333,6 +326,7 @@ void ViPER::DispatchCommand(int param, int val1, int val2, int val3, int val4, u
break; break;
} // 0x10014 } // 0x10014
case PARAM_HPFX_DIFFSURR_PROCESS_ENABLED: { case PARAM_HPFX_DIFFSURR_PROCESS_ENABLED: {
this->diffSurround->SetEnable(val1 != 0);
break; break;
} // 0x10015 } // 0x10015
case PARAM_HPFX_DIFFSURR_DELAYTIME: { case PARAM_HPFX_DIFFSURR_DELAYTIME: {
@ -340,9 +334,11 @@ void ViPER::DispatchCommand(int param, int val1, int val2, int val3, int val4, u
break; break;
} // 0x10016 } // 0x10016
case PARAM_HPFX_REVB_PROCESS_ENABLED: { case PARAM_HPFX_REVB_PROCESS_ENABLED: {
this->reverberation->SetEnable(val1 != 0);
break; break;
} // 0x10017 } // 0x10017
case PARAM_HPFX_REVB_ROOMSIZE: { case PARAM_HPFX_REVB_ROOMSIZE: {
this->reverberation->SetRoomSize((float) val1 / 100.0f);
break; break;
} // 0x10018 } // 0x10018
case PARAM_HPFX_REVB_WIDTH: { case PARAM_HPFX_REVB_WIDTH: {
@ -350,12 +346,15 @@ void ViPER::DispatchCommand(int param, int val1, int val2, int val3, int val4, u
break; break;
} // 0x10019 } // 0x10019
case PARAM_HPFX_REVB_DAMP: { case PARAM_HPFX_REVB_DAMP: {
this->reverberation->SetDamp((float) val1 / 100.0f);
break; break;
} // 0x1001A } // 0x1001A
case PARAM_HPFX_REVB_WET: { case PARAM_HPFX_REVB_WET: {
this->reverberation->SetWet((float) val1 / 100.0f);
break; break;
} // 0x1001B } // 0x1001B
case PARAM_HPFX_REVB_DRY: { case PARAM_HPFX_REVB_DRY: {
this->reverberation->SetDry((float) val1 / 100.0f);
break; break;
} // 0x1001C } // 0x1001C
case PARAM_HPFX_AGC_PROCESS_ENABLED: { case PARAM_HPFX_AGC_PROCESS_ENABLED: {
@ -395,11 +394,11 @@ void ViPER::DispatchCommand(int param, int val1, int val2, int val3, int val4, u
break; break;
} // 0x10025 } // 0x10025
case PARAM_HPFX_VIPERBASS_PROCESS_ENABLED: { case PARAM_HPFX_VIPERBASS_PROCESS_ENABLED: {
// this->viperBass->SetEnable(val1 != 0); this->viperBass->SetEnable(val1 != 0);
break; break;
} // 0x10026 } // 0x10026
case PARAM_HPFX_VIPERBASS_MODE: { case PARAM_HPFX_VIPERBASS_MODE: {
this->viperBass->SetProcessMode(static_cast<ViPERBass::ProcessMode>(val1)); this->viperBass->SetProcessMode((ViPERBass::ProcessMode) val1);
break; break;
} // 0x10027 } // 0x10027
case PARAM_HPFX_VIPERBASS_SPEAKER: { case PARAM_HPFX_VIPERBASS_SPEAKER: {
@ -411,11 +410,11 @@ void ViPER::DispatchCommand(int param, int val1, int val2, int val3, int val4, u
break; break;
} // 0x10029 } // 0x10029
case PARAM_HPFX_VIPERCLARITY_PROCESS_ENABLED: { case PARAM_HPFX_VIPERCLARITY_PROCESS_ENABLED: {
//this->viperClarity->SetEnable(val1 != 0); this->viperClarity->SetEnable(val1 != 0);
break; break;
} // 0x1002A } // 0x1002A
case PARAM_HPFX_VIPERCLARITY_MODE: { case PARAM_HPFX_VIPERCLARITY_MODE: {
this->viperClarity->SetProcessMode(static_cast<ViPERClarity::ClarityMode>(val1)); this->viperClarity->SetProcessMode((ViPERClarity::ClarityMode) val1);
break; break;
} // 0x1002B } // 0x1002B
case PARAM_HPFX_VIPERCLARITY_CLARITY: { case PARAM_HPFX_VIPERCLARITY_CLARITY: {
@ -441,11 +440,11 @@ void ViPER::DispatchCommand(int param, int val1, int val2, int val3, int val4, u
break; break;
} // 0x1002E } // 0x1002E
case PARAM_HPFX_TUBE_PROCESS_ENABLED: { case PARAM_HPFX_TUBE_PROCESS_ENABLED: {
// TODO: Enable this->tubeSimulator->SetEnable(val1 != 0);
break; break;
} // 0x1002F } // 0x1002F
case PARAM_HPFX_ANALOGX_PROCESS_ENABLED: { case PARAM_HPFX_ANALOGX_PROCESS_ENABLED: {
// TODO: Enable this->analogX->SetEnable(val1 != 0);
break; break;
} // 0x10030 } // 0x10030
case PARAM_HPFX_ANALOGX_MODE: { case PARAM_HPFX_ANALOGX_MODE: {
@ -453,17 +452,17 @@ void ViPER::DispatchCommand(int param, int val1, int val2, int val3, int val4, u
break; break;
} // 0x10031 } // 0x10031
case PARAM_HPFX_OUTPUT_VOLUME: { case PARAM_HPFX_OUTPUT_VOLUME: {
this->frameScale = (float) val1 / 100.0f;
break; break;
} // 0x10032 } // 0x10032
case PARAM_HPFX_OUTPUT_PAN: { case PARAM_HPFX_OUTPUT_PAN: {
float tmp = (float) val1 / 100.0f; float tmp = (float) val1 / 100.0f;
if (tmp < 0.0f) { if (tmp < 0.0f) {
this->left_pan = 1.0f; this->leftPan = 1.0f;
this->right_pan = 1.0f + tmp; this->rightPan = 1.0f + tmp;
} else { } else {
this->left_pan = 1.0f - tmp; this->leftPan = 1.0f - tmp;
this->right_pan = 1.0f; this->rightPan = 1.0f;
} }
break; break;
} // 0x10033 } // 0x10033
@ -472,77 +471,10 @@ void ViPER::DispatchCommand(int param, int val1, int val2, int val3, int val4, u
this->softwareLimiters[1]->SetGate((float) val1 / 100.0f); this->softwareLimiters[1]->SetGate((float) val1 / 100.0f);
break; break;
} // 0x10034 } // 0x10034
case PARAM_SPKFX_CONV_PROCESS_ENABLED: {
break;
} // 0x10035
case PARAM_SPKFX_CONV_UPDATEKERNEL: {
break;
} // 0x10036
case PARAM_SPKFX_CONV_PREPAREBUFFER: {
break;
} // 0x10037
case PARAM_SPKFX_CONV_SETBUFFER: {
break;
} // 0x10038
case PARAM_SPKFX_CONV_COMMITBUFFER: {
break;
} // 0x10039
case PARAM_SPKFX_CONV_CROSSCHANNEL: {
this->convolver->SetCrossChannel((float) val1 / 100.0f);
break;
} // 0x1003A
case PARAM_SPKFX_FIREQ_PROCESS_ENABLED: {
break;
} // 0x1003B
case PARAM_SPKFX_FIREQ_BANDLEVEL: {
break;
} // 0x1003C
case PARAM_SPKFX_REVB_PROCESS_ENABLED: {
this->reverberation->SetEnable(val1 != 0);
break;
} // 0x1003D
case PARAM_SPKFX_REVB_ROOMSIZE: {
this->reverberation->SetRoomSize((float) val1 / 100.0f);
break;
} // 0x1003E
case PARAM_SPKFX_REVB_WIDTH: {
break;
} // 0x1003F
case PARAM_SPKFX_REVB_DAMP: {
this->reverberation->SetDamp((float) val1 / 100.0f);
break;
} // 0x10040
case PARAM_SPKFX_REVB_WET: {
this->reverberation->SetWet((float) val1 / 100.0f);
break;
} // 0x10041
case PARAM_SPKFX_REVB_DRY: {
this->reverberation->SetDry((float) val1 / 100.0f);
break;
} // 0x10042
case PARAM_SPKFX_AGC_PROCESS_ENABLED: { case PARAM_SPKFX_AGC_PROCESS_ENABLED: {
this->speakerCorrection->SetEnable(val1 != 0); this->speakerCorrection->SetEnable(val1 != 0);
break; break;
} // 0x10043 } // 0x10043
case PARAM_SPKFX_AGC_RATIO: {
break;
} // 0x10044
case PARAM_SPKFX_AGC_VOLUME: {
this->playbackGain->SetVolume((float) val1 / 100.0f);
break;
} // 0x10045
case PARAM_SPKFX_AGC_MAXSCALER: {
this->playbackGain->SetMaxGainFactor((float) val1 / 100.0f);
break;
} // 0x10046
case PARAM_SPKFX_OUTPUT_VOLUME: {
this->frame_scale = (float) val1 / 100.0f;
break;
} // 0x10047
case PARAM_SPKFX_LIMITER_THRESHOLD: {
this->frame_scale = (float) val1 / 100.0f;
break;
} // 0x10048
case PARAM_HPFX_FETCOMP_PROCESS_ENABLED: { case PARAM_HPFX_FETCOMP_PROCESS_ENABLED: {
break; break;
} // 0x10049 } // 0x10049
@ -598,59 +530,6 @@ void ViPER::DispatchCommand(int param, int val1, int val2, int val3, int val4, u
this->fetCompressor->SetParameter(15, (float) val1 / 100.0f); this->fetCompressor->SetParameter(15, (float) val1 / 100.0f);
break; break;
} // 0x10059 } // 0x10059
case PARAM_SPKFX_FETCOMP_PROCESS_ENABLED: {
break;
} // 0x1005A
case PARAM_SPKFX_FETCOMP_THRESHOLD: {
break;
} // 0x1005B
case PARAM_SPKFX_FETCOMP_RATIO: {
break;
} // 0x1005C
case PARAM_SPKFX_FETCOMP_KNEEWIDTH: {
this->fetCompressor->SetParameter(2, (float) val1 / 100.0f);
break;
} // 0x1005D
case PARAM_SPKFX_FETCOMP_AUTOKNEE_ENABLED: {
break;
} // 0x1005E
case PARAM_SPKFX_FETCOMP_GAIN: {
break;
} // 0x1005F
case PARAM_SPKFX_FETCOMP_AUTOGAIN_ENABLED: {
break;
} // 0x10060
case PARAM_SPKFX_FETCOMP_ATTACK: {
break;
} // 0x10061
case PARAM_SPKFX_FETCOMP_AUTOATTACK_ENABLED: {
break;
} // 0x10062
case PARAM_SPKFX_FETCOMP_RELEASE: {
break;
} // 0x10063
case PARAM_SPKFX_FETCOMP_AUTORELEASE_ENABLED: {
break;
} // 0x10064
case PARAM_SPKFX_FETCOMP_META_KNEEMULTI: {
break;
} // 0x10065
case PARAM_SPKFX_FETCOMP_META_MAXATTACK: {
break;
} // 0x10066
case PARAM_SPKFX_FETCOMP_META_MAXRELEASE: {
break;
} // 0x10067
case PARAM_SPKFX_FETCOMP_META_CREST: {
break;
} // 0x10068
case PARAM_SPKFX_FETCOMP_META_ADAPT: {
break;
} // 0x10069
case PARAM_SPKFX_FETCOMP_META_NOCLIP_ENABLED: {
break;
} // 0x1006A
} }
} }

View File

@ -33,8 +33,8 @@ public:
void ResetAllEffects(); void ResetAllEffects();
//private: //private:
bool update_status; bool updateProcessTime;
uint64_t process_time_ms; uint64_t processTimeMs;
bool enabled; bool enabled;
uint32_t samplingRate; uint32_t samplingRate;
@ -60,7 +60,7 @@ public:
SpeakerCorrection *speakerCorrection; SpeakerCorrection *speakerCorrection;
SoftwareLimiter *softwareLimiters[2]; SoftwareLimiter *softwareLimiters[2];
float frame_scale; float frameScale;
float left_pan; float leftPan;
float right_pan; float rightPan;
}; };

View File

@ -18,11 +18,12 @@ static float ANALOGX_HARMONICS[10] = {
AnalogX::AnalogX() { AnalogX::AnalogX() {
this->samplingRate = DEFAULT_SAMPLERATE; this->samplingRate = DEFAULT_SAMPLERATE;
this->processingModel = 0; this->processingModel = 0;
this->enabled = false; this->enable = false;
Reset(); Reset();
} }
void AnalogX::Process(float *samples, uint32_t size) { void AnalogX::Process(float *samples, uint32_t size) {
if (this->enable) {
for (int i = 0; i < size * 2; i++) { for (int i = 0; i < size * 2; i++) {
float sample = samples[i]; float sample = samples[i];
int channel = i % 2; int channel = i % 2;
@ -40,6 +41,7 @@ void AnalogX::Process(float *samples, uint32_t size) {
this->freqRange += size; this->freqRange += size;
memset(samples, 0, size * 2 * sizeof(float)); memset(samples, 0, size * 2 * sizeof(float));
} }
}
} }
void AnalogX::Reset() { void AnalogX::Reset() {
@ -90,6 +92,15 @@ void AnalogX::Reset() {
this->freqRange = 0; this->freqRange = 0;
} }
void AnalogX::SetEnable(bool enable) {
if (this->enable != enable) {
if (!this->enable) {
Reset();
}
this->enable = enable;
}
}
void AnalogX::SetProcessingModel(int processingModel) { void AnalogX::SetProcessingModel(int processingModel) {
if (this->processingModel != processingModel) { if (this->processingModel != processingModel) {
this->processingModel = processingModel; this->processingModel = processingModel;

View File

@ -10,6 +10,7 @@ public:
void Process(float *samples, uint32_t size); void Process(float *samples, uint32_t size);
void Reset(); void Reset();
void SetEnable(bool enable);
void SetProcessingModel(int processingModel); void SetProcessingModel(int processingModel);
void SetSamplingRate(uint32_t samplingRate); void SetSamplingRate(uint32_t samplingRate);
@ -23,7 +24,7 @@ private:
uint32_t freqRange; uint32_t freqRange;
int processingModel; int processingModel;
uint32_t samplingRate; uint32_t samplingRate;
bool enabled; bool enable;
}; };

View File

@ -8,7 +8,7 @@ IIRFilter::IIRFilter(uint32_t bands) {
this->samplingRate = DEFAULT_SAMPLERATE; this->samplingRate = DEFAULT_SAMPLERATE;
if (bands == 10 || bands == 15 || bands == 25 || bands == 31) { if (bands == 10 || bands == 15 || bands == 25 || bands == 31) {
this->bands = bands; this->bands = bands;
this->minPhaseIirCoeffs.UpdateCoeffs(bands, this->samplingRate); this->minPhaseIirCoeffs.UpdateCoeffs(this->bands, this->samplingRate);
} else { } else {
this->bands = 0; this->bands = 0;
} }
@ -17,7 +17,7 @@ IIRFilter::IIRFilter(uint32_t bands) {
bandLevelWithQ = 0.636; bandLevelWithQ = 0.636;
} }
this->Reset(); Reset();
} }
void IIRFilter::Process(float *samples, uint32_t size) { void IIRFilter::Process(float *samples, uint32_t size) {
@ -54,14 +54,16 @@ void IIRFilter::Process(float *samples, uint32_t size) {
} }
void IIRFilter::Reset() { void IIRFilter::Reset() {
memset(this->buf,0,0x7c0); memset(this->buf,0,sizeof(buf)); // size should be 0x7c0
this->unknown3 = 1; this->unknown3 = 1;
this->unknown2 = 2; this->unknown2 = 2;
this->unknown4 = 0; this->unknown4 = 0;
} }
void IIRFilter::SetBandLevel(uint32_t band, float level) { void IIRFilter::SetBandLevel(uint32_t band, float level) {
this->bandLevelsWithQ[band] = (float) (pow(10.0, level / 20.0) * 0.636); if (band > 30) return;
double bandLevel = pow(10.0, level / 20.0);
this->bandLevelsWithQ[band] = (float) (bandLevel * 0.636);
} }
void IIRFilter::SetEnable(bool enable) { void IIRFilter::SetEnable(bool enable) {

View File

@ -8,6 +8,7 @@ SpeakerCorrection::SpeakerCorrection() {
} }
void SpeakerCorrection::Process(float *samples, uint32_t size) { void SpeakerCorrection::Process(float *samples, uint32_t size) {
if (this->enabled) {
for (int i = 0; i < size * 2; i++) { for (int i = 0; i < size * 2; i++) {
float sample = samples[i]; float sample = samples[i];
int index = i % 2; int index = i % 2;
@ -16,6 +17,7 @@ void SpeakerCorrection::Process(float *samples, uint32_t size) {
float tmp = sample / 2.f; float tmp = sample / 2.f;
samples[i] = tmp + this->bandpass[index].ProcessSample(tmp); samples[i] = tmp + this->bandpass[index].ProcessSample(tmp);
} }
}
} }
void SpeakerCorrection::Reset() { void SpeakerCorrection::Reset() {

View File

@ -27,6 +27,7 @@ SpectrumExtend::~SpectrumExtend() {
} }
void SpectrumExtend::Process(float *samples, uint32_t size) { void SpectrumExtend::Process(float *samples, uint32_t size) {
if (this->enabled) {
for (int i = 0; i < size * 2; i++) { for (int i = 0; i < size * 2; i++) {
float sample = samples[i]; float sample = samples[i];
int index = i % 2; int index = i % 2;
@ -35,6 +36,7 @@ void SpectrumExtend::Process(float *samples, uint32_t size) {
tmp = this->lowpass[index].ProcessSample(tmp * this->exciter); tmp = this->lowpass[index].ProcessSample(tmp * this->exciter);
samples[i] = samples[i] + tmp; samples[i] = samples[i] + tmp;
} }
}
} }
void SpectrumExtend::Reset() { void SpectrumExtend::Reset() {

View File

@ -3,17 +3,26 @@
TubeSimulator::TubeSimulator() { TubeSimulator::TubeSimulator() {
this->acc[0] = 0.f; this->acc[0] = 0.f;
this->acc[1] = 0.f; this->acc[1] = 0.f;
this->enabled = false; this->enable = false;
} }
void TubeSimulator::Reset() { void TubeSimulator::Reset() {
this->acc[0] = 0.f; this->acc[0] = 0.f;
this->acc[1] = 0.f; this->acc[1] = 0.f;
this->enabled = false; this->enable = false;
}
void TubeSimulator::SetEnable(bool enable) {
if (this->enable != enable) {
if (!this->enable) {
Reset();
}
this->enable = enable;
}
} }
void TubeSimulator::TubeProcess(float *buffer, uint32_t size) { void TubeSimulator::TubeProcess(float *buffer, uint32_t size) {
if (this->enabled) { if (this->enable) {
for (int x = 0; x < size; x++) { for (int x = 0; x < size; x++) {
this->acc[0] = (this->acc[0] + buffer[2 * x]) / 2.f; this->acc[0] = (this->acc[0] + buffer[2 * x]) / 2.f;
this->acc[1] = (this->acc[1] + buffer[2 * x + 1]) / 2.f; this->acc[1] = (this->acc[1] + buffer[2 * x + 1]) / 2.f;

View File

@ -8,9 +8,11 @@ public:
~TubeSimulator(); ~TubeSimulator();
void Reset(); void Reset();
void SetEnable(bool enable);
void TubeProcess(float *buffer, uint32_t size); void TubeProcess(float *buffer, uint32_t size);
private:
float acc[2]; float acc[2];
bool enabled; bool enable;
}; };

View File

@ -2,9 +2,10 @@
#include "../constants.h" #include "../constants.h"
ViPERBass::ViPERBass() { ViPERBass::ViPERBass() {
this->enable = false;
this->samplingRate = DEFAULT_SAMPLERATE; this->samplingRate = DEFAULT_SAMPLERATE;
this->speaker = 60; this->speaker = 60;
this->invertedSamplingRate = 1.0 / DEFAULT_SAMPLERATE; this->samplingRatePeriod = 1.0 / DEFAULT_SAMPLERATE;
this->antiPop = 0.0; this->antiPop = 0.0;
this->processMode = ProcessMode::NATURAL_BASS; this->processMode = ProcessMode::NATURAL_BASS;
this->bassFactor = 0.0; this->bassFactor = 0.0;
@ -27,6 +28,10 @@ ViPERBass::~ViPERBass() {
} }
void ViPERBass::Process(float *samples, uint32_t size) { void ViPERBass::Process(float *samples, uint32_t size) {
if (!this->enable) {
return;
}
if (size == 0) { if (size == 0) {
return; return;
} }
@ -36,7 +41,7 @@ void ViPERBass::Process(float *samples, uint32_t size) {
samples[i] *= this->antiPop; samples[i] *= this->antiPop;
samples[i + 1] *= this->antiPop; samples[i + 1] *= this->antiPop;
float x = this->antiPop + this->invertedSamplingRate; float x = this->antiPop + this->samplingRatePeriod;
if (x > 1.0) { if (x > 1.0) {
x = 1.0; x = 1.0;
} }
@ -48,14 +53,14 @@ void ViPERBass::Process(float *samples, uint32_t size) {
case ProcessMode::NATURAL_BASS: { case ProcessMode::NATURAL_BASS: {
for (uint32_t i = 0; i < size * 2; i += 2) { for (uint32_t i = 0; i < size * 2; i += 2) {
double sample = ((double) samples[i] + (double) samples[i + 1]) / 2.0; double sample = ((double) samples[i] + (double) samples[i + 1]) / 2.0;
auto x = (float) this->biquad->ProcessSample(sample); float x = (float) this->biquad->ProcessSample(sample) * this->bassFactor;
samples[i] += x; samples[i] += x;
samples[i + 1] += x; samples[i + 1] += x;
} }
break; break;
} }
case ProcessMode::PURE_BASS_PLUS: { case ProcessMode::PURE_BASS_PLUS: {
if (this->waveBuffer->PushSamples(samples, size) != 0) { if (this->waveBuffer->PushSamples(samples, size)) {
float *buffer = this->waveBuffer->GetBuffer(); float *buffer = this->waveBuffer->GetBuffer();
uint32_t bufferOffset = this->waveBuffer->GetBufferOffset(); uint32_t bufferOffset = this->waveBuffer->GetBufferOffset();
@ -90,8 +95,8 @@ void ViPERBass::Reset() {
this->waveBuffer->PushZeros(this->polyphase->GetLatency()); this->waveBuffer->PushZeros(this->polyphase->GetLatency());
this->subwoofer->SetBassGain(this->samplingRate, this->bassFactor * 2.5f); this->subwoofer->SetBassGain(this->samplingRate, this->bassFactor * 2.5f);
this->biquad->SetLowPassParameter((float) this->speaker, this->samplingRate, 0.53); this->biquad->SetLowPassParameter((float) this->speaker, this->samplingRate, 0.53);
this->samplingRatePeriod = 1.0f / (float) this->samplingRate;
this->antiPop = 0.0f; this->antiPop = 0.0f;
this->invertedSamplingRate = 1.0f / (float) this->samplingRate;
} }
void ViPERBass::SetBassFactor(float bassFactor) { void ViPERBass::SetBassFactor(float bassFactor) {
@ -101,6 +106,15 @@ void ViPERBass::SetBassFactor(float bassFactor) {
} }
} }
void ViPERBass::SetEnable(bool enable) {
if (this->enable != enable) {
if (!this->enable) {
Reset();
}
this->enable = enable;
}
}
void ViPERBass::SetProcessMode(ProcessMode processMode) { void ViPERBass::SetProcessMode(ProcessMode processMode) {
if (this->processMode != processMode) { if (this->processMode != processMode) {
this->processMode = processMode; this->processMode = processMode;
@ -111,10 +125,10 @@ void ViPERBass::SetProcessMode(ProcessMode processMode) {
void ViPERBass::SetSamplingRate(uint32_t samplingRate) { void ViPERBass::SetSamplingRate(uint32_t samplingRate) {
if (this->samplingRate != samplingRate) { if (this->samplingRate != samplingRate) {
this->samplingRate = samplingRate; this->samplingRate = samplingRate;
this->invertedSamplingRate = 1.0f / (float) samplingRate; this->samplingRatePeriod = 1.0f / (float) samplingRate;
this->polyphase->SetSamplingRate(samplingRate); this->polyphase->SetSamplingRate(this->samplingRate);
this->biquad->SetLowPassParameter((float) this->speaker, samplingRate, 0.53); this->biquad->SetLowPassParameter((float) this->speaker, this->samplingRate, 0.53);
this->subwoofer->SetBassGain(samplingRate, this->bassFactor * 2.5f); this->subwoofer->SetBassGain(this->samplingRate, this->bassFactor * 2.5f);
} }
} }

View File

@ -20,6 +20,7 @@ public:
void Process(float *samples, uint32_t size); void Process(float *samples, uint32_t size);
void Reset(); void Reset();
void SetBassFactor(float bassFactor); void SetBassFactor(float bassFactor);
void SetEnable(bool enable);
void SetProcessMode(ProcessMode processMode); void SetProcessMode(ProcessMode processMode);
void SetSamplingRate(uint32_t samplingRate); void SetSamplingRate(uint32_t samplingRate);
void SetSpeaker(uint32_t speaker); void SetSpeaker(uint32_t speaker);
@ -29,9 +30,10 @@ private:
Biquad *biquad; Biquad *biquad;
Subwoofer *subwoofer; Subwoofer *subwoofer;
WaveBuffer *waveBuffer; WaveBuffer *waveBuffer;
bool enable;
ProcessMode processMode; ProcessMode processMode;
uint32_t samplingRate; uint32_t samplingRate;
float invertedSamplingRate; float samplingRatePeriod;
float antiPop; float antiPop;
uint32_t speaker; uint32_t speaker;
float bassFactor; float bassFactor;

View File

@ -8,13 +8,18 @@ ViPERClarity::ViPERClarity() {
highShelf.SetSamplingRate(DEFAULT_SAMPLERATE); highShelf.SetSamplingRate(DEFAULT_SAMPLERATE);
} }
this->enable = false;
this->processMode = ClarityMode::NATURAL; this->processMode = ClarityMode::NATURAL;
this->samplingRate = DEFAULT_SAMPLERATE; this->samplingRate = DEFAULT_SAMPLERATE;
this->clarityGainPercent = 0.0; this->clarityGainPercent = 0.0;
this->Reset(); Reset();
} }
void ViPERClarity::Process(float *samples, uint32_t size) { void ViPERClarity::Process(float *samples, uint32_t size) {
if (!this->enable) {
return;
}
switch (this->processMode) { switch (this->processMode) {
case ClarityMode::NATURAL: { case ClarityMode::NATURAL: {
this->noiseSharpening.Process(samples, size); this->noiseSharpening.Process(samples, size);
@ -50,7 +55,7 @@ void ViPERClarity::SetClarity(float gainPercent) {
if (this->processMode != ClarityMode::OZONE) { if (this->processMode != ClarityMode::OZONE) {
this->SetClarityToFilter(); this->SetClarityToFilter();
} else { } else {
this->Reset(); Reset();
} }
} }
@ -61,16 +66,25 @@ void ViPERClarity::SetClarityToFilter() {
this->hifi.SetClarity(this->clarityGainPercent + 1.0f); this->hifi.SetClarity(this->clarityGainPercent + 1.0f);
} }
void ViPERClarity::SetEnable(bool enable) {
if (this->enable != enable) {
if (!this->enable) {
Reset();
}
this->enable = enable;
}
}
void ViPERClarity::SetProcessMode(ClarityMode processMode) { void ViPERClarity::SetProcessMode(ClarityMode processMode) {
if (this->processMode != processMode) { if (this->processMode != processMode) {
this->processMode = processMode; this->processMode = processMode;
this->Reset(); Reset();
} }
} }
void ViPERClarity::SetSamplingRate(uint32_t samplingRate) { void ViPERClarity::SetSamplingRate(uint32_t samplingRate) {
if (this->samplingRate != samplingRate) { if (this->samplingRate != samplingRate) {
this->samplingRate = samplingRate; this->samplingRate = samplingRate;
this->Reset(); Reset();
} }
} }

View File

@ -19,6 +19,7 @@ public:
void Reset(); void Reset();
void SetClarity(float gainPercent); void SetClarity(float gainPercent);
void SetClarityToFilter(); void SetClarityToFilter();
void SetEnable(bool enable);
void SetProcessMode(ClarityMode processMode); void SetProcessMode(ClarityMode processMode);
void SetSamplingRate(uint32_t samplingRate); void SetSamplingRate(uint32_t samplingRate);
@ -26,6 +27,7 @@ private:
NoiseSharpening noiseSharpening; NoiseSharpening noiseSharpening;
HighShelf highShelf[2]; HighShelf highShelf[2];
HiFi hifi; HiFi hifi;
bool enable;
ClarityMode processMode; ClarityMode processMode;
uint32_t samplingRate; uint32_t samplingRate;
float clarityGainPercent; float clarityGainPercent;

View File

@ -38,7 +38,7 @@ uint32_t AdaptiveBuffer::GetChannels() const {
void AdaptiveBuffer::PanFrames(float left, float right) { void AdaptiveBuffer::PanFrames(float left, float right) {
if (this->buffer != nullptr && this->channels == 2) { if (this->buffer != nullptr && this->channels == 2) {
for (int i = 0; i < this->offset * this->channels; i++) { for (uint32_t i = 0; i < this->offset * this->channels; i++) {
if (i % 2 == 0) { if (i % 2 == 0) {
this->buffer[i] = this->buffer[i] * left; this->buffer[i] = this->buffer[i] * left;
} else { } else {
@ -57,7 +57,7 @@ int AdaptiveBuffer::PopFrames(float *frames, uint32_t length) {
memcpy(frames, this->buffer, length * this->channels * sizeof(*frames)); memcpy(frames, this->buffer, length * this->channels * sizeof(*frames));
this->offset = this->offset - length; this->offset = this->offset - length;
if (this->offset != 0) { if (this->offset != 0) {
memmove(this->buffer, &this->buffer[length * this->channels], this->offset * this->channels * sizeof(float)); memmove(this->buffer, this->buffer + (length * this->channels), this->offset * this->channels * sizeof(float));
} }
} }
@ -78,7 +78,7 @@ int AdaptiveBuffer::PushFrames(const float *frames, uint32_t length) {
this->length = this->offset + length; this->length = this->offset + length;
} }
memcpy(&this->buffer[this->offset * this->channels], frames, length * this->channels * sizeof(float)); memcpy(this->buffer + (this->offset * this->channels), frames, length * this->channels * sizeof(float));
this->offset = this->offset + length; this->offset = this->offset + length;
} }
@ -98,7 +98,7 @@ int AdaptiveBuffer::PushZero(uint32_t length) {
this->length = this->offset + length; this->length = this->offset + length;
} }
memset(&this->buffer[this->offset * this->channels], 0, length * this->channels * sizeof(float)); memset(this->buffer + (this->offset * this->channels), 0, length * this->channels * sizeof(float));
this->offset = this->offset + length; this->offset = this->offset + length;
return 1; return 1;

View File

@ -1,53 +1,64 @@
#include "Biquad.h" #include "Biquad.h"
#include <cmath> #include <cmath>
// Some variable names RE'd with help from https://github.com/wooters/miniDSP/blob/master/biquad.c
Biquad::Biquad() { Biquad::Biquad() {
Reset(); Reset();
SetCoeffs(1.0, 0.0, 0.0, 1.0, 0.0, 0.0); SetCoeffs(1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
} }
double Biquad::ProcessSample(double sample) { double Biquad::ProcessSample(double sample) {
double out = sample * this->b0 + this->x_1 * this->b1 + this->x_2 * this->b2 + this->y_1 * this->a1 + double out =
this->y_2 * this->a2; sample * this->b0 +
this->y_2 = this->y_1; this->x1 * this->b1 +
this->y_1 = out; this->x2 * this->b2 +
this->x_2 = this->x_1; this->y1 * this->a1 +
this->x_1 = sample; this->y2 * this->a2;
this->x2 = this->x1;
this->x1 = sample;
this->y2 = this->y1;
this->y1 = out;
return out; return out;
} }
void Biquad::Reset() { void Biquad::Reset() {
this->a1 = 0; this->a1 = 0.0;
this->a2 = 0; this->a2 = 0.0;
this->b0 = 0; this->b0 = 0.0;
this->b1 = 0; this->b1 = 0.0;
this->b2 = 0; this->b2 = 0.0;
this->x_1 = 0; this->x1 = 0.0;
this->x_2 = 0; this->x2 = 0.0;
this->y_1 = 0; this->y1 = 0.0;
this->y_2 = 0; this->y2 = 0.0;
} }
void Biquad::SetBandPassParameter(float frequency, uint32_t samplingRate, float qFactor) { void Biquad::SetBandPassParameter(float frequency, uint32_t samplingRate, float qFactor) {
double x = (2.0 * M_PI * (double) frequency) / (double) samplingRate; double omega = (2.0 * M_PI * (double) frequency) / (double) samplingRate;
double sinX = sin(x); double sinOmega = sin(omega);
double cosX = cos(x); double cosOmega = cos(omega);
double y = sinX / ((double) qFactor * 2.0);
double a0 = 1.0 + y; double alpha = sinOmega / (2.0 * (double) qFactor);
double a1 = -cosX * 2.0;
double a2 = 1.0 - y; double a0 = 1.0 + alpha;
double b0 = sinX / 2.0; double a1 = -2.0 * cosOmega;
double a2 = 1.0 - alpha;
double b0 = sinOmega / 2.0; // Reference biquad implementation would use alpha here
double b1 = 0.0; double b1 = 0.0;
double b2 = -sinX / 2.0; double b2 = -sinOmega / 2.0; // Reference biquad implementation would use -alpha here
this->SetCoeffs(a0, a1, a2, b0, b1, b2);
SetCoeffs(a0, a1, a2, b0, b1, b2);
} }
void Biquad::SetCoeffs(double a0, double a1, double a2, double b0, double b1, double b2) { void Biquad::SetCoeffs(double a0, double a1, double a2, double b0, double b1, double b2) {
this->x_2 = 0; this->x2 = 0.0;
this->x_1 = 0; this->x1 = 0.0;
this->y_2 = 0; this->y2 = 0.0;
this->y_1 = 0; this->y1 = 0.0;
this->a1 = -a1 / a0; this->a1 = -a1 / a0;
this->a2 = -a2 / a0; this->a2 = -a2 / a0;
this->b0 = b0 / a0; this->b0 = b0 / a0;
@ -55,44 +66,47 @@ void Biquad::SetCoeffs(double a0, double a1, double a2, double b0, double b1, do
this->b2 = b2 / a0; this->b2 = b2 / a0;
} }
// TODO: Check
void void
Biquad::SetHighPassParameter(float frequency, uint32_t samplingRate, double param_4, float qFactor, double param_6) { Biquad::SetHighPassParameter(float frequency, uint32_t samplingRate, double dbGain, float qFactor, double param_6) {
double x = (2.0 * M_PI * (double) frequency) / (double) samplingRate; double omega = (2.0 * M_PI * (double) frequency) / (double) samplingRate;
double sinX = sin(x); double sinX = sin(omega);
double cosX = cos(x); double cosX = cos(omega);
double y = pow(10.0, param_4 / 40.0); double A = pow(10.0, dbGain / 40.0);
double sqrtY = sqrt(y); double sqrtY = sqrt(A);
double z = sinX / 2.0 * sqrt((1.0 / y + y) * (1.0 / (double) qFactor - 1.0) + 2.0); double z = sinX / 2.0 * sqrt((1.0 / A + A) * (1.0 / (double) qFactor - 1.0) + 2.0);
double a = (y - 1.0) * cosX; double a = (A - 1.0) * cosX;
double b = (y + 1.0) + a; double b = (A + 1.0) + a;
double c = (y + 1.0) * cosX; double c = (A + 1.0) * cosX;
double d = (y + 1.0) - a; double d = (A + 1.0) - a;
double e = pow(10.0, param_6 / 20.0); double e = pow(10.0, param_6 / 20.0);
double f = (y - 1.0) - c; double f = (A - 1.0) - c;
double a0 = d + (sqrtY * 2.0) * z; double a0 = d + (sqrtY * 2.0) * z;
double a1 = f * 2.0; double a1 = f * 2.0;
double a2 = d - (sqrtY * 2.0) * z; double a2 = d - (sqrtY * 2.0) * z;
double b0 = (b + (sqrtY * 2.0) * z) * y * e; double b0 = (b + (sqrtY * 2.0) * z) * A * e;
double b1 = y * -2.0 * ((y - 1.0) + c) * e; double b1 = A * -2.0 * ((A - 1.0) + c) * e;
double b2 = (b - (sqrtY * 2.0) * z) * y * e; double b2 = (b - (sqrtY * 2.0) * z) * A * e;
this->SetCoeffs(a0, a1, a2, b0, b1, b2);
SetCoeffs(a0, a1, a2, b0, b1, b2);
} }
void Biquad::SetLowPassParameter(float frequency, uint32_t samplingRate, float qFactor) { void Biquad::SetLowPassParameter(float frequency, uint32_t samplingRate, float qFactor) {
double x = (2.0 * M_PI * (double) frequency) / (double) samplingRate; double omega = (2.0 * M_PI * (double) frequency) / (double) samplingRate;
double sinX = sin(x); double sinOmega = sin(omega);
double y = sinX / ((double) qFactor * 2.0); double cosOmega = cos(omega);
double cosX = cos(x);
double z = 1.0 - cosX;
double a0 = y + 1.0; double alpha = sinOmega / (2.0 * (double) qFactor);
double a1 = -cosX * 2.0;
double a2 = 1.0 - y; double a0 = 1.0 + alpha;
double b0 = z / 2.0; double a1 = -2.0 * cosOmega;
double b1 = z; double a2 = 1.0 - alpha;
double b2 = z / 2.0; double b0 = (1.0 - cosOmega) / 2.0;
this->SetCoeffs(a0, a1, a2, b0, b1, b2); double b1 = 1.0 - cosOmega;
double b2 = (1.0 - cosOmega) / 2.0;
SetCoeffs(a0, a1, a2, b0, b1, b2);
} }

View File

@ -10,14 +10,14 @@ public:
void Reset(); void Reset();
void SetBandPassParameter(float frequency, uint32_t samplingRate, float qFactor); void SetBandPassParameter(float frequency, uint32_t samplingRate, float qFactor);
void SetCoeffs(double a0, double a1, double a2, double b0, double b1, double b2); void SetCoeffs(double a0, double a1, double a2, double b0, double b1, double b2);
void SetHighPassParameter(float frequency, uint32_t samplingRate, double param_4, float qFactor, double param_6); void SetHighPassParameter(float frequency, uint32_t samplingRate, double dbGain, float qFactor, double param_6);
void SetLowPassParameter(float frequency, uint32_t samplingRate, float qFactor); void SetLowPassParameter(float frequency, uint32_t samplingRate, float qFactor);
private: private:
double x_1; double x1;
double x_2; double x2;
double y_1; double y1;
double y_2; double y2;
double a1; double a1;
double a2; double a2;
double b0; double b0;

View File

@ -28,10 +28,10 @@ void FIR::FilterSamplesInterleaved(float *samples, uint32_t size, uint32_t chann
} }
if (this->blockLength > size) { if (this->blockLength > size) {
memset(&this->block[size], 0, (this->blockLength - size) * sizeof(float)); memset(this->block + size, 0, (this->blockLength - size) * sizeof(float));
} }
memcpy(&this->offsetBlock[this->coeffsSize - 1], this->block, this->blockLength * sizeof(float)); memcpy(this->offsetBlock + this->coeffsSize - 1, this->block, this->blockLength * sizeof(float));
for (uint32_t i = 0; i < this->blockLength; i++) { for (uint32_t i = 0; i < this->blockLength; i++) {
float sample = 0.0f; float sample = 0.0f;
@ -46,7 +46,7 @@ void FIR::FilterSamplesInterleaved(float *samples, uint32_t size, uint32_t chann
} }
if (this->coeffsSize > 1) { if (this->coeffsSize > 1) {
memcpy(&this->offsetBlock[this->coeffsSize - 2], &this->block[this->blockLength - 1], this->blockLength - (this->coeffsSize - 1) * sizeof(float)); memcpy(this->offsetBlock + this->coeffsSize - 2, this->block + this->blockLength - 1, this->blockLength - (this->coeffsSize - 1) * sizeof(float));
} }
} }

View File

@ -131,7 +131,7 @@ float MinPhaseIIRCoeffs::GetIndexFrequency(uint32_t index) {
} }
int MinPhaseIIRCoeffs::SolveRoot(double param_2, double param_3, double param_4, double *param_5) { int MinPhaseIIRCoeffs::SolveRoot(double param_2, double param_3, double param_4, double *param_5) {
double x = (param_4 - pow(param_3, 2.0) / (param_2 * 4.0)) / param_2; double x = (param_4 - pow(param_3, 2) / (param_2 * 4.0)) / param_2;
double y = param_3 / (param_2 * 2.0); double y = param_3 / (param_2 * 2.0);
if (x >= 0.0) { if (x >= 0.0) {
@ -151,7 +151,7 @@ int MinPhaseIIRCoeffs::SolveRoot(double param_2, double param_3, double param_4,
} }
int MinPhaseIIRCoeffs::UpdateCoeffs(uint32_t bands, uint32_t samplingRate) { int MinPhaseIIRCoeffs::UpdateCoeffs(uint32_t bands, uint32_t samplingRate) {
if ((bands != 10 && bands != 15 && bands != 25 && bands != 31) || samplingRate != 44100) { if ((bands != 10 && bands != 15 && bands != 25 && bands != 31) || samplingRate < 44100) {
return 0; return 0;
} }
@ -159,7 +159,7 @@ int MinPhaseIIRCoeffs::UpdateCoeffs(uint32_t bands, uint32_t samplingRate) {
this->samplingRate = samplingRate; this->samplingRate = samplingRate;
delete[] this->coeffs; delete[] this->coeffs;
this->coeffs = new float[bands * 4](); this->coeffs = new float[bands * 4](); // TODO: Check this array size
const float *coeffsArray; const float *coeffsArray;
double tmp; double tmp;
@ -186,7 +186,8 @@ int MinPhaseIIRCoeffs::UpdateCoeffs(uint32_t bands, uint32_t samplingRate) {
for (uint32_t i = 0; i < bands; i++) { for (uint32_t i = 0; i < bands; i++) {
double ret1; double ret1;
double ret2; double ret2;
this->Find_F1_F2(coeffsArray[i], tmp, &ret1, &ret2);
Find_F1_F2(coeffsArray[i], tmp, &ret1, &ret2);
double x = (2.0 * M_PI * (double) coeffsArray[i]) / (double) this->samplingRate; double x = (2.0 * M_PI * (double) coeffsArray[i]) / (double) this->samplingRate;
double y = (2.0 * M_PI * ret2) / (double) this->samplingRate; double y = (2.0 * M_PI * ret2) / (double) this->samplingRate;
@ -199,10 +200,17 @@ int MinPhaseIIRCoeffs::UpdateCoeffs(uint32_t bands, uint32_t samplingRate) {
double b = pow(cosX, 2.0) / 2.0; double b = pow(cosX, 2.0) / 2.0;
double c = pow(sinY, 2.0); double c = pow(sinY, 2.0);
if (this->SolveRoot(((b - a) + 0.5) - c, c + (((b + pow(cosY, 2.0)) - a) - 0.5), ((pow(cosX, 2.0) / 8.0 - cosX * cosY / 4.0) + 0.125) - c / 4.0, &ret1) == 0) { // ((b - a) + 0.5) - c
double d = ((b - a) + 0.5) - c;
// c + (((b + pow(cosY, 2.0)) - a) - 0.5)
double e = c + (((b + pow(cosY, 2.0)) - a) - 0.5);
// ((pow(cosX, 2.0) / 8.0 - cosX * cosY / 4.0) + 0.125) - c / 4.0
double f = ((pow(cosX, 2.0) * 0.125 - cosX * cosY * 0.25) + 0.125) - c * 0.25;
if (SolveRoot(d, e, f, &ret1) == 0) {
this->coeffs[4 * i] = (float) (ret1 * 2.0); this->coeffs[4 * i] = (float) (ret1 * 2.0);
this->coeffs[4 * i + 1] = (float) (0.5 - ret1); this->coeffs[4 * i + 1] = (float) (((0.5 - ret1) * 0.5) * 2.0);
this->coeffs[4 * i + 2] = (float) ((ret1 + 0.5) * cosX); this->coeffs[4 * i + 2] = (float) (((ret1 + 0.5) * cosX) * 2.0);
} }
} }

View File

@ -144,7 +144,7 @@ Polyphase::Polyphase(int unknown1) {
if (unknown1 == 2) { if (unknown1 == 2) {
this->fir1->LoadCoefficients(POLYPHASE_COEFFICIENTS_2, sizeof(POLYPHASE_COEFFICIENTS_2) / sizeof(float), 1008); this->fir1->LoadCoefficients(POLYPHASE_COEFFICIENTS_2, sizeof(POLYPHASE_COEFFICIENTS_2) / sizeof(float), 1008);
this->fir2->LoadCoefficients(POLYPHASE_COEFFICIENTS_2, sizeof(POLYPHASE_COEFFICIENTS_2) / sizeof(float), 1008); this->fir2->LoadCoefficients(POLYPHASE_COEFFICIENTS_2, sizeof(POLYPHASE_COEFFICIENTS_2) / sizeof(float), 1008);
} else if (unknown1 > 2) { } else { // if (unknown1 < 2)
this->fir1->LoadCoefficients(POLYPHASE_COEFFICIENTS_OTHER, sizeof(POLYPHASE_COEFFICIENTS_OTHER) / sizeof(float), 1008); this->fir1->LoadCoefficients(POLYPHASE_COEFFICIENTS_OTHER, sizeof(POLYPHASE_COEFFICIENTS_OTHER) / sizeof(float), 1008);
this->fir2->LoadCoefficients(POLYPHASE_COEFFICIENTS_OTHER, sizeof(POLYPHASE_COEFFICIENTS_OTHER) / sizeof(float), 1008); this->fir2->LoadCoefficients(POLYPHASE_COEFFICIENTS_OTHER, sizeof(POLYPHASE_COEFFICIENTS_OTHER) / sizeof(float), 1008);
} }
@ -163,21 +163,23 @@ uint32_t Polyphase::GetLatency() {
} }
uint32_t Polyphase::Process(float *samples, uint32_t size) { uint32_t Polyphase::Process(float *samples, uint32_t size) {
if (this->waveBuffer1->PushSamples(samples, size) != 0) { if (this->waveBuffer1->PushSamples(samples, size)) {
uint32_t bufferOffset = this->waveBuffer1->GetBufferOffset(); while (this->waveBuffer1->GetBufferOffset() >= 1008) {
while (bufferOffset >= 1008) {
if (this->waveBuffer1->PopSamples(this->buffer, 1008, false) == 1008) { if (this->waveBuffer1->PopSamples(this->buffer, 1008, false) == 1008) {
this->fir1->FilterSamplesInterleaved(this->buffer, 1008, 2); this->fir1->FilterSamplesInterleaved(this->buffer, 1008, 2);
this->fir2->FilterSamplesInterleaved(this->buffer + 1, 1008, 2); this->fir2->FilterSamplesInterleaved(this->buffer + 1, 1008, 2);
this->waveBuffer2->PushSamples(this->buffer, 1008); this->waveBuffer2->PushSamples(this->buffer, 1008);
} }
bufferOffset = this->waveBuffer1->GetBufferOffset();
} }
if (this->waveBuffer2->GetBufferOffset() >= size) {
if (this->waveBuffer2->GetBufferOffset() < size) {
return 0;
}
this->waveBuffer2->PopSamples(samples, size, true); this->waveBuffer2->PopSamples(samples, size, true);
} }
}
return 0; return size;
} }
void Polyphase::Reset() { void Polyphase::Reset() {