Rewrite downsample function to add flexibility for downsampling to a target sample rate.

This commit is contained in:
Chigozirim Igweamaka 2024-06-23 14:11:08 +01:00
parent 8a891ec3cd
commit 2f3bb8d32b

View file

@ -18,7 +18,7 @@ func Spectrogram(samples []float64, sampleRate int) ([][]complex128, error) {
lpf := NewLowPassFilter(maxFreq, float64(sampleRate)) lpf := NewLowPassFilter(maxFreq, float64(sampleRate))
filteredSamples := lpf.Filter(samples) filteredSamples := lpf.Filter(samples)
downsampledSamples, err := downsample(filteredSamples, dspRatio) downsampledSamples, err := Downsample(filteredSamples, sampleRate, sampleRate/dspRatio)
if err != nil { if err != nil {
return nil, fmt.Errorf("couldn't downsample audio samples: %v", err) return nil, fmt.Errorf("couldn't downsample audio samples: %v", err)
} }
@ -54,30 +54,36 @@ func Spectrogram(samples []float64, sampleRate int) ([][]complex128, error) {
return spectrogram, nil return spectrogram, nil
} }
func downsample(input []float64, ratio int) ([]float64, error) { // Downsample downsamples the input audio from originalSampleRate to targetSampleRate
if ratio <= 0 { func Downsample(input []float64, originalSampleRate, targetSampleRate int) ([]float64, error) {
return nil, errors.New("invalid or incompatible ratio") if targetSampleRate <= 0 || originalSampleRate <= 0 {
return nil, errors.New("sample rates must be positive")
}
if targetSampleRate > originalSampleRate {
return nil, errors.New("target sample rate must be less than or equal to original sample rate")
} }
outputSize := (len(input) + ratio - 1) / ratio ratio := originalSampleRate / targetSampleRate
output := make([]float64, outputSize) if ratio <= 0 {
return nil, errors.New("invalid ratio calculated from sample rates")
}
for i := 0; i < outputSize; i++ { var resampled []float64
startIndex := i * ratio for i := 0; i < len(input); i += ratio {
endIndex := startIndex + ratio end := i + ratio
if endIndex > len(input) { if end > len(input) {
endIndex = len(input) end = len(input)
} }
sum := 0.0
for j := startIndex; j < endIndex; j++ { sum := 0.0
for j := i; j < end; j++ {
sum += input[j] sum += input[j]
} }
avg := sum / float64(end-i)
output[i] = sum / float64(endIndex-startIndex) resampled = append(resampled, avg)
} }
return output, nil return resampled, nil
} }
type Peak struct { type Peak struct {
@ -107,20 +113,19 @@ func ExtractPeaks(spectrogram [][]complex128, audioDuration float64) []Peak {
var maxFreqs []complex128 var maxFreqs []complex128
var freqIndices []float64 var freqIndices []float64
binBandMaxies := map[string]maxies{} binBandMaxies := []maxies{}
for freqIdx, freq := range bin { for _, band := range bands {
magnitude := cmplx.Abs(freq) var maxx maxies
var maxMag float64
for _, band := range bands { for idx, freq := range bin[band.min:band.max] {
if magnitude >= float64(band.min) && magnitude < float64(band.max) { magnitude := cmplx.Abs(freq)
key := fmt.Sprintf("%d-%d", band.min, band.max) if magnitude > maxMag {
value, ok := binBandMaxies[key] maxMag = magnitude
freqIdx := band.min + idx
if !ok || magnitude > value.maxMag { maxx = maxies{magnitude, freq, freqIdx}
binBandMaxies[key] = maxies{magnitude, freq, freqIdx}
}
} }
} }
binBandMaxies = append(binBandMaxies, maxx)
} }
for _, value := range binBandMaxies { for _, value := range binBandMaxies {