Added query by TOC

This commit is contained in:
DataHoarder 2022-02-20 01:15:21 +01:00
parent 0cf78c99eb
commit 64ed905c81
2 changed files with 196 additions and 3 deletions

View file

@ -14,6 +14,7 @@ import (
"io/fs"
"io/ioutil"
"log"
"math"
"net/http"
"os"
"path"
@ -471,8 +472,10 @@ func processIndexDirectory(filePath, indexPath, kind string, wg *sync.WaitGroup)
track.Original = strings.TrimSpace(strings.Join(getStringValue(entry.MainTitle, values), " "))
case "lyrics", "vocals", "arranger", "composer", "producer", "remix":
track.Artists = append(track.Artists, getArtistEntries(keyEntry, values)...)
case "arrangement", "original arrangement":
case "arrangement":
track.Artists = append(track.Artists, getArtistEntries("arranger", values)...)
case "original arrangement":
track.Artists = append(track.Artists, getArtistEntries("original arranger", values)...)
case "composition":
track.Artists = append(track.Artists, getArtistEntries("composer", values)...)
@ -594,9 +597,31 @@ func normalizeStringCharacters(text string) (normalized string) {
type findByDurationResult struct {
albumEntry *albumEntry
cddb1 utilities.CDDB1
toc utilities.TOC
discIndex int
}
func findByTOC(toc utilities.TOC, trackThreshold, discThreshold int) (results []findByDurationResult) {
for _, result := range findByCDDB1(toc.GetCDDB1(), discThreshold) {
func() {
for i, track := range result.albumEntry.Discs[result.discIndex].Tracks {
diff := math.Abs(float64(track.Duration) - toc.GetTrackDuration(i).Seconds())
if diff > float64(trackThreshold) { //too much variation
return
}
}
results = append(results, result)
}()
}
return
}
func findByCDDB1(cddb1 utilities.CDDB1, discThreshold int) []findByDurationResult {
return findByTracksAndDuration(cddb1.GetTrackNumber(), int(cddb1.GetDuration().Seconds()), discThreshold)
}
func findByTracksAndDuration(tracks, duration, threshold int) (results []findByDurationResult) {
for _, r := range discTracksLookup[tracks] {
for i, d := range r.Discs {
@ -668,13 +693,20 @@ func main() {
cddb1 := utilities.NewCDDB1FromString(splits[2])
//cddb1_calc := utilities.GetCDDB1FromTOC(splits[3:])
toc := utilities.NewTOCFromCDDBString(strings.Join(splits[3:], " "))
if cddb1 == 0 {
writer.Write([]byte("500 Command syntax error\n.\n"))
return
}
entries := findByTracksAndDuration(cddb1.GetTrackNumber(), int(cddb1.GetDuration().Seconds()), 10)
var entries []findByDurationResult
if toc != nil {
cddb1 = toc.GetCDDB1()
entries = findByTOC(toc, 3, 10)
} else {
entries = findByCDDB1(cddb1, 10)
}
if len(entries) == 0 {
writer.Write([]byte("202 No match found\n.\n"))
return

161
utilities/toc.go Normal file
View file

@ -0,0 +1,161 @@
package utilities
import (
"fmt"
"strconv"
"strings"
"time"
)
const TocPregap = 150
const SectorsPerSecond = 75
const DataTrackGap = 11400
const BytesPerSector = 2352
const CDChannels = 2
const Int16SamplesPerSector = BytesPerSector / (2 * CDChannels)
const CDSampleRate = Int16SamplesPerSector * SectorsPerSecond
//TOC includes a list, index 0 being total sectors/end, then start times follow, with TocPregap added
type TOC []int
func NewTOCFromString(toc string, split ...string) (r TOC) {
sep := " "
if len(split) > 0 {
sep = split[0]
}
for _, i := range strings.Split(toc, sep) {
item, err := strconv.Atoi(i)
if err == nil {
r = append(r, item)
}
}
return
}
func NewTOCFromCDDBString(toc string) (r TOC) {
t := NewTOCFromString(toc)
if len(t) < 3 {
return nil
}
t = t[1 : len(t)-1] //cut
r = append(TOC{t[len(t)-1]}, t[0:len(t)-1]...) //put last sample at the front
for i := 0; i < len(t); i++ {
r[i] += TocPregap
}
return
}
func NewTOCFromCTDBString(toc string) (r TOC) {
t := NewTOCFromString(toc)
r = append(r, t[len(t)-1]+TocPregap)
for i := 0; i < len(t)-1; i++ {
r = append(r, t[i]+TocPregap)
}
return
}
func NewTOCFromCTDB2String(toc string) (r TOC) {
t := NewTOCFromString(toc, ":")
r = append(r, t[len(t)-1]+TocPregap)
for i := 0; i < len(t)-1; i++ {
r = append(r, t[i]+TocPregap)
}
return
}
func (t TOC) GetTrackNumber() int {
return len(t) - 1
}
func (t TOC) GetDuration() time.Duration {
return (time.Second * time.Duration(t[0]-t[1])) / SectorsPerSecond
}
func (t TOC) GetTrackDuration(index int) time.Duration {
if index < 0 || index > len(t)-2 {
return 0
} else if index == len(t)-2 {
return (time.Second * time.Duration(t[0]-t[index+1])) / SectorsPerSecond
} else {
return (time.Second * time.Duration(t[index+2]-t[index+1])) / SectorsPerSecond
}
}
func (t TOC) CTDBString() string {
toc := make([]string, 0, len(t))
for _, o := range t[1:] {
toc = append(toc, fmt.Sprintf("%d", o-TocPregap))
}
toc = append(toc, fmt.Sprintf("%d", t[0]-TocPregap))
return strings.Join(toc, ":")
}
func (t TOC) CDDBString() string {
return fmt.Sprintf("%s %d %s %d", t.GetCDDB1(), t.GetTrackNumber(), t[1:].String(), int(t.GetDuration().Seconds()))
}
func (t TOC) MusicBrainzString() string {
return fmt.Sprintf("1 %d %s", t.GetTrackNumber(), t.String())
}
func (t TOC) String() string {
toc := make([]string, 0, len(t))
for _, o := range t {
toc = append(toc, fmt.Sprintf("%d", o))
}
return strings.Join(toc, " ")
}
func (t TOC) GetCDDB1() CDDB1 {
length := uint32(t.GetDuration().Seconds())
checksum := uint32(0)
for i := 1; i < len(t); i++ {
n := uint32(t[i] / SectorsPerSecond)
for n > 0 {
checksum += n % 10
n /= 10
}
}
return CDDB1(uint32((len(t)-1)&0xFF) | ((length & 0xFFFF) << 8) | ((checksum % 255) << 24))
}
func (t TOC) GetAccurateRipData() (byte, uint32, uint32, CDDB1) {
var TrackOffsetsAdded uint32
var TrackOffsetsMultiplied uint32
var num uint32
for i := 1; i < len(t); i++ {
start := uint32(t[i] - TocPregap)
TrackOffsetsAdded += start
if start < 1 {
start = 1
}
num++
TrackOffsetsMultiplied += start * num
}
TrackOffsetsAdded += uint32(t[0] - TocPregap)
num++
TrackOffsetsMultiplied += uint32(t[0]-TocPregap) * num
return byte(t.GetTrackNumber()), TrackOffsetsAdded, TrackOffsetsMultiplied, t.GetCDDB1()
}
func (t TOC) Equals(o TOC) bool {
if len(t) != len(o) {
return false
}
for i, d := range t {
if o[i] != d {
return false
}
}
return true
}