From 9ece89c3e6d5730b8c773f31865700d148e6916b Mon Sep 17 00:00:00 2001 From: WeebDataHoarder <57538841+WeebDataHoarder@users.noreply.github.com> Date: Fri, 29 Jul 2022 11:41:39 +0200 Subject: [PATCH] made Volume filter work on integer samples natively --- audio/filter/filter.go | 61 ++++++++++++++++++++++++++++--------- audio/filter/filter_test.go | 2 +- audio/replaygain/filter.go | 4 +-- 3 files changed, 50 insertions(+), 17 deletions(-) diff --git a/audio/filter/filter.go b/audio/filter/filter.go index 086f91a..ddd9f66 100644 --- a/audio/filter/filter.go +++ b/audio/filter/filter.go @@ -173,10 +173,10 @@ func (f RealTimeFilter) Process(source audio.Source) audio.Source { } type VolumeFilter struct { - adjustment float32 + adjustment float64 } -func NewVolumeFilter(adjustment float32) VolumeFilter { +func NewVolumeFilter(adjustment float64) VolumeFilter { return VolumeFilter{ adjustment: adjustment, } @@ -187,21 +187,54 @@ func (f VolumeFilter) Process(source audio.Source) audio.Source { return source } - 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] * f.adjustment + if int32Source, ok := source.(audio.TypedSource[int32]); ok { + bpsMultiplier := int64((1 << (source.GetBitDepth() - 1)) - 1) + adjustment := int64(f.adjustment * float64(bpsMultiplier)) + outSource := audio.NewSource[int32](source.GetBitDepth(), source.GetSampleRate(), source.GetChannels()) + go func() { + defer outSource.Close() + for block := range int32Source.GetBlocks() { + 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 { diff --git a/audio/filter/filter_test.go b/audio/filter/filter_test.go index 11df9b2..44b651f 100644 --- a/audio/filter/filter_test.go +++ b/audio/filter/filter_test.go @@ -22,7 +22,7 @@ func TestFilterChainNoResample(t *testing.T) { return } - result := NewFilterChain(source, MonoFilter{}, StereoFilter{}) + result := NewFilterChain(source, NewVolumeFilter(0.5), MonoFilter{}, StereoFilter{}) sink := audio.NewForwardSink(audio.NewNullSink()) sink.Process(result) diff --git a/audio/replaygain/filter.go b/audio/replaygain/filter.go index 7ceeffb..0ca15e2 100644 --- a/audio/replaygain/filter.go +++ b/audio/replaygain/filter.go @@ -5,11 +5,11 @@ import ( "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 { volume := math.Pow(10, (gain+preAmp)/20) //prevent clipping volume = math.Min(volume, 1/peak) - return filter.NewVolumeFilter(float32(volume)) + return filter.NewVolumeFilter(volume) }