Skip to content

Commit 1c1dfce

Browse files
committed
Introduce tremulant frequnecy modulation.
1 parent d302a99 commit 1c1dfce

File tree

4 files changed

+25
-5
lines changed

4 files changed

+25
-5
lines changed

Source/aeolus/division.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,15 @@ Division::Division(Engine& engine, const String& name)
3535
, _midiChannel{0}
3636
, _tremulantEnabled{false}
3737
, _tremulantLevel{0.0f}
38-
, _tremulantMaxLevel{1.0f}
38+
, _tremulantMaxLevel{TREMULANT_TARGET_LEVEL}
3939
, _tremulantTargetLevel{0.0f}
4040
, _paramGain{nullptr}
4141
, _params{Division::NUM_PARAMS}
4242
, _swellFilterSpec{}
4343
, _swellFilterStateL{}
4444
, _swellFilterStateR{}
45+
, _tremulantDelayL(TREMULANT_DELAY_LENGTH)
46+
, _tremulantDelayR(TREMULANT_DELAY_LENGTH)
4547
, _stops{}
4648
, _activeVoices{}
4749
, _keysState{}
@@ -313,7 +315,7 @@ float Division::getTremulantLevel(bool update)
313315
const auto level = _tremulantLevel;
314316

315317
if (update)
316-
_tremulantLevel += 0.5f * (_tremulantTargetLevel - _tremulantLevel);
318+
_tremulantLevel += 0.1f * (_tremulantTargetLevel - _tremulantLevel);
317319

318320
return level;
319321
}
@@ -473,9 +475,20 @@ void Division::modulate(juce::AudioBuffer<float>& targetBuffer, const juce::Audi
473475
jassert(outR != nullptr);
474476

475477
for (int i = 0; i < SUB_FRAME_LENGTH; ++i) {
478+
_tremulantDelayL.write(outL[i]);
479+
_tremulantDelayR.write(outR[i]);
480+
476481
const float g = (1.0f + gain[i] * lvl) * paramGain.nextValue();
477-
outL[i] *= g;
478-
outR[i] *= g;
482+
483+
constexpr float freqModCenter = TREMULANT_DELAY_LENGTH * 0.5f;
484+
constexpr float freqModAmp = TREMULANT_DELAY_LENGTH * 0.5f * TREMULANT_DELAY_MODULATION_LEVEL;
485+
486+
const float p = freqModCenter + freqModAmp * (0.5f - gain[i] * lvl);
487+
outL[i] = _tremulantDelayL.read(p) * g;
488+
outR[i] = _tremulantDelayR.read(p) * g;
489+
490+
//outL[i] *= g;
491+
//outR[i] *= g;
479492
}
480493

481494
// Apply swell filter

Source/aeolus/division.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,10 @@ class Division
192192
dsp::BiquadFilter::State _swellFilterStateL;
193193
dsp::BiquadFilter::State _swellFilterStateR;
194194

195+
/// Delay lines used for tremulant frequency modulation.
196+
dsp::DelayLine _tremulantDelayL;
197+
dsp::DelayLine _tremulantDelayR;
198+
195199
std::vector<Stop> _stops; ///< All the stops this division has.
196200

197201
List<Voice> _activeVoices; ///< Active voices on this division.

Source/aeolus/globals.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ constexpr static float TREMULANT_PHASE_INCREMENT = juce::MathConstants<float>::t
8181

8282
/// Tremulant OSC wavetable amplitude.
8383
constexpr static float TREMULANT_LEVEL = 1.0f;
84+
constexpr static float TREMULANT_TARGET_LEVEL = 0.5f; // Amplitude modulation level.
85+
constexpr static size_t TREMULANT_DELAY_LENGTH = 32; // Frequency modulation delay line length (in samples).
86+
constexpr static float TREMULANT_DELAY_MODULATION_LEVEL = 0.9f; // Frequency modulation level.
8487

8588
/// Number of steps in the sequencer.
8689
constexpr static int SEQUENCER_N_STEPS = 16;

Source/aeolus/voice.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ void Voice::trigger(const Pipewave::State& state)
7777
_spatialSource.setSampleRate(SAMPLE_RATE_F);
7878
_spatialSource.setSourcePosition(x, 5.0f);
7979
_spatialSource.recalculate();
80-
_postReleaseCounter = _spatialSource.getPostFxSamplesCount() + int(2*_delay + 0.5f);
80+
_postReleaseCounter = _spatialSource.getPostFxSamplesCount() + int(2 * _delay + TREMULANT_DELAY_LENGTH + 0.5f);
8181
}
8282

8383
void Voice::release()

0 commit comments

Comments
 (0)