Skip ID3v2 data prepended to flac files on parsing (#21)
* Change signature to flacSignature In order to disambiguate the introduction of the ID3v2 signature. * Add check flac files containing ID3v2 data * Implement skipId3v2 Note: a new import for decoding synchronized integers from ID3v2 headers was introduced. * Add error checking on the r.Discard calls * Fix comments * Use limited scope for error handling * Capitalize ID in skipID3v2 * Fix comments * Add testcase for skipping id3 data
This commit is contained in:
parent
50441e5efb
commit
36cc17efed
2
enc.go
2
enc.go
|
@ -24,7 +24,7 @@ func Encode(w io.Writer, stream *Stream) error {
|
|||
enc := &encoder{bw: bitio.NewWriter(buf)}
|
||||
|
||||
// Store FLAC signature.
|
||||
if _, err := enc.bw.Write(signature); err != nil {
|
||||
if _, err := enc.bw.Write(flacSignature); err != nil {
|
||||
return errutil.Err(err)
|
||||
}
|
||||
|
||||
|
|
54
flac.go
54
flac.go
|
@ -30,6 +30,8 @@ import (
|
|||
|
||||
"github.com/mewkiz/flac/frame"
|
||||
"github.com/mewkiz/flac/meta"
|
||||
|
||||
"github.com/mikkyang/id3-go/encodedbytes"
|
||||
)
|
||||
|
||||
// A Stream contains the metadata blocks and provides access to the audio frames
|
||||
|
@ -79,8 +81,11 @@ func New(r io.Reader) (stream *Stream, err error) {
|
|||
return stream, nil
|
||||
}
|
||||
|
||||
// signature marks the beginning of a FLAC stream.
|
||||
var signature = []byte("fLaC")
|
||||
// flacSignature marks the beginning of a FLAC stream.
|
||||
var flacSignature = []byte("fLaC")
|
||||
|
||||
// id3Signature marks the beginning of an ID3 stream, used to skip over ID3 data.
|
||||
var id3Signature = []byte("ID3")
|
||||
|
||||
// parseStreamInfo verifies the signature which marks the beginning of a FLAC
|
||||
// stream, and parses the StreamInfo metadata block. It returns a boolean value
|
||||
|
@ -90,12 +95,24 @@ 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 {
|
||||
if _, err = io.ReadFull(r, buf[:]); 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)
|
||||
|
||||
// Skip prepended ID3v2 data.
|
||||
if bytes.Equal(buf[:3], id3Signature) {
|
||||
if err := stream.skipID3v2(); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Second attempt at verifying signature.
|
||||
if _, err = io.ReadFull(r, buf[:]); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
if !bytes.Equal(buf[:], flacSignature) {
|
||||
return false, fmt.Errorf("flac.parseStreamInfo: invalid FLAC signature; expected %q, got %q", flacSignature, buf)
|
||||
}
|
||||
|
||||
// Parse StreamInfo metadata block.
|
||||
|
@ -111,6 +128,31 @@ func (stream *Stream) parseStreamInfo() (isLast bool, err error) {
|
|||
return block.IsLast, nil
|
||||
}
|
||||
|
||||
// skipId3v2 skips ID3v2 data prepended to flac files.
|
||||
func (stream *Stream) skipID3v2() error {
|
||||
r := bufio.NewReader(stream.r)
|
||||
|
||||
// Discard unnecessary data from the ID3v2 header.
|
||||
if _, err := r.Discard(2); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Read the size from the ID3v2 header.
|
||||
var sizeBuf [4]byte
|
||||
if _, err := r.Read(sizeBuf[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// The size is encoded as a synchsafe integer.
|
||||
size, err := encodedbytes.SynchInt(sizeBuf[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Discard(int(size))
|
||||
return err
|
||||
}
|
||||
|
||||
// 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.
|
||||
//
|
||||
|
|
13
flac_test.go
Normal file
13
flac_test.go
Normal file
|
@ -0,0 +1,13 @@
|
|||
package flac_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/mewkiz/flac"
|
||||
)
|
||||
|
||||
func TestSkipID3v2(t *testing.T) {
|
||||
if _, err := flac.ParseFile("testdata/id3.flac"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
BIN
testdata/id3.flac
vendored
Normal file
BIN
testdata/id3.flac
vendored
Normal file
Binary file not shown.
Loading…
Reference in a new issue