Documentation
¶
Overview ¶
Package qoa provides functionality for encoding and decoding audio data in the QOA format.
The following is from the QOA specification:
Data Format ¶
QOA encodes pulse-code modulated (PCM) audio data with up to 255 channels, sample rates from 1 up to 16777215 hertz and a bit depth of 16 bits.
The compression method employed in QOA is lossy; it discards some information from the uncompressed PCM data. For many types of audio signals this compression is "transparent", i.e. the difference from the original file is often not audible.
QOA encodes 20 samples of 16 bit PCM data into slices of 64 bits. A single sample therefore requires 3.2 bits of storage space, resulting in a 5x compression (16 / 3.2).
A QOA file consists of an 8 byte file header, followed by a number of frames. Each frame contains an 8 byte frame header, the current 16 byte en-/decoder state per channel and 256 slices per channel. Each slice is 8 bytes wide and encodes 20 samples of audio data.
All values, including the slices, are big endian. The file layout is as follows:
struct { struct { char magic[4]; // magic bytes "qoaf" uint32_t samples; // samples per channel in this file } file_header; struct { struct { uint8_t num_channels; // no. of channels uint24_t samplerate; // samplerate in hz uint16_t fsamples; // samples per channel in this frame uint16_t fsize; // frame size (includes this header) } frame_header; struct { int16_t history[4]; // most recent last int16_t weights[4]; // most recent last } lms_state[num_channels]; qoa_slice_t slices[256][num_channels]; } frames[ceil(samples / (256 * 20))]; } qoa_file_t;
Each qoa_slice_t contains a quantized scalefactor sf_quant and 20 quantized residuals qrNN:
.- QOA_SLICE -- 64 bits, 20 samples --------------------------/ /------------. | Byte[0] | Byte[1] | Byte[2] \ \ Byte[7] | | 7 6 5 4 3 2 1 0 | 7 6 5 4 3 2 1 0 | 7 6 5 / / 2 1 0 | |------------+--------+--------+--------+---------+---------+-\ \--+---------| | sf_quant | qr00 | qr01 | qr02 | qr03 | qr04 | / / | qr19 | `-------------------------------------------------------------\ \------------`
Each frame except the last must contain exactly 256 slices per channel. The last frame may contain between 1 .. 256 (inclusive) slices per channel. The last slice (for each channel) in the last frame may contain less than 20 samples; the slice still must be 8 bytes wide, with the unused samples zeroed out.
Channels are interleaved per slice. E.g. for 2 channel stereo: slice[0] = L, slice[1] = R, slice[2] = L, slice[3] = R ...
A valid QOA file or stream must have at least one frame. Each frame must contain at least one channel and one sample with a samplerate between 1 .. 16777215 (inclusive).
If the total number of samples is not known by the encoder, the samples in the file header may be set to 0x00000000 to indicate that the encoder is "streaming". In a streaming context, the samplerate and number of channels may differ from frame to frame. For static files (those with samples set to a non-zero value), each frame must have the same number of channels and same samplerate.
Note that this implementation of QOA only handles files with a known total number of samples.
A decoder should support at least 8 channels. The channel layout for channel counts 1 .. 8 is:
- Mono
- L, R
- L, R, C
- FL, FR, B/SL, B/SR
- FL, FR, C, B/SL, B/SR
- FL, FR, C, LFE, B/SL, B/SR
- FL, FR, C, LFE, B, SL, SR
- FL, FR, C, LFE, BL, BR, SL, SR
QOA predicts each audio sample based on the previously decoded ones using a "Sign-Sign Least Mean Squares Filter" (LMS). This prediction plus the dequantized residual forms the final output sample.
Index ¶
Constants ¶
const ( // QOAMagic is the magic number identifying a QOA file QOAMagic = 0x716f6166 // 'qoaf' // QOAMinFilesize is the minimum valid size of a QOA file. QOAMinFilesize = 16 // QOAMaxChannels is the maximum number of audio channels supported by QOA. QOAMaxChannels = 8 // QOASliceLen is the length of each QOA audio slice. QOASliceLen = 20 // QOASlicesPerFrame is the number of slices per QOA frame. QOASlicesPerFrame = 256 // QOAFrameLen is the length of a QOA frame. QOAFrameLen = QOASlicesPerFrame * QOASliceLen // QOALMSLen is the length of the LMS state per channel. QOALMSLen = 4 )
Variables ¶
var ErrInvalidArgument = errors.New("invalid argument")
Functions ¶
func IsValidQOAFile ¶
Types ¶
type QOA ¶
type QOA struct { Channels uint32 // Number of audio channels SampleRate uint32 // Sample rate of the audio Samples uint32 // Total number of audio samples ErrorCount int // Sum of best LMS errors encountered during encoding // contains filtered or unexported fields }
QOA stores the QOA audio file description.
func Decode ¶
Decode decodes the provided QOA encoded bytes and returns the QOA struct and the decoded audio sample data.
func DecodeHeader ¶
DecodeHeader decodes the QOA header and initializes the QOA struct with header information.
func NewEncoder ¶
NewEncoder creates a new QOA encoder with the specified sample rate, channels, and samples.
type Reader ¶
type Reader struct {
// contains filtered or unexported fields
}
Reader is a custom io.Reader that reads from QOA audio data.