Fixing the Tube effect so it has more presence

pull/409/head
abscisys 2 years ago
parent ab4f23805e
commit f2006bd880
  1. 55
      src/fx_components.cpp
  2. 5
      src/fx_components.h
  3. 4
      src/fx_engine.hpp
  4. 5
      src/fx_shimmer_reverb.cpp
  5. 2
      src/fx_shimmer_reverb.h
  6. 10
      src/fx_tube.cpp
  7. 2
      src/fx_tube.h
  8. 10
      src/test/Makefile
  9. 68
      src/test/fxrack_test.cpp
  10. 2
      src/test/waveout.cpp

@ -189,7 +189,7 @@ float32_t JitterGenerator::process()
////////////////////////////////// //////////////////////////////////
// softSaturate implemlentation // // softSaturate implemlentation //
////////////////////////////////// //////////////////////////////////
float32_t softSaturate(float32_t in, float32_t threshold) float32_t softSaturator1(float32_t in, float32_t threshold)
{ {
float32_t x = std::abs(in); float32_t x = std::abs(in);
float32_t y = 0.0f; float32_t y = 0.0f;
@ -211,3 +211,56 @@ float32_t softSaturate(float32_t in, float32_t threshold)
return (in < 0.0f) ? -y : y; return (in < 0.0f) ? -y : y;
} }
float32_t softSaturator2(float32_t input, float32_t saturation)
{
constexpr static float kTubeCurve = 4.0f;
constexpr static float kTubeBias = 0.5f;
float absInput = std::abs(input);
float output = 0.0f;
if(absInput > kTubeBias)
{
output = (kTubeCurve + saturation) * (absInput - kTubeBias) / (1.0f - kTubeBias);
}
else
{
output = (kTubeCurve + saturation) * absInput / (1.0f + kTubeCurve * absInput);
}
// Clip the output if overdrive is set to 1
// output = std::min(1.0f, output);
if(output > 1.0f)
{
output = 1.0f;
}
else
{
output -= output * output * output / 3.0f;
}
if(input < 0.0f)
{
output = -output;
}
return output;
}
float32_t waveFolder(float32_t input, float32_t bias)
{
bias = 0.5 + (2.0f - bias) / 4.0f;
float32_t output = std::abs(input) / bias;
if(output > 1.0f)
{
output = 2.0f - output;
}
if(input < 0.0f)
{
output = -output;
}
return output;
}

@ -257,4 +257,7 @@ private:
float32_t phase_increment_; float32_t phase_increment_;
}; };
float32_t softSaturate(float32_t in, float32_t threshold); float32_t softSaturator1(float32_t in, float32_t threshold);
float32_t softSaturator2(float32_t in, float32_t saturation);
float32_t waveFolder(float32_t input, float32_t bias);

@ -99,13 +99,13 @@ public:
{ {
}; };
template <int32_t l, typename T = Empty> template <int32_t _length, typename T = Empty>
struct Reserve struct Reserve
{ {
typedef T Tail; typedef T Tail;
enum enum
{ {
length = l length = _length
}; };
}; };

@ -8,7 +8,10 @@
ShimmerReverb::ShimmerReverb(float32_t sampling_rate) : ShimmerReverb::ShimmerReverb(float32_t sampling_rate) :
FXElement(sampling_rate), FXElement(sampling_rate),
engine_(sampling_rate) engine_(sampling_rate),
input_gain_(-1.0f),
diffusion_(-1.0f),
lp_(-1.0f)
{ {
this->engine_.setLFOFrequency(LFO_1, 0.5f); this->engine_.setLFOFrequency(LFO_1, 0.5f);
this->engine_.setLFOFrequency(LFO_2, 0.3f); this->engine_.setLFOFrequency(LFO_2, 0.3f);

@ -47,7 +47,7 @@ public:
float32_t getLP() const; float32_t getLP() const;
private: private:
typedef FxEngine<16384, FORMAT_16_BIT> Engine; typedef FxEngine<16384, FORMAT_16_BIT, true> Engine;
Engine engine_; Engine engine_;
float32_t input_gain_; float32_t input_gain_;

@ -3,7 +3,9 @@
#include <cmath> #include <cmath>
Tube::Tube(float32_t samplingRate) : Tube::Tube(float32_t samplingRate) :
FXElement(samplingRate) FXElement(samplingRate),
overdrive_(0.0f),
saturation_(0.0f)
{ {
this->setOverdrive(0.0f); this->setOverdrive(0.0f);
} }
@ -14,14 +16,14 @@ Tube::~Tube()
void Tube::processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR) void Tube::processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR)
{ {
outL = softSaturate(inL, this->threshold_); outL = softSaturator2(inL, this->saturation_);
outR = softSaturate(inR, this->threshold_); outR = softSaturator2(inR, this->saturation_);
} }
void Tube::setOverdrive(float32_t overdrive) void Tube::setOverdrive(float32_t overdrive)
{ {
this->overdrive_ = constrain(overdrive, 0.0f, 1.0f); this->overdrive_ = constrain(overdrive, 0.0f, 1.0f);
this->threshold_ = 1.0f - this->overdrive_; this->saturation_ = 2.0f * this->overdrive_;
} }
float32_t Tube::getOverdrive() const float32_t Tube::getOverdrive() const

