1. Your while loop looks very strange to me and I believe the identical result would be achieved much faster by simply omitting the while and endwhile statements.
Without the "while" will not be possible get the Crest Factor desired, because when I just set everything greater than 1 to 1, and everything lower than -1 to -1, the RMS level will be changed.
The "while" function will check the newer RMS level and calculated it again.
2. The statement:
normalized = filtered / (rms(filtered) / 10^(-crest_factor/20));
normalises the signal to an RMS level of -6dB below 1. An RMS below 1 does not of
course guarantee there will be no samples greater than 1, but unless your signal is very
peculiar I would expect there to be very few or none.
This is why I'm using the "while" function, to reduce the number of samples greater than 1 & lower than -1
Possibly therefore the following code would meet your needs without the need for complex compression.
crest_factor = 6;
typenoise = noise(10*44100, 1, 'pink');
[z, p, k] = butter(4, [100/(44100/2), 500/(44100/2)]);
sos = zp2sos (z, p, k);
filtered = sosfilt(sos, typenoise);
normalized = filtered / (rms(filtered) / 10^(-crest_factor/20));
NumberOfClippedSamples = nnz(
normalized > 1 |normalized<-1)
normalized(normalized > 1) = 1;
normalized(normalized < -1) = -1;
In your example, I'm getting a Crest Factor of -6,36 instead of -6 (this 0,36dB is too much) and almost 20000 samples clipped.
I would like to avoid this approach "normalized(normalized > 1) = 1" to avoid a hard clipping.
What I'm looking for is a kind of Hard Limiter instead of a Hard Clipping.
Many thanks,
Renato