diff --git a/hash.go b/hash.go index 37ae981..c19276a 100644 --- a/hash.go +++ b/hash.go @@ -9,19 +9,14 @@ import ( "os" ) -// Hash creates a hash of the audio file data provided by the io.ReadSeeker -// which ignores metadata (ID3, MP4) associated with the file. +// Hash creates a hash of the audio file data provided by the io.ReadSeeker which metadata +// (ID3, MP4) invariant. func Hash(r io.ReadSeeker) (string, error) { b, err := readBytes(r, 11) if err != nil { return "", err } - _, err = r.Seek(0, os.SEEK_SET) - if err != nil { - return "", err - } - if string(b[4:11]) == "ftypM4A" { return HashAtoms(r) } @@ -42,6 +37,11 @@ func Hash(r io.ReadSeeker) (string, error) { // HashAll returns a hash of the entire content. func HashAll(r io.ReadSeeker) (string, error) { + _, err := r.Seek(0, os.SEEK_SET) + if err != nil { + return "", fmt.Errorf("error seeking to 0: %v", err) + } + b, err := ioutil.ReadAll(r) if err != nil { return "", nil @@ -49,7 +49,13 @@ func HashAll(r io.ReadSeeker) (string, error) { return hash(b), nil } +// HashAtoms constructs a hash of MP4 audio file data provided by the io.ReadSeeker which is metadata invariant. func HashAtoms(r io.ReadSeeker) (string, error) { + _, err := r.Seek(0, os.SEEK_SET) + if err != nil { + return "", fmt.Errorf("error seeking to 0: %v", err) + } + for { var size uint32 err := binary.Read(r, binary.BigEndian, &size) @@ -99,10 +105,12 @@ func HashAtoms(r io.ReadSeeker) (string, error) { } } +// HashID3v1 constructs a hash of MP3 audio file data (assumed to have ID3v1 tags) provided by the +// io.ReadSeeker which is metadata invariant. func HashID3v1(r io.ReadSeeker) (string, error) { _, err := r.Seek(0, os.SEEK_SET) if err != nil { - return "", err + return "", fmt.Errorf("error seeking to 0: %v", err) } b, err := ioutil.ReadAll(r) @@ -116,7 +124,14 @@ func HashID3v1(r io.ReadSeeker) (string, error) { return hash(b[:len(b)-128]), nil } +// HashID3v2 constructs a hash of MP3 audio file data (assumed to have ID3v2 tags) provided by the +// io.ReadSeeker which is metadata invariant. func HashID3v2(r io.ReadSeeker) (string, error) { + _, err := r.Seek(0, os.SEEK_SET) + if err != nil { + return "", fmt.Errorf("error seeking to 0: %v", err) + } + h, err := readID3v2Header(r) if err != nil { return "", fmt.Errorf("error reading ID3v2 header: %v", err) diff --git a/id3v1.go b/id3v1.go index c37dfac..d054cbe 100644 --- a/id3v1.go +++ b/id3v1.go @@ -13,8 +13,8 @@ import ( "strings" ) -// ID3v1Genres is a list of genres as given in the ID3v1 specification. -var ID3v1Genres = [...]string{ +// id3v1Genres is a list of genres as given in the ID3v1 specification. +var id3v1Genres = [...]string{ "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge", "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies", "Other", "Pop", "R&B", "Rap", "Reggae", "Rock", "Techno", "Industrial", "Alternative", "Ska", @@ -95,8 +95,8 @@ func ReadID3v1Tags(r io.Reader) (Metadata, error) { if err != nil { return nil, err } - if int(genreID[0]) < len(ID3v1Genres) { - genre = ID3v1Genres[int(genreID[0])] + if int(genreID[0]) < len(id3v1Genres) { + genre = id3v1Genres[int(genreID[0])] } m := make(map[string]interface{})