Here’s a somewhat controversial hack that let’s you normalize a Csound composition during the rendering process, scaling the amplitudes using Csound’s 32-bit or 64-bit resolutions.
This hack requires two renders. The first time you render a composition, look for the overall amps value at the end of the output message. It will look something similar to this:
end of score. overall amps: 0.64963
Next, you need to calculate the +3dB value above the overall amps value. Here is a function that does the trick, where x is overall amps:
f(x) = 10 ** (3.0 / 20.0) * x
Or if you want to skip most of the math involved:
f(x) = 1.4125375446227544 * x
Plug 0.64963 into x, and you get 0.91762676511328001. Set 0dbfs to this:
sr = 44100 kr = 4410 ksmps = 10 nchnls = 1 ;0dbfs = 1.0 0dbfs = 0.91762676511328001 ; 3dB normalization
Render again. Done.
This is a Hack
Though I do love this technique, I highly recommend that you use it only for a few situations, and certainly advise that you don’t make a habit of it.
I like to use this when I’m finished with a composition, and I’m ready to make a master audio file. This allows me to squeeze out a tiny bit of extra sound quality by scaling the audio inside csound64’s internal 64-bit float resolution. Which in theory, will do a better job that if I did the same process to a rendered sample of a lower bit resolution.
This can also be a last ditch effort for fixing problems with a final project that is due in 15 minutes. You have some minor clipping, and no time to globally adjust all your amplitudes? This could save you in a pinch.
This only works with absolute amplitudes. If there are any relative values or opcodes in play, then this technique will fail. For example, these two lines of instrument code will not work:
a1 oscils p4 * 0dbfs, 440, 0 ; Scales the amplitude relative to 0dbfs a2 diskin2 "foo.wav", 1 ; Scales the sample relative to 0dbfs
There are some other risks involved. If random elements exist in the composition, then the overall amps may vary between renders, which could lead to innaccurate normalization. I also highly suspect that the overall amps value at the end of the render is truncated, thus, it not pinpoint accurate — close enough for most situations.