badger/internal/metadata/fingerprint.go
2023-03-14 09:53:33 +01:00

82 lines
2.4 KiB
Go

package metadata
import (
"strconv"
"strings"
"velvettear/badger/internal/executables"
"velvettear/badger/internal/log"
"velvettear/badger/internal/tools"
)
// exported function(s)
func FingerprintFromString(rawValue string) (Fingerprint, error) {
fingerprint := Fingerprint{RawValue: rawValue}
error := fingerprint.setValue()
return fingerprint, error
}
func CompareWith(fingerprint []int32, comparisonFingerprint []int32) float64 {
dist := 0
if len(fingerprint) != len(comparisonFingerprint) {
return 0
}
for index, value := range fingerprint {
dist += strings.Count(strconv.FormatInt(int64(value^comparisonFingerprint[index]), 2), "1")
}
return 1 - float64(dist)/float64(len(fingerprint)*32)
}
func (fingerprint *Fingerprint) CompareWith(comparison Fingerprint) float64 {
return CompareWith(fingerprint.Value, comparison.Value)
}
// unexported function(s)
func (metadata *Metadata) generateFingerprint() {
timestamp := tools.LogTimestamp()
executable, error := executables.GetExecutable(executables.FPCALC)
if error != nil {
log.Fatal("could not get executable '"+executables.FPCALC+"'", error.Error())
}
metadata.Fingerprint = Fingerprint{}
executable.Spawn("-raw", "-plain", metadata.Path)
result, error := executable.Spawn("-raw", "-plain", metadata.Path)
if error != nil {
log.Error("encountered an error spawning process '" + executables.FPCALC + "' for file '" + metadata.Path + "'")
return
}
metadata.Fingerprint.RawValue = strings.Trim(string(result), "\n")
error = metadata.Fingerprint.setValue()
if error != nil {
log.Error("encountered an error generating the audio fingerprint for file '"+metadata.Path+"'", error.Error())
return
}
if metadata.Fingerprint.Value == nil {
log.Warning("generated audio fingerprint for file '"+metadata.Path+"' is empty", error.Error())
}
log.DebugTimed("generated fingerprint for file '"+metadata.Path+"'", timestamp)
}
func (fingerprint *Fingerprint) setValue() error {
if len(fingerprint.RawValue) == 0 {
return nil
}
var caughtError error
intArray := strings.Split(fingerprint.RawValue, ",")
elementCount := len(intArray)
fingerprint.Value = make([]int32, elementCount)
for index := 0; index < elementCount; index++ {
tmp, error := strconv.Atoi(intArray[index])
if error != nil {
caughtError = error
tmp = 0
}
fingerprint.Value[index] = int32(tmp)
}
return caughtError
}
// struct(s)
type Fingerprint struct {
RawValue string
Value []int32
}