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
ix!();
use crate::{
WTOscillator,
WTOscillatorParam,
};
impl WTOscillator {
pub fn convolute(&mut self, voice: i32, fm: bool, stereo: bool)
{
let vidx = voice as usize;
let block_pos: f32 =
self.blitter.oscstate[vidx] *
(BLOCK_SIZE_OS_INV as f32) *
self.blitter.pitchmult_inv;
let mut detune: f64 = (self.drift *
self.blitter.driftlfo[vidx]) as f64;
if self.blitter.n_unison > 1 {
detune += (self.pvalf_extended(WTOscillatorParam::UniSpread) as f64) *
(self.blitter.detune_bias * (voice as f32) + self.blitter.detune_offset) as f64;
}
let ipos = self.get_ipos(fm,vidx);
if self.blitter.state[vidx] == 0 {
self.do_blitstate_zero_for_convolute(vidx);
}
let delay: u32 = match fm {
true => self.fm_delay as u32,
false => ((ipos >> 24) & 0x3f) as u32,
};
let wt_inc: i32 = 1 << self.mipmap[vidx];
let mut dt: f32 = self.wave_wavetable.dt() * (wt_inc as f32);
let tempt: f64 = match self.params[WTOscillatorParam::UniSpread].absolute
{
true => {
let tempt = self.tuner.n2pinv::<f64,true>(
detune * self.tuner.n2pinv::<f64,true>( self.pitch_t as f64) * 16.0 / 0.9443
);
maxd(tempt,0.1)
},
false => {
self.tuner.n2pinv_tuningctr(detune)
},
};
let xt: f32 = {
let mut xt: f32 = ((self.blitter.state[vidx] as f32) + 0.50) * dt;
let taylorscale: f32 = (27.0_f32 / 4.0).sqrt();
xt = 1.0 + self.hskew * 4.0 * xt * (xt - 1.0) * (2.0 * xt - 1.0) * taylorscale;
xt
};
let formant: f32 = {
let ft: f32 = lerp(block_pos, self.formant_last, self.formant_t);
self.tuner.n2p_tuningctr(-ft)
};
dt *= formant * xt;
let wtsize: usize = self.wave_wavetable.num_samples_per_table() >> self.mipmap[vidx];
if self.blitter.state[vidx] >= ((wtsize - 1) as i32){
dt += 1.0 - formant;
}
let t: f32 = dt * (tempt as f32);
self.blitter.state[vidx] &= (wtsize - 1) as i32;
let newlevel: f32 = self.get_newlevel(vidx, block_pos);
let mut g: f32 = newlevel - self.last_level[vidx];
self.last_level[vidx] = newlevel;
g *= self.blitter.out_attenuation;
if stereo {
g *= self.blitter.pan_l[vidx];
}
match stereo {
true => self.convolute_stereo(g, delay, ipos),
false => self.convolute_mono(g, delay, ipos),
}
self.blitter.rate[vidx] = t;
self.blitter.oscstate[vidx] += self.blitter.rate[vidx];
self.blitter.oscstate[vidx] = maxf(0.0, self.blitter.oscstate[vidx]);
self.blitter.state[vidx] = (self.blitter.state[vidx] + 1) &
(((self.wave_wavetable.num_samples_per_table() >> self.mipmap[vidx]) - 1) as i32);
}
}