1+ use crate :: custom_dsp:: { Dsp , DspType , Parameter , ParameterType , ProcessResult } ;
2+ use circular_buffer:: CircularBuffer ;
3+ use realfft:: num_complex:: Complex ;
4+ use realfft:: num_traits:: Zero ;
5+ use realfft:: { ComplexToReal , RealFftPlanner , RealToComplex } ;
6+ use std:: sync:: Arc ;
7+
8+ const BUFLEN : usize = 4096 ;
9+ const HBUFLEN : usize = BUFLEN / 2 + 1 ;
10+
11+ pub struct Fantasy {
12+ delay : CircularBuffer < BUFLEN , f32 > ,
13+ silence : usize ,
14+
15+ persistent_freqs : [ f32 ; HBUFLEN ] ,
16+
17+ scratch : [ Complex < f32 > ; BUFLEN ] ,
18+ out : [ Complex < f32 > ; HBUFLEN ] ,
19+ copy : [ f32 ; BUFLEN ] ,
20+ residual : [ f32 ; BUFLEN / 2 ] ,
21+ dft_fwd : Arc < dyn RealToComplex < f32 > > ,
22+ dft_bwd : Arc < dyn ComplexToReal < f32 > > ,
23+
24+ detune_window : usize ,
25+ detune_factor : f32 ,
26+ detune_bias : bool ,
27+
28+ echo_decay : f32 ,
29+ echo_support : f32
30+ }
31+
32+ impl Dsp for Fantasy {
33+ fn name ( ) -> & ' static str {
34+ "Fantasy"
35+ }
36+
37+ fn version ( ) -> u32 {
38+ 1
39+ }
40+
41+ fn ty ( ) -> DspType {
42+ DspType :: Effect
43+ }
44+
45+ fn parameters ( ) -> Vec < Parameter < Self > > {
46+ vec ! [
47+ Parameter {
48+ ty: ParameterType :: Float {
49+ min: 0.0 ,
50+ max: 1.0 ,
51+ default : 0.7 ,
52+ setter: |value, dsp| dsp. detune_factor = value,
53+ getter: |dsp| dsp. detune_factor,
54+ } ,
55+ name: "detune_factor" ,
56+ unit: "" ,
57+ desc: "" ,
58+ } ,
59+ Parameter {
60+ ty: ParameterType :: Int {
61+ min: 0 ,
62+ max: 20 ,
63+ default : 8 ,
64+ max_is_inf: false ,
65+ names: None ,
66+ setter: |value, dsp| dsp. detune_window = value as usize ,
67+ getter: |dsp| dsp. detune_window as i32 ,
68+ } ,
69+ name: "detune_window" ,
70+ unit: " bands" ,
71+ desc: "" ,
72+ } ,
73+ Parameter {
74+ ty: ParameterType :: Bool {
75+ names: Some ( ( "Forward" , "Backwards" ) ) ,
76+ default : true ,
77+ setter: |value, dsp| dsp. detune_bias = value,
78+ getter: |dsp| dsp. detune_bias,
79+ } ,
80+ name: "detune_bias" ,
81+ unit: "" ,
82+ desc: "" ,
83+ } ,
84+ Parameter {
85+ ty: ParameterType :: Float {
86+ min: 0.5 ,
87+ max: 0.99 ,
88+ default : 0.95 ,
89+ setter: |value, dsp| dsp. echo_decay = value,
90+ getter: |dsp| dsp. echo_decay,
91+ } ,
92+ name: "echo_decay" ,
93+ unit: "" ,
94+ desc: "" ,
95+ } ,
96+ Parameter {
97+ ty: ParameterType :: Float {
98+ min: 0.0 ,
99+ max: 1.0 ,
100+ default : 0.1 ,
101+ setter: |value, dsp| dsp. echo_support = value,
102+ getter: |dsp| dsp. echo_support,
103+ } ,
104+ name: "echo_support" ,
105+ unit: "" ,
106+ desc: "" ,
107+ }
108+ ]
109+ }
110+
111+ fn create ( ) -> Self {
112+ let mut planner = RealFftPlanner :: new ( ) ;
113+ Fantasy {
114+ delay : Default :: default ( ) ,
115+ silence : 0 ,
116+
117+ persistent_freqs : [ 0. ; HBUFLEN ] ,
118+
119+ scratch : [ Complex :: zero ( ) ; BUFLEN ] ,
120+ out : [ Complex :: zero ( ) ; HBUFLEN ] ,
121+ copy : [ 0. ; BUFLEN ] ,
122+ residual : [ 0. ; BUFLEN / 2 ] ,
123+ dft_fwd : planner. plan_fft_forward ( BUFLEN ) ,
124+ dft_bwd : planner. plan_fft_inverse ( BUFLEN ) ,
125+
126+ detune_factor : 0.7 ,
127+ detune_window : 8 ,
128+ detune_bias : true ,
129+
130+ echo_decay : 0.95 ,
131+ echo_support : 0.1
132+ }
133+ }
134+
135+ fn reset ( & mut self ) {
136+ self . delay . fill ( 0. ) ;
137+ self . silence = 0 ;
138+ self . persistent_freqs . fill ( 0. ) ;
139+ self . residual . fill ( 0. ) ;
140+ }
141+
142+ fn should_process ( & mut self , idle : bool , incoming_length : usize ) -> ProcessResult {
143+ if idle {
144+ self . silence += incoming_length;
145+ if self . silence >= BUFLEN && self . persistent_freqs . iter ( ) . all ( |it| * it <= 0.0001 ) {
146+ ProcessResult :: SkipSilent
147+ } else {
148+ ProcessResult :: Continue
149+ }
150+ } else {
151+ self . silence = 0 ;
152+ ProcessResult :: Continue
153+ }
154+ }
155+
156+ fn read (
157+ & mut self ,
158+ in_data : & [ f32 ] ,
159+ out_data : & mut [ f32 ] ,
160+ in_channels : usize ,
161+ out_channels : usize ,
162+ ) {
163+ out_data. fill ( 0. ) ;
164+
165+ self . delay . extend (
166+ in_data
167+ . iter ( )
168+ . step_by ( 2 )
169+ . zip ( in_data. iter ( ) . skip ( 1 ) . step_by ( 2 ) )
170+ . map ( |( l, r) | ( l + r) / 2. ) ,
171+ ) ;
172+
173+ if self . delay . is_full ( ) {
174+ copy_contiguous ( & self . delay , & mut self . copy ) ;
175+ self . dft_fwd
176+ . process_with_scratch ( & mut self . copy , & mut self . out , & mut self . scratch )
177+ . unwrap ( ) ;
178+
179+ self . scratch [ ..HBUFLEN ] . copy_from_slice ( & self . out ) ;
180+ for i in 8 ..HBUFLEN -8 {
181+ let orig_norm = self . out [ i] . norm ( ) ;
182+ let mut target_norm = orig_norm;
183+
184+ let window: usize = self . detune_window ;
185+ if window > 0 {
186+ let start = window. saturating_sub ( i) ;
187+ let end = ( 2 * window + 1 ) . min ( HBUFLEN - 2 - i) ;
188+ let range = start..=end;
189+ if self . detune_bias {
190+ for j in range { // the world if you could `let it: impl Iterator<...>`
191+ target_norm = ( 1. - self . detune_factor ) * target_norm + self . detune_factor * self . scratch [ i + j - window] . norm ( ) ;
192+ }
193+ } else {
194+ for j in range. rev ( ) {
195+ target_norm = ( 1. - self . detune_factor ) * target_norm + self . detune_factor * self . scratch [ i + j - window] . norm ( ) ;
196+ }
197+ }
198+ //target_norm = (i-range..=i+range).map(|i| self.scratch[i].norm()).sum::<f32>() / (range * 2 + 1) as f32;
199+ }
200+
201+ target_norm += self . persistent_freqs [ i] ;
202+
203+ if orig_norm < 0.000001 {
204+ //self.out[i] = Complex::from(target_norm);
205+ } else {
206+ self . out [ i] *= target_norm / orig_norm;
207+ }
208+
209+ self . persistent_freqs [ i] += orig_norm * self . echo_support ;
210+ self . persistent_freqs [ i] *= self . echo_decay ;
211+ }
212+
213+ self . dft_bwd
214+ . process_with_scratch ( & mut self . out , & mut self . copy , & mut self . scratch )
215+ . unwrap ( ) ;
216+ }
217+
218+ let out_len = out_data. len ( ) / out_channels;
219+ for i in 0 ..BUFLEN {
220+ self . copy [ i] /= BUFLEN as f32 ;
221+ }
222+
223+ // write to outputs
224+ for i in 0 ..out_len {
225+ let new = self . copy [ BUFLEN - ( out_len * 2 ) + i] ;
226+ let old = self . residual [ i] ;
227+ let it = interp ( old, new, i, out_len) ;
228+ out_data[ i * 2 ] = it;
229+ out_data[ i * 2 + 1 ] = it;
230+ }
231+
232+ // update residual
233+ self . residual [ ..out_len] . copy_from_slice ( & self . copy [ BUFLEN - out_len..] ) ;
234+ }
235+ }
236+
237+ fn copy_contiguous < const N : usize , T : Copy > ( from : & CircularBuffer < N , T > , to : & mut [ T ] ) {
238+ let ( p1, p2) = from. as_slices ( ) ;
239+ to[ ..p1. len ( ) ] . copy_from_slice ( p1) ;
240+ to[ p1. len ( ) ..p1. len ( ) + p2. len ( ) ] . copy_from_slice ( p2) ;
241+ }
242+
243+ fn interp ( x : f32 , y : f32 , i : usize , l : usize ) -> f32 {
244+ let r = i as f32 / ( l - 1 ) as f32 ;
245+ ( 1. - r) * x + r * y
246+ }
0 commit comments