Skip to content

Commit 36cc17e

Browse files
karlekmewmew
authored andcommitted
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
1 parent 50441e5 commit 36cc17e

File tree

4 files changed

+62
-7
lines changed

4 files changed

+62
-7
lines changed

‎enc.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func Encode(w io.Writer, stream *Stream) error {
2424
enc := &encoder{bw: bitio.NewWriter(buf)}
2525

2626
// Store FLAC signature.
27-
if _, err := enc.bw.Write(signature); err != nil {
27+
if _, err := enc.bw.Write(flacSignature); err != nil {
2828
return errutil.Err(err)
2929
}
3030

‎flac.go‎

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ import (
3030

3131
"github.com/mewkiz/flac/frame"
3232
"github.com/mewkiz/flac/meta"
33+
34+
"github.com/mikkyang/id3-go/encodedbytes"
3335
)
3436

3537
// 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) {
7981
return stream, nil
8082
}
8183

82-
// signature marks the beginning of a FLAC stream.
83-
var signature = []byte("fLaC")
84+
// flacSignature marks the beginning of a FLAC stream.
85+
var flacSignature = []byte("fLaC")
86+
87+
// id3Signature marks the beginning of an ID3 stream, used to skip over ID3 data.
88+
var id3Signature = []byte("ID3")
8489

8590
// parseStreamInfo verifies the signature which marks the beginning of a FLAC
8691
// stream, and parses the StreamInfo metadata block. It returns a boolean value
@@ -90,12 +95,24 @@ func (stream *Stream) parseStreamInfo() (isLast bool, err error) {
9095
// Verify FLAC signature.
9196
r := stream.r
9297
var buf [4]byte
93-
_, err = io.ReadFull(r, buf[:])
94-
if err != nil {
98+
if _, err = io.ReadFull(r, buf[:]); err != nil {
9599
return false, err
96100
}
97-
if !bytes.Equal(buf[:], signature) {
98-
return false, fmt.Errorf("flac.parseStreamInfo: invalid FLAC signature; expected %q, got %q", signature, buf)
101+
102+
// Skip prepended ID3v2 data.
103+
if bytes.Equal(buf[:3], id3Signature) {
104+
if err := stream.skipID3v2(); err != nil {
105+
return false, err
106+
}
107+
108+
// Second attempt at verifying signature.
109+
if _, err = io.ReadFull(r, buf[:]); err != nil {
110+
return false, err
111+
}
112+
}
113+
114+
if !bytes.Equal(buf[:], flacSignature) {
115+
return false, fmt.Errorf("flac.parseStreamInfo: invalid FLAC signature; expected %q, got %q", flacSignature, buf)
99116
}
100117

101118
// Parse StreamInfo metadata block.
@@ -111,6 +128,31 @@ func (stream *Stream) parseStreamInfo() (isLast bool, err error) {
111128
return block.IsLast, nil
112129
}
113130

131+
// skipId3v2 skips ID3v2 data prepended to flac files.
132+
func (stream *Stream) skipID3v2() error {
133+
r := bufio.NewReader(stream.r)
134+
135+
// Discard unnecessary data from the ID3v2 header.
136+
if _, err := r.Discard(2); err != nil {
137+
return err
138+
}
139+
140+
// Read the size from the ID3v2 header.
141+
var sizeBuf [4]byte
142+
if _, err := r.Read(sizeBuf[:]); err != nil {
143+
return err
144+
}
145+
146+
// The size is encoded as a synchsafe integer.
147+
size, err := encodedbytes.SynchInt(sizeBuf[:])
148+
if err != nil {
149+
return err
150+
}
151+
152+
_, err = r.Discard(int(size))
153+
return err
154+
}
155+
114156
// Parse creates a new Stream for accessing the metadata blocks and audio
115157
// samples of r. It reads and parses the FLAC signature and all metadata blocks.
116158
//

‎flac_test.go‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package flac_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/mewkiz/flac"
7+
)
8+
9+
func TestSkipID3v2(t *testing.T) {
10+
if _, err := flac.ParseFile("testdata/id3.flac"); err != nil {
11+
t.Fatal(err)
12+
}
13+
}

‎testdata/id3.flac‎

74.1 KB
Binary file not shown.

0 commit comments

Comments
 (0)