func readStreamInfo(r io.Reader) (*StreamInfo, error) { fs, err := bit.NewReader(r).ReadFields(16, 16, 24, 24, 20, 3, 5, 36) if err != nil { return nil, err } info := &StreamInfo{ MinBlock: int(fs[0]), MaxBlock: int(fs[1]), MinFrame: int(fs[2]), MaxFrame: int(fs[3]), SampleRate: int(fs[4]), NChannels: int(fs[5]) + 1, BitsPerSample: int(fs[6]) + 1, TotalSamples: int64(fs[7]), } csum, err := ioutil.ReadAll(r) if err != nil { return nil, err } if len(csum) != md5.Size { return nil, errors.New("Bad MD5 checksum size") } copy(info.MD5[:], csum) if info.SampleRate == 0 { return info, errors.New("Bad sample rate") } return info, nil }
// Next returns the audio data from the next frame. func (d *Decoder) Next() ([]byte, error) { defer func() { d.n++ }() raw := bytes.NewBuffer(nil) frame := io.TeeReader(d.r, raw) h, err := readFrameHeader(frame, d.StreamInfo) if err == io.EOF { return nil, err } else if err != nil { return nil, errors.New("Failed to read the frame header: " + err.Error()) } br := bit.NewReader(frame) data := make([][]int32, h.channelAssignment.nChannels()) for ch := range data { if data[ch], err = readSubFrame(br, h, ch); err != nil { return nil, err } } // The bit.Reader buffers up to the next byte, so reading from frame occurs // on the next byte boundary. That takes care of the padding to align to the // next byte. var crc16 [2]byte if _, err := io.ReadFull(frame, crc16[:]); err != nil { return nil, err } if err = verifyCRC16(raw.Bytes()); err != nil { return nil, err } fixChannels(data, h.channelAssignment) return interleave(data, d.BitsPerSample) }
func readMetaDataHeader(r io.Reader) (last bool, kind blockType, n int32, err error) { const headerSize = 32 // bits br := bit.NewReader(&io.LimitedReader{R: r, N: headerSize}) fs, err := br.ReadFields(1, 7, 24) if err != nil { return false, 0, 0, err } return fs[0] == 1, blockType(fs[1]), int32(fs[2]), nil }
func TestUTF8Decode(t *testing.T) { tests := []struct { data []byte val uint64 }{ {[]byte{0x7F}, 0x7F}, {[]byte{0xC2, 0xA2}, 0xA2}, {[]byte{0xC2, 0x80}, 0x080}, {[]byte{0xDF, 0xBF}, 0x7FF}, {[]byte{0xE2, 0x82, 0xAC}, 0x20AC}, {[]byte{0xE0, 0xA0, 0x80}, 0x800}, {[]byte{0xEF, 0xBF, 0xBF}, 0xFFFF}, {[]byte{0xF0, 0x90, 0x80, 0x80}, 0x10000}, {[]byte{0xF7, 0xBF, 0xBF, 0xBF}, 0x1FFFFF}, {[]byte{0xF0, 0xA4, 0xAD, 0xA2}, 0x24B62}, {[]byte{0xF8, 0x88, 0x80, 0x80, 0x80}, 0x200000}, {[]byte{0xFB, 0xBF, 0xBF, 0xBF, 0xBF}, 0x3FFFFFF}, {[]byte{0xFC, 0x84, 0x80, 0x80, 0x80, 0x80}, 0x4000000}, {[]byte{0xFD, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF}, 0x7FFFFFFF}, } for _, test := range tests { br := bit.NewReader(bytes.NewReader(test.data)) switch v, err := utf8Decode(br); { case err != nil: t.Errorf("Unexpected error decoding %v: %v", test.data, err) case v != test.val: t.Errorf("Expected %v to decode to %v, got %v", test.data, test.val, v) } } }
func readFrameHeader(r io.Reader, info *StreamInfo) (*frameHeader, error) { raw := bytes.NewBuffer(nil) br := bit.NewReader(io.TeeReader(r, raw)) const syncCode = 0x3FFE switch sync, err := br.Read(14); { case err == nil && sync != syncCode: return nil, errors.New("Failed to find the synchronize code for the next frame") case err != nil: return nil, err } fs, err := br.ReadFields(1, 1, 4, 4, 4, 3, 1) if err != nil { return nil, err } if fs[0] != 0 || fs[6] != 0 { return nil, errors.New("Invalid reserved value in frame header") } h := new(frameHeader) h.variableSize = fs[1] == 1 blockSize := fs[2] sampleRate := fs[3] h.channelAssignment = channelAssignment(fs[4]) if h.channelAssignment > midSide { return nil, errors.New("Bad channel assignment") } switch sampleSize := fs[5]; sampleSize { case 0: h.sampleSize = info.BitsPerSample case 3, 7: return nil, errors.New("Bad sample size in frame header") default: h.sampleSize = sampleSizes[sampleSize] } if h.number, err = utf8Decode(br); err != nil { return nil, err } switch blockSize { case 0: return nil, errors.New("Bad block size in frame header") case 6: sz, err := br.Read(8) if err != nil { return nil, err } h.blockSize = int(sz) + 1 case 7: sz, err := br.Read(16) if err != nil { return nil, err } h.blockSize = int(sz) + 1 default: h.blockSize = blockSizes[blockSize] } switch sampleRate { case 0: h.sampleRate = info.SampleRate case 12: r, err := br.Read(8) if err != nil { return nil, err } h.sampleRate = int(r) case 13: r, err := br.Read(16) if err != nil { return nil, err } h.sampleRate = int(r) case 14: r, err := br.Read(16) if err != nil { return nil, err } h.sampleRate = int(r * 10) default: h.sampleRate = sampleRates[sampleRate] } crc8, err := br.Read(8) if err != nil { return nil, err } h.crc8 = byte(crc8) return h, verifyCRC8(raw.Bytes()) }