diff --git a/templates/amd64-386/effects.asm b/templates/amd64-386/effects.asm index 1eed166..dad845e 100644 --- a/templates/amd64-386/effects.asm +++ b/templates/amd64-386/effects.asm @@ -353,18 +353,16 @@ su_op_delay_loop: ; Stereo: push g g on stack, where g is calculated using l^2 + r^2 ;------------------------------------------------------------------------------- {{.Func "su_op_compressor" "Opcode"}} - fdiv dword [{{.Input "compressor" "invgain"}}]; l/g, we'll call this pre inverse gained signal x from now on fld st0 ; x x fmul st0, st0 ; x^2 x {{- if .StereoAndMono "compressor"}} jnc su_op_compressor_mono {{- end}} {{- if .Stereo "compressor"}} - fld st2 ; r x^2 l/g r - fdiv dword [{{.Input "compressor" "invgain"}}]; r/g, we'll call this pre inverse gained signal y from now on - fst st3 ; y x^2 l/g r/g - fmul st0, st0 ; y^2 x^2 l/g r/g - faddp st1, st0 ; y^2+x^2 l/g r/g + fld st2 ; r x^2 l r + fst st3 ; y x^2 l r + fmul st0, st0 ; y^2 x^2 l r + faddp st1, st0 ; y^2+x^2 l r call su_op_compressor_mono ; So, for stereo, we square both left & right and add them up fld st0 ; and return the computed gain two times, ready for MULP STEREO ret @@ -389,9 +387,11 @@ su_op_compressor_mono: fmul dword [{{.Float 0.5 | .Use}}] ; p=r/2 t*t/l' x fxch ; t*t/l' p x fyl2x ; p*log2(t*t/l') x - {{.TailCall "su_power"}} ; 2^(p*log2(t*t/l')) x - ; tail call ; Equal to: + {{.Call "su_power"}} ; 2^(p*log2(t*t/l')) x + ; Equal to: ; (t*t/l')^p x ; if ratio is at minimum => p=0 => 1 x ; if ratio is at maximum => p=0.5 => t/x => t/x*x=t + fdiv dword [{{.Input "compressor" "invgain"}}]; this used to be pregain but that ran into problems with getting back up to 0 dB so postgain should be better at that + ret {{- end}} diff --git a/templates/wasm/effects.wat b/templates/wasm/effects.wat index 5ce485e..e419ce5 100644 --- a/templates/wasm/effects.wat +++ b/templates/wasm/effects.wat @@ -409,10 +409,6 @@ ;; Stereo: push g g on stack, where g is calculated using l^2 + r^2 ;;------------------------------------------------------------------------------- (func $su_op_compressor (param $stereo i32) (local $x2 f32) (local $level f32) (local $t2 f32) - (call $push (f32.div ;; the inverse gain is applied on this signal, even if the gain is side-chained somewhere else - (call $pop) - (call $input (i32.const {{.InputNumber "compressor" "invgain"}})) - )) {{- if .Stereo "compressor"}} (local.set $x2 (f32.mul (call $peek) @@ -420,10 +416,6 @@ )) (if (local.get $stereo)(then (call $pop) - (call $push (f32.div - (call $pop) - (call $input (i32.const {{.InputNumber "compressor" "invgain"}})) - )) (local.set $x2 (f32.add (local.get $x2) (f32.mul @@ -472,6 +464,10 @@ )(else (call $push (f32.const 1)) ;; unity gain if we are below threshold )) + (call $push (f32.div ;; apply post-gain ("make up gain") + (call $pop) + (call $input (i32.const {{.InputNumber "compressor" "invgain"}})) + )) {{- if .Stereo "compressor"}} (if (local.get $stereo)(then (call $push (call $peek)) diff --git a/tests/expected_output/test_compressor.raw b/tests/expected_output/test_compressor.raw index f8732fa..087bd5e 100644 Binary files a/tests/expected_output/test_compressor.raw and b/tests/expected_output/test_compressor.raw differ diff --git a/tests/expected_output/test_compressor_stereo.raw b/tests/expected_output/test_compressor_stereo.raw index 8b0d4fa..a55eda8 100644 Binary files a/tests/expected_output/test_compressor_stereo.raw and b/tests/expected_output/test_compressor_stereo.raw differ diff --git a/tests/test_compressor.yml b/tests/test_compressor.yml index 845670f..ff6599d 100644 --- a/tests/test_compressor.yml +++ b/tests/test_compressor.yml @@ -49,7 +49,7 @@ patch: parameters: {stereo: 1} id: 1 - type: compressor - parameters: {attack: 32, invgain: 32, ratio: 96, release: 64, stereo: 0, threshold: 64} + parameters: {attack: 16, invgain: 64, ratio: 96, release: 64, stereo: 0, threshold: 51} - type: mulp parameters: {stereo: 0} - type: out diff --git a/tests/test_compressor_stereo.yml b/tests/test_compressor_stereo.yml index 4e512ac..bcb7e1f 100644 --- a/tests/test_compressor_stereo.yml +++ b/tests/test_compressor_stereo.yml @@ -49,7 +49,7 @@ patch: parameters: {stereo: 1} id: 1 - type: compressor - parameters: {attack: 32, invgain: 32, ratio: 96, release: 64, stereo: 1, threshold: 64} + parameters: {attack: 16, invgain: 64, ratio: 96, release: 64, stereo: 1, threshold: 71} - type: mulp parameters: {stereo: 1} - type: out diff --git a/vm/interpreter.go b/vm/interpreter.go index a81285e..0268804 100644 --- a/vm/interpreter.go +++ b/vm/interpreter.go @@ -505,10 +505,8 @@ func (s *Interpreter) Render(buffer []float32, syncBuf []float32, maxtime int) ( } unit.ports[4] = 0 case opCompressor: - stack[l-1] /= params[2] // apply inverse gain signalLevel := stack[l-1] * stack[l-1] // square the signal to get power if stereo { - stack[l-2] /= params[2] // apply inverse gain signalLevel += stack[l-2] * stack[l-2] } currentLevel := unit.state[0] @@ -523,6 +521,7 @@ func (s *Interpreter) Render(buffer []float32, syncBuf []float32, maxtime int) ( if threshold2 := params[3] * params[3]; currentLevel > threshold2 { gain = float32(math.Pow(float64(threshold2/currentLevel), float64(params[4]/2))) } + gain /= params[2] // apply inverse gain stack = append(stack, gain) if stereo { stack = append(stack, gain)