seek-tune/shazam/fingerprint.go
2024-05-03 05:29:48 +01:00

58 lines
1.8 KiB
Go

package shazam
import (
"fmt"
"song-recognition/models"
)
const (
maxFreqBits = 9
maxDeltaBits = 14
targetZoneSize = 5
)
// Fingerprint generates fingerprints from a list of peaks and stores them in an array.
// The fingerprints are encoded using a 32-bit integer format and stored in an array.
// Each fingerprint consists of an address and a table value.
// The address is calculated based on the frequency of the anchor and target points,
// as well as the delta time between them.
// The table value contains the anchor time and the song ID.
func Fingerprint(peaks []Peak, songID string) map[uint32]models.Table {
fingerprints := map[uint32]models.Table{}
duplicates := 0
for i, anchor := range peaks {
for j := i + 1; j < len(peaks) && j <= i+targetZoneSize; j++ {
target := peaks[j]
address := createAddress(anchor, target)
anchorTimeMs := uint32(anchor.Time * 1000)
_, ok := fingerprints[address]
if ok {
duplicates++
}
fingerprints[address] = models.Table{anchorTimeMs, songID}
}
}
fmt.Println("Duplicates: ", duplicates)
return fingerprints
}
// createAddress generates a unique address for a pair of anchor and target points.
// The address is a 32-bit integer where certain bits represent the frequency of
// the anchor and target points, and other bits represent the time difference (delta time)
// between them. This function combines these components into a single address.
func createAddress(anchor, target Peak) uint32 {
anchorFreq := int(real(anchor.Freq))
targetFreq := int(real(target.Freq))
deltaMs := uint32((target.Time - anchor.Time) * 1000)
// Combine the frequency of the anchor, target, and delta time into a 32-bit address
address := uint32(anchorFreq<<23) | uint32(targetFreq<<14) | deltaMs
return address
}