This commit is contained in:
Iscle 2022-09-27 03:48:49 +02:00
parent 96563a651d
commit 6d7fd4d9e6
15 changed files with 331 additions and 378 deletions

View File

@ -18,7 +18,6 @@ include_directories(src/include)
set(FILES set(FILES
# Main # Main
src/cpp/viper/Effect.cpp
src/cpp/viper/ViPER.cpp src/cpp/viper/ViPER.cpp
src/cpp/ViPER4Android.cpp src/cpp/ViPER4Android.cpp

View File

@ -1,7 +1,9 @@
#include <cstring> #include <cstring>
#include <cerrno> #include <cerrno>
#include <ctime>
#include "viper/ViPER.h" #include "viper/ViPER.h"
#include "essential.h"
#include "log.h" #include "log.h"
#include "viper/constants.h" #include "viper/constants.h"
@ -22,35 +24,217 @@ static effect_descriptor_t viper_descriptor = {
extern "C" { 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;
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 = (ViperContext *) self; auto pContext = reinterpret_cast<ViperContext *>(self);
if (pContext == nullptr || pContext->viper == nullptr || inBuffer == nullptr || outBuffer == nullptr) { if (pContext == nullptr ||
VIPER_LOGE("Viper_IProcess: pContext, pContext->viper, inBuffer or outBuffer is null!"); inBuffer == nullptr || outBuffer == nullptr ||
inBuffer->raw == nullptr || outBuffer->raw == nullptr ||
inBuffer->frameCount != outBuffer->frameCount ||
inBuffer->frameCount == 0) {
return -EINVAL; return -EINVAL;
} }
return pContext->viper->process(inBuffer, outBuffer); float *inBufferPtr = inBuffer->f32;
float *outBufferPtr = outBuffer->f32;
if (inBufferPtr != outBufferPtr) {
memcpy(outBufferPtr, inBufferPtr, outBuffer->frameCount * sizeof(float) * 2);
}
/*return */pContext->viper->processBuffer(outBufferPtr, outBuffer->frameCount);
return 0; // TODO: Return code from processBuffer()
}
static int configure(ViperContext *pContext, effect_config_t *newConfig) {
VIPER_LOGI("Begin audio configure ...");
VIPER_LOGI("Checking input and output configuration ...");
if (newConfig->inputCfg.samplingRate != newConfig->outputCfg.samplingRate) {
VIPER_LOGE("ViPER4Android disabled, reason [in.SR = %d, out.SR = %d]",
newConfig->inputCfg.samplingRate, newConfig->outputCfg.samplingRate);
return -EINVAL;
}
if (newConfig->inputCfg.samplingRate > 48000) {
VIPER_LOGE("ViPER4Android disabled, reason [SR out of range]");
return -EINVAL;
}
if (newConfig->inputCfg.channels != newConfig->outputCfg.channels) {
VIPER_LOGE("ViPER4Android disabled, reason [in.CH = %d, out.CH = %d]",
newConfig->inputCfg.channels, newConfig->outputCfg.channels);
return -EINVAL;
}
if (newConfig->inputCfg.channels != AUDIO_CHANNEL_OUT_STEREO) {
VIPER_LOGE("ViPER4Android disabled, reason [CH != 2]");
return -EINVAL;
}
if (newConfig->inputCfg.format != AUDIO_FORMAT_PCM_FLOAT) {
VIPER_LOGE("ViPER4Android disabled, reason [in.FMT = %d]", newConfig->inputCfg.format);
VIPER_LOGE("We only accept f32 format");
return -EINVAL;
}
if (newConfig->outputCfg.format != AUDIO_FORMAT_PCM_FLOAT) {
VIPER_LOGE("ViPER4Android disabled, reason [out.FMT = %d]", newConfig->outputCfg.format);
VIPER_LOGE("We only accept f32 format");
return -EINVAL;
}
VIPER_LOGI("Input and output configuration checked.");
pContext->config = *newConfig;
VIPER_LOGI("Audio configure finished");
return 0;
} }
static int32_t Viper_ICommand(effect_handle_t self, static int32_t Viper_ICommand(effect_handle_t self,
uint32_t cmdCode, uint32_t cmdSize, void *pCmdData, uint32_t cmdCode, uint32_t cmdSize, void *pCmdData,
uint32_t *replySize, void *pReplyData) { uint32_t *replySize, void *pReplyData) {
auto pContext = (ViperContext *) self; auto pContext = reinterpret_cast<ViperContext *>(self);
if (pContext == nullptr || pContext->viper == nullptr) { if (pContext == nullptr || pContext->viper == nullptr) {
VIPER_LOGE("Viper_ICommand: pContext or pContext->viper is null!"); VIPER_LOGE("Viper_ICommand: pContext or pContext->viper is null!");
return -EINVAL; return -EINVAL;
} }
return pContext->viper->command(cmdCode, cmdSize, pCmdData, replySize, pReplyData); 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 = (effect_param_t *) pCmdData;
if (pCmdParam->psize != sizeof(int32_t)) {
*(int *) pReplyData = -EINVAL;
return 0;
}
// TODO: implement
}
case EFFECT_CMD_GET_PARAM: {
auto *pCmdParam = (effect_param_t *) pCmdData;
auto *pReplyParam = (effect_param_t *) pReplyData;
if (pCmdParam->psize != sizeof(int)) break;
switch (*(int *) pCmdParam->data) {
case PARAM_GET_DRIVER_VERSION: {
pReplyParam->status = 0;
//pReplyParam->psize = sizeof(int32_t); // TODO
pReplyParam->vsize = sizeof(int32_t);
*(int32_t *) pReplyParam->data = 0x2050004; // As original, change as needed
*replySize = 0x14; // As original, TODO: calculate correctly
return 0;
}
case PARAM_GET_ENABLED: {
pReplyParam->status = 0;
//pReplyParam->psize = sizeof(int32_t); // TODO
pReplyParam->vsize = sizeof(int32_t);
*(int32_t *) pReplyParam->data = pContext->viper->enabled;
*replySize = 0x14; // As original, TODO: calculate correctly
return 0;
}
case PARAM_GET_CONFIGURE: {
pReplyParam->status = 0;
//pReplyParam->psize = sizeof(int32_t); // TODO
pReplyParam->vsize = sizeof(int32_t);
*(int32_t *) pReplyParam->data = 1; // TODO?
*replySize = 0x14; // As original, TODO: calculate correctly
return 0;
}
case PARAM_GET_DRVCANWORK: {
pReplyParam->status = 0;
//pReplyParam->psize = sizeof(int32_t); // TODO
pReplyParam->vsize = sizeof(int32_t);
*(int32_t *) pReplyParam->data = pContext->viper->init_ok;
*replySize = 0x14; // As original, TODO: calculate correctly
return 0;
}
case PARAM_GET_STREAMING: {
struct timeval time{};
gettimeofday(&time, nullptr);
// TODO: Do some calculations
return 0;
}
case PARAM_GET_SAMPLINGRATE: {
pReplyParam->status = 0;
//pReplyParam->psize = sizeof(int32_t); // TODO
pReplyParam->vsize = sizeof(int32_t);
*(uint32_t *) pReplyParam->data = pContext->viper->samplingRate;
*replySize = 0x14; // As original, TODO: calculate correctly
return 0;
}
case PARAM_GET_CONVUSABLE: {
pReplyParam->status = 0;
//pReplyParam->psize = sizeof(int32_t); // TODO
pReplyParam->vsize = sizeof(int32_t);
*(int32_t *) pReplyParam->data = 1; // TODO: Figure out what is this
*replySize = 0x14; // As original, TODO: calculate correctly
return 0;
}
case PARAM_GET_CONVKNLID: {
pReplyParam->status = 0;
//pReplyParam->psize = sizeof(int32_t); // TODO
pReplyParam->vsize = sizeof(int32_t);
*(uint32_t *) pReplyParam->data = pContext->viper->convolver->GetKernelID();
*replySize = 0x14; // As original, TODO: calculate correctly
return 0;
}
}
}
case EFFECT_CMD_GET_CONFIG: {
memcpy(pReplyData, &pContext->config, sizeof(effect_config_t));
return 0;
}
}
return -EINVAL;
} }
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 = (ViperContext *) self; auto pContext = reinterpret_cast<ViperContext *>(self);
if (pContext == nullptr || pDescriptor == nullptr) { if (pContext == nullptr || pDescriptor == nullptr) {
VIPER_LOGE("Viper_IGetDescriptor: pContext or pDescriptor is null!"); VIPER_LOGE("Viper_IGetDescriptor: pContext or pDescriptor is null!");
@ -68,6 +252,26 @@ static const effect_interface_s viper_interface = {
.get_descriptor = Viper_IGetDescriptor .get_descriptor = Viper_IGetDescriptor
}; };
static void Viper_Init(ViperContext *pContext) {
pContext->interface = &viper_interface;
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();
}
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()"); VIPER_LOGI("Enter Viper_Create()");
@ -84,17 +288,15 @@ Viper_Create(const effect_uuid_t *uuid, int32_t sessionId __unused, int32_t ioId
VIPER_LOGI("Viper_Create: uuid matches, creating viper..."); VIPER_LOGI("Viper_Create: uuid matches, creating viper...");
auto *pContext = new ViperContext(); auto *pContext = new ViperContext;
pContext->interface = &viper_interface; Viper_Init(pContext);
pContext->viper = new ViPER();
*pHandle = (effect_handle_t) pContext; *pHandle = (effect_handle_t) pContext;
return 0; return 0;
} }
static int32_t Viper_Release(effect_handle_t handle) { static int32_t Viper_Release(effect_handle_t handle) {
auto *pContext = (ViperContext *) handle; auto pContext = reinterpret_cast<ViperContext *>(handle);
VIPER_LOGI("Enter Viper_Release()"); VIPER_LOGI("Enter Viper_Release()");
@ -105,10 +307,7 @@ static int32_t Viper_Release(effect_handle_t handle) {
VIPER_LOGI("Viper_Release: deleting viper..."); VIPER_LOGI("Viper_Release: deleting viper...");
if (pContext->viper != nullptr) { delete pContext->viper;
delete pContext->viper;
pContext->viper = nullptr;
}
delete pContext; delete pContext;
return 0; return 0;

View File

@ -12,12 +12,10 @@ enum ParamsMode {
enum ParamsGet { enum ParamsGet {
PARAM_GET_STATUS_BEGIN = 0x08000, PARAM_GET_STATUS_BEGIN = 0x08000,
PARAM_GET_DRIVER_VERSION, PARAM_GET_DRIVER_VERSION,
PARAM_GET_NEONENABLED,
PARAM_GET_ENABLED, PARAM_GET_ENABLED,
PARAM_GET_CONFIGURE, PARAM_GET_CONFIGURE,
PARAM_GET_DRVCANWORK, PARAM_GET_DRVCANWORK,
PARAM_GET_STREAMING, PARAM_GET_STREAMING,
PARAM_GET_EFFECT_TYPE,
PARAM_GET_SAMPLINGRATE, PARAM_GET_SAMPLINGRATE,
PARAM_GET_CONVUSABLE, PARAM_GET_CONVUSABLE,
PARAM_GET_CONVKNLID, PARAM_GET_CONVKNLID,

View File

@ -1,112 +0,0 @@
#include <cstring>
#include "Effect.h"
#include "constants.h"
Effect::Effect() {
this->enabled = false;
this->configureOk = false;
this->sampleRate = DEFAULT_SAMPLERATE;
memset(&this->config, 0, sizeof(effect_config_t));
this->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
this->config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT; // TODO: Try to use PCM_FLOAT instead
this->config.inputCfg.samplingRate = DEFAULT_SAMPLERATE;
this->config.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
this->config.inputCfg.mask = AUDIO_PORT_CONFIG_ALL;
this->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
this->config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT; // TODO: Try to use PCM_FLOAT instead
this->config.outputCfg.samplingRate = DEFAULT_SAMPLERATE;
this->config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
this->config.outputCfg.mask = AUDIO_PORT_CONFIG_ALL;
this->buffer = nullptr;
this->bufferSize = 0;
this->instance = nullptr;
}
Effect::~Effect() {
delete this->buffer;
}
int32_t Effect::process(audio_buffer_s *in, audio_buffer_s *out) {
// TODO
return -1;
}
int32_t Effect::command(uint32_t cmdCode, uint32_t cmdSize, void *pCmdData, uint32_t *replySize, void *pReplyData) {
switch (cmdCode) {
case EFFECT_CMD_INIT:
case EFFECT_CMD_SET_CONFIG: // receives effect_config_t
case EFFECT_CMD_SET_PARAM:
case EFFECT_CMD_SET_PARAM_COMMIT:
*((int *) pReplyData) = 0;
case EFFECT_CMD_RESET:
case EFFECT_CMD_SET_PARAM_DEFERRED:
break;
case EFFECT_CMD_SET_CONFIG_REVERSE:
*((int *) pReplyData) = -EINVAL;
default:
return -EINVAL;
case EFFECT_CMD_GET_CONFIG:
memcpy(pReplyData, &this->config, sizeof(effect_config_t));
break;
}
return 0;
}
int32_t Effect::configure(effect_config_t *newConfig) {
VIPER_LOGI("Begin audio configure ...");
VIPER_LOGI("Checking input and output configuration ...");
if (newConfig->inputCfg.samplingRate != newConfig->outputCfg.samplingRate) {
VIPER_LOGE("ViPER4Android disabled, reason [in.SR = %d, out.SR = %d]",
newConfig->inputCfg.samplingRate, newConfig->outputCfg.samplingRate);
goto exit_error;
}
if (newConfig->inputCfg.samplingRate > 48000) {
VIPER_LOGE("ViPER4Android disabled, reason [SR out of range]");
goto exit_error;
}
if (newConfig->inputCfg.channels != newConfig->outputCfg.channels) {
VIPER_LOGE("ViPER4Android disabled, reason [in.CH = %d, out.CH = %d]",
newConfig->inputCfg.channels, newConfig->outputCfg.channels);
goto exit_error;
}
if (newConfig->inputCfg.channels != AUDIO_CHANNEL_OUT_STEREO) {
VIPER_LOGE("ViPER4Android disabled, reason [CH != 2]");
goto exit_error;
}
// TODO: Allow multiple formats by converting before/after processing
if (newConfig->inputCfg.format != AUDIO_FORMAT_PCM_FLOAT) {
VIPER_LOGE("ViPER4Android disabled, reason [in.FMT = %d]", newConfig->inputCfg.format);
VIPER_LOGE("We only accept f32 format");
goto exit_error;
}
if (newConfig->outputCfg.format != AUDIO_FORMAT_PCM_FLOAT) {
VIPER_LOGE("ViPER4Android disabled, reason [out.FMT = %d]", newConfig->outputCfg.format);
VIPER_LOGE("We only accept f32 format");
goto exit_error;
}
VIPER_LOGI("Input and output configuration checked.");
memcpy(&this->config, newConfig, sizeof(effect_config_t));
this->configureOk = true;
VIPER_LOGI("Audio configure finished");
return 0;
exit_error:
this->configureOk = false;
return -EINVAL;
}

View File

@ -1,28 +0,0 @@
#pragma once
#include <cstdint>
#include "essential.h"
class Effect {
public:
Effect();
~Effect();
virtual int32_t command(uint32_t cmdCode, uint32_t cmdSize, void *pCmdData, uint32_t *replySize, void *pReplyData);
int32_t process(audio_buffer_s *in, audio_buffer_s *out);
int32_t configure(effect_config_t *config);
bool enabled;
bool configureOk;
uint32_t sampleRate;
effect_config_t config;
// Misc data here?
// TODO: Figure out what buffer is used for
float *buffer;
uint32_t bufferSize;
void *instance; // type: ViPER
};

View File

@ -1,6 +1,5 @@
#include "ViPER.h" #include "ViPER.h"
#include <ctime> #include <ctime>
#include "Effect.h"
#include "constants.h" #include "constants.h"
ViPER::ViPER() { ViPER::ViPER() {
@ -12,72 +11,72 @@ ViPER::ViPER() {
this->convolver = new Convolver(); this->convolver = new Convolver();
this->convolver->SetEnable(false); this->convolver->SetEnable(false);
this->convolver->SetSamplingRate(this->sampleRate); this->convolver->SetSamplingRate(this->samplingRate);
this->convolver->Reset(); this->convolver->Reset();
this->vhe = new VHE(); this->vhe = new VHE();
this->vhe->SetEnable(false); this->vhe->SetEnable(false);
this->vhe->SetSamplingRate(this->sampleRate); this->vhe->SetSamplingRate(this->samplingRate);
this->vhe->Reset(); this->vhe->Reset();
this->viperDdc = new ViPERDDC(); this->viperDdc = new ViPERDDC();
this->viperDdc->SetEnable(false); this->viperDdc->SetEnable(false);
this->viperDdc->SetSamplingRate(this->sampleRate); this->viperDdc->SetSamplingRate(this->samplingRate);
this->viperDdc->Reset(); this->viperDdc->Reset();
this->spectrumExtend = new SpectrumExtend(); this->spectrumExtend = new SpectrumExtend();
this->spectrumExtend->SetEnable(false); this->spectrumExtend->SetEnable(false);
this->spectrumExtend->SetSamplingRate(this->sampleRate); this->spectrumExtend->SetSamplingRate(this->samplingRate);
this->spectrumExtend->SetReferenceFrequency(7600); this->spectrumExtend->SetReferenceFrequency(7600);
this->spectrumExtend->SetExciter(0); this->spectrumExtend->SetExciter(0);
this->spectrumExtend->Reset(); this->spectrumExtend->Reset();
this->iirFilter = new IIRFilter(); this->iirFilter = new IIRFilter(10);
this->iirFilter->SetEnable(false); this->iirFilter->SetEnable(false);
this->iirFilter->SetSamplingRate(this->sampleRate); this->iirFilter->SetSamplingRate(this->samplingRate);
this->iirFilter->Reset(); this->iirFilter->Reset();
this->colorfulMusic = new ColorfulMusic(); this->colorfulMusic = new ColorfulMusic();
this->colorfulMusic->SetEnable(false); this->colorfulMusic->SetEnable(false);
this->colorfulMusic->SetSamplingRate(this->sampleRate); this->colorfulMusic->SetSamplingRate(this->samplingRate);
this->colorfulMusic->Reset(); this->colorfulMusic->Reset();
this->reverberation = new Reverberation(); this->reverberation = new Reverberation();
this->reverberation->SetEnable(false); this->reverberation->SetEnable(false);
this->reverberation->SetSamplingRate(this->sampleRate); this->reverberation->SetSamplingRate(this->samplingRate);
this->reverberation->Reset(); this->reverberation->Reset();
this->playbackGain = new PlaybackGain(); this->playbackGain = new PlaybackGain();
this->playbackGain->SetEnable(false); this->playbackGain->SetEnable(false);
this->playbackGain->SetSamplingRate(this->sampleRate); this->playbackGain->SetSamplingRate(this->samplingRate);
this->playbackGain->Reset(); this->playbackGain->Reset();
this->fetCompressor = new FETCompressor(); this->fetCompressor = new FETCompressor();
this->fetCompressor->SetParameter(0, 0.0); this->fetCompressor->SetParameter(0, 0.0);
this->fetCompressor->SetSamplingRate(this->sampleRate); this->fetCompressor->SetSamplingRate(this->samplingRate);
this->fetCompressor->Reset(); this->fetCompressor->Reset();
this->dynamicSystem = new DynamicSystem(); this->dynamicSystem = new DynamicSystem();
this->dynamicSystem->SetEnable(false); this->dynamicSystem->SetEnable(false);
this->dynamicSystem->SetSamplingRate(this->sampleRate); this->dynamicSystem->SetSamplingRate(this->samplingRate);
this->dynamicSystem->Reset(); this->dynamicSystem->Reset();
this->viperBass = new ViPERBass(); this->viperBass = new ViPERBass();
this->viperBass->SetSamplingRate(this->sampleRate); this->viperBass->SetSamplingRate(this->samplingRate);
this->viperBass->Reset(); this->viperBass->Reset();
this->viperClarity = new ViPERClarity(); this->viperClarity = new ViPERClarity();
this->viperClarity->SetSamplingRate(this->sampleRate); this->viperClarity->SetSamplingRate(this->samplingRate);
this->viperClarity->Reset(); this->viperClarity->Reset();
this->diffSurround = new DiffSurround(); this->diffSurround = new DiffSurround();
this->diffSurround->SetEnable(false); this->diffSurround->SetEnable(false);
this->diffSurround->SetSamplingRate(this->sampleRate); this->diffSurround->SetSamplingRate(this->samplingRate);
this->diffSurround->Reset(); this->diffSurround->Reset();
this->cure = new Cure(); this->cure = new Cure();
this->cure->SetEnable(false); this->cure->SetEnable(false);
this->cure->SetSamplingRate(this->sampleRate); this->cure->SetSamplingRate(this->samplingRate);
this->cure->Reset(); this->cure->Reset();
this->tubeSimulator = new TubeSimulator(); this->tubeSimulator = new TubeSimulator();
@ -86,13 +85,13 @@ ViPER::ViPER() {
this->analogX = new AnalogX(); this->analogX = new AnalogX();
// this->analogX->SetEnable(false); // this->analogX->SetEnable(false);
this->analogX->SetSamplingRate(this->sampleRate); this->analogX->SetSamplingRate(this->samplingRate);
this->analogX->SetProcessingModel(0); this->analogX->SetProcessingModel(0);
this->analogX->Reset(); this->analogX->Reset();
this->speakerCorrection = new SpeakerCorrection(); this->speakerCorrection = new SpeakerCorrection();
this->speakerCorrection->SetEnable(false); this->speakerCorrection->SetEnable(false);
this->speakerCorrection->SetSamplingRate(this->sampleRate); this->speakerCorrection->SetSamplingRate(this->samplingRate);
this->speakerCorrection->Reset(); this->speakerCorrection->Reset();
for (auto &softwareLimiter: this->softwareLimiters) { for (auto &softwareLimiter: this->softwareLimiters) {
@ -136,143 +135,10 @@ ViPER::~ViPER() {
} }
} }
int32_t // TODO: Return int
ViPER::command(uint32_t cmdCode, uint32_t cmdSize, void *pCmdData, uint32_t *replySize, void *pReplyData) { void ViPER::processBuffer(float *buffer, uint32_t size) {
switch (cmdCode) {
case EFFECT_CMD_ENABLE: {
if (!this->enabled) {
ResetAllEffects();
break;
}
return 0;
}
case EFFECT_CMD_RESET: {
ResetAllEffects();
break;
}
case EFFECT_CMD_SET_CONFIG: {
if (cmdSize != 64 || *replySize != 4) {
return -EINVAL;
}
auto currentSampleRate = this->sampleRate;
*(int32_t *) pReplyData = this->configure((effect_config_t *) pCmdData);
if (*(int32_t *) pReplyData == 0) {
if (currentSampleRate != this->sampleRate) {
ResetAllEffects();
}
}
return 0;
}
case EFFECT_CMD_SET_PARAM: {
auto pCmdParam = (effect_param_t *) pCmdData;
if (pCmdParam->psize != sizeof(int32_t)) {
*(int32_t *) pReplyData = -EINVAL;
return 0;
}
// TODO: implement
}
case EFFECT_CMD_GET_PARAM: {
auto *pCmdParam = (effect_param_t *) pCmdData;
auto *pReplyParam = (effect_param_t *) pReplyData;
if (pCmdParam->psize != sizeof(int32_t)) break;
switch (*(int *) pCmdParam->data) {
case PARAM_GET_DRIVER_VERSION: {
pReplyParam->status = 0;
//pReplyParam->psize = sizeof(int32_t); // TODO
pReplyParam->vsize = sizeof(int32_t);
*(int32_t *) pReplyParam->data = 0x2050004; // As original, change as needed
*replySize = 0x14; // As original, TODO: calculate correctly
return 0;
}
case PARAM_GET_NEONENABLED: {
pReplyParam->status = 0;
//pReplyParam->psize = sizeof(int32_t); // TODO
pReplyParam->vsize = sizeof(int32_t);
*(int32_t *) pReplyParam->data = 1; // TODO: check if neon is enabled
*replySize = 0x14; // As original, TODO: calculate correctly
return 0;
}
case PARAM_GET_ENABLED: {
pReplyParam->status = 0;
//pReplyParam->psize = sizeof(int32_t); // TODO
pReplyParam->vsize = sizeof(int32_t);
*(int32_t *) pReplyParam->data = this->enabled;
*replySize = 0x14; // As original, TODO: calculate correctly
return 0;
}
case PARAM_GET_CONFIGURE: {
pReplyParam->status = 0;
//pReplyParam->psize = sizeof(int32_t); // TODO
pReplyParam->vsize = sizeof(int32_t);
*(int32_t *) pReplyParam->data = this->configureOk;
*replySize = 0x14; // As original, TODO: calculate correctly
return 0;
}
case PARAM_GET_DRVCANWORK: {
pReplyParam->status = 0;
//pReplyParam->psize = sizeof(int32_t); // TODO
pReplyParam->vsize = sizeof(int32_t);
*(int32_t *) pReplyParam->data = this->init_ok;
*replySize = 0x14; // As original, TODO: calculate correctly
return 0;
}
case PARAM_GET_STREAMING: {
struct timeval time{};
gettimeofday(&time, nullptr);
// TODO: Do some calculations
return 0;
}
case PARAM_GET_EFFECT_TYPE: {
pReplyParam->status = 0;
//pReplyParam->psize = sizeof(int32_t); // TODO
pReplyParam->vsize = sizeof(int32_t);
*(int32_t *) pReplyParam->data = 1; //this->mode; TODO: This driver is not using any effect type, it's completely controlled by the frontend
*replySize = 0x14; // As original, TODO: calculate correctly
return 0;
}
case PARAM_GET_SAMPLINGRATE: {
pReplyParam->status = 0;
//pReplyParam->psize = sizeof(int32_t); // TODO
pReplyParam->vsize = sizeof(int32_t);
*(uint32_t *) pReplyParam->data = this->sampleRate;
*replySize = 0x14; // As original, TODO: calculate correctly
return 0;
}
case PARAM_GET_CONVUSABLE: {
pReplyParam->status = 0;
//pReplyParam->psize = sizeof(int32_t); // TODO
pReplyParam->vsize = sizeof(int32_t);
*(int32_t *) pReplyParam->data = 1; // TODO: Figure out what is this
*replySize = 0x14; // As original, TODO: calculate correctly
return 0;
}
case PARAM_GET_CONVKNLID: {
pReplyParam->status = 0;
//pReplyParam->psize = sizeof(int32_t); // TODO
pReplyParam->vsize = sizeof(int32_t);
*(uint32_t *) pReplyParam->data = this->convolver->GetKernelID();
*replySize = 0x14; // As original, TODO: calculate correctly
return 0;
}
}
}
}
return this->Effect::command(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
}
void ViPER::processBuffer(float *buffer, int frameSize) {
if (!this->enabled) return; if (!this->enabled) return;
if (frameSize < 1) return; if (size == 0) return;
if (!this->init_ok) return; if (!this->init_ok) return;
if (this->update_status) { if (this->update_status) {
@ -284,18 +150,18 @@ void ViPER::processBuffer(float *buffer, int frameSize) {
uint32_t ret; uint32_t ret;
// if convolver is enabled // if convolver is enabled
ret = this->waveBuffer->PushSamples(buffer, frameSize); ret = this->waveBuffer->PushSamples(buffer, size);
if (ret == 0) { if (ret == 0) {
this->waveBuffer->Reset(); this->waveBuffer->Reset();
return; return;
} }
auto pWaveBuffer = this->waveBuffer->GetBuffer(); auto pWaveBuffer = this->waveBuffer->GetBuffer();
this->convolver->Process(pWaveBuffer, pWaveBuffer, frameSize); this->convolver->Process(pWaveBuffer, pWaveBuffer, size);
this->vhe->Process(pWaveBuffer, pWaveBuffer, frameSize); this->vhe->Process(pWaveBuffer, pWaveBuffer, size);
this->waveBuffer->SetBufferOffset(frameSize); this->waveBuffer->SetBufferOffset(size);
ret = this->adaptiveBuffer->PushZero(frameSize); ret = this->adaptiveBuffer->PushZero(size);
if (ret == 0) { if (ret == 0) {
this->waveBuffer->Reset(); this->waveBuffer->Reset();
this->adaptiveBuffer->FlushBuffer(); this->adaptiveBuffer->FlushBuffer();
@ -303,13 +169,13 @@ void ViPER::processBuffer(float *buffer, int frameSize) {
} }
auto pAdaptiveBuffer = this->adaptiveBuffer->GetBufferPointer(); auto pAdaptiveBuffer = this->adaptiveBuffer->GetBufferPointer();
ret = this->waveBuffer->PopSamples((float *) pAdaptiveBuffer, frameSize, true); ret = this->waveBuffer->PopSamples((float *) pAdaptiveBuffer, size, true);
this->adaptiveBuffer->SetBufferOffset(ret); this->adaptiveBuffer->SetBufferOffset(ret);
pAdaptiveBuffer = this->adaptiveBuffer->GetBufferPointer(); pAdaptiveBuffer = this->adaptiveBuffer->GetBufferPointer();
if (ret != 0) { if (ret != 0) {
this->viperDdc->Process(pAdaptiveBuffer, frameSize); this->viperDdc->Process(pAdaptiveBuffer, size);
this->spectrumExtend->Process(pAdaptiveBuffer, frameSize); this->spectrumExtend->Process(pAdaptiveBuffer, size);
this->iirFilter->Process(pAdaptiveBuffer, ret); this->iirFilter->Process(pAdaptiveBuffer, ret);
this->colorfulMusic->Process(pAdaptiveBuffer, ret); this->colorfulMusic->Process(pAdaptiveBuffer, ret);
this->diffSurround->Process(pAdaptiveBuffer, ret); this->diffSurround->Process(pAdaptiveBuffer, ret);
@ -321,7 +187,7 @@ void ViPER::processBuffer(float *buffer, int frameSize) {
this->viperBass->Process(pAdaptiveBuffer, ret); this->viperBass->Process(pAdaptiveBuffer, ret);
this->viperClarity->Process(pAdaptiveBuffer, ret); this->viperClarity->Process(pAdaptiveBuffer, ret);
this->cure->Process(pAdaptiveBuffer, ret); this->cure->Process(pAdaptiveBuffer, ret);
this->tubeSimulator->TubeProcess(pAdaptiveBuffer, frameSize); this->tubeSimulator->TubeProcess(pAdaptiveBuffer, size);
this->analogX->Process(pAdaptiveBuffer, ret); this->analogX->Process(pAdaptiveBuffer, ret);
} }
@ -351,70 +217,70 @@ void ViPER::ResetAllEffects() {
this->waveBuffer->Reset(); this->waveBuffer->Reset();
} }
if (this->convolver != nullptr) { if (this->convolver != nullptr) {
this->convolver->SetSamplingRate(this->sampleRate); this->convolver->SetSamplingRate(this->samplingRate);
this->convolver->Reset(); this->convolver->Reset();
} }
if (this->vhe != nullptr) { if (this->vhe != nullptr) {
this->vhe->SetSamplingRate(this->sampleRate); this->vhe->SetSamplingRate(this->samplingRate);
this->vhe->Reset(); this->vhe->Reset();
} }
if (this->viperDdc != nullptr) { if (this->viperDdc != nullptr) {
this->viperDdc->SetSamplingRate(this->sampleRate); this->viperDdc->SetSamplingRate(this->samplingRate);
this->viperDdc->Reset(); this->viperDdc->Reset();
} }
if (this->spectrumExtend != nullptr) { if (this->spectrumExtend != nullptr) {
this->spectrumExtend->SetSamplingRate(this->sampleRate); this->spectrumExtend->SetSamplingRate(this->samplingRate);
this->spectrumExtend->Reset(); this->spectrumExtend->Reset();
} }
if (this->iirFilter != nullptr) { if (this->iirFilter != nullptr) {
this->iirFilter->SetSamplingRate(this->sampleRate); this->iirFilter->SetSamplingRate(this->samplingRate);
this->iirFilter->Reset(); this->iirFilter->Reset();
} }
if (this->colorfulMusic != nullptr) { if (this->colorfulMusic != nullptr) {
this->colorfulMusic->SetSamplingRate(this->sampleRate); this->colorfulMusic->SetSamplingRate(this->samplingRate);
this->colorfulMusic->Reset(); this->colorfulMusic->Reset();
} }
if (this->reverberation != nullptr) { if (this->reverberation != nullptr) {
this->reverberation->SetSamplingRate(this->sampleRate); this->reverberation->SetSamplingRate(this->samplingRate);
this->reverberation->Reset(); this->reverberation->Reset();
} }
if (this->playbackGain != nullptr) { if (this->playbackGain != nullptr) {
this->playbackGain->SetSamplingRate(this->sampleRate); this->playbackGain->SetSamplingRate(this->samplingRate);
this->playbackGain->Reset(); this->playbackGain->Reset();
} }
if (this->fetCompressor != nullptr) { if (this->fetCompressor != nullptr) {
this->fetCompressor->SetSamplingRate(this->sampleRate); this->fetCompressor->SetSamplingRate(this->samplingRate);
this->fetCompressor->Reset(); this->fetCompressor->Reset();
} }
if (this->dynamicSystem != nullptr) { if (this->dynamicSystem != nullptr) {
this->dynamicSystem->SetSamplingRate(this->sampleRate); this->dynamicSystem->SetSamplingRate(this->samplingRate);
this->dynamicSystem->Reset(); this->dynamicSystem->Reset();
} }
if (this->viperBass != nullptr) { if (this->viperBass != nullptr) {
this->viperBass->SetSamplingRate(this->sampleRate); this->viperBass->SetSamplingRate(this->samplingRate);
this->viperBass->Reset(); this->viperBass->Reset();
} }
if (this->viperClarity != nullptr) { if (this->viperClarity != nullptr) {
this->viperClarity->SetSamplingRate(this->sampleRate); this->viperClarity->SetSamplingRate(this->samplingRate);
this->viperClarity->Reset(); this->viperClarity->Reset();
} }
if (this->diffSurround != nullptr) { if (this->diffSurround != nullptr) {
this->diffSurround->SetSamplingRate(this->sampleRate); this->diffSurround->SetSamplingRate(this->samplingRate);
this->diffSurround->Reset(); this->diffSurround->Reset();
} }
if (this->cure != nullptr) { if (this->cure != nullptr) {
this->cure->SetSamplingRate(this->sampleRate); this->cure->SetSamplingRate(this->samplingRate);
this->cure->Reset(); this->cure->Reset();
} }
if (this->tubeSimulator != nullptr) { if (this->tubeSimulator != nullptr) {
this->tubeSimulator->Reset(); this->tubeSimulator->Reset();
} }
if (this->analogX != nullptr) { if (this->analogX != nullptr) {
this->analogX->SetSamplingRate(this->sampleRate); this->analogX->SetSamplingRate(this->samplingRate);
this->analogX->Reset(); this->analogX->Reset();
} }
if (this->speakerCorrection != nullptr) { if (this->speakerCorrection != nullptr) {
this->speakerCorrection->SetSamplingRate(this->sampleRate); this->speakerCorrection->SetSamplingRate(this->samplingRate);
this->speakerCorrection->Reset(); this->speakerCorrection->Reset();
} }
for (auto &softwareLimiter: softwareLimiters) { for (auto &softwareLimiter: softwareLimiters) {

View File

@ -1,6 +1,5 @@
#pragma once #pragma once
#include "Effect.h"
#include "utils/WaveBuffer.h" #include "utils/WaveBuffer.h"
#include "effects/SpectrumExtend.h" #include "effects/SpectrumExtend.h"
#include "effects/Reverberation.h" #include "effects/Reverberation.h"
@ -23,29 +22,22 @@
#include "effects/PlaybackGain.h" #include "effects/PlaybackGain.h"
#include "../ViPER4Android.h" #include "../ViPER4Android.h"
class ViPER : public Effect { class ViPER {
public: public:
ViPER(); ViPER();
~ViPER(); ~ViPER();
int32_t command(uint32_t cmdCode, uint32_t cmdSize, void *pCmdData, uint32_t *replySize, void *pReplyData) override; void processBuffer(float *buffer, uint32_t size);
void processBuffer(float *buffer, int frameSize);
// TODO: Parameter types/names // TODO: Parameter types/names
void DispatchCommand(int param_1, int param_2, int param_3, int param_4, int param_5, int param_6, int param_7); void DispatchCommand(int param_1, int param_2, int param_3, int param_4, int param_5, int param_6, int param_7);
void ResetAllEffects(); void ResetAllEffects();
bool update_status; bool update_status;
// Something or padding of 3 bytes
uint64_t process_time_ms; uint64_t process_time_ms;
bool init_ok; bool init_ok;
bool enabled; bool enabled;
bool force_enabled; bool force_enabled;
// Something or padding of 1 byte uint32_t samplingRate;
// FxMode mode;
// Effects // Effects
AdaptiveBuffer *adaptiveBuffer; AdaptiveBuffer *adaptiveBuffer;

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->coeffs.UpdateCoeffs(bands,this->samplingRate); this->minPhaseIirCoeffs.UpdateCoeffs(bands, this->samplingRate);
} else { } else {
this->bands = 0; this->bands = 0;
} }
@ -25,14 +25,32 @@ IIRFilter::~IIRFilter() {
} }
void IIRFilter::Process(float *samples, uint32_t size) { void IIRFilter::Process(float *samples, uint32_t size) {
if (!this->enable) return;
float *coeffs = this->minPhaseIirCoeffs.GetCoefficients();
if (coeffs == nullptr || size == 0) return;
for (uint32_t i = 0; i < size; i++) {
for (uint32_t j = 0; j < 2; j++) {
float tmp = 0.0;
for (uint32_t k = 0; k < this->bands * 16; k++) {
samples[2 * i + j];
}
samples[2 * i + j] = tmp;
}
this->unknown2 = (this->unknown2 + 1) % 3;
this->unknown3 = (this->unknown3 + 1) % 3;
this->unknown4 = (this->unknown4 + 1) % 3;
}
} }
void IIRFilter::Reset() { void IIRFilter::Reset() {
memset(this->buf,0,0x7c0); memset(this->buf,0,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) {
@ -49,7 +67,7 @@ void IIRFilter::SetEnable(bool enable) {
void IIRFilter::SetSamplingRate(uint32_t samplingRate) { void IIRFilter::SetSamplingRate(uint32_t samplingRate) {
this->samplingRate = samplingRate; this->samplingRate = samplingRate;
if (this->bands != 0) { if (this->bands != 0) {
this->coeffs->UpdateCoeffs(bands, samplingRate); this->minPhaseIirCoeffs.UpdateCoeffs(bands, samplingRate);
} }
this->Reset(); this->Reset();
} }

View File

@ -18,9 +18,11 @@ private:
uint32_t bands; uint32_t bands;
uint32_t samplingRate; uint32_t samplingRate;
bool enable; bool enable;
MinPhaseIIRCoeffs coeffs; MinPhaseIIRCoeffs minPhaseIirCoeffs;
float buf[496]; float buf[496];
// 3 unknown uint32_t unknown2;
uint32_t unknown3;
uint32_t unknown4;
float bandLevelsWithQ[31]; float bandLevelsWithQ[31];
}; };

View File

@ -5,7 +5,6 @@
class SoftwareLimiter { class SoftwareLimiter {
public: public:
SoftwareLimiter(); SoftwareLimiter();
~SoftwareLimiter();
void Process(float *samples, uint32_t size); void Process(float *samples, uint32_t size);
void ResetLimiter(); void ResetLimiter();

View File

@ -40,18 +40,18 @@ float Harmonic::Process(float sample) {
sample * this->coeffs[9] + sample * this->coeffs[9] +
sample * this->coeffs[10] sample * this->coeffs[10]
); );
this->prevOut = this->lastProcessed + this->prevOut * 0.999f - prevLast; this->prevOut = (this->lastProcessed + this->prevOut * 0.999f) - prevLast;
if (this->sampleCounter < this->buildup) { if (this->sampleCounter < this->buildup) {
this->sampleCounter++; this->sampleCounter++;
return 0; return 0.0;
} }
return this->prevOut; return this->prevOut;
} }
void Harmonic::Reset() { void Harmonic::Reset() {
this->lastProcessed = 0.f; this->lastProcessed = 0.0;
this->prevOut = 0.f; this->prevOut = 0.0;
this->sampleCounter = 0.f; this->sampleCounter = 0;
} }
void Harmonic::SetHarmonics(float *coefficients) { void Harmonic::SetHarmonics(float *coefficients) {

View File

@ -1,27 +1,23 @@
#pragma once #pragma once
#include <cstdint> #include <cstdint>
class Harmonic { class Harmonic {
public: public:
Harmonic(); Harmonic();
~Harmonic(); ~Harmonic();
float Process(float sample); float Process(float sample);
void Reset(); void Reset();
void SetHarmonics(float *coeffs); void SetHarmonics(float *coeffs);
void UpdateCoeffs(float *coeffs); void UpdateCoeffs(float *coeffs);
private:
float coeffs[11]; float coeffs[11];
float lastProcessed; float lastProcessed;
float prevOut; float prevOut;
int buildup; uint32_t buildup;
int sampleCounter; uint32_t sampleCounter;
}; };

View File

@ -3,22 +3,47 @@
Stereo3DSurround::Stereo3DSurround() { Stereo3DSurround::Stereo3DSurround() {
this->middleImage = 1.0; this->middleImage = 1.0;
this->stereoWiden = 0.0; this->stereoWiden = 0.0;
this->unknown1 = 1.0;
this->unknown2 = 0.5;
this->coeffLeft = 0.5; this->coeffLeft = 0.5;
this->coeffRight = 0.5; this->coeffRight = 0.5;
} }
void Stereo3DSurround::Process(float *samples, uint32_t size) { void Stereo3DSurround::Process(float *samples, uint32_t size) {
if (size >= 2) { if (size == 0) return;
uint32_t pairs = size / 2;
uint32_t remainder = size % 2;
if (pairs > 0) {
for (uint32_t i = 0; i < pairs; i++) {
float a = this->coeffLeft * (samples[4 * i] + samples[4 * i + 1]);
float b = this->coeffRight * (samples[4 * i + 1] - samples[4 * i]);
float c = this->coeffLeft * (samples[4 * i + 2] + samples[4 * i + 3]);
float d = this->coeffRight * (samples[4 * i + 3] - samples[4 * i + 2]);
samples[4 * i] = a - b;
samples[4 * i + 1] = a + b;
samples[4 * i + 2] = c - d;
samples[4 * i + 3] = c + d;
}
}
if (remainder > 0) {
for (uint32_t i = pairs; i < pairs + remainder; i++) {
float a = samples[2 * i];
float b = samples[2 * i + 1];
float c = this->coeffLeft * (a + b);
float d = this->coeffRight * (b - a);
samples[2 * i] = c - d;
samples[2 * i + 1] = c + d;
}
} }
} }
inline void Stereo3DSurround::ConfigureVariables() { inline void Stereo3DSurround::ConfigureVariables() {
this->unknown1 = this->stereoWiden + 1.0f; float tmp = this->stereoWiden + 1.0f;
float x = this->unknown1 + 1.0f; float x = tmp + 1.0f;
float y; float y;
if (x < 2.0) { if (x < 2.0) {
y = 0.5; y = 0.5;
@ -26,9 +51,8 @@ inline void Stereo3DSurround::ConfigureVariables() {
y = 1.0f / x; y = 1.0f / x;
} }
this->unknown2 = y;
this->coeffLeft = this->middleImage * y; this->coeffLeft = this->middleImage * y;
this->coeffRight = this->unknown1 * y; this->coeffRight = tmp * y;
} }
void Stereo3DSurround::SetMiddleImage(float middleImage) { void Stereo3DSurround::SetMiddleImage(float middleImage) {

View File

@ -15,8 +15,6 @@ private:
float stereoWiden; float stereoWiden;
float middleImage; float middleImage;
float unknown1;
float unknown2;
float coeffLeft; float coeffLeft;
float coeffRight; float coeffRight;
}; };

View File

@ -1,3 +1,5 @@
#pragma once
// Source: https://android.googlesource.com/platform/system/media/+/master/audio/include/system // Source: https://android.googlesource.com/platform/system/media/+/master/audio/include/system
typedef struct effect_uuid_s typedef struct effect_uuid_s