---
title: "Decode Ogg Vorbis in C#"
url: https://recursiveai.org/oneaudio/cookbook/decode-ogg-vorbis/
description: "Decode Ogg Vorbis files in C# with oneaudio: load or stream the samples, read the comment tags, and play chained Ogg files as one stream."
version: "1.2.1"
---

# Decode Ogg Vorbis in C#

Decode Ogg Vorbis files in C# with oneaudio: load or stream the samples, read the comment tags, and play chained Ogg files as one stream.

```csharp
using OneAudio;
using OneAudio.Vorbis;

AudioClip clip = Audio.Load("music.ogg");
Console.WriteLine($"music.ogg: {clip.Format.SampleRate} Hz, " +
                  $"{clip.Format.Channels} ch, {clip.Frames} frames");

// The concrete decoder carries the comment header.
using (var vorbis = (VorbisDecoder)Audio.Open("music.ogg"))
{
    Console.WriteLine($"vendor: {vorbis.Vendor}");
    foreach (string comment in vorbis.Comments)     // NAME=value
        Console.WriteLine($"  {comment}");
}

// A chained file: two Ogg streams one after the other, music and then an
// announcement.
using (var chained = (VorbisDecoder)Audio.Open("chained.ogg"))
{
    Console.WriteLine($"chained.ogg: {chained.LinkCount} links, " +
                      $"{chained.LengthFrames} frames in all");
    float[] buffer = new float[4096 * chained.Format.Channels];
    long total = 0;
    int read;
    while ((read = chained.Read(buffer)) > 0)
        total += read;
    Console.WriteLine($"read {total} frames");
    Console.WriteLine($"comments of the last link: {string.Join(", ", chained.Comments)}");
}
```

```text
music.ogg: 44100 Hz, 2 ch, 1411200 frames
vendor: Lavf62.3.100
  encoder=Lavc62.11.100 libvorbis
  ARTIST=Test signal
  TITLE=Four chords
chained.ogg: 2 links, 1676903 frames in all
read 1676903 frames
comments of the last link: encoder=Lavc62.11.100 libvorbis, TITLE=Announcement
```

## Chained files

An Ogg file can hold several streams one after another, such as a radio recording or tracks joined with `cat`. Consecutive links in the same format decode as one stream. `LengthFrames` covers every link, and seeking works across them. `LinkCount` says how many links there are, and `GetLinkFormat(link)` returns the format of each one. `Vendor` and `Comments` belong to the link being decoded, which is why the sample prints the announcement’s title after reading to the end.

## Good to know

- `Audio.Open` returns a `VorbisDecoder` for Ogg Vorbis. Cast to it for `Vendor`, `Comments` and the link members. The same file through `Audio.Load` or the mixer needs no cast.
- Comments are `NAME=value` strings exactly as the file stores them. Names come in any case (ffmpeg writes `encoder` in lowercase), so compare them without regard to case. See [Read audio metadata](https://recursiveai.org/oneaudio/cookbook/read-audio-metadata/).
- The decoder was checked against libvorbis 1.3.7 on the Xiph test vectors: the same frame counts, and floor-1 streams within 2e-6.
- oneaudio doesn’t write Vorbis. An `.ogg` output path in `Audio.Transcode` writes Ogg Opus.

Streaming, exact seeking and chained files, compared with NVorbis: [Decode Ogg Vorbis in C#](https://recursiveai.org/oneaudio/articles/ogg-vorbis-csharp/).
