Audio.Transcode("in.wav", "out.flac") compresses a WAV file to FLAC in one call, and FlacEncoder adds the compression level and tags. FLAC is lossless: the samples decode to exactly what went in. Pass your own WAV to the program; without one, it first writes a three-second test WAV so that it runs as is.
dotnet new console -o WavToFlac && cd WavToFlac dotnet add package RecursiveAI.OneAudio --version 1.4.0
Put this in Program.cs and run dotnet run (or dotnet run -- yourfile.wav):
using OneAudio; using OneAudio.Flac; string input = args.Length > 0 ? args[0] : "test.wav"; if (!File.Exists(input)) WriteTestWav(input); // One call, at the default level (5). Audio.Transcode(input, "out.flac"); // Or with a level and tags: 0 is fastest, 8 smallest. using (IAudioDecoder source = Audio.Open(input)) using (FileStream output = File.Create("out-level8.flac")) { FlacEncoder.Encode(source, output, new FlacEncoderSettings { CompressionLevel = 8, Comments = ["TITLE=Test chord", "ARTIST=Recursive AI"], }); } foreach (string f in new[] { input, "out.flac", "out-level8.flac" }) Console.WriteLine($"{f,-16}{new FileInfo(f).Length,12:N0} bytes"); // Lossless: the FLAC decodes to the WAV's exact integers. using IAudioDecoder a = Audio.Open(input), b = Audio.Open("out-level8.flac"); int[] x = new int[8192], y = new int[8192]; bool same = true; int n; while ((n = a.ReadInteger(x)) > 0) same &= b.ReadInteger(y) == n && x.AsSpan(0, n).SequenceEqual(y.AsSpan(0, n)); Console.WriteLine($"bit-exact: {same}"); // A test WAV: 3 s of a fading C major chord with a little noise, 44.1 kHz stereo. static void WriteTestWav(string path) { var random = new Random(1); float[] s = new float[44100 * 3 * 2]; for (int i = 0; i < s.Length; i++) { double t = i / 2 / 44100.0; double chord = Math.Sin(2 * Math.PI * 261.63 * t) + Math.Sin(2 * Math.PI * 329.63 * t) + Math.Sin(2 * Math.PI * 392.00 * t); double noise = 0.01 * (random.NextDouble() - 0.5); s[i] = (float)(0.25 * chord * Math.Exp(-t) + noise); } var format = new AudioFormat(44100, 2); var pcm16 = new WavEncoderSettings { SampleType = NativeSampleType.PcmSigned16 }; using var wav = new WavEncoder(File.Create(path), format, pcm16, leaveOpen: false); wav.Write(s); }
test.wav 529,280 bytes out.flac 298,139 bytes out-level8.flac 297,551 bytes bit-exact: True
How much smaller the FLAC is depends on the audio. The test chord, with its layer of noise, comes out at 56 percent of the WAV; level 8 saves a little more than the default, at the cost of encoding time.
Settings
CompressionLevelruns from 0 (fastest) to 8 (smallest); the default is 5. Output stays within FLAC’s streamable subset unless you setSubset = false.Commentsare Vorbis comment tags,NAME=value.- Any depth from 4 to 32 bits, 1 to 8 channels. 16 and 24-bit WAV files are copied bit-exact; a float WAV is written as 16-bit unless you ask for 24 (
TranscodeOptions.Flac). - On a seekable stream, the encoder writes the length, the MD5 signature and a seek table when it finishes. On a stream that can’t seek, it can’t go back: there is no MD5 or seek table.
Audio.Transcodereads any format oneaudio decodes, so MP3, Ogg or M4A to FLAC is the same call.
Limits
- Ogg FLAC isn’t written, only native
.flac. - Embedded pictures (cover art) aren’t written.
- Files decoded by
flac -dare bit-exact, and sizes are within 0.4% of theflactool’s at levels 0 to 8, per the project’s published results.
To read FLAC files, see Read a FLAC file.