ViPERFX_RE/src/viper/effects/ViPERBass.cpp

125 lines
4.5 KiB
C++
Raw Normal View History

#include "ViPERBass.h"
2022-09-19 02:36:53 +02:00
#include "../constants.h"
2022-09-06 17:57:23 +02:00
2022-12-14 02:56:26 +01:00
// Iscle: Verified with the latest version at 13/12/2022
2023-09-03 03:22:29 +02:00
ViPERBass::ViPERBass() : polyphase(2), waveBuffer(2, 4096) {
2022-09-19 02:36:53 +02:00
this->speaker = 60;
2022-12-14 02:56:26 +01:00
this->enable = false;
2022-09-19 02:53:47 +02:00
this->processMode = ProcessMode::NATURAL_BASS;
2022-12-14 02:56:26 +01:00
this->antiPop = 0.0;
2022-09-23 00:12:27 +02:00
this->bassFactor = 0.0;
2022-12-14 02:56:26 +01:00
this->samplingRate = VIPER_DEFAULT_SAMPLING_RATE;
this->samplingRatePeriod = 1.0 / VIPER_DEFAULT_SAMPLING_RATE;
2022-09-19 02:36:53 +02:00
2023-09-03 03:22:29 +02:00
for (auto &biquad : this->biquad) {
biquad.Reset();
biquad.SetLowPassParameter((float) this->speaker, this->samplingRate, 0.53);
}
this->subwoofer.SetBassGain(this->samplingRate, 0.0);
2022-12-14 02:56:26 +01:00
Reset();
2022-09-06 17:57:23 +02:00
}
void ViPERBass::Process(float *samples, uint32_t size) {
2022-12-14 02:56:26 +01:00
if (!this->enable) return;
if (size == 0) return;
2022-09-06 17:57:23 +02:00
2022-12-14 02:56:26 +01:00
// Iscle: TODO: Maybe we could attenuate the effect instead of the entire sample
2022-09-19 02:43:27 +02:00
if (this->antiPop < 1.0) {
2022-09-19 02:36:53 +02:00
for (uint32_t i = 0; i < size * 2; i += 2) {
2022-09-19 02:43:27 +02:00
samples[i] *= this->antiPop;
samples[i + 1] *= this->antiPop;
2022-09-19 02:36:53 +02:00
2022-10-11 00:36:38 +02:00
float x = this->antiPop + this->samplingRatePeriod;
2022-12-14 02:56:26 +01:00
if (x > 1.0) x = 1.0;
2022-09-19 02:43:27 +02:00
this->antiPop = x;
2022-09-19 02:36:53 +02:00
}
}
switch (this->processMode) {
2022-09-19 02:53:47 +02:00
case ProcessMode::NATURAL_BASS: {
2022-09-19 02:36:53 +02:00
for (uint32_t i = 0; i < size * 2; i += 2) {
2023-09-03 03:22:29 +02:00
samples[i] += (float) this->biquad[0].ProcessSample(samples[i]) * this->bassFactor;
samples[i + 1] += (float) this->biquad[1].ProcessSample(samples[i + 1]) * this->bassFactor;
2022-09-19 02:36:53 +02:00
}
break;
}
2022-09-19 02:53:47 +02:00
case ProcessMode::PURE_BASS_PLUS: {
2023-09-03 03:22:29 +02:00
if (this->waveBuffer.PushSamples(samples, size)) {
float *buffer = this->waveBuffer.GetBuffer();
uint32_t bufferOffset = this->waveBuffer.GetBufferOffset();
2022-09-19 02:36:53 +02:00
for (uint32_t i = 0; i < size * 2; i += 2) {
2023-09-03 03:22:29 +02:00
buffer[bufferOffset - size + i] = (float) this->biquad[0].ProcessSample(samples[i]);
buffer[bufferOffset - size + i + 1] = (float) this->biquad[1].ProcessSample(samples[i + 1]);
2022-09-19 02:36:53 +02:00
}
2023-09-03 03:22:29 +02:00
if (this->polyphase.Process(samples, size) == size) {
2022-09-19 02:53:47 +02:00
for (uint32_t i = 0; i < size * 2; i += 2) {
2023-09-03 03:22:29 +02:00
samples[i] += buffer[i] * this->bassFactor;
samples[i + 1] += buffer[i + 1] * this->bassFactor;
2022-09-19 02:36:53 +02:00
}
2023-09-03 03:22:29 +02:00
this->waveBuffer.PopSamples(size, true);
2022-09-19 02:36:53 +02:00
}
}
break;
}
2022-09-19 02:53:47 +02:00
case ProcessMode::SUBWOOFER: {
2023-09-03 03:22:29 +02:00
this->subwoofer.Process(samples, size);
2022-09-19 02:36:53 +02:00
break;
}
}
2022-09-06 17:57:23 +02:00
}
void ViPERBass::Reset() {
2023-09-03 03:22:29 +02:00
this->polyphase.SetSamplingRate(this->samplingRate);
this->polyphase.Reset();
this->waveBuffer.Reset();
this->waveBuffer.PushZeros(this->polyphase.GetLatency());
this->subwoofer.SetBassGain(this->samplingRate, this->bassFactor * 2.5f);
this->biquad[0].SetLowPassParameter((float) this->speaker, this->samplingRate, 0.53);
this->biquad[1].SetLowPassParameter((float) this->speaker, this->samplingRate, 0.53);
2022-10-11 00:36:38 +02:00
this->samplingRatePeriod = 1.0f / (float) this->samplingRate;
2022-09-19 02:43:27 +02:00
this->antiPop = 0.0f;
2022-09-06 17:57:23 +02:00
}
2022-09-16 03:16:58 +02:00
void ViPERBass::SetBassFactor(float bassFactor) {
2022-09-19 02:36:53 +02:00
if (this->bassFactor != bassFactor) {
this->bassFactor = bassFactor;
2023-09-03 03:22:29 +02:00
this->subwoofer.SetBassGain(this->samplingRate, this->bassFactor * 2.5f);
2022-09-16 03:16:58 +02:00
}
2022-09-06 17:57:23 +02:00
}
2022-10-11 00:36:38 +02:00
void ViPERBass::SetEnable(bool enable) {
if (this->enable != enable) {
2022-12-14 02:56:26 +01:00
if (enable) Reset();
2022-10-11 00:36:38 +02:00
this->enable = enable;
}
}
2022-09-19 02:36:53 +02:00
void ViPERBass::SetProcessMode(ProcessMode processMode) {
2022-09-19 02:37:58 +02:00
if (this->processMode != processMode) {
2022-09-19 02:36:53 +02:00
this->processMode = processMode;
2022-12-14 02:56:26 +01:00
Reset();
2022-09-19 02:36:53 +02:00
}
2022-09-06 17:57:23 +02:00
}
void ViPERBass::SetSamplingRate(uint32_t samplingRate) {
2022-09-19 02:36:53 +02:00
if (this->samplingRate != samplingRate) {
this->samplingRate = samplingRate;
2022-10-11 00:36:38 +02:00
this->samplingRatePeriod = 1.0f / (float) samplingRate;
2023-09-03 03:22:29 +02:00
this->polyphase.SetSamplingRate(this->samplingRate);
this->biquad[0].SetLowPassParameter((float) this->speaker, this->samplingRate, 0.53);
this->biquad[1].SetLowPassParameter((float) this->speaker, this->samplingRate, 0.53);
this->subwoofer.SetBassGain(this->samplingRate, this->bassFactor * 2.5f);
2022-09-19 02:36:53 +02:00
}
2022-09-06 17:57:23 +02:00
}
2022-09-19 02:36:53 +02:00
void ViPERBass::SetSpeaker(uint32_t speaker) {
2022-09-16 03:16:58 +02:00
if (this->speaker != speaker) {
this->speaker = speaker;
2023-09-03 03:22:29 +02:00
this->biquad[0].SetLowPassParameter((float) this->speaker, this->samplingRate, 0.53);
this->biquad[1].SetLowPassParameter((float) this->speaker, this->samplingRate, 0.53);
2022-09-16 03:16:58 +02:00
}
2022-09-06 17:57:23 +02:00
}