mirror of
https://github.com/vsariola/sointu.git
synced 2025-05-28 03:10:24 -04:00
feat: change the compressor unit to apply post-gain instead of pregain.
Pregaining ran into trouble: could not bring the signal level back to near 0dB. For example, with infinite ratio in the pre-gain system, the signal level was capped at threshold, which in turn ran into trouble with stereo signals.
This commit is contained in:
parent
76cf47a070
commit
42c9e045b7
@ -353,18 +353,16 @@ su_op_delay_loop:
|
|||||||
; Stereo: push g g on stack, where g is calculated using l^2 + r^2
|
; Stereo: push g g on stack, where g is calculated using l^2 + r^2
|
||||||
;-------------------------------------------------------------------------------
|
;-------------------------------------------------------------------------------
|
||||||
{{.Func "su_op_compressor" "Opcode"}}
|
{{.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
|
fld st0 ; x x
|
||||||
fmul st0, st0 ; x^2 x
|
fmul st0, st0 ; x^2 x
|
||||||
{{- if .StereoAndMono "compressor"}}
|
{{- if .StereoAndMono "compressor"}}
|
||||||
jnc su_op_compressor_mono
|
jnc su_op_compressor_mono
|
||||||
{{- end}}
|
{{- end}}
|
||||||
{{- if .Stereo "compressor"}}
|
{{- if .Stereo "compressor"}}
|
||||||
fld st2 ; r x^2 l/g r
|
fld st2 ; r x^2 l 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 r
|
||||||
fst st3 ; y x^2 l/g r/g
|
fmul st0, st0 ; y^2 x^2 l r
|
||||||
fmul st0, st0 ; y^2 x^2 l/g r/g
|
faddp st1, st0 ; y^2+x^2 l r
|
||||||
faddp st1, st0 ; y^2+x^2 l/g r/g
|
|
||||||
call su_op_compressor_mono ; So, for stereo, we square both left & right and add them up
|
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
|
fld st0 ; and return the computed gain two times, ready for MULP STEREO
|
||||||
ret
|
ret
|
||||||
@ -389,9 +387,11 @@ su_op_compressor_mono:
|
|||||||
fmul dword [{{.Float 0.5 | .Use}}] ; p=r/2 t*t/l' x
|
fmul dword [{{.Float 0.5 | .Use}}] ; p=r/2 t*t/l' x
|
||||||
fxch ; t*t/l' p x
|
fxch ; t*t/l' p x
|
||||||
fyl2x ; p*log2(t*t/l') x
|
fyl2x ; p*log2(t*t/l') x
|
||||||
{{.TailCall "su_power"}} ; 2^(p*log2(t*t/l')) x
|
{{.Call "su_power"}} ; 2^(p*log2(t*t/l')) x
|
||||||
; tail call ; Equal to:
|
; Equal to:
|
||||||
; (t*t/l')^p x
|
; (t*t/l')^p x
|
||||||
; if ratio is at minimum => p=0 => 1 x
|
; if ratio is at minimum => p=0 => 1 x
|
||||||
; if ratio is at maximum => p=0.5 => t/x => t/x*x=t
|
; 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}}
|
{{- end}}
|
||||||
|
@ -409,10 +409,6 @@
|
|||||||
;; Stereo: push g g on stack, where g is calculated using l^2 + r^2
|
;; 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)
|
(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"}}
|
{{- if .Stereo "compressor"}}
|
||||||
(local.set $x2 (f32.mul
|
(local.set $x2 (f32.mul
|
||||||
(call $peek)
|
(call $peek)
|
||||||
@ -420,10 +416,6 @@
|
|||||||
))
|
))
|
||||||
(if (local.get $stereo)(then
|
(if (local.get $stereo)(then
|
||||||
(call $pop)
|
(call $pop)
|
||||||
(call $push (f32.div
|
|
||||||
(call $pop)
|
|
||||||
(call $input (i32.const {{.InputNumber "compressor" "invgain"}}))
|
|
||||||
))
|
|
||||||
(local.set $x2 (f32.add
|
(local.set $x2 (f32.add
|
||||||
(local.get $x2)
|
(local.get $x2)
|
||||||
(f32.mul
|
(f32.mul
|
||||||
@ -472,6 +464,10 @@
|
|||||||
)(else
|
)(else
|
||||||
(call $push (f32.const 1)) ;; unity gain if we are below threshold
|
(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 .Stereo "compressor"}}
|
||||||
(if (local.get $stereo)(then
|
(if (local.get $stereo)(then
|
||||||
(call $push (call $peek))
|
(call $push (call $peek))
|
||||||
|
Binary file not shown.
Binary file not shown.
@ -49,7 +49,7 @@ patch:
|
|||||||
parameters: {stereo: 1}
|
parameters: {stereo: 1}
|
||||||
id: 1
|
id: 1
|
||||||
- type: compressor
|
- 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
|
- type: mulp
|
||||||
parameters: {stereo: 0}
|
parameters: {stereo: 0}
|
||||||
- type: out
|
- type: out
|
||||||
|
@ -49,7 +49,7 @@ patch:
|
|||||||
parameters: {stereo: 1}
|
parameters: {stereo: 1}
|
||||||
id: 1
|
id: 1
|
||||||
- type: compressor
|
- 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
|
- type: mulp
|
||||||
parameters: {stereo: 1}
|
parameters: {stereo: 1}
|
||||||
- type: out
|
- type: out
|
||||||
|
@ -505,10 +505,8 @@ func (s *Interpreter) Render(buffer []float32, syncBuf []float32, maxtime int) (
|
|||||||
}
|
}
|
||||||
unit.ports[4] = 0
|
unit.ports[4] = 0
|
||||||
case opCompressor:
|
case opCompressor:
|
||||||
stack[l-1] /= params[2] // apply inverse gain
|
|
||||||
signalLevel := stack[l-1] * stack[l-1] // square the signal to get power
|
signalLevel := stack[l-1] * stack[l-1] // square the signal to get power
|
||||||
if stereo {
|
if stereo {
|
||||||
stack[l-2] /= params[2] // apply inverse gain
|
|
||||||
signalLevel += stack[l-2] * stack[l-2]
|
signalLevel += stack[l-2] * stack[l-2]
|
||||||
}
|
}
|
||||||
currentLevel := unit.state[0]
|
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 {
|
if threshold2 := params[3] * params[3]; currentLevel > threshold2 {
|
||||||
gain = float32(math.Pow(float64(threshold2/currentLevel), float64(params[4]/2)))
|
gain = float32(math.Pow(float64(threshold2/currentLevel), float64(params[4]/2)))
|
||||||
}
|
}
|
||||||
|
gain /= params[2] // apply inverse gain
|
||||||
stack = append(stack, gain)
|
stack = append(stack, gain)
|
||||||
if stereo {
|
if stereo {
|
||||||
stack = append(stack, gain)
|
stack = append(stack, gain)
|
||||||
|
Loading…
Reference in New Issue
Block a user