mirror of
https://github.com/cgzirim/seek-tune.git
synced 2025-12-18 09:24:19 +00:00
fix(fingerprint): prevent address overflow with bit masking
- Scale and mask frequencies to 9 bits each - Mask time delta to 14 bits - Add sampleRate parameter to ExtractPeaks calls Prevents hash collisions from bit overflow in fingerprint addresses.
This commit is contained in:
parent
e3a35ef1eb
commit
7104a1a7bc
1 changed files with 17 additions and 8 deletions
|
|
@ -26,7 +26,10 @@ func Fingerprint(peaks []Peak, songID uint32) map[uint32]models.Couple {
|
||||||
address := createAddress(anchor, target)
|
address := createAddress(anchor, target)
|
||||||
anchorTimeMs := uint32(anchor.Time * 1000)
|
anchorTimeMs := uint32(anchor.Time * 1000)
|
||||||
|
|
||||||
fingerprints[address] = models.Couple{anchorTimeMs, songID}
|
fingerprints[address] = models.Couple{
|
||||||
|
AnchorTimeMs: anchorTimeMs,
|
||||||
|
SongID: songID,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -38,12 +41,18 @@ func Fingerprint(peaks []Peak, songID uint32) map[uint32]models.Couple {
|
||||||
// the anchor and target points, and other bits represent the time difference (delta time)
|
// 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 (a hash).
|
// between them. This function combines these components into a single address (a hash).
|
||||||
func createAddress(anchor, target Peak) uint32 {
|
func createAddress(anchor, target Peak) uint32 {
|
||||||
anchorFreq := int(real(anchor.Freq))
|
anchorFreqBin := uint32(anchor.Freq / 10) // Scale down to fit in 9 bits
|
||||||
targetFreq := int(real(target.Freq))
|
targetFreqBin := uint32(target.Freq / 10)
|
||||||
deltaMs := uint32((target.Time - anchor.Time) * 1000)
|
|
||||||
|
|
||||||
// Combine the frequency of the anchor, target, and delta time into a 32-bit address
|
deltaMsRaw := uint32((target.Time - anchor.Time) * 1000)
|
||||||
address := uint32(anchorFreq<<23) | uint32(targetFreq<<14) | deltaMs
|
|
||||||
|
// Mask to fit within bit constraints
|
||||||
|
anchorFreqBits := anchorFreqBin & ((1 << maxFreqBits) - 1) // 9 bits
|
||||||
|
targetFreqBits := targetFreqBin & ((1 << maxFreqBits) - 1) // 9 bits
|
||||||
|
deltaBits := deltaMsRaw & ((1 << maxDeltaBits) - 1) // 14 bits (max ~16 seconds)
|
||||||
|
|
||||||
|
// Combine into 32-bit address
|
||||||
|
address := (anchorFreqBits << 23) | (targetFreqBits << 14) | deltaBits
|
||||||
|
|
||||||
return address
|
return address
|
||||||
}
|
}
|
||||||
|
|
@ -66,7 +75,7 @@ func FingerprintAudio(songFilePath string, songID uint32) (map[uint32]models.Cou
|
||||||
return nil, fmt.Errorf("error creating spectrogram: %v", err)
|
return nil, fmt.Errorf("error creating spectrogram: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
peaks := ExtractPeaks(spectro, wavInfo.Duration)
|
peaks := ExtractPeaks(spectro, wavInfo.Duration, wavInfo.SampleRate)
|
||||||
utils.ExtendMap(fingerprint, Fingerprint(peaks, songID))
|
utils.ExtendMap(fingerprint, Fingerprint(peaks, songID))
|
||||||
|
|
||||||
if wavInfo.Channels == 2 {
|
if wavInfo.Channels == 2 {
|
||||||
|
|
@ -75,7 +84,7 @@ func FingerprintAudio(songFilePath string, songID uint32) (map[uint32]models.Cou
|
||||||
return nil, fmt.Errorf("error creating spectrogram for right channel: %v", err)
|
return nil, fmt.Errorf("error creating spectrogram for right channel: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
peaks = ExtractPeaks(spectro, wavInfo.Duration)
|
peaks = ExtractPeaks(spectro, wavInfo.Duration, wavInfo.SampleRate)
|
||||||
utils.ExtendMap(fingerprint, Fingerprint(peaks, songID))
|
utils.ExtendMap(fingerprint, Fingerprint(peaks, songID))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue