AR: samples dynamics limiter (experimental)
to enable, compile with -D SOUND_DYNAMICS_LIMITER. still missing UI integration, and more testing.
This commit is contained in:
parent
d0f53cb14a
commit
b46a6ed094
@ -26,7 +26,7 @@
|
|||||||
// #define SR_DEBUG // generic SR DEBUG messages
|
// #define SR_DEBUG // generic SR DEBUG messages
|
||||||
|
|
||||||
// hackers corner
|
// hackers corner
|
||||||
// nothing atm
|
//#define SOUND_DYNAMICS_LIMITER // experimental: define to enable a dynamics limiter that avoids "sudden flashes" at onsets. Makes some effects look more "smooth and fluent"
|
||||||
|
|
||||||
#ifdef SR_DEBUG
|
#ifdef SR_DEBUG
|
||||||
#define DEBUGSR_PRINT(x) Serial.print(x)
|
#define DEBUGSR_PRINT(x) Serial.print(x)
|
||||||
@ -647,6 +647,39 @@ class AudioReactive : public Usermod {
|
|||||||
} // getSample()
|
} // getSample()
|
||||||
|
|
||||||
|
|
||||||
|
/* Limits the dynamics of volumeSmth (= sampleAvg or sampleAgc).
|
||||||
|
* It does not affect FFTResult[] or volumeRaw ( = sample or rawSampleAgc)
|
||||||
|
*/
|
||||||
|
// effects: Gravimeter, Gravcenter, Gravcentric, Noisefire, Plasmoid, Freqpixels, Freqwave, Gravfreq, (2D Swirl, 2D Waverly)
|
||||||
|
// experimental, as it still has side-effects on AGC - AGC detects "silence" to late (due to long decay time) and ditches up the gain multiplier.
|
||||||
|
// values below will be made user-configurable later
|
||||||
|
const float attackTime = 200; // attack time -> 0.2sec
|
||||||
|
const float decayTime = 2800; // decay time -> 2.8sec
|
||||||
|
|
||||||
|
void limitSampleDynamics(void) {
|
||||||
|
#ifdef SOUND_DYNAMICS_LIMITER
|
||||||
|
const float bigChange = 196; // just a representative number - a large, expected sample value
|
||||||
|
static unsigned long last_time = 0;
|
||||||
|
static float last_volumeSmth = 0.0f;
|
||||||
|
|
||||||
|
if ((attackTime > 0) && (decayTime > 0)) { // only change volume if user has defined attack>0 and decay>0
|
||||||
|
long delta_time = millis() - last_time;
|
||||||
|
delta_time = constrain(delta_time , 1, 1000); // below 1ms -> 1ms; above 1sec -> sily lil hick-up
|
||||||
|
float maxAttack = bigChange * float(delta_time) / attackTime;
|
||||||
|
float maxDecay = - bigChange * float(delta_time) / decayTime;
|
||||||
|
|
||||||
|
float deltaSample = volumeSmth - last_volumeSmth;
|
||||||
|
if (deltaSample > maxAttack) deltaSample = maxAttack;
|
||||||
|
if (deltaSample < maxDecay) deltaSample = maxDecay;
|
||||||
|
volumeSmth = last_volumeSmth + deltaSample;
|
||||||
|
}
|
||||||
|
|
||||||
|
last_volumeSmth = volumeSmth;
|
||||||
|
last_time = millis();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void transmitAudioData()
|
void transmitAudioData()
|
||||||
{
|
{
|
||||||
if (!udpSyncConnected) return;
|
if (!udpSyncConnected) return;
|
||||||
@ -922,6 +955,7 @@ class AudioReactive : public Usermod {
|
|||||||
if (soundAgc) my_magnitude *= multAgc;
|
if (soundAgc) my_magnitude *= multAgc;
|
||||||
if (volumeSmth < 1 ) my_magnitude = 0.001f; // noise gate closed - mute
|
if (volumeSmth < 1 ) my_magnitude = 0.001f; // noise gate closed - mute
|
||||||
|
|
||||||
|
limitSampleDynamics(); // optional - makes volumeSmth very smooth and fluent
|
||||||
|
|
||||||
// update UI
|
// update UI
|
||||||
uint8_t knownMode = strip.getFirstSelectedSeg().mode; // 1st selected segment is more appropriate than main segment
|
uint8_t knownMode = strip.getFirstSelectedSeg().mode; // 1st selected segment is more appropriate than main segment
|
||||||
@ -982,6 +1016,8 @@ class AudioReactive : public Usermod {
|
|||||||
transmitAudioData();
|
transmitAudioData();
|
||||||
lastTime = millis();
|
lastTime = millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//limitSampleDynamics(); // If done as the last step, it will also affect audio received by UDP sound sync. Problem: effects might see inconsistent intermediate values and start flickering :-(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user