From 18bd1fb12dd62f0fbc53f0bbef6593dbd8aeb481 Mon Sep 17 00:00:00 2001 From: "Alexander \"Arav\" Andreev" Date: Sun, 1 Oct 2023 03:34:16 +0400 Subject: [PATCH] Implementation of a simple OGG tag reader. --- pkg/oggtag/oggtag.go | 23 +++++++++++++++++++++++ pkg/oggtag/oggtag_test.go | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 pkg/oggtag/oggtag.go create mode 100644 pkg/oggtag/oggtag_test.go diff --git a/pkg/oggtag/oggtag.go b/pkg/oggtag/oggtag.go new file mode 100644 index 0000000..7fcf8aa --- /dev/null +++ b/pkg/oggtag/oggtag.go @@ -0,0 +1,23 @@ +package oggtag + +/* oggtag is a naive implementation of OGG tag's reader that is just looking +for certain tag names ending with an = character, e.g. artist= and title=. +*/ + +import ( + "bytes" +) + +// OggGetTag is searching for a certain tag in a given buffer buf and returns +// its value. +// +// It is a simple implementation that doesn't parse a header and instead just +// looking for a certain tag preceded with three zero bytes and ends with +// an = character. +func OggGetTag(buf []byte, tag string) string { + tagIdx := bytes.Index(buf, append([]byte{0, 0, 0}, (tag+"=")...)) + 3 + tagNameLen := len(tag) + 1 + valStart := tagIdx + tagNameLen + valLen := int(buf[tagIdx-4]) - tagNameLen + return string(buf[valStart : valStart+valLen]) +} diff --git a/pkg/oggtag/oggtag_test.go b/pkg/oggtag/oggtag_test.go new file mode 100644 index 0000000..a98c23f --- /dev/null +++ b/pkg/oggtag/oggtag_test.go @@ -0,0 +1,35 @@ +package oggtag + +import ( + "os" + "testing" +) + +const bufferSize = 4096 +const sampleSong = "/mnt/data/appdata/radio/fallback.ogg" +const sampleArtist = "breskina" +const sampleTitle = "Песня про мечты" + +func TestOggGetTag(t *testing.T) { + f, _ := os.Open(sampleSong) + buf := make([]byte, bufferSize) + f.Read(buf) + tag := OggGetTag(buf, "artist") + if tag != sampleArtist { + t.Error(tag, "!=", sampleArtist) + } + tag = OggGetTag(buf, "title") + if tag != sampleTitle { + t.Error(tag, "!=", sampleTitle) + } +} + +func BenchmarkOggGetTag(b *testing.B) { + f, _ := os.Open(sampleSong) + buf := make([]byte, bufferSize) + f.Read(buf) + b.ResetTimer() + for i := 0; i < b.N; i++ { + OggGetTag(buf, "artist") + } +}