---
title: "Decode MP3 in C#"
url: https://recursiveai.org/oneaudio/cookbook/decode-mp3/
description: "Decode MP3 files to float samples or WAV in C# with oneaudio, a managed decoder with no native code: gapless trimming, exact seeking, and MP3 bytes held…"
version: "1.2.1"
---

# Decode MP3 in C#

Decode MP3 files to float samples or WAV in C# with oneaudio, a managed decoder with no native code: gapless trimming, exact seeking, and MP3 bytes held in memory.

```csharp
using OneAudio;

// The whole file as float samples.
AudioClip clip = Audio.Load("music.mp3");
Console.WriteLine($"music.mp3: {clip.Format.SampleRate} Hz, {clip.Format.Channels} ch, " +
                  $"{clip.Frames} frames ({clip.Frames / 44100.0:F3} s)");

// The same audio encoded without the LAME/Xing header: nothing tells the
// decoder how much padding the encoder added.
using (IAudioDecoder plain = Audio.Open("music-noheader.mp3"))
    Console.WriteLine($"music-noheader.mp3: {plain.LengthFrames} frames " +
                      $"({plain.LengthFrames / 44100.0:F3} s)");

// MP3 to WAV, streamed block by block. A lossy source is written as 16-bit
// PCM unless you choose otherwise.
TranscodeResult wav = Audio.Transcode("music.mp3", "music-decoded.wav");
long bytes = new FileInfo("music-decoded.wav").Length;
Console.WriteLine($"music-decoded.wav: {wav.Frames} frames, {bytes:N0} bytes");

// MP3 bytes in memory, for example from a database or an HTTP response.
byte[] mp3 = File.ReadAllBytes("music.mp3");
using IAudioDecoder decoder = Audio.Open(new MemoryStream(mp3));
float[] block = new float[1152 * decoder.Format.Channels];
decoder.Seek(44100 * 20);       // exact: the same samples as decoding from the start
int frames = decoder.Read(block);
Console.WriteLine($"{decoder.GetType().Name}: read {frames} frames " +
                  $"at {decoder.PositionFrames - frames}");
```

```text
music.mp3: 44100 Hz, 2 ch, 1411200 frames (32.000 s)
music-noheader.mp3: 1412352 frames (32.026 s)
music-decoded.wav: 1411200 frames, 5,644,880 bytes
Mp3Decoder: read 1152 frames at 882000
```

## Gapless length

An MP3 encoder adds silence at the start and pads the end to a whole frame. LAME, and ffmpeg through LAME, records both amounts in a Xing/Info header with the LAME extension. oneaudio reads that header and trims both, so `music.mp3` decodes to exactly the 1,411,200 frames of the WAV it was made from. That’s what lets a loop or a track sequence play without a gap.

`music-noheader.mp3` is the same audio encoded without the header. Nothing says how much padding there is, so the whole decoded signal is kept: 1,152 frames longer, with the encoder’s delay at the start. A VBRI header, or a Xing header without the LAME extension, gives only the frame count.

## Good to know

- MPEG-1, MPEG-2 and MPEG-2.5 Layer III are supported, at fixed, variable or free-format bitrates, in mono, stereo, joint stereo and dual channel. Layer I and Layer II files throw `UnsupportedAudioFormatException`.
- An ID3v2 tag at the start is skipped, and ID3v1, APE and Lyrics3 tags at the end are ignored. oneaudio 1.2.1 doesn’t return their contents.
- Seeking is exact and gives the same samples as decoding from the start. The first seek in a file makes one pass over the frame headers. The decoder then starts up to 48 frames before the target, to rebuild the bit reservoir.
- A frame that can’t be decoded, for example after a cut in the file, comes out as silence and decoding goes on.
- Writing MP3 isn’t supported. To compress, write [Ogg Opus](https://recursiveai.org/oneaudio/cookbook/encode-opus/) or [FLAC](https://recursiveai.org/oneaudio/cookbook/flac/).
- The decoder matches all 11 ISO/IEC 11172-4 compliance streams within the full-accuracy limits.

The rest of the MP3 rules are in the [API overview](https://recursiveai.org/oneaudio/docs/api/#mp3).

A longer guide, with NAudio on Linux compared: [Decode MP3 in C#](https://recursiveai.org/oneaudio/articles/decode-mp3-csharp/).
