Skip to content

Commit

Permalink
Master compressor (#630)
Browse files Browse the repository at this point in the history
* add env follower mode to sidechain compressor

* use hold in comp

* barebones working

* working comp, no controls

* scaled appropriately

* editable ratio and threshold

* better shape

* working attack and release controls

* tweak attack and release minimums

* auto makeup gain

* clean up auto makeup gain

* saving and restoring parameters

* working auto makeup gain

* remove old comp

* show mode popup and add to community features

* remove remaining old master comp references

* dbt format

* fix gain scaling

* fix gain scaling properly

* improve parameter scaling and makeup

* set better defaults

* dbt format

* gr to gainReduction

* fix volume drop again

* fix retroactive sidechain hits

* improve gain scaling

* fix sidechain not releasing

* tweak makeup gain again

* float division for speed and accuracy

* adjust ratio range

* tie threshold to song volume

* limiting rework

* change popup

* format and correct gain

* slightly increase makeup gain to handle higher levels

* move limiter post envelope

* switch to feedback compression

* format
  • Loading branch information
m-m-adams authored Oct 25, 2023
1 parent c8516f0 commit 41bda54
Show file tree
Hide file tree
Showing 22 changed files with 335 additions and 748 deletions.
9 changes: 2 additions & 7 deletions docs/community_features.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,8 @@ Here is a list of features that have been added to the firmware as a list, group
### 4.1 - Song View Features

#### 4.1.1 - Master Compressor
- ([#137]) In the Song view, select "AFFECT ENTIRE" and "SIDECHAIN" modulation button, and adjust the upper gold knob. Push the upper gold knob to switch to the next setting (Threshold (dB), Makeup Gain (dB), Attack (ms), Release (ms), Ratio, MIX). The LEDs next to the knob act as a gain reduction meter.
- ([#630]) In the Song view, select "AFFECT ENTIRE" and "SIDECHAIN" modulation button, and adjust the upper gold knob for a single knob compressor with auto makeup gain. For detailed editing, press the sidechain gold knob. The top LED will become a compression meter, and the bottom LED level will show the compressor input level. The bottom (reverb) knob will adjust the ratio in this mode, from 1:8 to infinity/brick wall. The compressor attack and release are editable on the affect entire attack and release buttons if desired.

- This feature can be turned ON/OFF in the Runtime Settings (Community Features) Menu (accessed by pressing "SHIFT" + "SELECT").

- Follow up PR's:
- ([#200]) Fixed master compressor. The masterVolumeAdjustment value is now considered in the process. With this change, threshold value are now displayed correctly. This modification affects songs that had saved master compressor settings.
- ([#220]) Fixed a bug in the song view that, when the "SIDECHAIN" knob was turned while holding down a clip pad, the "SIDECHAIN" value and the Master Compressor Threshold would change at the same time.

#### 4.1.2 - Change Row Colour

Expand Down Expand Up @@ -357,7 +352,7 @@ This list includes all preprocessor switches that can alter firmware behaviour a
[#122]: https://github.com/SynthstromAudible/DelugeFirmware/pull/122
[#125]: https://github.com/SynthstromAudible/DelugeFirmware/pull/125
[#129]: https://github.com/SynthstromAudible/DelugeFirmware/pull/129
[#137]: https://github.com/SynthstromAudible/DelugeFirmware/pull/137
[#630]: https://github.com/SynthstromAudible/DelugeFirmware/pull/630
[#138]: https://github.com/SynthstromAudible/DelugeFirmware/pull/138
[#141]: https://github.com/SynthstromAudible/DelugeFirmware/pull/141
[#157]: https://github.com/SynthstromAudible/DelugeFirmware/pull/157
Expand Down
1 change: 1 addition & 0 deletions src/definitions_cxx.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ enum class EnvelopeStage : uint8_t {
SUSTAIN,
RELEASE,
FAST_RELEASE,
HOLD,
OFF,
};
constexpr int32_t kNumEnvelopeStages = util::to_underlying(EnvelopeStage::OFF) + 1;
Expand Down
62 changes: 48 additions & 14 deletions src/deluge/dsp/compressor/compressor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Compressor::Compressor() {
status = EnvelopeStage::OFF;
lastValue = 2147483647;
pos = 0;
follower = false;
attack = getParamFromUserValue(Param::Static::COMPRESSOR_ATTACK, 7);
release = getParamFromUserValue(Param::Static::COMPRESSOR_RELEASE, 28);
pendingHitStrength = 0;
Expand Down Expand Up @@ -80,11 +81,14 @@ void Compressor::registerHitRetrospectively(int32_t strength, uint32_t numSample
// If we're still in the release stage...
if (numSamplesSinceRelease < releaseStageLengthInSamples) {
pos = numSamplesSinceRelease * alteredRelease;
envelopeHeight = ONE_Q31 - envelopeOffset;
envelopeOffset = ONE_Q31;
status = EnvelopeStage::RELEASE;
}

// Or if we're past the release stage...
else {
envelopeOffset = ONE_Q31;
status = EnvelopeStage::OFF;
}
}
Expand Down Expand Up @@ -124,35 +128,65 @@ int32_t Compressor::getActualReleaseRate() {
int32_t Compressor::render(uint16_t numSamples, int32_t shapeValue) {

// Initial hit detected...
if (pendingHitStrength != 0) {
if (pendingHitStrength != 0 || follower) {
int32_t newOffset = ONE_Q31 - pendingHitStrength;

pendingHitStrength = 0;

//envelope offset is the value we're attack/decaying to
// Only actually do anything if this hit is going to cause a bigger dip than we're already currently experiencing
if (newOffset < lastValue) {
envelopeOffset = newOffset;

// If attack is all the way down, jump directly to release stage
if (attack == attackRateTable[0] << 2) {
goto prepareForRelease;
envelopeHeight = ONE_Q31 - envelopeOffset;
envelopeOffset = ONE_Q31;
pos = 0;
status = EnvelopeStage::RELEASE;
}
else {
if (!follower || status == EnvelopeStage::HOLD) {
status = EnvelopeStage::ATTACK;
pos = 0;
}
else if (status != EnvelopeStage::ATTACK) {
status = EnvelopeStage::HOLD;
}

envelopeHeight = lastValue - envelopeOffset;
}
}
//or if we're working in follower mode, in which case we want to start releasing whenever the current hit strength is below the envelope level
else if (follower && newOffset > envelopeOffset) {
envelopeOffset = newOffset;
envelopeHeight = newOffset - lastValue;
if (status == EnvelopeStage::HOLD) {
pos = 0;
status = EnvelopeStage::RELEASE;
}
else if (status != EnvelopeStage::RELEASE) {
status = EnvelopeStage::HOLD;
}

status = EnvelopeStage::ATTACK;
envelopeHeight = lastValue - envelopeOffset;
pos = 0;
}
}

if (status == EnvelopeStage::ATTACK) {
pos += numSamples * getActualAttackRate();

if (pos >= 8388608) {
//if we're in follower mode then we just hold the value
if (!follower) {
envelopeHeight = ONE_Q31 - envelopeOffset;
envelopeOffset = ONE_Q31;
prepareForRelease:
pos = 0;
status = EnvelopeStage::RELEASE;
envelopeHeight = ONE_Q31 - envelopeOffset;
goto doRelease;
pos = 0;
status = EnvelopeStage::RELEASE;

goto doRelease;
}
else {
status = EnvelopeStage::HOLD;
goto doOff;
}
}
//lastValue = (multiply_32x32_rshift32(envelopeHeight, decayTable4[pos >> 13]) << 1) + envelopeOffset; // Goes down quickly at first. Bad
//lastValue = (multiply_32x32_rshift32(envelopeHeight, 2147483647 - (pos << 8)) << 1) + envelopeOffset; // Straight line
Expand Down Expand Up @@ -191,15 +225,15 @@ int32_t Compressor::render(uint16_t numSamples, int32_t shapeValue) {
preValue = straightness * (pos >> 8) + (getDecay8(8388608 - pos, 23) >> 16) * curvedness16;
}

lastValue = ONE_Q31 - envelopeHeight + (multiply_32x32_rshift32(preValue, envelopeHeight) << 1);
lastValue = envelopeOffset - envelopeHeight + (multiply_32x32_rshift32(preValue, envelopeHeight) << 1);

//lastValue = 2147483647 - (multiply_32x32_rshift32(decayTable8[pos >> 13], envelopeHeight) << 1); // Upside down exponential curve
//lastValue = 2147483647 - (((int64_t)((sineWave[((pos >> 14) + 256) & 1023] >> 1) + 1073741824) * (int64_t)envelopeHeight) >> 31); // Sine wave. Not great
//lastValue = (multiply_32x32_rshift32(pos * (pos >> 15), envelopeHeight) << 1); // Parabola. Doesn't "punch".
}
else { // Off
doOff:
lastValue = ONE_Q31;
lastValue = envelopeOffset;
}

return lastValue - ONE_Q31;
Expand Down
2 changes: 1 addition & 1 deletion src/deluge/dsp/compressor/compressor.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class Compressor {
public:
Compressor();
void cloneFrom(Compressor* other);

bool follower;
EnvelopeStage status;
uint32_t pos;
int32_t lastValue;
Expand Down
88 changes: 0 additions & 88 deletions src/deluge/dsp/master_compressor/chunkware_simplecomp.cpp

This file was deleted.

Loading

0 comments on commit 41bda54

Please sign in to comment.