Kirika/audio/filter/resample_filter_nocgo.go
2022-05-20 17:23:50 +02:00

73 lines
1.7 KiB
Go

//go:build !cgo
package filter
import (
"git.gammaspectra.live/S.O.N.G/Kirika/audio"
"github.com/oov/audio/resampler"
"log"
)
const (
QualityBest ResampleQuality = 10
QualityGood ResampleQuality = 8
QualityFast ResampleQuality = 5
QualityFastest ResampleQuality = 0
)
func (f ResampleFilter) Process(source audio.Source) audio.Source {
if source.SampleRate == f.sampleRate { //no change
return source
}
outBlocks := make(chan []float32)
go func() {
defer close(outBlocks)
samplerateConverter := resampler.New(source.Channels, source.SampleRate, f.sampleRate, int(f.quality))
for block := range source.Blocks {
output := make([][]float32, source.Channels)
input := make([][]float32, source.Channels)
outputBufferLength := 0
for i := 0; i < source.Channels; i++ {
input[i] = make([]float32, len(block)/source.Channels)
ix := 0
for j := i; j < len(block); j += source.Channels {
input[i][ix] = block[j]
ix++
}
output[i] = make([]float32, int(float64(len(block)/source.Channels)*(float64(f.sampleRate)/float64(source.SampleRate))*1.1)) //resize to match expected output, with a fuzz factor of 10%
read, written := samplerateConverter.ProcessFloat32(i, input[i], output[i])
if read != len(input[i]) {
log.Panicf("could not read whole input: %d vs %d", len(input[i]), read)
}
output[i] = output[i][:written]
outputBufferLength += written
}
buffer := make([]float32, outputBufferLength)
for i, b := range output {
for j := range b {
buffer[i+j*len(output)] = b[j]
}
}
outBlocks <- buffer
}
}()
return audio.Source{
Channels: source.Channels,
SampleRate: f.sampleRate,
Blocks: outBlocks,
}
}