Add optional FLAC compression by braheezy · Pull Request #76 · mewkiz/flac

Hi! I added the ability for the encoder to optionally choose a prediction method for better compression. I'm not sure the API is great but it seems to work and allows this library to produce files smaller than their input, see the Results at the end.

Bonus: The change in frame.go may be inappropriate for this PR but it fixes an out-of-index error I was getting in wav2flac on all files.

How

Added an opt-in prediction analysis pass.

  • Encoder now has a boolean field AnalysisEnabled (helper EnablePredictionAnalysis(true)).
  • When the flag is off (default) the encoder behaves as before: it writes Constant / Verbatim frames exactly as provided by the caller. This guarantees the round-trip tests that decode an existing FLAC and immediately re-encode it still pass.
  • When the flag is on the encoder examines any sub-frame that is still marked PredVerbatim and chooses the smallest of:
    1. Constant predictor (all samples equal)
    2. Verbatim (no prediction)
    3. Fixed prediction. The new analyseFixed() picks the best order and Rice-k.

libFLAC exposes a range of parameters to tune the encoding process. This PR introduces one knob to try to pick the best prediction method.

Results

Here's what I got when enabling prediction analysis on various audio files:

File Original Size w/out analysis w/ analysis Reduction
forest_of_illusion.wav 6.7 MB 7.9 MB 4.1 MB 48%
yoshis_island.wav 4.8 MB 5.3 MB 2.6 MB 51%
vanilla_dome.wav 8.5 MB 9.8 MB 5.9 MB 40%

There's an expected increase in encoding resources:

Metric Before After Change
Time 1547070 ns/op 6727643 ns/op 4.35x slower
Memory 1101783 B/op 3449681 B/op 3.13x more
Allocations 244 allocs/op 704 allocs/op 2.89x more

The new enc_benchmark_test.go created these results.

Review

I'm open to feedback or questions, or if more tests are needed. I have no personal need for this, just thought it would be fun to try to enhance things a bit.