mirror of
https://github.com/cgzirim/seek-tune.git
synced 2025-12-17 17:04:22 +00:00
refactor: update FindMatches function
This commit is contained in:
parent
177c654cc8
commit
495163ebb4
2 changed files with 43 additions and 4 deletions
|
|
@ -1,3 +1,6 @@
|
|||
//go:build !js && !wasm
|
||||
// +build !js,!wasm
|
||||
|
||||
package shazam
|
||||
|
||||
import (
|
||||
|
|
@ -21,7 +24,6 @@ type Match struct {
|
|||
// FindMatches analyzes the audio sample to find matching songs in the database.
|
||||
func FindMatches(audioSample []float64, audioDuration float64, sampleRate int) ([]Match, time.Duration, error) {
|
||||
startTime := time.Now()
|
||||
logger := utils.GetLogger()
|
||||
|
||||
spectrogram, err := Spectrogram(audioSample, sampleRate)
|
||||
if err != nil {
|
||||
|
|
@ -31,6 +33,21 @@ func FindMatches(audioSample []float64, audioDuration float64, sampleRate int) (
|
|||
peaks := ExtractPeaks(spectrogram, audioDuration)
|
||||
sampleFingerprint := Fingerprint(peaks, utils.GenerateUniqueID())
|
||||
|
||||
sampleFingerprintMap := make(map[uint32]uint32)
|
||||
for address, couple := range sampleFingerprint {
|
||||
sampleFingerprintMap[address] = couple.AnchorTimeMs
|
||||
}
|
||||
|
||||
matches, _, err := FindMatchesFGP(sampleFingerprintMap)
|
||||
|
||||
return matches, time.Since(startTime), nil
|
||||
}
|
||||
|
||||
// FindMatchesFGP uses the sample fingerprint to find matching songs in the database.
|
||||
func FindMatchesFGP(sampleFingerprint map[uint32]uint32) ([]Match, time.Duration, error) {
|
||||
startTime := time.Now()
|
||||
logger := utils.GetLogger()
|
||||
|
||||
addresses := make([]uint32, 0, len(sampleFingerprint))
|
||||
for address := range sampleFingerprint {
|
||||
addresses = append(addresses, address)
|
||||
|
|
@ -55,7 +72,7 @@ func FindMatches(audioSample []float64, audioDuration float64, sampleRate int) (
|
|||
for _, couple := range couples {
|
||||
matches[couple.SongID] = append(
|
||||
matches[couple.SongID],
|
||||
[2]uint32{sampleFingerprint[address].AnchorTimeMs, couple.AnchorTimeMs},
|
||||
[2]uint32{sampleFingerprint[address], couple.AnchorTimeMs},
|
||||
)
|
||||
|
||||
if existingTime, ok := timestamps[couple.SongID]; !ok || couple.AnchorTimeMs < existingTime {
|
||||
|
|
|
|||
|
|
@ -15,8 +15,7 @@ const (
|
|||
)
|
||||
|
||||
func Spectrogram(sample []float64, sampleRate int) ([][]complex128, error) {
|
||||
lpf := NewLowPassFilter(maxFreq, float64(sampleRate))
|
||||
filteredSample := lpf.Filter(sample)
|
||||
filteredSample := LowPassFilter(maxFreq, float64(sampleRate), sample)
|
||||
|
||||
downsampledSample, err := Downsample(filteredSample, sampleRate, sampleRate/dspRatio)
|
||||
if err != nil {
|
||||
|
|
@ -53,6 +52,29 @@ func Spectrogram(sample []float64, sampleRate int) ([][]complex128, error) {
|
|||
return spectrogram, nil
|
||||
}
|
||||
|
||||
// LowPassFilter is a first-order low-pass filter that attenuates high
|
||||
// frequencies above the cutoffFrequency.
|
||||
// It uses the transfer function H(s) = 1 / (1 + sRC), where RC is the time constant.
|
||||
func LowPassFilter(cutoffFrequency, sampleRate float64, input []float64) []float64 {
|
||||
rc := 1.0 / (2 * math.Pi * cutoffFrequency)
|
||||
dt := 1.0 / sampleRate
|
||||
alpha := dt / (rc + dt)
|
||||
|
||||
filteredSignal := make([]float64, len(input))
|
||||
var prevOutput float64 = 0
|
||||
|
||||
for i, x := range input {
|
||||
if i == 0 {
|
||||
filteredSignal[i] = x * alpha
|
||||
} else {
|
||||
|
||||
filteredSignal[i] = alpha*x + (1-alpha)*prevOutput
|
||||
}
|
||||
prevOutput = filteredSignal[i]
|
||||
}
|
||||
return filteredSignal
|
||||
}
|
||||
|
||||
// Downsample downsamples the input audio from originalSampleRate to targetSampleRate
|
||||
func Downsample(input []float64, originalSampleRate, targetSampleRate int) ([]float64, error) {
|
||||
if targetSampleRate <= 0 || originalSampleRate <= 0 {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue