An MPEG audio codec in Zig that decodes Layers I, II and III and encodes Layers II and III.
zig-mp3 testdata README.md
2.6 kB · 46 lines
Markdown
at main

Test vectors #

Five short clips. The three Layer III ones each cover a different MPEG version, and each contains long, start, short and stop blocks so that every window shape is exercised; the stereo clip also contains a mid/side coded frame. The other two cover Layers I and II.

file layer version rate channels notes
stereo44.mp3 III MPEG-1 44100 Hz joint 19 frames, one M/S
mono22.mp3 III MPEG-2 22050 Hz mono 20 frames
mono11.mp3 III MPEG-2.5 11025 Hz mono 11 frames
layer2.mp2 II MPEG-1 44100 Hz stereo 23 frames, 64 kbit/s
layer1.mp1 I MPEG-1 44100 Hz joint 20 frames, bound 8

The source for the Layer II and Layer III clips is synthetic: sine tones, a quadratic sweep, white noise and periodic clicks, generated with ffmpeg's aevalsrc, so nothing here is anyone's copyrighted recording. Layer III was encoded with LAME through ffmpeg, with the Xing and ID3 headers suppressed so that the files are nothing but MPEG frames; Layer II with ffmpeg's own MP2 encoder, at a bit rate low enough that it reaches for the grouped quantization classes.

layer1.mp1 has no source clip, because nothing in common use still encodes Layer I. It was written directly by tools/gen_layer1.py, whose allocations, scalefactors and codes are drawn from a seeded generator; the same seed always gives the same file. It is joint stereo so that the committed vector exercises the subbands the two channels share. What comes out is noise rather than music, which for testing a decoder is the point: an encoder would leave most of the quantization classes untouched.

The .pcm files are the matching reference decodings: signed 16-bit little endian, interleaved, produced by ffmpeg's own decoder. They are not this decoder's output, which is what makes comparing against them meaningful. tools/check-against-ffmpeg.py regenerates the comparison over a much wider matrix of layers and formats.

Layer III agrees with the reference to the last bit of a sample. Layers I and II agree to two, because their requantization is a different arithmetic in the two decoders rather than the same one rounded differently; src/decode_test.zig carries the tolerance per clip.