1 /* GSequencer - Advanced GTK Sequencer
2  * Copyright (C) 2005-2021 Joël Krähemann
3  *
4  * This file is part of GSequencer.
5  *
6  * GSequencer is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GSequencer is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with GSequencer.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <ags/audio/ags_filter_util.h>
21 
22 #include <ags/audio/ags_audio_signal.h>
23 #include <ags/audio/ags_audio_buffer_util.h>
24 #include <ags/audio/ags_fourier_transform_util.h>
25 
26 #include <math.h>
27 #include <complex.h>
28 
29 gpointer ags_filter_util_copy(gpointer ptr);
30 void ags_filter_util_free(gpointer ptr);
31 
32 /**
33  * SECTION:ags_filter_util
34  * @short_description: filter util
35  * @title: AgsFilterUtil
36  * @section_id:
37  * @include: ags/audio/ags_filter_util.h
38  *
39  * Utility functions to compute filters.
40  */
41 
42 GType
ags_filter_util_get_type(void)43 ags_filter_util_get_type(void)
44 {
45   static volatile gsize g_define_type_id__volatile = 0;
46 
47   if(g_once_init_enter (&g_define_type_id__volatile)){
48     GType ags_type_filter_util = 0;
49 
50     ags_type_filter_util =
51       g_boxed_type_register_static("AgsFilterUtil",
52 				   (GBoxedCopyFunc) ags_filter_util_copy,
53 				   (GBoxedFreeFunc) ags_filter_util_free);
54 
55     g_once_init_leave(&g_define_type_id__volatile, ags_type_filter_util);
56   }
57 
58   return g_define_type_id__volatile;
59 }
60 
61 gpointer
ags_filter_util_copy(gpointer ptr)62 ags_filter_util_copy(gpointer ptr)
63 {
64   gpointer retval;
65 
66   retval = g_memdup(ptr, sizeof(AgsFilterUtil));
67 
68   return(retval);
69 }
70 
71 void
ags_filter_util_free(gpointer ptr)72 ags_filter_util_free(gpointer ptr)
73 {
74   g_free(ptr);
75 }
76 
77 /**
78  * ags_filter_util_pitch_s8:
79  * @buffer: the audio buffer
80  * @buffer_length: the buffer's length
81  * @samplerate: the samplerate
82  * @base_key: the base key
83  * @tuning: the tuning
84  *
85  * Apply pitch filter.
86  *
87  * Since: 3.0.0
88  */
89 void
ags_filter_util_pitch_s8(gint8 * buffer,guint buffer_length,guint samplerate,gdouble base_key,gdouble tuning)90 ags_filter_util_pitch_s8(gint8 *buffer,
91 			 guint buffer_length,
92 			 guint samplerate,
93 			 gdouble base_key,
94 			 gdouble tuning)
95 {
96   AgsComplex *ptr_mix_buffer, *ptr_im_mix_buffer, *ptr_low_mix_buffer, *ptr_new_mix_buffer;
97   AgsComplex *mix_buffer, *im_mix_buffer, *low_mix_buffer, *new_mix_buffer;
98   gint8 *ptr_buffer;
99 
100   gdouble volume;
101   gdouble im_key, low_key;
102   gdouble base_freq, im_freq, low_freq, new_freq;
103   gdouble offset_factor, im_offset_factor, low_offset_factor, new_offset_factor;
104   gdouble freq_period, im_freq_period, low_freq_period, new_freq_period;
105   gdouble t;
106   guint i;
107 
108   if(buffer == NULL){
109     return;
110   }
111 
112   /* frequency */
113   base_freq = exp2((base_key) / 12.0) * 440.0;
114 
115   im_key = (gdouble) ((gint) floor(tuning / 100.0) % 12);
116 
117   if(im_key < 0.0){
118     im_key += 12.0;
119   }
120 
121   if(im_key == 0.0){
122     im_key = 1.0;
123   }
124 
125   im_freq = exp2((base_key + im_key) / 12.0) * 440.0;
126 
127   low_key = base_key - 12.0;
128 
129   low_freq = exp2((low_key) / 12.0) * 440.0;
130 
131   new_freq = exp2((base_key + (tuning / 100.0))  / 12.0) * 440.0;
132 
133   if(base_freq <= 0.0){
134     g_warning("rejecting pitch base freq %f <= 0.0", base_freq);
135 
136     return;
137   }
138 
139   if(im_freq <= 0.0){
140     g_warning("rejecting pitch intermediate freq %f <= 0.0", im_freq);
141 
142     return;
143   }
144 
145   if(new_freq <= 0.0){
146     g_warning("rejecting pitch new freq %f <= 0.0", new_freq);
147 
148     return;
149   }
150 
151   volume = 1.0 / base_freq * new_freq;
152 
153   /* get frequency period */
154   freq_period = samplerate / base_freq;
155 
156   im_freq_period = samplerate / im_freq;
157   low_freq_period = samplerate / low_freq;
158   new_freq_period = samplerate / new_freq;
159 
160   /* get offset factor */
161   offset_factor = 1.0;
162 
163   im_offset_factor = 1.0 / (samplerate / base_freq) * (samplerate / im_freq);
164   low_offset_factor = 1.0 / (samplerate / base_freq) * (samplerate / low_freq);
165   new_offset_factor = 1.0 / (samplerate / base_freq) * (samplerate / new_freq);
166 
167   /* allocate buffer */
168   mix_buffer = (AgsComplex *) ags_stream_alloc(buffer_length,
169 					       AGS_SOUNDCARD_COMPLEX);
170 
171   im_mix_buffer = (AgsComplex *) ags_stream_alloc(buffer_length,
172 						  AGS_SOUNDCARD_COMPLEX);
173 
174   low_mix_buffer = (AgsComplex *) ags_stream_alloc(buffer_length,
175 						   AGS_SOUNDCARD_COMPLEX);
176 
177   new_mix_buffer = (AgsComplex *) ags_stream_alloc(buffer_length,
178 						   AGS_SOUNDCARD_COMPLEX);
179 
180   /* mix buffer */
181   for(i = 0; i < buffer_length; i++){
182     ptr_mix_buffer = mix_buffer + i;
183 
184     /* write mix buffer */
185     AGS_AUDIO_BUFFER_UTIL_S8_TO_COMPLEX(buffer[i], &ptr_mix_buffer);
186   }
187 
188   /* im mix buffer */
189   for(i = 0; i < buffer_length; i++){
190     double _Complex z, mix_z, im_z;
191     gdouble phase, im_phase;
192     guint start_x;
193 
194     if(floor(freq_period) != 0.0){
195       start_x = freq_period * floor((double) i / freq_period);
196     }else{
197       start_x = 0;
198     }
199 
200     im_phase = fmod(i, im_freq_period);
201 
202     phase = fmod(i, freq_period);
203 
204     if(start_x + (guint) floor(phase) < buffer_length){
205       ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(phase));
206     }else{
207       if((start_x + (guint) floor(phase)) - (guint) floor(freq_period) < buffer_length &&
208 	 (start_x + (guint) floor(phase)) - (guint) floor(freq_period) > 0){
209 	ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(phase)) - (guint) floor(freq_period);
210       }else{
211 	if(floor(phase) < buffer_length){
212 	  ptr_mix_buffer = mix_buffer + (guint) floor(phase);
213 	}else{
214 	  ptr_mix_buffer = mix_buffer + buffer_length - 1;
215 	}
216       }
217     }
218 
219     ptr_im_mix_buffer = im_mix_buffer + i;
220 
221     /* write im mix buffer */
222     z = ags_complex_get(mix_buffer + i);
223     mix_z = ags_complex_get(ptr_mix_buffer);
224 
225     t = (im_freq_period / freq_period);
226 
227     im_z = (1.0 - t) * z + (t * mix_z);
228 
229     ags_complex_set(ptr_im_mix_buffer, im_z);
230   }
231 
232   /* low mix buffer */
233   for(i = 0; i < buffer_length; i++){
234     double _Complex z, mix_z, low_z;
235     gdouble phase, low_phase;
236     guint start_x;
237 
238     if(floor(freq_period) != 0.0){
239       start_x = freq_period * floor((double) i / freq_period);
240     }else{
241       start_x = 0;
242     }
243 
244     low_phase = fmod(i, low_freq_period);
245 
246     phase = fmod(i, freq_period);
247 
248     if(start_x + (guint) floor(phase) < buffer_length){
249       ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(phase));
250     }else{
251       if((start_x + (guint) floor(phase)) - (guint) floor(freq_period) < buffer_length &&
252 	 (start_x + (guint) floor(phase)) - (guint) floor(freq_period) > 0){
253 	ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(phase)) - (guint) floor(freq_period);
254       }else{
255 	if(floor(phase) < buffer_length){
256 	  ptr_mix_buffer = mix_buffer + (guint) floor(phase);
257 	}else{
258 	  ptr_mix_buffer = mix_buffer + buffer_length - 1;
259 	}
260       }
261     }
262 
263     ptr_low_mix_buffer = low_mix_buffer + i;
264 
265     /* write low mix buffer */
266     z = ags_complex_get(mix_buffer + i);
267     mix_z = ags_complex_get(ptr_mix_buffer);
268 
269     t = (low_freq_period / freq_period);
270 
271     low_z = (1.0 - t) * z + (t * mix_z);
272 
273     ags_complex_set(ptr_low_mix_buffer, low_z);
274   }
275 
276   /* new mix buffer */
277   for(i = 0; i < buffer_length; i++){
278     double _Complex new_z;
279     gdouble phase, im_phase, low_phase, new_phase;
280     guint start_x, im_start_x, low_start_x;
281 
282     if(floor(freq_period) != 0.0){
283       start_x = freq_period * floor((double) i / freq_period);
284     }else{
285       start_x = 0;
286     }
287 
288     if(floor(im_freq_period) != 0.0){
289       im_start_x = im_freq_period * floor((double) i / im_freq_period);
290     }else{
291       im_start_x = 0;
292     }
293 
294     if(floor(low_freq_period) != 0.0){
295       low_start_x = low_freq_period * floor((double) i / low_freq_period);
296     }else{
297       low_start_x = 0;
298     }
299 
300     phase = fmod(i, freq_period);
301 
302     im_phase = fmod(i, im_freq_period);
303 
304     low_phase = fmod(i, low_freq_period);
305 
306     new_phase = fmod(i, new_freq_period);
307 
308     if(start_x + (guint) floor(new_phase) < buffer_length){
309       ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(new_phase));
310     }else{
311       if((start_x + (guint) floor(new_phase)) - (guint) floor(freq_period) < buffer_length &&
312 	 (start_x + (guint) floor(new_phase)) - (guint) floor(freq_period) > 0){
313 	ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(new_phase)) - (guint) floor(freq_period);
314       }else{
315 	if(floor(new_phase) < buffer_length){
316 	  ptr_mix_buffer = mix_buffer + (guint) floor(new_phase);
317 	}else{
318 	  ptr_mix_buffer = mix_buffer + buffer_length - 1;
319 	}
320       }
321     }
322 
323     if(im_start_x + (guint) floor(new_phase) < buffer_length){
324       ptr_im_mix_buffer = im_mix_buffer + (im_start_x + (guint) floor(new_phase));
325     }else{
326       if((im_start_x + (guint) floor(new_phase)) - (guint) floor(im_freq_period) < buffer_length &&
327 	 (im_start_x + (guint) floor(new_phase)) - (guint) floor(im_freq_period) > 0){
328 	ptr_im_mix_buffer = im_mix_buffer + (im_start_x + (guint) floor(new_phase)) - (guint) floor(im_freq_period);
329       }else{
330 	if(floor(new_phase) < buffer_length){
331 	  ptr_im_mix_buffer = im_mix_buffer + (guint) floor(new_phase);
332 	}else{
333 	  ptr_im_mix_buffer = im_mix_buffer + buffer_length - 1;
334 	}
335       }
336     }
337 
338     if(low_start_x + (guint) floor(new_phase) < buffer_length){
339       ptr_low_mix_buffer = low_mix_buffer + (low_start_x + (guint) floor(new_phase));
340     }else{
341       if((low_start_x + (guint) floor(new_phase)) - (guint) floor(low_freq_period) < buffer_length &&
342 	 (low_start_x + (guint) floor(new_phase)) - (guint) floor(low_freq_period) > 0){
343 	ptr_low_mix_buffer = low_mix_buffer + (low_start_x + (guint) floor(new_phase)) - (guint) floor(low_freq_period);
344       }else{
345 	if(floor(new_phase) < buffer_length){
346 	  ptr_low_mix_buffer = low_mix_buffer + (guint) floor(new_phase);
347 	}else{
348 	  ptr_low_mix_buffer = low_mix_buffer + buffer_length - 1;
349 	}
350       }
351     }
352 
353     ptr_new_mix_buffer = new_mix_buffer + i;
354 
355     /* write new mix buffer */
356     if(ptr_mix_buffer->real != 0.0){
357       new_z = volume * ((1.0 / 2.0) * (new_freq_period * (ags_complex_get(ptr_mix_buffer) / freq_period) * (ags_complex_get(ptr_im_mix_buffer) / im_freq_period) / (ags_complex_get(ptr_mix_buffer) / freq_period)) + (1.0 / 2.0) * (new_freq_period * (ags_complex_get(ptr_mix_buffer) / freq_period) * (ags_complex_get(ptr_low_mix_buffer) / low_freq_period) / (ags_complex_get(ptr_mix_buffer) / freq_period)));
358     }else{
359       new_z = 0.0 + I * 0.0;
360     }
361 
362     ags_complex_set(ptr_new_mix_buffer,
363 		    new_z);
364   }
365 
366   /* rewrite buffer */
367   for(i = 0; i < buffer_length; i++){
368     ptr_new_mix_buffer = new_mix_buffer + i;
369     ptr_buffer = buffer + i;
370 
371     AGS_AUDIO_BUFFER_UTIL_COMPLEX_TO_S8(ptr_new_mix_buffer, ptr_buffer);
372   }
373 
374   ags_stream_free(mix_buffer);
375 
376   ags_stream_free(im_mix_buffer);
377 
378   ags_stream_free(low_mix_buffer);
379 
380   ags_stream_free(new_mix_buffer);
381 }
382 
383 /**
384  * ags_filter_util_pitch_s16:
385  * @buffer: the audio buffer
386  * @buffer_length: the buffer's length
387  * @samplerate: the samplerate
388  * @base_key: the base key
389  * @tuning: the tuning
390  *
391  * Apply pitch filter.
392  *
393  * Since: 3.0.0
394  */
395 void
ags_filter_util_pitch_s16(gint16 * buffer,guint buffer_length,guint samplerate,gdouble base_key,gdouble tuning)396 ags_filter_util_pitch_s16(gint16 *buffer,
397 			  guint buffer_length,
398 			  guint samplerate,
399 			  gdouble base_key,
400 			  gdouble tuning)
401 {
402   AgsComplex *ptr_mix_buffer, *ptr_im_mix_buffer, *ptr_low_mix_buffer, *ptr_new_mix_buffer;
403   AgsComplex *mix_buffer, *im_mix_buffer, *low_mix_buffer, *new_mix_buffer;
404   gint16 *ptr_buffer;
405 
406   gdouble volume;
407   gdouble im_key, low_key;
408   gdouble base_freq, im_freq, low_freq, new_freq;
409   gdouble offset_factor, im_offset_factor, low_offset_factor, new_offset_factor;
410   gdouble freq_period, im_freq_period, low_freq_period, new_freq_period;
411   gdouble t;
412   guint i;
413 
414   if(buffer == NULL){
415     return;
416   }
417 
418   /* frequency */
419   base_freq = exp2((base_key) / 12.0) * 440.0;
420 
421   im_key = (gdouble) ((gint) floor(tuning / 100.0) % 12);
422 
423   if(im_key < 0.0){
424     im_key += 12.0;
425   }
426 
427   if(im_key == 0.0){
428     im_key = 1.0;
429   }
430 
431   im_freq = exp2((base_key + im_key) / 12.0) * 440.0;
432 
433   low_key = base_key - 12.0;
434 
435   low_freq = exp2((low_key) / 12.0) * 440.0;
436 
437   new_freq = exp2((base_key + (tuning / 100.0))  / 12.0) * 440.0;
438 
439   if(base_freq <= 0.0){
440     g_warning("rejecting pitch base freq %f <= 0.0", base_freq);
441 
442     return;
443   }
444 
445   if(im_freq <= 0.0){
446     g_warning("rejecting pitch intermediate freq %f <= 0.0", im_freq);
447 
448     return;
449   }
450 
451   if(new_freq <= 0.0){
452     g_warning("rejecting pitch new freq %f <= 0.0", new_freq);
453 
454     return;
455   }
456 
457   volume = 1.0 / base_freq * new_freq;
458 
459   /* get frequency period */
460   freq_period = samplerate / base_freq;
461 
462   im_freq_period = samplerate / im_freq;
463   low_freq_period = samplerate / low_freq;
464   new_freq_period = samplerate / new_freq;
465 
466   /* get offset factor */
467   offset_factor = 1.0;
468 
469   im_offset_factor = 1.0 / (samplerate / base_freq) * (samplerate / im_freq);
470   low_offset_factor = 1.0 / (samplerate / base_freq) * (samplerate / low_freq);
471   new_offset_factor = 1.0 / (samplerate / base_freq) * (samplerate / new_freq);
472 
473   /* allocate buffer */
474   mix_buffer = (AgsComplex *) ags_stream_alloc(buffer_length,
475 					       AGS_SOUNDCARD_COMPLEX);
476 
477   im_mix_buffer = (AgsComplex *) ags_stream_alloc(buffer_length,
478 						  AGS_SOUNDCARD_COMPLEX);
479 
480   low_mix_buffer = (AgsComplex *) ags_stream_alloc(buffer_length,
481 						   AGS_SOUNDCARD_COMPLEX);
482 
483   new_mix_buffer = (AgsComplex *) ags_stream_alloc(buffer_length,
484 						   AGS_SOUNDCARD_COMPLEX);
485 
486   /* mix buffer */
487   for(i = 0; i < buffer_length; i++){
488     ptr_mix_buffer = mix_buffer + i;
489 
490     /* write mix buffer */
491     AGS_AUDIO_BUFFER_UTIL_S16_TO_COMPLEX(buffer[i], &ptr_mix_buffer);
492   }
493 
494   /* im mix buffer */
495   for(i = 0; i < buffer_length; i++){
496     double _Complex z, mix_z, im_z;
497     gdouble phase, im_phase;
498     guint start_x;
499 
500     if(floor(freq_period) != 0.0){
501       start_x = freq_period * floor((double) i / freq_period);
502     }else{
503       start_x = 0;
504     }
505 
506     im_phase = fmod(i, im_freq_period);
507 
508     phase = fmod(i, freq_period);
509 
510     if(start_x + (guint) floor(phase) < buffer_length){
511       ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(phase));
512     }else{
513       if((start_x + (guint) floor(phase)) - (guint) floor(freq_period) < buffer_length &&
514 	 (start_x + (guint) floor(phase)) - (guint) floor(freq_period) > 0){
515 	ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(phase)) - (guint) floor(freq_period);
516       }else{
517 	if(floor(phase) < buffer_length){
518 	  ptr_mix_buffer = mix_buffer + (guint) floor(phase);
519 	}else{
520 	  ptr_mix_buffer = mix_buffer + buffer_length - 1;
521 	}
522       }
523     }
524 
525     ptr_im_mix_buffer = im_mix_buffer + i;
526 
527     /* write im mix buffer */
528     z = ags_complex_get(mix_buffer + i);
529     mix_z = ags_complex_get(ptr_mix_buffer);
530 
531     t = (im_freq_period / freq_period);
532 
533     im_z = (1.0 - t) * z + (t * mix_z);
534 
535     ags_complex_set(ptr_im_mix_buffer, im_z);
536   }
537 
538   /* low mix buffer */
539   for(i = 0; i < buffer_length; i++){
540     double _Complex z, mix_z, low_z;
541     gdouble phase, low_phase;
542     guint start_x;
543 
544     if(floor(freq_period) != 0.0){
545       start_x = freq_period * floor((double) i / freq_period);
546     }else{
547       start_x = 0;
548     }
549 
550     low_phase = fmod(i, low_freq_period);
551 
552     phase = fmod(i, freq_period);
553 
554     if(start_x + (guint) floor(phase) < buffer_length){
555       ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(phase));
556     }else{
557       if((start_x + (guint) floor(phase)) - (guint) floor(freq_period) < buffer_length &&
558 	 (start_x + (guint) floor(phase)) - (guint) floor(freq_period) > 0){
559 	ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(phase)) - (guint) floor(freq_period);
560       }else{
561 	if(floor(phase) < buffer_length){
562 	  ptr_mix_buffer = mix_buffer + (guint) floor(phase);
563 	}else{
564 	  ptr_mix_buffer = mix_buffer + buffer_length - 1;
565 	}
566       }
567     }
568 
569     ptr_low_mix_buffer = low_mix_buffer + i;
570 
571     /* write low mix buffer */
572     z = ags_complex_get(mix_buffer + i);
573     mix_z = ags_complex_get(ptr_mix_buffer);
574 
575     t = (low_freq_period / freq_period);
576 
577     low_z = (1.0 - t) * z + (t * mix_z);
578 
579     ags_complex_set(ptr_low_mix_buffer, low_z);
580   }
581 
582   /* new mix buffer */
583   for(i = 0; i < buffer_length; i++){
584     double _Complex new_z;
585     gdouble phase, im_phase, low_phase, new_phase;
586     guint start_x, im_start_x, low_start_x;
587 
588     if(floor(freq_period) != 0.0){
589       start_x = freq_period * floor((double) i / freq_period);
590     }else{
591       start_x = 0;
592     }
593 
594     if(floor(im_freq_period) != 0.0){
595       im_start_x = im_freq_period * floor((double) i / im_freq_period);
596     }else{
597       im_start_x = 0;
598     }
599 
600     if(floor(low_freq_period) != 0.0){
601       low_start_x = low_freq_period * floor((double) i / low_freq_period);
602     }else{
603       low_start_x = 0;
604     }
605 
606     phase = fmod(i, freq_period);
607 
608     im_phase = fmod(i, im_freq_period);
609 
610     low_phase = fmod(i, low_freq_period);
611 
612     new_phase = fmod(i, new_freq_period);
613 
614     if(start_x + (guint) floor(new_phase) < buffer_length){
615       ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(new_phase));
616     }else{
617       if((start_x + (guint) floor(new_phase)) - (guint) floor(freq_period) < buffer_length &&
618 	 (start_x + (guint) floor(new_phase)) - (guint) floor(freq_period) > 0){
619 	ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(new_phase)) - (guint) floor(freq_period);
620       }else{
621 	if(floor(new_phase) < buffer_length){
622 	  ptr_mix_buffer = mix_buffer + (guint) floor(new_phase);
623 	}else{
624 	  ptr_mix_buffer = mix_buffer + buffer_length - 1;
625 	}
626       }
627     }
628 
629     if(im_start_x + (guint) floor(new_phase) < buffer_length){
630       ptr_im_mix_buffer = im_mix_buffer + (im_start_x + (guint) floor(new_phase));
631     }else{
632       if((im_start_x + (guint) floor(new_phase)) - (guint) floor(im_freq_period) < buffer_length &&
633 	 (im_start_x + (guint) floor(new_phase)) - (guint) floor(im_freq_period) > 0){
634 	ptr_im_mix_buffer = im_mix_buffer + (im_start_x + (guint) floor(new_phase)) - (guint) floor(im_freq_period);
635       }else{
636 	if(floor(new_phase) < buffer_length){
637 	  ptr_im_mix_buffer = im_mix_buffer + (guint) floor(new_phase);
638 	}else{
639 	  ptr_im_mix_buffer = im_mix_buffer + buffer_length - 1;
640 	}
641       }
642     }
643 
644     if(low_start_x + (guint) floor(new_phase) < buffer_length){
645       ptr_low_mix_buffer = low_mix_buffer + (low_start_x + (guint) floor(new_phase));
646     }else{
647       if((low_start_x + (guint) floor(new_phase)) - (guint) floor(low_freq_period) < buffer_length &&
648 	 (low_start_x + (guint) floor(new_phase)) - (guint) floor(low_freq_period) > 0){
649 	ptr_low_mix_buffer = low_mix_buffer + (low_start_x + (guint) floor(new_phase)) - (guint) floor(low_freq_period);
650       }else{
651 	if(floor(new_phase) < buffer_length){
652 	  ptr_low_mix_buffer = low_mix_buffer + (guint) floor(new_phase);
653 	}else{
654 	  ptr_low_mix_buffer = low_mix_buffer + buffer_length - 1;
655 	}
656       }
657     }
658 
659     ptr_new_mix_buffer = new_mix_buffer + i;
660 
661     /* write new mix buffer */
662     if(ptr_mix_buffer->real != 0.0){
663       new_z = volume * ((1.0 / 2.0) * (new_freq_period * (ags_complex_get(ptr_mix_buffer) / freq_period) * (ags_complex_get(ptr_im_mix_buffer) / im_freq_period) / (ags_complex_get(ptr_mix_buffer) / freq_period)) + (1.0 / 2.0) * (new_freq_period * (ags_complex_get(ptr_mix_buffer) / freq_period) * (ags_complex_get(ptr_low_mix_buffer) / low_freq_period) / (ags_complex_get(ptr_mix_buffer) / freq_period)));
664     }else{
665       new_z = 0.0 + I * 0.0;
666     }
667 
668     ags_complex_set(ptr_new_mix_buffer,
669 		    new_z);
670   }
671 
672   /* rewrite buffer */
673   for(i = 0; i < buffer_length; i++){
674     ptr_new_mix_buffer = new_mix_buffer + i;
675     ptr_buffer = buffer + i;
676 
677     AGS_AUDIO_BUFFER_UTIL_COMPLEX_TO_S16(ptr_new_mix_buffer, ptr_buffer);
678   }
679 
680   ags_stream_free(mix_buffer);
681 
682   ags_stream_free(im_mix_buffer);
683 
684   ags_stream_free(low_mix_buffer);
685 
686   ags_stream_free(new_mix_buffer);
687 }
688 
689 /**
690  * ags_filter_util_pitch_s24:
691  * @buffer: the audio buffer
692  * @buffer_length: the buffer's length
693  * @samplerate: the samplerate
694  * @base_key: the base key
695  * @tuning: the tuning
696  *
697  * Apply pitch filter.
698  *
699  * Since: 3.0.0
700  */
701 void
ags_filter_util_pitch_s24(gint32 * buffer,guint buffer_length,guint samplerate,gdouble base_key,gdouble tuning)702 ags_filter_util_pitch_s24(gint32 *buffer,
703 			  guint buffer_length,
704 			  guint samplerate,
705 			  gdouble base_key,
706 			  gdouble tuning)
707 {
708   AgsComplex *ptr_mix_buffer, *ptr_im_mix_buffer, *ptr_low_mix_buffer, *ptr_new_mix_buffer;
709   AgsComplex *mix_buffer, *im_mix_buffer, *low_mix_buffer, *new_mix_buffer;
710   gint32 *ptr_buffer;
711 
712   gdouble volume;
713   gdouble im_key, low_key;
714   gdouble base_freq, im_freq, low_freq, new_freq;
715   gdouble offset_factor, im_offset_factor, low_offset_factor, new_offset_factor;
716   gdouble freq_period, im_freq_period, low_freq_period, new_freq_period;
717   gdouble t;
718   guint i;
719 
720   if(buffer == NULL){
721     return;
722   }
723 
724   /* frequency */
725   base_freq = exp2((base_key) / 12.0) * 440.0;
726 
727   im_key = (gdouble) ((gint) floor(tuning / 100.0) % 12);
728 
729   if(im_key < 0.0){
730     im_key += 12.0;
731   }
732 
733   if(im_key == 0.0){
734     im_key = 1.0;
735   }
736 
737   im_freq = exp2((base_key + im_key) / 12.0) * 440.0;
738 
739   low_key = base_key - 12.0;
740 
741   low_freq = exp2((low_key) / 12.0) * 440.0;
742 
743   new_freq = exp2((base_key + (tuning / 100.0))  / 12.0) * 440.0;
744 
745   if(base_freq <= 0.0){
746     g_warning("rejecting pitch base freq %f <= 0.0", base_freq);
747 
748     return;
749   }
750 
751   if(im_freq <= 0.0){
752     g_warning("rejecting pitch intermediate freq %f <= 0.0", im_freq);
753 
754     return;
755   }
756 
757   if(new_freq <= 0.0){
758     g_warning("rejecting pitch new freq %f <= 0.0", new_freq);
759 
760     return;
761   }
762 
763   volume = 1.0 / base_freq * new_freq;
764 
765   /* get frequency period */
766   freq_period = samplerate / base_freq;
767 
768   im_freq_period = samplerate / im_freq;
769   low_freq_period = samplerate / low_freq;
770   new_freq_period = samplerate / new_freq;
771 
772   /* get offset factor */
773   offset_factor = 1.0;
774 
775   im_offset_factor = 1.0 / (samplerate / base_freq) * (samplerate / im_freq);
776   low_offset_factor = 1.0 / (samplerate / base_freq) * (samplerate / low_freq);
777   new_offset_factor = 1.0 / (samplerate / base_freq) * (samplerate / new_freq);
778 
779   /* allocate buffer */
780   mix_buffer = (AgsComplex *) ags_stream_alloc(buffer_length,
781 					       AGS_SOUNDCARD_COMPLEX);
782 
783   im_mix_buffer = (AgsComplex *) ags_stream_alloc(buffer_length,
784 						  AGS_SOUNDCARD_COMPLEX);
785 
786   low_mix_buffer = (AgsComplex *) ags_stream_alloc(buffer_length,
787 						   AGS_SOUNDCARD_COMPLEX);
788 
789   new_mix_buffer = (AgsComplex *) ags_stream_alloc(buffer_length,
790 						   AGS_SOUNDCARD_COMPLEX);
791 
792   /* mix buffer */
793   for(i = 0; i < buffer_length; i++){
794     ptr_mix_buffer = mix_buffer + i;
795 
796     /* write mix buffer */
797     AGS_AUDIO_BUFFER_UTIL_S24_TO_COMPLEX(buffer[i], &ptr_mix_buffer);
798   }
799 
800   /* im mix buffer */
801   for(i = 0; i < buffer_length; i++){
802     double _Complex z, mix_z, im_z;
803     gdouble phase, im_phase;
804     guint start_x;
805 
806     if(floor(freq_period) != 0.0){
807       start_x = freq_period * floor((double) i / freq_period);
808     }else{
809       start_x = 0;
810     }
811 
812     im_phase = fmod(i, im_freq_period);
813 
814     phase = fmod(i, freq_period);
815 
816     if(start_x + (guint) floor(phase) < buffer_length){
817       ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(phase));
818     }else{
819       if((start_x + (guint) floor(phase)) - (guint) floor(freq_period) < buffer_length &&
820 	 (start_x + (guint) floor(phase)) - (guint) floor(freq_period) > 0){
821 	ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(phase)) - (guint) floor(freq_period);
822       }else{
823 	if(floor(phase) < buffer_length){
824 	  ptr_mix_buffer = mix_buffer + (guint) floor(phase);
825 	}else{
826 	  ptr_mix_buffer = mix_buffer + buffer_length - 1;
827 	}
828       }
829     }
830 
831     ptr_im_mix_buffer = im_mix_buffer + i;
832 
833     /* write im mix buffer */
834     z = ags_complex_get(mix_buffer + i);
835     mix_z = ags_complex_get(ptr_mix_buffer);
836 
837     t = (im_freq_period / freq_period);
838 
839     im_z = (1.0 - t) * z + (t * mix_z);
840 
841     ags_complex_set(ptr_im_mix_buffer, im_z);
842   }
843 
844   /* low mix buffer */
845   for(i = 0; i < buffer_length; i++){
846     double _Complex z, mix_z, low_z;
847     gdouble phase, low_phase;
848     guint start_x;
849 
850     if(floor(freq_period) != 0.0){
851       start_x = freq_period * floor((double) i / freq_period);
852     }else{
853       start_x = 0;
854     }
855 
856     low_phase = fmod(i, low_freq_period);
857 
858     phase = fmod(i, freq_period);
859 
860     if(start_x + (guint) floor(phase) < buffer_length){
861       ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(phase));
862     }else{
863       if((start_x + (guint) floor(phase)) - (guint) floor(freq_period) < buffer_length &&
864 	 (start_x + (guint) floor(phase)) - (guint) floor(freq_period) > 0){
865 	ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(phase)) - (guint) floor(freq_period);
866       }else{
867 	if(floor(phase) < buffer_length){
868 	  ptr_mix_buffer = mix_buffer + (guint) floor(phase);
869 	}else{
870 	  ptr_mix_buffer = mix_buffer + buffer_length - 1;
871 	}
872       }
873     }
874 
875     ptr_low_mix_buffer = low_mix_buffer + i;
876 
877     /* write low mix buffer */
878     z = ags_complex_get(mix_buffer + i);
879     mix_z = ags_complex_get(ptr_mix_buffer);
880 
881     t = (low_freq_period / freq_period);
882 
883     low_z = (1.0 - t) * z + (t * mix_z);
884 
885     ags_complex_set(ptr_low_mix_buffer, low_z);
886   }
887 
888   /* new mix buffer */
889   for(i = 0; i < buffer_length; i++){
890     double _Complex new_z;
891     gdouble phase, im_phase, low_phase, new_phase;
892     guint start_x, im_start_x, low_start_x;
893 
894     if(floor(freq_period) != 0.0){
895       start_x = freq_period * floor((double) i / freq_period);
896     }else{
897       start_x = 0;
898     }
899 
900     if(floor(im_freq_period) != 0.0){
901       im_start_x = im_freq_period * floor((double) i / im_freq_period);
902     }else{
903       im_start_x = 0;
904     }
905 
906     if(floor(low_freq_period) != 0.0){
907       low_start_x = low_freq_period * floor((double) i / low_freq_period);
908     }else{
909       low_start_x = 0;
910     }
911 
912     phase = fmod(i, freq_period);
913 
914     im_phase = fmod(i, im_freq_period);
915 
916     low_phase = fmod(i, low_freq_period);
917 
918     new_phase = fmod(i, new_freq_period);
919 
920     if(start_x + (guint) floor(new_phase) < buffer_length){
921       ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(new_phase));
922     }else{
923       if((start_x + (guint) floor(new_phase)) - (guint) floor(freq_period) < buffer_length &&
924 	 (start_x + (guint) floor(new_phase)) - (guint) floor(freq_period) > 0){
925 	ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(new_phase)) - (guint) floor(freq_period);
926       }else{
927 	if(floor(new_phase) < buffer_length){
928 	  ptr_mix_buffer = mix_buffer + (guint) floor(new_phase);
929 	}else{
930 	  ptr_mix_buffer = mix_buffer + buffer_length - 1;
931 	}
932       }
933     }
934 
935     if(im_start_x + (guint) floor(new_phase) < buffer_length){
936       ptr_im_mix_buffer = im_mix_buffer + (im_start_x + (guint) floor(new_phase));
937     }else{
938       if((im_start_x + (guint) floor(new_phase)) - (guint) floor(im_freq_period) < buffer_length &&
939 	 (im_start_x + (guint) floor(new_phase)) - (guint) floor(im_freq_period) > 0){
940 	ptr_im_mix_buffer = im_mix_buffer + (im_start_x + (guint) floor(new_phase)) - (guint) floor(im_freq_period);
941       }else{
942 	if(floor(new_phase) < buffer_length){
943 	  ptr_im_mix_buffer = im_mix_buffer + (guint) floor(new_phase);
944 	}else{
945 	  ptr_im_mix_buffer = im_mix_buffer + buffer_length - 1;
946 	}
947       }
948     }
949 
950     if(low_start_x + (guint) floor(new_phase) < buffer_length){
951       ptr_low_mix_buffer = low_mix_buffer + (low_start_x + (guint) floor(new_phase));
952     }else{
953       if((low_start_x + (guint) floor(new_phase)) - (guint) floor(low_freq_period) < buffer_length &&
954 	 (low_start_x + (guint) floor(new_phase)) - (guint) floor(low_freq_period) > 0){
955 	ptr_low_mix_buffer = low_mix_buffer + (low_start_x + (guint) floor(new_phase)) - (guint) floor(low_freq_period);
956       }else{
957 	if(floor(new_phase) < buffer_length){
958 	  ptr_low_mix_buffer = low_mix_buffer + (guint) floor(new_phase);
959 	}else{
960 	  ptr_low_mix_buffer = low_mix_buffer + buffer_length - 1;
961 	}
962       }
963     }
964 
965     ptr_new_mix_buffer = new_mix_buffer + i;
966 
967     /* write new mix buffer */
968     if(ptr_mix_buffer->real != 0.0){
969       new_z = volume * ((1.0 / 2.0) * (new_freq_period * (ags_complex_get(ptr_mix_buffer) / freq_period) * (ags_complex_get(ptr_im_mix_buffer) / im_freq_period) / (ags_complex_get(ptr_mix_buffer) / freq_period)) + (1.0 / 2.0) * (new_freq_period * (ags_complex_get(ptr_mix_buffer) / freq_period) * (ags_complex_get(ptr_low_mix_buffer) / low_freq_period) / (ags_complex_get(ptr_mix_buffer) / freq_period)));
970     }else{
971       new_z = 0.0 + I * 0.0;
972     }
973 
974     ags_complex_set(ptr_new_mix_buffer,
975 		    new_z);
976   }
977 
978   /* rewrite buffer */
979   for(i = 0; i < buffer_length; i++){
980     ptr_new_mix_buffer = new_mix_buffer + i;
981     ptr_buffer = buffer + i;
982 
983     AGS_AUDIO_BUFFER_UTIL_COMPLEX_TO_S24(ptr_new_mix_buffer, ptr_buffer);
984   }
985 
986   ags_stream_free(mix_buffer);
987 
988   ags_stream_free(im_mix_buffer);
989 
990   ags_stream_free(low_mix_buffer);
991 
992   ags_stream_free(new_mix_buffer);
993 }
994 
995 /**
996  * ags_filter_util_pitch_s32:
997  * @buffer: the audio buffer
998  * @buffer_length: the buffer's length
999  * @samplerate: the samplerate
1000  * @base_key: the base key
1001  * @tuning: the tuning
1002  *
1003  * Apply pitch filter.
1004  *
1005  * Since: 3.0.0
1006  */
1007 void
ags_filter_util_pitch_s32(gint32 * buffer,guint buffer_length,guint samplerate,gdouble base_key,gdouble tuning)1008 ags_filter_util_pitch_s32(gint32 *buffer,
1009 			  guint buffer_length,
1010 			  guint samplerate,
1011 			  gdouble base_key,
1012 			  gdouble tuning)
1013 {
1014   AgsComplex *ptr_mix_buffer, *ptr_im_mix_buffer, *ptr_low_mix_buffer, *ptr_new_mix_buffer;
1015   AgsComplex *mix_buffer, *im_mix_buffer, *low_mix_buffer, *new_mix_buffer;
1016   gint32 *ptr_buffer;
1017 
1018   gdouble volume;
1019   gdouble im_key, low_key;
1020   gdouble base_freq, im_freq, low_freq, new_freq;
1021   gdouble offset_factor, im_offset_factor, low_offset_factor, new_offset_factor;
1022   gdouble freq_period, im_freq_period, low_freq_period, new_freq_period;
1023   gdouble t;
1024   guint i;
1025 
1026   if(buffer == NULL){
1027     return;
1028   }
1029 
1030   /* frequency */
1031   base_freq = exp2((base_key) / 12.0) * 440.0;
1032 
1033   im_key = (gdouble) ((gint) floor(tuning / 100.0) % 12);
1034 
1035   if(im_key < 0.0){
1036     im_key += 12.0;
1037   }
1038 
1039   if(im_key == 0.0){
1040     im_key = 1.0;
1041   }
1042 
1043   im_freq = exp2((base_key + im_key) / 12.0) * 440.0;
1044 
1045   low_key = base_key - 12.0;
1046 
1047   low_freq = exp2((low_key) / 12.0) * 440.0;
1048 
1049   new_freq = exp2((base_key + (tuning / 100.0))  / 12.0) * 440.0;
1050 
1051   if(base_freq <= 0.0){
1052     g_warning("rejecting pitch base freq %f <= 0.0", base_freq);
1053 
1054     return;
1055   }
1056 
1057   if(im_freq <= 0.0){
1058     g_warning("rejecting pitch intermediate freq %f <= 0.0", im_freq);
1059 
1060     return;
1061   }
1062 
1063   if(new_freq <= 0.0){
1064     g_warning("rejecting pitch new freq %f <= 0.0", new_freq);
1065 
1066     return;
1067   }
1068 
1069   volume = 1.0 / base_freq * new_freq;
1070 
1071   /* get frequency period */
1072   freq_period = samplerate / base_freq;
1073 
1074   im_freq_period = samplerate / im_freq;
1075   low_freq_period = samplerate / low_freq;
1076   new_freq_period = samplerate / new_freq;
1077 
1078   /* get offset factor */
1079   offset_factor = 1.0;
1080 
1081   im_offset_factor = 1.0 / (samplerate / base_freq) * (samplerate / im_freq);
1082   low_offset_factor = 1.0 / (samplerate / base_freq) * (samplerate / low_freq);
1083   new_offset_factor = 1.0 / (samplerate / base_freq) * (samplerate / new_freq);
1084 
1085   /* allocate buffer */
1086   mix_buffer = (AgsComplex *) ags_stream_alloc(buffer_length,
1087 					       AGS_SOUNDCARD_COMPLEX);
1088 
1089   im_mix_buffer = (AgsComplex *) ags_stream_alloc(buffer_length,
1090 						  AGS_SOUNDCARD_COMPLEX);
1091 
1092   low_mix_buffer = (AgsComplex *) ags_stream_alloc(buffer_length,
1093 						   AGS_SOUNDCARD_COMPLEX);
1094 
1095   new_mix_buffer = (AgsComplex *) ags_stream_alloc(buffer_length,
1096 						   AGS_SOUNDCARD_COMPLEX);
1097 
1098   /* mix buffer */
1099   for(i = 0; i < buffer_length; i++){
1100     ptr_mix_buffer = mix_buffer + i;
1101 
1102     /* write mix buffer */
1103     AGS_AUDIO_BUFFER_UTIL_S32_TO_COMPLEX(buffer[i], &ptr_mix_buffer);
1104   }
1105 
1106   /* im mix buffer */
1107   for(i = 0; i < buffer_length; i++){
1108     double _Complex z, mix_z, im_z;
1109     gdouble phase, im_phase;
1110     guint start_x;
1111 
1112     if(floor(freq_period) != 0.0){
1113       start_x = freq_period * floor((double) i / freq_period);
1114     }else{
1115       start_x = 0;
1116     }
1117 
1118     im_phase = fmod(i, im_freq_period);
1119 
1120     phase = fmod(i, freq_period);
1121 
1122     if(start_x + (guint) floor(phase) < buffer_length){
1123       ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(phase));
1124     }else{
1125       if((start_x + (guint) floor(phase)) - (guint) floor(freq_period) < buffer_length &&
1126 	 (start_x + (guint) floor(phase)) - (guint) floor(freq_period) > 0){
1127 	ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(phase)) - (guint) floor(freq_period);
1128       }else{
1129 	if(floor(phase) < buffer_length){
1130 	  ptr_mix_buffer = mix_buffer + (guint) floor(phase);
1131 	}else{
1132 	  ptr_mix_buffer = mix_buffer + buffer_length - 1;
1133 	}
1134       }
1135     }
1136 
1137     ptr_im_mix_buffer = im_mix_buffer + i;
1138 
1139     /* write im mix buffer */
1140     z = ags_complex_get(mix_buffer + i);
1141     mix_z = ags_complex_get(ptr_mix_buffer);
1142 
1143     t = (im_freq_period / freq_period);
1144 
1145     im_z = (1.0 - t) * z + (t * mix_z);
1146 
1147     ags_complex_set(ptr_im_mix_buffer, im_z);
1148   }
1149 
1150   /* low mix buffer */
1151   for(i = 0; i < buffer_length; i++){
1152     double _Complex z, mix_z, low_z;
1153     gdouble phase, low_phase;
1154     guint start_x;
1155 
1156     if(floor(freq_period) != 0.0){
1157       start_x = freq_period * floor((double) i / freq_period);
1158     }else{
1159       start_x = 0;
1160     }
1161 
1162     low_phase = fmod(i, low_freq_period);
1163 
1164     phase = fmod(i, freq_period);
1165 
1166     if(start_x + (guint) floor(phase) < buffer_length){
1167       ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(phase));
1168     }else{
1169       if((start_x + (guint) floor(phase)) - (guint) floor(freq_period) < buffer_length &&
1170 	 (start_x + (guint) floor(phase)) - (guint) floor(freq_period) > 0){
1171 	ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(phase)) - (guint) floor(freq_period);
1172       }else{
1173 	if(floor(phase) < buffer_length){
1174 	  ptr_mix_buffer = mix_buffer + (guint) floor(phase);
1175 	}else{
1176 	  ptr_mix_buffer = mix_buffer + buffer_length - 1;
1177 	}
1178       }
1179     }
1180 
1181     ptr_low_mix_buffer = low_mix_buffer + i;
1182 
1183     /* write low mix buffer */
1184     z = ags_complex_get(mix_buffer + i);
1185     mix_z = ags_complex_get(ptr_mix_buffer);
1186 
1187     t = (low_freq_period / freq_period);
1188 
1189     low_z = (1.0 - t) * z + (t * mix_z);
1190 
1191     ags_complex_set(ptr_low_mix_buffer, low_z);
1192   }
1193 
1194   /* new mix buffer */
1195   for(i = 0; i < buffer_length; i++){
1196     double _Complex new_z;
1197     gdouble phase, im_phase, low_phase, new_phase;
1198     guint start_x, im_start_x, low_start_x;
1199 
1200     if(floor(freq_period) != 0.0){
1201       start_x = freq_period * floor((double) i / freq_period);
1202     }else{
1203       start_x = 0;
1204     }
1205 
1206     if(floor(im_freq_period) != 0.0){
1207       im_start_x = im_freq_period * floor((double) i / im_freq_period);
1208     }else{
1209       im_start_x = 0;
1210     }
1211 
1212     if(floor(low_freq_period) != 0.0){
1213       low_start_x = low_freq_period * floor((double) i / low_freq_period);
1214     }else{
1215       low_start_x = 0;
1216     }
1217 
1218     phase = fmod(i, freq_period);
1219 
1220     im_phase = fmod(i, im_freq_period);
1221 
1222     low_phase = fmod(i, low_freq_period);
1223 
1224     new_phase = fmod(i, new_freq_period);
1225 
1226     if(start_x + (guint) floor(new_phase) < buffer_length){
1227       ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(new_phase));
1228     }else{
1229       if((start_x + (guint) floor(new_phase)) - (guint) floor(freq_period) < buffer_length &&
1230 	 (start_x + (guint) floor(new_phase)) - (guint) floor(freq_period) > 0){
1231 	ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(new_phase)) - (guint) floor(freq_period);
1232       }else{
1233 	if(floor(new_phase) < buffer_length){
1234 	  ptr_mix_buffer = mix_buffer + (guint) floor(new_phase);
1235 	}else{
1236 	  ptr_mix_buffer = mix_buffer + buffer_length - 1;
1237 	}
1238       }
1239     }
1240 
1241     if(im_start_x + (guint) floor(new_phase) < buffer_length){
1242       ptr_im_mix_buffer = im_mix_buffer + (im_start_x + (guint) floor(new_phase));
1243     }else{
1244       if((im_start_x + (guint) floor(new_phase)) - (guint) floor(im_freq_period) < buffer_length &&
1245 	 (im_start_x + (guint) floor(new_phase)) - (guint) floor(im_freq_period) > 0){
1246 	ptr_im_mix_buffer = im_mix_buffer + (im_start_x + (guint) floor(new_phase)) - (guint) floor(im_freq_period);
1247       }else{
1248 	if(floor(new_phase) < buffer_length){
1249 	  ptr_im_mix_buffer = im_mix_buffer + (guint) floor(new_phase);
1250 	}else{
1251 	  ptr_im_mix_buffer = im_mix_buffer + buffer_length - 1;
1252 	}
1253       }
1254     }
1255 
1256     if(low_start_x + (guint) floor(new_phase) < buffer_length){
1257       ptr_low_mix_buffer = low_mix_buffer + (low_start_x + (guint) floor(new_phase));
1258     }else{
1259       if((low_start_x + (guint) floor(new_phase)) - (guint) floor(low_freq_period) < buffer_length &&
1260 	 (low_start_x + (guint) floor(new_phase)) - (guint) floor(low_freq_period) > 0){
1261 	ptr_low_mix_buffer = low_mix_buffer + (low_start_x + (guint) floor(new_phase)) - (guint) floor(low_freq_period);
1262       }else{
1263 	if(floor(new_phase) < buffer_length){
1264 	  ptr_low_mix_buffer = low_mix_buffer + (guint) floor(new_phase);
1265 	}else{
1266 	  ptr_low_mix_buffer = low_mix_buffer + buffer_length - 1;
1267 	}
1268       }
1269     }
1270 
1271     ptr_new_mix_buffer = new_mix_buffer + i;
1272 
1273     /* write new mix buffer */
1274     if(ptr_mix_buffer->real != 0.0){
1275       new_z = volume * ((1.0 / 2.0) * (new_freq_period * (ags_complex_get(ptr_mix_buffer) / freq_period) * (ags_complex_get(ptr_im_mix_buffer) / im_freq_period) / (ags_complex_get(ptr_mix_buffer) / freq_period)) + (1.0 / 2.0) * (new_freq_period * (ags_complex_get(ptr_mix_buffer) / freq_period) * (ags_complex_get(ptr_low_mix_buffer) / low_freq_period) / (ags_complex_get(ptr_mix_buffer) / freq_period)));
1276     }else{
1277       new_z = 0.0 + I * 0.0;
1278     }
1279 
1280     ags_complex_set(ptr_new_mix_buffer,
1281 		    new_z);
1282   }
1283 
1284   /* rewrite buffer */
1285   for(i = 0; i < buffer_length; i++){
1286     ptr_new_mix_buffer = new_mix_buffer + i;
1287     ptr_buffer = buffer + i;
1288 
1289     AGS_AUDIO_BUFFER_UTIL_COMPLEX_TO_S32(ptr_new_mix_buffer, ptr_buffer);
1290   }
1291 
1292   ags_stream_free(mix_buffer);
1293 
1294   ags_stream_free(im_mix_buffer);
1295 
1296   ags_stream_free(low_mix_buffer);
1297 
1298   ags_stream_free(new_mix_buffer);
1299 }
1300 
1301 /**
1302  * ags_filter_util_pitch_s64:
1303  * @buffer: the audio buffer
1304  * @buffer_length: the buffer's length
1305  * @samplerate: the samplerate
1306  * @base_key: the base key
1307  * @tuning: the tuning
1308  *
1309  * Apply pitch filter.
1310  *
1311  * Since: 3.0.0
1312  */
1313 void
ags_filter_util_pitch_s64(gint64 * buffer,guint buffer_length,guint samplerate,gdouble base_key,gdouble tuning)1314 ags_filter_util_pitch_s64(gint64 *buffer,
1315 			  guint buffer_length,
1316 			  guint samplerate,
1317 			  gdouble base_key,
1318 			  gdouble tuning)
1319 {
1320   AgsComplex *ptr_mix_buffer, *ptr_im_mix_buffer, *ptr_low_mix_buffer, *ptr_new_mix_buffer;
1321   AgsComplex *mix_buffer, *im_mix_buffer, *low_mix_buffer, *new_mix_buffer;
1322   gint64 *ptr_buffer;
1323 
1324   gdouble volume;
1325   gdouble im_key, low_key;
1326   gdouble base_freq, im_freq, low_freq, new_freq;
1327   gdouble offset_factor, im_offset_factor, low_offset_factor, new_offset_factor;
1328   gdouble freq_period, im_freq_period, low_freq_period, new_freq_period;
1329   gdouble t;
1330   guint i;
1331 
1332   if(buffer == NULL){
1333     return;
1334   }
1335 
1336   /* frequency */
1337   base_freq = exp2((base_key) / 12.0) * 440.0;
1338 
1339   im_key = (gdouble) ((gint) floor(tuning / 100.0) % 12);
1340 
1341   if(im_key < 0.0){
1342     im_key += 12.0;
1343   }
1344 
1345   if(im_key == 0.0){
1346     im_key = 1.0;
1347   }
1348 
1349   im_freq = exp2((base_key + im_key) / 12.0) * 440.0;
1350 
1351   low_key = base_key - 12.0;
1352 
1353   low_freq = exp2((low_key) / 12.0) * 440.0;
1354 
1355   new_freq = exp2((base_key + (tuning / 100.0))  / 12.0) * 440.0;
1356 
1357   if(base_freq <= 0.0){
1358     g_warning("rejecting pitch base freq %f <= 0.0", base_freq);
1359 
1360     return;
1361   }
1362 
1363   if(im_freq <= 0.0){
1364     g_warning("rejecting pitch intermediate freq %f <= 0.0", im_freq);
1365 
1366     return;
1367   }
1368 
1369   if(new_freq <= 0.0){
1370     g_warning("rejecting pitch new freq %f <= 0.0", new_freq);
1371 
1372     return;
1373   }
1374 
1375   volume = 1.0 / base_freq * new_freq;
1376 
1377   /* get frequency period */
1378   freq_period = samplerate / base_freq;
1379 
1380   im_freq_period = samplerate / im_freq;
1381   low_freq_period = samplerate / low_freq;
1382   new_freq_period = samplerate / new_freq;
1383 
1384   /* get offset factor */
1385   offset_factor = 1.0;
1386 
1387   im_offset_factor = 1.0 / (samplerate / base_freq) * (samplerate / im_freq);
1388   low_offset_factor = 1.0 / (samplerate / base_freq) * (samplerate / low_freq);
1389   new_offset_factor = 1.0 / (samplerate / base_freq) * (samplerate / new_freq);
1390 
1391   /* allocate buffer */
1392   mix_buffer = (AgsComplex *) ags_stream_alloc(buffer_length,
1393 					       AGS_SOUNDCARD_COMPLEX);
1394 
1395   im_mix_buffer = (AgsComplex *) ags_stream_alloc(buffer_length,
1396 						  AGS_SOUNDCARD_COMPLEX);
1397 
1398   low_mix_buffer = (AgsComplex *) ags_stream_alloc(buffer_length,
1399 						   AGS_SOUNDCARD_COMPLEX);
1400 
1401   new_mix_buffer = (AgsComplex *) ags_stream_alloc(buffer_length,
1402 						   AGS_SOUNDCARD_COMPLEX);
1403 
1404   /* mix buffer */
1405   for(i = 0; i < buffer_length; i++){
1406     ptr_mix_buffer = mix_buffer + i;
1407 
1408     /* write mix buffer */
1409     AGS_AUDIO_BUFFER_UTIL_S64_TO_COMPLEX(buffer[i], &ptr_mix_buffer);
1410   }
1411 
1412   /* im mix buffer */
1413   for(i = 0; i < buffer_length; i++){
1414     double _Complex z, mix_z, im_z;
1415     gdouble phase, im_phase;
1416     guint start_x;
1417 
1418     if(floor(freq_period) != 0.0){
1419       start_x = freq_period * floor((double) i / freq_period);
1420     }else{
1421       start_x = 0;
1422     }
1423 
1424     im_phase = fmod(i, im_freq_period);
1425 
1426     phase = fmod(i, freq_period);
1427 
1428     if(start_x + (guint) floor(phase) < buffer_length){
1429       ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(phase));
1430     }else{
1431       if((start_x + (guint) floor(phase)) - (guint) floor(freq_period) < buffer_length &&
1432 	 (start_x + (guint) floor(phase)) - (guint) floor(freq_period) > 0){
1433 	ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(phase)) - (guint) floor(freq_period);
1434       }else{
1435 	if(floor(phase) < buffer_length){
1436 	  ptr_mix_buffer = mix_buffer + (guint) floor(phase);
1437 	}else{
1438 	  ptr_mix_buffer = mix_buffer + buffer_length - 1;
1439 	}
1440       }
1441     }
1442 
1443     ptr_im_mix_buffer = im_mix_buffer + i;
1444 
1445     /* write im mix buffer */
1446     z = ags_complex_get(mix_buffer + i);
1447     mix_z = ags_complex_get(ptr_mix_buffer);
1448 
1449     t = (im_freq_period / freq_period);
1450 
1451     im_z = (1.0 - t) * z + (t * mix_z);
1452 
1453     ags_complex_set(ptr_im_mix_buffer, im_z);
1454   }
1455 
1456   /* low mix buffer */
1457   for(i = 0; i < buffer_length; i++){
1458     double _Complex z, mix_z, low_z;
1459     gdouble phase, low_phase;
1460     guint start_x;
1461 
1462     if(floor(freq_period) != 0.0){
1463       start_x = freq_period * floor((double) i / freq_period);
1464     }else{
1465       start_x = 0;
1466     }
1467 
1468     low_phase = fmod(i, low_freq_period);
1469 
1470     phase = fmod(i, freq_period);
1471 
1472     if(start_x + (guint) floor(phase) < buffer_length){
1473       ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(phase));
1474     }else{
1475       if((start_x + (guint) floor(phase)) - (guint) floor(freq_period) < buffer_length &&
1476 	 (start_x + (guint) floor(phase)) - (guint) floor(freq_period) > 0){
1477 	ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(phase)) - (guint) floor(freq_period);
1478       }else{
1479 	if(floor(phase) < buffer_length){
1480 	  ptr_mix_buffer = mix_buffer + (guint) floor(phase);
1481 	}else{
1482 	  ptr_mix_buffer = mix_buffer + buffer_length - 1;
1483 	}
1484       }
1485     }
1486 
1487     ptr_low_mix_buffer = low_mix_buffer + i;
1488 
1489     /* write low mix buffer */
1490     z = ags_complex_get(mix_buffer + i);
1491     mix_z = ags_complex_get(ptr_mix_buffer);
1492 
1493     t = (low_freq_period / freq_period);
1494 
1495     low_z = (1.0 - t) * z + (t * mix_z);
1496 
1497     ags_complex_set(ptr_low_mix_buffer, low_z);
1498   }
1499 
1500   /* new mix buffer */
1501   for(i = 0; i < buffer_length; i++){
1502     double _Complex new_z;
1503     gdouble phase, im_phase, low_phase, new_phase;
1504     guint start_x, im_start_x, low_start_x;
1505 
1506     if(floor(freq_period) != 0.0){
1507       start_x = freq_period * floor((double) i / freq_period);
1508     }else{
1509       start_x = 0;
1510     }
1511 
1512     if(floor(im_freq_period) != 0.0){
1513       im_start_x = im_freq_period * floor((double) i / im_freq_period);
1514     }else{
1515       im_start_x = 0;
1516     }
1517 
1518     if(floor(low_freq_period) != 0.0){
1519       low_start_x = low_freq_period * floor((double) i / low_freq_period);
1520     }else{
1521       low_start_x = 0;
1522     }
1523 
1524     phase = fmod(i, freq_period);
1525 
1526     im_phase = fmod(i, im_freq_period);
1527 
1528     low_phase = fmod(i, low_freq_period);
1529 
1530     new_phase = fmod(i, new_freq_period);
1531 
1532     if(start_x + (guint) floor(new_phase) < buffer_length){
1533       ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(new_phase));
1534     }else{
1535       if((start_x + (guint) floor(new_phase)) - (guint) floor(freq_period) < buffer_length &&
1536 	 (start_x + (guint) floor(new_phase)) - (guint) floor(freq_period) > 0){
1537 	ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(new_phase)) - (guint) floor(freq_period);
1538       }else{
1539 	if(floor(new_phase) < buffer_length){
1540 	  ptr_mix_buffer = mix_buffer + (guint) floor(new_phase);
1541 	}else{
1542 	  ptr_mix_buffer = mix_buffer + buffer_length - 1;
1543 	}
1544       }
1545     }
1546 
1547     if(im_start_x + (guint) floor(new_phase) < buffer_length){
1548       ptr_im_mix_buffer = im_mix_buffer + (im_start_x + (guint) floor(new_phase));
1549     }else{
1550       if((im_start_x + (guint) floor(new_phase)) - (guint) floor(im_freq_period) < buffer_length &&
1551 	 (im_start_x + (guint) floor(new_phase)) - (guint) floor(im_freq_period) > 0){
1552 	ptr_im_mix_buffer = im_mix_buffer + (im_start_x + (guint) floor(new_phase)) - (guint) floor(im_freq_period);
1553       }else{
1554 	if(floor(new_phase) < buffer_length){
1555 	  ptr_im_mix_buffer = im_mix_buffer + (guint) floor(new_phase);
1556 	}else{
1557 	  ptr_im_mix_buffer = im_mix_buffer + buffer_length - 1;
1558 	}
1559       }
1560     }
1561 
1562     if(low_start_x + (guint) floor(new_phase) < buffer_length){
1563       ptr_low_mix_buffer = low_mix_buffer + (low_start_x + (guint) floor(new_phase));
1564     }else{
1565       if((low_start_x + (guint) floor(new_phase)) - (guint) floor(low_freq_period) < buffer_length &&
1566 	 (low_start_x + (guint) floor(new_phase)) - (guint) floor(low_freq_period) > 0){
1567 	ptr_low_mix_buffer = low_mix_buffer + (low_start_x + (guint) floor(new_phase)) - (guint) floor(low_freq_period);
1568       }else{
1569 	if(floor(new_phase) < buffer_length){
1570 	  ptr_low_mix_buffer = low_mix_buffer + (guint) floor(new_phase);
1571 	}else{
1572 	  ptr_low_mix_buffer = low_mix_buffer + buffer_length - 1;
1573 	}
1574       }
1575     }
1576 
1577     ptr_new_mix_buffer = new_mix_buffer + i;
1578 
1579     /* write new mix buffer */
1580     if(ptr_mix_buffer->real != 0.0){
1581       new_z = volume * ((1.0 / 2.0) * (new_freq_period * (ags_complex_get(ptr_mix_buffer) / freq_period) * (ags_complex_get(ptr_im_mix_buffer) / im_freq_period) / (ags_complex_get(ptr_mix_buffer) / freq_period)) + (1.0 / 2.0) * (new_freq_period * (ags_complex_get(ptr_mix_buffer) / freq_period) * (ags_complex_get(ptr_low_mix_buffer) / low_freq_period) / (ags_complex_get(ptr_mix_buffer) / freq_period)));
1582     }else{
1583       new_z = 0.0 + I * 0.0;
1584     }
1585 
1586     ags_complex_set(ptr_new_mix_buffer,
1587 		    new_z);
1588   }
1589 
1590   /* rewrite buffer */
1591   for(i = 0; i < buffer_length; i++){
1592     ptr_new_mix_buffer = new_mix_buffer + i;
1593     ptr_buffer = buffer + i;
1594 
1595     AGS_AUDIO_BUFFER_UTIL_COMPLEX_TO_S64(ptr_new_mix_buffer, ptr_buffer);
1596   }
1597 
1598   ags_stream_free(mix_buffer);
1599 
1600   ags_stream_free(im_mix_buffer);
1601 
1602   ags_stream_free(low_mix_buffer);
1603 
1604   ags_stream_free(new_mix_buffer);
1605 }
1606 
1607 /**
1608  * ags_filter_util_pitch_float:
1609  * @buffer: the audio buffer
1610  * @buffer_length: the buffer's length
1611  * @samplerate: the samplerate
1612  * @base_key: the base key
1613  * @tuning: the tuning
1614  *
1615  * Apply pitch filter.
1616  *
1617  * Since: 3.0.0
1618  */
1619 void
ags_filter_util_pitch_float(gfloat * buffer,guint buffer_length,guint samplerate,gdouble base_key,gdouble tuning)1620 ags_filter_util_pitch_float(gfloat *buffer,
1621 			    guint buffer_length,
1622 			    guint samplerate,
1623 			    gdouble base_key,
1624 			    gdouble tuning)
1625 {
1626   AgsComplex *ptr_mix_buffer, *ptr_im_mix_buffer, *ptr_low_mix_buffer, *ptr_new_mix_buffer;
1627   AgsComplex *mix_buffer, *im_mix_buffer, *low_mix_buffer, *new_mix_buffer;
1628   gfloat *ptr_buffer;
1629 
1630   gdouble volume;
1631   gdouble im_key, low_key;
1632   gdouble base_freq, im_freq, low_freq, new_freq;
1633   gdouble offset_factor, im_offset_factor, low_offset_factor, new_offset_factor;
1634   gdouble freq_period, im_freq_period, low_freq_period, new_freq_period;
1635   gdouble t;
1636   guint i;
1637 
1638   if(buffer == NULL){
1639     return;
1640   }
1641 
1642   /* frequency */
1643   base_freq = exp2((base_key) / 12.0) * 440.0;
1644 
1645   im_key = (gdouble) ((gint) floor(tuning / 100.0) % 12);
1646 
1647   if(im_key < 0.0){
1648     im_key += 12.0;
1649   }
1650 
1651   if(im_key == 0.0){
1652     im_key = 1.0;
1653   }
1654 
1655   im_freq = exp2((base_key + im_key) / 12.0) * 440.0;
1656 
1657   low_key = base_key - 12.0;
1658 
1659   low_freq = exp2((low_key) / 12.0) * 440.0;
1660 
1661   new_freq = exp2((base_key + (tuning / 100.0))  / 12.0) * 440.0;
1662 
1663   if(base_freq <= 0.0){
1664     g_warning("rejecting pitch base freq %f <= 0.0", base_freq);
1665 
1666     return;
1667   }
1668 
1669   if(im_freq <= 0.0){
1670     g_warning("rejecting pitch intermediate freq %f <= 0.0", im_freq);
1671 
1672     return;
1673   }
1674 
1675   if(new_freq <= 0.0){
1676     g_warning("rejecting pitch new freq %f <= 0.0", new_freq);
1677 
1678     return;
1679   }
1680 
1681   volume = 1.0 / base_freq * new_freq;
1682 
1683   /* get frequency period */
1684   freq_period = samplerate / base_freq;
1685 
1686   im_freq_period = samplerate / im_freq;
1687   low_freq_period = samplerate / low_freq;
1688   new_freq_period = samplerate / new_freq;
1689 
1690   /* get offset factor */
1691   offset_factor = 1.0;
1692 
1693   im_offset_factor = 1.0 / (samplerate / base_freq) * (samplerate / im_freq);
1694   low_offset_factor = 1.0 / (samplerate / base_freq) * (samplerate / low_freq);
1695   new_offset_factor = 1.0 / (samplerate / base_freq) * (samplerate / new_freq);
1696 
1697   /* allocate buffer */
1698   mix_buffer = (AgsComplex *) ags_stream_alloc(buffer_length,
1699 					       AGS_SOUNDCARD_COMPLEX);
1700 
1701   im_mix_buffer = (AgsComplex *) ags_stream_alloc(buffer_length,
1702 						  AGS_SOUNDCARD_COMPLEX);
1703 
1704   low_mix_buffer = (AgsComplex *) ags_stream_alloc(buffer_length,
1705 						   AGS_SOUNDCARD_COMPLEX);
1706 
1707   new_mix_buffer = (AgsComplex *) ags_stream_alloc(buffer_length,
1708 						   AGS_SOUNDCARD_COMPLEX);
1709 
1710   /* mix buffer */
1711   for(i = 0; i < buffer_length; i++){
1712     ptr_mix_buffer = mix_buffer + i;
1713 
1714     /* write mix buffer */
1715     AGS_AUDIO_BUFFER_UTIL_FLOAT_TO_COMPLEX(buffer[i], &ptr_mix_buffer);
1716   }
1717 
1718   /* im mix buffer */
1719   for(i = 0; i < buffer_length; i++){
1720     double _Complex z, mix_z, im_z;
1721     gdouble phase, im_phase;
1722     guint start_x;
1723 
1724     if(floor(freq_period) != 0.0){
1725       start_x = freq_period * floor((double) i / freq_period);
1726     }else{
1727       start_x = 0;
1728     }
1729 
1730     im_phase = fmod(i, im_freq_period);
1731 
1732     phase = fmod(i, freq_period);
1733 
1734     if(start_x + (guint) floor(phase) < buffer_length){
1735       ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(phase));
1736     }else{
1737       if((start_x + (guint) floor(phase)) - (guint) floor(freq_period) < buffer_length &&
1738 	 (start_x + (guint) floor(phase)) - (guint) floor(freq_period) > 0){
1739 	ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(phase)) - (guint) floor(freq_period);
1740       }else{
1741 	if(floor(phase) < buffer_length){
1742 	  ptr_mix_buffer = mix_buffer + (guint) floor(phase);
1743 	}else{
1744 	  ptr_mix_buffer = mix_buffer + buffer_length - 1;
1745 	}
1746       }
1747     }
1748 
1749     ptr_im_mix_buffer = im_mix_buffer + i;
1750 
1751     /* write im mix buffer */
1752     z = ags_complex_get(mix_buffer + i);
1753     mix_z = ags_complex_get(ptr_mix_buffer);
1754 
1755     t = (im_freq_period / freq_period);
1756 
1757     im_z = (1.0 - t) * z + (t * mix_z);
1758 
1759     ags_complex_set(ptr_im_mix_buffer, im_z);
1760   }
1761 
1762   /* low mix buffer */
1763   for(i = 0; i < buffer_length; i++){
1764     double _Complex z, mix_z, low_z;
1765     gdouble phase, low_phase;
1766     guint start_x;
1767 
1768     if(floor(freq_period) != 0.0){
1769       start_x = freq_period * floor((double) i / freq_period);
1770     }else{
1771       start_x = 0;
1772     }
1773 
1774     low_phase = fmod(i, low_freq_period);
1775 
1776     phase = fmod(i, freq_period);
1777 
1778     if(start_x + (guint) floor(phase) < buffer_length){
1779       ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(phase));
1780     }else{
1781       if((start_x + (guint) floor(phase)) - (guint) floor(freq_period) < buffer_length &&
1782 	 (start_x + (guint) floor(phase)) - (guint) floor(freq_period) > 0){
1783 	ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(phase)) - (guint) floor(freq_period);
1784       }else{
1785 	if(floor(phase) < buffer_length){
1786 	  ptr_mix_buffer = mix_buffer + (guint) floor(phase);
1787 	}else{
1788 	  ptr_mix_buffer = mix_buffer + buffer_length - 1;
1789 	}
1790       }
1791     }
1792 
1793     ptr_low_mix_buffer = low_mix_buffer + i;
1794 
1795     /* write low mix buffer */
1796     z = ags_complex_get(mix_buffer + i);
1797     mix_z = ags_complex_get(ptr_mix_buffer);
1798 
1799     t = (low_freq_period / freq_period);
1800 
1801     low_z = (1.0 - t) * z + (t * mix_z);
1802 
1803     ags_complex_set(ptr_low_mix_buffer, low_z);
1804   }
1805 
1806   /* new mix buffer */
1807   for(i = 0; i < buffer_length; i++){
1808     double _Complex new_z;
1809     gdouble phase, im_phase, low_phase, new_phase;
1810     guint start_x, im_start_x, low_start_x;
1811 
1812     if(floor(freq_period) != 0.0){
1813       start_x = freq_period * floor((double) i / freq_period);
1814     }else{
1815       start_x = 0;
1816     }
1817 
1818     if(floor(im_freq_period) != 0.0){
1819       im_start_x = im_freq_period * floor((double) i / im_freq_period);
1820     }else{
1821       im_start_x = 0;
1822     }
1823 
1824     if(floor(low_freq_period) != 0.0){
1825       low_start_x = low_freq_period * floor((double) i / low_freq_period);
1826     }else{
1827       low_start_x = 0;
1828     }
1829 
1830     phase = fmod(i, freq_period);
1831 
1832     im_phase = fmod(i, im_freq_period);
1833 
1834     low_phase = fmod(i, low_freq_period);
1835 
1836     new_phase = fmod(i, new_freq_period);
1837 
1838     if(start_x + (guint) floor(new_phase) < buffer_length){
1839       ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(new_phase));
1840     }else{
1841       if((start_x + (guint) floor(new_phase)) - (guint) floor(freq_period) < buffer_length &&
1842 	 (start_x + (guint) floor(new_phase)) - (guint) floor(freq_period) > 0){
1843 	ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(new_phase)) - (guint) floor(freq_period);
1844       }else{
1845 	if(floor(new_phase) < buffer_length){
1846 	  ptr_mix_buffer = mix_buffer + (guint) floor(new_phase);
1847 	}else{
1848 	  ptr_mix_buffer = mix_buffer + buffer_length - 1;
1849 	}
1850       }
1851     }
1852 
1853     if(im_start_x + (guint) floor(new_phase) < buffer_length){
1854       ptr_im_mix_buffer = im_mix_buffer + (im_start_x + (guint) floor(new_phase));
1855     }else{
1856       if((im_start_x + (guint) floor(new_phase)) - (guint) floor(im_freq_period) < buffer_length &&
1857 	 (im_start_x + (guint) floor(new_phase)) - (guint) floor(im_freq_period) > 0){
1858 	ptr_im_mix_buffer = im_mix_buffer + (im_start_x + (guint) floor(new_phase)) - (guint) floor(im_freq_period);
1859       }else{
1860 	if(floor(new_phase) < buffer_length){
1861 	  ptr_im_mix_buffer = im_mix_buffer + (guint) floor(new_phase);
1862 	}else{
1863 	  ptr_im_mix_buffer = im_mix_buffer + buffer_length - 1;
1864 	}
1865       }
1866     }
1867 
1868     if(low_start_x + (guint) floor(new_phase) < buffer_length){
1869       ptr_low_mix_buffer = low_mix_buffer + (low_start_x + (guint) floor(new_phase));
1870     }else{
1871       if((low_start_x + (guint) floor(new_phase)) - (guint) floor(low_freq_period) < buffer_length &&
1872 	 (low_start_x + (guint) floor(new_phase)) - (guint) floor(low_freq_period) > 0){
1873 	ptr_low_mix_buffer = low_mix_buffer + (low_start_x + (guint) floor(new_phase)) - (guint) floor(low_freq_period);
1874       }else{
1875 	if(floor(new_phase) < buffer_length){
1876 	  ptr_low_mix_buffer = low_mix_buffer + (guint) floor(new_phase);
1877 	}else{
1878 	  ptr_low_mix_buffer = low_mix_buffer + buffer_length - 1;
1879 	}
1880       }
1881     }
1882 
1883     ptr_new_mix_buffer = new_mix_buffer + i;
1884 
1885     /* write new mix buffer */
1886     if(ptr_mix_buffer->real != 0.0){
1887       new_z = volume * ((1.0 / 2.0) * (new_freq_period * (ags_complex_get(ptr_mix_buffer) / freq_period) * (ags_complex_get(ptr_im_mix_buffer) / im_freq_period) / (ags_complex_get(ptr_mix_buffer) / freq_period)) + (1.0 / 2.0) * (new_freq_period * (ags_complex_get(ptr_mix_buffer) / freq_period) * (ags_complex_get(ptr_low_mix_buffer) / low_freq_period) / (ags_complex_get(ptr_mix_buffer) / freq_period)));
1888     }else{
1889       new_z = 0.0 + I * 0.0;
1890     }
1891 
1892     ags_complex_set(ptr_new_mix_buffer,
1893 		    new_z);
1894   }
1895 
1896   /* rewrite buffer */
1897   for(i = 0; i < buffer_length; i++){
1898     ptr_new_mix_buffer = new_mix_buffer + i;
1899     ptr_buffer = buffer + i;
1900 
1901     AGS_AUDIO_BUFFER_UTIL_COMPLEX_TO_FLOAT(ptr_new_mix_buffer, ptr_buffer);
1902   }
1903 
1904   ags_stream_free(mix_buffer);
1905 
1906   ags_stream_free(im_mix_buffer);
1907 
1908   ags_stream_free(low_mix_buffer);
1909 
1910   ags_stream_free(new_mix_buffer);
1911 }
1912 
1913 /**
1914  * ags_filter_util_pitch_double:
1915  * @buffer: the audio buffer
1916  * @buffer_length: the buffer's length
1917  * @samplerate: the samplerate
1918  * @base_key: the base key
1919  * @tuning: the tuning
1920  *
1921  * Apply pitch filter.
1922  *
1923  * Since: 3.0.0
1924  */
1925 void
ags_filter_util_pitch_double(gdouble * buffer,guint buffer_length,guint samplerate,gdouble base_key,gdouble tuning)1926 ags_filter_util_pitch_double(gdouble *buffer,
1927 			     guint buffer_length,
1928 			     guint samplerate,
1929 			     gdouble base_key,
1930 			     gdouble tuning)
1931 {
1932   AgsComplex *ptr_mix_buffer, *ptr_im_mix_buffer, *ptr_low_mix_buffer, *ptr_new_mix_buffer;
1933   AgsComplex *mix_buffer, *im_mix_buffer, *low_mix_buffer, *new_mix_buffer;
1934   gdouble *ptr_buffer;
1935 
1936   gdouble volume;
1937   gdouble im_key, low_key;
1938   gdouble base_freq, im_freq, low_freq, new_freq;
1939   gdouble offset_factor, im_offset_factor, low_offset_factor, new_offset_factor;
1940   gdouble freq_period, im_freq_period, low_freq_period, new_freq_period;
1941   gdouble t;
1942   guint i;
1943 
1944   if(buffer == NULL){
1945     return;
1946   }
1947 
1948   /* frequency */
1949   base_freq = exp2((base_key) / 12.0) * 440.0;
1950 
1951   im_key = (gdouble) ((gint) floor(tuning / 100.0) % 12);
1952 
1953   if(im_key < 0.0){
1954     im_key += 12.0;
1955   }
1956 
1957   if(im_key == 0.0){
1958     im_key = 1.0;
1959   }
1960 
1961   im_freq = exp2((base_key + im_key) / 12.0) * 440.0;
1962 
1963   low_key = base_key - 12.0;
1964 
1965   low_freq = exp2((low_key) / 12.0) * 440.0;
1966 
1967   new_freq = exp2((base_key + (tuning / 100.0))  / 12.0) * 440.0;
1968 
1969   if(base_freq <= 0.0){
1970     g_warning("rejecting pitch base freq %f <= 0.0", base_freq);
1971 
1972     return;
1973   }
1974 
1975   if(im_freq <= 0.0){
1976     g_warning("rejecting pitch intermediate freq %f <= 0.0", im_freq);
1977 
1978     return;
1979   }
1980 
1981   if(new_freq <= 0.0){
1982     g_warning("rejecting pitch new freq %f <= 0.0", new_freq);
1983 
1984     return;
1985   }
1986 
1987   volume = 1.0 / base_freq * new_freq;
1988 
1989   /* get frequency period */
1990   freq_period = samplerate / base_freq;
1991 
1992   im_freq_period = samplerate / im_freq;
1993   low_freq_period = samplerate / low_freq;
1994   new_freq_period = samplerate / new_freq;
1995 
1996   /* get offset factor */
1997   offset_factor = 1.0;
1998 
1999   im_offset_factor = 1.0 / (samplerate / base_freq) * (samplerate / im_freq);
2000   low_offset_factor = 1.0 / (samplerate / base_freq) * (samplerate / low_freq);
2001   new_offset_factor = 1.0 / (samplerate / base_freq) * (samplerate / new_freq);
2002 
2003   /* allocate buffer */
2004   mix_buffer = (AgsComplex *) ags_stream_alloc(buffer_length,
2005 					       AGS_SOUNDCARD_COMPLEX);
2006 
2007   im_mix_buffer = (AgsComplex *) ags_stream_alloc(buffer_length,
2008 						  AGS_SOUNDCARD_COMPLEX);
2009 
2010   low_mix_buffer = (AgsComplex *) ags_stream_alloc(buffer_length,
2011 						   AGS_SOUNDCARD_COMPLEX);
2012 
2013   new_mix_buffer = (AgsComplex *) ags_stream_alloc(buffer_length,
2014 						   AGS_SOUNDCARD_COMPLEX);
2015 
2016   /* mix buffer */
2017   for(i = 0; i < buffer_length; i++){
2018     ptr_mix_buffer = mix_buffer + i;
2019 
2020     /* write mix buffer */
2021     AGS_AUDIO_BUFFER_UTIL_DOUBLE_TO_COMPLEX(buffer[i], &ptr_mix_buffer);
2022   }
2023 
2024   /* im mix buffer */
2025   for(i = 0; i < buffer_length; i++){
2026     double _Complex z, mix_z, im_z;
2027     gdouble phase, im_phase;
2028     guint start_x;
2029 
2030     if(floor(freq_period) != 0.0){
2031       start_x = freq_period * floor((double) i / freq_period);
2032     }else{
2033       start_x = 0;
2034     }
2035 
2036     im_phase = fmod(i, im_freq_period);
2037 
2038     phase = fmod(i, freq_period);
2039 
2040     if(start_x + (guint) floor(phase) < buffer_length){
2041       ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(phase));
2042     }else{
2043       if((start_x + (guint) floor(phase)) - (guint) floor(freq_period) < buffer_length &&
2044 	 (start_x + (guint) floor(phase)) - (guint) floor(freq_period) > 0){
2045 	ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(phase)) - (guint) floor(freq_period);
2046       }else{
2047 	if(floor(phase) < buffer_length){
2048 	  ptr_mix_buffer = mix_buffer + (guint) floor(phase);
2049 	}else{
2050 	  ptr_mix_buffer = mix_buffer + buffer_length - 1;
2051 	}
2052       }
2053     }
2054 
2055     ptr_im_mix_buffer = im_mix_buffer + i;
2056 
2057     /* write im mix buffer */
2058     z = ags_complex_get(mix_buffer + i);
2059     mix_z = ags_complex_get(ptr_mix_buffer);
2060 
2061     t = (im_freq_period / freq_period);
2062 
2063     im_z = (1.0 - t) * z + (t * mix_z);
2064 
2065     ags_complex_set(ptr_im_mix_buffer, im_z);
2066   }
2067 
2068   /* low mix buffer */
2069   for(i = 0; i < buffer_length; i++){
2070     double _Complex z, mix_z, low_z;
2071     gdouble phase, low_phase;
2072     guint start_x;
2073 
2074     if(floor(freq_period) != 0.0){
2075       start_x = freq_period * floor((double) i / freq_period);
2076     }else{
2077       start_x = 0;
2078     }
2079 
2080     low_phase = fmod(i, low_freq_period);
2081 
2082     phase = fmod(i, freq_period);
2083 
2084     if(start_x + (guint) floor(phase) < buffer_length){
2085       ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(phase));
2086     }else{
2087       if((start_x + (guint) floor(phase)) - (guint) floor(freq_period) < buffer_length &&
2088 	 (start_x + (guint) floor(phase)) - (guint) floor(freq_period) > 0){
2089 	ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(phase)) - (guint) floor(freq_period);
2090       }else{
2091 	if(floor(phase) < buffer_length){
2092 	  ptr_mix_buffer = mix_buffer + (guint) floor(phase);
2093 	}else{
2094 	  ptr_mix_buffer = mix_buffer + buffer_length - 1;
2095 	}
2096       }
2097     }
2098 
2099     ptr_low_mix_buffer = low_mix_buffer + i;
2100 
2101     /* write low mix buffer */
2102     z = ags_complex_get(mix_buffer + i);
2103     mix_z = ags_complex_get(ptr_mix_buffer);
2104 
2105     t = (low_freq_period / freq_period);
2106 
2107     low_z = (1.0 - t) * z + (t * mix_z);
2108 
2109     ags_complex_set(ptr_low_mix_buffer, low_z);
2110   }
2111 
2112   /* new mix buffer */
2113   for(i = 0; i < buffer_length; i++){
2114     double _Complex new_z;
2115     gdouble phase, im_phase, low_phase, new_phase;
2116     guint start_x, im_start_x, low_start_x;
2117 
2118     if(floor(freq_period) != 0.0){
2119       start_x = freq_period * floor((double) i / freq_period);
2120     }else{
2121       start_x = 0;
2122     }
2123 
2124     if(floor(im_freq_period) != 0.0){
2125       im_start_x = im_freq_period * floor((double) i / im_freq_period);
2126     }else{
2127       im_start_x = 0;
2128     }
2129 
2130     if(floor(low_freq_period) != 0.0){
2131       low_start_x = low_freq_period * floor((double) i / low_freq_period);
2132     }else{
2133       low_start_x = 0;
2134     }
2135 
2136     phase = fmod(i, freq_period);
2137 
2138     im_phase = fmod(i, im_freq_period);
2139 
2140     low_phase = fmod(i, low_freq_period);
2141 
2142     new_phase = fmod(i, new_freq_period);
2143 
2144     if(start_x + (guint) floor(new_phase) < buffer_length){
2145       ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(new_phase));
2146     }else{
2147       if((start_x + (guint) floor(new_phase)) - (guint) floor(freq_period) < buffer_length &&
2148 	 (start_x + (guint) floor(new_phase)) - (guint) floor(freq_period) > 0){
2149 	ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(new_phase)) - (guint) floor(freq_period);
2150       }else{
2151 	if(floor(new_phase) < buffer_length){
2152 	  ptr_mix_buffer = mix_buffer + (guint) floor(new_phase);
2153 	}else{
2154 	  ptr_mix_buffer = mix_buffer + buffer_length - 1;
2155 	}
2156       }
2157     }
2158 
2159     if(im_start_x + (guint) floor(new_phase) < buffer_length){
2160       ptr_im_mix_buffer = im_mix_buffer + (im_start_x + (guint) floor(new_phase));
2161     }else{
2162       if((im_start_x + (guint) floor(new_phase)) - (guint) floor(im_freq_period) < buffer_length &&
2163 	 (im_start_x + (guint) floor(new_phase)) - (guint) floor(im_freq_period) > 0){
2164 	ptr_im_mix_buffer = im_mix_buffer + (im_start_x + (guint) floor(new_phase)) - (guint) floor(im_freq_period);
2165       }else{
2166 	if(floor(new_phase) < buffer_length){
2167 	  ptr_im_mix_buffer = im_mix_buffer + (guint) floor(new_phase);
2168 	}else{
2169 	  ptr_im_mix_buffer = im_mix_buffer + buffer_length - 1;
2170 	}
2171       }
2172     }
2173 
2174     if(low_start_x + (guint) floor(new_phase) < buffer_length){
2175       ptr_low_mix_buffer = low_mix_buffer + (low_start_x + (guint) floor(new_phase));
2176     }else{
2177       if((low_start_x + (guint) floor(new_phase)) - (guint) floor(low_freq_period) < buffer_length &&
2178 	 (low_start_x + (guint) floor(new_phase)) - (guint) floor(low_freq_period) > 0){
2179 	ptr_low_mix_buffer = low_mix_buffer + (low_start_x + (guint) floor(new_phase)) - (guint) floor(low_freq_period);
2180       }else{
2181 	if(floor(new_phase) < buffer_length){
2182 	  ptr_low_mix_buffer = low_mix_buffer + (guint) floor(new_phase);
2183 	}else{
2184 	  ptr_low_mix_buffer = low_mix_buffer + buffer_length - 1;
2185 	}
2186       }
2187     }
2188 
2189     ptr_new_mix_buffer = new_mix_buffer + i;
2190 
2191     /* write new mix buffer */
2192     if(ptr_mix_buffer->real != 0.0){
2193       new_z = volume * ((1.0 / 2.0) * (new_freq_period * (ags_complex_get(ptr_mix_buffer) / freq_period) * (ags_complex_get(ptr_im_mix_buffer) / im_freq_period) / (ags_complex_get(ptr_mix_buffer) / freq_period)) + (1.0 / 2.0) * (new_freq_period * (ags_complex_get(ptr_mix_buffer) / freq_period) * (ags_complex_get(ptr_low_mix_buffer) / low_freq_period) / (ags_complex_get(ptr_mix_buffer) / freq_period)));
2194     }else{
2195       new_z = 0.0 + I * 0.0;
2196     }
2197 
2198     ags_complex_set(ptr_new_mix_buffer,
2199 		    new_z);
2200   }
2201 
2202   /* rewrite buffer */
2203   for(i = 0; i < buffer_length; i++){
2204     ptr_new_mix_buffer = new_mix_buffer + i;
2205     ptr_buffer = buffer + i;
2206 
2207     AGS_AUDIO_BUFFER_UTIL_COMPLEX_TO_DOUBLE(ptr_new_mix_buffer, ptr_buffer);
2208   }
2209 
2210   ags_stream_free(mix_buffer);
2211 
2212   ags_stream_free(im_mix_buffer);
2213 
2214   ags_stream_free(low_mix_buffer);
2215 
2216   ags_stream_free(new_mix_buffer);
2217 }
2218 
2219 /**
2220  * ags_filter_util_pitch_complex:
2221  * @buffer: the audio buffer
2222  * @buffer_length: the buffer's length
2223  * @samplerate: the samplerate
2224  * @base_key: the base key
2225  * @tuning: the tuning
2226  *
2227  * Apply pitch filter.
2228  *
2229  * Since: 3.0.0
2230  */
2231 void
ags_filter_util_pitch_complex(AgsComplex * buffer,guint buffer_length,guint samplerate,gdouble base_key,gdouble tuning)2232 ags_filter_util_pitch_complex(AgsComplex *buffer,
2233 			      guint buffer_length,
2234 			      guint samplerate,
2235 			      gdouble base_key,
2236 			      gdouble tuning)
2237 {
2238   AgsComplex *ptr_mix_buffer, *ptr_im_mix_buffer, *ptr_low_mix_buffer, *ptr_new_mix_buffer;
2239   AgsComplex *mix_buffer, *im_mix_buffer, *low_mix_buffer, *new_mix_buffer;
2240   AgsComplex *ptr_buffer;
2241 
2242   gdouble volume;
2243   gdouble im_key, low_key;
2244   gdouble base_freq, im_freq, low_freq, new_freq;
2245   gdouble offset_factor, im_offset_factor, low_offset_factor, new_offset_factor;
2246   gdouble freq_period, im_freq_period, low_freq_period, new_freq_period;
2247   gdouble t;
2248   guint i;
2249 
2250   if(buffer == NULL){
2251     return;
2252   }
2253 
2254   /* frequency */
2255   base_freq = exp2((base_key) / 12.0) * 440.0;
2256 
2257   im_key = (gdouble) ((gint) floor(tuning / 100.0) % 12);
2258 
2259   if(im_key < 0.0){
2260     im_key += 12.0;
2261   }
2262 
2263   if(im_key == 0.0){
2264     im_key = 1.0;
2265   }
2266 
2267   im_freq = exp2((base_key + im_key) / 12.0) * 440.0;
2268 
2269   low_key = base_key - 12.0;
2270 
2271   low_freq = exp2((low_key) / 12.0) * 440.0;
2272 
2273   new_freq = exp2((base_key + (tuning / 100.0))  / 12.0) * 440.0;
2274 
2275   if(base_freq <= 0.0){
2276     g_warning("rejecting pitch base freq %f <= 0.0", base_freq);
2277 
2278     return;
2279   }
2280 
2281   if(im_freq <= 0.0){
2282     g_warning("rejecting pitch intermediate freq %f <= 0.0", im_freq);
2283 
2284     return;
2285   }
2286 
2287   if(new_freq <= 0.0){
2288     g_warning("rejecting pitch new freq %f <= 0.0", new_freq);
2289 
2290     return;
2291   }
2292 
2293   volume = 1.0 / base_freq * new_freq;
2294 
2295   /* get frequency period */
2296   freq_period = samplerate / base_freq;
2297 
2298   im_freq_period = samplerate / im_freq;
2299   low_freq_period = samplerate / low_freq;
2300   new_freq_period = samplerate / new_freq;
2301 
2302   /* get offset factor */
2303   offset_factor = 1.0;
2304 
2305   im_offset_factor = 1.0 / (samplerate / base_freq) * (samplerate / im_freq);
2306   low_offset_factor = 1.0 / (samplerate / base_freq) * (samplerate / low_freq);
2307   new_offset_factor = 1.0 / (samplerate / base_freq) * (samplerate / new_freq);
2308 
2309   /* allocate buffer */
2310   mix_buffer = (AgsComplex *) ags_stream_alloc(buffer_length,
2311 					       AGS_SOUNDCARD_COMPLEX);
2312 
2313   im_mix_buffer = (AgsComplex *) ags_stream_alloc(buffer_length,
2314 						  AGS_SOUNDCARD_COMPLEX);
2315 
2316   low_mix_buffer = (AgsComplex *) ags_stream_alloc(buffer_length,
2317 						   AGS_SOUNDCARD_COMPLEX);
2318 
2319   new_mix_buffer = (AgsComplex *) ags_stream_alloc(buffer_length,
2320 						   AGS_SOUNDCARD_COMPLEX);
2321 
2322   /* mix buffer */
2323   for(i = 0; i < buffer_length; i++){
2324     ptr_mix_buffer = mix_buffer + i;
2325 
2326     /* write mix buffer */
2327     ags_complex_set(ptr_mix_buffer, ags_complex_get(buffer + i));
2328   }
2329 
2330   /* im mix buffer */
2331   for(i = 0; i < buffer_length; i++){
2332     double _Complex z, mix_z, im_z;
2333     gdouble phase, im_phase;
2334     guint start_x;
2335 
2336     if(floor(freq_period) != 0.0){
2337       start_x = freq_period * floor((double) i / freq_period);
2338     }else{
2339       start_x = 0;
2340     }
2341 
2342     im_phase = fmod(i, im_freq_period);
2343 
2344     phase = fmod(i, freq_period);
2345 
2346     if(start_x + (guint) floor(phase) < buffer_length){
2347       ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(phase));
2348     }else{
2349       if((start_x + (guint) floor(phase)) - (guint) floor(freq_period) < buffer_length &&
2350 	 (start_x + (guint) floor(phase)) - (guint) floor(freq_period) > 0){
2351 	ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(phase)) - (guint) floor(freq_period);
2352       }else{
2353 	if(floor(phase) < buffer_length){
2354 	  ptr_mix_buffer = mix_buffer + (guint) floor(phase);
2355 	}else{
2356 	  ptr_mix_buffer = mix_buffer + buffer_length - 1;
2357 	}
2358       }
2359     }
2360 
2361     ptr_im_mix_buffer = im_mix_buffer + i;
2362 
2363     /* write im mix buffer */
2364     z = ags_complex_get(mix_buffer + i);
2365     mix_z = ags_complex_get(ptr_mix_buffer);
2366 
2367     t = (im_freq_period / freq_period);
2368 
2369     im_z = (1.0 - t) * z + (t * mix_z);
2370 
2371     ags_complex_set(ptr_im_mix_buffer, im_z);
2372   }
2373 
2374   /* low mix buffer */
2375   for(i = 0; i < buffer_length; i++){
2376     double _Complex z, mix_z, low_z;
2377     gdouble phase, low_phase;
2378     guint start_x;
2379 
2380     if(floor(freq_period) != 0.0){
2381       start_x = freq_period * floor((double) i / freq_period);
2382     }else{
2383       start_x = 0;
2384     }
2385 
2386     low_phase = fmod(i, low_freq_period);
2387 
2388     phase = fmod(i, freq_period);
2389 
2390     if(start_x + (guint) floor(phase) < buffer_length){
2391       ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(phase));
2392     }else{
2393       if((start_x + (guint) floor(phase)) - (guint) floor(freq_period) < buffer_length &&
2394 	 (start_x + (guint) floor(phase)) - (guint) floor(freq_period) > 0){
2395 	ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(phase)) - (guint) floor(freq_period);
2396       }else{
2397 	if(floor(phase) < buffer_length){
2398 	  ptr_mix_buffer = mix_buffer + (guint) floor(phase);
2399 	}else{
2400 	  ptr_mix_buffer = mix_buffer + buffer_length - 1;
2401 	}
2402       }
2403     }
2404 
2405     ptr_low_mix_buffer = low_mix_buffer + i;
2406 
2407     /* write low mix buffer */
2408     z = ags_complex_get(mix_buffer + i);
2409     mix_z = ags_complex_get(ptr_mix_buffer);
2410 
2411     t = (low_freq_period / freq_period);
2412 
2413     low_z = (1.0 - t) * z + (t * mix_z);
2414 
2415     ags_complex_set(ptr_low_mix_buffer, low_z);
2416   }
2417 
2418   /* new mix buffer */
2419   for(i = 0; i < buffer_length; i++){
2420     double _Complex new_z;
2421     gdouble phase, im_phase, low_phase, new_phase;
2422     guint start_x, im_start_x, low_start_x;
2423 
2424     if(floor(freq_period) != 0.0){
2425       start_x = freq_period * floor((double) i / freq_period);
2426     }else{
2427       start_x = 0;
2428     }
2429 
2430     if(floor(im_freq_period) != 0.0){
2431       im_start_x = im_freq_period * floor((double) i / im_freq_period);
2432     }else{
2433       im_start_x = 0;
2434     }
2435 
2436     if(floor(low_freq_period) != 0.0){
2437       low_start_x = low_freq_period * floor((double) i / low_freq_period);
2438     }else{
2439       low_start_x = 0;
2440     }
2441 
2442     phase = fmod(i, freq_period);
2443 
2444     im_phase = fmod(i, im_freq_period);
2445 
2446     low_phase = fmod(i, low_freq_period);
2447 
2448     new_phase = fmod(i, new_freq_period);
2449 
2450     if(start_x + (guint) floor(new_phase) < buffer_length){
2451       ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(new_phase));
2452     }else{
2453       if((start_x + (guint) floor(new_phase)) - (guint) floor(freq_period) < buffer_length &&
2454 	 (start_x + (guint) floor(new_phase)) - (guint) floor(freq_period) > 0){
2455 	ptr_mix_buffer = mix_buffer + (start_x + (guint) floor(new_phase)) - (guint) floor(freq_period);
2456       }else{
2457 	if(floor(new_phase) < buffer_length){
2458 	  ptr_mix_buffer = mix_buffer + (guint) floor(new_phase);
2459 	}else{
2460 	  ptr_mix_buffer = mix_buffer + buffer_length - 1;
2461 	}
2462       }
2463     }
2464 
2465     if(im_start_x + (guint) floor(new_phase) < buffer_length){
2466       ptr_im_mix_buffer = im_mix_buffer + (im_start_x + (guint) floor(new_phase));
2467     }else{
2468       if((im_start_x + (guint) floor(new_phase)) - (guint) floor(im_freq_period) < buffer_length &&
2469 	 (im_start_x + (guint) floor(new_phase)) - (guint) floor(im_freq_period) > 0){
2470 	ptr_im_mix_buffer = im_mix_buffer + (im_start_x + (guint) floor(new_phase)) - (guint) floor(im_freq_period);
2471       }else{
2472 	if(floor(new_phase) < buffer_length){
2473 	  ptr_im_mix_buffer = im_mix_buffer + (guint) floor(new_phase);
2474 	}else{
2475 	  ptr_im_mix_buffer = im_mix_buffer + buffer_length - 1;
2476 	}
2477       }
2478     }
2479 
2480     if(low_start_x + (guint) floor(new_phase) < buffer_length){
2481       ptr_low_mix_buffer = low_mix_buffer + (low_start_x + (guint) floor(new_phase));
2482     }else{
2483       if((low_start_x + (guint) floor(new_phase)) - (guint) floor(low_freq_period) < buffer_length &&
2484 	 (low_start_x + (guint) floor(new_phase)) - (guint) floor(low_freq_period) > 0){
2485 	ptr_low_mix_buffer = low_mix_buffer + (low_start_x + (guint) floor(new_phase)) - (guint) floor(low_freq_period);
2486       }else{
2487 	if(floor(new_phase) < buffer_length){
2488 	  ptr_low_mix_buffer = low_mix_buffer + (guint) floor(new_phase);
2489 	}else{
2490 	  ptr_low_mix_buffer = low_mix_buffer + buffer_length - 1;
2491 	}
2492       }
2493     }
2494 
2495     ptr_new_mix_buffer = new_mix_buffer + i;
2496 
2497     /* write new mix buffer */
2498     if(ptr_mix_buffer->real != 0.0){
2499       new_z = volume * ((1.0 / 2.0) * (new_freq_period * (ags_complex_get(ptr_mix_buffer) / freq_period) * (ags_complex_get(ptr_im_mix_buffer) / im_freq_period) / (ags_complex_get(ptr_mix_buffer) / freq_period)) + (1.0 / 2.0) * (new_freq_period * (ags_complex_get(ptr_mix_buffer) / freq_period) * (ags_complex_get(ptr_low_mix_buffer) / low_freq_period) / (ags_complex_get(ptr_mix_buffer) / freq_period)));
2500     }else{
2501       new_z = 0.0 + I * 0.0;
2502     }
2503 
2504     ags_complex_set(ptr_new_mix_buffer,
2505 		    new_z);
2506   }
2507 
2508   /* rewrite buffer */
2509   for(i = 0; i < buffer_length; i++){
2510     ptr_new_mix_buffer = new_mix_buffer + i;
2511     ptr_buffer = buffer + i;
2512 
2513     ags_complex_set(ptr_buffer, ags_complex_get(ptr_new_mix_buffer));
2514   }
2515 
2516   ags_stream_free(mix_buffer);
2517 
2518   ags_stream_free(im_mix_buffer);
2519 
2520   ags_stream_free(low_mix_buffer);
2521 
2522   ags_stream_free(new_mix_buffer);
2523 }
2524