SpeakerCorrection and Subwoofer

This commit is contained in:
Martmists 2021-07-30 21:51:26 +02:00
parent 4fb9cee285
commit 7b60aaeecd
7 changed files with 140 additions and 0 deletions

1
.gitignore vendored
View File

@ -4,6 +4,7 @@
# User-specific stuff # User-specific stuff
.idea/ .idea/
.cmake/
.ninja_deps .ninja_deps
.ninja_log .ninja_log
build.ninja build.ninja

View File

@ -23,6 +23,7 @@ set(FILES
src/effects/Cure.cpp src/effects/Cure.cpp
src/effects/DynamicSystem.cpp src/effects/DynamicSystem.cpp
src/effects/Reverberation.cpp src/effects/Reverberation.cpp
src/effects/SpeakerCorrection.cpp
src/effects/SpectrumExtend.cpp src/effects/SpectrumExtend.cpp
src/effects/TubeSimulator.cpp src/effects/TubeSimulator.cpp
@ -43,6 +44,7 @@ set(FILES
src/utils/NoiseSharpening.cpp src/utils/NoiseSharpening.cpp
src/utils/PassFilter.cpp src/utils/PassFilter.cpp
src/utils/PolesFilter.cpp src/utils/PolesFilter.cpp
src/utils/Subwoofer.cpp
src/utils/TimeConstDelay.cpp src/utils/TimeConstDelay.cpp
) )

View File

@ -13,6 +13,7 @@ To view the progress, see [Issue #2](https://github.com/AndroidAudioMods/ViPERFX
# CLion # CLion
Make sure to install `ninja`
In CLion, make sure to set the following custom arguments: `-DCMAKE_TOOLCHAIN_FILE=<NDKROOT>/build/cmake/android.toolchain.cmake -DANDROID_ABI=<ABI> -G Ninja` In CLion, make sure to set the following custom arguments: `-DCMAKE_TOOLCHAIN_FILE=<NDKROOT>/build/cmake/android.toolchain.cmake -DANDROID_ABI=<ABI> -G Ninja`
Then you can build the project with `ninja` instead of `make` Then you can build the project with `ninja` instead of `make`

View File

@ -0,0 +1,47 @@
//
// Created by mart on 7/30/21.
//
#include "SpeakerCorrection.h"
#include "../constants.h"
SpeakerCorrection::SpeakerCorrection() {
this->samplerate = DEFAULT_SAMPLERATE;
this->enabled = false;
Reset();
}
void SpeakerCorrection::Process(float *samples, uint32_t size) {
for (int i = 0; i < size * 2; i++) {
float sample = samples[i];
int index = i % 2;
sample = this->lowpass[index].ProcessSample(sample);
sample = this->highpass[index].ProcessSample(sample);
float tmp = sample / 2.f;
samples[i] = tmp + this->bandpass[index].ProcessSample(tmp);
}
}
void SpeakerCorrection::Reset() {
this->lowpass[0].Reset();
this->lowpass[1].Reset();
this->bandpass[0].Reset();
this->bandpass[1].Reset();
this->highpass[0].RefreshFilter(FilterType::HIGHPASS, 0.f, 80.f, (float)this->samplerate, 1.f, false);
this->highpass[1].RefreshFilter(FilterType::HIGHPASS, 0.f, 80.f, (float)this->samplerate, 1.f, false);
this->lowpass[0].SetLowPassParameter(13500.f, this->samplerate, 1.0);
this->lowpass[1].SetLowPassParameter(13500.f, this->samplerate, 1.0);
this->bandpass[0].SetBandPassParameter(420.f, this->samplerate, 3.88f);
this->bandpass[1].SetBandPassParameter(420.f, this->samplerate, 3.88f);
}
void SpeakerCorrection::SetEnable(bool enabled) {
this->enabled = enabled;
Reset();
}
void SpeakerCorrection::SetSamplingRate(uint32_t samplerate) {
this->samplerate = samplerate;
Reset();
}

View File

@ -0,0 +1,25 @@
//
// Created by mart on 7/30/21.
//
#pragma once
#include "../utils/MultiBiquad.h"
#include "../utils/FixedBiquad.h"
class SpeakerCorrection {
public:
SpeakerCorrection();
void Process(float* samples, uint32_t size);
void Reset();
void SetEnable(bool enabled);
void SetSamplingRate(uint32_t samplerate);
uint32_t samplerate;
bool enabled;
MultiBiquad highpass[2];
FixedBiquad lowpass[2];
FixedBiquad bandpass[2];
};

40
src/utils/Subwoofer.cpp Normal file
View File

@ -0,0 +1,40 @@
//
// Created by mart on 7/30/21.
//
#include "Subwoofer.h"
#include "../constants.h"
#include <cmath>
Subwoofer::Subwoofer() {
float samplerate = (float)DEFAULT_SAMPLERATE;
this->peak[0].RefreshFilter(FilterType::PEAK, 0.f, 37.f, samplerate, 1.f, false);
this->peak[1].RefreshFilter(FilterType::PEAK, 0.f, 37.f, samplerate, 1.f, false);
this->peakLow[0].RefreshFilter(FilterType::PEAK, 0.f, 75.f, samplerate, 1.f, false);
this->peakLow[1].RefreshFilter(FilterType::PEAK, 0.f, 75.f, samplerate, 1.f, false);
this->lowpass[0].RefreshFilter(FilterType::LOWPASS, 0.f, 200.f, samplerate, 1.f, false);
this->lowpass[1].RefreshFilter(FilterType::LOWPASS, 0.f, 200.f, samplerate, 1.f, false);
}
void Subwoofer::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->peak[index].ProcessSample(sample);
tmp = this->peakLow[index].ProcessSample(tmp);
tmp = this->lowpass[index].ProcessSample(tmp - sample);
samples[i] = (sample / 2.f) + (tmp * 0.6f);
}
}
void Subwoofer::SetBassGain(uint32_t samplerate, float gainDb) {
float gain = 20.f * log10f(gainDb);
float gainLower = 20.f * log10f(gainDb / 8.f);
this->peak[0].RefreshFilter(FilterType::PEAK, gain, 44.f, (float)samplerate, 0.75, true);
this->peak[1].RefreshFilter(FilterType::PEAK, gain, 44.f, (float)samplerate, 0.75, true);
this->peakLow[0].RefreshFilter(FilterType::PEAK, gainLower, 80.f, (float)samplerate, 0.2, true);
this->peakLow[1].RefreshFilter(FilterType::PEAK, gainLower, 80.f, (float)samplerate, 0.2, true);
this->lowpass[0].RefreshFilter(FilterType::LOWPASS, 0.f, 380.f, (float)samplerate, 0.6, false);
this->lowpass[1].RefreshFilter(FilterType::LOWPASS, 0.f, 380.f, (float)samplerate, 0.6, false);
}

24
src/utils/Subwoofer.h Normal file
View File

@ -0,0 +1,24 @@
//
// Created by mart on 7/30/21.
//
#pragma once
#include <cstdint>
#include "MultiBiquad.h"
class Subwoofer {
public:
Subwoofer();
void Process(float* samples, uint32_t size);
void SetBassGain(uint32_t samplerate, float gainDb);
MultiBiquad peak[2];
MultiBiquad peakLow[2];
MultiBiquad lowpass[2];
};