2014-08-06 01:08:32 +00:00
// Package frame implements access to FLAC audio frames.
2014-08-07 23:04:38 +00:00
//
2014-08-08 00:38:26 +00:00
// A brief introduction of the FLAC audio format [1] follows. FLAC encoders
// divide the audio stream into blocks through a process called blocking [2]. A
// block contains the unencoded audio samples from all channels during a short
// period of time. Each audio block is divided into subblocks, one per channel.
2014-08-07 23:04:38 +00:00
//
// There is often a correlation between the left and right channel of stereo
2014-08-08 00:38:26 +00:00
// audio. Using inter-channel decorrelation [3] it is possible to store only one
2014-08-07 23:04:38 +00:00
// of the channels and the difference between the channels, or store the average
// of the channels and their difference. An encoder decorrelates audio samples
// as follows:
2022-07-16 22:07:10 +00:00
//
// mid = (left + right)/2 // average of the channels
// side = left - right // difference between the channels
2014-08-07 23:04:38 +00:00
//
2014-08-08 00:38:26 +00:00
// The blocks are encoded using a variety of prediction methods [4][5] and
2014-08-07 23:04:38 +00:00
// stored in frames. Blocks and subblocks contains unencoded audio samples while
// frames and subframes contain encoded audio samples. A FLAC stream contains
// one or more audio frames.
//
2022-07-16 22:07:10 +00:00
// [1]: https://www.xiph.org/flac/format.html#architecture
// [2]: https://www.xiph.org/flac/format.html#blocking
// [3]: https://www.xiph.org/flac/format.html#interchannel
// [4]: https://www.xiph.org/flac/format.html#prediction
// [5]: https://godoc.org/git.gammaspectra.live/S.O.N.G/flacgo/frame#Pred
2014-08-06 01:08:32 +00:00
package frame
2014-08-06 15:56:18 +00:00
import (
"encoding/binary"
"errors"
"fmt"
2014-08-08 06:17:39 +00:00
"hash"
2014-08-06 15:56:18 +00:00
"io"
2014-08-08 06:17:39 +00:00
"log"
2014-08-06 15:56:18 +00:00
2022-07-16 22:07:10 +00:00
"git.gammaspectra.live/S.O.N.G/flacgo/internal/bits"
"git.gammaspectra.live/S.O.N.G/flacgo/internal/hashutil"
"git.gammaspectra.live/S.O.N.G/flacgo/internal/hashutil/crc16"
"git.gammaspectra.live/S.O.N.G/flacgo/internal/hashutil/crc8"
"git.gammaspectra.live/S.O.N.G/flacgo/internal/utf8"
2014-08-06 15:56:18 +00:00
)
2014-08-06 01:08:32 +00:00
// A Frame contains the header and subframes of an audio frame. It holds the
// encoded samples from a block (a part) of the audio stream. Each subframe
// holding the samples from one of its channel.
//
// ref: https://www.xiph.org/flac/format.html#frame
type Frame struct {
// Audio frame header.
Header
// One subframe per channel, containing encoded audio samples.
2014-08-06 02:43:38 +00:00
Subframes [ ] * Subframe
2014-08-06 16:49:18 +00:00
// CRC-16 hash sum, calculated by read operations on hr.
crc hashutil . Hash16
2014-08-07 00:18:12 +00:00
// A bit reader, wrapping read operations to hr.
2014-09-30 00:24:15 +00:00
br * bits . Reader
2014-08-06 16:49:18 +00:00
// A CRC-16 hash reader, wrapping read operations to r.
hr io . Reader
2014-08-06 01:08:32 +00:00
// Underlying io.Reader.
r io . Reader
}
// New creates a new Frame for accessing the audio samples of r. It reads and
2014-08-08 03:33:21 +00:00
// parses an audio frame header. It returns io.EOF to signal a graceful end of
// FLAC stream.
//
// Call Frame.Parse to parse the audio samples of its subframes.
2014-08-06 01:08:32 +00:00
func New ( r io . Reader ) ( frame * Frame , err error ) {
2014-08-06 16:49:18 +00:00
// Create a new CRC-16 hash reader which adds the data from all read
// operations to a running hash.
crc := crc16 . NewIBM ( )
hr := io . TeeReader ( r , crc )
// Parse frame header.
frame = & Frame { crc : crc , hr : hr , r : r }
2014-08-06 01:08:32 +00:00
err = frame . parseHeader ( )
2014-08-06 16:49:18 +00:00
return frame , err
}
// Parse reads and parses the header, and the audio samples from each subframe
2014-08-06 21:19:33 +00:00
// of a frame. If the samples are inter-channel decorrelated between the
2014-08-08 03:33:21 +00:00
// subframes, it correlates them. It returns io.EOF to signal a graceful end of
// FLAC stream.
2014-08-06 16:49:18 +00:00
//
// ref: https://www.xiph.org/flac/format.html#interchannel
func Parse ( r io . Reader ) ( frame * Frame , err error ) {
// Parse frame header.
frame , err = New ( r )
2014-08-06 01:08:32 +00:00
if err != nil {
2014-08-06 16:49:18 +00:00
return frame , err
2014-08-06 01:08:32 +00:00
}
2014-08-06 16:49:18 +00:00
// Parse subframes.
err = frame . Parse ( )
return frame , err
2014-08-06 01:08:32 +00:00
}
2014-08-06 02:24:36 +00:00
// Parse reads and parses the audio samples from each subframe of the frame. If
2014-08-06 21:19:33 +00:00
// the samples are inter-channel decorrelated between the subframes, it
// correlates them.
2014-08-06 01:08:32 +00:00
//
// ref: https://www.xiph.org/flac/format.html#interchannel
func ( frame * Frame ) Parse ( ) error {
2014-08-06 16:49:18 +00:00
// Parse subframes.
frame . Subframes = make ( [ ] * Subframe , frame . Channels . Count ( ) )
var err error
2014-08-06 21:19:33 +00:00
for channel := range frame . Subframes {
// The side channel requires an extra bit per sample when using
// inter-channel decorrelation.
bps := uint ( frame . BitsPerSample )
switch frame . Channels {
case ChannelsSideRight :
// channel 0 is the side channel.
if channel == 0 {
bps ++
}
case ChannelsLeftSide , ChannelsMidSide :
// channel 1 is the side channel.
if channel == 1 {
bps ++
}
}
// Parse subframe.
2018-05-27 13:09:56 +00:00
frame . Subframes [ channel ] , err = frame . parseSubframe ( frame . br , bps )
2014-08-06 16:49:18 +00:00
if err != nil {
return err
}
}
2014-08-06 21:19:33 +00:00
// Inter-channel correlation of subframe samples.
frame . correlate ( )
2014-08-06 16:49:18 +00:00
// 2 bytes: CRC-16 checksum.
var want uint16
2016-07-21 22:56:37 +00:00
if err = binary . Read ( frame . r , binary . BigEndian , & want ) ; err != nil {
2014-08-08 03:33:21 +00:00
return unexpected ( err )
2014-08-06 16:49:18 +00:00
}
got := frame . crc . Sum16 ( )
if got != want {
2018-08-18 18:18:12 +00:00
return fmt . Errorf ( "frame.Frame.Parse: CRC-16 checksum mismatch; expected 0x%04X, got 0x%04X" , want , got )
2014-08-06 16:49:18 +00:00
}
return nil
2014-08-06 01:08:32 +00:00
}
2015-01-30 00:18:22 +00:00
// Hash adds the decoded audio samples of the frame to a running MD5 hash. It
2014-08-08 06:27:05 +00:00
// can be used in conjunction with StreamInfo.MD5sum to verify the integrity of
// the decoded audio samples.
//
// Note: The audio samples of the frame must be decoded before calling Hash.
2014-08-08 06:17:39 +00:00
func ( frame * Frame ) Hash ( md5sum hash . Hash ) {
// Write decoded samples to a running MD5 hash.
bps := frame . BitsPerSample
var buf [ 3 ] byte
for i := 0 ; i < int ( frame . BlockSize ) ; i ++ {
for _ , subframe := range frame . Subframes {
sample := subframe . Samples [ i ]
switch bps {
case 8 :
buf [ 0 ] = uint8 ( sample )
2018-05-27 12:39:47 +00:00
md5sum . Write ( buf [ : 1 ] )
2014-08-08 06:17:39 +00:00
case 16 :
buf [ 0 ] = uint8 ( sample )
buf [ 1 ] = uint8 ( sample >> 8 )
2018-05-27 12:39:47 +00:00
md5sum . Write ( buf [ : 2 ] )
2014-08-08 06:17:39 +00:00
case 24 :
buf [ 0 ] = uint8 ( sample )
buf [ 1 ] = uint8 ( sample >> 8 )
buf [ 2 ] = uint8 ( sample >> 16 )
2018-05-27 12:39:47 +00:00
md5sum . Write ( buf [ : ] )
2014-08-08 06:17:39 +00:00
default :
2016-02-11 03:05:58 +00:00
log . Printf ( "frame.Frame.Hash: support for %d-bit sample size not yet implemented" , bps )
2014-08-08 06:17:39 +00:00
}
}
}
}
2014-08-06 01:08:32 +00:00
// A Header contains the basic properties of an audio frame, such as its sample
// rate and channel count. To facilitate random access decoding each frame
// header starts with a sync-code. This allows the decoder to synchronize and
// locate the start of a frame header.
//
// ref: https://www.xiph.org/flac/format.html#frame_header
2014-08-06 02:24:36 +00:00
type Header struct {
// Specifies if the block size is fixed or variable.
HasFixedBlockSize bool
// Block size in inter-channel samples, i.e. the number of audio samples in
// each subframe.
BlockSize uint16
// Sample rate in Hz; a 0 value implies unknown, get sample rate from
// StreamInfo.
SampleRate uint32
// Specifies the number of channels (subframes) that exist in the frame,
2014-08-06 21:19:33 +00:00
// their order and possible inter-channel decorrelation.
2014-08-06 02:24:36 +00:00
Channels Channels
// Sample size in bits-per-sample; a 0 value implies unknown, get sample size
// from StreamInfo.
BitsPerSample uint8
// Specifies the frame number if the block size is fixed, and the first
// sample number in the frame otherwise. When using fixed block size, the
// first sample number in the frame can be derived by multiplying the frame
// number with the block size (in samples).
Num uint64
}
2014-08-06 01:08:32 +00:00
2014-08-06 15:56:18 +00:00
// Errors returned by Frame.parseHeader.
var (
ErrInvalidSync = errors . New ( "frame.Frame.parseHeader: invalid sync-code" )
)
2014-08-06 01:08:32 +00:00
// parseHeader reads and parses the header of an audio frame.
func ( frame * Frame ) parseHeader ( ) error {
2014-08-06 16:49:18 +00:00
// Create a new CRC-8 hash reader which adds the data from all read
// operations to a running hash.
2014-08-06 15:56:18 +00:00
h := crc8 . NewATM ( )
2014-08-06 16:49:18 +00:00
hr := io . TeeReader ( frame . hr , h )
2014-08-06 15:56:18 +00:00
2018-05-27 13:09:56 +00:00
// Create bit reader.
2014-09-30 00:24:15 +00:00
br := bits . NewReader ( hr )
2014-08-07 00:18:12 +00:00
frame . br = br
2018-05-27 13:09:56 +00:00
// 14 bits: sync-code (11111111111110)
2014-08-06 15:56:18 +00:00
x , err := br . Read ( 14 )
if err != nil {
2014-08-08 04:42:26 +00:00
// This is the only place an audio frame may return io.EOF, which signals
// a graceful end of a FLAC stream.
2014-08-06 15:56:18 +00:00
return err
}
if x != 0x3FFE {
return ErrInvalidSync
}
// 1 bit: reserved.
x , err = br . Read ( 1 )
if err != nil {
2014-08-08 03:33:21 +00:00
return unexpected ( err )
2014-08-06 15:56:18 +00:00
}
if x != 0 {
return errors . New ( "frame.Frame.parseHeader: non-zero reserved value" )
}
// 1 bit: HasFixedBlockSize.
x , err = br . Read ( 1 )
if err != nil {
2014-08-08 03:33:21 +00:00
return unexpected ( err )
2014-08-06 15:56:18 +00:00
}
2015-05-16 15:45:39 +00:00
if x == 0 {
2014-08-06 15:56:18 +00:00
frame . HasFixedBlockSize = true
}
// 4 bits: BlockSize. The block size parsing is simplified by deferring it to
// the end of the header.
blockSize , err := br . Read ( 4 )
if err != nil {
2014-08-08 03:33:21 +00:00
return unexpected ( err )
2014-08-06 15:56:18 +00:00
}
// 4 bits: SampleRate. The sample rate parsing is simplified by deferring it
// to the end of the header.
sampleRate , err := br . Read ( 4 )
if err != nil {
2014-08-08 03:33:21 +00:00
return unexpected ( err )
2014-08-06 15:56:18 +00:00
}
2018-05-27 13:09:56 +00:00
// Parse channels.
if err := frame . parseChannels ( br ) ; err != nil {
return err
}
// Parse bits per sample.
if err := frame . parseBitsPerSample ( br ) ; err != nil {
return err
}
// 1 bit: reserved.
x , err = br . Read ( 1 )
2014-08-06 15:56:18 +00:00
if err != nil {
2014-08-08 03:33:21 +00:00
return unexpected ( err )
2014-08-06 15:56:18 +00:00
}
2018-05-27 13:09:56 +00:00
if x != 0 {
return errors . New ( "frame.Frame.parseHeader: non-zero reserved value" )
}
// if (fixed block size)
// 1-6 bytes: UTF-8 encoded frame number.
// else
// 1-7 bytes: UTF-8 encoded sample number.
2018-08-18 18:18:12 +00:00
frame . Num , err = utf8 . Decode ( hr )
2018-05-27 13:09:56 +00:00
if err != nil {
return unexpected ( err )
}
// Parse block size.
if err := frame . parseBlockSize ( br , blockSize ) ; err != nil {
return err
}
// Parse sample rate.
if err := frame . parseSampleRate ( br , sampleRate ) ; err != nil {
return err
}
// 1 byte: CRC-8 checksum.
var want uint8
if err = binary . Read ( frame . hr , binary . BigEndian , & want ) ; err != nil {
return unexpected ( err )
}
got := h . Sum8 ( )
if want != got {
2018-08-18 18:18:12 +00:00
return fmt . Errorf ( "frame.Frame.parseHeader: CRC-8 checksum mismatch; expected 0x%02X, got 0x%02X" , want , got )
2014-08-06 15:56:18 +00:00
}
2018-05-27 13:09:56 +00:00
return nil
}
// parseBitsPerSample parses the bits per sample of the header.
func ( frame * Frame ) parseBitsPerSample ( br * bits . Reader ) error {
2014-08-06 15:56:18 +00:00
// 3 bits: BitsPerSample.
2018-05-27 13:09:56 +00:00
x , err := br . Read ( 3 )
2014-08-06 15:56:18 +00:00
if err != nil {
2014-08-08 03:33:21 +00:00
return unexpected ( err )
2014-08-06 15:56:18 +00:00
}
2018-05-27 13:09:56 +00:00
2014-08-06 15:56:18 +00:00
// The 3 bits are used to specify the sample size as follows:
// 000: unknown sample size; get from StreamInfo.
// 001: 8 bits-per-sample.
// 010: 12 bits-per-sample.
// 011: reserved.
// 100: 16 bits-per-sample.
// 101: 20 bits-per-sample.
// 110: 24 bits-per-sample.
// 111: reserved.
switch x {
case 0x0 :
// 000: unknown bits-per-sample; get from StreamInfo.
case 0x1 :
// 001: 8 bits-per-sample.
frame . BitsPerSample = 8
case 0x2 :
// 010: 12 bits-per-sample.
frame . BitsPerSample = 12
2016-02-11 03:05:58 +00:00
// TODO(u): Remove log message when the test cases have been extended.
log . Printf ( "frame.Frame.parseHeader: The flac library test cases do not yet include any audio files with %d bits-per-sample. If possible please consider contributing this audio sample to improve the reliability of the test cases." , frame . BitsPerSample )
2014-08-06 15:56:18 +00:00
case 0x4 :
// 100: 16 bits-per-sample.
frame . BitsPerSample = 16
case 0x5 :
// 101: 20 bits-per-sample.
frame . BitsPerSample = 20
2016-02-11 03:05:58 +00:00
// TODO(u): Remove log message when the test cases have been extended.
log . Printf ( "frame.Frame.parseHeader: The flac library test cases do not yet include any audio files with %d bits-per-sample. If possible please consider contributing this audio sample to improve the reliability of the test cases." , frame . BitsPerSample )
2014-08-06 15:56:18 +00:00
case 0x6 :
// 110: 24 bits-per-sample.
frame . BitsPerSample = 24
default :
// 011: reserved.
// 111: reserved.
return fmt . Errorf ( "frame.Frame.parseHeader: reserved sample size bit pattern (%03b)" , x )
}
2018-05-27 13:09:56 +00:00
return nil
}
2014-08-06 15:56:18 +00:00
2018-05-27 13:09:56 +00:00
// parseChannels parses the channels of the header.
func ( frame * Frame ) parseChannels ( br * bits . Reader ) error {
// 4 bits: Channels.
//
// The 4 bits are used to specify the channels as follows:
// 0000: (1 channel) mono.
// 0001: (2 channels) left, right.
// 0010: (3 channels) left, right, center.
// 0011: (4 channels) left, right, left surround, right surround.
// 0100: (5 channels) left, right, center, left surround, right surround.
// 0101: (6 channels) left, right, center, LFE, left surround, right surround.
// 0110: (7 channels) left, right, center, LFE, center surround, side left, side right.
// 0111: (8 channels) left, right, center, LFE, left surround, right surround, side left, side right.
// 1000: (2 channels) left, side; using inter-channel decorrelation.
// 1001: (2 channels) side, right; using inter-channel decorrelation.
// 1010: (2 channels) mid, side; using inter-channel decorrelation.
// 1011: reserved.
// 1100: reserved.
// 1101: reserved.
// 1111: reserved.
x , err := br . Read ( 4 )
2014-08-06 15:56:18 +00:00
if err != nil {
2014-08-08 03:33:21 +00:00
return unexpected ( err )
2014-08-06 15:56:18 +00:00
}
2018-05-27 13:09:56 +00:00
if x >= 0xB {
return fmt . Errorf ( "frame.Frame.parseHeader: reserved channels bit pattern (%04b)" , x )
2014-08-06 15:56:18 +00:00
}
2018-05-27 13:09:56 +00:00
frame . Channels = Channels ( x )
return nil
}
2014-08-06 15:56:18 +00:00
2018-05-27 13:09:56 +00:00
// parseBlockSize parses the block size of the header.
func ( frame * Frame ) parseBlockSize ( br * bits . Reader , blockSize uint64 ) error {
2014-08-06 15:56:18 +00:00
// The 4 bits of n are used to specify the block size as follows:
// 0000: reserved.
// 0001: 192 samples.
// 0010-0101: 576 * 2^(n-2) samples.
// 0110: get 8 bit (block size)-1 from the end of the header.
// 0111: get 16 bit (block size)-1 from the end of the header.
// 1000-1111: 256 * 2^(n-8) samples.
n := blockSize
switch {
case n == 0x0 :
// 0000: reserved.
return errors . New ( "frame.Frame.parseHeader: reserved block size bit pattern (0000)" )
case n == 0x1 :
// 0001: 192 samples.
frame . BlockSize = 192
2016-02-11 03:05:58 +00:00
// TODO(u): Remove log message when the test cases have been extended.
log . Printf ( "frame.Frame.parseHeader: The flac library test cases do not yet include any audio files with block size %d. If possible please consider contributing this audio sample to improve the reliability of the test cases." , frame . BlockSize )
2014-08-06 15:56:18 +00:00
case n >= 0x2 && n <= 0x5 :
// 0010-0101: 576 * 2^(n-2) samples.
frame . BlockSize = 576 * ( 1 << ( n - 2 ) )
case n == 0x6 :
// 0110: get 8 bit (block size)-1 from the end of the header.
2018-05-27 13:09:56 +00:00
x , err := br . Read ( 8 )
2014-08-06 15:56:18 +00:00
if err != nil {
2014-08-08 03:33:21 +00:00
return unexpected ( err )
2014-08-06 15:56:18 +00:00
}
frame . BlockSize = uint16 ( x + 1 )
case n == 0x7 :
// 0111: get 16 bit (block size)-1 from the end of the header.
2018-05-27 13:09:56 +00:00
x , err := br . Read ( 16 )
2014-08-06 15:56:18 +00:00
if err != nil {
2014-08-08 03:33:21 +00:00
return unexpected ( err )
2014-08-06 15:56:18 +00:00
}
frame . BlockSize = uint16 ( x + 1 )
default :
// 1000-1111: 256 * 2^(n-8) samples.
frame . BlockSize = 256 * ( 1 << ( n - 8 ) )
}
2018-05-27 13:09:56 +00:00
return nil
}
2014-08-06 15:56:18 +00:00
2018-05-27 13:09:56 +00:00
// parseSampleRate parses the sample rate of the header.
func ( frame * Frame ) parseSampleRate ( br * bits . Reader , sampleRate uint64 ) error {
2014-08-06 15:56:18 +00:00
// The 4 bits are used to specify the sample rate as follows:
// 0000: unknown sample rate; get from StreamInfo.
// 0001: 88.2 kHz.
// 0010: 176.4 kHz.
// 0011: 192 kHz.
// 0100: 8 kHz.
// 0101: 16 kHz.
// 0110: 22.05 kHz.
// 0111: 24 kHz.
// 1000: 32 kHz.
// 1001: 44.1 kHz.
// 1010: 48 kHz.
// 1011: 96 kHz.
// 1100: get 8 bit sample rate (in kHz) from the end of the header.
// 1101: get 16 bit sample rate (in Hz) from the end of the header.
// 1110: get 16 bit sample rate (in daHz) from the end of the header.
// 1111: invalid.
switch sampleRate {
case 0x0 :
// 0000: unknown sample rate; get from StreamInfo.
case 0x1 :
// 0001: 88.2 kHz.
frame . SampleRate = 88200
case 0x2 :
// 0010: 176.4 kHz.
frame . SampleRate = 176400
2016-02-11 03:05:58 +00:00
// TODO(u): Remove log message when the test cases have been extended.
log . Printf ( "frame.Frame.parseHeader: The flac library test cases do not yet include any audio files with sample rate %d. If possible please consider contributing this audio sample to improve the reliability of the test cases." , frame . SampleRate )
2014-08-06 15:56:18 +00:00
case 0x3 :
// 0011: 192 kHz.
frame . SampleRate = 192000
case 0x4 :
// 0100: 8 kHz.
frame . SampleRate = 8000
case 0x5 :
// 0101: 16 kHz.
frame . SampleRate = 16000
case 0x6 :
// 0110: 22.05 kHz.
frame . SampleRate = 22050
case 0x7 :
// 0111: 24 kHz.
frame . SampleRate = 24000
2016-02-11 03:05:58 +00:00
// TODO(u): Remove log message when the test cases have been extended.
log . Printf ( "frame.Frame.parseHeader: The flac library test cases do not yet include any audio files with sample rate %d. If possible please consider contributing this audio sample to improve the reliability of the test cases." , frame . SampleRate )
2014-08-06 15:56:18 +00:00
case 0x8 :
// 1000: 32 kHz.
frame . SampleRate = 32000
case 0x9 :
// 1001: 44.1 kHz.
frame . SampleRate = 44100
case 0xA :
// 1010: 48 kHz.
frame . SampleRate = 48000
case 0xB :
// 1011: 96 kHz.
frame . SampleRate = 96000
case 0xC :
// 1100: get 8 bit sample rate (in kHz) from the end of the header.
2018-05-27 13:09:56 +00:00
x , err := br . Read ( 8 )
2014-08-06 15:56:18 +00:00
if err != nil {
2014-08-08 03:33:21 +00:00
return unexpected ( err )
2014-08-06 15:56:18 +00:00
}
frame . SampleRate = uint32 ( x * 1000 )
2016-02-11 03:05:58 +00:00
// TODO(u): Remove log message when the test cases have been extended.
log . Printf ( "frame.Frame.parseHeader: The flac library test cases do not yet include any audio files with sample rate %d. If possible please consider contributing this audio sample to improve the reliability of the test cases." , frame . SampleRate )
2014-08-06 15:56:18 +00:00
case 0xD :
// 1101: get 16 bit sample rate (in Hz) from the end of the header.
2018-05-27 13:09:56 +00:00
x , err := br . Read ( 16 )
2014-08-06 15:56:18 +00:00
if err != nil {
2014-08-08 03:33:21 +00:00
return unexpected ( err )
2014-08-06 15:56:18 +00:00
}
frame . SampleRate = uint32 ( x )
case 0xE :
// 1110: get 16 bit sample rate (in daHz) from the end of the header.
2018-05-27 13:09:56 +00:00
x , err := br . Read ( 16 )
2014-08-06 15:56:18 +00:00
if err != nil {
2014-08-08 03:33:21 +00:00
return unexpected ( err )
2014-08-06 15:56:18 +00:00
}
frame . SampleRate = uint32 ( x * 10 )
2016-02-11 03:05:58 +00:00
// TODO(u): Remove log message when the test cases have been extended.
log . Printf ( "frame.Frame.parseHeader: The flac library test cases do not yet include any audio files with sample rate %d. If possible please consider contributing this audio sample to improve the reliability of the test cases." , frame . SampleRate )
2014-08-06 15:56:18 +00:00
default :
// 1111: invalid.
return errors . New ( "frame.Frame.parseHeader: invalid sample rate bit pattern (1111)" )
}
return nil
2014-08-06 01:08:32 +00:00
}
2014-08-06 02:24:36 +00:00
// Channels specifies the number of channels (subframes) that exist in a frame,
2014-08-06 21:19:33 +00:00
// their order and possible inter-channel decorrelation.
2014-08-06 02:24:36 +00:00
type Channels uint8
// Channel assignments. The following abbreviations are used:
2022-07-16 22:07:10 +00:00
//
// C: center (directly in front)
// R: right (standard stereo)
// Sr: side right (directly to the right)
// Rs: right surround (back right)
// Cs: center surround (rear center)
// Ls: left surround (back left)
// Sl: side left (directly to the left)
// L: left (standard stereo)
// Lfe: low-frequency effect (placed according to room acoustics)
2014-08-06 02:24:36 +00:00
//
// The first 6 channel constants follow the SMPTE/ITU-R channel order:
2022-07-16 22:07:10 +00:00
//
// L R C Lfe Ls Rs
2014-08-06 02:24:36 +00:00
const (
2014-08-06 21:19:33 +00:00
ChannelsMono Channels = iota // 1 channel: mono.
ChannelsLR // 2 channels: left, right.
ChannelsLRC // 3 channels: left, right, center.
ChannelsLRLsRs // 4 channels: left, right, left surround, right surround.
ChannelsLRCLsRs // 5 channels: left, right, center, left surround, right surround.
ChannelsLRCLfeLsRs // 6 channels: left, right, center, LFE, left surround, right surround.
ChannelsLRCLfeCsSlSr // 7 channels: left, right, center, LFE, center surround, side left, side right.
ChannelsLRCLfeLsRsSlSr // 8 channels: left, right, center, LFE, left surround, right surround, side left, side right.
ChannelsLeftSide // 2 channels: left, side; using inter-channel decorrelation.
ChannelsSideRight // 2 channels: side, right; using inter-channel decorrelation.
ChannelsMidSide // 2 channels: mid, side; using inter-channel decorrelation.
2014-08-06 02:24:36 +00:00
)
// nChannels specifies the number of channels used by each channel assignment.
var nChannels = [ ... ] int {
ChannelsMono : 1 ,
ChannelsLR : 2 ,
ChannelsLRC : 3 ,
ChannelsLRLsRs : 4 ,
ChannelsLRCLsRs : 5 ,
ChannelsLRCLfeLsRs : 6 ,
ChannelsLRCLfeCsSlSr : 7 ,
ChannelsLRCLfeLsRsSlSr : 8 ,
ChannelsLeftSide : 2 ,
ChannelsSideRight : 2 ,
ChannelsMidSide : 2 ,
}
2014-08-06 02:38:58 +00:00
// Count returns the number of channels (subframes) used by the provided channel
// assignment.
func ( channels Channels ) Count ( ) int {
return nChannels [ channels ]
}
2014-08-06 21:19:33 +00:00
// correlate reverts any inter-channel decorrelation between the samples of the
// subframes.
//
// An encoder decorrelates audio samples as follows:
2022-07-16 22:07:10 +00:00
//
// mid = (left + right)/2
// side = left - right
2014-08-06 21:19:33 +00:00
func ( frame * Frame ) correlate ( ) {
switch frame . Channels {
case ChannelsLeftSide :
// 2 channels: left, side; using inter-channel decorrelation.
left := frame . Subframes [ 0 ] . Samples
side := frame . Subframes [ 1 ] . Samples
for i := range side {
// right = left - side
side [ i ] = left [ i ] - side [ i ]
}
case ChannelsSideRight :
// 2 channels: side, right; using inter-channel decorrelation.
side := frame . Subframes [ 0 ] . Samples
right := frame . Subframes [ 1 ] . Samples
// left = right + side
for i := range side {
side [ i ] += right [ i ]
}
case ChannelsMidSide :
// 2 channels: mid, side; using inter-channel decorrelation.
mid := frame . Subframes [ 0 ] . Samples
side := frame . Subframes [ 1 ] . Samples
for i := range side {
// left = (2*mid + side)/2
// right = (2*mid - side)/2
m := mid [ i ]
s := side [ i ]
m *= 2
// Notice that the integer division in mid = (left + right)/2 discards
// the least significant bit. It can be reconstructed however, since a
2017-12-26 14:14:11 +00:00
// sum A+B and a difference A-B has the same least significant bit.
2014-08-06 21:19:33 +00:00
//
// ref: Data Compression: The Complete Reference (ch. 7, Decorrelation)
m |= s & 1
mid [ i ] = ( m + s ) / 2
side [ i ] = ( m - s ) / 2
}
}
}
2014-08-08 03:33:21 +00:00
2021-01-27 23:23:27 +00:00
// SampleNumber returns the first sample number contained within the frame.
func ( frame * Frame ) SampleNumber ( ) uint64 {
if frame . HasFixedBlockSize {
return frame . Num * uint64 ( frame . BlockSize )
}
return frame . Num
}
2014-08-08 03:33:21 +00:00
// unexpected returns io.ErrUnexpectedEOF if err is io.EOF, and returns err
// otherwise.
func unexpected ( err error ) error {
if err == io . EOF {
return io . ErrUnexpectedEOF
}
return err
}