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 //
//////////////////////////////////
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 y = 0.0f;
@ -211,3 +211,56 @@ float32_t softSaturate(float32_t in, float32_t threshold)
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 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
{
typedef T Tail;
enum
{
length = l
length = _length
};
};

@ -8,7 +8,10 @@
ShimmerReverb::ShimmerReverb(float32_t 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_2, 0.3f);

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

@ -3,7 +3,9 @@
#include <cmath>
Tube::Tube(float32_t samplingRate) :
FXElement(samplingRate)
FXElement(samplingRate),
overdrive_(0.0f),
saturation_(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)
{
outL = softSaturate(inL, this->threshold_);
outR = softSaturate(inR, this->threshold_);
outL = softSaturator2(inL, this->saturation_);
outR = softSaturator2(inR, this->saturation_);
}
void Tube::setOverdrive(float32_t overdrive)
{
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

@ -35,5 +35,5 @@ public:
private:
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
$(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
../fx_chorus.cpp: ../fx_engine.hpp
touch ../fx_chorus.cpp
fx_chorus.o: ../fx_chorus.cpp
$(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
fx_phaser.o: ../fx_phaser.cpp
$(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
../fx_orbitone.cpp: ../fx_engine.hpp
touch ../fx_orbitone.cpp
fx_orbitone.o: ../fx_orbitone.cpp
$(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
@ -66,8 +72,8 @@ fx_flanger.o: ../fx_flanger.cpp
fx_delay.o: ../fx_delay.cpp
$(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
../fx_shimmer_reverb3.cpp: ../fx_engine.hpp
touch ../fx_shimmer_reverb3.cpp
../fx_shimmer_reverb.cpp: ../fx_engine.hpp
touch ../fx_shimmer_reverb.cpp
fx_shimmer_reverb.o: ../fx_shimmer_reverb.cpp
$(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;
FXRack *rack = new FXRack(44100.0f);
@ -128,59 +141,42 @@ void testFXRack(unsigned& step)
rack->setEnable(true);
rack->setWetLevel(1.0f);
rack->getTube()->setEnable(false);
rack->getTube()->setEnable(Active(fxSwitch, FXSitch::Tube));
rack->getTube()->setWetLevel(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()->setRate(0.4f);
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()->setRate(0.4f);
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()->setLeftDelayTime(0.075f);
rack->getDelay()->setLeftDelayTime(0.05f);
rack->getDelay()->setFeedbak(0.5f);
rack->getShimmerReverb()->setEnable(false);
rack->getShimmerReverb()->setEnable(Active(fxSwitch, FXSitch::Shimmer));
rack->getShimmerReverb()->setWetLevel(0.7f);
rack->getShimmerReverb()->setInputGain(0.45f);
rack->getShimmerReverb()->setTime(0.89f);
rack->getShimmerReverb()->setDiffusion(0.75f);
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 size;
@ -195,7 +191,7 @@ void testFXRack(unsigned& step)
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[] sampleOutR;
@ -211,10 +207,16 @@ int main()
{
unsigned step = 0;
testLFO(step);
// testLFO(step);
// testFlutter(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;
}

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

Loading…
Cancel
Save