frame: simplify parseHeader by refactoring
Fixes lint issue reported by gocyclo: frame/frame.go:212:1: cyclomatic complexity 52 of func `(*Frame).parseHeader` is high (> 30) (gocyclo) func (frame *Frame) parseHeader() error { ^ Updates #25.
This commit is contained in:
parent
f6859d9088
commit
46e9cd6b14
167
frame/frame.go
167
frame/frame.go
|
@ -121,7 +121,7 @@ func (frame *Frame) Parse() error {
|
|||
}
|
||||
|
||||
// Parse subframe.
|
||||
frame.Subframes[channel], err = frame.parseSubframe(bps)
|
||||
frame.Subframes[channel], err = frame.parseSubframe(frame.br, bps)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -215,9 +215,11 @@ func (frame *Frame) parseHeader() error {
|
|||
h := crc8.NewATM()
|
||||
hr := io.TeeReader(frame.hr, h)
|
||||
|
||||
// 14 bits: sync-code (11111111111110)
|
||||
// Create bit reader.
|
||||
br := bits.NewReader(hr)
|
||||
frame.br = br
|
||||
|
||||
// 14 bits: sync-code (11111111111110)
|
||||
x, err := br.Read(14)
|
||||
if err != nil {
|
||||
// This is the only place an audio frame may return io.EOF, which signals
|
||||
|
@ -260,38 +262,65 @@ func (frame *Frame) parseHeader() error {
|
|||
return unexpected(err)
|
||||
}
|
||||
|
||||
// 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)
|
||||
if err != nil {
|
||||
return unexpected(err)
|
||||
// Parse channels.
|
||||
if err := frame.parseChannels(br); err != nil {
|
||||
return err
|
||||
}
|
||||
if x >= 0xB {
|
||||
return fmt.Errorf("frame.Frame.parseHeader: reserved channels bit pattern (%04b)", x)
|
||||
}
|
||||
frame.Channels = Channels(x)
|
||||
|
||||
// 3 bits: BitsPerSample.
|
||||
x, err = br.Read(3)
|
||||
// Parse bits per sample.
|
||||
if err := frame.parseBitsPerSample(br); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 1 bit: reserved.
|
||||
x, err = br.Read(1)
|
||||
if err != nil {
|
||||
return unexpected(err)
|
||||
}
|
||||
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.
|
||||
frame.Num, err = decodeUTF8Int(hr)
|
||||
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 {
|
||||
return fmt.Errorf("frame.Frame.parseHeader: CRC-8 checksum mismatch; expected %v, got %v", want, got)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseBitsPerSample parses the bits per sample of the header.
|
||||
func (frame *Frame) parseBitsPerSample(br *bits.Reader) error {
|
||||
// 3 bits: BitsPerSample.
|
||||
x, err := br.Read(3)
|
||||
if err != nil {
|
||||
return unexpected(err)
|
||||
}
|
||||
|
||||
// The 3 bits are used to specify the sample size as follows:
|
||||
// 000: unknown sample size; get from StreamInfo.
|
||||
// 001: 8 bits-per-sample.
|
||||
|
@ -328,27 +357,42 @@ func (frame *Frame) parseHeader() error {
|
|||
// 111: reserved.
|
||||
return fmt.Errorf("frame.Frame.parseHeader: reserved sample size bit pattern (%03b)", x)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 1 bit: reserved.
|
||||
x, err = br.Read(1)
|
||||
if err != nil {
|
||||
return unexpected(err)
|
||||
}
|
||||
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.
|
||||
frame.Num, err = decodeUTF8Int(hr)
|
||||
if err != nil {
|
||||
return unexpected(err)
|
||||
}
|
||||
|
||||
// Parse block size.
|
||||
// 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)
|
||||
if err != nil {
|
||||
return unexpected(err)
|
||||
}
|
||||
if x >= 0xB {
|
||||
return fmt.Errorf("frame.Frame.parseHeader: reserved channels bit pattern (%04b)", x)
|
||||
}
|
||||
frame.Channels = Channels(x)
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseBlockSize parses the block size of the header.
|
||||
func (frame *Frame) parseBlockSize(br *bits.Reader, blockSize uint64) error {
|
||||
// The 4 bits of n are used to specify the block size as follows:
|
||||
// 0000: reserved.
|
||||
// 0001: 192 samples.
|
||||
|
@ -371,14 +415,14 @@ func (frame *Frame) parseHeader() error {
|
|||
frame.BlockSize = 576 * (1 << (n - 2))
|
||||
case n == 0x6:
|
||||
// 0110: get 8 bit (block size)-1 from the end of the header.
|
||||
x, err = br.Read(8)
|
||||
x, err := br.Read(8)
|
||||
if err != nil {
|
||||
return unexpected(err)
|
||||
}
|
||||
frame.BlockSize = uint16(x + 1)
|
||||
case n == 0x7:
|
||||
// 0111: get 16 bit (block size)-1 from the end of the header.
|
||||
x, err = br.Read(16)
|
||||
x, err := br.Read(16)
|
||||
if err != nil {
|
||||
return unexpected(err)
|
||||
}
|
||||
|
@ -387,9 +431,11 @@ func (frame *Frame) parseHeader() error {
|
|||
// 1000-1111: 256 * 2^(n-8) samples.
|
||||
frame.BlockSize = 256 * (1 << (n - 8))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Parse sample rate.
|
||||
//
|
||||
// parseSampleRate parses the sample rate of the header.
|
||||
func (frame *Frame) parseSampleRate(br *bits.Reader, sampleRate uint64) error {
|
||||
// The 4 bits are used to specify the sample rate as follows:
|
||||
// 0000: unknown sample rate; get from StreamInfo.
|
||||
// 0001: 88.2 kHz.
|
||||
|
@ -449,7 +495,7 @@ func (frame *Frame) parseHeader() error {
|
|||
frame.SampleRate = 96000
|
||||
case 0xC:
|
||||
// 1100: get 8 bit sample rate (in kHz) from the end of the header.
|
||||
x, err = br.Read(8)
|
||||
x, err := br.Read(8)
|
||||
if err != nil {
|
||||
return unexpected(err)
|
||||
}
|
||||
|
@ -458,14 +504,14 @@ func (frame *Frame) parseHeader() error {
|
|||
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)
|
||||
case 0xD:
|
||||
// 1101: get 16 bit sample rate (in Hz) from the end of the header.
|
||||
x, err = br.Read(16)
|
||||
x, err := br.Read(16)
|
||||
if err != nil {
|
||||
return unexpected(err)
|
||||
}
|
||||
frame.SampleRate = uint32(x)
|
||||
case 0xE:
|
||||
// 1110: get 16 bit sample rate (in daHz) from the end of the header.
|
||||
x, err = br.Read(16)
|
||||
x, err := br.Read(16)
|
||||
if err != nil {
|
||||
return unexpected(err)
|
||||
}
|
||||
|
@ -476,17 +522,6 @@ func (frame *Frame) parseHeader() error {
|
|||
// 1111: invalid.
|
||||
return errors.New("frame.Frame.parseHeader: invalid sample rate bit pattern (1111)")
|
||||
}
|
||||
|
||||
// 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 got != want {
|
||||
return fmt.Errorf("frame.Frame.parseHeader: CRC-8 checksum mismatch; expected %v, got %v", want, got)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -28,10 +28,10 @@ type Subframe struct {
|
|||
|
||||
// parseSubframe reads and parses the header, and the audio samples of a
|
||||
// subframe.
|
||||
func (frame *Frame) parseSubframe(bps uint) (subframe *Subframe, err error) {
|
||||
func (frame *Frame) parseSubframe(br *bits.Reader, bps uint) (subframe *Subframe, err error) {
|
||||
// Parse subframe header.
|
||||
subframe = new(Subframe)
|
||||
if err = subframe.parseHeader(frame.br); err != nil {
|
||||
if err = subframe.parseHeader(br); err != nil {
|
||||
return subframe, err
|
||||
}
|
||||
// Adjust bps of subframe for wasted bits-per-sample.
|
||||
|
@ -42,13 +42,13 @@ func (frame *Frame) parseSubframe(bps uint) (subframe *Subframe, err error) {
|
|||
subframe.Samples = make([]int32, 0, subframe.NSamples)
|
||||
switch subframe.Pred {
|
||||
case PredConstant:
|
||||
err = subframe.decodeConstant(frame.br, bps)
|
||||
err = subframe.decodeConstant(br, bps)
|
||||
case PredVerbatim:
|
||||
err = subframe.decodeVerbatim(frame.br, bps)
|
||||
err = subframe.decodeVerbatim(br, bps)
|
||||
case PredFixed:
|
||||
err = subframe.decodeFixed(frame.br, bps)
|
||||
err = subframe.decodeFixed(br, bps)
|
||||
case PredFIR:
|
||||
err = subframe.decodeFIR(frame.br, bps)
|
||||
err = subframe.decodeFIR(br, bps)
|
||||
}
|
||||
|
||||
// Left shift to accout for wasted bits-per-sample.
|
||||
|
|
Loading…
Reference in a new issue