When exporting to FLAC with a recent master build, I noticed that the output had noticeable (sometimes severe) crackling not present in previous exports. Here's a comparison of the output waveform, with WAV on top and FLAC on the bottom:

Examining the top left of both waveforms, the FLAC export appears to have a downwards DC offset. In addition, when this offset wave reaches -1.0, it wraps around and "sticks" at 1.0.
Export options: 44.1kHz, 24 Bit, Sinc best, No oversampling
Also, a minor filename bug:
.wav.flacReproduced. 16bit FLAC works fine, only 24bit FLAC is problematic.
It seems like there's a bug with libsndfile's FLAC export: https://github.com/erikd/libsndfile/issues/309
Probably we can use sf_writef_int instead of sf_writef_float which is buggy for FLAC.
@PhysSong int instead of float, wont that be inaccurate ?
what about treating the float value as a string, and write that string into the export, as a string(?)
Here is a pre-release of libsndfile-1.0.29 which should see this issue fixed.
http://www.mega-nerd.com/libsndfile/files/1.0.29pre2/
Probably we can use
sf_writef_intinstead ofsf_writef_floatwhich is buggy for FLAC.
But FLAC is integer only so there will be conversion anyway. The bug is in the clipping algorithm and if we don't clip the file I think there may be an issue with overflow when going over +/-1.0f. Worth a try though.
Another way is to clip samples on LMMS side before passing to the buggy libsndfile function.
Another way is to clip samples on LMMS side before passing to the buggy
libsndfilefunction.
This sound like the best solution to me. The buggy libsndfile versions are going to be around for quite some time so I'm milestoning this.
buf[frame*channels() + channel] = _ab[frame][channel] * master_gain;
to
buf[frame*channels() + channel] = qMax(-0.9999999, _ab[frame][channel] * master_gain);
This works. I was thinking -1.0f as min value would work but it was still clipping.
I think clamping the samples inside of LMMS isn't a good idea. As written here it's perfectly OK for a float encoded WAV file to have values that are outside of the [-1, 1] interval. Here's the relevant section from the link:
WAV files saved as floating point do allow values exceeding the 0 dB range. This means the range is actually beyond [-1, 1] for values that normally would clip.
The explanation for this can be that floating point formats are intended for intermediate use in production setups due to very little loss of dynamic range, where future processing (gain-staging, compressing, limiting etc.) can bring back the values (without loss) well within the final and normal -0.2 - 0 dB range; and therefor preserves the values as-is.
If you clamp the samples inside of LMMS this will not work anymore.
Therefore I think a better fix would be to integrate the newer version of libsndfile and to show a warning message to the user if the export has clipped for formats where clipping can occur. I think the engine of LMMS should never clamp any values at any point in the path and just mix (float) audio streams regardless of how they look.
As written here it's perfectly OK for a float encoded WAV file to have values that are outside of the [-1, 1] interval. Here's the relevant section from the link:
I mean, clipping on LMMS side only for 24-bit integer FLAC.
If you clamp the samples inside of LMMS this will not work anymore.
The FLAC export clips the sample already in:
sf_command(m_sf, SFC_SET_CLIPPING, nullptr, SF_TRUE);
If you remove this the export becomes even more destroyed. You need to clip it to prevent issues if the signal goes above/below +/-1.0 and libsndfile provides this function (If the code works that is).
I tried some exporting options with a loud decaying sinewave.
sf_command(m_sf, SFC_SET_CLIPPING, nullptr, SF_FALSE);qMax(-0.999999f, _ab[frame][channel] * master_gain);
Probably we can use
sf_writef_intinstead ofsf_writef_floatwhich is buggy for FLAC.
As I understand it then we need a 24 bit version of AudioDevice::convertToS16. Too much work for the same result. I'll pull a fix clipping the negative side instead.
It seems like there's a bug with
libsndfile's FLAC export: erikd/libsndfile#309
libsndfile was just tagged 1.0.29: https://github.com/erikd/libsndfile/releases/tag/v1.0.29