// Parse creates a new Stream for accessing the metadata blocks and audio // samples of r. It reads and parses the FLAC signature and all metadata blocks. // // Call Stream.Next to parse the frame header of the next audio frame, and call // Stream.ParseNext to parse the entire next frame including audio samples. func Parse(r io.Reader) (stream *Stream, err error) { // Verify FLAC signature and parse the StreamInfo metadata block. br := bufio.NewReader(r) stream = &Stream{r: br} isLast, err := stream.parseStreamInfo() if err != nil { return nil, err } // Parse the remaining metadata blocks. for !isLast { block, err := meta.Parse(br) if err != nil { if err != meta.ErrReservedType { return stream, err } // Skip the body of unknown (reserved) metadata blocks, as stated by // the specification. // // ref: https://www.xiph.org/flac/format.html#format_overview if err = block.Skip(); err != nil { return stream, err } } stream.Blocks = append(stream.Blocks, block) isLast = block.IsLast } return stream, nil }
// parseStreamInfo verifies the signature which marks the beginning of a FLAC // stream, and parses the StreamInfo metadata block. It returns a boolean value // which specifies if the StreamInfo block was the last metadata block of the // FLAC stream. func (stream *Stream) parseStreamInfo() (isLast bool, err error) { // Verify FLAC signature. r := stream.r var buf [4]byte _, err = io.ReadFull(r, buf[:]) if err != nil { return false, err } if !bytes.Equal(buf[:], signature) { return false, fmt.Errorf("flac.parseStreamInfo: invalid FLAC signature; expected %q, got %q", signature, buf) } // Parse StreamInfo metadata block. block, err := meta.Parse(r) if err != nil { return false, err } si, ok := block.Body.(*meta.StreamInfo) if !ok { return false, fmt.Errorf("flac.parseStreamInfo: incorrect type of first metadata block; expected *meta.StreamInfo, got %T", si) } stream.Info = si return block.IsLast, nil }