hifi and clarity

This commit is contained in:
Martmists 2021-07-31 16:00:35 +02:00
parent aa87dba34f
commit 779c172aa8
9 changed files with 267 additions and 12 deletions

View File

@ -27,6 +27,7 @@ set(FILES
src/effects/SpeakerCorrection.cpp
src/effects/SpectrumExtend.cpp
src/effects/TubeSimulator.cpp
src/effects/ViPERClarity.cpp
# Utils
src/utils/CAllpassFilter.cpp
@ -37,6 +38,7 @@ set(FILES
src/utils/DynamicBass.cpp
src/utils/FixedBiquad.cpp
src/utils/Harmonic.cpp
src/utils/HiFi.cpp
src/utils/HighShelf.cpp
src/utils/IIR_1st.cpp
src/utils/IIR_NOrder_BW_BP.cpp

View File

@ -0,0 +1,81 @@
//
// Created by mart on 7/31/21.
//
#include "ViPERClarity.h"
#include "../constants.h"
ViPERClarity::ViPERClarity() {
for (int i = 0; i < 2; i++) {
this->hiShelf[i].SetFrequency(12000.f);
this->hiShelf[i].SetQuality(100.f);
this->hiShelf[i].SetGain(1.f);
this->hiShelf[i].SetSamplingRate(DEFAULT_SAMPLERATE);
}
this->enabled = false;
this->processMode = 0;
this->clarityGainPercent = 0.f;
this->samplerate = DEFAULT_SAMPLERATE;
Reset();
}
void ViPERClarity::Process(float *samples, uint32_t size) {
if (this->enabled) {
if (this->processMode == 0) {
this->sharp.Process(samples, size);
} else if (this->processMode == 1) {
for (int i = 0; i < size * 2; i++) {
samples[i] = this->hiShelf[i % 2].Process(samples[i]);
}
} else {
this->hifi.Process(samples, size);
}
}
}
void ViPERClarity::Reset() {
this->sharp.SetSamplingRate(this->samplerate);
this->sharp.Reset();
SetClarityToFilter();
for (int i = 0; i < 2; i++) {
this->hiShelf[i].SetFrequency(8250.f);
this->hiShelf[i].SetQuality(100.f);
this->hiShelf[i].SetSamplingRate(DEFAULT_SAMPLERATE);
}
this->hifi.SetSamplingRate(this->samplerate);
this->hifi.Reset();
}
void ViPERClarity::SetClarity(float gainPercent) {
this->clarityGainPercent = gainPercent;
if (this->processMode != 1) {
SetClarityToFilter();
} else {
Reset();
}
}
void ViPERClarity::SetClarityToFilter() {
this->sharp.SetGain(this->clarityGainPercent);
this->hiShelf[0].SetGain(this->clarityGainPercent + 1.f);
this->hiShelf[1].SetGain(this->clarityGainPercent + 1.f);
this->hifi.SetClarity(this->clarityGainPercent + 1.f);
}
void ViPERClarity::SetEnable(bool enabled) {
this->enabled = enabled;
if (this->enabled) {
Reset();
}
}
void ViPERClarity::SetProcessMode(int mode) {
this->processMode = mode;
Reset();
}
void ViPERClarity::SetSamplingRate(uint32_t samplerate) {
this->samplerate = samplerate;
Reset();
}

View File

@ -0,0 +1,34 @@
//
// Created by mart on 7/31/21.
//
#pragma once
#include "../utils/NoiseSharpening.h"
#include "../utils/HiFi.h"
#include "../utils/HighShelf.h"
class ViPERClarity {
public:
ViPERClarity();
void Process(float* samples, uint32_t size);
void Reset();
void SetClarity(float gainPercent);
void SetClarityToFilter();
void SetEnable(bool enabled);
void SetProcessMode(int mode);
void SetSamplingRate(uint32_t samplerate);
NoiseSharpening sharp;
HighShelf hiShelf[2];
HiFi hifi;
bool enabled;
int processMode;
uint32_t samplerate;
float clarityGainPercent;
};

82
src/utils/HiFi.cpp Normal file
View File

@ -0,0 +1,82 @@
//
// Created by mart on 7/31/21.
//
#include "HiFi.h"
#include "../constants.h"
HiFi::HiFi() {
this->gain = 1.f;
this->samplerate = DEFAULT_SAMPLERATE;
for (int i = 0; i < 2; i++) {
this->buffers[i] = new WaveBuffer_I32(2, 0x800);
this->filters[i].lowpass = new IIR_NOrder_BW_LH(1);
this->filters[i].highpass = new IIR_NOrder_BW_LH(3);
this->filters[i].bandpass = new IIR_NOrder_BW_BP(3);
}
Reset();
}
HiFi::~HiFi() {
for (int i = 0; i < 2; i++) {
delete this->buffers[i];
delete this->filters[i].lowpass;
delete this->filters[i].highpass;
delete this->filters[i].bandpass;
}
}
void HiFi::Process(float *samples, uint32_t size) {
if (size > 0) {
float* bpBuf = this->buffers[0]->PushZerosGetBuffer(size);
float* lpBuf = this->buffers[1]->PushZerosGetBuffer(size);
if (bpBuf == nullptr || lpBuf == nullptr) {
Reset();
return;
}
for (int i = 0; i < size*2; i++) {
int index = i % 2;
float out1 = do_filter_lh(this->filters[index].lowpass, samples[i]);
float out2 = do_filter_lh(this->filters[index].highpass, samples[i]);
float out3 = do_filter_bp(this->filters[index].bandpass, samples[i]);
samples[i] = out2;
lpBuf[i] = out1;
bpBuf[i] = out3;
}
float* bpOut = this->buffers[0]->GetCurrentBufferI32Ptr();
float* lpOut = this->buffers[1]->GetCurrentBufferI32Ptr();
for (int i = 0; i < size * 2; i++) {
float hp = samples[i] * this->gain * 1.2f;
float bp = bpOut[i] * this->gain;
samples[i] = hp + bp + lpOut[i];
}
this->buffers[0]->PopSamples(size, false);
this->buffers[1]->PopSamples(size, false);
}
}
void HiFi::Reset() {
for (int i = 0; i < 2; i++) {
this->filters[i].lowpass->setLPF(120.0, this->samplerate);
this->filters[i].lowpass->Mute();
this->filters[i].highpass->setHPF(1200.0, this->samplerate);
this->filters[i].highpass->Mute();
this->filters[i].bandpass->setBPF(120.f, 1200.f, this->samplerate);
this->filters[i].bandpass->Mute();
}
this->buffers[0]->Reset();
this->buffers[0]->PushZeros(this->samplerate/400);
this->buffers[1]->Reset();
this->buffers[1]->PushZeros(this->samplerate/200);
}
void HiFi::SetClarity(float value) {
this->gain = value;
}
void HiFi::SetSamplingRate(uint32_t samplerate) {
this->samplerate = samplerate;
Reset();
}

33
src/utils/HiFi.h Normal file
View File

@ -0,0 +1,33 @@
//
// Created by mart on 7/31/21.
//
#pragma once
#include "IIR_NOrder_BW_LH.h"
#include "WaveBuffer_I32.h"
#include "IIR_NOrder_BW_BP.h"
class HiFi {
public:
HiFi();
~HiFi();
void Process(float* samples, uint32_t size);
void Reset();
void SetClarity(float value);
void SetSamplingRate(uint32_t samplerate);
WaveBuffer_I32* buffers[2];
struct {
IIR_NOrder_BW_LH* lowpass;
IIR_NOrder_BW_LH* highpass;
IIR_NOrder_BW_BP* bandpass;
} filters[2];
float gain;
uint32_t samplerate;
};

View File

@ -30,3 +30,10 @@ public:
float b0, b1, a1;
float prevSample;
};
inline float do_filter(IIR_1st* filter, float sample) {
float hist = sample * filter->b1;
sample = filter->prevSample + sample * filter->b0;
filter->prevSample = sample * filter->a1 + hist;
return sample;
}

View File

@ -19,3 +19,20 @@ public:
uint32_t order;
};
inline float do_filter_bplp(IIR_NOrder_BW_BP* filt, float sample) {
for (int idx = 0; idx < filt->order; idx++) {
sample = do_filter(&filt->lowpass[idx], sample);
}
return sample;
}
inline float do_filter_bphp(IIR_NOrder_BW_BP* filt, float sample) {
for (int idx = 0; idx < filt->order; idx++) {
sample = do_filter(&filt->highpass[idx], sample);
}
return sample;
}
inline float do_filter_bp(IIR_NOrder_BW_BP* filt, float sample) {
return do_filter_bphp(filt, do_filter_bplp(filt, sample));
}

