// parseHeader reads and parses the header of a metadata block. func (block *Block) parseHeader(r io.Reader) error { // 1 bit: IsLast. br := bits.NewReader(r) x, err := br.Read(1) if err != nil { // This is the only place a metadata block may return io.EOF, which // signals a graceful end of a FLAC stream (from a metadata point of // view). // // Note that valid FLAC streams always contain at least one audio frame // after the last metadata block. Therefore an io.EOF error at this // location is always invalid. This logic is to be handled by the flac // package however. return err } if x != 0 { block.IsLast = true } // 7 bits: Type. x, err = br.Read(7) if err != nil { return unexpected(err) } block.Type = Type(x) // 24 bits: Length. x, err = br.Read(24) if err != nil { return unexpected(err) } block.Length = int64(x) return nil }
// parseHeader reads and parses the header of an audio frame. func (frame *Frame) parseHeader() error { // Create a new CRC-8 hash reader which adds the data from all read // operations to a running hash. h := crc8.NewATM() hr := io.TeeReader(frame.hr, h) // 14 bits: sync-code (11111111111110) br := bits.NewReader(hr) frame.br = br x, err := br.Read(14) if err != nil { // This is the only place an audio frame may return io.EOF, which signals // a graceful end of a FLAC stream. return err } if x != 0x3FFE { return ErrInvalidSync } // 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") } // 1 bit: HasFixedBlockSize. x, err = br.Read(1) if err != nil { return unexpected(err) } if x == 0 { 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 { return unexpected(err) } // 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 { 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) } 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) 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. // 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 // 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) case 0x4: // 100: 16 bits-per-sample. frame.BitsPerSample = 16 case 0x5: // 101: 20 bits-per-sample. frame.BitsPerSample = 20 // 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) 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) } // 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. // // 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 // 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) 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. 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) if err != nil { return unexpected(err) } frame.BlockSize = uint16(x + 1) default: // 1000-1111: 256 * 2^(n-8) samples. frame.BlockSize = 256 * (1 << (n - 8)) } // Parse sample rate. // // 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 // 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) case 0x3: // 0011: 192 kHz. frame.SampleRate = 192000 case 0x4: // 0100: 8 kHz. frame.SampleRate = 8000 case 0x5: // 0101: 16 kHz. frame.SampleRate = 16000 // 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) case 0x6: // 0110: 22.05 kHz. frame.SampleRate = 22050 case 0x7: // 0111: 24 kHz. frame.SampleRate = 24000 // 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) 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. x, err = br.Read(8) if err != nil { return unexpected(err) } frame.SampleRate = uint32(x * 1000) // 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) case 0xD: // 1101: get 16 bit sample rate (in Hz) from the end of the header. 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) if err != nil { return unexpected(err) } frame.SampleRate = uint32(x * 10) // 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) default: // 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 }
// parseStreamInfo reads and parses the body of a StreamInfo metadata block. func (block *Block) parseStreamInfo() error { // 16 bits: BlockSizeMin. br := bits.NewReader(block.lr) x, err := br.Read(16) if err != nil { return unexpected(err) } if x < 16 { return fmt.Errorf("meta.Block.parseStreamInfo: invalid minimum block size (%d); expected >= 16", x) } si := new(StreamInfo) block.Body = si si.BlockSizeMin = uint16(x) // 16 bits: BlockSizeMax. x, err = br.Read(16) if err != nil { return unexpected(err) } if x < 16 { return fmt.Errorf("meta.Block.parseStreamInfo: invalid maximum block size (%d); expected >= 16", x) } si.BlockSizeMax = uint16(x) // 24 bits: FrameSizeMin. x, err = br.Read(24) if err != nil { return unexpected(err) } si.FrameSizeMin = uint32(x) // 24 bits: FrameSizeMax. x, err = br.Read(24) if err != nil { return unexpected(err) } si.FrameSizeMax = uint32(x) // 20 bits: SampleRate. x, err = br.Read(20) if err != nil { return unexpected(err) } if x == 0 { return errors.New("meta.Block.parseStreamInfo: invalid sample rate (0)") } si.SampleRate = uint32(x) // 3 bits: NChannels. x, err = br.Read(3) if err != nil { return unexpected(err) } // x contains: (number of channels) - 1 si.NChannels = uint8(x + 1) // 5 bits: BitsPerSample. x, err = br.Read(5) if err != nil { return unexpected(err) } // x contains: (bits-per-sample) - 1 si.BitsPerSample = uint8(x + 1) // 36 bits: NSamples. si.NSamples, err = br.Read(36) if err != nil { return unexpected(err) } // 16 bytes: MD5sum. _, err = io.ReadFull(block.lr, si.MD5sum[:]) return unexpected(err) }