//go:build !cgo package filter import ( "git.gammaspectra.live/S.O.N.G/Kirika/audio" "git.gammaspectra.live/S.O.N.G/Kirika/audio/filter/internal/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.GetSampleRate() == f.sampleRate { //no change return source } outSource := audio.NewSource[float32](source.GetBitDepth(), f.sampleRate, source.GetChannels()) go func() { defer outSource.Close() samplerateConverter := resampler.New(source.GetChannels(), source.GetSampleRate(), f.sampleRate, int(f.quality)) for block := range source.ToFloat32().GetBlocks() { output := make([][]float32, source.GetChannels()) input := make([][]float32, source.GetChannels()) outputBufferLength := 0 for i := 0; i < source.GetChannels(); i++ { input[i] = make([]float32, len(block)/source.GetChannels()) ix := 0 for j := i; j < len(block); j += source.GetChannels() { input[i][ix] = block[j] ix++ } output[i] = make([]float32, int(float64(len(block)/source.GetChannels())*(float64(f.sampleRate)/float64(source.GetSampleRate()))*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] } } outSource.IngestFloat32(buffer) } }() return outSource }