View File

@ -18,3 +18,10 @@ public:
IIR_1st* filters;
uint32_t order;
};
inline float do_filter_lh(IIR_NOrder_BW_LH* filt, float sample) {
for (int idx = 0; idx < filt->order; idx++) {
sample = do_filter(&filt->filters[idx], sample);
}
return sample;
}

View File

@ -40,23 +40,15 @@ void PassFilter::Reset() {
this->filters[3]->Mute();
}
#define do_filter(filt, sample) \
for (int idx = 0; idx < (filt)->order; idx++) {\
IIR_1st filter = this->filters[2]->filters[idx];\
float hist = (sample) * filter.b1;\
left = filter.prevSample + (sample) * filter.b0;\
filter.prevSample = (sample) * filter.a1 + hist;\
}
void PassFilter::ProcessFrames(float *buffer, uint32_t size) {
for (int x = 0; x < size; x++) {
float left = buffer[2*x];
float right = buffer[2*x+1];
do_filter(this->filters[2], left)
do_filter(this->filters[0], left)
do_filter(this->filters[3], right)
do_filter(this->filters[1], right)
left = do_filter_lh(this->filters[2], left);
left = do_filter_lh(this->filters[0], left);
right = do_filter_lh(this->filters[3], right);
right = do_filter_lh(this->filters[1], right);
buffer[2*x] = left;
buffer[2*x+1] = right;