AnalogTapeModel

Physical modelling signal processing for analog tape recording
Log | Files | Refs | Submodules | README | LICENSE

ToneControl.cpp (4518B)


      1 #include "ToneControl.h"
      2 
      3 namespace
      4 {
      5 constexpr double slewTime = 0.05;
      6 constexpr float transFreq = 500.0f;
      7 } // namespace
      8 
      9 ToneStage::ToneStage() = default;
     10 
     11 void ToneStage::prepare (double sampleRate, int numChannels)
     12 {
     13     fs = (float) sampleRate;
     14 
     15     tone.resize ((size_t) numChannels);
     16     lowGain.resize ((size_t) numChannels);
     17     highGain.resize ((size_t) numChannels);
     18     tFreq.resize ((size_t) numChannels);
     19 
     20     for (size_t ch = 0; ch < (size_t) numChannels; ++ch)
     21     {
     22         auto resetSmoothValue = [sampleRate] (SmoothGain& value, float startValue)
     23         {
     24             value.reset (sampleRate, slewTime);
     25             value.setCurrentAndTargetValue (startValue);
     26         };
     27 
     28         resetSmoothValue (lowGain[ch], 1.0f);
     29         resetSmoothValue (highGain[ch], 1.0f);
     30         resetSmoothValue (tFreq[ch], transFreq);
     31 
     32         tone[ch].reset();
     33         tone[ch].calcCoefs (lowGain[ch].getTargetValue(), highGain[ch].getTargetValue(), tFreq[ch].getTargetValue(), fs);
     34     }
     35 }
     36 
     37 void setSmoothValues (std::vector<SmoothGain>& values, float newValue)
     38 {
     39     if (newValue == values[0].getTargetValue())
     40         return;
     41 
     42     for (auto& smoothedVal : values)
     43         smoothedVal.setTargetValue (newValue);
     44 }
     45 
     46 void ToneStage::setLowGain (float lowGainDB) { setSmoothValues (lowGain, Decibels::decibelsToGain (lowGainDB)); }
     47 void ToneStage::setHighGain (float highGainDB) { setSmoothValues (highGain, Decibels::decibelsToGain (highGainDB)); }
     48 void ToneStage::setTransFreq (float newTFreq) { setSmoothValues (tFreq, newTFreq); }
     49 
     50 void ToneStage::processBlock (AudioBuffer<float>& buffer)
     51 {
     52     const auto numChannels = buffer.getNumChannels();
     53     const auto numSamples = buffer.getNumSamples();
     54 
     55     for (size_t ch = 0; ch < (size_t) numChannels; ++ch)
     56     {
     57         auto* data = buffer.getWritePointer ((int) ch);
     58         if (lowGain[ch].isSmoothing() || highGain[ch].isSmoothing() || tFreq[ch].isSmoothing())
     59         {
     60             for (int n = 0; n < numSamples; ++n)
     61             {
     62                 tone[ch].calcCoefs (lowGain[ch].getNextValue(), highGain[ch].getNextValue(), tFreq[ch].getNextValue(), fs);
     63                 data[n] = tone[ch].processSample (data[n]);
     64             }
     65         }
     66         else
     67         {
     68             tone[ch].processBlock (data, numSamples);
     69         }
     70     }
     71 }
     72 
     73 //===================================================
     74 ToneControl::ToneControl (AudioProcessorValueTreeState& vts)
     75 {
     76     using namespace chowdsp::ParamUtils;
     77     loadParameterPointer (bassParam, vts, "h_bass");
     78     loadParameterPointer (trebleParam, vts, "h_treble");
     79     loadParameterPointer (tFreqParam, vts, "h_tfreq");
     80     onOffParam = vts.getRawParameterValue ("tone_onoff");
     81 }
     82 
     83 void ToneControl::createParameterLayout (std::vector<std::unique_ptr<RangedAudioParameter>>& params)
     84 {
     85     NormalisableRange freqRange { 100.0f, 4000.0f };
     86     freqRange.setSkewForCentre (transFreq);
     87 
     88     using namespace chowdsp::ParamUtils;
     89     emplace_param<chowdsp::BoolParameter> (params, "tone_onoff", "Tone On/Off", true);
     90     emplace_param<chowdsp::FloatParameter> (params, "h_bass", "Tone Bass", NormalisableRange { -1.0f, 1.0f }, 0.0f, &floatValToString, &stringToFloatVal);
     91     emplace_param<chowdsp::FloatParameter> (params, "h_treble", "Tone Treble", NormalisableRange { -1.0f, 1.0f }, 0.0f, &floatValToString, &stringToFloatVal);
     92     createFreqParameter (params, "h_tfreq", "Tone Transition Frequency", 100.0f, 4000.0f, transFreq, transFreq);
     93 }
     94 
     95 void ToneControl::prepare (double sampleRate, int numChannels)
     96 {
     97     toneIn.prepare (sampleRate, numChannels);
     98     toneOut.prepare (sampleRate, numChannels);
     99 }
    100 
    101 void ToneControl::processBlockIn (AudioBuffer<float>& buffer)
    102 {
    103     if (static_cast<bool> (onOffParam->load()))
    104     {
    105         toneIn.setLowGain (dbScale * bassParam->getCurrentValue());
    106         toneIn.setHighGain (dbScale * trebleParam->getCurrentValue());
    107     }
    108     else
    109     {
    110         toneIn.setLowGain (0.0f);
    111         toneIn.setHighGain (0.0f);
    112     }
    113     toneIn.setTransFreq (tFreqParam->getCurrentValue());
    114 
    115     toneIn.processBlock (buffer);
    116 }
    117 
    118 void ToneControl::processBlockOut (AudioBuffer<float>& buffer)
    119 {
    120     if (static_cast<bool> (onOffParam->load()))
    121     {
    122         toneOut.setLowGain (-1.0f * dbScale * bassParam->getCurrentValue());
    123         toneOut.setHighGain (-1.0f * dbScale * trebleParam->getCurrentValue());
    124     }
    125     else
    126     {
    127         toneOut.setLowGain (0.0f);
    128         toneOut.setHighGain (0.0f);
    129     }
    130     toneOut.setTransFreq (tFreqParam->getCurrentValue());
    131 
    132     toneOut.processBlock (buffer);
    133 }