Example #1
0
File: meta.go Project: mewkiz/flac
// 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
}
Example #2
0
File: frame.go Project: mewkiz/flac
// 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
}
Example #3
0
// 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)
}