harmonics, analogx and spectrumextend

This commit is contained in:
Martijn 2021-07-30 16:54:59 +02:00
parent 46dac9bf20
commit 4fb9cee285
7 changed files with 331 additions and 0 deletions

View File

@ -19,9 +19,11 @@ set(FILES
src/viper.cpp
# Effects
src/effects/AnalogX.cpp
src/effects/Cure.cpp
src/effects/DynamicSystem.cpp
src/effects/Reverberation.cpp
src/effects/SpectrumExtend.cpp
src/effects/TubeSimulator.cpp
# Utils
@ -32,6 +34,7 @@ set(FILES
src/utils/DepthSurround.cpp
src/utils/DynamicBass.cpp
src/utils/FixedBiquad.cpp
src/utils/Harmonic.cpp
src/utils/HighShelf.cpp
src/utils/IIR_1st.cpp
src/utils/IIR_NOrder_BW_BP.cpp

90
src/effects/AnalogX.cpp Normal file
View File

@ -0,0 +1,90 @@
//
// Created by mart on 7/30/21.
//
#include <cstring>
#include "AnalogX.h"
#include "../constants.h"
static float ANALOGX_HARMONICS[10] = {
0.01f,
0.02f,
0.0001f,
0.001f,
0.f,
0.f,
0.f,
0.f,
0.f,
0.f
};
AnalogX::AnalogX() {
this->samplerate = DEFAULT_SAMPLERATE;
this->processingModel = 0;
this->enabled = false;
Reset();
}
void AnalogX::Process(float *samples, uint32_t size) {
for (int i = 0; i < 2*size; i++) {
float sample = samples[i];
int index = i % 2;
float tmp = this->highpass[index].ProcessSample(sample);
tmp = this->harmonics[index].Process(tmp);
tmp = this->lowpass[index].ProcessSample(sample + tmp * this->gain);
tmp = this->peak->ProcessSample(tmp * 0.8f);
samples[i] = tmp;
}
if (this->freqRange < this->samplerate / 4) {
this->freqRange += size;
memset(samples, 0, 2 * size * sizeof(float));
}
}
void AnalogX::Reset() {
this->highpass[0].RefreshFilter(FilterType::HIGHPASS, 0.f, 240.f, (float)this->samplerate, 0.717, false);
this->highpass[1].RefreshFilter(FilterType::HIGHPASS, 0.f, 240.f, (float)this->samplerate, 0.717, false);
this->peak[0].RefreshFilter(FilterType::PEAK, 0.58f, 633.f, (float)this->samplerate, 6.28, true);
this->peak[1].RefreshFilter(FilterType::PEAK, 0.58f, 633.f, (float)this->samplerate, 6.28, true);
this->harmonics[0].Reset();
this->harmonics[1].Reset();
if (this->processingModel == 0) {
this->harmonics[0].SetHarmonics(ANALOGX_HARMONICS);
this->harmonics[1].SetHarmonics(ANALOGX_HARMONICS);
this->gain = 0.6f;
this->lowpass[0].RefreshFilter(FilterType::LOWPASS, 0.0, 18233.f, (float)this->samplerate, 0.717f, false);
this->lowpass[1].RefreshFilter(FilterType::LOWPASS, 0.0, 18233.f, (float)this->samplerate, 0.717f, false);
} else if (this->processingModel == 1) {
this->harmonics[0].SetHarmonics(ANALOGX_HARMONICS);
this->harmonics[1].SetHarmonics(ANALOGX_HARMONICS);
this->gain = 1.2f;
this->lowpass[0].RefreshFilter(FilterType::LOWPASS, 0.0, 19650.f, (float)this->samplerate, 0.717f, false);
this->lowpass[1].RefreshFilter(FilterType::LOWPASS, 0.0, 19650.f, (float)this->samplerate, 0.717f, false);
} else if (this->processingModel == 2) {
this->harmonics[0].SetHarmonics(ANALOGX_HARMONICS);
this->harmonics[1].SetHarmonics(ANALOGX_HARMONICS);
this->gain = 2.4f;
this->lowpass[0].RefreshFilter(FilterType::LOWPASS, 0.0, 16307.f, (float)this->samplerate, 0.717f, false);
this->lowpass[1].RefreshFilter(FilterType::LOWPASS, 0.0, 16307.f, (float)this->samplerate, 0.717f, false);
}
this->freqRange = 0;
}
void AnalogX::SetProcessingModel(int model) {
this->processingModel = model;
Reset();
}
void AnalogX::SetSamplingRate(uint32_t samplerate) {
this->samplerate = samplerate;
Reset();
}

33
src/effects/AnalogX.h Normal file
View File

@ -0,0 +1,33 @@
//
// Created by mart on 7/30/21.
//
#pragma once
#include "../utils/Harmonic.h"
#include "../utils/MultiBiquad.h"
class AnalogX {
public:
AnalogX();
void Process(float* samples, uint32_t size);
void Reset();
void SetProcessingModel(int model);
void SetSamplingRate(uint32_t samplerate);
MultiBiquad highpass[2];
Harmonic harmonics[2];
MultiBiquad lowpass[2];
MultiBiquad peak[2];
float gain;
uint32_t freqRange;
int processingModel;
uint32_t samplerate;
bool enabled;
};

View File

@ -0,0 +1,80 @@
//
// Created by mart on 7/30/21.
//
#include "SpectrumExtend.h"
#include "../constants.h"
static float SPECTRUM_HARMONICS[10] = {
0.02f,
0.f,
0.02f,
0.f,
0.02f,
0.f,
0.02f,
0.f,
0.02f,
0.f,
};
SpectrumExtend::SpectrumExtend() {
this->samplerate = DEFAULT_SAMPLERATE;
this->referenceFreq = 7600;
this->enabled = false;
this->exciter = 0.f;
Reset();
}
SpectrumExtend::~SpectrumExtend() {
// empty?
}
void SpectrumExtend::Process(float *samples, uint32_t size) {
for (int i = 0; i < size * 2; i++) {
float sample = samples[i];
int index = i % 2;
float tmp = this->highpass[index].ProcessSample(sample);
tmp = this->harmonics[index].Process(tmp);
tmp = this->lowpass[index].ProcessSample(tmp * this->exciter);
samples[i] = samples[i] + tmp;
}
}
void SpectrumExtend::Reset() {
this->highpass[0].RefreshFilter(FilterType::HIGHPASS, 0.0, (float)this->referenceFreq, (float)this->samplerate, 0.717, false);
this->highpass[1].RefreshFilter(FilterType::HIGHPASS, 0.0, (float)this->referenceFreq, (float)this->samplerate, 0.717, false);
this->lowpass[0].RefreshFilter(FilterType::LOWPASS, 0.0, (float)this->referenceFreq / 2.f - 2000.f, (float)this->referenceFreq, 0.717, false);
this->lowpass[1].RefreshFilter(FilterType::LOWPASS, 0.0, (float)this->referenceFreq / 2.f - 2000.f, (float)this->referenceFreq, 0.717, false);
this->harmonics[0].Reset();
this->harmonics[1].Reset();
this->harmonics[0].SetHarmonics(SPECTRUM_HARMONICS);
this->harmonics[1].SetHarmonics(SPECTRUM_HARMONICS);
}
void SpectrumExtend::SetEnable(bool enable) {
this->enabled = enable;
}
void SpectrumExtend::SetExciter(float value) {
this->exciter = value;
}
void SpectrumExtend::SetReferenceFrequency(uint32_t freq) {
if (this->samplerate / 2 - 100 < freq) {
freq = this->samplerate / 2 - 100;
}
this->referenceFreq = freq;
Reset();
}
void SpectrumExtend::SetSamplingRate(uint32_t samplerate) {
this->samplerate = samplerate;
if (this->samplerate / 2 - 100 < this->referenceFreq) {
this->referenceFreq = this->samplerate / 2 - 100;
}
Reset();
}

View File

@ -0,0 +1,32 @@
//
// Created by mart on 7/30/21.
//
#pragma once
#include "../utils/Harmonic.h"
#include "../utils/MultiBiquad.h"
class SpectrumExtend {
public:
SpectrumExtend();
~SpectrumExtend();
void Process(float* samples, uint32_t size);
void Reset();
void SetEnable(bool enable);
void SetExciter(float value);
void SetReferenceFrequency(uint32_t freq);
void SetSamplingRate(uint32_t samplerate);
MultiBiquad highpass[2];
MultiBiquad lowpass[2];
Harmonic harmonics[2];
bool enabled;
uint32_t samplerate;
uint32_t referenceFreq;
float exciter;
};

65
src/utils/Harmonic.cpp Normal file
View File

@ -0,0 +1,65 @@
//
// Created by mart on 7/30/21.
//
#include "Harmonic.h"
static float HARMONIC_DEFAULT[10] = {
1.f,
0.f,
0.f,
0.f,
0.f,
0.f,
0.f,
0.f,
0.f,
0.f,
};
Harmonic::Harmonic() {
UpdateCoeffs(HARMONIC_DEFAULT);
Reset();
}
Harmonic::~Harmonic() {
}
float Harmonic::Process(float sample) {
float prevLast = this->lastProcessed;
this->lastProcessed = (
sample * this->coeffs[0] +
sample * this->coeffs[1] +
sample * this->coeffs[2] +
sample * this->coeffs[3] +
sample * this->coeffs[4] +
sample * this->coeffs[5] +
sample * this->coeffs[6] +
sample * this->coeffs[7] +
sample * this->coeffs[8] +
sample * this->coeffs[9] +
sample * this->coeffs[10]
);
this->prevOut = this->lastProcessed + this->prevOut * 0.999f - prevLast;
if (this->sampleCounter < this->buildup) {
this->sampleCounter++;
return 0;
}
return this->prevOut;
}
void Harmonic::Reset() {
this->lastProcessed = 0.f;
this->prevOut = 0.f;
this->sampleCounter = 0.f;
}
void Harmonic::SetHarmonics(float *coeffs) {
UpdateCoeffs(coeffs);
Reset();
}
void Harmonic::UpdateCoeffs(float *coeffs) {
// TODO
}

28
src/utils/Harmonic.h Normal file
View File

@ -0,0 +1,28 @@
//
// Created by mart on 7/30/21.
//
#pragma once
#include <cstdint>
class Harmonic {
public:
Harmonic();
~Harmonic();
float Process(float sample);
void Reset();
void SetHarmonics(float* coeffs);
void UpdateCoeffs(float* coeffs);
float coeffs[11];
float lastProcessed;
float prevOut;
int buildup;
int sampleCounter;
};