MCPcopy Create free account
hub / github.com/aethersdr/AetherSDR / process

Method process

src/core/ClientTube.cpp:205–288  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

203}
204
205void ClientTube::process(float* interleaved, int frames, int channels) noexcept
206{
207 if (frames <= 0) return;
208 if (channels != 1 && channels != 2) return;
209
210 recacheIfDirty();
211 const bool enabled = m_atomics.enabled.load(std::memory_order_acquire);
212
213 float inPeakLin = 0.0f;
214 float outPeakLin = 0.0f;
215 float maxDriveLin = 0.0f;
216
217 const float baseDrive = m_cached.baseDriveLin;
218 const float outputLin = m_cached.outputLin;
219 const float dryWet = m_cached.dryWet;
220 const float envAmount = m_cached.envAmount;
221 const float attackCoeff = m_cached.attackCoeff;
222 const float releaseCoeff = m_cached.releaseCoeff;
223 const float toneCoef = m_cached.toneCoeff;
224 const float tone = m_cached.tone;
225
226 for (int f = 0; f < frames; ++f) {
227 const float dryL = interleaved[f * channels];
228 const float dryR = (channels == 2)
229 ? interleaved[f * channels + 1] : dryL;
230
231 const float inAbs = std::max(std::fabs(dryL), std::fabs(dryR));
232 if (inAbs > inPeakLin) inPeakLin = inAbs;
233
234 // Envelope follower for dynamic drive.
235 const float alpha = (inAbs > m_envLin) ? attackCoeff : releaseCoeff;
236 m_envLin += alpha * (inAbs - m_envLin);
237
238 // Effective drive: baseDrive * (1 + envAmount * envLin).
239 // envAmount = 0 → static drive (no modulation)
240 // envAmount = +1 → at full-scale input, drive × 2
241 // envAmount = -1 → at full-scale input, drive × 0
242 // Clamped to [0.1, 10] so an aggressive negative envelope at
243 // a loud level doesn't zero the drive entirely.
244 const float envMod = 1.0f + envAmount * m_envLin;
245 const float drive = std::clamp(baseDrive * envMod, 0.1f, 10.0f);
246 if (drive > maxDriveLin) maxDriveLin = drive;
247
248 // Per-channel tone pre-filter (simple one-pole LP with HP
249 // blend). m_toneState holds the LP output; the shaper sees
250 // dry blended toward HP (tone > 0) or LP (tone < 0).
251 auto shapeChan = [&](float x, float& state) {
252 state += toneCoef * (x - state);
253 const float lp = state;
254 const float hp = x - state;
255 const float shaped = (tone >= 0.0f)
256 ? x + tone * (hp - x * 0.5f) // brighten
257 : x + (-tone) * (lp - x * 0.5f); // darken
258 return shape(shaped * drive);
259 };
260
261 const float wetL = shapeChan(dryL, m_toneStateL);
262 const float wetR = (channels == 2)

Callers

nothing calls this directly

Calls 2

linToDbFunction · 0.70
loadMethod · 0.45

Tested by

no test coverage detected