1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
ix!();

use crate::{
    Conditioner,
    ConditionerProcessCfg,
};

macro_rules! write_vu_from_falloff {
    ($self:ident,$cfg:ident) => ({
        $self.vu[0] = minf(8.0, $cfg.a * $self.vu[0]);
        $self.vu[1] = minf(8.0, $cfg.a * $self.vu[1]);
        $self.vu[4] = minf(8.0, $cfg.a * $self.vu[4]);
        $self.vu[5] = minf(8.0, $cfg.a * $self.vu[5]);
    });
}

impl Process for Conditioner {

    fn process<const N: usize>(&mut self, data_l: &mut [f32; N], data_r: &mut [f32; N]) {

        let cfg = ConditionerProcessCfg::new(self);

        write_vu_from_falloff![self,cfg];

        self.update();

        unsafe {
            self.band1.process_block_stereo(
                data_l.as_mut_ptr(), 
                data_r.as_mut_ptr(), 
                None);

            self.band2.process_block_stereo(
                data_l.as_mut_ptr(), 
                data_r.as_mut_ptr(), 
                None);
        }

        self.amp_l.set_target_smoothed(
            cfg.pregain * 0.5 * clamp1bp(1.0 - cfg.balance_f));

        self.amp_r.set_target_smoothed(
            cfg.pregain * 0.5 * clamp1bp(1.0 + cfg.balance_f));

        self.width.set_target_smoothed(clamp1bp(cfg.width_f));

        self.postamp.set_target_smoothed(self.tables.db_to_linear(cfg.gain_f));

        let mut mid_side = MSBlock::new(N);

        unsafe {

            encode_mid_side(
                data_l.as_mut_ptr(), 
                data_r.as_mut_ptr(), 
                mid_side.m(), 
                mid_side.s(), 
                block_size_quad![N]);

            self.width.multiply_block(mid_side.s(), block_size_quad![N]);

            decode_mid_side(
                mid_side.m(), 
                mid_side.s(), 
                data_l.as_mut_ptr(), 
                data_r.as_mut_ptr(), 
                block_size_quad![N]);

            self.amp_l.multiply_block(
                data_l.as_mut_ptr(), 
                block_size_quad![N]);

            self.amp_r.multiply_block(
                data_r.as_mut_ptr(), 
                block_size_quad![N]);
        }

        self.vu[0] = maxf(
            self.vu[0], 
            get_absmax(
                data_l.as_mut_ptr(), 
                block_size_quad![N])
        );

        self.vu[1] = maxf(
            self.vu[1], 
            get_absmax(
                data_r.as_mut_ptr(), 
                block_size_quad![N])
        );

        for k in 0..N {
            self.do_conditioner_block(
                k, 
                &cfg,
                data_l,
                data_r);
        }

        unsafe {
            self.postamp.multiply_2_blocks(
                data_l.as_mut_ptr(), 
                data_r.as_mut_ptr(), 
                block_size_quad![N]);
        }

        self.vu[2] = self.gain;

        self.vu[4] = maxf(
            self.vu[4], 
            get_absmax(
                data_l.as_mut_ptr(), 
                block_size_quad![N])
        );

        self.vu[5] = maxf(
            self.vu[5], 
            get_absmax(
                data_r.as_mut_ptr(), 
                block_size_quad![N])
        );
    }
}

impl ProcessOnlyControl for Conditioner {

    fn process_only_control<const N: usize>(&mut self) { 

        let cfg = ConditionerProcessCfg::new(self);

        write_vu_from_falloff![self,cfg];

        for _k in 0..N 
        {
            self.filtered_lamax  = (1.0 - cfg.attack)  * self.filtered_lamax  + cfg.attack;
            self.filtered_lamax2 = (1.0 - cfg.release) * self.filtered_lamax2 + ( cfg.release * self.filtered_lamax );

            if self.filtered_lamax > self.filtered_lamax2 {
                self.filtered_lamax2 = self.filtered_lamax;
            }

            self.gain = 1.0 / self.filtered_lamax2;
        }

        self.vu[2] = self.gain;
    }
}