I still can reproduce this problem with today’s git version. If I write a buffer alternating between -1.0f and 1.0f to a 16-bit wav file, all samples end up as -32778.
This still occurs in PPMulator, and here’s the code I used to double-check it:
We had a “great time” today with a similar issue when checking the reference files created with ppmulator. At some levels (for example -20dBFS / 0.1) the peaks in the wav file are not symmetric (min=-3277 and max=3276). ToneGeneratorAudioSource doesn’t look responsible for that, so it’s probably a similar rounding/conversion issue in the juce_AudioDataConverter.h. This may sound nitpicky, but for sine reference signals it’s really odd to have an dc offset.
It would be great if you could have another look at both the clipping and rounding issue. We tried to debug this on our own, but couldn’t follow all the casting and rounding involved there. What’s happeding in AudioData::Float32::getAsInt32LE() seemed odd to us (as data seems to hold a valid int32 value, so why interpret is as float?), but probably we just didn’t understand the context right.
Thanks for the sample code, that was really helpful. What was happening was that the 32-bit floats used in conversion were overflowing, so I’ve changed it to use doubles and all seems good now - it’s checked-in if you want to have a go.
What I find in the 16-bit wav file are these sample values, where most samples (except 0.25, 0.5, 0.75, 1.0) are rounded differently on the inverted channel.
Just looks like a difference between the direction of rounding of positive and negative integers… Luckily I don’t think any human has good enough hearing to be able to detect the difference.
yes, this is definitely far from being audible, but still an issue for metering fanatics, or in cases where its important that an original and inverted wav-file you create actually cancel each other out. (we use this from time to time, as a quick way to test the plugin-output for dropouts or other minor glitches ).
ok… but to change it would mean using a different rounding method. It currently uses roundToInt(), but you could try just doing a simple cast-to-int instead. Probably not as fast as using roundToInt though.
If the performance impact is limited to writing wav files, or other cases where you explicitly use these converters then I’d definitely vote for the exact rounding - If it’s a small change for you, and the performance decrease is negligible compared to the time used to actually write the data to disk.
I’m not actually even certain that the rounding would be any different - if you’ve already got a way to test it, you could try replacing the roundToInt() calls in the data converter file, and see if it makes a difference?