I’ve been teaching myself audio programming and have created a Minimoog Model D emulation to use as a guinea pig for new concepts and virtual analog techniques as I learn them.
First, given that it is forever in progress, any constructive feedback for improvement is welcomed and encouraged.
Second, I smelled burning plastic and somehow maimed my laptop speakers the other day after a short period (less than 30 seconds) of experimentation, and would like to figure out why. My actual laptop volume was at 54%, so it didn’t seem excessively loud audibly, but in hindsight, I’m guessing the energy out of the speakers does not equal the energy in the signal path going to the speakers.
To be fair, I was playing with synth feedback when it happened, which in an analog realm could certainly lead to these issues. I assumed since it was all digital that I couldn’t break things like this.
Is there some type of hard-coded limiting I need to do in my plugins to prevent chaotic users like myself from harming their own equipment, or perhaps something programming-wise I did incorrectly? Or was this a fluke of hardware and it’s a coincidence that I was playing with my synth at the time as opposed to listening to Spotify?
One thing you definitely want to avoid is excessive infrasonic frequencies/DC offset getting into the speakers/headphones. There are specialized filters for doing that, but often a simple non-resonating highpass filter can also do the job. (Set the cut off around 16-32 Hz or so.) This type of filtering may already be happening somewhere in the hardware signal chain, but it’s best to assume that is not going to be there.
It may also be possible floating point signals can cause excessive output energies to happen with certain softwares/operating systems/hardwares. So, even if you have your laptop volume set to something below the maximum, the actual signal getting into the headphones/speakers might still go above the expected limit. I’ve observed this behavior on my Mac laptop. I’ve got horrible bursts of noise when bugs have happened in audio softwares. This seems like an issue where Mac Os doesn’t clip floating point signals before it lets them out into the analog amplifiers and the rest of the signal chain on the hardware. This seems it could be avoided by clipping floating point signals into the nominal -1.0 to 1.0 range.
You will also want to avoid infinities and NaN floating point values getting out of your software as those can also cause excessive noises and/or mess up the CPU floating point state.
I am not filtering the actual output in any way, so not filtering out dc offset/infrasonic frequencies could both be complicating factors. It definitely makes sense how those issues could manifest as burning plastic when I’m maxing out parameters.
The last time I ran interp-tracer against my Faust code there weren’t any nans, and the only overflows were expected from a noise method. I’ll run it again to double-check I haven’t introduced a random bug though, definitely drives home the impact of those types of issues. I was also just assuming my values were limited to the [-1.0, 1.0] range, but like the filtering above, I’m sure it’s better to just explicitly do it than assume.
I cloned and built your plugin. I was unfortunately unable to debug/test it properly since it crashes/jasserts right away when Reaper scans the VST3 plugin when running under the debugger. Might be a good idea for you to check what’s going on with that with the debugger. (I built and tested on Visual Studio 2022/Windows 10.)
edit : The same issue also happens with the standalone executable when running under the debugger. The application does start but I get the same issue in the debugger as with the VST3 plugin when I quit the application.
The call stack leading to the crash/jassert begins from your
FaugAudioSource::~FaugAudioSource()
destructor. While there’s no code in the destructor, the destructor leads to other stuff happening which isn’t working correctly.
Hmmm, It has been a while since I ran it as a vst3 plugin, I hadn’t noticed it was crashing like that. I did notice the jasserts when building the Standalone app though, time to get those figured out. I’ll report back when I have it running properly!
That’s a good point. In my own music projects, I generally try to keep the plugin outputs around -6dBFS, so I’ll take that into account for the app’s default values.
also - at least in debug builds, check your whole main output buffer for inf and nan (and replace with silence/assert if that happens).
where x is a value in your buffer:
std::isnan(x);
std::isinf(x);
Otherwise, at minimum also hard clip the output as others mentioned.