made Volume filter work on integer samples natively

This commit is contained in:
DataHoarder 2022-07-29 11:41:39 +02:00
parent cd71da809b
commit 9ece89c3e6
Signed by: DataHoarder
SSH key fingerprint: SHA256:OLTRf6Fl87G52SiR7sWLGNzlJt4WOX+tfI2yxo0z7xk
3 changed files with 50 additions and 17 deletions

View file

@ -173,10 +173,10 @@ func (f RealTimeFilter) Process(source audio.Source) audio.Source {
} }
type VolumeFilter struct { type VolumeFilter struct {
adjustment float32 adjustment float64
} }
func NewVolumeFilter(adjustment float32) VolumeFilter { func NewVolumeFilter(adjustment float64) VolumeFilter {
return VolumeFilter{ return VolumeFilter{
adjustment: adjustment, adjustment: adjustment,
} }
@ -187,21 +187,54 @@ func (f VolumeFilter) Process(source audio.Source) audio.Source {
return source return source
} }
outSource := audio.NewSource[float32](source.GetBitDepth(), source.GetSampleRate(), source.GetChannels()) if int32Source, ok := source.(audio.TypedSource[int32]); ok {
go func() { bpsMultiplier := int64((1 << (source.GetBitDepth() - 1)) - 1)
defer outSource.Close() adjustment := int64(f.adjustment * float64(bpsMultiplier))
outSource := audio.NewSource[int32](source.GetBitDepth(), source.GetSampleRate(), source.GetChannels())
for block := range source.ToFloat32().GetBlocks() { go func() {
out := make([]float32, len(block)) defer outSource.Close()
for i := range block { for block := range int32Source.GetBlocks() {
out[i] = block[i] * f.adjustment out := make([]int32, len(block))
for i := range block {
out[i] = int32((int64(block[i]) * adjustment) / bpsMultiplier)
}
outSource.IngestNative(out, source.GetBitDepth())
} }
outSource.IngestFloat32(out) }()
} return outSource
} else if int16Source, ok := source.(audio.TypedSource[int16]); ok {
bpsMultiplier := int32((1 << (source.GetBitDepth() - 1)) - 1)
adjustment := int32(f.adjustment * float64(bpsMultiplier))
outSource := audio.NewSource[int16](source.GetBitDepth(), source.GetSampleRate(), source.GetChannels())
go func() {
defer outSource.Close()
for block := range int16Source.GetBlocks() {
out := make([]int16, len(block))
for i := range block {
out[i] = int16((int32(block[i]) * adjustment) / bpsMultiplier)
}
outSource.IngestNative(out, source.GetBitDepth())
}
}()
return outSource
} else {
adjustment := float32(f.adjustment)
outSource := audio.NewSource[float32](source.GetBitDepth(), source.GetSampleRate(), source.GetChannels())
go func() {
defer outSource.Close()
}() for block := range source.ToFloat32().GetBlocks() {
out := make([]float32, len(block))
for i := range block {
out[i] = block[i] * adjustment
}
outSource.IngestNative(out, source.GetBitDepth())
}
return outSource }()
return outSource
}
} }
type StereoFilter struct { type StereoFilter struct {

View file

@ -22,7 +22,7 @@ func TestFilterChainNoResample(t *testing.T) {
return return
} }
result := NewFilterChain(source, MonoFilter{}, StereoFilter{}) result := NewFilterChain(source, NewVolumeFilter(0.5), MonoFilter{}, StereoFilter{})
sink := audio.NewForwardSink(audio.NewNullSink()) sink := audio.NewForwardSink(audio.NewNullSink())
sink.Process(result) sink.Process(result)

View file

@ -5,11 +5,11 @@ import (
"math" "math"
) )
//NewReplayGainFilter Creates a VolumeFilter applying calculated ReplayGain values, pre amplifying by preAmp. Values are in dB // NewReplayGainFilter Creates a VolumeFilter applying calculated ReplayGain values, pre amplifying by preAmp. Values are in dB
func NewReplayGainFilter(gain, peak, preAmp float64) filter.VolumeFilter { func NewReplayGainFilter(gain, peak, preAmp float64) filter.VolumeFilter {
volume := math.Pow(10, (gain+preAmp)/20) volume := math.Pow(10, (gain+preAmp)/20)
//prevent clipping //prevent clipping
volume = math.Min(volume, 1/peak) volume = math.Min(volume, 1/peak)
return filter.NewVolumeFilter(float32(volume)) return filter.NewVolumeFilter(volume)
} }