---
title: "Read a FLAC file in C#"
url: https://recursiveai.org/oneaudio/cookbook/read-flac/
description: "Decode FLAC to exact integer or float samples in C#, read the tags, verify the MD5 signature and convert FLAC to WAV, with no libFLAC."
version: "1.4.0"
---

# Read a FLAC file in C#

`Audio.Open` reads a FLAC file as exact integers or floats, and the `FlacDecoder` it returns adds the tags and the MD5 check. It’s managed code with no libFLAC. The file here is a three-second synthetic test file from the oneaudio repository; any FLAC file works the same way.

```shell
dotnet new console -o ReadFlac && cd ReadFlac
dotnet add package RecursiveAI.OneAudio --version 1.4.0
t=https://raw.githubusercontent.com/recursive-ai-oss/oneaudio-csharp/v1.4.0/testdata
curl -L -o song.flac $t/flac/stereo16_seektable.flac
```

Put this in `Program.cs` and run `dotnet run`:

```csharp
using OneAudio;
using OneAudio.Flac;

using (var flac = (FlacDecoder)Audio.Open("song.flac"))
{
    AudioFormat f = flac.Format;
    Console.WriteLine($"song.flac: {f.SampleRate} Hz, {f.Channels} ch, " +
                      $"{flac.BitsPerSample}-bit, {flac.LengthFrames} frames");
    Console.WriteLine($"vendor: {flac.Vendor}, tags: {flac.Comments.Count}");

    // Decodes the whole file and checks it against the signature in the header.
    Console.WriteLine($"MD5 matches: {flac.VerifyMd5()}");

    // The exact integer samples, for lossless work.
    int[] ints = new int[4096 * f.Channels];
    int frames = flac.ReadInteger(ints);
    int peak = ints.Take(frames * f.Channels).Max(Math.Abs);
    Console.WriteLine($"first {frames} frames as integers, peak {peak} of 32767");
}

// Or the whole file as floats, full scale at -1 and 1.
AudioClip clip = Audio.Load("song.flac");
Console.WriteLine($"as floats: {clip.Samples.Length} samples");

// FLAC to WAV: bit-exact, at the same bit depth.
TranscodeResult wav = Audio.Transcode("song.flac", "song.wav");
Console.WriteLine($"song.wav: {wav.Frames} frames, " +
                  $"{new FileInfo("song.wav").Length:N0} bytes");
```

```text
song.flac: 22050 Hz, 2 ch, 16-bit, 66000 frames
vendor: reference libFLAC 1.4.3 20230623, tags: 0
MD5 matches: True
first 4096 frames as integers, peak 25104 of 32767
as floats: 132000 samples
song.wav: 66000 frames, 264,080 bytes
```

## What you get

- `ReadInteger` returns the stream’s exact samples. A depth that isn’t a whole number of bytes is shifted up to the container width, so a 12-bit stream reads as 16-bit values; `FlacDecoder.BitsPerSample` is the true depth. `Read` returns floats.
- `VerifyMd5` returns null when the encoder stored no signature, and puts the read position back where it was.
- `Comments` holds the Vorbis comment tags as `NAME=value` strings: `TITLE`, `ARTIST` and so on.
- FLAC to WAV is bit-exact: the WAV holds the same integers at the same depth.

## Limits

- Every frame is CRC-checked. A frame that contradicts the stream header is rejected with `AudioFormatException`, after the frames before it have been delivered.
- Ogg FLAC opens the same way as native FLAC. Embedded pictures (cover art) aren’t returned.
- Bit-exact against `flac` 1.4.3 and the MD5 on all 64 files of the IETF CELLAR test suite’s subset; its 11 faulty files are rejected cleanly.

## With NAudio

NAudio 3.3.0’s `AudioFileReader` reads FLAC through Media Foundation, on Windows only ([package README](https://www.nuget.org/packages/NAudio/3.3.0)); elsewhere `NAudio.SoundFile` needs a system libsndfile. In the project’s [published results](https://github.com/recursive-ai-oss/oneaudio-csharp/blob/v1.4.0/README.md#results), oneaudio decoded FLAC 1.36 to 1.57 times as fast as PureFlac 1.0.0 and 2.07 to 8.09 times as fast as BunLabs.NAudio.Flac 2.0.1.

To write FLAC, see [Convert WAV to FLAC](https://recursiveai.org/oneaudio/cookbook/convert-wav-to-flac/).
