Noise bursts can happen from a few possible causes:
1. Sample buffers weren't zero'd before mixing waveforms onto them.
2. Accessed wrong memory.
3. Most often, maybe, all the time, an IIR filter went outside its safe ranges and went unstable, these filters become "broken" because they feed onto their immediate past to define their present.
About the noise burst detection:
Here is the noise burst heuristic that was used in Overloader. It keeps track of a "demerit" score based on delta and peak sample values.
Not sure if its a reasonable algorithm (maybe not, but it could be disabled or reset), its kinda simple, but please feel free to use it for any purpose, I set this noise burst protection code into the public domain for any use.
Code: Select all
float chprot_peak_threshold;
float chprot_delta_threshold;
int chprot_silence_time;
int chprot_silence_samples;
int chprot_release_time;
int chprot_release_samples;
float chprot_current_envelope;
int chprot_current_env_period;
float post_last_sample;
float post_demerit;
// int chprot_windowopen; // GUI
// int chprot_windowaclose;
Initialize:
chprot_peak_threshold = 40000.0f;
chprot_delta_threshold = 10000.0f;
chprot_silence_time = 1000;
chprot_release_time = 100;
chprot_silence_samples = (chprot_silence_time * getSampleRate()) / 1000;
chprot_release_samples = (chprot_release_time * getSampleRate()) / 1000;
chprot_current_envelope = 1.0f;
chprot_current_env_period = 0;
post_last_sample = 0.0f;
post_demerit = 0.0f;
chprot_windowopen = 0;
chprot_windowaclose = 0;
To reset:
chprot_current_envelope = 1.0f;
chprot_current_env_period = 0;
post_last_sample = 0.0f;
post_demerit = 0.0f;
Work:
if (overload_enableburst == 1) {
bufrel = (float)(32767.0f / (float)chprot_release_samples) / 32767.0f;
nmsp2 = numsamples * 2;
for (i = 0; i < nmsp2; ++ i) {
if (post_demerit > 0) post_demerit--;
if (psamples[i] > chprot_peak_threshold) post_demerit+=3;
if (fabs(post_last_sample - psamples[i]) > chprot_delta_threshold) post_demerit+=3;
if (post_demerit > 8000) {
chprot_current_envelope = 0.01f;
chprot_current_env_period = 0;
}
if (chprot_current_envelope < 1.0f) {
chprot_current_env_period++;
if (chprot_current_env_period > chprot_silence_samples) {
chprot_current_envelope += bufrel;
if (chprot_current_envelope > 0.70f) {
chprot_windowaclose = 0;
}
}
} else if (chprot_current_envelope > 1.0f) {
chprot_current_envelope = 1.0f;
chprot_windowaclose = 0;
} else {
chprot_windowaclose = 0;
}
psamples[i] *= chprot_current_envelope;
post_last_sample = psamples[i];
++ i;
psamples[i] *= chprot_current_envelope;
}
}