Skip to content

Commit

Permalink
cleaner mod tracker code.
Browse files Browse the repository at this point in the history
  • Loading branch information
bengarrett committed Aug 11, 2024
1 parent 1c59b70 commit 57b357a
Show file tree
Hide file tree
Showing 2 changed files with 168 additions and 133 deletions.
159 changes: 71 additions & 88 deletions handler/app/internal/mf/mf.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,19 @@ type entry struct {
program bool
}

func (e *entry) parseDirEntry(path string, d fs.DirEntry, platform string) bool {
func (e *entry) ParseFile(path string, platform string) bool {
const skipEntry = true
info, err := os.Stat(path)
if err != nil {
return skipEntry
}
if info.IsDir() {
return skipEntry
}
return e.parse(path, platform, info)
}

func (e *entry) ParseDirEntry(path string, d fs.DirEntry, platform string) bool {
const skipEntry = true
if d.IsDir() {
return skipEntry
Expand All @@ -159,6 +171,11 @@ func (e *entry) parseDirEntry(path string, d fs.DirEntry, platform string) bool
if info == nil {
return skipEntry
}
return e.parse(path, platform, info)
}

func (e *entry) parse(path, platform string, info fs.FileInfo) bool {
const skipEntry = true
e.bytes = info.Size()
if e.bytes == 0 {
e.zeros++
Expand All @@ -176,110 +193,76 @@ func (e *entry) parseDirEntry(path string, d fs.DirEntry, platform string) bool
fmt.Fprintf(io.Discard, "ignore this error, %v", err)
return skipEntry
}
e.image, e.text, e.program = isImage(e.sign), isText(e.sign), isProgram(e.sign, platform)
if e.program {
r, _ := os.Open(path)
if r == nil {
return skipEntry
}
defer r.Close()
exec, err := magicnumber.FindExecutable(r)
if err == nil {
e.exec = exec
}
}
if e.sign == magicnumber.MusicModule {
r, _ := os.Open(path)
if r == nil {
return skipEntry
}
defer r.Close()
size := 1100
buf := make([]byte, size)
if _, err := io.ReadFull(r, buf); err == nil {
e.module = magicnumber.MusicMod(buf)
}
e.image = isImage(e.sign)
e.text = isText(e.sign)
e.program = isProgram(e.sign, platform)
switch {
case e.program:
return e.parseProgram(path)
case e.sign == magicnumber.MusicModule:
return e.parseMusicMod(path)
case e.sign == magicnumber.MPEG1AudioLayer3:
return e.parseMusicID3(path)
}
return !skipEntry
}

func (e *entry) parseFile(path string, platform string) bool {
func (e *entry) parseProgram(path string) bool {
const skipEntry = true
info, err := os.Stat(path)
if err != nil {
return skipEntry
}
if info.IsDir() {
r, _ := os.Open(path)
if r == nil {
return skipEntry
}
e.bytes = info.Size()
if e.bytes == 0 {
e.zeros++
return skipEntry
defer r.Close()
exec, err := magicnumber.FindExecutable(r)
if err == nil {
e.exec = exec
}
e.size = humanize.Bytes(uint64(info.Size()))
return !skipEntry
}

func (e *entry) parseMusicMod(path string) bool {
const skipEntry = true
r, _ := os.Open(path)
if r == nil {
return skipEntry
}
defer r.Close()
e.sign, err = magicnumber.Find1500B(r)
if err != nil {
fmt.Fprintf(io.Discard, "ignore this error, %v", err)
buf := make([]byte, magicnumber.MusicTrackerSize)
if _, err := io.ReadFull(r, buf); err == nil {
e.module = magicnumber.MusicTracker(buf)
}
return !skipEntry
}

func (e *entry) parseMusicID3(path string) bool {
const skipEntry = true
r1, _ := os.Open(path)
if r1 == nil {
return skipEntry
}
e.image, e.text, e.program = isImage(e.sign), isText(e.sign), isProgram(e.sign, platform)
if e.program {
r, _ := os.Open(path)
if r == nil {
return skipEntry
}
defer r.Close()
exec, err := magicnumber.FindExecutable(r)
if err == nil {
e.exec = exec
}
defer r1.Close()
size, offset := 128, int64(-128)
_, err := r1.Seek(offset, io.SeekEnd)
if err != nil {
return skipEntry
}
if e.sign == magicnumber.MusicModule {
r, _ := os.Open(path)
if r == nil {
return skipEntry
}
defer r.Close()
size := 1100
buf := make([]byte, size)
if _, err := io.ReadFull(r, buf); err == nil {
e.module = magicnumber.MusicMod(buf)
}
buf := make([]byte, size)
if _, err := io.ReadFull(r1, buf); err == nil {
e.module = magicnumber.MusicID3v1(buf)
}
if e.sign == magicnumber.MPEG1AudioLayer3 {
r, _ := os.Open(path)
if r == nil {
return skipEntry
}
defer r.Close()
size, offset := 128, int64(-128)
_, err = r.Seek(offset, io.SeekEnd)
if err != nil {
return skipEntry
}
buf := make([]byte, size)
if _, err := io.ReadFull(r, buf); err == nil {
e.module = magicnumber.MusicID3v1(buf)
}

rr, _ := os.Open(path)
if r == nil {
return skipEntry
}
defer r.Close()
buf = make([]byte, 1024*10)
x := ""
if _, err := io.ReadFull(rr, buf); err == nil {
x = magicnumber.MusicID3v2(buf)
}
fmt.Println("ID3v2.3:", x)
rr, _ := os.Open(path)
if rr == nil {
return skipEntry
}
defer rr.Close()
buf = make([]byte, 1024*10)
x := ""
if _, err := io.ReadFull(rr, buf); err == nil {
x = magicnumber.MusicID3v2(buf)
}
fmt.Println("ID3v2.3:", x)
return !skipEntry
}

Expand All @@ -303,7 +286,7 @@ func ListContent(art *models.File, src string) template.HTML {
return template.HTML(err.Error())
}
e := entry{zeros: zeroByteFiles}
if e.parseFile(src, platform) {
if e.ParseFile(src, platform) {
return "error, empty byte file"
}
var b strings.Builder
Expand Down Expand Up @@ -333,7 +316,7 @@ func ListContent(art *models.File, src string) template.HTML {
return skipEntry
}
e := entry{zeros: zeroByteFiles}
if e.parseDirEntry(path, d, platform) {
if e.ParseDirEntry(path, d, platform) {
zeroByteFiles = e.zeros
return skipEntry
}
Expand Down
142 changes: 97 additions & 45 deletions internal/magicnumber/synthesismusic.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import (

// Package file synthesismusic.go contains the functions that parse bytes as common synthesis and tracker music formats.

// MusicTrackerSize is the minimum buffer size of a tracked music metadata.
const MusicTrackerSize = 1024 * 2

func Midi(p []byte) bool {
const min = 4
if len(p) < min {
Expand All @@ -18,7 +21,7 @@ func Midi(p []byte) bool {

// Mod matches common tracked music formats in the byte slice.
func Mod(p []byte) bool {
return MusicMod(p) != ""
return MusicTracker(p) != ""
}

// MusicMod returns the tracked music format in the byte slice and
Expand All @@ -29,57 +32,106 @@ func Mod(p []byte) bool {
// [Modland] has a large collection of tracked music format documentation.
//
// [Modland]: https://ftp.modland.com/pub/documents/format_documentation/
func MusicMod(p []byte) string {
const offset, length = 1080, 4
if len(p) < offset+length {
return ""
}
mtnHeader := p[0:3]
switch {
case bytes.Equal(mtnHeader, []byte{'M', 'T', 'M'}):
s := "MultiTrack module music"
name := string(bytes.Trim(p[4:20+4], "\x00"))
if name != "" {
s += fmt.Sprintf(", %q", strings.TrimSpace(name))
}
func MusicTracker(p []byte) string {
if s := MusicMTM(p); s != "" {
return s
}
impulse := p[0:4]
switch {
case bytes.Equal(impulse, []byte{'I', 'M', 'P', 'M'}):
s := "Impulse Tracker module music"
name := string(bytes.Trim(p[4:20+4], "\x00"))
if name != "" {
s += fmt.Sprintf(", %q", strings.TrimSpace(name))
}
if s := MusicIT(p); s != "" {
return s
}
xmHeader := p[0:17]
fmt.Println(xmHeader, fmt.Sprintf("%q", xmHeader))
switch { //Extended module:
// Extended Module:
case bytes.Equal(xmHeader, []byte{'E', 'x', 't', 'e', 'n', 'd', 'e', 'd', 0x20,
'M', 'o', 'd', 'u', 'l', 'e', ':', 0x20}):
s := "extended module tracked music"
name := strings.TrimSpace(string(bytes.Trim(p[17:17+20], "\x00")))
if name != "" {
s += fmt.Sprintf(", %q", name)
}
if s := MusicXM(p); s != "" {
return s
}
modHeader := p[offset : offset+length]
switch {
case bytes.Equal(modHeader, []byte{'M', '.', 'K', '.'}):
// The original Amiga ProTracker MOD format had no signature.
// The M.K. signature was added by Mahoney & Kaktus in their MOD samples,
// and became a common signature in the MOD format.
s := "ProTracker module music"
name := string(bytes.Trim(p[0:20], "\x00"))
name = strings.TrimSpace(name)
if name != "" {
s += fmt.Sprintf(", %q", name)
}
if s := MusicMK(p); s != "" {
return s
}
return ""
}

// MusicMTM returns the [MultiTracker] song or title in the byte slice if available.
// The MultiTracker format is a tracked music format created by the scene group Renaissance.
//
// [MultiTracker]: https://ftp.modland.com/pub/documents/format_documentation/MultiTracker%20(.mtm).txt
func MusicMTM(p []byte) string {
const id, offset, headerLen = 3, 4, 20
if len(p) < id {
return ""
}
mtnHeader := p[0:id]
if !bytes.Equal(mtnHeader, []byte{'M', 'T', 'M'}) {
return ""
}
s := "MultiTrack song"
song := string(bytes.Trim(p[offset:headerLen+offset], "\x00"))
if song != "" {
s += fmt.Sprintf(", %q", strings.TrimSpace(song))
}
return s
}

// MusicIT returns the [Impulse Tracker] song or title in the byte slice if available.
// The Impulse Tracker format is a tracked music format created by Jeffrey Lim.
//
// [Impulse Tracker]: https://ftp.modland.com/pub/documents/format_documentation/Impulse%20Tracker%20v2.04%20(.it).html
func MusicIT(p []byte) string {
const id, offset, headerLen = 4, 4, 20
impulse := p[0:id]
if !bytes.Equal(impulse, []byte{'I', 'M', 'P', 'M'}) {
return ""
}
s := "Impulse Tracker song"
song := string(bytes.Trim(p[offset:headerLen+offset], "\x00"))
if song != "" {
s += fmt.Sprintf(", %q", strings.TrimSpace(song))
}
return s
}

// MusicXM returns the [eXtended Module] song or title in the byte slice if available.
// The XM format was originally used by FastTracker II (FT2) and later modified by other trackers.
//
// [eXtended Module]: https://ftp.modland.com/pub/documents/format_documentation/FastTracker%202%20v2.04%20(.xm).html
func MusicXM(p []byte) string {
const id, offset, headerLen = 17, 17, 20
if len(p) < id {
return ""
}
xmHeader := p[0:id]
if !bytes.Equal(xmHeader, []byte{'E', 'x', 't', 'e', 'n', 'd', 'e', 'd', 0x20,
'M', 'o', 'd', 'u', 'l', 'e', ':', 0x20}) {
return ""
}
s := "extended module tracked music"
song := string(bytes.Trim(p[offset:headerLen+offset], "\x00"))
if song != "" {
s += fmt.Sprintf(", %q", strings.TrimSpace(song))
}
return s
}

// MusicMK returns the MOD song or title in the byte slice if available.
// The Soundtracker MOD format is a tracked music format created by Karsten Obarski on the Commodore Amiga.
// The original MOD format had no signature, but the M.K. signature was added by Mahoney & Kaktus
// in their MOD samples and became a common signature in the MOD format.
//
// Common MOD formats include the original The Ultimate Soundtracker, Protracker, FastTracker II...
//
// [ProTracker]: https://ftp.modland.com/pub/documents/format_documentation/ProTracker%20v1.0%20(.mod).html
func MusicMK(p []byte) string {
const offset, length, headerLen = 1080, 4, 20
if len(p) < offset+length+headerLen {
return ""
}
modHeader := p[offset : offset+length]
if !bytes.Equal(modHeader, []byte{'M', '.', 'K', '.'}) {
return ""
}
s := "ProTracker song"
song := string(bytes.Trim(p[0:headerLen], "\x00"))
song = strings.TrimSpace(song)
fmt.Println("MusicMK", string(modHeader), "<>", song)
if song != "" {
s += fmt.Sprintf(", %q", song)
}
return s
}

0 comments on commit 57b357a

Please sign in to comment.