73 lines
1.7 KiB
Go
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,
|
|
}
|
|
}
|