initial implementation of finding matches

This commit is contained in:
Chigozirim Igweamaka 2024-05-15 05:08:02 +01:00
parent 9332b06003
commit 2b73b5825e

135
shazam/shazamInit.go Normal file
View file

@ -0,0 +1,135 @@
package shazam
import (
"fmt"
"song-recognition/models"
"song-recognition/utils"
"sort"
)
type Match1 struct {
SongID uint32
SongTitle string
SongArtist string
YouTubeID string
Timestamp uint32
Coherency float64
}
func Search(audioSamples []float64, audioDuration float64, sampleRate int) ([]Match1, error) {
spectrogram, err := Spectrogram(audioSamples, sampleRate)
if err != nil {
return nil, fmt.Errorf("failed to get spectrogram of samples: %v", err)
}
peaks := ExtractPeaks(spectrogram, audioDuration)
fingerprints := Fingerprint(peaks, utils.GenerateUniqueID())
addresses := make([]uint32, 0, len(fingerprints))
for address, _ := range fingerprints {
addresses = append(addresses, address)
}
db, err := utils.NewDbClient()
if err != nil {
return nil, err
}
defer db.Close()
couples, err := db.GetCouples(addresses)
if err != nil {
return nil, err
}
targetZones := targetZones(couples)
fmt.Println("TargetZones: ", targetZones)
matches := timeCoherency(fingerprints, targetZones)
var matchList []Match1
for songID, coherency := range matches {
song, songExists, err := db.GetSongByID(songID)
if err != nil || !songExists {
return nil, err
}
timestamp := targetZones[songID][0]
match := Match1{songID, song.Title, song.Artist, song.YouTubeID, timestamp, float64(coherency)}
matchList = append(matchList, match)
}
sort.Slice(matchList, func(i, j int) bool {
return matchList[i].Coherency > matchList[j].Coherency
})
return matchList, nil
}
func targetZones(m map[uint32][]models.Couple) map[uint32][]uint32 {
songs := make(map[uint32]map[uint32]int)
for _, couples := range m {
for _, couple := range couples {
if _, ok := songs[couple.SongID]; !ok {
songs[couple.SongID] = make(map[uint32]int)
}
songs[couple.SongID][couple.AnchorTimeMs]++
}
}
fmt.Println("couples: ", songs)
for songID, anchorTimes := range songs {
for msTime, count := range anchorTimes {
if count < 5 {
delete(songs[songID], msTime)
}
}
}
fmt.Println("anchorTimes: ", songs)
targetZones := make(map[uint32][]uint32)
for songID, anchorTimes := range songs {
for anchorTime, _ := range anchorTimes {
targetZones[songID] = append(targetZones[songID], anchorTime)
}
}
return targetZones
}
func timeCoherency(record map[uint32]models.Couple, songs map[uint32][]uint32) map[uint32]int {
// var threshold float64
matches := make(map[uint32]int)
for songID, songAnchorTimes := range songs {
deltas := make(map[float64]int)
for _, songAnchorTime := range songAnchorTimes {
for _, recordAnchor := range record {
recordAnchorTimeMs := float64(recordAnchor.AnchorTimeMs)
delta := recordAnchorTimeMs - float64(songAnchorTime)
deltas[delta]++
}
}
// Find the maximum number of time-coherent notes
var maxOccurrences int
for _, occurrences := range deltas {
if occurrences > maxOccurrences {
maxOccurrences = occurrences
}
}
matches[songID] = maxOccurrences
}
// Apply threshold for coherency
/**
for songID, coherency := range matches {
if float64(coherency) < threshold*float64(len(record)) {
delete(matches, songID) // Remove songs with insufficient coherency
}
}
*/
return matches
}