@ -35,5 +35,5 @@ public:
private: private:
float32_t overdrive_; float32_t overdrive_;
float32_t threshold_; float32_t saturation_;
}; };

@ -51,12 +51,18 @@ fx_svf.o: ../fx_svf.cpp
fx_tube.o: ../fx_tube.cpp fx_tube.o: ../fx_tube.cpp
$(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@ $(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
../fx_chorus.cpp: ../fx_engine.hpp
touch ../fx_chorus.cpp
fx_chorus.o: ../fx_chorus.cpp fx_chorus.o: ../fx_chorus.cpp
$(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@ $(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
fx_phaser.o: ../fx_phaser.cpp fx_phaser.o: ../fx_phaser.cpp
$(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@ $(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
../fx_orbitone.cpp: ../fx_engine.hpp
touch ../fx_orbitone.cpp
fx_orbitone.o: ../fx_orbitone.cpp fx_orbitone.o: ../fx_orbitone.cpp
$(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@ $(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
@ -66,8 +72,8 @@ fx_flanger.o: ../fx_flanger.cpp
fx_delay.o: ../fx_delay.cpp fx_delay.o: ../fx_delay.cpp
$(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@ $(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
../fx_shimmer_reverb3.cpp: ../fx_engine.hpp ../fx_shimmer_reverb.cpp: ../fx_engine.hpp
touch ../fx_shimmer_reverb3.cpp touch ../fx_shimmer_reverb.cpp
fx_shimmer_reverb.o: ../fx_shimmer_reverb.cpp fx_shimmer_reverb.o: ../fx_shimmer_reverb.cpp
$(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@ $(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@

@ -119,7 +119,20 @@ void testSVF(unsigned& step)
} }
} }
void testFXRack(unsigned& step) enum FXSitch
{
Tube = 1 << 0,
Chorus = 1 << 1,
Phaser = 1 << 2,
Orbitone = 1 << 3,
Flanger = 1 << 4,
Delay = 1 << 5,
Shimmer = 1 << 6
};
#define Active(fxSwitch, FxID) (fxSwitch & FxID) == FxID
void testFXRack(unsigned& step, unsigned fxSwitch)
{ {
cout << "Step #" << (++step) << ": Intanciation FXRack" << endl; cout << "Step #" << (++step) << ": Intanciation FXRack" << endl;
FXRack *rack = new FXRack(44100.0f); FXRack *rack = new FXRack(44100.0f);
@ -128,59 +141,42 @@ void testFXRack(unsigned& step)
rack->setEnable(true); rack->setEnable(true);
rack->setWetLevel(1.0f); rack->setWetLevel(1.0f);
rack->getTube()->setEnable(false); rack->getTube()->setEnable(Active(fxSwitch, FXSitch::Tube));
rack->getTube()->setWetLevel(1.0f); rack->getTube()->setWetLevel(1.0f);
rack->getTube()->setOverdrive(1.0f); rack->getTube()->setOverdrive(1.0f);
rack->getChorus()->setEnable(false); rack->getChorus()->setEnable(Active(fxSwitch, FXSitch::Chorus));
rack->getChorus()->setWetLevel(0.5f); rack->getChorus()->setWetLevel(0.5f);
rack->getChorus()->setRate(0.4f); rack->getChorus()->setRate(0.4f);
rack->getChorus()->setDepth(0.5f); rack->getChorus()->setDepth(0.5f);
rack->getPhaser()->setEnable(false); rack->getPhaser()->setEnable(Active(fxSwitch, FXSitch::Phaser));
rack->getOrbitone()->setEnable(true); rack->getOrbitone()->setEnable(Active(fxSwitch, FXSitch::Orbitone));
rack->getOrbitone()->setWetLevel(0.8f); rack->getOrbitone()->setWetLevel(0.8f);
rack->getOrbitone()->setRate(0.4f); rack->getOrbitone()->setRate(0.4f);
rack->getOrbitone()->setDepth(0.5f); rack->getOrbitone()->setDepth(0.5f);
rack->getFlanger()->setEnable(false); rack->getFlanger()->setEnable(Active(fxSwitch, FXSitch::Flanger));
rack->getFlanger()->setWetLevel(0.5f);
rack->getFlanger()->setDelayTime(0.8f);
rack->getFlanger()->setFrequency(0.25f);
rack->getFlanger()->setDepth(0.8f);
rack->getFlanger()->setFeedback(0.75f);
rack->getDelay()->setEnable(false); rack->getDelay()->setEnable(Active(fxSwitch, FXSitch::Delay));
rack->getDelay()->setWetLevel(0.6f); rack->getDelay()->setWetLevel(0.6f);
rack->getDelay()->setLeftDelayTime(0.075f); rack->getDelay()->setLeftDelayTime(0.075f);
rack->getDelay()->setLeftDelayTime(0.05f); rack->getDelay()->setLeftDelayTime(0.05f);
rack->getDelay()->setFeedbak(0.5f); rack->getDelay()->setFeedbak(0.5f);
rack->getShimmerReverb()->setEnable(false); rack->getShimmerReverb()->setEnable(Active(fxSwitch, FXSitch::Shimmer));
rack->getShimmerReverb()->setWetLevel(0.7f); rack->getShimmerReverb()->setWetLevel(0.7f);
rack->getShimmerReverb()->setInputGain(0.45f); rack->getShimmerReverb()->setInputGain(0.45f);
rack->getShimmerReverb()->setTime(0.89f); rack->getShimmerReverb()->setTime(0.89f);
rack->getShimmerReverb()->setDiffusion(0.75f); rack->getShimmerReverb()->setDiffusion(0.75f);
rack->getShimmerReverb()->setLP(0.8f); rack->getShimmerReverb()->setLP(0.8f);
const unsigned nSamples = 1;
float32_t inSamples[2][nSamples];
float32_t outSamples[2][nSamples];
for (unsigned i = 0; i < nSamples; ++i)
{
inSamples[0][i] = dist(gen);
inSamples[1][i] = dist(gen);
}
memset(outSamples[0], 0, nSamples * sizeof(float32_t));
memset(outSamples[1], 0, nSamples * sizeof(float32_t));
cout << "Step #" << (++step) << ": Run test" << endl;
rack->process(inSamples[0], inSamples[1], outSamples[0], outSamples[1], nSamples);
cout << "Step #" << (++step) << ": Render results" << endl;
for (unsigned i = 0; i < nSamples; ++i)
{
std::cout << "#" << i << " " << inSamples[0][i] << " --> " << outSamples[0][i] << " = " << ((outSamples[0][i] - inSamples[0][i]) * 100.0f / inSamples[0][i]) << "%" << std::endl;
}
unsigned nbRepeats = 4; unsigned nbRepeats = 4;
unsigned size; unsigned size;
@ -195,7 +191,7 @@ void testFXRack(unsigned& step)
rack->process(samples[0], samples[1], sampleOutL + i * size, sampleOutR + i * size, size); rack->process(samples[0], samples[1], sampleOutL + i * size, sampleOutR + i * size, size);
} }
saveWaveFile("result.wav", sampleOutL, sampleOutR, nbRepeats * size, 44100, 16); saveWaveFile("result.wav", sampleOutL, sampleOutR, nbRepeats * size, static_cast<unsigned>(FS), 16);
delete[] sampleOutL; delete[] sampleOutL;
delete[] sampleOutR; delete[] sampleOutR;
@ -211,10 +207,16 @@ int main()
{ {
unsigned step = 0; unsigned step = 0;
testLFO(step); // testLFO(step);
// testFlutter(step); // testFlutter(step);
// testSVF(step); // testSVF(step);
// testFXRack(step); testFXRack(step, FXSitch::Tube);
// testFXRack(step, FXSitch::Flanger); // to be fixed -> feedback deletes FX effect
// testFXRack(step, FXSitch::Phaser); // to be fixed -> far too load but saturation is interested
// testFXRack(step, FXSitch::Chorus);
// testFXRack(step, FXSitch::Orbitone);
// testFXRack(step, FXSitch::Delay);
// testFXRack(step, FXSitch::Shimmer);
return 0; return 0;
} }

@ -82,4 +82,6 @@ void saveWaveFile(const std::string& fileName,
std::cerr << "Error: unsupported bit depth: " << bitsPerSample << std::endl; std::cerr << "Error: unsupported bit depth: " << bitsPerSample << std::endl;
return; return;
} }
file.close();
} }

Loading…
Cancel
Save