2022-05-20 15:23:50 +00:00
//go:build !cgo
package filter
import (
"git.gammaspectra.live/S.O.N.G/Kirika/audio"
2022-11-30 07:09:16 +00:00
"git.gammaspectra.live/S.O.N.G/Kirika/audio/filter/internal/resampler"
2022-05-20 15:23:50 +00:00
"log"
)
const (
QualityBest ResampleQuality = 10
QualityGood ResampleQuality = 8
QualityFast ResampleQuality = 5
QualityFastest ResampleQuality = 0
)
func ( f ResampleFilter ) Process ( source audio . Source ) audio . Source {
2022-07-19 08:36:22 +00:00
if source . GetSampleRate ( ) == f . sampleRate { //no change
2022-05-20 15:23:50 +00:00
return source
}
2022-07-22 09:39:58 +00:00
outSource := audio . NewSource [ float32 ] ( source . GetBitDepth ( ) , f . sampleRate , source . GetChannels ( ) )
2022-05-20 15:23:50 +00:00
go func ( ) {
2022-07-19 08:36:22 +00:00
defer outSource . Close ( )
2022-05-20 15:23:50 +00:00
2022-07-19 08:36:22 +00:00
samplerateConverter := resampler . New ( source . GetChannels ( ) , source . GetSampleRate ( ) , f . sampleRate , int ( f . quality ) )
2022-05-20 15:23:50 +00:00
2022-07-19 08:36:22 +00:00
for block := range source . ToFloat32 ( ) . GetBlocks ( ) {
output := make ( [ ] [ ] float32 , source . GetChannels ( ) )
input := make ( [ ] [ ] float32 , source . GetChannels ( ) )
2022-05-20 15:23:50 +00:00
outputBufferLength := 0
2022-07-19 08:36:22 +00:00
for i := 0 ; i < source . GetChannels ( ) ; i ++ {
input [ i ] = make ( [ ] float32 , len ( block ) / source . GetChannels ( ) )
2022-05-20 15:23:50 +00:00
ix := 0
2022-07-19 08:36:22 +00:00
for j := i ; j < len ( block ) ; j += source . GetChannels ( ) {
2022-05-20 15:23:50 +00:00
input [ i ] [ ix ] = block [ j ]
ix ++
}
2022-07-19 08:36:22 +00:00
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%
2022-05-20 15:23:50 +00:00
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 ]
}
}
2022-07-19 08:36:22 +00:00
outSource . IngestFloat32 ( buffer )
2022-05-20 15:23:50 +00:00
}
} ( )
2022-07-19 08:36:22 +00:00
return outSource
2022-05-20 15:23:50 +00:00
}