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_audio_buffer_util.h>
21 
22 #include <ags/libags.h>
23 
24 #include <samplerate.h>
25 
26 #if defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
27 #include <Accelerate/Accelerate.h>
28 #endif
29 
30 gpointer ags_audio_buffer_util_copy(gpointer ptr);
31 void ags_audio_buffer_util_free(gpointer ptr);
32 
33 #include <stdlib.h>
34 #include <string.h>
35 #include <math.h>
36 #include <complex.h>
37 
38 /**
39  * SECTION:ags_audio_buffer_util
40  * @short_description: audio buffer util
41  * @title: AgsAudioBufferUtil
42  * @section_id:
43  * @include: ags/audio/ags_audio_buffer_util.h
44  *
45  * Utility functions to process audio buffer.
46  */
47 
48 GType
ags_audio_buffer_util_get_type(void)49 ags_audio_buffer_util_get_type(void)
50 {
51   static volatile gsize g_define_type_id__volatile = 0;
52 
53   if(g_once_init_enter (&g_define_type_id__volatile)){
54     GType ags_type_audio_buffer_util = 0;
55 
56     ags_type_audio_buffer_util =
57       g_boxed_type_register_static("AgsAudioBufferUtil",
58 				   (GBoxedCopyFunc) ags_audio_buffer_util_copy,
59 				   (GBoxedFreeFunc) ags_audio_buffer_util_free);
60 
61     g_once_init_leave(&g_define_type_id__volatile, ags_type_audio_buffer_util);
62   }
63 
64   return g_define_type_id__volatile;
65 }
66 
67 gpointer
ags_audio_buffer_util_copy(gpointer ptr)68 ags_audio_buffer_util_copy(gpointer ptr)
69 {
70   gpointer retval;
71 
72   retval = g_memdup(ptr, sizeof(AgsAudioBufferUtil));
73 
74   return(retval);
75 }
76 
77 void
ags_audio_buffer_util_free(gpointer ptr)78 ags_audio_buffer_util_free(gpointer ptr)
79 {
80   g_free(ptr);
81 }
82 
83 /**
84  * ags_audio_buffer_util_format_from_soundcard:
85  * @soundcard_format: the soundcard bit mode
86  *
87  * Translate soundcard format to audio buffer util format.
88  *
89  * Returns: the converted format
90  *
91  * Since: 3.0.0
92  */
93 guint
ags_audio_buffer_util_format_from_soundcard(guint soundcard_format)94 ags_audio_buffer_util_format_from_soundcard(guint soundcard_format)
95 {
96   switch(soundcard_format){
97   case AGS_SOUNDCARD_SIGNED_8_BIT:
98     return(AGS_AUDIO_BUFFER_UTIL_S8);
99   case AGS_SOUNDCARD_SIGNED_16_BIT:
100     return(AGS_AUDIO_BUFFER_UTIL_S16);
101   case AGS_SOUNDCARD_SIGNED_24_BIT:
102     return(AGS_AUDIO_BUFFER_UTIL_S24);
103   case AGS_SOUNDCARD_SIGNED_32_BIT:
104     return(AGS_AUDIO_BUFFER_UTIL_S32);
105   case AGS_SOUNDCARD_SIGNED_64_BIT:
106     return(AGS_AUDIO_BUFFER_UTIL_S64);
107   case AGS_SOUNDCARD_FLOAT:
108     return(AGS_AUDIO_BUFFER_UTIL_FLOAT);
109   case AGS_SOUNDCARD_DOUBLE:
110     return(AGS_AUDIO_BUFFER_UTIL_DOUBLE);
111   case AGS_SOUNDCARD_COMPLEX:
112     return(AGS_AUDIO_BUFFER_UTIL_COMPLEX);
113   default:
114     {
115       g_warning("ags_audio_buffer_util_format_from_soundcard() - unsupported soundcard format");
116 
117       return(0);
118     }
119   }
120 }
121 
122 /**
123  * ags_audio_buffer_util_get_copy_mode:
124  * @destination_format: the destination buffer format
125  * @source_format: the source buffer format
126  *
127  * Get copy mode for given destination and source format.
128  *
129  * Returns: the desired copy mode
130  *
131  * Since: 3.0.0
132  */
133 guint
ags_audio_buffer_util_get_copy_mode(guint destination_format,guint source_format)134 ags_audio_buffer_util_get_copy_mode(guint destination_format,
135 				    guint source_format)
136 {
137   guint copy_mode;
138 
139   copy_mode = 0;
140 
141   if(source_format == AGS_AUDIO_BUFFER_UTIL_S8){
142 
143     /* signed 8 bit source */
144     switch(destination_format){
145     case AGS_AUDIO_BUFFER_UTIL_S8:
146       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S8_TO_S8;
147       break;
148     case AGS_AUDIO_BUFFER_UTIL_S16:
149       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S8_TO_S16;
150       break;
151     case AGS_AUDIO_BUFFER_UTIL_S24:
152       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S8_TO_S24;
153       break;
154     case AGS_AUDIO_BUFFER_UTIL_S32:
155       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S8_TO_S32;
156       break;
157     case AGS_AUDIO_BUFFER_UTIL_S64:
158       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S8_TO_S64;
159       break;
160     case AGS_AUDIO_BUFFER_UTIL_FLOAT:
161       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S8_TO_FLOAT;
162       break;
163     case AGS_AUDIO_BUFFER_UTIL_DOUBLE:
164       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S8_TO_DOUBLE;
165       break;
166 #ifdef __APPLE__
167     case AGS_AUDIO_BUFFER_UTIL_FLOAT32:
168       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S8_TO_FLOAT32;
169       break;
170 #endif
171     case AGS_AUDIO_BUFFER_UTIL_COMPLEX:
172       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S8_TO_COMPLEX;
173       break;
174     default:
175       {
176 	g_warning("ags_audio_buffer_util_get_copy_mode() - unsupported destination buffer format");
177       }
178     }
179 
180   }else if(source_format == AGS_AUDIO_BUFFER_UTIL_S16){
181 
182     /* signed 16 bit source */
183     switch(destination_format){
184     case AGS_AUDIO_BUFFER_UTIL_S8:
185       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S16_TO_S8;
186       break;
187     case AGS_AUDIO_BUFFER_UTIL_S16:
188       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S16_TO_S16;
189       break;
190     case AGS_AUDIO_BUFFER_UTIL_S24:
191       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S16_TO_S24;
192       break;
193     case AGS_AUDIO_BUFFER_UTIL_S32:
194       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S16_TO_S32;
195       break;
196     case AGS_AUDIO_BUFFER_UTIL_S64:
197       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S16_TO_S64;
198       break;
199     case AGS_AUDIO_BUFFER_UTIL_FLOAT:
200       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S16_TO_FLOAT;
201       break;
202     case AGS_AUDIO_BUFFER_UTIL_DOUBLE:
203       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S16_TO_DOUBLE;
204       break;
205 #ifdef __APPLE__
206     case AGS_AUDIO_BUFFER_UTIL_FLOAT32:
207       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S16_TO_FLOAT32;
208       break;
209 #endif
210     case AGS_AUDIO_BUFFER_UTIL_COMPLEX:
211       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S16_TO_COMPLEX;
212       break;
213     default:
214       {
215 	g_warning("ags_audio_buffer_util_get_copy_mode() - unsupported destination buffer format");
216       }
217     }
218 
219   }else if(source_format == AGS_AUDIO_BUFFER_UTIL_S24){
220 
221     /* signed 24 bit source */
222     switch(destination_format){
223     case AGS_AUDIO_BUFFER_UTIL_S8:
224       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S24_TO_S8;
225       break;
226     case AGS_AUDIO_BUFFER_UTIL_S16:
227       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S24_TO_S16;
228       break;
229     case AGS_AUDIO_BUFFER_UTIL_S24:
230       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S24_TO_S24;
231       break;
232     case AGS_AUDIO_BUFFER_UTIL_S32:
233       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S24_TO_S32;
234       break;
235     case AGS_AUDIO_BUFFER_UTIL_S64:
236       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S24_TO_S64;
237       break;
238     case AGS_AUDIO_BUFFER_UTIL_FLOAT:
239       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S24_TO_FLOAT;
240       break;
241     case AGS_AUDIO_BUFFER_UTIL_DOUBLE:
242       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S24_TO_DOUBLE;
243       break;
244 #ifdef __APPLE__
245     case AGS_AUDIO_BUFFER_UTIL_FLOAT32:
246       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S24_TO_FLOAT32;
247       break;
248 #endif
249     case AGS_AUDIO_BUFFER_UTIL_COMPLEX:
250       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S24_TO_COMPLEX;
251       break;
252     default:
253       {
254 	g_warning("ags_audio_buffer_util_get_copy_mode() - unsupported destination buffer format");
255       }
256     }
257 
258   }else if(source_format == AGS_AUDIO_BUFFER_UTIL_S32){
259 
260     /* signed 32 bit source */
261     switch(destination_format){
262     case AGS_AUDIO_BUFFER_UTIL_S8:
263       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S32_TO_S8;
264       break;
265     case AGS_AUDIO_BUFFER_UTIL_S16:
266       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S32_TO_S16;
267       break;
268     case AGS_AUDIO_BUFFER_UTIL_S24:
269       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S32_TO_S24;
270       break;
271     case AGS_AUDIO_BUFFER_UTIL_S32:
272       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S32_TO_S32;
273       break;
274     case AGS_AUDIO_BUFFER_UTIL_S64:
275       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S32_TO_S64;
276       break;
277     case AGS_AUDIO_BUFFER_UTIL_FLOAT:
278       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S32_TO_FLOAT;
279       break;
280     case AGS_AUDIO_BUFFER_UTIL_DOUBLE:
281       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S32_TO_DOUBLE;
282       break;
283 #ifdef __APPLE__
284     case AGS_AUDIO_BUFFER_UTIL_FLOAT32:
285       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S32_TO_FLOAT32;
286       break;
287 #endif
288     case AGS_AUDIO_BUFFER_UTIL_COMPLEX:
289       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S32_TO_COMPLEX;
290       break;
291     default:
292       {
293 	g_warning("ags_audio_buffer_util_get_copy_mode() - unsupported destination buffer format");
294       }
295     }
296 
297   }else if(source_format == AGS_AUDIO_BUFFER_UTIL_S64){
298 
299     /* signed 64 bit source */
300     switch(destination_format){
301     case AGS_AUDIO_BUFFER_UTIL_S8:
302       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S64_TO_S8;
303       break;
304     case AGS_AUDIO_BUFFER_UTIL_S16:
305       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S64_TO_S16;
306       break;
307     case AGS_AUDIO_BUFFER_UTIL_S24:
308       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S64_TO_S24;
309       break;
310     case AGS_AUDIO_BUFFER_UTIL_S32:
311       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S64_TO_S32;
312       break;
313     case AGS_AUDIO_BUFFER_UTIL_S64:
314       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S64_TO_S64;
315       break;
316     case AGS_AUDIO_BUFFER_UTIL_FLOAT:
317       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S64_TO_FLOAT;
318       break;
319     case AGS_AUDIO_BUFFER_UTIL_DOUBLE:
320       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S64_TO_DOUBLE;
321       break;
322 #ifdef __APPLE__
323     case AGS_AUDIO_BUFFER_UTIL_FLOAT32:
324       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S64_TO_FLOAT32;
325       break;
326 #endif
327     case AGS_AUDIO_BUFFER_UTIL_COMPLEX:
328       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_S64_TO_COMPLEX;
329       break;
330     default:
331       {
332 	g_warning("ags_audio_buffer_util_get_copy_mode() - unsupported destination buffer format");
333       }
334     }
335 
336   }else if(source_format == AGS_AUDIO_BUFFER_UTIL_FLOAT){
337 
338     /* float source */
339     switch(destination_format){
340     case AGS_AUDIO_BUFFER_UTIL_S8:
341       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT_TO_S8;
342       break;
343     case AGS_AUDIO_BUFFER_UTIL_S16:
344       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT_TO_S16;
345       break;
346     case AGS_AUDIO_BUFFER_UTIL_S24:
347       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT_TO_S24;
348       break;
349     case AGS_AUDIO_BUFFER_UTIL_S32:
350       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT_TO_S32;
351       break;
352     case AGS_AUDIO_BUFFER_UTIL_S64:
353       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT_TO_S64;
354       break;
355     case AGS_AUDIO_BUFFER_UTIL_FLOAT:
356       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT_TO_FLOAT;
357       break;
358     case AGS_AUDIO_BUFFER_UTIL_DOUBLE:
359       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT_TO_DOUBLE;
360       break;
361 #ifdef __APPLE__
362     case AGS_AUDIO_BUFFER_UTIL_FLOAT32:
363       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT_TO_FLOAT32;
364       break;
365 #endif
366     case AGS_AUDIO_BUFFER_UTIL_COMPLEX:
367       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT_TO_COMPLEX;
368       break;
369     default:
370       {
371 	g_warning("ags_audio_buffer_util_get_copy_mode() - unsupported destination buffer format");
372       }
373     }
374 
375   }else if(source_format == AGS_AUDIO_BUFFER_UTIL_DOUBLE){
376 
377     /* double source */
378     switch(destination_format){
379     case AGS_AUDIO_BUFFER_UTIL_S8:
380       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_DOUBLE_TO_S8;
381       break;
382     case AGS_AUDIO_BUFFER_UTIL_S16:
383       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_DOUBLE_TO_S16;
384       break;
385     case AGS_AUDIO_BUFFER_UTIL_S24:
386       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_DOUBLE_TO_S24;
387       break;
388     case AGS_AUDIO_BUFFER_UTIL_S32:
389       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_DOUBLE_TO_S32;
390       break;
391     case AGS_AUDIO_BUFFER_UTIL_S64:
392       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_DOUBLE_TO_S64;
393       break;
394     case AGS_AUDIO_BUFFER_UTIL_FLOAT:
395       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_DOUBLE_TO_FLOAT;
396       break;
397     case AGS_AUDIO_BUFFER_UTIL_DOUBLE:
398       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_DOUBLE_TO_DOUBLE;
399       break;
400 #ifdef __APPLE__
401     case AGS_AUDIO_BUFFER_UTIL_FLOAT32:
402       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_DOUBLE_TO_FLOAT32;
403       break;
404 #endif
405     case AGS_AUDIO_BUFFER_UTIL_COMPLEX:
406       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_DOUBLE_TO_COMPLEX;
407       break;
408     default:
409       {
410 	g_warning("ags_audio_buffer_util_get_copy_mode() - unsupported destination buffer format");
411       }
412     }
413 
414 #ifdef __APPLE__
415   }else if(source_format == AGS_AUDIO_BUFFER_UTIL_FLOAT32){
416 
417     /* double source */
418     switch(destination_format){
419     case AGS_AUDIO_BUFFER_UTIL_S8:
420       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT32_TO_S8;
421       break;
422     case AGS_AUDIO_BUFFER_UTIL_S16:
423       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT32_TO_S16;
424       break;
425     case AGS_AUDIO_BUFFER_UTIL_S24:
426       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT32_TO_S24;
427       break;
428     case AGS_AUDIO_BUFFER_UTIL_S32:
429       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT32_TO_S32;
430       break;
431     case AGS_AUDIO_BUFFER_UTIL_S64:
432       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT32_TO_S64;
433       break;
434     case AGS_AUDIO_BUFFER_UTIL_FLOAT:
435       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT32_TO_FLOAT;
436       break;
437     case AGS_AUDIO_BUFFER_UTIL_DOUBLE:
438       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT32_TO_DOUBLE;
439       break;
440     case AGS_AUDIO_BUFFER_UTIL_FLOAT32:
441       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT32_TO_FLOAT32;
442       break;
443     case AGS_AUDIO_BUFFER_UTIL_COMPLEX:
444       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT32_TO_COMPLEX;
445       break;
446     default:
447       {
448 	g_warning("ags_audio_buffer_util_get_copy_mode() - unsupported destination buffer format");
449       }
450     }
451 #endif
452 
453   }else if(source_format == AGS_AUDIO_BUFFER_UTIL_COMPLEX){
454 
455     /* complex source */
456     switch(destination_format){
457     case AGS_AUDIO_BUFFER_UTIL_S8:
458       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_COMPLEX_TO_S8;
459       break;
460     case AGS_AUDIO_BUFFER_UTIL_S16:
461       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_COMPLEX_TO_S16;
462       break;
463     case AGS_AUDIO_BUFFER_UTIL_S24:
464       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_COMPLEX_TO_S24;
465       break;
466     case AGS_AUDIO_BUFFER_UTIL_S32:
467       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_COMPLEX_TO_S32;
468       break;
469     case AGS_AUDIO_BUFFER_UTIL_S64:
470       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_COMPLEX_TO_S64;
471       break;
472     case AGS_AUDIO_BUFFER_UTIL_FLOAT:
473       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_COMPLEX_TO_FLOAT;
474       break;
475     case AGS_AUDIO_BUFFER_UTIL_DOUBLE:
476       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_COMPLEX_TO_DOUBLE;
477       break;
478 #ifdef __APPLE__
479     case AGS_AUDIO_BUFFER_UTIL_FLOAT32:
480       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_COMPLEX_TO_FLOAT32;
481       break;
482 #endif
483     case AGS_AUDIO_BUFFER_UTIL_COMPLEX:
484       copy_mode = AGS_AUDIO_BUFFER_UTIL_COPY_COMPLEX_TO_COMPLEX;
485       break;
486     default:
487       {
488 	g_warning("ags_audio_buffer_util_get_copy_mode() - unsupported destination buffer format");
489       }
490     }
491   }else{
492     g_warning("ags_audio_buffer_util_get_copy_mode() - unsupported source buffer format");
493   }
494 
495   return(copy_mode);
496 }
497 
498 /**
499  * ags_audio_buffer_util_clear_float:
500  * @buffer: the buffer to clear
501  * @channels: number of channels
502  * @count: count frames
503  *
504  * Clears a buffer.
505  *
506  * Since: 3.0.0
507  */
508 void
ags_audio_buffer_util_clear_float(gfloat * buffer,guint channels,guint count)509 ags_audio_buffer_util_clear_float(gfloat *buffer, guint channels,
510 				  guint count)
511 {
512   guint limit;
513   guint current_channel;
514   guint i;
515 
516   if(buffer == NULL){
517     return;
518   }
519 
520   i = 0;
521 
522   /* unrolled function */
523   if(count > 8){
524     limit = count - 8;
525 
526     for(; i < limit; i += 8){
527       current_channel = 0;
528 
529       buffer[0] = 0.0;
530       buffer[(current_channel = channels)] = 0.0;
531       buffer[(current_channel += channels)] = 0.0;
532       buffer[(current_channel += channels)] = 0.0;
533       buffer[(current_channel += channels)] = 0.0;
534       buffer[(current_channel += channels)] = 0.0;
535       buffer[(current_channel += channels)] = 0.0;
536       buffer[(current_channel += channels)] = 0.0;
537 
538       buffer += (current_channel + channels);
539     }
540   }
541 
542   for(; i < count; i++){
543     *buffer = 0.0;
544 
545     buffer += channels;
546   }
547 }
548 
549 #ifdef __APPLE__
550 /**
551  * ags_audio_buffer_util_clear_float32:
552  * @buffer: the buffer to clear
553  * @channels: number of channels
554  * @count: count frames
555  *
556  * Clears a buffer.
557  *
558  * Since: 3.0.0
559  */
560 void
ags_audio_buffer_util_clear_float32(Float32 * buffer,guint channels,guint count)561 ags_audio_buffer_util_clear_float32(Float32 *buffer, guint channels,
562 				    guint count)
563 {
564   guint limit;
565   guint current_channel;
566   guint i;
567 
568   if(buffer == NULL){
569     return;
570   }
571 
572   i = 0;
573 
574   /* unrolled function */
575   if(count > 8){
576     limit = count - (count % 8);
577 
578     for(; i < limit; i += 8){
579       current_channel = 0;
580 
581       buffer[0] = (Float32) 0.0;
582       buffer[(current_channel = channels)] = (Float32) 0.0;
583       buffer[(current_channel += channels)] = (Float32) 0.0;
584       buffer[(current_channel += channels)] = (Float32) 0.0;
585       buffer[(current_channel += channels)] = (Float32) 0.0;
586       buffer[(current_channel += channels)] = (Float32) 0.0;
587       buffer[(current_channel += channels)] = (Float32) 0.0;
588       buffer[(current_channel += channels)] = (Float32) 0.0;
589 
590       buffer += (current_channel + channels);
591     }
592   }
593 
594   for(; i < count; i++){
595     *buffer = (Float32) 0.0;
596 
597     buffer += channels;
598   }
599 }
600 #endif
601 
602 /**
603  * ags_audio_buffer_util_clear_double:
604  * @buffer: the buffer to clear
605  * @channels: number of channels
606  * @count: count frames
607  *
608  * Clears a buffer.
609  *
610  * Since: 3.0.0
611  */
612 void
ags_audio_buffer_util_clear_double(gdouble * buffer,guint channels,guint count)613 ags_audio_buffer_util_clear_double(gdouble *buffer, guint channels,
614 				   guint count)
615 {
616   guint limit;
617   guint current_channel;
618   guint i;
619 
620   if(buffer == NULL){
621     return;
622   }
623 
624   i = 0;
625 
626   /* unrolled function */
627   if(count > 8){
628     limit = count - (count % 8);
629 
630     for(; i < limit; i += 8){
631       current_channel = 0;
632 
633       buffer[0] = 0.0;
634       buffer[(current_channel = channels)] = 0.0;
635       buffer[(current_channel += channels)] = 0.0;
636       buffer[(current_channel += channels)] = 0.0;
637       buffer[(current_channel += channels)] = 0.0;
638       buffer[(current_channel += channels)] = 0.0;
639       buffer[(current_channel += channels)] = 0.0;
640       buffer[(current_channel += channels)] = 0.0;
641 
642       buffer += (current_channel + channels);
643     }
644   }
645 
646   for(; i < count; i++){
647     *buffer = 0.0;
648 
649     buffer += channels;
650   }
651 }
652 
653 /**
654  * ags_audio_buffer_util_clear_complex:
655  * @buffer: the buffer to clear
656  * @channels: number of channels
657  * @count: count frames
658  *
659  * Clears a buffer.
660  *
661  * Since: 3.0.0
662  */
663 void
ags_audio_buffer_util_clear_complex(AgsComplex * buffer,guint channels,guint count)664 ags_audio_buffer_util_clear_complex(AgsComplex *buffer, guint channels,
665 				    guint count)
666 {
667   guint limit;
668   guint current_channel;
669   guint i;
670 
671   if(buffer == NULL){
672     return;
673   }
674 
675   i = 0;
676 
677   /* unrolled function */
678   if(count > 8){
679     limit = count - (count % 8);
680 
681     for(; i < limit; i += 8){
682       current_channel = 0;
683 
684       buffer[0].real = 0.0;
685       buffer[0].imag = 0.0;
686 
687       buffer[(current_channel = channels)].real = 0.0;
688       buffer[(current_channel)].imag = 0.0;
689 
690       buffer[(current_channel += channels)].real = 0.0;
691       buffer[(current_channel)].imag = 0.0;
692 
693       buffer[(current_channel += channels)].real = 0.0;
694       buffer[(current_channel)].imag = 0.0;
695 
696       buffer[(current_channel += channels)].real = 0.0;
697       buffer[(current_channel)].imag = 0.0;
698 
699       buffer[(current_channel += channels)].real = 0.0;
700       buffer[(current_channel)].imag = 0.0;
701 
702       buffer[(current_channel += channels)].real = 0.0;
703       buffer[(current_channel)].imag = 0.0;
704 
705       buffer[(current_channel += channels)].real = 0.0;
706       buffer[(current_channel)].imag = 0.0;
707 
708       buffer += (current_channel + channels);
709     }
710   }
711 
712   for(; i < count; i++){
713     buffer[0].real = 0.0;
714     buffer[0].imag = 0.0;
715 
716     buffer += channels;
717   }
718 }
719 
720 /**
721  * ags_audio_buffer_util_clear_buffer:
722  * @buffer: the audio data
723  * @channels: the number of channels
724  * @count: number of frames
725  * @format: the format
726  *
727  * Clears the audio data.
728  *
729  * Since: 3.0.0
730  */
731 void
ags_audio_buffer_util_clear_buffer(void * buffer,guint channels,guint count,guint format)732 ags_audio_buffer_util_clear_buffer(void *buffer, guint channels,
733 				   guint count, guint format)
734 {
735   switch(format){
736   case AGS_AUDIO_BUFFER_UTIL_S8:
737     {
738       memset((gint8 *) buffer, 0, channels * count * sizeof(gint8));
739     }
740     break;
741   case AGS_AUDIO_BUFFER_UTIL_S16:
742     {
743       memset((gint16 *) buffer, 0, channels * count * sizeof(gint16));
744     }
745     break;
746   case AGS_AUDIO_BUFFER_UTIL_S24:
747     {
748       memset((gint32 *) buffer, 0, channels * count * sizeof(gint32));
749     }
750     break;
751   case AGS_AUDIO_BUFFER_UTIL_S32:
752     {
753       memset((gint32 *) buffer, 0, channels * count * sizeof(gint32));
754     }
755     break;
756   case AGS_AUDIO_BUFFER_UTIL_S64:
757     {
758       memset((gint64 *) buffer, 0, channels * count * sizeof(gint64));
759     }
760     break;
761   case AGS_AUDIO_BUFFER_UTIL_FLOAT:
762     {
763       ags_audio_buffer_util_clear_float(buffer, channels,
764 					count);
765     }
766     break;
767   case AGS_AUDIO_BUFFER_UTIL_DOUBLE:
768     {
769       ags_audio_buffer_util_clear_double(buffer, channels,
770 					 count);
771     }
772     break;
773 #ifdef __APPLE__
774   case AGS_AUDIO_BUFFER_UTIL_FLOAT32:
775     {
776       ags_audio_buffer_util_clear_float32(buffer, channels,
777 					  count);
778     }
779     break;
780 #endif
781   case AGS_AUDIO_BUFFER_UTIL_COMPLEX:
782     {
783       ags_audio_buffer_util_clear_complex(buffer, channels,
784 					  count);
785     }
786     break;
787   default:
788     g_critical("unsupported audio buffer format");
789   }
790 }
791 
792 /**
793  * ags_audio_buffer_util_envelope_s8:
794  * @buffer: the audio buffer
795  * @channels: number of audio channels
796  * @buffer_length: the buffer's length
797  * @current_volume: current volume
798  * @ratio: the amount to increment
799  *
800  * Envelope buffer at @ratio.
801  *
802  * Returns: the last volume used
803  *
804  * Since: 3.0.0
805  */
806 gdouble
ags_audio_buffer_util_envelope_s8(gint8 * buffer,guint channels,guint buffer_length,gdouble current_volume,gdouble ratio)807 ags_audio_buffer_util_envelope_s8(gint8 *buffer, guint channels,
808 				  guint buffer_length,
809 				  gdouble current_volume,
810 				  gdouble ratio)
811 {
812   gdouble start_volume;
813   guint limit;
814   guint current_channel;
815   guint i;
816 
817   if(buffer == NULL){
818     return(1.0);
819   }
820 
821   start_volume = current_volume;
822   i = 0;
823 
824 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
825   /* vectorized function */
826   if(buffer_length > 8){
827     limit = buffer_length - (buffer_length % 8);
828 
829     for(; i < limit; i += 8, current_volume = start_volume + i * ratio){
830       ags_v8double v_buffer;
831 
832       current_channel = 0;
833 
834       v_buffer = (ags_v8double) {(gdouble) buffer[0],
835 				 (gdouble) buffer[(current_channel = channels)],
836 				 (gdouble) buffer[(current_channel += channels)],
837 				 (gdouble) buffer[(current_channel += channels)],
838 				 (gdouble) buffer[(current_channel += channels)],
839 				 (gdouble) buffer[(current_channel += channels)],
840 				 (gdouble) buffer[(current_channel += channels)],
841 				 (gdouble) buffer[(current_channel += channels)]};
842 
843       v_buffer *= current_volume;
844 
845       current_channel = 0;
846 
847       buffer[0] = (gint8) v_buffer[0];
848       buffer[(current_channel = channels)] = (gint8) v_buffer[1];
849       buffer[(current_channel += channels)] = (gint8) v_buffer[2];
850       buffer[(current_channel += channels)] = (gint8) v_buffer[3];
851       buffer[(current_channel += channels)] = (gint8) v_buffer[4];
852       buffer[(current_channel += channels)] = (gint8) v_buffer[5];
853       buffer[(current_channel += channels)] = (gint8) v_buffer[6];
854       buffer[(current_channel += channels)] = (gint8) v_buffer[7];
855 
856       buffer += (current_channel + channels);
857     }
858   }
859 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
860   /* vectorized function using accelerate framework */
861   if(buffer_length > 8){
862     double v_current_volume[1];
863 
864     limit = buffer_length - (buffer_length % 8);
865 
866     for(; i < limit; i += 8, v_current_volume[0] = start_volume + i * ratio){
867       double ret_v_buffer[8];
868 
869       current_channel = 0;
870 
871       double v_buffer[] = {(double) buffer[0],
872 			   (double) buffer[(current_channel = channels)],
873 			   (double) buffer[(current_channel += channels)],
874 			   (double) buffer[(current_channel += channels)],
875 			   (double) buffer[(current_channel += channels)],
876 			   (double) buffer[(current_channel += channels)],
877 			   (double) buffer[(current_channel += channels)],
878 			   (double) buffer[(current_channel += channels)]};
879 
880       vDSP_vmulD(v_buffer, 1, v_current_volume, 0, ret_v_buffer, 1, 8);
881 
882       current_channel = 0;
883 
884       buffer[0] = (gint8) ret_v_buffer[0];
885       buffer[(current_channel = channels)] = (gint8) ret_v_buffer[1];
886       buffer[(current_channel += channels)] = (gint8) ret_v_buffer[2];
887       buffer[(current_channel += channels)] = (gint8) ret_v_buffer[3];
888       buffer[(current_channel += channels)] = (gint8) ret_v_buffer[4];
889       buffer[(current_channel += channels)] = (gint8) ret_v_buffer[5];
890       buffer[(current_channel += channels)] = (gint8) ret_v_buffer[6];
891       buffer[(current_channel += channels)] = (gint8) ret_v_buffer[7];
892 
893       buffer += (current_channel + channels);
894     }
895   }
896 #else
897   /* unrolled function */
898   if(buffer_length > 8){
899     limit = buffer_length - (buffer_length % 8);
900 
901     for(; i < limit; i += 8, current_volume = start_volume + i * ratio){
902       current_channel = 0;
903 
904       buffer[0] = 0xff & ((gint16) (buffer[0] * current_volume));
905       buffer[current_channel] = 0xff & ((gint16) (buffer[(current_channel = channels)] * current_volume));
906       buffer[current_channel] = 0xff & ((gint16) (buffer[(current_channel += channels)] * current_volume));
907       buffer[current_channel] = 0xff & ((gint16) (buffer[(current_channel += channels)] * current_volume));
908       buffer[current_channel] = 0xff & ((gint16) (buffer[(current_channel += channels)] * current_volume));
909       buffer[current_channel] = 0xff & ((gint16) (buffer[(current_channel += channels)] * current_volume));
910       buffer[current_channel] = 0xff & ((gint16) (buffer[(current_channel += channels)] * current_volume));
911       buffer[current_channel] = 0xff & ((gint16) (buffer[(current_channel += channels)] * current_volume));
912 
913       buffer += (current_channel + channels);
914     }
915   }
916 #endif
917 
918   for(; i < buffer_length; i++, current_volume = start_volume + i * ratio){
919     buffer[0] = 0xff & ((gint16) (buffer[0] * current_volume));
920 
921     buffer += channels;
922   }
923 
924   return(current_volume);
925 }
926 
927 /**
928  * ags_audio_buffer_util_envelope_s16:
929  * @buffer: the audio buffer
930  * @channels: number of audio channels
931  * @buffer_length: the buffer's length
932  * @current_volume: current volume
933  * @ratio: the amount to increment
934  *
935  * Envelope buffer at @ratio.
936  *
937  * Returns: the last volume used
938  *
939  * Since: 3.0.0
940  */
941 gdouble
ags_audio_buffer_util_envelope_s16(gint16 * buffer,guint channels,guint buffer_length,gdouble current_volume,gdouble ratio)942 ags_audio_buffer_util_envelope_s16(gint16 *buffer, guint channels,
943 				   guint buffer_length,
944 				   gdouble current_volume,
945 				   gdouble ratio)
946 {
947   gdouble start_volume;
948   guint limit;
949   guint current_channel;
950   guint i;
951 
952   if(buffer == NULL){
953     return(1.0);
954   }
955 
956   start_volume = current_volume;
957   i = 0;
958 
959 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
960   /* vectorized function */
961   if(buffer_length > 8){
962     limit = buffer_length - (buffer_length % 8);
963 
964     for(; i < limit; i += 8, current_volume = start_volume + i * ratio){
965       ags_v8double v_buffer;
966 
967       current_channel = 0;
968 
969       v_buffer = (ags_v8double) {(gdouble) buffer[0],
970 				 (gdouble) buffer[(current_channel = channels)],
971 				 (gdouble) buffer[(current_channel += channels)],
972 				 (gdouble) buffer[(current_channel += channels)],
973 				 (gdouble) buffer[(current_channel += channels)],
974 				 (gdouble) buffer[(current_channel += channels)],
975 				 (gdouble) buffer[(current_channel += channels)],
976 				 (gdouble) buffer[(current_channel += channels)]};
977 
978       v_buffer *= current_volume;
979 
980       current_channel = 0;
981 
982       buffer[0] = (gint16) v_buffer[0];
983       buffer[(current_channel = channels)] = (gint16) v_buffer[1];
984       buffer[(current_channel += channels)] = (gint16) v_buffer[2];
985       buffer[(current_channel += channels)] = (gint16) v_buffer[3];
986       buffer[(current_channel += channels)] = (gint16) v_buffer[4];
987       buffer[(current_channel += channels)] = (gint16) v_buffer[5];
988       buffer[(current_channel += channels)] = (gint16) v_buffer[6];
989       buffer[(current_channel += channels)] = (gint16) v_buffer[7];
990 
991       buffer += (current_channel + channels);
992     }
993   }
994 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
995   /* vectorized function using accelerate framework */
996   if(buffer_length > 8){
997     double v_current_volume[1];
998 
999     limit = buffer_length - (buffer_length % 8);
1000 
1001     for(; i < limit; i += 8, v_current_volume[0] = start_volume + i * ratio){
1002       double ret_v_buffer[8];
1003 
1004       current_channel = 0;
1005 
1006       double v_buffer[] = {(double) buffer[0],
1007 			   (double) buffer[(current_channel = channels)],
1008 			   (double) buffer[(current_channel += channels)],
1009 			   (double) buffer[(current_channel += channels)],
1010 			   (double) buffer[(current_channel += channels)],
1011 			   (double) buffer[(current_channel += channels)],
1012 			   (double) buffer[(current_channel += channels)],
1013 			   (double) buffer[(current_channel += channels)]};
1014 
1015       vDSP_vmulD(v_buffer, 1, v_current_volume, 0, ret_v_buffer, 1, 8);
1016 
1017       current_channel = 0;
1018 
1019       buffer[0] = (gint16) ret_v_buffer[0];
1020       buffer[(current_channel = channels)] = (gint16) ret_v_buffer[1];
1021       buffer[(current_channel += channels)] = (gint16) ret_v_buffer[2];
1022       buffer[(current_channel += channels)] = (gint16) ret_v_buffer[3];
1023       buffer[(current_channel += channels)] = (gint16) ret_v_buffer[4];
1024       buffer[(current_channel += channels)] = (gint16) ret_v_buffer[5];
1025       buffer[(current_channel += channels)] = (gint16) ret_v_buffer[6];
1026       buffer[(current_channel += channels)] = (gint16) ret_v_buffer[7];
1027 
1028       buffer += (current_channel + channels);
1029     }
1030   }
1031 #else
1032   /* unrolled function */
1033   if(buffer_length > 8){
1034     limit = buffer_length - (buffer_length % 8);
1035 
1036     for(; i < limit; i += 8, current_volume = start_volume + i * ratio){
1037       current_channel = 0;
1038 
1039       buffer[0] = (gint16) 0xffff & ((gint32) (buffer[0] * current_volume));
1040       buffer[current_channel] = (gint16) 0xffff & ((gint32) (buffer[(current_channel = channels)] * current_volume));
1041       buffer[current_channel] = (gint16) 0xffff & ((gint32) (buffer[(current_channel += channels)] * current_volume));
1042       buffer[current_channel] = (gint16) 0xffff & ((gint32) (buffer[(current_channel += channels)] * current_volume));
1043       buffer[current_channel] = (gint16) 0xffff & ((gint32) (buffer[(current_channel += channels)] * current_volume));
1044       buffer[current_channel] = (gint16) 0xffff & ((gint32) (buffer[(current_channel += channels)] * current_volume));
1045       buffer[current_channel] = (gint16) 0xffff & ((gint32) (buffer[(current_channel += channels)] * current_volume));
1046       buffer[current_channel] = (gint16) 0xffff & ((gint32) (buffer[(current_channel += channels)] * current_volume));
1047 
1048       buffer += (current_channel + channels);
1049     }
1050   }
1051 #endif
1052 
1053   for(; i < buffer_length; i++, current_volume = start_volume + i * ratio){
1054     buffer[0] = (gint16) 0xffff & ((gint32) (buffer[0] * current_volume));
1055 
1056     buffer += channels;
1057   }
1058 
1059   return(current_volume);
1060 }
1061 
1062 /**
1063  * ags_audio_buffer_util_envelope_s24:
1064  * @buffer: the audio buffer
1065  * @channels: number of audio channels
1066  * @buffer_length: the buffer's length
1067  * @current_volume: current volume
1068  * @ratio: the amount to increment
1069  *
1070  * Envelope buffer at @ratio.
1071  *
1072  * Returns: the last volume used
1073  *
1074  * Since: 3.0.0
1075  */
1076 gdouble
ags_audio_buffer_util_envelope_s24(gint32 * buffer,guint channels,guint buffer_length,gdouble current_volume,gdouble ratio)1077 ags_audio_buffer_util_envelope_s24(gint32 *buffer, guint channels,
1078 				   guint buffer_length,
1079 				   gdouble current_volume,
1080 				   gdouble ratio)
1081 {
1082   gdouble start_volume;
1083   guint limit;
1084   guint current_channel;
1085   guint i;
1086 
1087   if(buffer == NULL){
1088     return(1.0);
1089   }
1090 
1091   start_volume = current_volume;
1092   i = 0;
1093 
1094 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
1095   /* vectorized function */
1096   if(buffer_length > 8){
1097     limit = buffer_length - (buffer_length % 8);
1098 
1099     for(; i < limit; i += 8, current_volume = start_volume + i * ratio){
1100       ags_v8double v_buffer;
1101 
1102       current_channel = 0;
1103 
1104       v_buffer = (ags_v8double) {(gdouble) buffer[0],
1105 				 (gdouble) buffer[(current_channel = channels)],
1106 				 (gdouble) buffer[(current_channel += channels)],
1107 				 (gdouble) buffer[(current_channel += channels)],
1108 				 (gdouble) buffer[(current_channel += channels)],
1109 				 (gdouble) buffer[(current_channel += channels)],
1110 				 (gdouble) buffer[(current_channel += channels)],
1111 				 (gdouble) buffer[(current_channel += channels)]};
1112 
1113       v_buffer *= current_volume;
1114 
1115       current_channel = 0;
1116 
1117       buffer[0] = (gint32) v_buffer[0];
1118       buffer[(current_channel = channels)] = (gint32) v_buffer[1];
1119       buffer[(current_channel += channels)] = (gint32) v_buffer[2];
1120       buffer[(current_channel += channels)] = (gint32) v_buffer[3];
1121       buffer[(current_channel += channels)] = (gint32) v_buffer[4];
1122       buffer[(current_channel += channels)] = (gint32) v_buffer[5];
1123       buffer[(current_channel += channels)] = (gint32) v_buffer[6];
1124       buffer[(current_channel += channels)] = (gint32) v_buffer[7];
1125 
1126       buffer += (current_channel + channels);
1127     }
1128   }
1129 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
1130   /* vectorized function using accelerate framework */
1131   if(buffer_length > 8){
1132     double v_current_volume[1];
1133 
1134     limit = buffer_length - (buffer_length % 8);
1135 
1136     for(; i < limit; i += 8, v_current_volume[0] = start_volume + i * ratio){
1137       double ret_v_buffer[8];
1138 
1139       current_channel = 0;
1140 
1141       double v_buffer[] = {(double) buffer[0],
1142 			   (double) buffer[(current_channel = channels)],
1143 			   (double) buffer[(current_channel += channels)],
1144 			   (double) buffer[(current_channel += channels)],
1145 			   (double) buffer[(current_channel += channels)],
1146 			   (double) buffer[(current_channel += channels)],
1147 			   (double) buffer[(current_channel += channels)],
1148 			   (double) buffer[(current_channel += channels)]};
1149 
1150       vDSP_vmulD(v_buffer, 1, v_current_volume, 0, ret_v_buffer, 1, 8);
1151 
1152       current_channel = 0;
1153 
1154       buffer[0] = (gint32) ret_v_buffer[0];
1155       buffer[(current_channel = channels)] = (gint32) ret_v_buffer[1];
1156       buffer[(current_channel += channels)] = (gint32) ret_v_buffer[2];
1157       buffer[(current_channel += channels)] = (gint32) ret_v_buffer[3];
1158       buffer[(current_channel += channels)] = (gint32) ret_v_buffer[4];
1159       buffer[(current_channel += channels)] = (gint32) ret_v_buffer[5];
1160       buffer[(current_channel += channels)] = (gint32) ret_v_buffer[6];
1161       buffer[(current_channel += channels)] = (gint32) ret_v_buffer[7];
1162 
1163       buffer += (current_channel + channels);
1164     }
1165   }
1166 #else
1167   /* unrolled function */
1168   if(buffer_length > 8){
1169     limit = buffer_length - (buffer_length % 8);
1170 
1171     for(; i < limit; i += 8, current_volume = start_volume + i * ratio){
1172       current_channel = 0;
1173 
1174       buffer[0] = (gint32) 0xffffffff & ((gint32) (buffer[0] * current_volume));
1175       buffer[current_channel] = (gint32) 0xffffffff & ((gint32) (buffer[(current_channel = channels)] * current_volume));
1176       buffer[current_channel] = (gint32) 0xffffffff & ((gint32) (buffer[(current_channel += channels)] * current_volume));
1177       buffer[current_channel] = (gint32) 0xffffffff & ((gint32) (buffer[(current_channel += channels)] * current_volume));
1178       buffer[current_channel] = (gint32) 0xffffffff & ((gint32) (buffer[(current_channel += channels)] * current_volume));
1179       buffer[current_channel] = (gint32) 0xffffffff & ((gint32) (buffer[(current_channel += channels)] * current_volume));
1180       buffer[current_channel] = (gint32) 0xffffffff & ((gint32) (buffer[(current_channel += channels)] * current_volume));
1181       buffer[current_channel] = (gint32) 0xffffffff & ((gint32) (buffer[(current_channel += channels)] * current_volume));
1182 
1183       buffer += (current_channel + channels);
1184     }
1185   }
1186 #endif
1187 
1188   for(; i < buffer_length; i++, current_volume = start_volume + i * ratio){
1189     buffer[0] = (gint32) 0xffffffff & ((gint32) (buffer[0] * current_volume));
1190 
1191     buffer += channels;
1192   }
1193 
1194   return(current_volume);
1195 }
1196 
1197 /**
1198  * ags_audio_buffer_util_envelope_s32:
1199  * @buffer: the audio buffer
1200  * @channels: number of audio channels
1201  * @buffer_length: the buffer's length
1202  * @current_volume: current volume
1203  * @ratio: the amount to increment
1204  *
1205  * Envelope buffer at @ratio.
1206  *
1207  * Returns: the last volume used
1208  *
1209  * Since: 3.0.0
1210  */
1211 gdouble
ags_audio_buffer_util_envelope_s32(gint32 * buffer,guint channels,guint buffer_length,gdouble current_volume,gdouble ratio)1212 ags_audio_buffer_util_envelope_s32(gint32 *buffer, guint channels,
1213 				   guint buffer_length,
1214 				   gdouble current_volume,
1215 				   gdouble ratio)
1216 {
1217   gdouble start_volume;
1218   guint limit;
1219   guint current_channel;
1220   guint i;
1221 
1222   if(buffer == NULL){
1223     return(1.0);
1224   }
1225 
1226   start_volume = current_volume;
1227   i = 0;
1228 
1229 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
1230   /* vectorized function */
1231   if(buffer_length > 8){
1232     limit = buffer_length - (buffer_length % 8);
1233 
1234     for(; i < limit; i += 8, current_volume = start_volume + i * ratio){
1235       ags_v8double v_buffer;
1236 
1237       current_channel = 0;
1238 
1239       v_buffer = (ags_v8double) {(gdouble) buffer[0],
1240 				 (gdouble) buffer[(current_channel = channels)],
1241 				 (gdouble) buffer[(current_channel += channels)],
1242 				 (gdouble) buffer[(current_channel += channels)],
1243 				 (gdouble) buffer[(current_channel += channels)],
1244 				 (gdouble) buffer[(current_channel += channels)],
1245 				 (gdouble) buffer[(current_channel += channels)],
1246 				 (gdouble) buffer[(current_channel += channels)]};
1247 
1248       v_buffer *= current_volume;
1249 
1250       current_channel = 0;
1251 
1252       buffer[0] = (gint32) v_buffer[0];
1253       buffer[(current_channel = channels)] = (gint32) v_buffer[1];
1254       buffer[(current_channel += channels)] = (gint32) v_buffer[2];
1255       buffer[(current_channel += channels)] = (gint32) v_buffer[3];
1256       buffer[(current_channel += channels)] = (gint32) v_buffer[4];
1257       buffer[(current_channel += channels)] = (gint32) v_buffer[5];
1258       buffer[(current_channel += channels)] = (gint32) v_buffer[6];
1259       buffer[(current_channel += channels)] = (gint32) v_buffer[7];
1260 
1261       buffer += (current_channel + channels);
1262     }
1263   }
1264 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
1265   /* vectorized function using accelerate framework */
1266   if(buffer_length > 8){
1267     double v_current_volume[1];
1268 
1269     limit = buffer_length - (buffer_length % 8);
1270 
1271     for(; i < limit; i += 8, v_current_volume[0] = start_volume + i * ratio){
1272       double ret_v_buffer[8];
1273 
1274       current_channel = 0;
1275 
1276       double v_buffer[] = {(double) buffer[0],
1277 			   (double) buffer[(current_channel = channels)],
1278 			   (double) buffer[(current_channel += channels)],
1279 			   (double) buffer[(current_channel += channels)],
1280 			   (double) buffer[(current_channel += channels)],
1281 			   (double) buffer[(current_channel += channels)],
1282 			   (double) buffer[(current_channel += channels)],
1283 			   (double) buffer[(current_channel += channels)]};
1284 
1285       vDSP_vmulD(v_buffer, 1, v_current_volume, 0, ret_v_buffer, 1, 8);
1286 
1287       current_channel = 0;
1288 
1289       buffer[0] = (gint32) ret_v_buffer[0];
1290       buffer[(current_channel = channels)] = (gint32) ret_v_buffer[1];
1291       buffer[(current_channel += channels)] = (gint32) ret_v_buffer[2];
1292       buffer[(current_channel += channels)] = (gint32) ret_v_buffer[3];
1293       buffer[(current_channel += channels)] = (gint32) ret_v_buffer[4];
1294       buffer[(current_channel += channels)] = (gint32) ret_v_buffer[5];
1295       buffer[(current_channel += channels)] = (gint32) ret_v_buffer[6];
1296       buffer[(current_channel += channels)] = (gint32) ret_v_buffer[7];
1297 
1298       buffer += (current_channel + channels);
1299     }
1300   }
1301 #else
1302   /* unrolled function */
1303   if(buffer_length > 8){
1304     limit = buffer_length - (buffer_length % 8);
1305 
1306     for(; i < limit; i += 8, current_volume = start_volume + i * ratio){
1307       current_channel = 0;
1308 
1309       buffer[0] = (gint32) 0xffffffff & ((gint64) (buffer[0] * current_volume));
1310       buffer[current_channel] = (gint32) 0xffffffff & ((gint64) (buffer[(current_channel = channels)] * current_volume));
1311       buffer[current_channel] = (gint32) 0xffffffff & ((gint64) (buffer[(current_channel += channels)] * current_volume));
1312       buffer[current_channel] = (gint32) 0xffffffff & ((gint64) (buffer[(current_channel += channels)] * current_volume));
1313       buffer[current_channel] = (gint32) 0xffffffff & ((gint64) (buffer[(current_channel += channels)] * current_volume));
1314       buffer[current_channel] = (gint32) 0xffffffff & ((gint64) (buffer[(current_channel += channels)] * current_volume));
1315       buffer[current_channel] = (gint32) 0xffffffff & ((gint64) (buffer[(current_channel += channels)] * current_volume));
1316       buffer[current_channel] = (gint32) 0xffffffff & ((gint64) (buffer[(current_channel += channels)] * current_volume));
1317 
1318       buffer += (current_channel + channels);
1319     }
1320   }
1321 #endif
1322 
1323   for(; i < buffer_length; i++, current_volume = start_volume + i * ratio){
1324     buffer[0] = (gint32) 0xffffffff & ((gint64) (buffer[0] * current_volume));
1325 
1326     buffer += channels;
1327   }
1328 
1329   return(current_volume);
1330 }
1331 
1332 /**
1333  * ags_audio_buffer_util_envelope_s64:
1334  * @buffer: the audio buffer
1335  * @channels: number of audio channels
1336  * @buffer_length: the buffer's length
1337  * @current_volume: current volume
1338  * @ratio: the amount to increment
1339  *
1340  * Envelope buffer at @ratio.
1341  *
1342  * Returns: the last volume used
1343  *
1344  * Since: 3.0.0
1345  */
1346 gdouble
ags_audio_buffer_util_envelope_s64(gint64 * buffer,guint channels,guint buffer_length,gdouble current_volume,gdouble ratio)1347 ags_audio_buffer_util_envelope_s64(gint64 *buffer, guint channels,
1348 				   guint buffer_length,
1349 				   gdouble current_volume,
1350 				   gdouble ratio)
1351 {
1352   gdouble start_volume;
1353   guint limit;
1354   guint current_channel;
1355   guint i;
1356 
1357   if(buffer == NULL){
1358     return(1.0);
1359   }
1360 
1361   start_volume = current_volume;
1362   i = 0;
1363 
1364 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
1365   /* vectorized function */
1366   if(buffer_length > 8){
1367     limit = buffer_length - (buffer_length % 8);
1368 
1369     for(; i < limit; i += 8, current_volume = start_volume + i * ratio){
1370       ags_v8double v_buffer;
1371 
1372       current_channel = 0;
1373 
1374       v_buffer = (ags_v8double) {(gdouble) buffer[0],
1375 				 (gdouble) buffer[(current_channel = channels)],
1376 				 (gdouble) buffer[(current_channel += channels)],
1377 				 (gdouble) buffer[(current_channel += channels)],
1378 				 (gdouble) buffer[(current_channel += channels)],
1379 				 (gdouble) buffer[(current_channel += channels)],
1380 				 (gdouble) buffer[(current_channel += channels)],
1381 				 (gdouble) buffer[(current_channel += channels)]};
1382 
1383       v_buffer *= current_volume;
1384 
1385       current_channel = 0;
1386 
1387       buffer[0] = (gint64) v_buffer[0];
1388       buffer[(current_channel = channels)] = (gint64) v_buffer[1];
1389       buffer[(current_channel += channels)] = (gint64) v_buffer[2];
1390       buffer[(current_channel += channels)] = (gint64) v_buffer[3];
1391       buffer[(current_channel += channels)] = (gint64) v_buffer[4];
1392       buffer[(current_channel += channels)] = (gint64) v_buffer[5];
1393       buffer[(current_channel += channels)] = (gint64) v_buffer[6];
1394       buffer[(current_channel += channels)] = (gint64) v_buffer[7];
1395 
1396       buffer += (current_channel + channels);
1397     }
1398   }
1399 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
1400   /* vectorized function using accelerate framework */
1401   if(buffer_length > 8){
1402     double v_current_volume[1];
1403 
1404     limit = buffer_length - (buffer_length % 8);
1405 
1406     for(; i < limit; i += 8, v_current_volume[0] = start_volume + i * ratio){
1407       double ret_v_buffer[8];
1408 
1409       current_channel = 0;
1410 
1411       double v_buffer[] = {(double) buffer[0],
1412 			   (double) buffer[(current_channel = channels)],
1413 			   (double) buffer[(current_channel += channels)],
1414 			   (double) buffer[(current_channel += channels)],
1415 			   (double) buffer[(current_channel += channels)],
1416 			   (double) buffer[(current_channel += channels)],
1417 			   (double) buffer[(current_channel += channels)],
1418 			   (double) buffer[(current_channel += channels)]};
1419 
1420       vDSP_vmulD(v_buffer, 1, v_current_volume, 0, ret_v_buffer, 1, 8);
1421 
1422       current_channel = 0;
1423 
1424       buffer[0] = (gint64) ret_v_buffer[0];
1425       buffer[(current_channel = channels)] = (gint64) ret_v_buffer[1];
1426       buffer[(current_channel += channels)] = (gint64) ret_v_buffer[2];
1427       buffer[(current_channel += channels)] = (gint64) ret_v_buffer[3];
1428       buffer[(current_channel += channels)] = (gint64) ret_v_buffer[4];
1429       buffer[(current_channel += channels)] = (gint64) ret_v_buffer[5];
1430       buffer[(current_channel += channels)] = (gint64) ret_v_buffer[6];
1431       buffer[(current_channel += channels)] = (gint64) ret_v_buffer[7];
1432 
1433       buffer += (current_channel + channels);
1434     }
1435   }
1436 #else
1437   /* unrolled function */
1438   if(buffer_length > 8){
1439     limit = buffer_length - (buffer_length % 8);
1440 
1441     for(; i < limit; i += 8, current_volume = start_volume + i * ratio){
1442       current_channel = 0;
1443 
1444       buffer[0] = (gint64) 0xffffffffffffffff & ((gint64) (buffer[0] * current_volume));
1445       buffer[current_channel] = (gint64) 0xffffffffffffffff & ((gint64) (buffer[(current_channel = channels)] * current_volume));
1446       buffer[current_channel] = (gint64) 0xffffffffffffffff & ((gint64) (buffer[(current_channel += channels)] * current_volume));
1447       buffer[current_channel] = (gint64) 0xffffffffffffffff & ((gint64) (buffer[(current_channel += channels)] * current_volume));
1448       buffer[current_channel] = (gint64) 0xffffffffffffffff & ((gint64) (buffer[(current_channel += channels)] * current_volume));
1449       buffer[current_channel] = (gint64) 0xffffffffffffffff & ((gint64) (buffer[(current_channel += channels)] * current_volume));
1450       buffer[current_channel] = (gint64) 0xffffffffffffffff & ((gint64) (buffer[(current_channel += channels)] * current_volume));
1451       buffer[current_channel] = (gint64) 0xffffffffffffffff & ((gint64) (buffer[(current_channel += channels)] * current_volume));
1452 
1453       buffer += (current_channel + channels);
1454     }
1455   }
1456 #endif
1457 
1458   for(; i < buffer_length; i++, current_volume = start_volume + i * ratio){
1459     buffer[0] = (gint64) 0xffffffffffffffff & ((gint64) (buffer[0] * current_volume));
1460 
1461     buffer += channels;
1462   }
1463 
1464   return(current_volume);
1465 }
1466 
1467 /**
1468  * ags_audio_buffer_util_envelope_float:
1469  * @buffer: the audio buffer
1470  * @channels: number of audio channels
1471  * @buffer_length: the buffer's length
1472  * @current_volume: current volume
1473  * @ratio: the amount to increment
1474  *
1475  * Envelope buffer at @ratio.
1476  *
1477  * Returns: the last volume used
1478  *
1479  * Since: 3.0.0
1480  */
1481 gdouble
ags_audio_buffer_util_envelope_float(gfloat * buffer,guint channels,guint buffer_length,gdouble current_volume,gdouble ratio)1482 ags_audio_buffer_util_envelope_float(gfloat *buffer, guint channels,
1483 				     guint buffer_length,
1484 				     gdouble current_volume,
1485 				     gdouble ratio)
1486 {
1487   gdouble start_volume;
1488   guint limit;
1489   guint current_channel;
1490   guint i;
1491 
1492   if(buffer == NULL){
1493     return(1.0);
1494   }
1495 
1496   start_volume = current_volume;
1497   i = 0;
1498 
1499 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
1500   /* vectorized function */
1501   if(buffer_length > 8){
1502     limit = buffer_length - (buffer_length % 8);
1503 
1504     for(; i < limit; i += 8, current_volume = start_volume + i * ratio){
1505       ags_v8double v_buffer;
1506 
1507       current_channel = 0;
1508 
1509       v_buffer = (ags_v8double) {(gdouble) buffer[0],
1510 				 (gdouble) buffer[(current_channel = channels)],
1511 				 (gdouble) buffer[(current_channel += channels)],
1512 				 (gdouble) buffer[(current_channel += channels)],
1513 				 (gdouble) buffer[(current_channel += channels)],
1514 				 (gdouble) buffer[(current_channel += channels)],
1515 				 (gdouble) buffer[(current_channel += channels)],
1516 				 (gdouble) buffer[(current_channel += channels)]};
1517 
1518       v_buffer *= current_volume;
1519 
1520       current_channel = 0;
1521 
1522       buffer[0] = (gfloat) v_buffer[0];
1523       buffer[(current_channel = channels)] = (gfloat) v_buffer[1];
1524       buffer[(current_channel += channels)] = (gfloat) v_buffer[2];
1525       buffer[(current_channel += channels)] = (gfloat) v_buffer[3];
1526       buffer[(current_channel += channels)] = (gfloat) v_buffer[4];
1527       buffer[(current_channel += channels)] = (gfloat) v_buffer[5];
1528       buffer[(current_channel += channels)] = (gfloat) v_buffer[6];
1529       buffer[(current_channel += channels)] = (gfloat) v_buffer[7];
1530 
1531       buffer += (current_channel + channels);
1532     }
1533   }
1534 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
1535   /* vectorized function using accelerate framework */
1536   if(buffer_length > 8){
1537     double v_current_volume[1];
1538 
1539     limit = buffer_length - (buffer_length % 8);
1540 
1541     for(; i < limit; i += 8, v_current_volume[0] = start_volume + i * ratio){
1542       double ret_v_buffer[8];
1543 
1544       current_channel = 0;
1545 
1546       double v_buffer[] = {(double) buffer[0],
1547 			   (double) buffer[(current_channel = channels)],
1548 			   (double) buffer[(current_channel += channels)],
1549 			   (double) buffer[(current_channel += channels)],
1550 			   (double) buffer[(current_channel += channels)],
1551 			   (double) buffer[(current_channel += channels)],
1552 			   (double) buffer[(current_channel += channels)],
1553 			   (double) buffer[(current_channel += channels)]};
1554 
1555       vDSP_vmulD(v_buffer, 1, v_current_volume, 0, ret_v_buffer, 1, 8);
1556 
1557       current_channel = 0;
1558 
1559       buffer[0] = (gfloat) ret_v_buffer[0];
1560       buffer[(current_channel = channels)] = (gfloat) ret_v_buffer[1];
1561       buffer[(current_channel += channels)] = (gfloat) ret_v_buffer[2];
1562       buffer[(current_channel += channels)] = (gfloat) ret_v_buffer[3];
1563       buffer[(current_channel += channels)] = (gfloat) ret_v_buffer[4];
1564       buffer[(current_channel += channels)] = (gfloat) ret_v_buffer[5];
1565       buffer[(current_channel += channels)] = (gfloat) ret_v_buffer[6];
1566       buffer[(current_channel += channels)] = (gfloat) ret_v_buffer[7];
1567 
1568       buffer += (current_channel + channels);
1569     }
1570   }
1571 #else
1572   /* unrolled function */
1573   if(buffer_length > 8){
1574     limit = buffer_length - (buffer_length % 8);
1575 
1576     for(; i < limit; i += 8){
1577       current_channel = 0;
1578 
1579       buffer[0] = ((gdouble) (buffer[0] * current_volume));
1580       buffer[current_channel] = ((gdouble) (buffer[(current_channel = channels)] * current_volume));
1581       buffer[current_channel] = ((gdouble) (buffer[(current_channel += channels)] * current_volume));
1582       buffer[current_channel] = ((gdouble) (buffer[(current_channel += channels)] * current_volume));
1583       buffer[current_channel] = ((gdouble) (buffer[(current_channel += channels)] * current_volume));
1584       buffer[current_channel] = ((gdouble) (buffer[(current_channel += channels)] * current_volume));
1585       buffer[current_channel] = ((gdouble) (buffer[(current_channel += channels)] * current_volume));
1586       buffer[current_channel] = ((gdouble) (buffer[(current_channel += channels)] * current_volume));
1587 
1588       buffer += (current_channel + channels);
1589 
1590       current_volume = start_volume + i * ratio;
1591     }
1592   }
1593 #endif
1594 
1595   for(; i < buffer_length; i++){
1596     buffer[0] = ((gdouble) (buffer[0] * current_volume));
1597 
1598     buffer += channels;
1599 
1600     current_volume = start_volume + i * ratio;
1601   }
1602 
1603   return(current_volume);
1604 }
1605 
1606 /**
1607  * ags_audio_buffer_util_envelope_double:
1608  * @buffer: the audio buffer
1609  * @channels: number of audio channels
1610  * @buffer_length: the buffer's length
1611  * @current_volume: current volume
1612  * @ratio: the amount to increment
1613  *
1614  * Envelope buffer at @ratio.
1615  *
1616  * Returns: the last volume used
1617  *
1618  * Since: 3.0.0
1619  */
1620 gdouble
ags_audio_buffer_util_envelope_double(gdouble * buffer,guint channels,guint buffer_length,gdouble current_volume,gdouble ratio)1621 ags_audio_buffer_util_envelope_double(gdouble *buffer, guint channels,
1622 				      guint buffer_length,
1623 				      gdouble current_volume,
1624 				      gdouble ratio)
1625 {
1626   gdouble start_volume;
1627   guint limit;
1628   guint current_channel;
1629   guint i;
1630 
1631   if(buffer == NULL){
1632     return(1.0);
1633   }
1634 
1635   start_volume = current_volume;
1636   i = 0;
1637 
1638 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
1639   /* vectorized function */
1640   if(buffer_length > 8){
1641     limit = buffer_length - (buffer_length % 8);
1642 
1643     for(; i < limit; i += 8, current_volume = start_volume + i * ratio){
1644       ags_v8double v_buffer;
1645 
1646       current_channel = 0;
1647 
1648       v_buffer = (ags_v8double) {(gdouble) buffer[0],
1649 				 (gdouble) buffer[(current_channel = channels)],
1650 				 (gdouble) buffer[(current_channel += channels)],
1651 				 (gdouble) buffer[(current_channel += channels)],
1652 				 (gdouble) buffer[(current_channel += channels)],
1653 				 (gdouble) buffer[(current_channel += channels)],
1654 				 (gdouble) buffer[(current_channel += channels)],
1655 				 (gdouble) buffer[(current_channel += channels)]};
1656 
1657       v_buffer *= current_volume;
1658 
1659       current_channel = 0;
1660 
1661       buffer[0] = v_buffer[0];
1662       buffer[(current_channel = channels)] = v_buffer[1];
1663       buffer[(current_channel += channels)] = v_buffer[2];
1664       buffer[(current_channel += channels)] = v_buffer[3];
1665       buffer[(current_channel += channels)] = v_buffer[4];
1666       buffer[(current_channel += channels)] = v_buffer[5];
1667       buffer[(current_channel += channels)] = v_buffer[6];
1668       buffer[(current_channel += channels)] = v_buffer[7];
1669 
1670       buffer += (current_channel + channels);
1671     }
1672   }
1673 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
1674   /* vectorized function using accelerate framework */
1675   if(buffer_length > 8){
1676     double v_current_volume[1];
1677 
1678     limit = buffer_length - (buffer_length % 8);
1679 
1680     for(; i < limit; i += 8, v_current_volume[0] = start_volume + i * ratio){
1681       double ret_v_buffer[8];
1682 
1683       current_channel = 0;
1684 
1685       double v_buffer[] = {(double) buffer[0],
1686 			   (double) buffer[(current_channel = channels)],
1687 			   (double) buffer[(current_channel += channels)],
1688 			   (double) buffer[(current_channel += channels)],
1689 			   (double) buffer[(current_channel += channels)],
1690 			   (double) buffer[(current_channel += channels)],
1691 			   (double) buffer[(current_channel += channels)],
1692 			   (double) buffer[(current_channel += channels)]};
1693 
1694       vDSP_vmulD(v_buffer, 1, v_current_volume, 0, ret_v_buffer, 1, 8);
1695 
1696       current_channel = 0;
1697 
1698       buffer[0] = (gdouble) ret_v_buffer[0];
1699       buffer[(current_channel = channels)] = (gdouble) ret_v_buffer[1];
1700       buffer[(current_channel += channels)] = (gdouble) ret_v_buffer[2];
1701       buffer[(current_channel += channels)] = (gdouble) ret_v_buffer[3];
1702       buffer[(current_channel += channels)] = (gdouble) ret_v_buffer[4];
1703       buffer[(current_channel += channels)] = (gdouble) ret_v_buffer[5];
1704       buffer[(current_channel += channels)] = (gdouble) ret_v_buffer[6];
1705       buffer[(current_channel += channels)] = (gdouble) ret_v_buffer[7];
1706 
1707       buffer += (current_channel + channels);
1708     }
1709   }
1710 #else
1711   /* unrolled function */
1712   if(buffer_length > 8){
1713     limit = buffer_length - (buffer_length % 8);
1714 
1715     for(; i < limit; i += 8, current_volume = start_volume + i * ratio){
1716       current_channel = 0;
1717 
1718       buffer[0] = ((gdouble) (buffer[0] * current_volume));
1719       buffer[current_channel] = ((gdouble) (buffer[(current_channel = channels)] * current_volume));
1720       buffer[current_channel] = ((gdouble) (buffer[(current_channel += channels)] * current_volume));
1721       buffer[current_channel] = ((gdouble) (buffer[(current_channel += channels)] * current_volume));
1722       buffer[current_channel] = ((gdouble) (buffer[(current_channel += channels)] * current_volume));
1723       buffer[current_channel] = ((gdouble) (buffer[(current_channel += channels)] * current_volume));
1724       buffer[current_channel] = ((gdouble) (buffer[(current_channel += channels)] * current_volume));
1725       buffer[current_channel] = ((gdouble) (buffer[(current_channel += channels)] * current_volume));
1726 
1727       buffer += (current_channel + channels);
1728     }
1729   }
1730 #endif
1731 
1732   for(; i < buffer_length; i++, current_volume = start_volume + i * ratio){
1733     buffer[0] = ((gdouble) (buffer[0] * current_volume));
1734 
1735     buffer += channels;
1736   }
1737 
1738   return(current_volume);
1739 }
1740 
1741 /**
1742  * ags_audio_buffer_util_envelope_complex:
1743  * @buffer: the audio buffer
1744  * @channels: number of audio channels
1745  * @buffer_length: the buffer's length
1746  * @current_volume: current volume
1747  * @ratio: the amount to increment
1748  *
1749  * Envelope buffer at @ratio.
1750  *
1751  * Returns: the last volume used
1752  *
1753  * Since: 3.0.0
1754  */
1755 gdouble
ags_audio_buffer_util_envelope_complex(AgsComplex * buffer,guint channels,guint buffer_length,gdouble current_volume,gdouble ratio)1756 ags_audio_buffer_util_envelope_complex(AgsComplex *buffer, guint channels,
1757 				       guint buffer_length,
1758 				       gdouble current_volume,
1759 				       gdouble ratio)
1760 {
1761   gdouble start_volume;
1762   guint limit;
1763   guint current_channel;
1764   guint i;
1765 
1766   if(buffer == NULL){
1767     return(1.0);
1768   }
1769 
1770   start_volume = current_volume;
1771   i = 0;
1772 
1773   //TODO:JK: improve me
1774 
1775   for(; i < buffer_length; i++, current_volume = start_volume + i * ratio){
1776     double complex z;
1777 
1778     z = ags_complex_get(buffer) * current_volume;
1779 
1780     ags_complex_set(buffer,
1781 		    z);
1782 
1783     buffer += channels;
1784   }
1785 
1786   return(current_volume);
1787 }
1788 
1789 /**
1790  * ags_audio_buffer_util_envelope:
1791  * @buffer: the audio buffer
1792  * @channels: number of audio channels
1793  * @format: the format to use
1794  * @buffer_length: the buffer's length
1795  * @current_volume: current volume
1796  * @ratio: the amount to increment
1797  *
1798  * Envelope buffer at @ratio.
1799  *
1800  * Returns: the last volume used
1801  *
1802  * Since: 3.0.0
1803  */
1804 gdouble
ags_audio_buffer_util_envelope(void * buffer,guint channels,guint format,guint buffer_length,gdouble current_volume,gdouble ratio)1805 ags_audio_buffer_util_envelope(void *buffer, guint channels,
1806 			       guint format,
1807 			       guint buffer_length,
1808 			       gdouble current_volume,
1809 			       gdouble ratio)
1810 {
1811   gdouble retval;
1812 
1813   if(buffer == NULL){
1814     return(1.0);
1815   }
1816 
1817   retval = 0.0;
1818 
1819   switch(format){
1820   case AGS_AUDIO_BUFFER_UTIL_S8:
1821     {
1822       retval = ags_audio_buffer_util_envelope_s8((gint8 *) buffer, channels,
1823 						 buffer_length,
1824 						 current_volume,
1825 						 ratio);
1826     }
1827     break;
1828   case AGS_AUDIO_BUFFER_UTIL_S16:
1829     {
1830       retval = ags_audio_buffer_util_envelope_s16((gint16 *) buffer, channels,
1831 						  buffer_length,
1832 						  current_volume,
1833 						  ratio);
1834     }
1835     break;
1836   case AGS_AUDIO_BUFFER_UTIL_S24:
1837     {
1838       retval = ags_audio_buffer_util_envelope_s24((gint32 *) buffer, channels,
1839 						  buffer_length,
1840 						  current_volume,
1841 						  ratio);
1842     }
1843     break;
1844   case AGS_AUDIO_BUFFER_UTIL_S32:
1845     {
1846       retval = ags_audio_buffer_util_envelope_s32((gint32 *) buffer, channels,
1847 						  buffer_length,
1848 						  current_volume,
1849 						  ratio);
1850     }
1851     break;
1852   case AGS_AUDIO_BUFFER_UTIL_S64:
1853     {
1854       retval = ags_audio_buffer_util_envelope_s64((gint64 *) buffer, channels,
1855 						  buffer_length,
1856 						  current_volume,
1857 						  ratio);
1858     }
1859     break;
1860   case AGS_AUDIO_BUFFER_UTIL_FLOAT:
1861     {
1862       retval = ags_audio_buffer_util_envelope_float((gfloat *) buffer, channels,
1863 						    buffer_length,
1864 						    current_volume,
1865 						    ratio);
1866     }
1867     break;
1868   case AGS_AUDIO_BUFFER_UTIL_DOUBLE:
1869     {
1870       retval = ags_audio_buffer_util_envelope_double((gdouble *) buffer, channels,
1871 						     buffer_length,
1872 						     current_volume,
1873 						     ratio);
1874     }
1875     break;
1876   case AGS_AUDIO_BUFFER_UTIL_COMPLEX:
1877     {
1878       retval = ags_audio_buffer_util_envelope_complex((AgsComplex *) buffer, channels,
1879 						      buffer_length,
1880 						      current_volume,
1881 						      ratio);
1882     }
1883     break;
1884   default:
1885     g_warning("ags_audio_buffer_util_envelope() - unknown format");
1886   }
1887 
1888   return(retval);
1889 }
1890 
1891 /**
1892  * ags_audio_buffer_util_volume_s8:
1893  * @buffer: the audio buffer
1894  * @channels: number of audio channels
1895  * @buffer_length: the buffer's length
1896  * @volume: volume
1897  *
1898  * Adjust volume of buffer.
1899  *
1900  * Since: 3.0.0
1901  */
1902 void
ags_audio_buffer_util_volume_s8(gint8 * buffer,guint channels,guint buffer_length,gdouble volume)1903 ags_audio_buffer_util_volume_s8(gint8 *buffer, guint channels,
1904 				guint buffer_length,
1905 				gdouble volume)
1906 {
1907   guint limit;
1908   guint current_channel;
1909   guint i;
1910 
1911   if(buffer == NULL){
1912     return;
1913   }
1914 
1915   i = 0;
1916 
1917 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
1918   /* vectorized function */
1919   if(buffer_length > 8){
1920     limit = buffer_length - (buffer_length % 8);
1921 
1922     for(; i < limit; i += 8){
1923       ags_v8double v_buffer;
1924 
1925       current_channel = 0;
1926 
1927       v_buffer = (ags_v8double) {(gdouble) buffer[0],
1928 				 (gdouble) buffer[(current_channel = channels)],
1929 				 (gdouble) buffer[(current_channel += channels)],
1930 				 (gdouble) buffer[(current_channel += channels)],
1931 				 (gdouble) buffer[(current_channel += channels)],
1932 				 (gdouble) buffer[(current_channel += channels)],
1933 				 (gdouble) buffer[(current_channel += channels)],
1934 				 (gdouble) buffer[(current_channel += channels)]};
1935 
1936       v_buffer *= volume;
1937 
1938       current_channel = 0;
1939 
1940       buffer[0] = (gint8) v_buffer[0];
1941       buffer[(current_channel = channels)] = (gint8) v_buffer[1];
1942       buffer[(current_channel += channels)] = (gint8) v_buffer[2];
1943       buffer[(current_channel += channels)] = (gint8) v_buffer[3];
1944       buffer[(current_channel += channels)] = (gint8) v_buffer[4];
1945       buffer[(current_channel += channels)] = (gint8) v_buffer[5];
1946       buffer[(current_channel += channels)] = (gint8) v_buffer[6];
1947       buffer[(current_channel += channels)] = (gint8) v_buffer[7];
1948 
1949       buffer += (current_channel + channels);
1950     }
1951   }
1952 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
1953   /* vectorized function using accelerate framework */
1954   if(buffer_length > 8){
1955     double v_volume[1];
1956 
1957     v_volume[0] = (double) volume;
1958 
1959     limit = buffer_length - (buffer_length % 8);
1960 
1961     for(; i < limit; i += 8){
1962       double ret_v_buffer[8];
1963 
1964       current_channel = 0;
1965 
1966       double v_buffer[] = {(double) buffer[0],
1967 			   (double) buffer[(current_channel = channels)],
1968 			   (double) buffer[(current_channel += channels)],
1969 			   (double) buffer[(current_channel += channels)],
1970 			   (double) buffer[(current_channel += channels)],
1971 			   (double) buffer[(current_channel += channels)],
1972 			   (double) buffer[(current_channel += channels)],
1973 			   (double) buffer[(current_channel += channels)]};
1974 
1975       vDSP_vmulD(v_buffer, 1, v_volume, 0, ret_v_buffer, 1, 8);
1976 
1977       current_channel = 0;
1978 
1979       buffer[0] = (gint8) ret_v_buffer[0];
1980       buffer[(current_channel = channels)] = (gint8) ret_v_buffer[1];
1981       buffer[(current_channel += channels)] = (gint8) ret_v_buffer[2];
1982       buffer[(current_channel += channels)] = (gint8) ret_v_buffer[3];
1983       buffer[(current_channel += channels)] = (gint8) ret_v_buffer[4];
1984       buffer[(current_channel += channels)] = (gint8) ret_v_buffer[5];
1985       buffer[(current_channel += channels)] = (gint8) ret_v_buffer[6];
1986       buffer[(current_channel += channels)] = (gint8) ret_v_buffer[7];
1987 
1988       buffer += (current_channel + channels);
1989     }
1990   }
1991 #else
1992   /* unrolled function */
1993   if(buffer_length > 8){
1994     limit = buffer_length - (buffer_length % 8);
1995 
1996     for(; i < limit; i += 8){
1997       current_channel = 0;
1998 
1999       buffer[0] = 0xff & ((gint16) (buffer[0] * volume));
2000       buffer[current_channel] = 0xff & ((gint16) (buffer[(current_channel = channels)] * volume));
2001       buffer[current_channel] = 0xff & ((gint16) (buffer[(current_channel += channels)] * volume));
2002       buffer[current_channel] = 0xff & ((gint16) (buffer[(current_channel += channels)] * volume));
2003       buffer[current_channel] = 0xff & ((gint16) (buffer[(current_channel += channels)] * volume));
2004       buffer[current_channel] = 0xff & ((gint16) (buffer[(current_channel += channels)] * volume));
2005       buffer[current_channel] = 0xff & ((gint16) (buffer[(current_channel += channels)] * volume));
2006       buffer[current_channel] = 0xff & ((gint16) (buffer[(current_channel += channels)] * volume));
2007 
2008       buffer += (current_channel + channels);
2009     }
2010   }
2011 #endif
2012 
2013   for(; i < buffer_length; i++){
2014     buffer[0] = 0xff & ((gint16) (buffer[0] * volume));
2015 
2016     buffer += channels;
2017   }
2018 }
2019 
2020 /**
2021  * ags_audio_buffer_util_volume_s16:
2022  * @buffer: the audio buffer
2023  * @channels: number of audio channels
2024  * @buffer_length: the buffer's length
2025  * @volume: volume
2026  *
2027  * Adjust volume of buffer.
2028  *
2029  * Since: 3.0.0
2030  */
2031 void
ags_audio_buffer_util_volume_s16(gint16 * buffer,guint channels,guint buffer_length,gdouble volume)2032 ags_audio_buffer_util_volume_s16(gint16 *buffer, guint channels,
2033 				 guint buffer_length,
2034 				 gdouble volume)
2035 {
2036   guint limit;
2037   guint current_channel;
2038   guint i;
2039 
2040   if(buffer == NULL){
2041     return;
2042   }
2043 
2044   i = 0;
2045 
2046 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
2047   /* vectorized function */
2048   if(buffer_length > 8){
2049     limit = buffer_length - (buffer_length % 8);
2050 
2051     for(; i < limit; i += 8){
2052       ags_v8double v_buffer;
2053 
2054       current_channel = 0;
2055 
2056       v_buffer = (ags_v8double) {(gdouble) buffer[0],
2057 				 (gdouble) buffer[(current_channel = channels)],
2058 				 (gdouble) buffer[(current_channel += channels)],
2059 				 (gdouble) buffer[(current_channel += channels)],
2060 				 (gdouble) buffer[(current_channel += channels)],
2061 				 (gdouble) buffer[(current_channel += channels)],
2062 				 (gdouble) buffer[(current_channel += channels)],
2063 				 (gdouble) buffer[(current_channel += channels)]};
2064 
2065       v_buffer *= volume;
2066 
2067       current_channel = 0;
2068 
2069       buffer[0] = (gint16) v_buffer[0];
2070       buffer[(current_channel = channels)] = (gint16) v_buffer[1];
2071       buffer[(current_channel += channels)] = (gint16) v_buffer[2];
2072       buffer[(current_channel += channels)] = (gint16) v_buffer[3];
2073       buffer[(current_channel += channels)] = (gint16) v_buffer[4];
2074       buffer[(current_channel += channels)] = (gint16) v_buffer[5];
2075       buffer[(current_channel += channels)] = (gint16) v_buffer[6];
2076       buffer[(current_channel += channels)] = (gint16) v_buffer[7];
2077 
2078       buffer += (current_channel + channels);
2079     }
2080   }
2081 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
2082   /* vectorized function using accelerate framework */
2083   if(buffer_length > 8){
2084     double v_volume[1];
2085 
2086     v_volume[0] = (double) volume;
2087 
2088     limit = buffer_length - (buffer_length % 8);
2089 
2090     for(; i < limit; i += 8){
2091       double ret_v_buffer[8];
2092 
2093       current_channel = 0;
2094 
2095       double v_buffer[] = {(double) buffer[0],
2096 			   (double) buffer[(current_channel = channels)],
2097 			   (double) buffer[(current_channel += channels)],
2098 			   (double) buffer[(current_channel += channels)],
2099 			   (double) buffer[(current_channel += channels)],
2100 			   (double) buffer[(current_channel += channels)],
2101 			   (double) buffer[(current_channel += channels)],
2102 			   (double) buffer[(current_channel += channels)]};
2103 
2104       vDSP_vmulD(v_buffer, 1, v_volume, 0, ret_v_buffer, 1, 8);
2105 
2106       current_channel = 0;
2107 
2108       buffer[0] = (gint16) ret_v_buffer[0];
2109       buffer[(current_channel = channels)] = (gint16) ret_v_buffer[1];
2110       buffer[(current_channel += channels)] = (gint16) ret_v_buffer[2];
2111       buffer[(current_channel += channels)] = (gint16) ret_v_buffer[3];
2112       buffer[(current_channel += channels)] = (gint16) ret_v_buffer[4];
2113       buffer[(current_channel += channels)] = (gint16) ret_v_buffer[5];
2114       buffer[(current_channel += channels)] = (gint16) ret_v_buffer[6];
2115       buffer[(current_channel += channels)] = (gint16) ret_v_buffer[7];
2116 
2117       buffer += (current_channel + channels);
2118     }
2119   }
2120 #else
2121   /* unrolled function */
2122   if(buffer_length > 8){
2123     limit = buffer_length - (buffer_length % 8);
2124 
2125     for(; i < limit; i += 8){
2126       current_channel = 0;
2127 
2128       buffer[0] = (gint16) 0xffff & ((gint32) (buffer[0] * volume));
2129       buffer[current_channel] = (gint16) 0xffff & ((gint32) (buffer[(current_channel = channels)] * volume));
2130       buffer[current_channel] = (gint16) 0xffff & ((gint32) (buffer[(current_channel += channels)] * volume));
2131       buffer[current_channel] = (gint16) 0xffff & ((gint32) (buffer[(current_channel += channels)] * volume));
2132       buffer[current_channel] = (gint16) 0xffff & ((gint32) (buffer[(current_channel += channels)] * volume));
2133       buffer[current_channel] = (gint16) 0xffff & ((gint32) (buffer[(current_channel += channels)] * volume));
2134       buffer[current_channel] = (gint16) 0xffff & ((gint32) (buffer[(current_channel += channels)] * volume));
2135       buffer[current_channel] = (gint16) 0xffff & ((gint32) (buffer[(current_channel += channels)] * volume));
2136 
2137       buffer += (current_channel + channels);
2138     }
2139   }
2140 #endif
2141 
2142   for(; i < buffer_length; i++){
2143     buffer[0] = (gint16) 0xffff & ((gint32) (buffer[0] * volume));
2144 
2145     buffer += channels;
2146   }
2147 }
2148 
2149 /**
2150  * ags_audio_buffer_util_volume_s24:
2151  * @buffer: the audio buffer
2152  * @channels: number of audio channels
2153  * @buffer_length: the buffer's length
2154  * @volume: volume
2155  *
2156  * Adjust volume of buffer.
2157  *
2158  * Since: 3.0.0
2159  */
2160 void
ags_audio_buffer_util_volume_s24(gint32 * buffer,guint channels,guint buffer_length,gdouble volume)2161 ags_audio_buffer_util_volume_s24(gint32 *buffer, guint channels,
2162 				 guint buffer_length,
2163 				 gdouble volume)
2164 {
2165   guint limit;
2166   guint current_channel;
2167   guint i;
2168 
2169   if(buffer == NULL){
2170     return;
2171   }
2172 
2173   i = 0;
2174 
2175 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
2176   /* vectorized function */
2177   if(buffer_length > 8){
2178     limit = buffer_length - (buffer_length % 8);
2179 
2180     for(; i < limit; i += 8){
2181       ags_v8double v_buffer;
2182 
2183       current_channel = 0;
2184 
2185       v_buffer = (ags_v8double) {(gdouble) buffer[0],
2186 				 (gdouble) buffer[(current_channel = channels)],
2187 				 (gdouble) buffer[(current_channel += channels)],
2188 				 (gdouble) buffer[(current_channel += channels)],
2189 				 (gdouble) buffer[(current_channel += channels)],
2190 				 (gdouble) buffer[(current_channel += channels)],
2191 				 (gdouble) buffer[(current_channel += channels)],
2192 				 (gdouble) buffer[(current_channel += channels)]};
2193 
2194       v_buffer *= volume;
2195 
2196       current_channel = 0;
2197 
2198       buffer[0] = (gint32) v_buffer[0];
2199       buffer[(current_channel = channels)] = (gint32) v_buffer[1];
2200       buffer[(current_channel += channels)] = (gint32) v_buffer[2];
2201       buffer[(current_channel += channels)] = (gint32) v_buffer[3];
2202       buffer[(current_channel += channels)] = (gint32) v_buffer[4];
2203       buffer[(current_channel += channels)] = (gint32) v_buffer[5];
2204       buffer[(current_channel += channels)] = (gint32) v_buffer[6];
2205       buffer[(current_channel += channels)] = (gint32) v_buffer[7];
2206 
2207       buffer += (current_channel + channels);
2208     }
2209   }
2210 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
2211   /* vectorized function using accelerate framework */
2212   if(buffer_length > 8){
2213     double v_volume[1];
2214 
2215     v_volume[0] = (double) volume;
2216 
2217     limit = buffer_length - (buffer_length % 8);
2218 
2219     for(; i < limit; i += 8){
2220       double ret_v_buffer[8];
2221 
2222       current_channel = 0;
2223 
2224       double v_buffer[] = {(double) buffer[0],
2225 			   (double) buffer[(current_channel = channels)],
2226 			   (double) buffer[(current_channel += channels)],
2227 			   (double) buffer[(current_channel += channels)],
2228 			   (double) buffer[(current_channel += channels)],
2229 			   (double) buffer[(current_channel += channels)],
2230 			   (double) buffer[(current_channel += channels)],
2231 			   (double) buffer[(current_channel += channels)]};
2232 
2233       vDSP_vmulD(v_buffer, 1, v_volume, 0, ret_v_buffer, 1, 8);
2234 
2235       current_channel = 0;
2236 
2237       buffer[0] = (gint32) ret_v_buffer[0];
2238       buffer[(current_channel = channels)] = (gint32) ret_v_buffer[1];
2239       buffer[(current_channel += channels)] = (gint32) ret_v_buffer[2];
2240       buffer[(current_channel += channels)] = (gint32) ret_v_buffer[3];
2241       buffer[(current_channel += channels)] = (gint32) ret_v_buffer[4];
2242       buffer[(current_channel += channels)] = (gint32) ret_v_buffer[5];
2243       buffer[(current_channel += channels)] = (gint32) ret_v_buffer[6];
2244       buffer[(current_channel += channels)] = (gint32) ret_v_buffer[7];
2245 
2246       buffer += (current_channel + channels);
2247     }
2248   }
2249 #else
2250   /* unrolled function */
2251   if(buffer_length > 8){
2252     limit = buffer_length - (buffer_length % 8);
2253 
2254     for(; i < limit; i += 8){
2255       current_channel = 0;
2256 
2257       buffer[0] = 0xffffffff & ((gint32) (buffer[0] * volume));
2258       buffer[current_channel] = 0xffffffff & ((gint32) (buffer[(current_channel = channels)] * volume));
2259       buffer[current_channel] = 0xffffffff & ((gint32) (buffer[(current_channel += channels)] * volume));
2260       buffer[current_channel] = 0xffffffff & ((gint32) (buffer[(current_channel += channels)] * volume));
2261       buffer[current_channel] = 0xffffffff & ((gint32) (buffer[(current_channel += channels)] * volume));
2262       buffer[current_channel] = 0xffffffff & ((gint32) (buffer[(current_channel += channels)] * volume));
2263       buffer[current_channel] = 0xffffffff & ((gint32) (buffer[(current_channel += channels)] * volume));
2264       buffer[current_channel] = 0xffffffff & ((gint32) (buffer[(current_channel += channels)] * volume));
2265 
2266       buffer += (current_channel + channels);
2267     }
2268   }
2269 #endif
2270 
2271   for(; i < buffer_length; i++){
2272     buffer[0] = 0xffffffff & ((gint32) (buffer[0] * volume));
2273 
2274     buffer += channels;
2275   }
2276 }
2277 
2278 /**
2279  * ags_audio_buffer_util_volume_s32:
2280  * @buffer: the audio buffer
2281  * @channels: number of audio channels
2282  * @buffer_length: the buffer's length
2283  * @volume: volume
2284  *
2285  * Adjust volume of buffer.
2286  *
2287  * Since: 3.0.0
2288  */
2289 void
ags_audio_buffer_util_volume_s32(gint32 * buffer,guint channels,guint buffer_length,gdouble volume)2290 ags_audio_buffer_util_volume_s32(gint32 *buffer, guint channels,
2291 				 guint buffer_length,
2292 				 gdouble volume)
2293 {
2294   guint limit;
2295   guint current_channel;
2296   guint i;
2297 
2298   if(buffer == NULL){
2299     return;
2300   }
2301 
2302   i = 0;
2303 
2304 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
2305   /* vectorized function */
2306   if(buffer_length > 8){
2307     limit = buffer_length - (buffer_length % 8);
2308 
2309     for(; i < limit; i += 8){
2310       ags_v8double v_buffer;
2311 
2312       current_channel = 0;
2313 
2314       v_buffer = (ags_v8double) {(gdouble) buffer[0],
2315 				 (gdouble) buffer[(current_channel = channels)],
2316 				 (gdouble) buffer[(current_channel += channels)],
2317 				 (gdouble) buffer[(current_channel += channels)],
2318 				 (gdouble) buffer[(current_channel += channels)],
2319 				 (gdouble) buffer[(current_channel += channels)],
2320 				 (gdouble) buffer[(current_channel += channels)],
2321 				 (gdouble) buffer[(current_channel += channels)]};
2322 
2323       v_buffer *= volume;
2324 
2325       current_channel = 0;
2326 
2327       buffer[0] = (gint32) v_buffer[0];
2328       buffer[(current_channel = channels)] = (gint32) v_buffer[1];
2329       buffer[(current_channel += channels)] = (gint32) v_buffer[2];
2330       buffer[(current_channel += channels)] = (gint32) v_buffer[3];
2331       buffer[(current_channel += channels)] = (gint32) v_buffer[4];
2332       buffer[(current_channel += channels)] = (gint32) v_buffer[5];
2333       buffer[(current_channel += channels)] = (gint32) v_buffer[6];
2334       buffer[(current_channel += channels)] = (gint32) v_buffer[7];
2335 
2336       buffer += (current_channel + channels);
2337     }
2338   }
2339 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
2340   /* vectorized function using accelerate framework */
2341   if(buffer_length > 8){
2342     double v_volume[1];
2343 
2344     v_volume[0] = (double) volume;
2345 
2346     limit = buffer_length - (buffer_length % 8);
2347 
2348     for(; i < limit; i += 8){
2349       double ret_v_buffer[8];
2350 
2351       current_channel = 0;
2352 
2353       double v_buffer[] = {(double) buffer[0],
2354 			   (double) buffer[(current_channel = channels)],
2355 			   (double) buffer[(current_channel += channels)],
2356 			   (double) buffer[(current_channel += channels)],
2357 			   (double) buffer[(current_channel += channels)],
2358 			   (double) buffer[(current_channel += channels)],
2359 			   (double) buffer[(current_channel += channels)],
2360 			   (double) buffer[(current_channel += channels)]};
2361 
2362       vDSP_vmulD(v_buffer, 1, v_volume, 0, ret_v_buffer, 1, 8);
2363 
2364       current_channel = 0;
2365 
2366       buffer[0] = (gint32) ret_v_buffer[0];
2367       buffer[(current_channel = channels)] = (gint32) ret_v_buffer[1];
2368       buffer[(current_channel += channels)] = (gint32) ret_v_buffer[2];
2369       buffer[(current_channel += channels)] = (gint32) ret_v_buffer[3];
2370       buffer[(current_channel += channels)] = (gint32) ret_v_buffer[4];
2371       buffer[(current_channel += channels)] = (gint32) ret_v_buffer[5];
2372       buffer[(current_channel += channels)] = (gint32) ret_v_buffer[6];
2373       buffer[(current_channel += channels)] = (gint32) ret_v_buffer[7];
2374 
2375       buffer += (current_channel + channels);
2376     }
2377   }
2378 #else
2379   /* unrolled function */
2380   if(buffer_length > 8){
2381     limit = buffer_length - (buffer_length % 8);
2382 
2383     for(; i < limit; i += 8){
2384       current_channel = 0;
2385 
2386       buffer[0] = 0xffffffff & ((gint64) (buffer[0] * volume));
2387       buffer[current_channel] = 0xffffffff & ((gint64) (buffer[(current_channel = channels)] * volume));
2388       buffer[current_channel] = 0xffffffff & ((gint64) (buffer[(current_channel += channels)] * volume));
2389       buffer[current_channel] = 0xffffffff & ((gint64) (buffer[(current_channel += channels)] * volume));
2390       buffer[current_channel] = 0xffffffff & ((gint64) (buffer[(current_channel += channels)] * volume));
2391       buffer[current_channel] = 0xffffffff & ((gint64) (buffer[(current_channel += channels)] * volume));
2392       buffer[current_channel] = 0xffffffff & ((gint64) (buffer[(current_channel += channels)] * volume));
2393       buffer[current_channel] = 0xffffffff & ((gint64) (buffer[(current_channel += channels)] * volume));
2394 
2395       buffer += (current_channel + channels);
2396     }
2397   }
2398 #endif
2399 
2400   for(; i < buffer_length; i++){
2401     buffer[0] = 0xffffffff & ((gint64) (buffer[0] * volume));
2402 
2403     buffer += channels;
2404   }
2405 }
2406 
2407 /**
2408  * ags_audio_buffer_util_volume_s64:
2409  * @buffer: the audio buffer
2410  * @channels: number of audio channels
2411  * @buffer_length: the buffer's length
2412  * @volume: volume
2413  *
2414  * Adjust volume of buffer.
2415  *
2416  * Since: 3.0.0
2417  */
2418 void
ags_audio_buffer_util_volume_s64(gint64 * buffer,guint channels,guint buffer_length,gdouble volume)2419 ags_audio_buffer_util_volume_s64(gint64 *buffer, guint channels,
2420 				 guint buffer_length,
2421 				 gdouble volume)
2422 {
2423   guint limit;
2424   guint current_channel;
2425   guint i;
2426 
2427   if(buffer == NULL){
2428     return;
2429   }
2430 
2431   i = 0;
2432 
2433 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
2434   /* vectorized function */
2435   if(buffer_length > 8){
2436     limit = buffer_length - (buffer_length % 8);
2437 
2438     for(; i < limit; i += 8){
2439       ags_v8double v_buffer;
2440 
2441       current_channel = 0;
2442 
2443       v_buffer = (ags_v8double) {(gdouble) buffer[0],
2444 				 (gdouble) buffer[(current_channel = channels)],
2445 				 (gdouble) buffer[(current_channel += channels)],
2446 				 (gdouble) buffer[(current_channel += channels)],
2447 				 (gdouble) buffer[(current_channel += channels)],
2448 				 (gdouble) buffer[(current_channel += channels)],
2449 				 (gdouble) buffer[(current_channel += channels)],
2450 				 (gdouble) buffer[(current_channel += channels)]};
2451 
2452       v_buffer *= volume;
2453 
2454       current_channel = 0;
2455 
2456       buffer[0] = (gint64) v_buffer[0];
2457       buffer[(current_channel = channels)] = (gint64) v_buffer[1];
2458       buffer[(current_channel += channels)] = (gint64) v_buffer[2];
2459       buffer[(current_channel += channels)] = (gint64) v_buffer[3];
2460       buffer[(current_channel += channels)] = (gint64) v_buffer[4];
2461       buffer[(current_channel += channels)] = (gint64) v_buffer[5];
2462       buffer[(current_channel += channels)] = (gint64) v_buffer[6];
2463       buffer[(current_channel += channels)] = (gint64) v_buffer[7];
2464 
2465       buffer += (current_channel + channels);
2466     }
2467   }
2468 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
2469   /* vectorized function using accelerate framework */
2470   if(buffer_length > 8){
2471     double v_volume[1];
2472 
2473     v_volume[0] = (double) volume;
2474 
2475     limit = buffer_length - (buffer_length % 8);
2476 
2477     for(; i < limit; i += 8){
2478       double ret_v_buffer[8];
2479 
2480       current_channel = 0;
2481 
2482       double v_buffer[] = {(double) buffer[0],
2483 			   (double) buffer[(current_channel = channels)],
2484 			   (double) buffer[(current_channel += channels)],
2485 			   (double) buffer[(current_channel += channels)],
2486 			   (double) buffer[(current_channel += channels)],
2487 			   (double) buffer[(current_channel += channels)],
2488 			   (double) buffer[(current_channel += channels)],
2489 			   (double) buffer[(current_channel += channels)]};
2490 
2491       vDSP_vmulD(v_buffer, 1, v_volume, 0, ret_v_buffer, 1, 8);
2492 
2493       current_channel = 0;
2494 
2495       buffer[0] = (gint64) ret_v_buffer[0];
2496       buffer[(current_channel = channels)] = (gint64) ret_v_buffer[1];
2497       buffer[(current_channel += channels)] = (gint64) ret_v_buffer[2];
2498       buffer[(current_channel += channels)] = (gint64) ret_v_buffer[3];
2499       buffer[(current_channel += channels)] = (gint64) ret_v_buffer[4];
2500       buffer[(current_channel += channels)] = (gint64) ret_v_buffer[5];
2501       buffer[(current_channel += channels)] = (gint64) ret_v_buffer[6];
2502       buffer[(current_channel += channels)] = (gint64) ret_v_buffer[7];
2503 
2504       buffer += (current_channel + channels);
2505     }
2506   }
2507 #else
2508   /* unrolled function */
2509   if(buffer_length > 8){
2510     limit = buffer_length - (buffer_length % 8);
2511 
2512     for(; i < limit; i += 8){
2513       current_channel = 0;
2514 
2515       buffer[0] = 0xffffffffffffffff & ((gint64) (buffer[0] * volume));
2516       buffer[current_channel] = 0xffffffffffffffff & ((gint64) (buffer[(current_channel = channels)] * volume));
2517       buffer[current_channel] = 0xffffffffffffffff & ((gint64) (buffer[(current_channel += channels)] * volume));
2518       buffer[current_channel] = 0xffffffffffffffff & ((gint64) (buffer[(current_channel += channels)] * volume));
2519       buffer[current_channel] = 0xffffffffffffffff & ((gint64) (buffer[(current_channel += channels)] * volume));
2520       buffer[current_channel] = 0xffffffffffffffff & ((gint64) (buffer[(current_channel += channels)] * volume));
2521       buffer[current_channel] = 0xffffffffffffffff & ((gint64) (buffer[(current_channel += channels)] * volume));
2522       buffer[current_channel] = 0xffffffffffffffff & ((gint64) (buffer[(current_channel += channels)] * volume));
2523 
2524       buffer += (current_channel + channels);
2525     }
2526   }
2527 #endif
2528 
2529   for(; i < buffer_length; i++){
2530     buffer[0] = 0xffffffffffffffff & ((gint64) (buffer[0] * volume));
2531 
2532     buffer += channels;
2533   }
2534 }
2535 
2536 /**
2537  * ags_audio_buffer_util_volume_float:
2538  * @buffer: the audio buffer
2539  * @channels: number of audio channels
2540  * @buffer_length: the buffer's length
2541  * @volume: volume
2542  *
2543  * Adjust volume of buffer.
2544  *
2545  * Since: 3.0.0
2546  */
2547 void
ags_audio_buffer_util_volume_float(gfloat * buffer,guint channels,guint buffer_length,gdouble volume)2548 ags_audio_buffer_util_volume_float(gfloat *buffer, guint channels,
2549 				   guint buffer_length,
2550 				   gdouble volume)
2551 {
2552   guint limit;
2553   guint current_channel;
2554   guint i;
2555 
2556   if(buffer == NULL){
2557     return;
2558   }
2559 
2560   i = 0;
2561 
2562 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
2563   /* vectorized function */
2564   if(buffer_length > 8){
2565     limit = buffer_length - (buffer_length % 8);
2566 
2567     for(; i < limit; i += 8){
2568       ags_v8double v_buffer;
2569 
2570       current_channel = 0;
2571 
2572       v_buffer = (ags_v8double) {(gdouble) buffer[0],
2573 				 (gdouble) buffer[(current_channel = channels)],
2574 				 (gdouble) buffer[(current_channel += channels)],
2575 				 (gdouble) buffer[(current_channel += channels)],
2576 				 (gdouble) buffer[(current_channel += channels)],
2577 				 (gdouble) buffer[(current_channel += channels)],
2578 				 (gdouble) buffer[(current_channel += channels)],
2579 				 (gdouble) buffer[(current_channel += channels)]};
2580 
2581       v_buffer *= volume;
2582 
2583       current_channel = 0;
2584 
2585       buffer[0] = (gfloat) v_buffer[0];
2586       buffer[(current_channel = channels)] = (gfloat) v_buffer[1];
2587       buffer[(current_channel += channels)] = (gfloat) v_buffer[2];
2588       buffer[(current_channel += channels)] = (gfloat) v_buffer[3];
2589       buffer[(current_channel += channels)] = (gfloat) v_buffer[4];
2590       buffer[(current_channel += channels)] = (gfloat) v_buffer[5];
2591       buffer[(current_channel += channels)] = (gfloat) v_buffer[6];
2592       buffer[(current_channel += channels)] = (gfloat) v_buffer[7];
2593 
2594       buffer += (current_channel + channels);
2595     }
2596   }
2597 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
2598   /* vectorized function using accelerate framework */
2599   if(buffer_length > 8){
2600     double v_volume[1];
2601 
2602     v_volume[0] = (double) volume;
2603 
2604     limit = buffer_length - (buffer_length % 8);
2605 
2606     for(; i < limit; i += 8){
2607       double ret_v_buffer[8];
2608 
2609       current_channel = 0;
2610 
2611       double v_buffer[] = {(double) buffer[0],
2612 			   (double) buffer[(current_channel = channels)],
2613 			   (double) buffer[(current_channel += channels)],
2614 			   (double) buffer[(current_channel += channels)],
2615 			   (double) buffer[(current_channel += channels)],
2616 			   (double) buffer[(current_channel += channels)],
2617 			   (double) buffer[(current_channel += channels)],
2618 			   (double) buffer[(current_channel += channels)]};
2619 
2620       vDSP_vmulD(v_buffer, 1, v_volume, 0, ret_v_buffer, 1, 8);
2621 
2622       current_channel = 0;
2623 
2624       buffer[0] = (gfloat) ret_v_buffer[0];
2625       buffer[(current_channel = channels)] = (gfloat) ret_v_buffer[1];
2626       buffer[(current_channel += channels)] = (gfloat) ret_v_buffer[2];
2627       buffer[(current_channel += channels)] = (gfloat) ret_v_buffer[3];
2628       buffer[(current_channel += channels)] = (gfloat) ret_v_buffer[4];
2629       buffer[(current_channel += channels)] = (gfloat) ret_v_buffer[5];
2630       buffer[(current_channel += channels)] = (gfloat) ret_v_buffer[6];
2631       buffer[(current_channel += channels)] = (gfloat) ret_v_buffer[7];
2632 
2633       buffer += (current_channel + channels);
2634     }
2635   }
2636 #else
2637   /* unrolled function */
2638   if(buffer_length > 8){
2639     limit = buffer_length - (buffer_length % 8);
2640 
2641     for(; i < limit; i += 8){
2642       current_channel = 0;
2643 
2644       buffer[0] = ((gdouble) (buffer[0] * volume));
2645       buffer[current_channel] = ((gdouble) (buffer[(current_channel = channels)] * volume));
2646       buffer[current_channel] = ((gdouble) (buffer[(current_channel += channels)] * volume));
2647       buffer[current_channel] = ((gdouble) (buffer[(current_channel += channels)] * volume));
2648       buffer[current_channel] = ((gdouble) (buffer[(current_channel += channels)] * volume));
2649       buffer[current_channel] = ((gdouble) (buffer[(current_channel += channels)] * volume));
2650       buffer[current_channel] = ((gdouble) (buffer[(current_channel += channels)] * volume));
2651       buffer[current_channel] = ((gdouble) (buffer[(current_channel += channels)] * volume));
2652 
2653       buffer += (current_channel + channels);
2654     }
2655   }
2656 #endif
2657 
2658   for(; i < buffer_length; i++){
2659     buffer[0] = ((gdouble) (buffer[0] * volume));
2660 
2661     buffer += channels;
2662   }
2663 }
2664 
2665 /**
2666  * ags_audio_buffer_util_volume_double:
2667  * @buffer: the audio buffer
2668  * @channels: number of audio channels
2669  * @buffer_length: the buffer's length
2670  * @volume: volume
2671  *
2672  * Adjust volume of buffer.
2673  *
2674  * Since: 3.0.0
2675  */
2676 void
ags_audio_buffer_util_volume_double(gdouble * buffer,guint channels,guint buffer_length,gdouble volume)2677 ags_audio_buffer_util_volume_double(gdouble *buffer, guint channels,
2678 				    guint buffer_length,
2679 				    gdouble volume)
2680 {
2681   guint limit;
2682   guint current_channel;
2683   guint i;
2684 
2685   if(buffer == NULL){
2686     return;
2687   }
2688 
2689   i = 0;
2690 
2691 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
2692   /* vectorized function */
2693   if(buffer_length > 8){
2694     limit = buffer_length - (buffer_length % 8);
2695 
2696     for(; i < limit; i += 8){
2697       ags_v8double v_buffer;
2698 
2699       current_channel = 0;
2700 
2701       v_buffer = (ags_v8double) {(gdouble) buffer[0],
2702 				 (gdouble) buffer[(current_channel = channels)],
2703 				 (gdouble) buffer[(current_channel += channels)],
2704 				 (gdouble) buffer[(current_channel += channels)],
2705 				 (gdouble) buffer[(current_channel += channels)],
2706 				 (gdouble) buffer[(current_channel += channels)],
2707 				 (gdouble) buffer[(current_channel += channels)],
2708 				 (gdouble) buffer[(current_channel += channels)]};
2709 
2710       v_buffer *= volume;
2711 
2712       current_channel = 0;
2713 
2714       buffer[0] = (gdouble) v_buffer[0];
2715       buffer[(current_channel = channels)] = (gdouble) v_buffer[1];
2716       buffer[(current_channel += channels)] = (gdouble) v_buffer[2];
2717       buffer[(current_channel += channels)] = (gdouble) v_buffer[3];
2718       buffer[(current_channel += channels)] = (gdouble) v_buffer[4];
2719       buffer[(current_channel += channels)] = (gdouble) v_buffer[5];
2720       buffer[(current_channel += channels)] = (gdouble) v_buffer[6];
2721       buffer[(current_channel += channels)] = (gdouble) v_buffer[7];
2722 
2723       buffer += (current_channel + channels);
2724     }
2725   }
2726 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
2727   /* vectorized function using accelerate framework */
2728   if(buffer_length > 8){
2729     double v_volume[1];
2730 
2731     v_volume[0] = (double) volume;
2732 
2733     limit = buffer_length - (buffer_length % 8);
2734 
2735     for(; i < limit; i += 8){
2736       double ret_v_buffer[8];
2737 
2738       current_channel = 0;
2739 
2740       double v_buffer[] = {(double) buffer[0],
2741 			   (double) buffer[(current_channel = channels)],
2742 			   (double) buffer[(current_channel += channels)],
2743 			   (double) buffer[(current_channel += channels)],
2744 			   (double) buffer[(current_channel += channels)],
2745 			   (double) buffer[(current_channel += channels)],
2746 			   (double) buffer[(current_channel += channels)],
2747 			   (double) buffer[(current_channel += channels)]};
2748 
2749       vDSP_vmulD(v_buffer, 1, v_volume, 0, ret_v_buffer, 1, 8);
2750 
2751       current_channel = 0;
2752 
2753       buffer[0] = (gdouble) ret_v_buffer[0];
2754       buffer[(current_channel = channels)] = (gdouble) ret_v_buffer[1];
2755       buffer[(current_channel += channels)] = (gdouble) ret_v_buffer[2];
2756       buffer[(current_channel += channels)] = (gdouble) ret_v_buffer[3];
2757       buffer[(current_channel += channels)] = (gdouble) ret_v_buffer[4];
2758       buffer[(current_channel += channels)] = (gdouble) ret_v_buffer[5];
2759       buffer[(current_channel += channels)] = (gdouble) ret_v_buffer[6];
2760       buffer[(current_channel += channels)] = (gdouble) ret_v_buffer[7];
2761 
2762       buffer += (current_channel + channels);
2763     }
2764   }
2765 #else
2766   /* unrolled function */
2767   if(buffer_length > 8){
2768     limit = buffer_length - (buffer_length % 8);
2769 
2770     for(; i < limit; i += 8){
2771       current_channel = 0;
2772 
2773       buffer[0] = ((gdouble) (buffer[0] * volume));
2774       buffer[current_channel] = ((gdouble) (buffer[(current_channel = channels)] * volume));
2775       buffer[current_channel] = ((gdouble) (buffer[(current_channel += channels)] * volume));
2776       buffer[current_channel] = ((gdouble) (buffer[(current_channel += channels)] * volume));
2777       buffer[current_channel] = ((gdouble) (buffer[(current_channel += channels)] * volume));
2778       buffer[current_channel] = ((gdouble) (buffer[(current_channel += channels)] * volume));
2779       buffer[current_channel] = ((gdouble) (buffer[(current_channel += channels)] * volume));
2780       buffer[current_channel] = ((gdouble) (buffer[(current_channel += channels)] * volume));
2781 
2782       buffer += (current_channel + channels);
2783     }
2784   }
2785 #endif
2786 
2787   for(; i < buffer_length; i++){
2788     buffer[0] = ((gdouble) (buffer[0] * volume));
2789 
2790     buffer += channels;
2791   }
2792 }
2793 
2794 /**
2795  * ags_audio_buffer_util_volume_complex:
2796  * @buffer: the audio buffer
2797  * @channels: number of audio channels
2798  * @buffer_length: the buffer's length
2799  * @volume: volume
2800  *
2801  * Adjust volume of buffer.
2802  *
2803  * Since: 3.0.0
2804  */
2805 void
ags_audio_buffer_util_volume_complex(AgsComplex * buffer,guint channels,guint buffer_length,gdouble volume)2806 ags_audio_buffer_util_volume_complex(AgsComplex *buffer, guint channels,
2807 				     guint buffer_length,
2808 				     gdouble volume)
2809 {
2810   guint limit;
2811   guint current_channel;
2812   guint i;
2813 
2814   if(buffer == NULL){
2815     return;
2816   }
2817 
2818   i = 0;
2819 
2820   //TODO:JK: improve me
2821 
2822   for(; i < buffer_length; i++){
2823     double _Complex z;
2824 
2825     z = ags_complex_get(buffer) * volume;
2826     ags_complex_set(buffer,
2827 		    z);
2828 
2829     buffer += channels;
2830   }
2831 }
2832 
2833 /**
2834  * ags_audio_buffer_util_volume:
2835  * @buffer: the audio buffer
2836  * @channels: number of audio channels
2837  * @format: the format to use
2838  * @buffer_length: the buffer's length
2839  * @volume: volume
2840  *
2841  * Adjust volume of buffer.
2842  *
2843  * Since: 3.0.0
2844  */
2845 void
ags_audio_buffer_util_volume(void * buffer,guint channels,guint format,guint buffer_length,gdouble volume)2846 ags_audio_buffer_util_volume(void *buffer, guint channels,
2847 			     guint format,
2848 			     guint buffer_length,
2849 			     gdouble volume)
2850 {
2851   if(buffer == NULL){
2852     return;
2853   }
2854 
2855   switch(format){
2856   case AGS_AUDIO_BUFFER_UTIL_S8:
2857     {
2858       ags_audio_buffer_util_volume_s8((gint8 *) buffer, channels,
2859 				      buffer_length,
2860 				      volume);
2861     }
2862     break;
2863   case AGS_AUDIO_BUFFER_UTIL_S16:
2864     {
2865       ags_audio_buffer_util_volume_s16((gint16 *) buffer, channels,
2866 				       buffer_length,
2867 				       volume);
2868     }
2869     break;
2870   case AGS_AUDIO_BUFFER_UTIL_S24:
2871     {
2872       ags_audio_buffer_util_volume_s24((gint32 *) buffer, channels,
2873 				       buffer_length,
2874 				       volume);
2875     }
2876     break;
2877   case AGS_AUDIO_BUFFER_UTIL_S32:
2878     {
2879       ags_audio_buffer_util_volume_s32((gint32 *) buffer, channels,
2880 				       buffer_length,
2881 				       volume);
2882     }
2883     break;
2884   case AGS_AUDIO_BUFFER_UTIL_S64:
2885     {
2886       ags_audio_buffer_util_volume_s64((gint64 *) buffer, channels,
2887 				       buffer_length,
2888 				       volume);
2889     }
2890     break;
2891   case AGS_AUDIO_BUFFER_UTIL_FLOAT:
2892     {
2893       ags_audio_buffer_util_volume_float((gfloat *) buffer, channels,
2894 					 buffer_length,
2895 					 volume);
2896     }
2897     break;
2898   case AGS_AUDIO_BUFFER_UTIL_DOUBLE:
2899     {
2900       ags_audio_buffer_util_volume_double((gdouble *) buffer, channels,
2901 					  buffer_length,
2902 					  volume);
2903     }
2904     break;
2905   case AGS_AUDIO_BUFFER_UTIL_COMPLEX:
2906     {
2907       ags_audio_buffer_util_volume_complex((AgsComplex *) buffer, channels,
2908 					   buffer_length,
2909 					   volume);
2910     }
2911     break;
2912   default:
2913     g_warning("ags_audio_buffer_util_volume() - unknown format");
2914   }
2915 }
2916 
2917 /**
2918  * ags_audio_buffer_util_peak_s8:
2919  * @buffer: the audio buffer
2920  * @channels: number of audio channels
2921  * @buffer_length: the buffer length
2922  * @harmonic_rate: the harmonic rate
2923  * @max_rate: the max rate
2924  * @pressure_factor: the pressure factor
2925  *
2926  * Retrive peak of buffer.
2927  *
2928  * Returns: the peak as gdouble
2929  *
2930  * Since: 3.0.0
2931  */
2932 gdouble
ags_audio_buffer_util_peak_s8(gint8 * buffer,guint channels,guint buffer_length,gdouble harmonic_rate,gdouble max_rate,gdouble pressure_factor)2933 ags_audio_buffer_util_peak_s8(gint8 *buffer, guint channels,
2934 			      guint buffer_length,
2935 			      gdouble harmonic_rate,
2936 			      gdouble max_rate,
2937 			      gdouble pressure_factor)
2938 {
2939   double current_value;
2940   guint limit;
2941   guint current_channel;
2942   guint i;
2943 
2944   if(buffer == NULL){
2945     return(0.0);
2946   }
2947 
2948   /* calculate average value */
2949   current_value = 0.0;
2950 
2951   i = 0;
2952 
2953 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
2954   /* vectorized function */
2955   if(buffer_length > 8){
2956     limit = buffer_length - (buffer_length % 8);
2957 
2958     for(; i < limit; i += 8){
2959       ags_v8double v_buffer;
2960       ags_v8double v_zero;
2961 
2962       current_channel = 0;
2963 
2964       v_buffer = (ags_v8double) {(gdouble) buffer[0],
2965 				 (gdouble) buffer[(current_channel = channels)],
2966 				 (gdouble) buffer[(current_channel += channels)],
2967 				 (gdouble) buffer[(current_channel += channels)],
2968 				 (gdouble) buffer[(current_channel += channels)],
2969 				 (gdouble) buffer[(current_channel += channels)],
2970 				 (gdouble) buffer[(current_channel += channels)],
2971 				 (gdouble) buffer[(current_channel += channels)]};
2972 
2973       v_zero = (ags_v8double) {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
2974 
2975       v_buffer = (1.0 / (gdouble) G_MAXUINT8 * pressure_factor) * v_buffer;
2976 
2977       v_zero = v_buffer == v_zero;
2978 
2979       if(v_zero[0] != 0.0){
2980 	v_buffer[0] = 1.0;
2981       }
2982 
2983       if(v_zero[1] != 0.0){
2984 	v_buffer[1] = 1.0;
2985       }
2986 
2987       if(v_zero[2] != 0.0){
2988 	v_buffer[2] = 1.0;
2989       }
2990 
2991       if(v_zero[3] != 0.0){
2992 	v_buffer[3] = 1.0;
2993       }
2994 
2995       if(v_zero[4] != 0.0){
2996 	v_buffer[4] = 1.0;
2997       }
2998 
2999       if(v_zero[5] != 0.0){
3000 	v_buffer[5] = 1.0;
3001       }
3002 
3003       if(v_zero[6] != 0.0){
3004 	v_buffer[6] = 1.0;
3005       }
3006 
3007       if(v_zero[7] != 0.0){
3008 	v_buffer[7] = 1.0;
3009       }
3010 
3011       v_buffer = 1.0 / v_buffer;
3012 
3013       if(v_zero[0] != 0.0){
3014 	v_buffer[0] = 0.0;
3015       }
3016 
3017       if(v_zero[1] != 0.0){
3018 	v_buffer[1] = 0.0;
3019       }
3020 
3021       if(v_zero[2] != 0.0){
3022 	v_buffer[2] = 0.0;
3023       }
3024 
3025       if(v_zero[3] != 0.0){
3026 	v_buffer[3] = 0.0;
3027       }
3028 
3029       if(v_zero[4] != 0.0){
3030 	v_buffer[4] = 0.0;
3031       }
3032 
3033       if(v_zero[5] != 0.0){
3034 	v_buffer[5] = 0.0;
3035       }
3036 
3037       if(v_zero[6] != 0.0){
3038 	v_buffer[6] = 0.0;
3039       }
3040 
3041       if(v_zero[7] != 0.0){
3042 	v_buffer[7] = 0.0;
3043       }
3044 
3045       current_value += v_buffer[0] + v_buffer[1] + v_buffer[2] + v_buffer[3] + v_buffer[4] + v_buffer[5] + v_buffer[6] + v_buffer[7];
3046 
3047       buffer += (current_channel + channels);
3048     }
3049   }
3050 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
3051   /* vectorized function */
3052   if(buffer_length > 8){
3053     limit = buffer_length - (buffer_length % 8);
3054 
3055     for(; i < limit; i += 8){
3056       double ret_v_buffer[8];
3057       gboolean v_zero[8];
3058       double v_result[8];
3059       double v_factor[1];
3060 
3061       static const double v_one[] = { 1.0 };
3062 
3063       current_channel = 0;
3064 
3065       double v_buffer[] = {(double) buffer[0],
3066 			   (double) buffer[(current_channel = channels)],
3067 			   (double) buffer[(current_channel += channels)],
3068 			   (double) buffer[(current_channel += channels)],
3069 			   (double) buffer[(current_channel += channels)],
3070 			   (double) buffer[(current_channel += channels)],
3071 			   (double) buffer[(current_channel += channels)],
3072 			   (double) buffer[(current_channel += channels)]};
3073 
3074       v_factor[0] = 1.0 / ((double) G_MAXUINT8) * pressure_factor;
3075 
3076       vDSP_vmulD(v_buffer, 1, v_factor, 0, ret_v_buffer, 1, 8);
3077 
3078       if(ret_v_buffer[0] == 0.0){
3079 	ret_v_buffer[0] = 1.0;
3080 
3081 	v_zero[0] = TRUE;
3082       }
3083 
3084       if(ret_v_buffer[1] == 0.0){
3085 	ret_v_buffer[1] = 1.0;
3086 
3087 	v_zero[1] = TRUE;
3088       }
3089 
3090       if(ret_v_buffer[2] == 0.0){
3091 	ret_v_buffer[2] = 1.0;
3092 
3093 	v_zero[2] = TRUE;
3094       }
3095 
3096       if(ret_v_buffer[3] == 0.0){
3097 	ret_v_buffer[3] = 1.0;
3098 
3099 	v_zero[3] = TRUE;
3100       }
3101 
3102       if(ret_v_buffer[4] == 0.0){
3103 	ret_v_buffer[4] = 1.0;
3104 
3105 	v_zero[4] = TRUE;
3106       }
3107 
3108       if(ret_v_buffer[5] == 0.0){
3109 	ret_v_buffer[5] = 1.0;
3110 
3111 	v_zero[5] = TRUE;
3112       }
3113 
3114       if(ret_v_buffer[6] == 0.0){
3115 	ret_v_buffer[6] = 1.0;
3116 
3117 	v_zero[6] = TRUE;
3118       }
3119 
3120       if(ret_v_buffer[7] == 0.0){
3121 	ret_v_buffer[7] = 1.0;
3122 
3123 	v_zero[7] = TRUE;
3124       }
3125 
3126       vDSP_vdiv(v_one, 0, ret_v_buffer, 1, v_result, 1, 8);
3127 
3128       if(v_zero[0]){
3129 	v_result[0] = 0.0;
3130       }
3131 
3132       if(v_zero[1]){
3133 	v_result[1] = 0.0;
3134       }
3135 
3136       if(v_zero[2]){
3137 	v_result[2] = 0.0;
3138       }
3139 
3140       if(v_zero[3]){
3141 	v_result[3] = 0.0;
3142       }
3143 
3144       if(v_zero[4]){
3145 	v_result[4] = 0.0;
3146       }
3147 
3148       if(v_zero[5]){
3149 	v_result[5] = 0.0;
3150       }
3151 
3152       if(v_zero[6]){
3153 	v_result[6] = 0.0;
3154       }
3155 
3156       if(v_zero[7]){
3157 	v_result[7] = 0.0;
3158       }
3159 
3160       current_value += v_result[0] + v_result[1] + v_result[2] + v_result[3] + v_result[4] + v_result[5] + v_result[6] + v_result[7];
3161 
3162       buffer += (current_channel + channels);
3163     }
3164   }
3165 #else
3166   /* unrolled function */
3167   if(buffer_length > 0){
3168     limit = buffer_length - (buffer_length % 8);
3169 
3170     for(; i < limit; i += 8){
3171       current_channel = 0;
3172 
3173       if(buffer[0] != 0){
3174 	current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT8 * pressure_factor) * buffer[0]));
3175       }
3176 
3177       if(buffer[(current_channel = channels)] != 0){
3178 	current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT8 * pressure_factor) * buffer[current_channel]));
3179       }
3180 
3181       if(buffer[(current_channel += channels)] != 0){
3182 	current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT8 * pressure_factor) * buffer[current_channel]));
3183       }
3184 
3185       if(buffer[(current_channel += channels)] != 0){
3186 	current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT8 * pressure_factor) * buffer[current_channel]));
3187       }
3188 
3189       if(buffer[(current_channel += channels)] != 0){
3190 	current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT8 * pressure_factor) * buffer[current_channel]));
3191       }
3192 
3193       if(buffer[(current_channel += channels)] != 0){
3194 	current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT8 * pressure_factor) * buffer[current_channel]));
3195       }
3196 
3197       if(buffer[(current_channel += channels)] != 0){
3198 	current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT8 * pressure_factor) * buffer[current_channel]));
3199       }
3200 
3201       if(buffer[(current_channel += channels)] != 0){
3202 	current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT8 * pressure_factor) * buffer[current_channel]));
3203       }
3204 
3205       buffer += (current_channel + channels);
3206     }
3207   }
3208 #endif
3209 
3210   for(; i < buffer_length; i++){
3211     if(buffer[0] != 0){
3212       current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT8 * pressure_factor) * buffer[0]));
3213     }
3214 
3215     buffer += channels;
3216   }
3217 
3218   if(current_value != 0.0){
3219     current_value = (atan(1.0 / harmonic_rate) / sin(current_value / max_rate));
3220   }
3221 
3222   return(current_value);
3223 }
3224 
3225 /**
3226  * ags_audio_buffer_util_peak_s16:
3227  * @buffer: the audio buffer
3228  * @channels: number of audio channels
3229  * @buffer_length: the buffer length
3230  * @harmonic_rate: the harmonic rate
3231  * @max_rate: the max rate
3232  * @pressure_factor: the pressure factor
3233  *
3234  * Retrive peak of buffer.
3235  *
3236  * Returns: the peak as gdouble
3237  *
3238  * Since: 3.0.0
3239  */
3240 gdouble
ags_audio_buffer_util_peak_s16(gint16 * buffer,guint channels,guint buffer_length,gdouble harmonic_rate,gdouble max_rate,gdouble pressure_factor)3241 ags_audio_buffer_util_peak_s16(gint16 *buffer, guint channels,
3242 			       guint buffer_length,
3243 			       gdouble harmonic_rate,
3244 			       gdouble max_rate,
3245 			       gdouble pressure_factor)
3246 {
3247   double current_value;
3248   guint limit;
3249   guint current_channel;
3250   guint i;
3251 
3252   if(buffer == NULL){
3253     return(0.0);
3254   }
3255 
3256   /* calculate average value */
3257   current_value = 0.0;
3258 
3259   i = 0;
3260 
3261 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
3262   /* vectorized function */
3263   if(buffer_length > 8){
3264     limit = buffer_length - (buffer_length % 8);
3265 
3266     for(; i < limit; i += 8){
3267       ags_v8double v_buffer;
3268       ags_v8double v_zero;
3269 
3270       current_channel = 0;
3271 
3272       v_buffer = (ags_v8double) {(gdouble) buffer[0],
3273 				 (gdouble) buffer[(current_channel = channels)],
3274 				 (gdouble) buffer[(current_channel += channels)],
3275 				 (gdouble) buffer[(current_channel += channels)],
3276 				 (gdouble) buffer[(current_channel += channels)],
3277 				 (gdouble) buffer[(current_channel += channels)],
3278 				 (gdouble) buffer[(current_channel += channels)],
3279 				 (gdouble) buffer[(current_channel += channels)]};
3280 
3281       v_zero = (ags_v8double) {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
3282 
3283       v_buffer = (1.0 / (gdouble) G_MAXUINT16 * pressure_factor) * v_buffer;
3284 
3285       v_zero = v_buffer == v_zero;
3286 
3287       if(v_zero[0] != 0.0){
3288 	v_buffer[0] = 1.0;
3289       }
3290 
3291       if(v_zero[1] != 0.0){
3292 	v_buffer[1] = 1.0;
3293       }
3294 
3295       if(v_zero[2] != 0.0){
3296 	v_buffer[2] = 1.0;
3297       }
3298 
3299       if(v_zero[3] != 0.0){
3300 	v_buffer[3] = 1.0;
3301       }
3302 
3303       if(v_zero[4] != 0.0){
3304 	v_buffer[4] = 1.0;
3305       }
3306 
3307       if(v_zero[5] != 0.0){
3308 	v_buffer[5] = 1.0;
3309       }
3310 
3311       if(v_zero[6] != 0.0){
3312 	v_buffer[6] = 1.0;
3313       }
3314 
3315       if(v_zero[7] != 0.0){
3316 	v_buffer[7] = 1.0;
3317       }
3318 
3319       v_buffer = 1.0 / v_buffer;
3320 
3321       if(v_zero[0] != 0.0){
3322 	v_buffer[0] = 0.0;
3323       }
3324 
3325       if(v_zero[1] != 0.0){
3326 	v_buffer[1] = 0.0;
3327       }
3328 
3329       if(v_zero[2] != 0.0){
3330 	v_buffer[2] = 0.0;
3331       }
3332 
3333       if(v_zero[3] != 0.0){
3334 	v_buffer[3] = 0.0;
3335       }
3336 
3337       if(v_zero[4] != 0.0){
3338 	v_buffer[4] = 0.0;
3339       }
3340 
3341       if(v_zero[5] != 0.0){
3342 	v_buffer[5] = 0.0;
3343       }
3344 
3345       if(v_zero[6] != 0.0){
3346 	v_buffer[6] = 0.0;
3347       }
3348 
3349       if(v_zero[7] != 0.0){
3350 	v_buffer[7] = 0.0;
3351       }
3352 
3353       current_value += v_buffer[0] + v_buffer[1] + v_buffer[2] + v_buffer[3] + v_buffer[4] + v_buffer[5] + v_buffer[6] + v_buffer[7];
3354 
3355       buffer += (current_channel + channels);
3356     }
3357   }
3358 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
3359   /* vectorized function */
3360   if(buffer_length > 8){
3361     limit = buffer_length - (buffer_length % 8);
3362 
3363     for(; i < limit; i += 8){
3364       double ret_v_buffer[8];
3365       gboolean v_zero[8];
3366       double v_result[8];
3367       double v_factor[1];
3368 
3369       static const double v_one[] = { 1.0 };
3370 
3371       current_channel = 0;
3372 
3373       double v_buffer[] = {(double) buffer[0],
3374 			   (double) buffer[(current_channel = channels)],
3375 			   (double) buffer[(current_channel += channels)],
3376 			   (double) buffer[(current_channel += channels)],
3377 			   (double) buffer[(current_channel += channels)],
3378 			   (double) buffer[(current_channel += channels)],
3379 			   (double) buffer[(current_channel += channels)],
3380 			   (double) buffer[(current_channel += channels)]};
3381 
3382       v_factor[0] = 1.0 / ((double) G_MAXUINT16) * pressure_factor;
3383 
3384       vDSP_vmulD(v_buffer, 1, v_factor, 0, ret_v_buffer, 1, 8);
3385 
3386       if(ret_v_buffer[0] == 0.0){
3387 	ret_v_buffer[0] = 1.0;
3388 
3389 	v_zero[0] = TRUE;
3390       }
3391 
3392       if(ret_v_buffer[1] == 0.0){
3393 	ret_v_buffer[1] = 1.0;
3394 
3395 	v_zero[1] = TRUE;
3396       }
3397 
3398       if(ret_v_buffer[2] == 0.0){
3399 	ret_v_buffer[2] = 1.0;
3400 
3401 	v_zero[2] = TRUE;
3402       }
3403 
3404       if(ret_v_buffer[3] == 0.0){
3405 	ret_v_buffer[3] = 1.0;
3406 
3407 	v_zero[3] = TRUE;
3408       }
3409 
3410       if(ret_v_buffer[4] == 0.0){
3411 	ret_v_buffer[4] = 1.0;
3412 
3413 	v_zero[4] = TRUE;
3414       }
3415 
3416       if(ret_v_buffer[5] == 0.0){
3417 	ret_v_buffer[5] = 1.0;
3418 
3419 	v_zero[5] = TRUE;
3420       }
3421 
3422       if(ret_v_buffer[6] == 0.0){
3423 	ret_v_buffer[6] = 1.0;
3424 
3425 	v_zero[6] = TRUE;
3426       }
3427 
3428       if(ret_v_buffer[7] == 0.0){
3429 	ret_v_buffer[7] = 1.0;
3430 
3431 	v_zero[7] = TRUE;
3432       }
3433 
3434       vDSP_vdiv(v_one, 0, ret_v_buffer, 1, v_result, 1, 8);
3435 
3436       if(v_zero[0]){
3437 	v_result[0] = 0.0;
3438       }
3439 
3440       if(v_zero[1]){
3441 	v_result[1] = 0.0;
3442       }
3443 
3444       if(v_zero[2]){
3445 	v_result[2] = 0.0;
3446       }
3447 
3448       if(v_zero[3]){
3449 	v_result[3] = 0.0;
3450       }
3451 
3452       if(v_zero[4]){
3453 	v_result[4] = 0.0;
3454       }
3455 
3456       if(v_zero[5]){
3457 	v_result[5] = 0.0;
3458       }
3459 
3460       if(v_zero[6]){
3461 	v_result[6] = 0.0;
3462       }
3463 
3464       if(v_zero[7]){
3465 	v_result[7] = 0.0;
3466       }
3467 
3468       current_value += v_result[0] + v_result[1] + v_result[2] + v_result[3] + v_result[4] + v_result[5] + v_result[6] + v_result[7];
3469 
3470       buffer += (current_channel + channels);
3471     }
3472   }
3473 #else
3474   /* unrolled function */
3475   if(buffer_length > 0){
3476     limit = buffer_length - (buffer_length % 8);
3477 
3478     for(; i < limit; i += 8){
3479       current_channel = 0;
3480 
3481       if(buffer[0] != 0){
3482 	current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT16 * pressure_factor) * buffer[0]));
3483       }
3484 
3485       if(buffer[(current_channel = channels)] != 0){
3486 	current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT16 * pressure_factor) * buffer[current_channel]));
3487       }
3488 
3489       if(buffer[(current_channel += channels)] != 0){
3490 	current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT16 * pressure_factor) * buffer[current_channel]));
3491       }
3492 
3493       if(buffer[(current_channel += channels)] != 0){
3494 	current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT16 * pressure_factor) * buffer[current_channel]));
3495       }
3496 
3497       if(buffer[(current_channel += channels)] != 0){
3498 	current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT16 * pressure_factor) * buffer[current_channel]));
3499       }
3500 
3501       if(buffer[(current_channel += channels)] != 0){
3502 	current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT16 * pressure_factor) * buffer[current_channel]));
3503       }
3504 
3505       if(buffer[(current_channel += channels)] != 0){
3506 	current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT16 * pressure_factor) * buffer[current_channel]));
3507       }
3508 
3509       if(buffer[(current_channel += channels)] != 0){
3510 	current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT16 * pressure_factor) * buffer[current_channel]));
3511       }
3512 
3513       buffer += (current_channel + channels);
3514     }
3515   }
3516 #endif
3517 
3518   for(; i < buffer_length; i++){
3519     if(buffer[0] != 0){
3520       current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT16 * pressure_factor) * buffer[0]));
3521     }
3522 
3523     buffer += channels;
3524   }
3525 
3526   if(current_value != 0.0){
3527     current_value = (atan(1.0 / harmonic_rate) / sin(current_value / max_rate));
3528   }
3529 
3530   return(current_value);
3531 }
3532 
3533 /**
3534  * ags_audio_buffer_util_peak_s24:
3535  * @buffer: the audio buffer
3536  * @channels: number of audio channels
3537  * @buffer_length: the buffer length
3538  * @harmonic_rate: the harmonic rate
3539  * @max_rate: the max rate
3540  * @pressure_factor: the pressure factor
3541  *
3542  * Retrive peak of buffer.
3543  *
3544  * Returns: the peak as gdouble
3545  *
3546  * Since: 3.0.0
3547  */
3548 gdouble
ags_audio_buffer_util_peak_s24(gint32 * buffer,guint channels,guint buffer_length,gdouble harmonic_rate,gdouble max_rate,gdouble pressure_factor)3549 ags_audio_buffer_util_peak_s24(gint32 *buffer, guint channels,
3550 			       guint buffer_length,
3551 			       gdouble harmonic_rate,
3552 			       gdouble max_rate,
3553 			       gdouble pressure_factor)
3554 {
3555   double current_value;
3556   guint limit;
3557   guint current_channel;
3558   guint i;
3559 
3560   if(buffer == NULL){
3561     return(0.0);
3562   }
3563 
3564   /* calculate average value */
3565   current_value = 0.0;
3566 
3567   i = 0;
3568 
3569 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
3570   /* vectorized function */
3571   if(buffer_length > 8){
3572     limit = buffer_length - (buffer_length % 8);
3573 
3574     for(; i < limit; i += 8){
3575       ags_v8double v_buffer;
3576       ags_v8double v_zero;
3577 
3578       current_channel = 0;
3579 
3580       v_buffer = (ags_v8double) {(gdouble) buffer[0],
3581 				 (gdouble) buffer[(current_channel = channels)],
3582 				 (gdouble) buffer[(current_channel += channels)],
3583 				 (gdouble) buffer[(current_channel += channels)],
3584 				 (gdouble) buffer[(current_channel += channels)],
3585 				 (gdouble) buffer[(current_channel += channels)],
3586 				 (gdouble) buffer[(current_channel += channels)],
3587 				 (gdouble) buffer[(current_channel += channels)]};
3588 
3589       v_zero = (ags_v8double) {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
3590 
3591       v_buffer = (1.0 / (gdouble) 0xffffffff * pressure_factor) * v_buffer;
3592 
3593       v_zero = v_buffer == v_zero;
3594 
3595       if(v_zero[0] != 0.0){
3596 	v_buffer[0] = 1.0;
3597       }
3598 
3599       if(v_zero[1] != 0.0){
3600 	v_buffer[1] = 1.0;
3601       }
3602 
3603       if(v_zero[2] != 0.0){
3604 	v_buffer[2] = 1.0;
3605       }
3606 
3607       if(v_zero[3] != 0.0){
3608 	v_buffer[3] = 1.0;
3609       }
3610 
3611       if(v_zero[4] != 0.0){
3612 	v_buffer[4] = 1.0;
3613       }
3614 
3615       if(v_zero[5] != 0.0){
3616 	v_buffer[5] = 1.0;
3617       }
3618 
3619       if(v_zero[6] != 0.0){
3620 	v_buffer[6] = 1.0;
3621       }
3622 
3623       if(v_zero[7] != 0.0){
3624 	v_buffer[7] = 1.0;
3625       }
3626 
3627       v_buffer = 1.0 / v_buffer;
3628 
3629       if(v_zero[0] != 0.0){
3630 	v_buffer[0] = 0.0;
3631       }
3632 
3633       if(v_zero[1] != 0.0){
3634 	v_buffer[1] = 0.0;
3635       }
3636 
3637       if(v_zero[2] != 0.0){
3638 	v_buffer[2] = 0.0;
3639       }
3640 
3641       if(v_zero[3] != 0.0){
3642 	v_buffer[3] = 0.0;
3643       }
3644 
3645       if(v_zero[4] != 0.0){
3646 	v_buffer[4] = 0.0;
3647       }
3648 
3649       if(v_zero[5] != 0.0){
3650 	v_buffer[5] = 0.0;
3651       }
3652 
3653       if(v_zero[6] != 0.0){
3654 	v_buffer[6] = 0.0;
3655       }
3656 
3657       if(v_zero[7] != 0.0){
3658 	v_buffer[7] = 0.0;
3659       }
3660 
3661       current_value += v_buffer[0] + v_buffer[1] + v_buffer[2] + v_buffer[3] + v_buffer[4] + v_buffer[5] + v_buffer[6] + v_buffer[7];
3662 
3663       buffer += (current_channel + channels);
3664     }
3665   }
3666 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
3667   /* vectorized function */
3668   if(buffer_length > 8){
3669     limit = buffer_length - (buffer_length % 8);
3670 
3671     for(; i < limit; i += 8){
3672       double ret_v_buffer[8];
3673       gboolean v_zero[8];
3674       double v_result[8];
3675       double v_factor[1];
3676 
3677       static const double v_one[] = { 1.0 };
3678 
3679       current_channel = 0;
3680 
3681       double v_buffer[] = {(double) buffer[0],
3682 			   (double) buffer[(current_channel = channels)],
3683 			   (double) buffer[(current_channel += channels)],
3684 			   (double) buffer[(current_channel += channels)],
3685 			   (double) buffer[(current_channel += channels)],
3686 			   (double) buffer[(current_channel += channels)],
3687 			   (double) buffer[(current_channel += channels)],
3688 			   (double) buffer[(current_channel += channels)]};
3689 
3690       v_factor[0] = 1.0 / ((double) 0xffffffff) * pressure_factor;
3691 
3692       vDSP_vmulD(v_buffer, 1, v_factor, 0, ret_v_buffer, 1, 8);
3693 
3694       if(ret_v_buffer[0] == 0.0){
3695 	ret_v_buffer[0] = 1.0;
3696 
3697 	v_zero[0] = TRUE;
3698       }
3699 
3700       if(ret_v_buffer[1] == 0.0){
3701 	ret_v_buffer[1] = 1.0;
3702 
3703 	v_zero[1] = TRUE;
3704       }
3705 
3706       if(ret_v_buffer[2] == 0.0){
3707 	ret_v_buffer[2] = 1.0;
3708 
3709 	v_zero[2] = TRUE;
3710       }
3711 
3712       if(ret_v_buffer[3] == 0.0){
3713 	ret_v_buffer[3] = 1.0;
3714 
3715 	v_zero[3] = TRUE;
3716       }
3717 
3718       if(ret_v_buffer[4] == 0.0){
3719 	ret_v_buffer[4] = 1.0;
3720 
3721 	v_zero[4] = TRUE;
3722       }
3723 
3724       if(ret_v_buffer[5] == 0.0){
3725 	ret_v_buffer[5] = 1.0;
3726 
3727 	v_zero[5] = TRUE;
3728       }
3729 
3730       if(ret_v_buffer[6] == 0.0){
3731 	ret_v_buffer[6] = 1.0;
3732 
3733 	v_zero[6] = TRUE;
3734       }
3735 
3736       if(ret_v_buffer[7] == 0.0){
3737 	ret_v_buffer[7] = 1.0;
3738 
3739 	v_zero[7] = TRUE;
3740       }
3741 
3742       vDSP_vdiv(v_one, 0, ret_v_buffer, 1, v_result, 1, 8);
3743 
3744       if(v_zero[0]){
3745 	v_result[0] = 0.0;
3746       }
3747 
3748       if(v_zero[1]){
3749 	v_result[1] = 0.0;
3750       }
3751 
3752       if(v_zero[2]){
3753 	v_result[2] = 0.0;
3754       }
3755 
3756       if(v_zero[3]){
3757 	v_result[3] = 0.0;
3758       }
3759 
3760       if(v_zero[4]){
3761 	v_result[4] = 0.0;
3762       }
3763 
3764       if(v_zero[5]){
3765 	v_result[5] = 0.0;
3766       }
3767 
3768       if(v_zero[6]){
3769 	v_result[6] = 0.0;
3770       }
3771 
3772       if(v_zero[7]){
3773 	v_result[7] = 0.0;
3774       }
3775 
3776       current_value += v_result[0] + v_result[1] + v_result[2] + v_result[3] + v_result[4] + v_result[5] + v_result[6] + v_result[7];
3777 
3778       buffer += (current_channel + channels);
3779     }
3780   }
3781 #else
3782   /* unrolled function */
3783   if(buffer_length > 0){
3784     limit = buffer_length - (buffer_length % 8);
3785 
3786     for(; i < limit; i += 8){
3787       current_channel = 0;
3788 
3789       if(buffer[0] != 0){
3790 	current_value += (1.0 / ((1.0 / (gdouble) 0xffffffff * pressure_factor) * buffer[0]));
3791       }
3792 
3793       if(buffer[(current_channel = channels)] != 0){
3794 	current_value += (1.0 / ((1.0 / (gdouble) 0xffffffff * pressure_factor) * buffer[current_channel]));
3795       }
3796 
3797       if(buffer[(current_channel += channels)] != 0){
3798 	current_value += (1.0 / ((1.0 / (gdouble) 0xffffffff * pressure_factor) * buffer[current_channel]));
3799       }
3800 
3801       if(buffer[(current_channel += channels)] != 0){
3802 	current_value += (1.0 / ((1.0 / (gdouble) 0xffffffff * pressure_factor) * buffer[current_channel]));
3803       }
3804 
3805       if(buffer[(current_channel += channels)] != 0){
3806 	current_value += (1.0 / ((1.0 / (gdouble) 0xffffffff * pressure_factor) * buffer[current_channel]));
3807       }
3808 
3809       if(buffer[(current_channel += channels)] != 0){
3810 	current_value += (1.0 / ((1.0 / (gdouble) 0xffffffff * pressure_factor) * buffer[current_channel]));
3811       }
3812 
3813       if(buffer[(current_channel += channels)] != 0){
3814 	current_value += (1.0 / ((1.0 / (gdouble) 0xffffffff * pressure_factor) * buffer[current_channel]));
3815       }
3816 
3817       if(buffer[(current_channel += channels)] != 0){
3818 	current_value += (1.0 / ((1.0 / (gdouble) 0xffffffff * pressure_factor) * buffer[current_channel]));
3819       }
3820 
3821       buffer += (current_channel + channels);
3822     }
3823   }
3824 #endif
3825 
3826   for(; i < buffer_length; i++){
3827     if(buffer[0] != 0){
3828       current_value += (1.0 / ((1.0 / (gdouble) 0xffffffff * pressure_factor) * buffer[0]));
3829     }
3830 
3831     buffer += channels;
3832   }
3833 
3834   if(current_value != 0.0){
3835     current_value = (atan(1.0 / harmonic_rate) / sin(current_value / max_rate));
3836   }
3837 
3838   return(current_value);
3839 }
3840 
3841 /**
3842  * ags_audio_buffer_util_peak_32:
3843  * @buffer: the audio buffer
3844  * @channels: number of audio channels
3845  * @buffer_length: the buffer length
3846  * @harmonic_rate: the harmonic rate
3847  * @max_rate: the max rate
3848  * @pressure_factor: the pressure factor
3849  *
3850  * Retrive peak of buffer.
3851  *
3852  * Returns: the peak as gdouble
3853  *
3854  * Since: 3.0.0
3855  */
3856 gdouble
ags_audio_buffer_util_peak_s32(gint32 * buffer,guint channels,guint buffer_length,gdouble harmonic_rate,gdouble max_rate,gdouble pressure_factor)3857 ags_audio_buffer_util_peak_s32(gint32 *buffer, guint channels,
3858 			       guint buffer_length,
3859 			       gdouble harmonic_rate,
3860 			       gdouble max_rate,
3861 			       gdouble pressure_factor)
3862 {
3863   double current_value;
3864   guint limit;
3865   guint current_channel;
3866   guint i;
3867 
3868   if(buffer == NULL){
3869     return(0.0);
3870   }
3871 
3872   /* calculate average value */
3873   current_value = 0.0;
3874 
3875   i = 0;
3876 
3877 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
3878   /* vectorized function */
3879   if(buffer_length > 8){
3880     limit = buffer_length - (buffer_length % 8);
3881 
3882     for(; i < limit; i += 8){
3883       ags_v8double v_buffer;
3884       ags_v8double v_zero;
3885 
3886       current_channel = 0;
3887 
3888       v_buffer = (ags_v8double) {(gdouble) buffer[0],
3889 				 (gdouble) buffer[(current_channel = channels)],
3890 				 (gdouble) buffer[(current_channel += channels)],
3891 				 (gdouble) buffer[(current_channel += channels)],
3892 				 (gdouble) buffer[(current_channel += channels)],
3893 				 (gdouble) buffer[(current_channel += channels)],
3894 				 (gdouble) buffer[(current_channel += channels)],
3895 				 (gdouble) buffer[(current_channel += channels)]};
3896 
3897       v_zero = (ags_v8double) {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
3898 
3899       v_buffer = (1.0 / (gdouble) G_MAXUINT32 * pressure_factor) * v_buffer;
3900 
3901       v_zero = v_buffer == v_zero;
3902 
3903       if(v_zero[0] != 0.0){
3904 	v_buffer[0] = 1.0;
3905       }
3906 
3907       if(v_zero[1] != 0.0){
3908 	v_buffer[1] = 1.0;
3909       }
3910 
3911       if(v_zero[2] != 0.0){
3912 	v_buffer[2] = 1.0;
3913       }
3914 
3915       if(v_zero[3] != 0.0){
3916 	v_buffer[3] = 1.0;
3917       }
3918 
3919       if(v_zero[4] != 0.0){
3920 	v_buffer[4] = 1.0;
3921       }
3922 
3923       if(v_zero[5] != 0.0){
3924 	v_buffer[5] = 1.0;
3925       }
3926 
3927       if(v_zero[6] != 0.0){
3928 	v_buffer[6] = 1.0;
3929       }
3930 
3931       if(v_zero[7] != 0.0){
3932 	v_buffer[7] = 1.0;
3933       }
3934 
3935       v_buffer = 1.0 / v_buffer;
3936 
3937       if(v_zero[0] != 0.0){
3938 	v_buffer[0] = 0.0;
3939       }
3940 
3941       if(v_zero[1] != 0.0){
3942 	v_buffer[1] = 0.0;
3943       }
3944 
3945       if(v_zero[2] != 0.0){
3946 	v_buffer[2] = 0.0;
3947       }
3948 
3949       if(v_zero[3] != 0.0){
3950 	v_buffer[3] = 0.0;
3951       }
3952 
3953       if(v_zero[4] != 0.0){
3954 	v_buffer[4] = 0.0;
3955       }
3956 
3957       if(v_zero[5] != 0.0){
3958 	v_buffer[5] = 0.0;
3959       }
3960 
3961       if(v_zero[6] != 0.0){
3962 	v_buffer[6] = 0.0;
3963       }
3964 
3965       if(v_zero[7] != 0.0){
3966 	v_buffer[7] = 0.0;
3967       }
3968 
3969       current_value += v_buffer[0] + v_buffer[1] + v_buffer[2] + v_buffer[3] + v_buffer[4] + v_buffer[5] + v_buffer[6] + v_buffer[7];
3970 
3971       buffer += (current_channel + channels);
3972     }
3973   }
3974 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
3975   /* vectorized function */
3976   if(buffer_length > 8){
3977     limit = buffer_length - (buffer_length % 8);
3978 
3979     for(; i < limit; i += 8){
3980       double ret_v_buffer[8];
3981       gboolean v_zero[8];
3982       double v_result[8];
3983       double v_factor[1];
3984 
3985       static const double v_one[] = { 1.0 };
3986 
3987       current_channel = 0;
3988 
3989       double v_buffer[] = {(double) buffer[0],
3990 			   (double) buffer[(current_channel = channels)],
3991 			   (double) buffer[(current_channel += channels)],
3992 			   (double) buffer[(current_channel += channels)],
3993 			   (double) buffer[(current_channel += channels)],
3994 			   (double) buffer[(current_channel += channels)],
3995 			   (double) buffer[(current_channel += channels)],
3996 			   (double) buffer[(current_channel += channels)]};
3997 
3998       v_factor[0] = 1.0 / ((double) G_MAXUINT32) * pressure_factor;
3999 
4000       vDSP_vmulD(v_buffer, 1, v_factor, 0, ret_v_buffer, 1, 8);
4001 
4002       if(ret_v_buffer[0] == 0.0){
4003 	ret_v_buffer[0] = 1.0;
4004 
4005 	v_zero[0] = TRUE;
4006       }
4007 
4008       if(ret_v_buffer[1] == 0.0){
4009 	ret_v_buffer[1] = 1.0;
4010 
4011 	v_zero[1] = TRUE;
4012       }
4013 
4014       if(ret_v_buffer[2] == 0.0){
4015 	ret_v_buffer[2] = 1.0;
4016 
4017 	v_zero[2] = TRUE;
4018       }
4019 
4020       if(ret_v_buffer[3] == 0.0){
4021 	ret_v_buffer[3] = 1.0;
4022 
4023 	v_zero[3] = TRUE;
4024       }
4025 
4026       if(ret_v_buffer[4] == 0.0){
4027 	ret_v_buffer[4] = 1.0;
4028 
4029 	v_zero[4] = TRUE;
4030       }
4031 
4032       if(ret_v_buffer[5] == 0.0){
4033 	ret_v_buffer[5] = 1.0;
4034 
4035 	v_zero[5] = TRUE;
4036       }
4037 
4038       if(ret_v_buffer[6] == 0.0){
4039 	ret_v_buffer[6] = 1.0;
4040 
4041 	v_zero[6] = TRUE;
4042       }
4043 
4044       if(ret_v_buffer[7] == 0.0){
4045 	ret_v_buffer[7] = 1.0;
4046 
4047 	v_zero[7] = TRUE;
4048       }
4049 
4050       vDSP_vdiv(v_one, 0, ret_v_buffer, 1, v_result, 1, 8);
4051 
4052       if(v_zero[0]){
4053 	v_result[0] = 0.0;
4054       }
4055 
4056       if(v_zero[1]){
4057 	v_result[1] = 0.0;
4058       }
4059 
4060       if(v_zero[2]){
4061 	v_result[2] = 0.0;
4062       }
4063 
4064       if(v_zero[3]){
4065 	v_result[3] = 0.0;
4066       }
4067 
4068       if(v_zero[4]){
4069 	v_result[4] = 0.0;
4070       }
4071 
4072       if(v_zero[5]){
4073 	v_result[5] = 0.0;
4074       }
4075 
4076       if(v_zero[6]){
4077 	v_result[6] = 0.0;
4078       }
4079 
4080       if(v_zero[7]){
4081 	v_result[7] = 0.0;
4082       }
4083 
4084       current_value += v_result[0] + v_result[1] + v_result[2] + v_result[3] + v_result[4] + v_result[5] + v_result[6] + v_result[7];
4085 
4086       buffer += (current_channel + channels);
4087     }
4088   }
4089 #else
4090   /* unrolled function */
4091   if(buffer_length > 0){
4092     limit = buffer_length - (buffer_length % 8);
4093 
4094     for(; i < limit; i += 8){
4095       current_channel = 0;
4096 
4097       if(buffer[0] != 0){
4098 	current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT32 * pressure_factor) * buffer[0]));
4099       }
4100 
4101       if(buffer[(current_channel = channels)] != 0){
4102 	current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT32 * pressure_factor) * buffer[current_channel]));
4103       }
4104 
4105       if(buffer[(current_channel += channels)] != 0){
4106 	current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT32 * pressure_factor) * buffer[current_channel]));
4107       }
4108 
4109       if(buffer[(current_channel += channels)] != 0){
4110 	current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT32 * pressure_factor) * buffer[current_channel]));
4111       }
4112 
4113       if(buffer[(current_channel += channels)] != 0){
4114 	current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT32 * pressure_factor) * buffer[current_channel]));
4115       }
4116 
4117       if(buffer[(current_channel += channels)] != 0){
4118 	current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT32 * pressure_factor) * buffer[current_channel]));
4119       }
4120 
4121       if(buffer[(current_channel += channels)] != 0){
4122 	current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT32 * pressure_factor) * buffer[current_channel]));
4123       }
4124 
4125       if(buffer[(current_channel += channels)] != 0){
4126 	current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT32 * pressure_factor) * buffer[current_channel]));
4127       }
4128 
4129       buffer += (current_channel + channels);
4130     }
4131   }
4132 #endif
4133 
4134   for(; i < buffer_length; i++){
4135     if(buffer[0] != 0){
4136       current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT32 * pressure_factor) * buffer[0]));
4137     }
4138 
4139     buffer += channels;
4140   }
4141 
4142   if(current_value != 0.0){
4143     current_value = (atan(1.0 / harmonic_rate) / sin(current_value / max_rate));
4144   }
4145 
4146   return(current_value);
4147 }
4148 
4149 /**
4150  * ags_audio_buffer_util_peak_64:
4151  * @buffer: the audio buffer
4152  * @channels: number of audio channels
4153  * @buffer_length: the buffer length
4154  * @harmonic_rate: the harmonic rate
4155  * @max_rate: the max rate
4156  * @pressure_factor: the pressure factor
4157  *
4158  * Retrive peak of buffer.
4159  *
4160  * Returns: the peak as gdouble
4161  *
4162  * Since: 3.0.0
4163  */
4164 gdouble
ags_audio_buffer_util_peak_s64(gint64 * buffer,guint channels,guint buffer_length,gdouble harmonic_rate,gdouble max_rate,gdouble pressure_factor)4165 ags_audio_buffer_util_peak_s64(gint64 *buffer, guint channels,
4166 			       guint buffer_length,
4167 			       gdouble harmonic_rate,
4168 			       gdouble max_rate,
4169 			       gdouble pressure_factor)
4170 {
4171   double current_value;
4172   guint limit;
4173   guint current_channel;
4174   guint i;
4175 
4176   if(buffer == NULL){
4177     return(0.0);
4178   }
4179 
4180   /* calculate average value */
4181   current_value = 0.0;
4182 
4183   i = 0;
4184 
4185 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
4186   /* vectorized function */
4187   if(buffer_length > 8){
4188     limit = buffer_length - (buffer_length % 8);
4189 
4190     for(; i < limit; i += 8){
4191       ags_v8double v_buffer;
4192       ags_v8double v_zero;
4193 
4194       current_channel = 0;
4195 
4196       v_buffer = (ags_v8double) {(gdouble) buffer[0],
4197 				 (gdouble) buffer[(current_channel = channels)],
4198 				 (gdouble) buffer[(current_channel += channels)],
4199 				 (gdouble) buffer[(current_channel += channels)],
4200 				 (gdouble) buffer[(current_channel += channels)],
4201 				 (gdouble) buffer[(current_channel += channels)],
4202 				 (gdouble) buffer[(current_channel += channels)],
4203 				 (gdouble) buffer[(current_channel += channels)]};
4204 
4205       v_zero = (ags_v8double) {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
4206 
4207       v_buffer = (1.0 / (gdouble) G_MAXUINT64 * pressure_factor) * v_buffer;
4208 
4209       v_zero = v_buffer == v_zero;
4210 
4211       if(v_zero[0] != 0.0){
4212 	v_buffer[0] = 1.0;
4213       }
4214 
4215       if(v_zero[1] != 0.0){
4216 	v_buffer[1] = 1.0;
4217       }
4218 
4219       if(v_zero[2] != 0.0){
4220 	v_buffer[2] = 1.0;
4221       }
4222 
4223       if(v_zero[3] != 0.0){
4224 	v_buffer[3] = 1.0;
4225       }
4226 
4227       if(v_zero[4] != 0.0){
4228 	v_buffer[4] = 1.0;
4229       }
4230 
4231       if(v_zero[5] != 0.0){
4232 	v_buffer[5] = 1.0;
4233       }
4234 
4235       if(v_zero[6] != 0.0){
4236 	v_buffer[6] = 1.0;
4237       }
4238 
4239       if(v_zero[7] != 0.0){
4240 	v_buffer[7] = 1.0;
4241       }
4242 
4243       v_buffer = 1.0 / v_buffer;
4244 
4245       if(v_zero[0] != 0.0){
4246 	v_buffer[0] = 0.0;
4247       }
4248 
4249       if(v_zero[1] != 0.0){
4250 	v_buffer[1] = 0.0;
4251       }
4252 
4253       if(v_zero[2] != 0.0){
4254 	v_buffer[2] = 0.0;
4255       }
4256 
4257       if(v_zero[3] != 0.0){
4258 	v_buffer[3] = 0.0;
4259       }
4260 
4261       if(v_zero[4] != 0.0){
4262 	v_buffer[4] = 0.0;
4263       }
4264 
4265       if(v_zero[5] != 0.0){
4266 	v_buffer[5] = 0.0;
4267       }
4268 
4269       if(v_zero[6] != 0.0){
4270 	v_buffer[6] = 0.0;
4271       }
4272 
4273       if(v_zero[7] != 0.0){
4274 	v_buffer[7] = 0.0;
4275       }
4276 
4277       current_value += v_buffer[0] + v_buffer[1] + v_buffer[2] + v_buffer[3] + v_buffer[4] + v_buffer[5] + v_buffer[6] + v_buffer[7];
4278 
4279       buffer += (current_channel + channels);
4280     }
4281   }
4282 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
4283   /* vectorized function */
4284   if(buffer_length > 8){
4285     limit = buffer_length - (buffer_length % 8);
4286 
4287     for(; i < limit; i += 8){
4288       double ret_v_buffer[8];
4289       gboolean v_zero[8];
4290       double v_result[8];
4291       double v_factor[1];
4292 
4293       static const double v_one[] = { 1.0 };
4294 
4295       current_channel = 0;
4296 
4297       double v_buffer[] = {(double) buffer[0],
4298 			   (double) buffer[(current_channel = channels)],
4299 			   (double) buffer[(current_channel += channels)],
4300 			   (double) buffer[(current_channel += channels)],
4301 			   (double) buffer[(current_channel += channels)],
4302 			   (double) buffer[(current_channel += channels)],
4303 			   (double) buffer[(current_channel += channels)],
4304 			   (double) buffer[(current_channel += channels)]};
4305 
4306       v_factor[0] = 1.0 / ((double) G_MAXUINT64) * pressure_factor;
4307 
4308       vDSP_vmulD(v_buffer, 1, v_factor, 0, ret_v_buffer, 1, 8);
4309 
4310       if(ret_v_buffer[0] == 0.0){
4311 	ret_v_buffer[0] = 1.0;
4312 
4313 	v_zero[0] = TRUE;
4314       }
4315 
4316       if(ret_v_buffer[1] == 0.0){
4317 	ret_v_buffer[1] = 1.0;
4318 
4319 	v_zero[1] = TRUE;
4320       }
4321 
4322       if(ret_v_buffer[2] == 0.0){
4323 	ret_v_buffer[2] = 1.0;
4324 
4325 	v_zero[2] = TRUE;
4326       }
4327 
4328       if(ret_v_buffer[3] == 0.0){
4329 	ret_v_buffer[3] = 1.0;
4330 
4331 	v_zero[3] = TRUE;
4332       }
4333 
4334       if(ret_v_buffer[4] == 0.0){
4335 	ret_v_buffer[4] = 1.0;
4336 
4337 	v_zero[4] = TRUE;
4338       }
4339 
4340       if(ret_v_buffer[5] == 0.0){
4341 	ret_v_buffer[5] = 1.0;
4342 
4343 	v_zero[5] = TRUE;
4344       }
4345 
4346       if(ret_v_buffer[6] == 0.0){
4347 	ret_v_buffer[6] = 1.0;
4348 
4349 	v_zero[6] = TRUE;
4350       }
4351 
4352       if(ret_v_buffer[7] == 0.0){
4353 	ret_v_buffer[7] = 1.0;
4354 
4355 	v_zero[7] = TRUE;
4356       }
4357 
4358       vDSP_vdiv(v_one, 0, ret_v_buffer, 1, v_result, 1, 8);
4359 
4360       if(v_zero[0]){
4361 	v_result[0] = 0.0;
4362       }
4363 
4364       if(v_zero[1]){
4365 	v_result[1] = 0.0;
4366       }
4367 
4368       if(v_zero[2]){
4369 	v_result[2] = 0.0;
4370       }
4371 
4372       if(v_zero[3]){
4373 	v_result[3] = 0.0;
4374       }
4375 
4376       if(v_zero[4]){
4377 	v_result[4] = 0.0;
4378       }
4379 
4380       if(v_zero[5]){
4381 	v_result[5] = 0.0;
4382       }
4383 
4384       if(v_zero[6]){
4385 	v_result[6] = 0.0;
4386       }
4387 
4388       if(v_zero[7]){
4389 	v_result[7] = 0.0;
4390       }
4391 
4392       current_value += v_result[0] + v_result[1] + v_result[2] + v_result[3] + v_result[4] + v_result[5] + v_result[6] + v_result[7];
4393 
4394       buffer += (current_channel + channels);
4395     }
4396   }
4397 #else
4398   /* unrolled function */
4399   if(buffer_length > 0){
4400     limit = buffer_length - (buffer_length % 8);
4401 
4402     for(; i < limit; i += 8){
4403       current_channel = 0;
4404 
4405       if(buffer[0] != 0){
4406 	current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT64 * pressure_factor) * buffer[0]));
4407       }
4408 
4409       if(buffer[(current_channel = channels)] != 0){
4410 	current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT64 * pressure_factor) * buffer[current_channel]));
4411       }
4412 
4413       if(buffer[(current_channel += channels)] != 0){
4414 	current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT64 * pressure_factor) * buffer[current_channel]));
4415       }
4416 
4417       if(buffer[(current_channel += channels)] != 0){
4418 	current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT64 * pressure_factor) * buffer[current_channel]));
4419       }
4420 
4421       if(buffer[(current_channel += channels)] != 0){
4422 	current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT64 * pressure_factor) * buffer[current_channel]));
4423       }
4424 
4425       if(buffer[(current_channel += channels)] != 0){
4426 	current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT64 * pressure_factor) * buffer[current_channel]));
4427       }
4428 
4429       if(buffer[(current_channel += channels)] != 0){
4430 	current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT64 * pressure_factor) * buffer[current_channel]));
4431       }
4432 
4433       if(buffer[(current_channel += channels)] != 0){
4434 	current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT64 * pressure_factor) * buffer[current_channel]));
4435       }
4436 
4437       buffer += (current_channel + channels);
4438     }
4439   }
4440 #endif
4441 
4442   for(; i < buffer_length; i++){
4443     if(buffer[0] != 0){
4444       current_value += (1.0 / ((1.0 / (gdouble) G_MAXUINT64 * pressure_factor) * buffer[0]));
4445     }
4446 
4447     buffer += channels;
4448   }
4449 
4450   if(current_value != 0.0){
4451     current_value = (atan(1.0 / harmonic_rate) / sin(current_value / max_rate));
4452   }
4453 
4454   return(current_value);
4455 }
4456 
4457 /**
4458  * ags_audio_buffer_util_peak_float:
4459  * @buffer: the audio buffer
4460  * @channels: number of audio channels
4461  * @buffer_length: the buffer length
4462  * @harmonic_rate: the harmonic rate
4463  * @max_rate: the max rate
4464  * @pressure_factor: the pressure factor
4465  *
4466  * Retrive peak of buffer.
4467  *
4468  * Returns: the peak as gdouble
4469  *
4470  * Since: 3.0.0
4471  */
4472 gdouble
ags_audio_buffer_util_peak_float(gfloat * buffer,guint channels,guint buffer_length,gdouble harmonic_rate,gdouble max_rate,gdouble pressure_factor)4473 ags_audio_buffer_util_peak_float(gfloat *buffer, guint channels,
4474 				 guint buffer_length,
4475 				 gdouble harmonic_rate,
4476 				 gdouble max_rate,
4477 				 gdouble pressure_factor)
4478 {
4479   double current_value;
4480   guint limit;
4481   guint current_channel;
4482   guint i;
4483 
4484   if(buffer == NULL){
4485     return(0.0);
4486   }
4487 
4488   /* calculate average value */
4489   current_value = 0.0;
4490 
4491   i = 0;
4492 
4493 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
4494   /* vectorized function */
4495   if(buffer_length > 8){
4496     limit = buffer_length - (buffer_length % 8);
4497 
4498     for(; i < limit; i += 8){
4499       ags_v8double v_buffer;
4500       ags_v8double v_zero;
4501 
4502       current_channel = 0;
4503 
4504       v_buffer = (ags_v8double) {(gdouble) buffer[0],
4505 				 (gdouble) buffer[(current_channel = channels)],
4506 				 (gdouble) buffer[(current_channel += channels)],
4507 				 (gdouble) buffer[(current_channel += channels)],
4508 				 (gdouble) buffer[(current_channel += channels)],
4509 				 (gdouble) buffer[(current_channel += channels)],
4510 				 (gdouble) buffer[(current_channel += channels)],
4511 				 (gdouble) buffer[(current_channel += channels)]};
4512 
4513       v_zero = (ags_v8double) {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
4514 
4515       v_buffer = (0.5 * pressure_factor) * v_buffer;
4516 
4517       v_zero = v_buffer == v_zero;
4518 
4519       if(v_zero[0] != 0.0){
4520 	v_buffer[0] = 1.0;
4521       }
4522 
4523       if(v_zero[1] != 0.0){
4524 	v_buffer[1] = 1.0;
4525       }
4526 
4527       if(v_zero[2] != 0.0){
4528 	v_buffer[2] = 1.0;
4529       }
4530 
4531       if(v_zero[3] != 0.0){
4532 	v_buffer[3] = 1.0;
4533       }
4534 
4535       if(v_zero[4] != 0.0){
4536 	v_buffer[4] = 1.0;
4537       }
4538 
4539       if(v_zero[5] != 0.0){
4540 	v_buffer[5] = 1.0;
4541       }
4542 
4543       if(v_zero[6] != 0.0){
4544 	v_buffer[6] = 1.0;
4545       }
4546 
4547       if(v_zero[7] != 0.0){
4548 	v_buffer[7] = 1.0;
4549       }
4550 
4551       v_buffer = 1.0 / v_buffer;
4552 
4553       if(v_zero[0] != 0.0){
4554 	v_buffer[0] = 0.0;
4555       }
4556 
4557       if(v_zero[1] != 0.0){
4558 	v_buffer[1] = 0.0;
4559       }
4560 
4561       if(v_zero[2] != 0.0){
4562 	v_buffer[2] = 0.0;
4563       }
4564 
4565       if(v_zero[3] != 0.0){
4566 	v_buffer[3] = 0.0;
4567       }
4568 
4569       if(v_zero[4] != 0.0){
4570 	v_buffer[4] = 0.0;
4571       }
4572 
4573       if(v_zero[5] != 0.0){
4574 	v_buffer[5] = 0.0;
4575       }
4576 
4577       if(v_zero[6] != 0.0){
4578 	v_buffer[6] = 0.0;
4579       }
4580 
4581       if(v_zero[7] != 0.0){
4582 	v_buffer[7] = 0.0;
4583       }
4584 
4585       current_value += v_buffer[0] + v_buffer[1] + v_buffer[2] + v_buffer[3] + v_buffer[4] + v_buffer[5] + v_buffer[6] + v_buffer[7];
4586 
4587       buffer += (current_channel + channels);
4588     }
4589   }
4590 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
4591   /* vectorized function */
4592   if(buffer_length > 8){
4593     limit = buffer_length - (buffer_length % 8);
4594 
4595     for(; i < limit; i += 8){
4596       gboolean v_zero[8];
4597       double v_result[8];
4598 
4599       static const double v_one[] = { 1.0 };
4600 
4601       current_channel = 0;
4602 
4603       double ret_v_buffer[] = {(double) buffer[0],
4604 			       (double) buffer[(current_channel = channels)],
4605 			       (double) buffer[(current_channel += channels)],
4606 			       (double) buffer[(current_channel += channels)],
4607 			       (double) buffer[(current_channel += channels)],
4608 			       (double) buffer[(current_channel += channels)],
4609 			       (double) buffer[(current_channel += channels)],
4610 			       (double) buffer[(current_channel += channels)]};
4611 
4612       if(ret_v_buffer[0] == 0.0){
4613 	ret_v_buffer[0] = 1.0;
4614 
4615 	v_zero[0] = TRUE;
4616       }
4617 
4618       if(ret_v_buffer[1] == 0.0){
4619 	ret_v_buffer[1] = 1.0;
4620 
4621 	v_zero[1] = TRUE;
4622       }
4623 
4624       if(ret_v_buffer[2] == 0.0){
4625 	ret_v_buffer[2] = 1.0;
4626 
4627 	v_zero[2] = TRUE;
4628       }
4629 
4630       if(ret_v_buffer[3] == 0.0){
4631 	ret_v_buffer[3] = 1.0;
4632 
4633 	v_zero[3] = TRUE;
4634       }
4635 
4636       if(ret_v_buffer[4] == 0.0){
4637 	ret_v_buffer[4] = 1.0;
4638 
4639 	v_zero[4] = TRUE;
4640       }
4641 
4642       if(ret_v_buffer[5] == 0.0){
4643 	ret_v_buffer[5] = 1.0;
4644 
4645 	v_zero[5] = TRUE;
4646       }
4647 
4648       if(ret_v_buffer[6] == 0.0){
4649 	ret_v_buffer[6] = 1.0;
4650 
4651 	v_zero[6] = TRUE;
4652       }
4653 
4654       if(ret_v_buffer[7] == 0.0){
4655 	ret_v_buffer[7] = 1.0;
4656 
4657 	v_zero[7] = TRUE;
4658       }
4659 
4660       vDSP_vdiv(v_one, 0, ret_v_buffer, 1, v_result, 1, 8);
4661 
4662       if(v_zero[0]){
4663 	v_result[0] = 0.0;
4664       }
4665 
4666       if(v_zero[1]){
4667 	v_result[1] = 0.0;
4668       }
4669 
4670       if(v_zero[2]){
4671 	v_result[2] = 0.0;
4672       }
4673 
4674       if(v_zero[3]){
4675 	v_result[3] = 0.0;
4676       }
4677 
4678       if(v_zero[4]){
4679 	v_result[4] = 0.0;
4680       }
4681 
4682       if(v_zero[5]){
4683 	v_result[5] = 0.0;
4684       }
4685 
4686       if(v_zero[6]){
4687 	v_result[6] = 0.0;
4688       }
4689 
4690       if(v_zero[7]){
4691 	v_result[7] = 0.0;
4692       }
4693 
4694       current_value += v_result[0] + v_result[1] + v_result[2] + v_result[3] + v_result[4] + v_result[5] + v_result[6] + v_result[7];
4695 
4696       buffer += (current_channel + channels);
4697     }
4698   }
4699 #else
4700   /* unrolled function */
4701   if(buffer_length > 0){
4702     limit = buffer_length - 8;
4703 
4704     for(; i < limit; i += 8){
4705       current_channel = 0;
4706 
4707       if(buffer[0] != 0){
4708 	current_value += (1.0 / ((0.5 * pressure_factor) * buffer[0]));
4709       }
4710 
4711       if(buffer[(current_channel = channels)] != 0){
4712 	current_value += (1.0 / ((0.5 * pressure_factor) * buffer[current_channel]));
4713       }
4714 
4715       if(buffer[(current_channel += channels)] != 0){
4716 	current_value += (1.0 / ((0.5 * pressure_factor) * buffer[current_channel]));
4717       }
4718 
4719       if(buffer[(current_channel += channels)] != 0){
4720 	current_value += (1.0 / ((0.5 * pressure_factor) * buffer[current_channel]));
4721       }
4722 
4723       if(buffer[(current_channel += channels)] != 0){
4724 	current_value += (1.0 / ((0.5 * pressure_factor) * buffer[current_channel]));
4725       }
4726 
4727       if(buffer[(current_channel += channels)] != 0){
4728 	current_value += (1.0 / ((0.5 * pressure_factor) * buffer[current_channel]));
4729       }
4730 
4731       if(buffer[(current_channel += channels)] != 0){
4732 	current_value += (1.0 / ((0.5 * pressure_factor) * buffer[current_channel]));
4733       }
4734 
4735       if(buffer[(current_channel += channels)] != 0){
4736 	current_value += (1.0 / ((0.5 * pressure_factor) * buffer[current_channel]));
4737       }
4738 
4739       buffer += (current_channel + channels);
4740     }
4741   }
4742 #endif
4743 
4744   for(; i < buffer_length; i++){
4745     if(buffer[0] != 0){
4746       current_value += (1.0 / ((0.5 * pressure_factor) * buffer[0]));
4747     }
4748 
4749     buffer += channels;
4750   }
4751 
4752   if(current_value != 0.0){
4753     current_value = (atan(1.0 / harmonic_rate) / sin(current_value / max_rate));
4754   }
4755 
4756   return(current_value);
4757 }
4758 
4759 /**
4760  * ags_audio_buffer_util_peak_double:
4761  * @buffer: the audio buffer
4762  * @channels: number of audio channels
4763  * @buffer_length: the buffer length
4764  * @harmonic_rate: the harmonic rate
4765  * @max_rate: the max rate
4766  * @pressure_factor: the pressure factor
4767  *
4768  * Retrive peak of buffer.
4769  *
4770  * Returns: the peak as gdouble
4771  *
4772  * Since: 3.0.0
4773  */
4774 gdouble
ags_audio_buffer_util_peak_double(gdouble * buffer,guint channels,guint buffer_length,gdouble harmonic_rate,gdouble max_rate,gdouble pressure_factor)4775 ags_audio_buffer_util_peak_double(gdouble *buffer, guint channels,
4776 				  guint buffer_length,
4777 				  gdouble harmonic_rate,
4778 				  gdouble max_rate,
4779 				  gdouble pressure_factor)
4780 {
4781   double current_value;
4782   guint limit;
4783   guint current_channel;
4784   guint i;
4785 
4786   if(buffer == NULL){
4787     return(0.0);
4788   }
4789 
4790   /* calculate average value */
4791   current_value = 0.0;
4792 
4793   i = 0;
4794 
4795 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
4796   /* vectorized function */
4797   if(buffer_length > 8){
4798     limit = buffer_length - (buffer_length % 8);
4799 
4800     for(; i < limit; i += 8){
4801       ags_v8double v_buffer;
4802       ags_v8double v_zero;
4803 
4804       current_channel = 0;
4805 
4806       v_buffer = (ags_v8double) {(gdouble) buffer[0],
4807 				 (gdouble) buffer[(current_channel = channels)],
4808 				 (gdouble) buffer[(current_channel += channels)],
4809 				 (gdouble) buffer[(current_channel += channels)],
4810 				 (gdouble) buffer[(current_channel += channels)],
4811 				 (gdouble) buffer[(current_channel += channels)],
4812 				 (gdouble) buffer[(current_channel += channels)],
4813 				 (gdouble) buffer[(current_channel += channels)]};
4814 
4815       v_zero = (ags_v8double) {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
4816 
4817       v_buffer = (0.5 * pressure_factor) * v_buffer;
4818 
4819       v_zero = v_buffer == v_zero;
4820 
4821       if(v_zero[0] != 0.0){
4822 	v_buffer[0] = 1.0;
4823       }
4824 
4825       if(v_zero[1] != 0.0){
4826 	v_buffer[1] = 1.0;
4827       }
4828 
4829       if(v_zero[2] != 0.0){
4830 	v_buffer[2] = 1.0;
4831       }
4832 
4833       if(v_zero[3] != 0.0){
4834 	v_buffer[3] = 1.0;
4835       }
4836 
4837       if(v_zero[4] != 0.0){
4838 	v_buffer[4] = 1.0;
4839       }
4840 
4841       if(v_zero[5] != 0.0){
4842 	v_buffer[5] = 1.0;
4843       }
4844 
4845       if(v_zero[6] != 0.0){
4846 	v_buffer[6] = 1.0;
4847       }
4848 
4849       if(v_zero[7] != 0.0){
4850 	v_buffer[7] = 1.0;
4851       }
4852 
4853       v_buffer = 1.0 / v_buffer;
4854 
4855       if(v_zero[0] != 0.0){
4856 	v_buffer[0] = 0.0;
4857       }
4858 
4859       if(v_zero[1] != 0.0){
4860 	v_buffer[1] = 0.0;
4861       }
4862 
4863       if(v_zero[2] != 0.0){
4864 	v_buffer[2] = 0.0;
4865       }
4866 
4867       if(v_zero[3] != 0.0){
4868 	v_buffer[3] = 0.0;
4869       }
4870 
4871       if(v_zero[4] != 0.0){
4872 	v_buffer[4] = 0.0;
4873       }
4874 
4875       if(v_zero[5] != 0.0){
4876 	v_buffer[5] = 0.0;
4877       }
4878 
4879       if(v_zero[6] != 0.0){
4880 	v_buffer[6] = 0.0;
4881       }
4882 
4883       if(v_zero[7] != 0.0){
4884 	v_buffer[7] = 0.0;
4885       }
4886 
4887       current_value += v_buffer[0] + v_buffer[1] + v_buffer[2] + v_buffer[3] + v_buffer[4] + v_buffer[5] + v_buffer[6] + v_buffer[7];
4888 
4889       buffer += (current_channel + channels);
4890     }
4891   }
4892 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
4893   /* vectorized function */
4894   if(buffer_length > 8){
4895     limit = buffer_length - (buffer_length % 8);
4896 
4897     for(; i < limit; i += 8){
4898       gboolean v_zero[8];
4899       double v_result[8];
4900       double v_factor[1];
4901 
4902       static const double v_one[] = { 1.0 };
4903 
4904       current_channel = 0;
4905 
4906       double ret_v_buffer[] = {(double) buffer[0],
4907 			       (double) buffer[(current_channel = channels)],
4908 			       (double) buffer[(current_channel += channels)],
4909 			       (double) buffer[(current_channel += channels)],
4910 			       (double) buffer[(current_channel += channels)],
4911 			       (double) buffer[(current_channel += channels)],
4912 			       (double) buffer[(current_channel += channels)],
4913 			       (double) buffer[(current_channel += channels)]};
4914 
4915       if(ret_v_buffer[0] == 0.0){
4916 	ret_v_buffer[0] = 1.0;
4917 
4918 	v_zero[0] = TRUE;
4919       }
4920 
4921       if(ret_v_buffer[1] == 0.0){
4922 	ret_v_buffer[1] = 1.0;
4923 
4924 	v_zero[1] = TRUE;
4925       }
4926 
4927       if(ret_v_buffer[2] == 0.0){
4928 	ret_v_buffer[2] = 1.0;
4929 
4930 	v_zero[2] = TRUE;
4931       }
4932 
4933       if(ret_v_buffer[3] == 0.0){
4934 	ret_v_buffer[3] = 1.0;
4935 
4936 	v_zero[3] = TRUE;
4937       }
4938 
4939       if(ret_v_buffer[4] == 0.0){
4940 	ret_v_buffer[4] = 1.0;
4941 
4942 	v_zero[4] = TRUE;
4943       }
4944 
4945       if(ret_v_buffer[5] == 0.0){
4946 	ret_v_buffer[5] = 1.0;
4947 
4948 	v_zero[5] = TRUE;
4949       }
4950 
4951       if(ret_v_buffer[6] == 0.0){
4952 	ret_v_buffer[6] = 1.0;
4953 
4954 	v_zero[6] = TRUE;
4955       }
4956 
4957       if(ret_v_buffer[7] == 0.0){
4958 	ret_v_buffer[7] = 1.0;
4959 
4960 	v_zero[7] = TRUE;
4961       }
4962 
4963       vDSP_vdiv(v_one, 0, ret_v_buffer, 1, v_result, 1, 8);
4964 
4965       if(v_zero[0]){
4966 	v_result[0] = 0.0;
4967       }
4968 
4969       if(v_zero[1]){
4970 	v_result[1] = 0.0;
4971       }
4972 
4973       if(v_zero[2]){
4974 	v_result[2] = 0.0;
4975       }
4976 
4977       if(v_zero[3]){
4978 	v_result[3] = 0.0;
4979       }
4980 
4981       if(v_zero[4]){
4982 	v_result[4] = 0.0;
4983       }
4984 
4985       if(v_zero[5]){
4986 	v_result[5] = 0.0;
4987       }
4988 
4989       if(v_zero[6]){
4990 	v_result[6] = 0.0;
4991       }
4992 
4993       if(v_zero[7]){
4994 	v_result[7] = 0.0;
4995       }
4996 
4997       current_value += v_result[0] + v_result[1] + v_result[2] + v_result[3] + v_result[4] + v_result[5] + v_result[6] + v_result[7];
4998 
4999       buffer += (current_channel + channels);
5000     }
5001   }
5002 #else
5003   /* unrolled function */
5004   if(buffer_length > 0){
5005     limit = buffer_length - 8;
5006 
5007     for(; i < limit; i += 8){
5008       current_channel = 0;
5009 
5010       if(buffer[0] != 0){
5011 	current_value += (1.0 / ((0.5 * pressure_factor) * buffer[0]));
5012       }
5013 
5014       if(buffer[(current_channel = channels)] != 0){
5015 	current_value += (1.0 / ((0.5 * pressure_factor) * buffer[current_channel]));
5016       }
5017 
5018       if(buffer[(current_channel += channels)] != 0){
5019 	current_value += (1.0 / ((0.5 * pressure_factor) * buffer[current_channel]));
5020       }
5021 
5022       if(buffer[(current_channel += channels)] != 0){
5023 	current_value += (1.0 / ((0.5 * pressure_factor) * buffer[current_channel]));
5024       }
5025 
5026       if(buffer[(current_channel += channels)] != 0){
5027 	current_value += (1.0 / ((0.5 * pressure_factor) * buffer[current_channel]));
5028       }
5029 
5030       if(buffer[(current_channel += channels)] != 0){
5031 	current_value += (1.0 / ((0.5 * pressure_factor) * buffer[current_channel]));
5032       }
5033 
5034       if(buffer[(current_channel += channels)] != 0){
5035 	current_value += (1.0 / ((0.5 * pressure_factor) * buffer[current_channel]));
5036       }
5037 
5038       if(buffer[(current_channel += channels)] != 0){
5039 	current_value += (1.0 / ((0.5 * pressure_factor) * buffer[current_channel]));
5040       }
5041 
5042       buffer += (current_channel + channels);
5043     }
5044   }
5045 #endif
5046 
5047   for(; i < buffer_length; i++){
5048     if(buffer[0] != 0){
5049       current_value += (1.0 / ((0.5 * pressure_factor) * buffer[0]));
5050     }
5051 
5052     buffer += channels;
5053   }
5054 
5055   if(current_value != 0.0){
5056     current_value = (atan(1.0 / harmonic_rate) / sin(current_value / max_rate));
5057   }
5058 
5059   return(current_value);
5060 }
5061 
5062 /**
5063  * ags_audio_buffer_util_peak_complex:
5064  * @buffer: the audio buffer
5065  * @channels: number of audio channels
5066  * @buffer_length: the buffer length
5067  * @harmonic_rate: the harmonic rate
5068  * @max_rate: the max rate
5069  * @pressure_factor: the pressure factor
5070  *
5071  * Retrive peak of buffer.
5072  *
5073  * Returns: the peak as gdouble
5074  *
5075  * Since: 3.0.0
5076  */
5077 gdouble
ags_audio_buffer_util_peak_complex(AgsComplex * buffer,guint channels,guint buffer_length,gdouble harmonic_rate,gdouble max_rate,gdouble pressure_factor)5078 ags_audio_buffer_util_peak_complex(AgsComplex *buffer, guint channels,
5079 				   guint buffer_length,
5080 				   gdouble harmonic_rate,
5081 				   gdouble max_rate,
5082 				   gdouble pressure_factor)
5083 {
5084   double current_value;
5085   guint limit;
5086   guint current_channel;
5087   guint i;
5088 
5089   if(buffer == NULL){
5090     return(0.0);
5091   }
5092 
5093   i = 0;
5094 
5095   /* calculate average value */
5096   current_value = 0.0;
5097 
5098   //TODO:JK: improve me
5099 
5100   for(; i < buffer_length; i++){
5101     double _Complex z;
5102 
5103     z = ags_complex_get(buffer);
5104 
5105     if(creal(z) != 0.0 ||
5106        cimag(z) != 0.0){
5107       current_value += (1.0 / ((0.5 * pressure_factor) * (z / M_PI)));
5108     }
5109 
5110     buffer += channels;
5111   }
5112 
5113   if(current_value != 0.0){
5114     current_value = (atan(1.0 / harmonic_rate) / sin(current_value / max_rate));
5115   }
5116 
5117   return(current_value);
5118 }
5119 
5120 /**
5121  * ags_audio_buffer_util_peak:
5122  * @buffer: the audio buffer
5123  * @channels: number of audio channels
5124  * @format: the format to use
5125  * @buffer_length: the buffer length
5126  * @harmonic_rate: the harmonic rate
5127  * @max_rate: the max rate
5128  * @pressure_factor: the pressure factor
5129  *
5130  * Retrive peak of buffer.
5131  *
5132  * Returns: the peak as gdouble
5133  *
5134  * Since: 3.0.0
5135  */
5136 gdouble
ags_audio_buffer_util_peak(void * buffer,guint channels,guint format,guint buffer_length,gdouble harmonic_rate,gdouble max_rate,gdouble pressure_factor)5137 ags_audio_buffer_util_peak(void *buffer, guint channels,
5138 			   guint format,
5139 			   guint buffer_length,
5140 			   gdouble harmonic_rate,
5141 			   gdouble max_rate,
5142 			   gdouble pressure_factor)
5143 {
5144   gdouble current_value;
5145 
5146   if(buffer == NULL){
5147     return(0.0);
5148   }
5149 
5150   current_value = 0.0;
5151 
5152   switch(format){
5153   case AGS_AUDIO_BUFFER_UTIL_S8:
5154     {
5155       current_value = ags_audio_buffer_util_peak_s8((gint8 *) buffer, channels,
5156 						    buffer_length,
5157 						    harmonic_rate,
5158 						    max_rate,
5159 						    pressure_factor);
5160     }
5161     break;
5162   case AGS_AUDIO_BUFFER_UTIL_S16:
5163     {
5164       current_value = ags_audio_buffer_util_peak_s16((gint16 *) buffer, channels,
5165 						     buffer_length,
5166 						     harmonic_rate,
5167 						     max_rate,
5168 						     pressure_factor);
5169     }
5170     break;
5171   case AGS_AUDIO_BUFFER_UTIL_S24:
5172     {
5173       current_value = ags_audio_buffer_util_peak_s24((gint32 *) buffer, channels,
5174 						     buffer_length,
5175 						     harmonic_rate,
5176 						     max_rate,
5177 						     pressure_factor);
5178     }
5179     break;
5180   case AGS_AUDIO_BUFFER_UTIL_S32:
5181     {
5182       current_value = ags_audio_buffer_util_peak_s32((gint32 *) buffer, channels,
5183 						     buffer_length,
5184 						     harmonic_rate,
5185 						     max_rate,
5186 						     pressure_factor);
5187     }
5188     break;
5189   case AGS_AUDIO_BUFFER_UTIL_S64:
5190     {
5191       current_value = ags_audio_buffer_util_peak_s64((gint64 *) buffer, channels,
5192 						     buffer_length,
5193 						     harmonic_rate,
5194 						     max_rate,
5195 						     pressure_factor);
5196     }
5197     break;
5198   case AGS_AUDIO_BUFFER_UTIL_FLOAT:
5199     {
5200       current_value = ags_audio_buffer_util_peak_float((gfloat *) buffer, channels,
5201 						       buffer_length,
5202 						       harmonic_rate,
5203 						       max_rate,
5204 						       pressure_factor);
5205     }
5206     break;
5207   case AGS_AUDIO_BUFFER_UTIL_DOUBLE:
5208     {
5209       current_value = ags_audio_buffer_util_peak_double((gdouble *) buffer, channels,
5210 							buffer_length,
5211 							harmonic_rate,
5212 							max_rate,
5213 							pressure_factor);
5214     }
5215     break;
5216   case AGS_AUDIO_BUFFER_UTIL_COMPLEX:
5217     {
5218       current_value = ags_audio_buffer_util_peak_complex((AgsComplex *) buffer, channels,
5219 							 buffer_length,
5220 							 harmonic_rate,
5221 							 max_rate,
5222 							 pressure_factor);
5223     }
5224     break;
5225   default:
5226     g_warning("ags_audio_buffer_util_peak() - unknown format");
5227   }
5228 
5229   return(current_value);
5230 }
5231 
5232 /**
5233  * ags_audio_buffer_util_resample_s8:
5234  * @buffer: the audio buffer
5235  * @channels: number of audio channels
5236  * @samplerate: the current samplerate
5237  * @buffer_length: the buffer's length
5238  * @target_samplerate: the samplerate to use
5239  *
5240  * Resamples @buffer from @samplerate to @target_samplerate.
5241  *
5242  * Returns: the resampled audio buffer
5243  *
5244  * Since: 3.0.0
5245  */
5246 gint8*
ags_audio_buffer_util_resample_s8(gint8 * buffer,guint channels,guint samplerate,guint buffer_length,guint target_samplerate)5247 ags_audio_buffer_util_resample_s8(gint8 *buffer, guint channels,
5248 				  guint samplerate,
5249 				  guint buffer_length,
5250 				  guint target_samplerate)
5251 {
5252   SRC_DATA secret_rabbit;
5253 
5254   gint8 *ret_buffer;
5255 
5256   if(buffer == NULL){
5257     return(NULL);
5258   }
5259 
5260   secret_rabbit.src_ratio = target_samplerate / samplerate;
5261 
5262   secret_rabbit.input_frames = buffer_length;
5263   secret_rabbit.data_in = (gfloat *) malloc(channels * buffer_length * sizeof(gfloat));
5264   ags_audio_buffer_util_clear_float(secret_rabbit.data_in, 1,
5265 				    channels * buffer_length);
5266   ags_audio_buffer_util_copy_s8_to_float(secret_rabbit.data_in, 1,
5267 					 buffer, 1,
5268 					 channels * buffer_length);
5269 
5270   secret_rabbit.output_frames = ceil(secret_rabbit.src_ratio * buffer_length);
5271   secret_rabbit.data_out = (gfloat *) malloc(channels * secret_rabbit.output_frames * sizeof(gfloat));
5272 
5273   src_simple(&secret_rabbit,
5274 	     SRC_SINC_BEST_QUALITY,
5275 	     channels);
5276 
5277   ret_buffer = (gint8 *) malloc(channels * secret_rabbit.output_frames * sizeof(gint8));
5278   memset(ret_buffer, 0, secret_rabbit.output_frames * sizeof(gint8));
5279   ags_audio_buffer_util_copy_float_to_s8(ret_buffer, 1,
5280 					 secret_rabbit.data_out, 1,
5281 					 channels * secret_rabbit.output_frames);
5282 
5283   free(secret_rabbit.data_out);
5284   free(secret_rabbit.data_in);
5285 
5286   return(ret_buffer);
5287 }
5288 
5289 /**
5290  * ags_audio_buffer_util_resample_s16:
5291  * @buffer: the audio buffer
5292  * @channels: number of audio channels
5293  * @samplerate: the current samplerate
5294  * @buffer_length: the buffer's length
5295  * @target_samplerate: the samplerate to use
5296  *
5297  * Resamples @buffer from @samplerate to @target_samplerate.
5298  *
5299  * Returns: the resampled audio buffer
5300  *
5301  * Since: 3.0.0
5302  */
5303 gint16*
ags_audio_buffer_util_resample_s16(gint16 * buffer,guint channels,guint samplerate,guint buffer_length,guint target_samplerate)5304 ags_audio_buffer_util_resample_s16(gint16 *buffer, guint channels,
5305 				   guint samplerate,
5306 				   guint buffer_length,
5307 				   guint target_samplerate)
5308 {
5309   SRC_DATA secret_rabbit;
5310 
5311   gint16 *ret_buffer;
5312 
5313   if(buffer == NULL){
5314     return(NULL);
5315   }
5316 
5317   secret_rabbit.src_ratio = target_samplerate / samplerate;
5318 
5319   secret_rabbit.input_frames = buffer_length;
5320   secret_rabbit.data_in = (gfloat *) malloc(channels * buffer_length * sizeof(gfloat));
5321   ags_audio_buffer_util_clear_float(secret_rabbit.data_in, 1,
5322 				    channels * buffer_length);
5323   ags_audio_buffer_util_copy_s16_to_float(secret_rabbit.data_in, 1,
5324 					  buffer, 1,
5325 					  channels * buffer_length);
5326 
5327   secret_rabbit.output_frames = ceil(secret_rabbit.src_ratio * buffer_length);
5328   secret_rabbit.data_out = (gfloat *) malloc(channels * secret_rabbit.output_frames * sizeof(gfloat));
5329 
5330   src_simple(&secret_rabbit,
5331 	     SRC_SINC_BEST_QUALITY,
5332 	     channels);
5333 
5334   ret_buffer = (gint16 *) malloc(channels * secret_rabbit.output_frames * sizeof(gint16));
5335   memset(ret_buffer, 0, secret_rabbit.output_frames * sizeof(gint16));
5336   ags_audio_buffer_util_copy_float_to_s16(ret_buffer, 1,
5337 					  secret_rabbit.data_out, 1,
5338 					  channels * secret_rabbit.output_frames);
5339 
5340   free(secret_rabbit.data_out);
5341   free(secret_rabbit.data_in);
5342 
5343   return(ret_buffer);
5344 }
5345 
5346 /**
5347  * ags_audio_buffer_util_resample_s24:
5348  * @buffer: the audio buffer
5349  * @channels: number of audio channels
5350  * @samplerate: the current samplerate
5351  * @buffer_length: the buffer's length
5352  * @target_samplerate: the samplerate to use
5353  *
5354  * Resamples @buffer from @samplerate to @target_samplerate.
5355  *
5356  * Returns: the resampled audio buffer
5357  *
5358  * Since: 3.0.0
5359  */
5360 gint32*
ags_audio_buffer_util_resample_s24(gint32 * buffer,guint channels,guint samplerate,guint buffer_length,guint target_samplerate)5361 ags_audio_buffer_util_resample_s24(gint32 *buffer, guint channels,
5362 				   guint samplerate,
5363 				   guint buffer_length,
5364 				   guint target_samplerate)
5365 {
5366   SRC_DATA secret_rabbit;
5367 
5368   gint32 *ret_buffer;
5369 
5370   if(buffer == NULL){
5371     return(NULL);
5372   }
5373 
5374   secret_rabbit.src_ratio = target_samplerate / samplerate;
5375 
5376   secret_rabbit.input_frames = buffer_length;
5377   secret_rabbit.data_in = (gfloat *) malloc(channels * buffer_length * sizeof(gfloat));
5378   ags_audio_buffer_util_clear_float(secret_rabbit.data_in, 1,
5379 				    channels * buffer_length);
5380   ags_audio_buffer_util_copy_s24_to_float(secret_rabbit.data_in, 1,
5381 					  buffer, 1,
5382 					  channels * buffer_length);
5383 
5384   secret_rabbit.output_frames = ceil(secret_rabbit.src_ratio * buffer_length);
5385   secret_rabbit.data_out = (gfloat *) malloc(channels * secret_rabbit.output_frames * sizeof(gfloat));
5386 
5387   src_simple(&secret_rabbit,
5388 	     SRC_SINC_BEST_QUALITY,
5389 	     channels);
5390 
5391   ret_buffer = (gint32 *) malloc(channels * secret_rabbit.output_frames * sizeof(gint32));
5392   memset(ret_buffer, 0, secret_rabbit.output_frames * sizeof(gint32));
5393   ags_audio_buffer_util_copy_float_to_s24(ret_buffer, 1,
5394 					  secret_rabbit.data_out, 1,
5395 					  channels * secret_rabbit.output_frames);
5396 
5397   free(secret_rabbit.data_out);
5398   free(secret_rabbit.data_in);
5399 
5400   return(ret_buffer);
5401 }
5402 
5403 /**
5404  * ags_audio_buffer_util_resample_s32:
5405  * @buffer: the audio buffer
5406  * @channels: number of audio channels
5407  * @samplerate: the current samplerate
5408  * @buffer_length: the buffer's length
5409  * @target_samplerate: the samplerate to use
5410  *
5411  * Resamples @buffer from @samplerate to @target_samplerate.
5412  *
5413  * Returns: the resampled audio buffer
5414  *
5415  * Since: 3.0.0
5416  */
5417 gint32*
ags_audio_buffer_util_resample_s32(gint32 * buffer,guint channels,guint samplerate,guint buffer_length,guint target_samplerate)5418 ags_audio_buffer_util_resample_s32(gint32 *buffer, guint channels,
5419 				   guint samplerate,
5420 				   guint buffer_length,
5421 				   guint target_samplerate)
5422 {
5423   SRC_DATA secret_rabbit;
5424 
5425   gint32 *ret_buffer;
5426 
5427   if(buffer == NULL){
5428     return(NULL);
5429   }
5430 
5431   secret_rabbit.src_ratio = target_samplerate / samplerate;
5432 
5433   secret_rabbit.input_frames = buffer_length;
5434   secret_rabbit.data_in = (gfloat *) malloc(channels * buffer_length * sizeof(gfloat));
5435   ags_audio_buffer_util_clear_float(secret_rabbit.data_in, 1,
5436 				    channels * buffer_length);
5437   ags_audio_buffer_util_copy_s32_to_float(secret_rabbit.data_in, 1,
5438 					  buffer, 1,
5439 					  channels * buffer_length);
5440 
5441   secret_rabbit.output_frames = ceil(secret_rabbit.src_ratio * buffer_length);
5442   secret_rabbit.data_out = (gfloat *) malloc(channels * secret_rabbit.output_frames * sizeof(gfloat));
5443 
5444   src_simple(&secret_rabbit,
5445 	     SRC_SINC_BEST_QUALITY,
5446 	     channels);
5447 
5448   ret_buffer = (gint32 *) malloc(channels * secret_rabbit.output_frames * sizeof(gint32));
5449   memset(ret_buffer, 0, secret_rabbit.output_frames * sizeof(gint32));
5450   ags_audio_buffer_util_copy_float_to_s32(ret_buffer, 1,
5451 					  secret_rabbit.data_out, 1,
5452 					  channels * secret_rabbit.output_frames);
5453 
5454   free(secret_rabbit.data_out);
5455   free(secret_rabbit.data_in);
5456 
5457   return(ret_buffer);
5458 }
5459 
5460 /**
5461  * ags_audio_buffer_util_resample_s64:
5462  * @buffer: the audio buffer
5463  * @channels: number of audio channels
5464  * @samplerate: the current samplerate
5465  * @buffer_length: the buffer's length
5466  * @target_samplerate: the samplerate to use
5467  *
5468  * Resamples @buffer from @samplerate to @target_samplerate.
5469  *
5470  * Returns: the resampled audio buffer
5471  *
5472  * Since: 3.0.0
5473  */
5474 gint64*
ags_audio_buffer_util_resample_s64(gint64 * buffer,guint channels,guint samplerate,guint buffer_length,guint target_samplerate)5475 ags_audio_buffer_util_resample_s64(gint64 *buffer, guint channels,
5476 				   guint samplerate,
5477 				   guint buffer_length,
5478 				   guint target_samplerate)
5479 {
5480   SRC_DATA secret_rabbit;
5481 
5482   gint64 *ret_buffer;
5483 
5484   if(buffer == NULL){
5485     return(NULL);
5486   }
5487 
5488   secret_rabbit.src_ratio = target_samplerate / samplerate;
5489 
5490   secret_rabbit.input_frames = buffer_length;
5491   secret_rabbit.data_in = (gfloat *) malloc(channels * buffer_length * sizeof(gfloat));
5492   ags_audio_buffer_util_clear_float(secret_rabbit.data_in, 1,
5493 				    channels * buffer_length);
5494   ags_audio_buffer_util_copy_s64_to_float(secret_rabbit.data_in, 1,
5495 					  buffer, 1,
5496 					  channels * buffer_length);
5497 
5498   secret_rabbit.output_frames = ceil(secret_rabbit.src_ratio * buffer_length);
5499   secret_rabbit.data_out = (gfloat *) malloc(channels * secret_rabbit.output_frames * sizeof(gfloat));
5500 
5501   src_simple(&secret_rabbit,
5502 	     SRC_SINC_BEST_QUALITY,
5503 	     channels);
5504 
5505   ret_buffer = (gint64 *) malloc(channels * secret_rabbit.output_frames * sizeof(gint64));
5506   memset(ret_buffer, 0, secret_rabbit.output_frames * sizeof(gint64));
5507   ags_audio_buffer_util_copy_float_to_s64(ret_buffer, 1,
5508 					  secret_rabbit.data_out, 1,
5509 					  channels * secret_rabbit.output_frames);
5510 
5511   free(secret_rabbit.data_out);
5512   free(secret_rabbit.data_in);
5513 
5514   return(ret_buffer);
5515 }
5516 
5517 /**
5518  * ags_audio_buffer_util_resample_float:
5519  * @buffer: the audio buffer
5520  * @channels: number of audio channels
5521  * @samplerate: the current samplerate
5522  * @buffer_length: the buffer's length
5523  * @target_samplerate: the samplerate to use
5524  *
5525  * Resamples @buffer from @samplerate to @target_samplerate.
5526  *
5527  * Returns: the resampled audio buffer
5528  *
5529  * Since: 3.0.0
5530  */
5531 float*
ags_audio_buffer_util_resample_float(gfloat * buffer,guint channels,guint samplerate,guint buffer_length,guint target_samplerate)5532 ags_audio_buffer_util_resample_float(gfloat *buffer, guint channels,
5533 				     guint samplerate,
5534 				     guint buffer_length,
5535 				     guint target_samplerate)
5536 {
5537   SRC_DATA secret_rabbit;
5538 
5539   gfloat *ret_buffer;
5540 
5541   if(buffer == NULL){
5542     return(NULL);
5543   }
5544 
5545   //FIXME:JK: lost precision
5546 
5547   secret_rabbit.src_ratio = target_samplerate / samplerate;
5548 
5549   secret_rabbit.input_frames = buffer_length;
5550   secret_rabbit.data_in = (gfloat *) malloc(channels * buffer_length * sizeof(gfloat));
5551   ags_audio_buffer_util_clear_float(secret_rabbit.data_in, 1,
5552 				    channels * buffer_length);
5553   ags_audio_buffer_util_copy_float_to_float(secret_rabbit.data_in, 1,
5554 					    buffer, 1,
5555 					    channels * buffer_length);
5556 
5557   secret_rabbit.output_frames = ceil(secret_rabbit.src_ratio * buffer_length);
5558   secret_rabbit.data_out = (gfloat *) malloc(channels * secret_rabbit.output_frames * sizeof(gfloat));
5559 
5560   src_simple(&secret_rabbit,
5561 	     SRC_SINC_BEST_QUALITY,
5562 	     channels);
5563 
5564   ret_buffer = (gfloat *) malloc(channels * (ceil((gfloat) buffer_length / (gfloat) samplerate * (gfloat) target_samplerate)) * sizeof(gfloat));
5565   ags_audio_buffer_util_clear_float(ret_buffer, 1,
5566 				    (ceil((gfloat) buffer_length / (gfloat) samplerate * (gfloat) target_samplerate)));
5567   ags_audio_buffer_util_copy_float_to_float(ret_buffer, 1,
5568 					    secret_rabbit.data_out, 1,
5569 					    channels * secret_rabbit.output_frames);
5570 
5571   free(secret_rabbit.data_out);
5572   free(secret_rabbit.data_in);
5573 
5574   return(ret_buffer);
5575 }
5576 
5577 /**
5578  * ags_audio_buffer_util_resample_double:
5579  * @buffer: the audio buffer
5580  * @channels: number of audio channels
5581  * @samplerate: the current samplerate
5582  * @buffer_length: the buffer's length
5583  * @target_samplerate: the samplerate to use
5584  *
5585  * Resamples @buffer from @samplerate to @target_samplerate.
5586  *
5587  * Returns: the resampled audio buffer
5588  *
5589  * Since: 3.0.0
5590  */
5591 double*
ags_audio_buffer_util_resample_double(gdouble * buffer,guint channels,guint samplerate,guint buffer_length,guint target_samplerate)5592 ags_audio_buffer_util_resample_double(gdouble *buffer, guint channels,
5593 				      guint samplerate,
5594 				      guint buffer_length,
5595 				      guint target_samplerate)
5596 {
5597   SRC_DATA secret_rabbit;
5598 
5599   gdouble *ret_buffer;
5600 
5601   if(buffer == NULL){
5602     return(NULL);
5603   }
5604 
5605   //FIXME:JK: lost precision
5606 
5607   secret_rabbit.src_ratio = target_samplerate / samplerate;
5608 
5609   secret_rabbit.input_frames = buffer_length;
5610   secret_rabbit.data_in = (gfloat *) malloc(channels * buffer_length * sizeof(gfloat));
5611   ags_audio_buffer_util_clear_float(secret_rabbit.data_in, 1,
5612 				    channels * buffer_length);
5613   ags_audio_buffer_util_copy_double_to_float(secret_rabbit.data_in, 1,
5614 					     buffer, 1,
5615 					     channels * buffer_length);
5616 
5617   secret_rabbit.output_frames = ceil(secret_rabbit.src_ratio * buffer_length);
5618   secret_rabbit.data_out = (gfloat *) malloc(channels * secret_rabbit.output_frames * sizeof(gfloat));
5619 
5620   src_simple(&secret_rabbit,
5621 	     SRC_SINC_BEST_QUALITY,
5622 	     channels);
5623 
5624   ret_buffer = (gdouble *) malloc(channels * secret_rabbit.output_frames * sizeof(gdouble));
5625   ags_audio_buffer_util_clear_double(ret_buffer, 1,
5626 				     channels * secret_rabbit.output_frames);
5627   ags_audio_buffer_util_copy_float_to_double(ret_buffer, 1,
5628 					     secret_rabbit.data_out, 1,
5629 					     channels * secret_rabbit.output_frames);
5630 
5631   free(secret_rabbit.data_out);
5632   free(secret_rabbit.data_in);
5633 
5634   return(ret_buffer);
5635 }
5636 
5637 /**
5638  * ags_audio_buffer_util_resample_complex:
5639  * @buffer: the audio buffer
5640  * @channels: number of audio channels
5641  * @samplerate: the current samplerate
5642  * @buffer_length: the buffer's length
5643  * @target_samplerate: the samplerate to use
5644  *
5645  * Resamples @buffer from @samplerate to @target_samplerate.
5646  *
5647  * Returns: the resampled audio buffer
5648  *
5649  * Since: 3.0.0
5650  */
5651 AgsComplex*
ags_audio_buffer_util_resample_complex(AgsComplex * buffer,guint channels,guint samplerate,guint buffer_length,guint target_samplerate)5652 ags_audio_buffer_util_resample_complex(AgsComplex *buffer, guint channels,
5653 				       guint samplerate,
5654 				       guint buffer_length,
5655 				       guint target_samplerate)
5656 {
5657   AgsComplex **ptr_ptr_ret_buffer;
5658   AgsComplex *ptr_ret_buffer;
5659   AgsComplex *ret_buffer;
5660 
5661   double _Complex **z_ptr_ptr;
5662   double _Complex *z_ptr;
5663   gdouble **y_ptr_ptr;
5664   gdouble *y_ptr;
5665 
5666   double _Complex z;
5667   gdouble y;
5668   gdouble delay_factor;
5669   gdouble delay;
5670   guint output_frames;
5671   guint i, n;
5672 
5673   if(buffer == NULL){
5674     return(NULL);
5675   }
5676 
5677   delay_factor = 1.0 / (gdouble) target_samplerate * (gdouble) samplerate;
5678 
5679   output_frames = ceil((gdouble) buffer_length / (gdouble) samplerate * (gdouble) target_samplerate);
5680 
5681   ret_buffer = (AgsComplex *) malloc(channels * output_frames * sizeof(AgsComplex));
5682 
5683   ptr_ptr_ret_buffer = &ptr_ret_buffer;
5684 
5685   z_ptr = &z;
5686   z_ptr_ptr = &z_ptr;
5687 
5688   y_ptr = &y;
5689   y_ptr_ptr = &y_ptr;
5690 
5691   for(i = 0, n = 0, delay = 0.0; i < output_frames; i++){
5692     /* get y */
5693     //TODO:JK: improve me
5694     AGS_AUDIO_BUFFER_UTIL_COMPLEX_TO_DOUBLE(buffer + n, y_ptr);
5695 
5696     /* put z */
5697     ptr_ret_buffer = ret_buffer + i;
5698 
5699     AGS_AUDIO_BUFFER_UTIL_DOUBLE_TO_COMPLEX(y, ptr_ptr_ret_buffer);
5700 
5701     delay += delay_factor;
5702 
5703     if(delay_factor < 1.0){
5704       if(delay >= 1.0){
5705 	n += floor(delay);
5706 
5707 	delay -= floor(delay);
5708       }
5709     }else{
5710       n += floor(delay);
5711       delay -= floor(delay);
5712     }
5713   }
5714 
5715   return(ret_buffer);
5716 }
5717 
5718 /**
5719  * ags_audio_buffer_util_resample:
5720  * @buffer: the audio buffer
5721  * @channels: number of audio channels
5722  * @format: the format
5723  * @samplerate: the current samplerate
5724  * @buffer_length: the buffer's length
5725  * @target_samplerate: the samplerate to use
5726  *
5727  * Resamples @buffer from @samplerate to @target_samplerate.
5728  *
5729  * Returns: the resampled audio buffer
5730  *
5731  * Since: 3.0.0
5732  */
5733 void*
ags_audio_buffer_util_resample(void * buffer,guint channels,guint format,guint samplerate,guint buffer_length,guint target_samplerate)5734 ags_audio_buffer_util_resample(void *buffer, guint channels,
5735 			       guint format,  guint samplerate,
5736 			       guint buffer_length,
5737 			       guint target_samplerate)
5738 {
5739   void *retval;
5740 
5741   if(buffer == NULL){
5742     return(NULL);
5743   }
5744 
5745   retval = NULL;
5746 
5747   switch(format){
5748   case AGS_AUDIO_BUFFER_UTIL_S8:
5749     {
5750       retval = ags_audio_buffer_util_resample_s8((gint8 *) buffer, channels,
5751 						 samplerate,
5752 						 buffer_length,
5753 						 target_samplerate);
5754     }
5755     break;
5756   case AGS_AUDIO_BUFFER_UTIL_S16:
5757     {
5758       retval = ags_audio_buffer_util_resample_s16((gint16 *) buffer, channels,
5759 						  samplerate,
5760 						  buffer_length,
5761 						  target_samplerate);
5762     }
5763     break;
5764   case AGS_AUDIO_BUFFER_UTIL_S24:
5765     {
5766       retval = ags_audio_buffer_util_resample_s24((gint32 *) buffer, channels,
5767 						  samplerate,
5768 						  buffer_length,
5769 						  target_samplerate);
5770     }
5771     break;
5772   case AGS_AUDIO_BUFFER_UTIL_S32:
5773     {
5774       retval = ags_audio_buffer_util_resample_s32((gint32 *) buffer, channels,
5775 						  samplerate,
5776 						  buffer_length,
5777 						  target_samplerate);
5778     }
5779     break;
5780   case AGS_AUDIO_BUFFER_UTIL_S64:
5781     {
5782       retval = ags_audio_buffer_util_resample_s64((gint64 *) buffer, channels,
5783 						  samplerate,
5784 						  buffer_length,
5785 						  target_samplerate);
5786     }
5787     break;
5788   case AGS_AUDIO_BUFFER_UTIL_FLOAT:
5789     {
5790       retval = ags_audio_buffer_util_resample_float((gfloat *) buffer, channels,
5791 						    samplerate,
5792 						    buffer_length,
5793 						    target_samplerate);
5794     }
5795     break;
5796   case AGS_AUDIO_BUFFER_UTIL_DOUBLE:
5797     {
5798       retval = ags_audio_buffer_util_resample_double((gdouble *) buffer, channels,
5799 						     samplerate,
5800 						     buffer_length,
5801 						     target_samplerate);
5802     }
5803     break;
5804   case AGS_AUDIO_BUFFER_UTIL_COMPLEX:
5805     {
5806       retval = ags_audio_buffer_util_resample_complex((AgsComplex *) buffer, channels,
5807 						      samplerate,
5808 						      buffer_length,
5809 						      target_samplerate);
5810     }
5811     break;
5812   default:
5813     g_warning("ags_audio_buffer_util_resample() - unknown format");
5814   }
5815 
5816   return(retval);
5817 }
5818 
5819 /**
5820  * ags_audio_buffer_util_resample_s8_with_buffer:
5821  * @buffer: the buffer to resample
5822  * @channels: the channels
5823  * @samplerate: the samplerate
5824  * @buffer_length: the buffer length
5825  * @target_samplerate: target samplerate
5826  * @target_buffer_length: target buffer length
5827  * @target_buffer: (out): target buffer
5828  *
5829  * Resample @buffer by providing @target_buffer.
5830  *
5831  * Since: 3.0.0
5832  */
5833 void
ags_audio_buffer_util_resample_s8_with_buffer(gint8 * buffer,guint channels,guint samplerate,guint buffer_length,guint target_samplerate,guint target_buffer_length,gint8 * target_buffer)5834 ags_audio_buffer_util_resample_s8_with_buffer(gint8 *buffer, guint channels,
5835 					      guint samplerate,
5836 					      guint buffer_length,
5837 					      guint target_samplerate,
5838 					      guint target_buffer_length,
5839 					      gint8 *target_buffer)
5840 {
5841   SRC_DATA secret_rabbit;
5842 
5843   if(buffer == NULL ||
5844      target_buffer == NULL){
5845     return;
5846   }
5847 
5848   secret_rabbit.src_ratio = target_samplerate / samplerate;
5849 
5850   secret_rabbit.input_frames = buffer_length;
5851   secret_rabbit.data_in = (gfloat *) malloc(channels * buffer_length * sizeof(gfloat));
5852   ags_audio_buffer_util_clear_float(secret_rabbit.data_in, channels,
5853 				    channels * buffer_length);
5854   ags_audio_buffer_util_copy_s8_to_float(secret_rabbit.data_in, channels,
5855 					 buffer, channels,
5856 					 channels * buffer_length);
5857 
5858   secret_rabbit.output_frames = ceil(secret_rabbit.src_ratio * buffer_length);
5859   secret_rabbit.data_out = (gfloat *) malloc(channels * secret_rabbit.output_frames * sizeof(gfloat));
5860 
5861   src_simple(&secret_rabbit,
5862 	     SRC_SINC_BEST_QUALITY,
5863 	     channels);
5864 
5865   ags_audio_buffer_util_copy_float_to_s8(target_buffer, channels,
5866 					 secret_rabbit.data_out, channels,
5867 					 ((secret_rabbit.output_frames > target_buffer_length) ? target_buffer_length: secret_rabbit.output_frames));
5868 
5869   free(secret_rabbit.data_out);
5870   free(secret_rabbit.data_in);
5871 }
5872 
5873 /**
5874  * ags_audio_buffer_util_resample_s16_with_buffer:
5875  * @buffer: the buffer to resample
5876  * @channels: the channels
5877  * @samplerate: the samplerate
5878  * @buffer_length: the buffer length
5879  * @target_samplerate: target samplerate
5880  * @target_buffer_length: target buffer length
5881  * @target_buffer: (out): target buffer
5882  *
5883  * Resample @buffer by providing @target_buffer.
5884  *
5885  * Since: 3.0.0
5886  */
5887 void
ags_audio_buffer_util_resample_s16_with_buffer(gint16 * buffer,guint channels,guint samplerate,guint buffer_length,guint target_samplerate,guint target_buffer_length,gint16 * target_buffer)5888 ags_audio_buffer_util_resample_s16_with_buffer(gint16 *buffer, guint channels,
5889 					       guint samplerate,
5890 					       guint buffer_length,
5891 					       guint target_samplerate,
5892 					       guint target_buffer_length,
5893 					       gint16 *target_buffer)
5894 {
5895   SRC_DATA secret_rabbit;
5896 
5897   if(buffer == NULL ||
5898      target_buffer == NULL){
5899     return;
5900   }
5901 
5902   secret_rabbit.src_ratio = target_samplerate / samplerate;
5903 
5904   secret_rabbit.input_frames = buffer_length;
5905   secret_rabbit.data_in = (gfloat *) malloc(channels * buffer_length * sizeof(gfloat));
5906   ags_audio_buffer_util_clear_float(secret_rabbit.data_in, channels,
5907 				    channels * buffer_length);
5908   ags_audio_buffer_util_copy_s16_to_float(secret_rabbit.data_in, channels,
5909 					  buffer, channels,
5910 					  channels * buffer_length);
5911 
5912   secret_rabbit.output_frames = ceil(secret_rabbit.src_ratio * buffer_length);
5913   secret_rabbit.data_out = (gfloat *) malloc(channels * secret_rabbit.output_frames * sizeof(gfloat));
5914 
5915   src_simple(&secret_rabbit,
5916 	     SRC_SINC_BEST_QUALITY,
5917 	     channels);
5918 
5919   ags_audio_buffer_util_copy_float_to_s16(target_buffer, channels,
5920 					  secret_rabbit.data_out, channels,
5921 					  ((secret_rabbit.output_frames > target_buffer_length) ? target_buffer_length: secret_rabbit.output_frames));
5922 
5923   free(secret_rabbit.data_out);
5924   free(secret_rabbit.data_in);
5925 }
5926 
5927 /**
5928  * ags_audio_buffer_util_resample_s24_with_buffer:
5929  * @buffer: the buffer to resample
5930  * @channels: the channels
5931  * @samplerate: the samplerate
5932  * @buffer_length: the buffer length
5933  * @target_samplerate: target samplerate
5934  * @target_buffer_length: target buffer length
5935  * @target_buffer: (out): target buffer
5936  *
5937  * Resample @buffer by providing @target_buffer.
5938  *
5939  * Since: 3.0.0
5940  */
5941 void
ags_audio_buffer_util_resample_s24_with_buffer(gint32 * buffer,guint channels,guint samplerate,guint buffer_length,guint target_samplerate,guint target_buffer_length,gint32 * target_buffer)5942 ags_audio_buffer_util_resample_s24_with_buffer(gint32 *buffer, guint channels,
5943 					       guint samplerate,
5944 					       guint buffer_length,
5945 					       guint target_samplerate,
5946 					       guint target_buffer_length,
5947 					       gint32 *target_buffer)
5948 {
5949   SRC_DATA secret_rabbit;
5950 
5951   if(buffer == NULL ||
5952      target_buffer == NULL){
5953     return;
5954   }
5955 
5956   secret_rabbit.src_ratio = target_samplerate / samplerate;
5957 
5958   secret_rabbit.input_frames = buffer_length;
5959   secret_rabbit.data_in = (gfloat *) malloc(channels * buffer_length * sizeof(gfloat));
5960   ags_audio_buffer_util_clear_float(secret_rabbit.data_in, channels,
5961 				    channels * buffer_length);
5962   ags_audio_buffer_util_copy_s24_to_float(secret_rabbit.data_in, channels,
5963 					  buffer, channels,
5964 					  channels * buffer_length);
5965 
5966   secret_rabbit.output_frames = ceil(secret_rabbit.src_ratio * buffer_length);
5967   secret_rabbit.data_out = (gfloat *) malloc(channels * secret_rabbit.output_frames * sizeof(gfloat));
5968 
5969   src_simple(&secret_rabbit,
5970 	     SRC_SINC_BEST_QUALITY,
5971 	     channels);
5972 
5973   ags_audio_buffer_util_copy_float_to_s24(target_buffer, channels,
5974 					  secret_rabbit.data_out, channels,
5975 					  ((secret_rabbit.output_frames > target_buffer_length) ? target_buffer_length: secret_rabbit.output_frames));
5976 
5977   free(secret_rabbit.data_out);
5978   free(secret_rabbit.data_in);
5979 }
5980 
5981 /**
5982  * ags_audio_buffer_util_resample_s32_with_buffer:
5983  * @buffer: the buffer to resample
5984  * @channels: the channels
5985  * @samplerate: the samplerate
5986  * @buffer_length: the buffer length
5987  * @target_samplerate: target samplerate
5988  * @target_buffer_length: target buffer length
5989  * @target_buffer: (out): target buffer
5990  *
5991  * Resample @buffer by providing @target_buffer.
5992  *
5993  * Since: 3.0.0
5994  */
5995 void
ags_audio_buffer_util_resample_s32_with_buffer(gint32 * buffer,guint channels,guint samplerate,guint buffer_length,guint target_samplerate,guint target_buffer_length,gint32 * target_buffer)5996 ags_audio_buffer_util_resample_s32_with_buffer(gint32 *buffer, guint channels,
5997 					       guint samplerate,
5998 					       guint buffer_length,
5999 					       guint target_samplerate,
6000 					       guint target_buffer_length,
6001 					       gint32 *target_buffer)
6002 {
6003   SRC_DATA secret_rabbit;
6004 
6005   if(buffer == NULL ||
6006      target_buffer == NULL){
6007     return;
6008   }
6009 
6010   secret_rabbit.src_ratio = target_samplerate / samplerate;
6011 
6012   secret_rabbit.input_frames = buffer_length;
6013   secret_rabbit.data_in = (gfloat *) malloc(channels * buffer_length * sizeof(gfloat));
6014   ags_audio_buffer_util_clear_float(secret_rabbit.data_in, channels,
6015 				    channels * buffer_length);
6016   ags_audio_buffer_util_copy_s32_to_float(secret_rabbit.data_in, channels,
6017 					  buffer, channels,
6018 					  channels * buffer_length);
6019 
6020   secret_rabbit.output_frames = ceil(secret_rabbit.src_ratio * buffer_length);
6021   secret_rabbit.data_out = (gfloat *) malloc(channels * secret_rabbit.output_frames * sizeof(gfloat));
6022 
6023   src_simple(&secret_rabbit,
6024 	     SRC_SINC_BEST_QUALITY,
6025 	     channels);
6026 
6027   ags_audio_buffer_util_copy_float_to_s32(target_buffer, channels,
6028 					  secret_rabbit.data_out, channels,
6029 					  ((secret_rabbit.output_frames > target_buffer_length) ? target_buffer_length: secret_rabbit.output_frames));
6030 
6031   free(secret_rabbit.data_out);
6032   free(secret_rabbit.data_in);
6033 }
6034 
6035 /**
6036  * ags_audio_buffer_util_resample_s64_with_buffer:
6037  * @buffer: the buffer to resample
6038  * @channels: the channels
6039  * @samplerate: the samplerate
6040  * @buffer_length: the buffer length
6041  * @target_samplerate: target samplerate
6042  * @target_buffer_length: target buffer length
6043  * @target_buffer: (out): target buffer
6044  *
6045  * Resample @buffer by providing @target_buffer.
6046  *
6047  * Since: 3.0.0
6048  */
6049 void
ags_audio_buffer_util_resample_s64_with_buffer(gint64 * buffer,guint channels,guint samplerate,guint buffer_length,guint target_samplerate,guint target_buffer_length,gint64 * target_buffer)6050 ags_audio_buffer_util_resample_s64_with_buffer(gint64 *buffer, guint channels,
6051 					       guint samplerate,
6052 					       guint buffer_length,
6053 					       guint target_samplerate,
6054 					       guint target_buffer_length,
6055 					       gint64 *target_buffer)
6056 {
6057   SRC_DATA secret_rabbit;
6058 
6059   if(buffer == NULL ||
6060      target_buffer == NULL){
6061     return;
6062   }
6063 
6064   secret_rabbit.src_ratio = target_samplerate / samplerate;
6065 
6066   secret_rabbit.input_frames = buffer_length;
6067   secret_rabbit.data_in = (gfloat *) malloc(channels * buffer_length * sizeof(gfloat));
6068   ags_audio_buffer_util_clear_float(secret_rabbit.data_in, channels,
6069 				    channels * buffer_length);
6070   ags_audio_buffer_util_copy_s64_to_float(secret_rabbit.data_in, channels,
6071 					  buffer, channels,
6072 					  channels * buffer_length);
6073 
6074   secret_rabbit.output_frames = ceil(secret_rabbit.src_ratio * buffer_length);
6075   secret_rabbit.data_out = (gfloat *) malloc(channels * secret_rabbit.output_frames * sizeof(gfloat));
6076 
6077   src_simple(&secret_rabbit,
6078 	     SRC_SINC_BEST_QUALITY,
6079 	     channels);
6080 
6081   ags_audio_buffer_util_copy_float_to_s64(target_buffer, channels,
6082 					  secret_rabbit.data_out, channels,
6083 					  ((secret_rabbit.output_frames > target_buffer_length) ? target_buffer_length: secret_rabbit.output_frames));
6084 
6085   free(secret_rabbit.data_out);
6086   free(secret_rabbit.data_in);
6087 }
6088 
6089 /**
6090  * ags_audio_buffer_util_resample_float_with_buffer:
6091  * @buffer: the buffer to resample
6092  * @channels: the channels
6093  * @samplerate: the samplerate
6094  * @buffer_length: the buffer length
6095  * @target_samplerate: target samplerate
6096  * @target_buffer_length: target buffer length
6097  * @target_buffer: (out): target buffer
6098  *
6099  * Resample @buffer by providing @target_buffer.
6100  *
6101  * Since: 3.0.0
6102  */
6103 void
ags_audio_buffer_util_resample_float_with_buffer(gfloat * buffer,guint channels,guint samplerate,guint buffer_length,guint target_samplerate,guint target_buffer_length,gfloat * target_buffer)6104 ags_audio_buffer_util_resample_float_with_buffer(gfloat *buffer, guint channels,
6105 						 guint samplerate,
6106 						 guint buffer_length,
6107 						 guint target_samplerate,
6108 						 guint target_buffer_length,
6109 						 gfloat *target_buffer)
6110 {
6111   SRC_DATA secret_rabbit;
6112 
6113   if(buffer == NULL ||
6114      target_buffer == NULL){
6115     return;
6116   }
6117 
6118   secret_rabbit.src_ratio = target_samplerate / samplerate;
6119 
6120   secret_rabbit.input_frames = buffer_length;
6121   secret_rabbit.data_in = buffer;
6122 
6123   secret_rabbit.output_frames = ceil(secret_rabbit.src_ratio * buffer_length);
6124   secret_rabbit.data_out = (gfloat *) malloc(channels * secret_rabbit.output_frames * sizeof(gfloat));
6125 
6126   src_simple(&secret_rabbit,
6127 	     SRC_SINC_BEST_QUALITY,
6128 	     channels);
6129 
6130   ags_audio_buffer_util_copy_float_to_float(target_buffer, channels,
6131 					    secret_rabbit.data_out, channels,
6132 					    ((secret_rabbit.output_frames > target_buffer_length) ? target_buffer_length: secret_rabbit.output_frames));
6133 
6134   free(secret_rabbit.data_out);
6135   free(secret_rabbit.data_in);
6136 }
6137 
6138 /**
6139  * ags_audio_buffer_util_resample_double_with_buffer:
6140  * @buffer: the buffer to resample
6141  * @channels: the channels
6142  * @samplerate: the samplerate
6143  * @buffer_length: the buffer length
6144  * @target_samplerate: target samplerate
6145  * @target_buffer_length: target buffer length
6146  * @target_buffer: (out): target buffer
6147  *
6148  * Resample @buffer by providing @target_buffer.
6149  *
6150  * Since: 3.0.0
6151  */
6152 void
ags_audio_buffer_util_resample_double_with_buffer(gdouble * buffer,guint channels,guint samplerate,guint buffer_length,guint target_samplerate,guint target_buffer_length,gdouble * target_buffer)6153 ags_audio_buffer_util_resample_double_with_buffer(gdouble *buffer, guint channels,
6154 						  guint samplerate,
6155 						  guint buffer_length,
6156 						  guint target_samplerate,
6157 						  guint target_buffer_length,
6158 						  gdouble *target_buffer)
6159 {
6160   SRC_DATA secret_rabbit;
6161 
6162   if(buffer == NULL ||
6163      target_buffer == NULL){
6164     return;
6165   }
6166 
6167   secret_rabbit.src_ratio = target_samplerate / samplerate;
6168 
6169   secret_rabbit.input_frames = buffer_length;
6170   secret_rabbit.data_in = (gfloat *) malloc(channels * buffer_length * sizeof(gfloat));
6171   ags_audio_buffer_util_clear_float(secret_rabbit.data_in, 1,
6172 				    channels * buffer_length);
6173   ags_audio_buffer_util_copy_double_to_float(secret_rabbit.data_in, 1,
6174 					     buffer, 1,
6175 					     channels * buffer_length);
6176 
6177   secret_rabbit.output_frames = ceil(secret_rabbit.src_ratio * buffer_length);
6178   secret_rabbit.data_out = (gfloat *) malloc(channels * secret_rabbit.output_frames * sizeof(gfloat));
6179 
6180   src_simple(&secret_rabbit,
6181 	     SRC_SINC_BEST_QUALITY,
6182 	     channels);
6183 
6184   ags_audio_buffer_util_copy_float_to_double(target_buffer, channels,
6185 					     secret_rabbit.data_out, channels,
6186 					     ((secret_rabbit.output_frames > target_buffer_length) ? target_buffer_length: secret_rabbit.output_frames));
6187 
6188   free(secret_rabbit.data_out);
6189   free(secret_rabbit.data_in);
6190 }
6191 
6192 /**
6193  * ags_audio_buffer_util_resample_complex_with_buffer:
6194  * @buffer: the buffer to resample
6195  * @channels: the channels
6196  * @samplerate: the samplerate
6197  * @buffer_length: the buffer length
6198  * @target_samplerate: target samplerate
6199  * @target_buffer_length: target buffer length
6200  * @target_buffer: (out): target buffer
6201  *
6202  * Resample @buffer by providing @target_buffer.
6203  *
6204  * Since: 3.0.0
6205  */
6206 void
ags_audio_buffer_util_resample_complex_with_buffer(AgsComplex * buffer,guint channels,guint samplerate,guint buffer_length,guint target_samplerate,guint target_buffer_length,AgsComplex * target_buffer)6207 ags_audio_buffer_util_resample_complex_with_buffer(AgsComplex *buffer, guint channels,
6208 						   guint samplerate,
6209 						   guint buffer_length,
6210 						   guint target_samplerate,
6211 						   guint target_buffer_length,
6212 						   AgsComplex *target_buffer)
6213 {
6214   AgsComplex **ptr_ptr_target_buffer;
6215   AgsComplex *ptr_target_buffer;
6216 
6217   double _Complex **z_ptr_ptr;
6218   double _Complex *z_ptr;
6219   gdouble **y_ptr_ptr;
6220   gdouble *y_ptr;
6221 
6222   double _Complex z;
6223   gdouble y;
6224   gdouble delay_factor;
6225   gdouble delay;
6226   guint output_frames;
6227   guint i, n;
6228 
6229   if(buffer == NULL ||
6230      target_buffer == NULL){
6231     return;
6232   }
6233 
6234   delay_factor = 1.0 / (gdouble) target_samplerate * (gdouble) samplerate;
6235 
6236   output_frames = ceil((gdouble) buffer_length / (gdouble) samplerate * (gdouble) target_samplerate);
6237 
6238   ptr_ptr_target_buffer = &ptr_target_buffer;
6239 
6240   z_ptr = &z;
6241   z_ptr_ptr = &z_ptr;
6242 
6243   y_ptr = &y;
6244   y_ptr_ptr = &y_ptr;
6245 
6246   for(i = 0, n = 0, delay = 0.0; i < output_frames && i < target_buffer_length; i++){
6247     /* get y */
6248     //TODO:JK: improve me
6249     AGS_AUDIO_BUFFER_UTIL_COMPLEX_TO_DOUBLE(buffer + n, y_ptr);
6250 
6251     /* put z */
6252     ptr_target_buffer = target_buffer + i;
6253 
6254     AGS_AUDIO_BUFFER_UTIL_DOUBLE_TO_COMPLEX(y, ptr_ptr_target_buffer);
6255 
6256     delay += delay_factor;
6257 
6258     if(delay_factor < 1.0){
6259       if(delay >= 1.0){
6260 	n += floor(delay);
6261 
6262 	delay -= floor(delay);
6263       }
6264     }else{
6265       n += floor(delay);
6266       delay -= floor(delay);
6267     }
6268   }
6269 }
6270 
6271 /**
6272  * ags_audio_buffer_util_resample_with_buffer:
6273  * @buffer: the buffer to resample
6274  * @channels: the channels
6275  * @format: the format
6276  * @samplerate: the samplerate
6277  * @buffer_length: the buffer length
6278  * @target_samplerate: target samplerate
6279  * @target_buffer_length: target buffer length
6280  * @target_buffer: (out): target buffer
6281  *
6282  * Resample @buffer by providing @target_buffer.
6283  *
6284  * Since: 3.0.0
6285  */
6286 void
ags_audio_buffer_util_resample_with_buffer(void * buffer,guint channels,guint format,guint samplerate,guint buffer_length,guint target_samplerate,guint target_buffer_length,void * target_buffer)6287 ags_audio_buffer_util_resample_with_buffer(void *buffer, guint channels,
6288 					   guint format,  guint samplerate,
6289 					   guint buffer_length,
6290 					   guint target_samplerate,
6291 					   guint target_buffer_length,
6292 					   void *target_buffer)
6293 {
6294   if(buffer == NULL ||
6295      target_buffer == NULL){
6296     return;
6297   }
6298 
6299   switch(format){
6300   case AGS_AUDIO_BUFFER_UTIL_S8:
6301     {
6302       ags_audio_buffer_util_resample_s8_with_buffer((gint8 *) buffer, channels,
6303 						    samplerate,
6304 						    buffer_length,
6305 						    target_samplerate,
6306 						    target_buffer_length,
6307 						    (gint8 *) target_buffer);
6308     }
6309     break;
6310   case AGS_AUDIO_BUFFER_UTIL_S16:
6311     {
6312       ags_audio_buffer_util_resample_s16_with_buffer((gint16 *) buffer, channels,
6313 						     samplerate,
6314 						     buffer_length,
6315 						     target_samplerate,
6316 						     target_buffer_length,
6317 						     (gint16 *) target_buffer);
6318     }
6319     break;
6320   case AGS_AUDIO_BUFFER_UTIL_S24:
6321     {
6322       ags_audio_buffer_util_resample_s24_with_buffer((gint32 *) buffer, channels,
6323 						     samplerate,
6324 						     buffer_length,
6325 						     target_samplerate,
6326 						     target_buffer_length,
6327 						     (gint32 *) target_buffer);
6328     }
6329     break;
6330   case AGS_AUDIO_BUFFER_UTIL_S32:
6331     {
6332       ags_audio_buffer_util_resample_s32_with_buffer((gint32 *) buffer, channels,
6333 						     samplerate,
6334 						     buffer_length,
6335 						     target_samplerate,
6336 						     target_buffer_length,
6337 						     (gint32 *) target_buffer);
6338     }
6339     break;
6340   case AGS_AUDIO_BUFFER_UTIL_S64:
6341     {
6342       ags_audio_buffer_util_resample_s64_with_buffer((gint64 *) buffer, channels,
6343 						     samplerate,
6344 						     buffer_length,
6345 						     target_samplerate,
6346 						     target_buffer_length,
6347 						     (gint64 *) target_buffer);
6348     }
6349     break;
6350   case AGS_AUDIO_BUFFER_UTIL_FLOAT:
6351     {
6352       ags_audio_buffer_util_resample_float_with_buffer((gfloat *) buffer, channels,
6353 						       samplerate,
6354 						       buffer_length,
6355 						       target_samplerate,
6356 						       target_buffer_length,
6357 						       (gfloat *) target_buffer);
6358     }
6359     break;
6360   case AGS_AUDIO_BUFFER_UTIL_DOUBLE:
6361     {
6362       ags_audio_buffer_util_resample_double_with_buffer((gdouble *) buffer, channels,
6363 							samplerate,
6364 							buffer_length,
6365 							target_samplerate,
6366 							target_buffer_length,
6367 							(gdouble *) target_buffer);
6368     }
6369     break;
6370   case AGS_AUDIO_BUFFER_UTIL_COMPLEX:
6371     {
6372       ags_audio_buffer_util_resample_complex_with_buffer((AgsComplex *) buffer, channels,
6373 							 samplerate,
6374 							 buffer_length,
6375 							 target_samplerate,
6376 							 target_buffer_length,
6377 							 (AgsComplex *) target_buffer);
6378     }
6379     break;
6380   default:
6381     g_warning("ags_audio_buffer_util_resample_with_buffer() - unknown format");
6382   }
6383 }
6384 
6385 /**
6386  * ags_audio_buffer_util_pong_s8:
6387  * @destination: the destination
6388  * @dchannels: the destination channels
6389  * @source: the source
6390  * @schannels: the source channels
6391  * @count: the count of frames
6392  *
6393  * Pingpong copy @source to @destination.
6394  *
6395  * Since: 3.4.0
6396  */
6397 void
ags_audio_buffer_util_pong_s8(gint8 * destination,guint dchannels,gint8 * source,guint schannels,guint count)6398 ags_audio_buffer_util_pong_s8(gint8 *destination, guint dchannels,
6399 			      gint8 *source, guint schannels,
6400 			      guint count)
6401 {
6402   guint limit;
6403   gint current_dchannel, current_schannel;
6404   guint i;
6405 
6406   if(destination == NULL ||
6407      source == NULL){
6408     return;
6409   }
6410 
6411   i = 0;
6412 
6413 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
6414   /* vectorized function */
6415   if(count > 8){
6416     limit = count - (count % 8);
6417 
6418     for(; i < limit; i += 8){
6419       ags_v8s8 v_destination;
6420       ags_v8s8 v_source;
6421 
6422       current_dchannel = 0;
6423       current_schannel = 0;
6424 
6425       v_destination = (ags_v8s8) {destination[0],
6426 				  destination[(current_dchannel = dchannels)],
6427 				  destination[(current_dchannel += dchannels)],
6428 				  destination[(current_dchannel += dchannels)],
6429 				  destination[(current_dchannel += dchannels)],
6430 				  destination[(current_dchannel += dchannels)],
6431 				  destination[(current_dchannel += dchannels)],
6432 				  destination[(current_dchannel += dchannels)]};
6433 
6434       v_source = (ags_v8s8) {source[0],
6435 			     source[(current_schannel -= schannels)],
6436 			     source[(current_schannel -= schannels)],
6437 			     source[(current_schannel -= schannels)],
6438 			     source[(current_schannel -= schannels)],
6439 			     source[(current_schannel -= schannels)],
6440 			     source[(current_schannel -= schannels)],
6441 			     source[(current_schannel -= schannels)]};
6442 
6443       /* no scale, just copy */
6444       v_destination += v_source;
6445 
6446       current_dchannel = 0;
6447 
6448       destination[0] = v_destination[0];
6449       destination[(current_dchannel = dchannels)] = v_destination[1];
6450       destination[(current_dchannel += dchannels)] = v_destination[2];
6451       destination[(current_dchannel += dchannels)] = v_destination[3];
6452       destination[(current_dchannel += dchannels)] = v_destination[4];
6453       destination[(current_dchannel += dchannels)] = v_destination[5];
6454       destination[(current_dchannel += dchannels)] = v_destination[6];
6455       destination[(current_dchannel += dchannels)] = v_destination[7];
6456 
6457       /* iterate destination */
6458       destination += (current_dchannel + dchannels);
6459 
6460       /* iterate source */
6461       source += (current_schannel - schannels);
6462     }
6463   }
6464 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
6465   /* vectorized function */
6466   if(count > 8){
6467     limit = count - (count % 8);
6468 
6469     for(; i < limit; i += 8){
6470       int v_result[8];
6471 
6472       current_dchannel = 0;
6473       current_schannel = 0;
6474 
6475       int v_destination[] = {(int) destination[0],
6476 			     (int) destination[(current_dchannel = dchannels)],
6477 			     (int) destination[(current_dchannel += dchannels)],
6478 			     (int) destination[(current_dchannel += dchannels)],
6479 			     (int) destination[(current_dchannel += dchannels)],
6480 			     (int) destination[(current_dchannel += dchannels)],
6481 			     (int) destination[(current_dchannel += dchannels)],
6482 			     (int) destination[(current_dchannel += dchannels)]};
6483 
6484       int v_source[] = {(int) source[0],
6485 			(int) source[(current_schannel -= schannels)],
6486 			(int) source[(current_schannel -= schannels)],
6487 			(int) source[(current_schannel -= schannels)],
6488 			(int) source[(current_schannel -= schannels)],
6489 			(int) source[(current_schannel -= schannels)],
6490 			(int) source[(current_schannel -= schannels)],
6491 			(int) source[(current_schannel -= schannels)]};
6492 
6493       /* no scale, just copy */
6494       vDSP_vaddi(v_destination, 1, v_source, 1, v_result, 1, 8);
6495 
6496       current_dchannel = 0;
6497 
6498       destination[0] = (gint8) v_result[0];
6499       destination[(current_dchannel = dchannels)] = (gint8) v_result[1];
6500       destination[(current_dchannel += dchannels)] = (gint8) v_result[2];
6501       destination[(current_dchannel += dchannels)] = (gint8) v_result[3];
6502       destination[(current_dchannel += dchannels)] = (gint8) v_result[4];
6503       destination[(current_dchannel += dchannels)] = (gint8) v_result[5];
6504       destination[(current_dchannel += dchannels)] = (gint8) v_result[6];
6505       destination[(current_dchannel += dchannels)] = (gint8) v_result[7];
6506 
6507       /* iterate destination */
6508       destination += (current_dchannel + dchannels);
6509 
6510       /* iterate source */
6511       source += (current_schannel - schannels);
6512     }
6513   }
6514 #else
6515   /* unrolled function */
6516   if(count > 8){
6517     limit = count - (count % 8);
6518 
6519     for(; i < limit; i += 8){
6520       current_dchannel = 0;
6521       current_schannel = 0;
6522 
6523       destination[0] = 0xff & ((gint16) (destination[0] + source[0]));
6524       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel = dchannels)] + source[(current_schannel -= schannels)]));
6525       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + source[(current_schannel -= schannels)]));
6526       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + source[(current_schannel -= schannels)]));
6527       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + source[(current_schannel -= schannels)]));
6528       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + source[(current_schannel -= schannels)]));
6529       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + source[(current_schannel -= schannels)]));
6530       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + source[(current_schannel -= schannels)]));
6531 
6532       /* iterate destination */
6533       destination += (current_dchannel + dchannels);
6534 
6535       /* iterate source */
6536       source += (current_schannel - schannels);
6537     }
6538   }
6539 #endif
6540 
6541   for(; i < count; i++){
6542     destination[0] = 0xff & ((gint16) (destination[0] + source[0]));
6543 
6544     destination += dchannels;
6545     source -= schannels;
6546   }
6547 }
6548 
6549 /**
6550  * ags_audio_buffer_util_pong_s16:
6551  * @destination: the destination
6552  * @dchannels: the destination channels
6553  * @source: the source
6554  * @schannels: the source channels
6555  * @count: the count of frames
6556  *
6557  * Pingpong copy @source to @destination.
6558  *
6559  * Since: 3.4.0
6560  */
6561 void
ags_audio_buffer_util_pong_s16(gint16 * destination,guint dchannels,gint16 * source,guint schannels,guint count)6562 ags_audio_buffer_util_pong_s16(gint16 *destination, guint dchannels,
6563 			       gint16 *source, guint schannels,
6564 			       guint count)
6565 {
6566   guint limit;
6567   gint current_dchannel, current_schannel;
6568   guint i;
6569 
6570   if(destination == NULL ||
6571      source == NULL){
6572     return;
6573   }
6574 
6575   i = 0;
6576 
6577 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
6578   /* vectorized function */
6579   if(count > 8){
6580     limit = count - (count % 8);
6581 
6582     for(; i < limit; i += 8){
6583       ags_v8s16 v_destination;
6584       ags_v8s16 v_source;
6585 
6586       current_dchannel = 0;
6587       current_schannel = 0;
6588 
6589       v_destination = (ags_v8s16) {destination[0],
6590 				   destination[(current_dchannel = dchannels)],
6591 				   destination[(current_dchannel += dchannels)],
6592 				   destination[(current_dchannel += dchannels)],
6593 				   destination[(current_dchannel += dchannels)],
6594 				   destination[(current_dchannel += dchannels)],
6595 				   destination[(current_dchannel += dchannels)],
6596 				   destination[(current_dchannel += dchannels)]};
6597       v_source = (ags_v8s16) {source[0],
6598 			      source[(current_schannel -= schannels)],
6599 			      source[(current_schannel -= schannels)],
6600 			      source[(current_schannel -= schannels)],
6601 			      source[(current_schannel -= schannels)],
6602 			      source[(current_schannel -= schannels)],
6603 			      source[(current_schannel -= schannels)],
6604 			      source[(current_schannel -= schannels)]};
6605 
6606       /* no scale, just copy */
6607       v_destination += v_source;
6608 
6609       current_dchannel = 0;
6610 
6611       destination[0] = v_destination[0];
6612       destination[(current_dchannel = dchannels)] = v_destination[1];
6613       destination[(current_dchannel += dchannels)] = v_destination[2];
6614       destination[(current_dchannel += dchannels)] = v_destination[3];
6615       destination[(current_dchannel += dchannels)] = v_destination[4];
6616       destination[(current_dchannel += dchannels)] = v_destination[5];
6617       destination[(current_dchannel += dchannels)] = v_destination[6];
6618       destination[(current_dchannel += dchannels)] = v_destination[7];
6619 
6620       /* iterate destination */
6621       destination += (current_dchannel + dchannels);
6622 
6623       /* iterate source */
6624       source += (current_schannel - schannels);
6625     }
6626   }
6627 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
6628   /* vectorized function */
6629   if(count > 8){
6630     limit = count - (count % 8);
6631 
6632     for(; i < limit; i += 8){
6633       int v_result[8];
6634 
6635       current_dchannel = 0;
6636       current_schannel = 0;
6637 
6638       int v_destination[] = {(int) destination[0],
6639 			     (int) destination[(current_dchannel = dchannels)],
6640 			     (int) destination[(current_dchannel += dchannels)],
6641 			     (int) destination[(current_dchannel += dchannels)],
6642 			     (int) destination[(current_dchannel += dchannels)],
6643 			     (int) destination[(current_dchannel += dchannels)],
6644 			     (int) destination[(current_dchannel += dchannels)],
6645 			     (int) destination[(current_dchannel += dchannels)]};
6646 
6647       int v_source[] = {(int) source[0],
6648 			(int) source[(current_schannel -= schannels)],
6649 			(int) source[(current_schannel -= schannels)],
6650 			(int) source[(current_schannel -= schannels)],
6651 			(int) source[(current_schannel -= schannels)],
6652 			(int) source[(current_schannel -= schannels)],
6653 			(int) source[(current_schannel -= schannels)],
6654 			(int) source[(current_schannel -= schannels)]};
6655 
6656       /* no scale, just copy */
6657       vDSP_vaddi(v_destination, 1, v_source, 1, v_result, 1, 8);
6658 
6659       current_dchannel = 0;
6660 
6661       destination[0] = (gint16) v_result[0];
6662       destination[(current_dchannel = dchannels)] = (gint16) v_result[1];
6663       destination[(current_dchannel += dchannels)] = (gint16) v_result[2];
6664       destination[(current_dchannel += dchannels)] = (gint16) v_result[3];
6665       destination[(current_dchannel += dchannels)] = (gint16) v_result[4];
6666       destination[(current_dchannel += dchannels)] = (gint16) v_result[5];
6667       destination[(current_dchannel += dchannels)] = (gint16) v_result[6];
6668       destination[(current_dchannel += dchannels)] = (gint16) v_result[7];
6669 
6670       /* iterate destination */
6671       destination += (current_dchannel + dchannels);
6672 
6673       /* iterate source */
6674       source += (current_schannel - schannels);
6675     }
6676   }
6677 #else
6678   /* unrolled function */
6679   if(count > 8){
6680     limit = count - (count % 8);
6681 
6682     for(; i < limit; i += 8){
6683       current_dchannel = 0;
6684       current_schannel = 0;
6685 
6686       destination[0] = (gint16) 0xffff & ((gint32) (destination[0] + source[0]));
6687       destination[current_dchannel] = (gint16) 0xffff & ((gint32) (destination[(current_dchannel = dchannels)] + source[(current_schannel -= schannels)]));
6688       destination[current_dchannel] = (gint16) 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + source[(current_schannel -= schannels)]));
6689       destination[current_dchannel] = (gint16) 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + source[(current_schannel -= schannels)]));
6690       destination[current_dchannel] = (gint16) 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + source[(current_schannel -= schannels)]));
6691       destination[current_dchannel] = (gint16) 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + source[(current_schannel -= schannels)]));
6692       destination[current_dchannel] = (gint16) 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + source[(current_schannel -= schannels)]));
6693       destination[current_dchannel] = (gint16) 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + source[(current_schannel -= schannels)]));
6694 
6695       /* iterate destination */
6696       destination += (current_dchannel + dchannels);
6697 
6698       /* iterate source */
6699       source += (current_schannel - schannels);
6700     }
6701   }
6702 #endif
6703 
6704   for(; i < count; i++){
6705     destination[0] = (gint16) 0xffff & ((gint32) (destination[0] + source[0]));
6706 
6707     destination += dchannels;
6708     source -= schannels;
6709   }
6710 }
6711 
6712 /**
6713  * ags_audio_buffer_util_pong_s24:
6714  * @destination: the destination
6715  * @dchannels: the destination channels
6716  * @source: the source
6717  * @schannels: the source channels
6718  * @count: the count of frames
6719  *
6720  * Pingpong copy @source to @destination.
6721  *
6722  * Since: 3.4.0
6723  */
6724 void
ags_audio_buffer_util_pong_s24(gint32 * destination,guint dchannels,gint32 * source,guint schannels,guint count)6725 ags_audio_buffer_util_pong_s24(gint32 *destination, guint dchannels,
6726 			       gint32 *source, guint schannels,
6727 			       guint count)
6728 {
6729   guint limit;
6730   gint current_dchannel, current_schannel;
6731   guint i;
6732 
6733   if(destination == NULL ||
6734      source == NULL){
6735     return;
6736   }
6737 
6738   i = 0;
6739 
6740 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
6741   /* vectorized function */
6742   if(count > 8){
6743     limit = count - (count % 8);
6744 
6745     for(; i < limit; i += 8){
6746       ags_v8s32 v_destination;
6747       ags_v8s32 v_source;
6748 
6749       current_dchannel = 0;
6750       current_schannel = 0;
6751 
6752       v_destination = (ags_v8s32) {destination[0],
6753 				   destination[(current_dchannel = dchannels)],
6754 				   destination[(current_dchannel += dchannels)],
6755 				   destination[(current_dchannel += dchannels)],
6756 				   destination[(current_dchannel += dchannels)],
6757 				   destination[(current_dchannel += dchannels)],
6758 				   destination[(current_dchannel += dchannels)],
6759 				   destination[(current_dchannel += dchannels)]};
6760 
6761       v_source = (ags_v8s32) {source[0],
6762 			      source[(current_schannel -= schannels)],
6763 			      source[(current_schannel -= schannels)],
6764 			      source[(current_schannel -= schannels)],
6765 			      source[(current_schannel -= schannels)],
6766 			      source[(current_schannel -= schannels)],
6767 			      source[(current_schannel -= schannels)],
6768 			      source[(current_schannel -= schannels)]};
6769 
6770       /* no scale, just copy */
6771       v_destination += v_source;
6772 
6773       current_dchannel = 0;
6774 
6775       destination[0] = v_destination[0];
6776       destination[(current_dchannel = dchannels)] = v_destination[1];
6777       destination[(current_dchannel += dchannels)] = v_destination[2];
6778       destination[(current_dchannel += dchannels)] = v_destination[3];
6779       destination[(current_dchannel += dchannels)] = v_destination[4];
6780       destination[(current_dchannel += dchannels)] = v_destination[5];
6781       destination[(current_dchannel += dchannels)] = v_destination[6];
6782       destination[(current_dchannel += dchannels)] = v_destination[7];
6783 
6784       /* iterate destination */
6785       destination += (current_dchannel + dchannels);
6786 
6787       /* iterate source */
6788       source += (current_schannel - schannels);
6789     }
6790   }
6791 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
6792   /* vectorized function */
6793   if(count > 8){
6794     limit = count - (count % 8);
6795 
6796     for(; i < limit; i += 8){
6797       int v_result[8];
6798 
6799       current_dchannel = 0;
6800       current_schannel = 0;
6801 
6802       int v_destination[] = {(int) destination[0],
6803 			     (int) destination[(current_dchannel = dchannels)],
6804 			     (int) destination[(current_dchannel += dchannels)],
6805 			     (int) destination[(current_dchannel += dchannels)],
6806 			     (int) destination[(current_dchannel += dchannels)],
6807 			     (int) destination[(current_dchannel += dchannels)],
6808 			     (int) destination[(current_dchannel += dchannels)],
6809 			     (int) destination[(current_dchannel += dchannels)]};
6810 
6811       int v_source[] = {(int) source[0],
6812 			(int) source[(current_schannel -= schannels)],
6813 			(int) source[(current_schannel -= schannels)],
6814 			(int) source[(current_schannel -= schannels)],
6815 			(int) source[(current_schannel -= schannels)],
6816 			(int) source[(current_schannel -= schannels)],
6817 			(int) source[(current_schannel -= schannels)],
6818 			(int) source[(current_schannel -= schannels)]};
6819 
6820       /* no scale, just copy */
6821       vDSP_vaddi(v_destination, 1, v_source, 1, v_result, 1, 8);
6822 
6823       current_dchannel = 0;
6824 
6825       destination[0] = (gint32) v_result[0];
6826       destination[(current_dchannel = dchannels)] = (gint32) v_result[1];
6827       destination[(current_dchannel += dchannels)] = (gint32) v_result[2];
6828       destination[(current_dchannel += dchannels)] = (gint32) v_result[3];
6829       destination[(current_dchannel += dchannels)] = (gint32) v_result[4];
6830       destination[(current_dchannel += dchannels)] = (gint32) v_result[5];
6831       destination[(current_dchannel += dchannels)] = (gint32) v_result[6];
6832       destination[(current_dchannel += dchannels)] = (gint32) v_result[7];
6833 
6834       /* iterate destination */
6835       destination += (current_dchannel + dchannels);
6836 
6837       /* iterate source */
6838       source += (current_schannel - schannels);
6839     }
6840   }
6841 #else
6842   /* unrolled function */
6843   if(count > 8){
6844     limit = count - (count % 8);
6845 
6846     for(; i < limit; i += 8){
6847       current_dchannel = 0;
6848       current_schannel = 0;
6849 
6850       destination[0] = 0xffffffff & ((gint32) (destination[0] + source[0]));
6851       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel = dchannels)] + source[(current_schannel -= schannels)]));
6852       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + source[(current_schannel -= schannels)]));
6853       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + source[(current_schannel -= schannels)]));
6854       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + source[(current_schannel -= schannels)]));
6855       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + source[(current_schannel -= schannels)]));
6856       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + source[(current_schannel -= schannels)]));
6857       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + source[(current_schannel -= schannels)]));
6858 
6859       /* iterate destination */
6860       destination += (current_dchannel + dchannels);
6861 
6862       /* iterate source */
6863       source += (current_schannel - schannels);
6864     }
6865   }
6866 #endif
6867 
6868   for(; i < count; i++){
6869     destination[0] = 0xffffffff & ((gint32) (destination[0] + source[0]));
6870 
6871     destination += dchannels;
6872     source -= schannels;
6873   }
6874 }
6875 
6876 /**
6877  * ags_audio_buffer_util_pong_s32:
6878  * @destination: the destination
6879  * @dchannels: the destination channels
6880  * @source: the source
6881  * @schannels: the source channels
6882  * @count: the count of frames
6883  *
6884  * Pingpong copy @source to @destination.
6885  *
6886  * Since: 3.4.0
6887  */
6888 void
ags_audio_buffer_util_pong_s32(gint32 * destination,guint dchannels,gint32 * source,guint schannels,guint count)6889 ags_audio_buffer_util_pong_s32(gint32 *destination, guint dchannels,
6890 			       gint32 *source, guint schannels,
6891 			       guint count)
6892 {
6893   guint limit;
6894   gint current_dchannel, current_schannel;
6895   guint i;
6896 
6897   if(destination == NULL ||
6898      source == NULL){
6899     return;
6900   }
6901 
6902   i = 0;
6903 
6904 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
6905   /* vectorized function */
6906   if(count > 8){
6907     limit = count - (count % 8);
6908 
6909     for(; i < limit; i += 8){
6910       ags_v8s32 v_destination;
6911       ags_v8s32 v_source;
6912 
6913       current_dchannel = 0;
6914       current_schannel = 0;
6915 
6916       v_destination = (ags_v8s32) {destination[0],
6917 				   destination[(current_dchannel = dchannels)],
6918 				   destination[(current_dchannel += dchannels)],
6919 				   destination[(current_dchannel += dchannels)],
6920 				   destination[(current_dchannel += dchannels)],
6921 				   destination[(current_dchannel += dchannels)],
6922 				   destination[(current_dchannel += dchannels)],
6923 				   destination[(current_dchannel += dchannels)]};
6924 
6925       v_source = (ags_v8s32) {source[0],
6926 			      source[(current_schannel -= schannels)],
6927 			      source[(current_schannel -= schannels)],
6928 			      source[(current_schannel -= schannels)],
6929 			      source[(current_schannel -= schannels)],
6930 			      source[(current_schannel -= schannels)],
6931 			      source[(current_schannel -= schannels)],
6932 			      source[(current_schannel -= schannels)]};
6933 
6934       /* no scale, just copy */
6935       v_destination += v_source;
6936 
6937       current_dchannel = 0;
6938 
6939       destination[0] = v_destination[0];
6940       destination[(current_dchannel = dchannels)] = v_destination[1];
6941       destination[(current_dchannel += dchannels)] = v_destination[2];
6942       destination[(current_dchannel += dchannels)] = v_destination[3];
6943       destination[(current_dchannel += dchannels)] = v_destination[4];
6944       destination[(current_dchannel += dchannels)] = v_destination[5];
6945       destination[(current_dchannel += dchannels)] = v_destination[6];
6946       destination[(current_dchannel += dchannels)] = v_destination[7];
6947 
6948       /* iterate destination */
6949       destination += (current_dchannel + dchannels);
6950 
6951       /* iterate source */
6952       source += (current_schannel - schannels);
6953     }
6954   }
6955 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
6956   /* vectorized function */
6957   if(count > 8){
6958     limit = count - (count % 8);
6959 
6960     for(; i < limit; i += 8){
6961       int v_result[8];
6962 
6963       current_dchannel = 0;
6964       current_schannel = 0;
6965 
6966       int v_destination[] = {(int) destination[0],
6967 			     (int) destination[(current_dchannel = dchannels)],
6968 			     (int) destination[(current_dchannel += dchannels)],
6969 			     (int) destination[(current_dchannel += dchannels)],
6970 			     (int) destination[(current_dchannel += dchannels)],
6971 			     (int) destination[(current_dchannel += dchannels)],
6972 			     (int) destination[(current_dchannel += dchannels)],
6973 			     (int) destination[(current_dchannel += dchannels)]};
6974 
6975       int v_source[] = {(int) source[0],
6976 			(int) source[(current_schannel -= schannels)],
6977 			(int) source[(current_schannel -= schannels)],
6978 			(int) source[(current_schannel -= schannels)],
6979 			(int) source[(current_schannel -= schannels)],
6980 			(int) source[(current_schannel -= schannels)],
6981 			(int) source[(current_schannel -= schannels)],
6982 			(int) source[(current_schannel -= schannels)]};
6983 
6984       /* no scale, just copy */
6985       vDSP_vaddi(v_destination, 1, v_source, 1, v_result, 1, 8);
6986 
6987       current_dchannel = 0;
6988 
6989       destination[0] = (gint32) v_result[0];
6990       destination[(current_dchannel = dchannels)] = (gint32) v_result[1];
6991       destination[(current_dchannel += dchannels)] = (gint32) v_result[2];
6992       destination[(current_dchannel += dchannels)] = (gint32) v_result[3];
6993       destination[(current_dchannel += dchannels)] = (gint32) v_result[4];
6994       destination[(current_dchannel += dchannels)] = (gint32) v_result[5];
6995       destination[(current_dchannel += dchannels)] = (gint32) v_result[6];
6996       destination[(current_dchannel += dchannels)] = (gint32) v_result[7];
6997 
6998       /* iterate destination */
6999       destination += (current_dchannel + dchannels);
7000 
7001       /* iterate source */
7002       source += (current_schannel - schannels);
7003     }
7004   }
7005 #else
7006   /* unrolled function */
7007   if(count > 8){
7008     limit = count - (count % 8);
7009 
7010     for(; i < limit; i += 8){
7011       destination[0] = 0xffffffff & ((gint64) (destination[0] + source[0]));
7012       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel = dchannels)] + source[(current_schannel -= schannels)]));
7013       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + source[(current_schannel -= schannels)]));
7014       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + source[(current_schannel -= schannels)]));
7015       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + source[(current_schannel -= schannels)]));
7016       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + source[(current_schannel -= schannels)]));
7017       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + source[(current_schannel -= schannels)]));
7018       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + source[(current_schannel -= schannels)]));
7019 
7020       /* iterate destination */
7021       destination += (current_dchannel + dchannels);
7022 
7023       /* iterate source */
7024       source += (current_schannel - schannels);
7025     }
7026   }
7027 #endif
7028 
7029   for(; i < count; i++){
7030     destination[0] = 0xffffffff & ((gint64) (destination[0] + source[0]));
7031 
7032     destination += dchannels;
7033     source -= schannels;
7034   }
7035 }
7036 
7037 /**
7038  * ags_audio_buffer_util_pong_s64:
7039  * @destination: the destination
7040  * @dchannels: the destination channels
7041  * @source: the source
7042  * @schannels: the source channels
7043  * @count: the count of frames
7044  *
7045  * Pingpong copy @source to @destination.
7046  *
7047  * Since: 3.4.0
7048  */
7049 void
ags_audio_buffer_util_pong_s64(gint64 * destination,guint dchannels,gint64 * source,guint schannels,guint count)7050 ags_audio_buffer_util_pong_s64(gint64 *destination, guint dchannels,
7051 			       gint64 *source, guint schannels,
7052 			       guint count)
7053 {
7054   guint limit;
7055   gint current_dchannel, current_schannel;
7056   guint i;
7057 
7058   if(destination == NULL ||
7059      source == NULL){
7060     return;
7061   }
7062 
7063   i = 0;
7064 
7065 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
7066   /* vectorized function */
7067   if(count > 8){
7068     limit = count - (count % 8);
7069 
7070     for(; i < limit; i += 8){
7071       ags_v8s64 v_destination;
7072       ags_v8s64 v_source;
7073 
7074       current_dchannel = 0;
7075       current_schannel = 0;
7076 
7077       v_destination = (ags_v8s64) {destination[0],
7078 				   destination[(current_dchannel = dchannels)],
7079 				   destination[(current_dchannel += dchannels)],
7080 				   destination[(current_dchannel += dchannels)],
7081 				   destination[(current_dchannel += dchannels)],
7082 				   destination[(current_dchannel += dchannels)],
7083 				   destination[(current_dchannel += dchannels)],
7084 				   destination[(current_dchannel += dchannels)]};
7085 
7086       v_source = (ags_v8s64) {source[0],
7087 			      source[(current_schannel -= schannels)],
7088 			      source[(current_schannel -= schannels)],
7089 			      source[(current_schannel -= schannels)],
7090 			      source[(current_schannel -= schannels)],
7091 			      source[(current_schannel -= schannels)],
7092 			      source[(current_schannel -= schannels)],
7093 			      source[(current_schannel -= schannels)]};
7094 
7095       /* no scale, just copy */
7096       v_destination += v_source;
7097 
7098       current_dchannel = 0;
7099 
7100       destination[0] = v_destination[0];
7101       destination[(current_dchannel = dchannels)] = v_destination[1];
7102       destination[(current_dchannel += dchannels)] = v_destination[2];
7103       destination[(current_dchannel += dchannels)] = v_destination[3];
7104       destination[(current_dchannel += dchannels)] = v_destination[4];
7105       destination[(current_dchannel += dchannels)] = v_destination[5];
7106       destination[(current_dchannel += dchannels)] = v_destination[6];
7107       destination[(current_dchannel += dchannels)] = v_destination[7];
7108 
7109       /* iterate destination */
7110       destination += (current_dchannel + dchannels);
7111 
7112       /* iterate source */
7113       source += (current_schannel - schannels);
7114     }
7115   }
7116 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
7117   /* vectorized function */
7118   if(count > 8){
7119     limit = count - (count % 8);
7120 
7121     for(; i < limit; i += 8){
7122       int v_result[8];
7123 
7124       current_dchannel = 0;
7125       current_schannel = 0;
7126 
7127       int v_destination[] = {(int) destination[0],
7128 			     (int) destination[(current_dchannel = dchannels)],
7129 			     (int) destination[(current_dchannel += dchannels)],
7130 			     (int) destination[(current_dchannel += dchannels)],
7131 			     (int) destination[(current_dchannel += dchannels)],
7132 			     (int) destination[(current_dchannel += dchannels)],
7133 			     (int) destination[(current_dchannel += dchannels)],
7134 			     (int) destination[(current_dchannel += dchannels)]};
7135 
7136       int v_source[] = {(int) source[0],
7137 			(int) source[(current_schannel -= schannels)],
7138 			(int) source[(current_schannel -= schannels)],
7139 			(int) source[(current_schannel -= schannels)],
7140 			(int) source[(current_schannel -= schannels)],
7141 			(int) source[(current_schannel -= schannels)],
7142 			(int) source[(current_schannel -= schannels)],
7143 			(int) source[(current_schannel -= schannels)]};
7144 
7145       /* no scale, just copy */
7146       vDSP_vaddi(v_destination, 1, v_source, 1, v_result, 1, 8);
7147 
7148       current_dchannel = 0;
7149 
7150       destination[0] = (gint64) v_result[0];
7151       destination[(current_dchannel = dchannels)] = (gint64) v_result[1];
7152       destination[(current_dchannel += dchannels)] = (gint64) v_result[2];
7153       destination[(current_dchannel += dchannels)] = (gint64) v_result[3];
7154       destination[(current_dchannel += dchannels)] = (gint64) v_result[4];
7155       destination[(current_dchannel += dchannels)] = (gint64) v_result[5];
7156       destination[(current_dchannel += dchannels)] = (gint64) v_result[6];
7157       destination[(current_dchannel += dchannels)] = (gint64) v_result[7];
7158 
7159       /* iterate destination */
7160       destination += (current_dchannel + dchannels);
7161 
7162       /* iterate source */
7163       source += (current_schannel - schannels);
7164     }
7165   }
7166 #else
7167   /* unrolled function */
7168   if(count > 8){
7169     limit = count - (count % 8);
7170 
7171     for(; i < limit; i += 8){
7172       current_dchannel = 0;
7173       current_schannel = 0;
7174 
7175       destination[0] = 0xffffffffffffffff & ((gint64) (destination[0] + source[0]));
7176       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel = dchannels)] + source[(current_schannel -= schannels)]));
7177       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + source[(current_schannel -= schannels)]));
7178       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + source[(current_schannel -= schannels)]));
7179       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + source[(current_schannel -= schannels)]));
7180       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + source[(current_schannel -= schannels)]));
7181       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + source[(current_schannel -= schannels)]));
7182       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + source[(current_schannel -= schannels)]));
7183 
7184       /* iterate destination */
7185       destination += (current_dchannel + dchannels);
7186 
7187       /* iterate source */
7188       source += (current_schannel - schannels);
7189     }
7190   }
7191 #endif
7192 
7193   for(; i < count; i++){
7194     destination[0] = 0xffffffffffffffff & ((gint64) (destination[0] + source[0]));
7195 
7196     destination += dchannels;
7197     source -= schannels;
7198   }
7199 }
7200 
7201 /**
7202  * ags_audio_buffer_util_pong_float:
7203  * @destination: the destination
7204  * @dchannels: the destination channels
7205  * @source: the source
7206  * @schannels: the source channels
7207  * @count: the count of frames
7208  *
7209  * Pingpong copy @source to @destination.
7210  *
7211  * Since: 3.4.0
7212  */
7213 void
ags_audio_buffer_util_pong_float(gfloat * destination,guint dchannels,gfloat * source,guint schannels,guint count)7214 ags_audio_buffer_util_pong_float(gfloat *destination, guint dchannels,
7215 				 gfloat *source, guint schannels,
7216 				 guint count)
7217 {
7218   guint limit;
7219   gint current_dchannel, current_schannel;
7220   guint i;
7221 
7222   if(destination == NULL ||
7223      source == NULL){
7224     return;
7225   }
7226 
7227   i = 0;
7228 
7229 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
7230   /* vectorized function */
7231   if(count > 8){
7232     limit = count - (count % 8);
7233 
7234     for(; i < limit; i += 8){
7235       ags_v8float v_destination;
7236       ags_v8float v_source;
7237 
7238       current_dchannel = 0;
7239       current_schannel = 0;
7240 
7241       v_destination = (ags_v8float) {destination[0],
7242 				     destination[(current_dchannel = dchannels)],
7243 				     destination[(current_dchannel += dchannels)],
7244 				     destination[(current_dchannel += dchannels)],
7245 				     destination[(current_dchannel += dchannels)],
7246 				     destination[(current_dchannel += dchannels)],
7247 				     destination[(current_dchannel += dchannels)],
7248 				     destination[(current_dchannel += dchannels)]};
7249 
7250       v_source = (ags_v8float) {source[0],
7251 				source[(current_schannel -= schannels)],
7252 				source[(current_schannel -= schannels)],
7253 				source[(current_schannel -= schannels)],
7254 				source[(current_schannel -= schannels)],
7255 				source[(current_schannel -= schannels)],
7256 				source[(current_schannel -= schannels)],
7257 				source[(current_schannel -= schannels)]};
7258 
7259       /* just copy */
7260       v_destination += v_source;
7261 
7262       current_dchannel = 0;
7263 
7264       destination[0] = v_destination[0];
7265       destination[(current_dchannel = dchannels)] = v_destination[1];
7266       destination[(current_dchannel += dchannels)] = v_destination[2];
7267       destination[(current_dchannel += dchannels)] = v_destination[3];
7268       destination[(current_dchannel += dchannels)] = v_destination[4];
7269       destination[(current_dchannel += dchannels)] = v_destination[5];
7270       destination[(current_dchannel += dchannels)] = v_destination[6];
7271       destination[(current_dchannel += dchannels)] = v_destination[7];
7272 
7273       /* iterate destination */
7274       destination += (current_dchannel + dchannels);
7275 
7276       /* iterate source */
7277       source += (current_schannel - schannels);
7278     }
7279   }
7280 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
7281   /* vectorized function */
7282   if(count > 8){
7283     limit = count - (count % 8);
7284 
7285     for(; i < limit; i += 8){
7286       double v_result[8];
7287 
7288       current_dchannel = 0;
7289       current_schannel = 0;
7290 
7291       double v_destination[] = {(double) destination[0],
7292 				(double) destination[(current_dchannel = dchannels)],
7293 				(double) destination[(current_dchannel += dchannels)],
7294 				(double) destination[(current_dchannel += dchannels)],
7295 				(double) destination[(current_dchannel += dchannels)],
7296 				(double) destination[(current_dchannel += dchannels)],
7297 				(double) destination[(current_dchannel += dchannels)],
7298 				(double) destination[(current_dchannel += dchannels)]};
7299 
7300       double v_source[] = {(double) source[0],
7301 			   (double) source[(current_schannel -= schannels)],
7302 			   (double) source[(current_schannel -= schannels)],
7303 			   (double) source[(current_schannel -= schannels)],
7304 			   (double) source[(current_schannel -= schannels)],
7305 			   (double) source[(current_schannel -= schannels)],
7306 			   (double) source[(current_schannel -= schannels)],
7307 			   (double) source[(current_schannel -= schannels)]};
7308 
7309       /* no scale, just copy */
7310       vDSP_vaddD(v_destination, 1, v_source, 1, v_result, 1, 8);
7311 
7312       current_dchannel = 0;
7313 
7314       destination[0] = (gfloat) v_result[0];
7315       destination[(current_dchannel = dchannels)] = (gfloat) v_result[1];
7316       destination[(current_dchannel += dchannels)] = (gfloat) v_result[2];
7317       destination[(current_dchannel += dchannels)] = (gfloat) v_result[3];
7318       destination[(current_dchannel += dchannels)] = (gfloat) v_result[4];
7319       destination[(current_dchannel += dchannels)] = (gfloat) v_result[5];
7320       destination[(current_dchannel += dchannels)] = (gfloat) v_result[6];
7321       destination[(current_dchannel += dchannels)] = (gfloat) v_result[7];
7322 
7323       /* iterate destination */
7324       destination += (current_dchannel + dchannels);
7325 
7326       /* iterate source */
7327       source += (current_schannel - schannels);
7328     }
7329   }
7330 #else
7331   /* unrolled function */
7332   if(count > 8){
7333     limit = count - (count % 8);
7334 
7335     for(; i < limit; i += 8){
7336       destination[0] = (gfloat) ((gdouble) (destination[0] + (gdouble) (source[0])));
7337       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (source[(current_schannel -= schannels)])));
7338       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel -= schannels)])));
7339       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel -= schannels)])));
7340       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel -= schannels)])));
7341       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel -= schannels)])));
7342       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel -= schannels)])));
7343       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel -= schannels)])));
7344 
7345       /* iterate destination */
7346       destination += (current_dchannel + dchannels);
7347 
7348       /* iterate source */
7349       source += (current_schannel - schannels);
7350     }
7351   }
7352 #endif
7353 
7354   for(; i < count; i++){
7355     destination[0] = (gfloat) ((gdouble) (destination[0] + (gdouble) (source[0])));
7356 
7357     destination += dchannels;
7358     source -= schannels;
7359   }
7360 }
7361 
7362 /**
7363  * ags_audio_buffer_util_pong_double:
7364  * @destination: the destination
7365  * @dchannels: the destination channels
7366  * @source: the source
7367  * @schannels: the source channels
7368  * @count: the count of frames
7369  *
7370  * Pingpong copy @source to @destination.
7371  *
7372  * Since: 3.4.0
7373  */
7374 void
ags_audio_buffer_util_pong_double(gdouble * destination,guint dchannels,gdouble * source,guint schannels,guint count)7375 ags_audio_buffer_util_pong_double(gdouble *destination, guint dchannels,
7376 				  gdouble *source, guint schannels,
7377 				  guint count)
7378 {
7379   guint limit;
7380   gint current_dchannel, current_schannel;
7381   guint i;
7382 
7383   if(destination == NULL ||
7384      source == NULL){
7385     return;
7386   }
7387 
7388   i = 0;
7389 
7390 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
7391   /* vectorized function */
7392   if(count > 8){
7393     limit = count - (count % 8);
7394 
7395     for(; i < limit; i += 8){
7396       ags_v8double v_destination;
7397       ags_v8double v_source;
7398 
7399       current_dchannel = 0;
7400       current_schannel = 0;
7401 
7402       v_destination = (ags_v8double) {destination[0],
7403 				      destination[(current_dchannel = dchannels)],
7404 				      destination[(current_dchannel += dchannels)],
7405 				      destination[(current_dchannel += dchannels)],
7406 				      destination[(current_dchannel += dchannels)],
7407 				      destination[(current_dchannel += dchannels)],
7408 				      destination[(current_dchannel += dchannels)],
7409 				      destination[(current_dchannel += dchannels)]};
7410 
7411       v_source = (ags_v8double) {source[0],
7412 				 source[(current_schannel -= schannels)],
7413 				 source[(current_schannel -= schannels)],
7414 				 source[(current_schannel -= schannels)],
7415 				 source[(current_schannel -= schannels)],
7416 				 source[(current_schannel -= schannels)],
7417 				 source[(current_schannel -= schannels)],
7418 				 source[(current_schannel -= schannels)]};
7419 
7420       /* just copy */
7421       v_destination += v_source;
7422 
7423       current_dchannel = 0;
7424 
7425       destination[0] = v_destination[0];
7426       destination[(current_dchannel = dchannels)] = v_destination[1];
7427       destination[(current_dchannel += dchannels)] = v_destination[2];
7428       destination[(current_dchannel += dchannels)] = v_destination[3];
7429       destination[(current_dchannel += dchannels)] = v_destination[4];
7430       destination[(current_dchannel += dchannels)] = v_destination[5];
7431       destination[(current_dchannel += dchannels)] = v_destination[6];
7432       destination[(current_dchannel += dchannels)] = v_destination[7];
7433 
7434       /* iterate destination */
7435       destination += (current_dchannel + dchannels);
7436 
7437       /* iterate source */
7438       source += (current_schannel - schannels);
7439     }
7440   }
7441 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
7442   /* vectorized function */
7443   if(count > 8){
7444     limit = count - (count % 8);
7445 
7446     for(; i < limit; i += 8){
7447       double v_result[8];
7448 
7449       current_dchannel = 0;
7450       current_schannel = 0;
7451 
7452       double v_destination[] = {(double) destination[0],
7453 				(double) destination[(current_dchannel = dchannels)],
7454 				(double) destination[(current_dchannel += dchannels)],
7455 				(double) destination[(current_dchannel += dchannels)],
7456 				(double) destination[(current_dchannel += dchannels)],
7457 				(double) destination[(current_dchannel += dchannels)],
7458 				(double) destination[(current_dchannel += dchannels)],
7459 				(double) destination[(current_dchannel += dchannels)]};
7460 
7461       double v_source[] = {(double) source[0],
7462 			   (double) source[(current_schannel -= schannels)],
7463 			   (double) source[(current_schannel -= schannels)],
7464 			   (double) source[(current_schannel -= schannels)],
7465 			   (double) source[(current_schannel -= schannels)],
7466 			   (double) source[(current_schannel -= schannels)],
7467 			   (double) source[(current_schannel -= schannels)],
7468 			   (double) source[(current_schannel -= schannels)]};
7469 
7470       /* no scale, just copy */
7471       vDSP_vaddD(v_destination, 1, v_source, 1, v_result, 1, 8);
7472 
7473       current_dchannel = 0;
7474 
7475       destination[0] = (gdouble) v_result[0];
7476       destination[(current_dchannel = dchannels)] = (gdouble) v_result[1];
7477       destination[(current_dchannel += dchannels)] = (gdouble) v_result[2];
7478       destination[(current_dchannel += dchannels)] = (gdouble) v_result[3];
7479       destination[(current_dchannel += dchannels)] = (gdouble) v_result[4];
7480       destination[(current_dchannel += dchannels)] = (gdouble) v_result[5];
7481       destination[(current_dchannel += dchannels)] = (gdouble) v_result[6];
7482       destination[(current_dchannel += dchannels)] = (gdouble) v_result[7];
7483 
7484       /* iterate destination */
7485       destination += (current_dchannel + dchannels);
7486 
7487       /* iterate source */
7488       source += (current_schannel - schannels);
7489     }
7490   }
7491 #else
7492   /* unrolled function */
7493   if(count > 8){
7494     limit = count - (count % 8);
7495 
7496     for(; i < limit; i += 8){
7497       current_dchannel = 0;
7498       current_schannel = 0;
7499 
7500       destination[0] = ((gdouble) (destination[0] + (gdouble) (source[0])));
7501       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (source[(current_schannel -= schannels)])));
7502       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel -= schannels)])));
7503       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel -= schannels)])));
7504       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel -= schannels)])));
7505       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel -= schannels)])));
7506       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel -= schannels)])));
7507       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel -= schannels)])));
7508 
7509       /* iterate destination */
7510       destination += (current_dchannel + dchannels);
7511 
7512       /* iterate source */
7513       source += (current_schannel - schannels);
7514     }
7515   }
7516 #endif
7517 
7518   for(; i < count; i++){
7519     destination[0] = ((gdouble) ((destination[0]) + (gdouble) (source[0])));
7520 
7521     destination += dchannels;
7522     source -= schannels;
7523   }
7524 }
7525 
7526 /**
7527  * ags_audio_buffer_util_pong_complex:
7528  * @destination: the destination
7529  * @dchannels: the destination channels
7530  * @source: the source
7531  * @schannels: the source channels
7532  * @count: the count of frames
7533  *
7534  * Pingpong copy @source to @destination.
7535  *
7536  * Since: 3.4.0
7537  */
7538 void
ags_audio_buffer_util_pong_complex(AgsComplex * destination,guint dchannels,AgsComplex * source,guint schannels,guint count)7539 ags_audio_buffer_util_pong_complex(AgsComplex *destination, guint dchannels,
7540 				   AgsComplex *source, guint schannels,
7541 				   guint count)
7542 {
7543   guint i;
7544 
7545   if(destination == NULL ||
7546      source == NULL){
7547     return;
7548   }
7549 
7550   i = 0;
7551 
7552   for(; i < count; i++){
7553     double _Complex z0, z1;
7554 
7555     z0 = ags_complex_get(destination);
7556     z1 = ags_complex_get(source);
7557 
7558     ags_complex_set(destination,
7559 		    z0 + z1);
7560 
7561     destination += dchannels;
7562     source -= schannels;
7563   }
7564 }
7565 
7566 /**
7567  * ags_audio_buffer_util_pong:
7568  * @destination: the destination
7569  * @dchannels: the destination channels
7570  * @source: the source
7571  * @schannels: the source channels
7572  * @count: the count of frames
7573  * @format: the format
7574  *
7575  * Pingpong copy @source to @destination.
7576  *
7577  * Since: 3.4.0
7578  */
7579 void
ags_audio_buffer_util_pong(void * destination,guint dchannels,void * source,guint schannels,guint count,guint format)7580 ags_audio_buffer_util_pong(void *destination, guint dchannels,
7581 			   void *source, guint schannels,
7582 			   guint count, guint format)
7583 {
7584   if(destination == NULL ||
7585      source == NULL){
7586     return;
7587   }
7588 
7589   switch(format){
7590   case AGS_AUDIO_BUFFER_UTIL_S8:
7591     {
7592       ags_audio_buffer_util_pong_s8((gint8 *) destination, dchannels,
7593 				    (gint8 *) source, schannels,
7594 				    count);
7595     }
7596     break;
7597   case AGS_AUDIO_BUFFER_UTIL_S16:
7598     {
7599       ags_audio_buffer_util_pong_s16((gint16 *) destination, dchannels,
7600 				     (gint16 *) source, schannels,
7601 				     count);
7602     }
7603     break;
7604   case AGS_AUDIO_BUFFER_UTIL_S24:
7605     {
7606       ags_audio_buffer_util_pong_s24((gint32 *) destination, dchannels,
7607 				     (gint32 *) source, schannels,
7608 				     count);
7609     }
7610     break;
7611   case AGS_AUDIO_BUFFER_UTIL_S32:
7612     {
7613       ags_audio_buffer_util_pong_s32((gint32 *) destination, dchannels,
7614 				     (gint32 *) source, schannels,
7615 				     count);
7616     }
7617     break;
7618   case AGS_AUDIO_BUFFER_UTIL_S64:
7619     {
7620       ags_audio_buffer_util_pong_s64((gint64 *) destination, dchannels,
7621 				     (gint64 *) source, schannels,
7622 				     count);
7623     }
7624     break;
7625   case AGS_AUDIO_BUFFER_UTIL_FLOAT:
7626     {
7627       ags_audio_buffer_util_pong_float((gfloat *) destination, dchannels,
7628 				       (gfloat *) source, schannels,
7629 				       count);
7630     }
7631     break;
7632   case AGS_AUDIO_BUFFER_UTIL_DOUBLE:
7633     {
7634       ags_audio_buffer_util_pong_double((gdouble *) destination, dchannels,
7635 					(gdouble *) source, schannels,
7636 					count);
7637     }
7638     break;
7639   case AGS_AUDIO_BUFFER_UTIL_COMPLEX:
7640     {
7641       ags_audio_buffer_util_pong_complex((AgsComplex *) destination, dchannels,
7642 					 (AgsComplex *) source, schannels,
7643 					 count);
7644     }
7645     break;
7646   default:
7647     g_warning("ags_audio_buffer_util_pong() - unknown format");
7648   }
7649 }
7650 
7651 /**
7652  * ags_audio_buffer_util_copy_s8_to_s8:
7653  * @destination: destination buffer
7654  * @dchannels: destination buffer's count of channels
7655  * @source: source buffer
7656  * @schannels: source buffer's count of channels
7657  * @count: number of frames to copy
7658  *
7659  * Copy audio data using additive strategy.
7660  *
7661  * Since: 3.0.0
7662  */
7663 void
ags_audio_buffer_util_copy_s8_to_s8(gint8 * destination,guint dchannels,gint8 * source,guint schannels,guint count)7664 ags_audio_buffer_util_copy_s8_to_s8(gint8 *destination, guint dchannels,
7665 				    gint8 *source, guint schannels,
7666 				    guint count)
7667 {
7668   guint limit;
7669   guint current_dchannel, current_schannel;
7670   guint i;
7671 
7672   if(destination == NULL ||
7673      source == NULL){
7674     return;
7675   }
7676 
7677   i = 0;
7678 
7679 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
7680   /* vectorized function */
7681   if(count > 8){
7682     limit = count - (count % 8);
7683 
7684     for(; i < limit; i += 8){
7685       ags_v8s8 v_destination;
7686       ags_v8s8 v_source;
7687 
7688       current_dchannel = 0;
7689       current_schannel = 0;
7690 
7691       v_destination = (ags_v8s8) {destination[0],
7692 				  destination[(current_dchannel = dchannels)],
7693 				  destination[(current_dchannel += dchannels)],
7694 				  destination[(current_dchannel += dchannels)],
7695 				  destination[(current_dchannel += dchannels)],
7696 				  destination[(current_dchannel += dchannels)],
7697 				  destination[(current_dchannel += dchannels)],
7698 				  destination[(current_dchannel += dchannels)]};
7699 
7700       v_source = (ags_v8s8) {source[0],
7701 			     source[(current_schannel = schannels)],
7702 			     source[(current_schannel += schannels)],
7703 			     source[(current_schannel += schannels)],
7704 			     source[(current_schannel += schannels)],
7705 			     source[(current_schannel += schannels)],
7706 			     source[(current_schannel += schannels)],
7707 			     source[(current_schannel += schannels)]};
7708 
7709       /* no scale, just copy */
7710       v_destination += v_source;
7711 
7712       current_dchannel = 0;
7713 
7714       destination[0] = v_destination[0];
7715       destination[(current_dchannel = dchannels)] = v_destination[1];
7716       destination[(current_dchannel += dchannels)] = v_destination[2];
7717       destination[(current_dchannel += dchannels)] = v_destination[3];
7718       destination[(current_dchannel += dchannels)] = v_destination[4];
7719       destination[(current_dchannel += dchannels)] = v_destination[5];
7720       destination[(current_dchannel += dchannels)] = v_destination[6];
7721       destination[(current_dchannel += dchannels)] = v_destination[7];
7722 
7723       /* iterate destination */
7724       destination += (current_dchannel + dchannels);
7725 
7726       /* iterate source */
7727       source += (current_schannel + schannels);
7728     }
7729   }
7730 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
7731   /* vectorized function */
7732   if(count > 8){
7733     limit = count - (count % 8);
7734 
7735     for(; i < limit; i += 8){
7736       int v_result[8];
7737 
7738       current_dchannel = 0;
7739       current_schannel = 0;
7740 
7741       int v_destination[] = {(int) destination[0],
7742 			     (int) destination[(current_dchannel = dchannels)],
7743 			     (int) destination[(current_dchannel += dchannels)],
7744 			     (int) destination[(current_dchannel += dchannels)],
7745 			     (int) destination[(current_dchannel += dchannels)],
7746 			     (int) destination[(current_dchannel += dchannels)],
7747 			     (int) destination[(current_dchannel += dchannels)],
7748 			     (int) destination[(current_dchannel += dchannels)]};
7749 
7750       int v_source[] = {(int) source[0],
7751 			(int) source[(current_schannel = schannels)],
7752 			(int) source[(current_schannel += schannels)],
7753 			(int) source[(current_schannel += schannels)],
7754 			(int) source[(current_schannel += schannels)],
7755 			(int) source[(current_schannel += schannels)],
7756 			(int) source[(current_schannel += schannels)],
7757 			(int) source[(current_schannel += schannels)]};
7758 
7759       /* no scale, just copy */
7760       vDSP_vaddi(v_destination, 1, v_source, 1, v_result, 1, 8);
7761 
7762       current_dchannel = 0;
7763 
7764       destination[0] = (gint8) v_result[0];
7765       destination[(current_dchannel = dchannels)] = (gint8) v_result[1];
7766       destination[(current_dchannel += dchannels)] = (gint8) v_result[2];
7767       destination[(current_dchannel += dchannels)] = (gint8) v_result[3];
7768       destination[(current_dchannel += dchannels)] = (gint8) v_result[4];
7769       destination[(current_dchannel += dchannels)] = (gint8) v_result[5];
7770       destination[(current_dchannel += dchannels)] = (gint8) v_result[6];
7771       destination[(current_dchannel += dchannels)] = (gint8) v_result[7];
7772 
7773       /* iterate destination */
7774       destination += (current_dchannel + dchannels);
7775 
7776       /* iterate source */
7777       source += (current_schannel + schannels);
7778     }
7779   }
7780 #else
7781   /* unrolled function */
7782   if(count > 8){
7783     limit = count - (count % 8);
7784 
7785     for(; i < limit; i += 8){
7786       current_dchannel = 0;
7787       current_schannel = 0;
7788 
7789       destination[0] = 0xff & ((gint16) (destination[0] + source[0]));
7790       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel = dchannels)] + source[(current_schannel = schannels)]));
7791       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + source[(current_schannel += schannels)]));
7792       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + source[(current_schannel += schannels)]));
7793       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + source[(current_schannel += schannels)]));
7794       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + source[(current_schannel += schannels)]));
7795       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + source[(current_schannel += schannels)]));
7796       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + source[(current_schannel += schannels)]));
7797 
7798       /* iterate destination */
7799       destination += (current_dchannel + dchannels);
7800 
7801       /* iterate source */
7802       source += (current_schannel + schannels);
7803     }
7804   }
7805 #endif
7806 
7807   for(; i < count; i++){
7808     destination[0] = 0xff & ((gint16) (destination[0] + source[0]));
7809 
7810     destination += dchannels;
7811     source += schannels;
7812   }
7813 }
7814 
7815 /**
7816  * ags_audio_buffer_util_copy_s8_to_s16:
7817  * @destination: destination buffer
7818  * @dchannels: destination buffer's count of channels
7819  * @source: source buffer
7820  * @schannels: source buffer's count of channels
7821  * @count: number of frames to copy
7822  *
7823  * Copy audio data using additive strategy.
7824  *
7825  * Since: 3.0.0
7826  */
7827 void
ags_audio_buffer_util_copy_s8_to_s16(gint16 * destination,guint dchannels,gint8 * source,guint schannels,guint count)7828 ags_audio_buffer_util_copy_s8_to_s16(gint16 *destination, guint dchannels,
7829 				     gint8 *source, guint schannels,
7830 				     guint count)
7831 {
7832   //NOTE:JK: scale = (2^bits_destination / 2.0 - 1.0) / (2^bits_source / 2.0 - 1.0)
7833   static const gdouble scale = 258.00787401574803149606;
7834   guint limit;
7835   guint current_dchannel, current_schannel;
7836   guint i;
7837 
7838   if(destination == NULL ||
7839      source == NULL){
7840     return;
7841   }
7842 
7843   i = 0;
7844 
7845 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
7846   /* vectorized function */
7847   if(count > 8){
7848     limit = count - (count % 8);
7849 
7850     for(; i < limit; i += 8){
7851       ags_v8double v_destination;
7852       ags_v8double v_source;
7853 
7854       current_dchannel = 0;
7855       current_schannel = 0;
7856 
7857       v_destination = (ags_v8double) {(gdouble) destination[0],
7858 				      (gdouble) destination[(current_dchannel = dchannels)],
7859 				      (gdouble) destination[(current_dchannel += dchannels)],
7860 				      (gdouble) destination[(current_dchannel += dchannels)],
7861 				      (gdouble) destination[(current_dchannel += dchannels)],
7862 				      (gdouble) destination[(current_dchannel += dchannels)],
7863 				      (gdouble) destination[(current_dchannel += dchannels)],
7864 				      (gdouble) destination[(current_dchannel += dchannels)]};
7865 
7866       v_source = (ags_v8double) {(gdouble) source[0],
7867 				 (gdouble) source[(current_schannel = schannels)],
7868 				 (gdouble) source[(current_schannel += schannels)],
7869 				 (gdouble) source[(current_schannel += schannels)],
7870 				 (gdouble) source[(current_schannel += schannels)],
7871 				 (gdouble) source[(current_schannel += schannels)],
7872 				 (gdouble) source[(current_schannel += schannels)],
7873 				 (gdouble) source[(current_schannel += schannels)]};
7874 
7875       /* scale and copy */
7876       v_source *= scale;
7877       v_destination += v_source;
7878 
7879       current_dchannel = 0;
7880 
7881       destination[0] = (gint16) v_destination[0];
7882       destination[(current_dchannel = dchannels)] = (gint16) v_destination[1];
7883       destination[(current_dchannel += dchannels)] = (gint16) v_destination[2];
7884       destination[(current_dchannel += dchannels)] = (gint16) v_destination[3];
7885       destination[(current_dchannel += dchannels)] = (gint16) v_destination[4];
7886       destination[(current_dchannel += dchannels)] = (gint16) v_destination[5];
7887       destination[(current_dchannel += dchannels)] = (gint16) v_destination[6];
7888       destination[(current_dchannel += dchannels)] = (gint16) v_destination[7];
7889 
7890       /* iterate destination */
7891       destination += (current_dchannel + dchannels);
7892 
7893       /* iterate source */
7894       source += (current_schannel + schannels);
7895     }
7896   }
7897 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
7898   /* vectorized function */
7899   if(count > 8){
7900     limit = count - (count % 8);
7901 
7902     for(; i < limit; i += 8){
7903       double v_scaled[8];
7904       double v_result[8];
7905       static const double v_scale[1] = { (double) scale };
7906 
7907       current_dchannel = 0;
7908       current_schannel = 0;
7909 
7910       double v_destination[] = {(double) destination[0],
7911 				(double) destination[(current_dchannel = dchannels)],
7912 				(double) destination[(current_dchannel += dchannels)],
7913 				(double) destination[(current_dchannel += dchannels)],
7914 				(double) destination[(current_dchannel += dchannels)],
7915 				(double) destination[(current_dchannel += dchannels)],
7916 				(double) destination[(current_dchannel += dchannels)],
7917 				(double) destination[(current_dchannel += dchannels)]};
7918 
7919       double v_source[] = {(double) source[0],
7920 			   (double) source[(current_schannel = schannels)],
7921 			   (double) source[(current_schannel += schannels)],
7922 			   (double) source[(current_schannel += schannels)],
7923 			   (double) source[(current_schannel += schannels)],
7924 			   (double) source[(current_schannel += schannels)],
7925 			   (double) source[(current_schannel += schannels)],
7926 			   (double) source[(current_schannel += schannels)]};
7927 
7928       /* no scale, just copy */
7929       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
7930       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
7931 
7932       current_dchannel = 0;
7933 
7934       destination[0] = (gint16) v_result[0];
7935       destination[(current_dchannel = dchannels)] = (gint16) v_result[1];
7936       destination[(current_dchannel += dchannels)] = (gint16) v_result[2];
7937       destination[(current_dchannel += dchannels)] = (gint16) v_result[3];
7938       destination[(current_dchannel += dchannels)] = (gint16) v_result[4];
7939       destination[(current_dchannel += dchannels)] = (gint16) v_result[5];
7940       destination[(current_dchannel += dchannels)] = (gint16) v_result[6];
7941       destination[(current_dchannel += dchannels)] = (gint16) v_result[7];
7942 
7943       /* iterate destination */
7944       destination += (current_dchannel + dchannels);
7945 
7946       /* iterate source */
7947       source += (current_schannel + schannels);
7948     }
7949   }
7950 #else
7951   /* unrolled function */
7952   if(count > 8){
7953     limit = count - (count % 8);
7954 
7955     for(; i < limit; i += 8){
7956       current_dchannel = 0;
7957       current_schannel = 0;
7958 
7959       destination[0] = 0xffff & ((gint32) (destination[0] + (gint32) (scale * source[0])));
7960       destination[current_dchannel] = 0xffff & ((gint32) (destination[(current_dchannel = dchannels)] + (gint32) (scale * source[(current_schannel = schannels)])));
7961       destination[current_dchannel] = 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
7962       destination[current_dchannel] = 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
7963       destination[current_dchannel] = 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
7964       destination[current_dchannel] = 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
7965       destination[current_dchannel] = 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
7966       destination[current_dchannel] = 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
7967 
7968       /* iterate destination */
7969       destination += (current_dchannel + dchannels);
7970 
7971       /* iterate source */
7972       source += (current_schannel + schannels);
7973     }
7974   }
7975 #endif
7976 
7977   for(; i < count; i++){
7978     destination[0] = 0xffff & ((gint32) (destination[0] + (gint32) (scale * source[0])));
7979 
7980     destination += dchannels;
7981     source += schannels;
7982   }
7983 }
7984 
7985 /**
7986  * ags_audio_buffer_util_copy_s8_to_s24:
7987  * @destination: destination buffer
7988  * @dchannels: destination buffer's count of channels
7989  * @source: source buffer
7990  * @schannels: source buffer's count of channels
7991  * @count: number of frames to copy
7992  *
7993  * Copy audio data using additive strategy.
7994  *
7995  * Since: 3.0.0
7996  */
7997 void
ags_audio_buffer_util_copy_s8_to_s24(gint32 * destination,guint dchannels,gint8 * source,guint schannels,guint count)7998 ags_audio_buffer_util_copy_s8_to_s24(gint32 *destination, guint dchannels,
7999 				     gint8 *source, guint schannels,
8000 				     guint count)
8001 {
8002   //NOTE:JK: scale = (2^bits_destination / 2.0 - 1.0) / (2^bits_source / 2.0 - 1.0)
8003   static const gdouble scale = 66052.03149606299212598425;
8004   guint limit;
8005   guint current_dchannel, current_schannel;
8006   guint i;
8007 
8008   if(destination == NULL ||
8009      source == NULL){
8010     return;
8011   }
8012 
8013   i = 0;
8014 
8015 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
8016   /* vectorized function */
8017   if(count > 8){
8018     limit = count - (count % 8);
8019 
8020     for(; i < limit; i += 8){
8021       ags_v8double v_destination;
8022       ags_v8double v_source;
8023 
8024       current_dchannel = 0;
8025       current_schannel = 0;
8026 
8027       v_destination = (ags_v8double) {(gdouble) destination[0],
8028 				      (gdouble) destination[(current_dchannel = dchannels)],
8029 				      (gdouble) destination[(current_dchannel += dchannels)],
8030 				      (gdouble) destination[(current_dchannel += dchannels)],
8031 				      (gdouble) destination[(current_dchannel += dchannels)],
8032 				      (gdouble) destination[(current_dchannel += dchannels)],
8033 				      (gdouble) destination[(current_dchannel += dchannels)],
8034 				      (gdouble) destination[(current_dchannel += dchannels)]};
8035 
8036       v_source = (ags_v8double) {(gdouble) source[0],
8037 				 (gdouble) source[(current_schannel = schannels)],
8038 				 (gdouble) source[(current_schannel += schannels)],
8039 				 (gdouble) source[(current_schannel += schannels)],
8040 				 (gdouble) source[(current_schannel += schannels)],
8041 				 (gdouble) source[(current_schannel += schannels)],
8042 				 (gdouble) source[(current_schannel += schannels)],
8043 				 (gdouble) source[(current_schannel += schannels)]};
8044 
8045       /* scale and copy */
8046       v_source *= scale;
8047       v_destination += v_source;
8048 
8049       current_dchannel = 0;
8050 
8051       destination[0] = (gint32) v_destination[0];
8052       destination[(current_dchannel = dchannels)] = (gint32) v_destination[1];
8053       destination[(current_dchannel += dchannels)] = (gint32) v_destination[2];
8054       destination[(current_dchannel += dchannels)] = (gint32) v_destination[3];
8055       destination[(current_dchannel += dchannels)] = (gint32) v_destination[4];
8056       destination[(current_dchannel += dchannels)] = (gint32) v_destination[5];
8057       destination[(current_dchannel += dchannels)] = (gint32) v_destination[6];
8058       destination[(current_dchannel += dchannels)] = (gint32) v_destination[7];
8059 
8060       /* iterate destination */
8061       destination += (current_dchannel + dchannels);
8062 
8063       /* iterate source */
8064       source += (current_schannel + schannels);
8065     }
8066   }
8067 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
8068   /* vectorized function */
8069   if(count > 8){
8070     limit = count - (count % 8);
8071 
8072     for(; i < limit; i += 8){
8073       double v_scaled[8];
8074       double v_result[8];
8075       static const double v_scale[1] = { (double) scale };
8076 
8077       current_dchannel = 0;
8078       current_schannel = 0;
8079 
8080       double v_destination[] = {(double) destination[0],
8081 				(double) destination[(current_dchannel = dchannels)],
8082 				(double) destination[(current_dchannel += dchannels)],
8083 				(double) destination[(current_dchannel += dchannels)],
8084 				(double) destination[(current_dchannel += dchannels)],
8085 				(double) destination[(current_dchannel += dchannels)],
8086 				(double) destination[(current_dchannel += dchannels)],
8087 				(double) destination[(current_dchannel += dchannels)]};
8088 
8089       double v_source[] = {(double) source[0],
8090 			   (double) source[(current_schannel = schannels)],
8091 			   (double) source[(current_schannel += schannels)],
8092 			   (double) source[(current_schannel += schannels)],
8093 			   (double) source[(current_schannel += schannels)],
8094 			   (double) source[(current_schannel += schannels)],
8095 			   (double) source[(current_schannel += schannels)],
8096 			   (double) source[(current_schannel += schannels)]};
8097 
8098       /* no scale, just copy */
8099       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
8100       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
8101 
8102       current_dchannel = 0;
8103 
8104       destination[0] = (gint32) v_result[0];
8105       destination[(current_dchannel = dchannels)] = (gint32) v_result[1];
8106       destination[(current_dchannel += dchannels)] = (gint32) v_result[2];
8107       destination[(current_dchannel += dchannels)] = (gint32) v_result[3];
8108       destination[(current_dchannel += dchannels)] = (gint32) v_result[4];
8109       destination[(current_dchannel += dchannels)] = (gint32) v_result[5];
8110       destination[(current_dchannel += dchannels)] = (gint32) v_result[6];
8111       destination[(current_dchannel += dchannels)] = (gint32) v_result[7];
8112 
8113       /* iterate destination */
8114       destination += (current_dchannel + dchannels);
8115 
8116       /* iterate source */
8117       source += (current_schannel + schannels);
8118     }
8119   }
8120 #else
8121   /* unrolled function */
8122   if(count > 8){
8123     limit = count - (count % 8);
8124 
8125     for(; i < limit; i += 8){
8126       current_dchannel = 0;
8127       current_schannel = 0;
8128 
8129       destination[0] = 0xffffffff & ((gint32) (destination[0] + (gint32) (scale * source[0])));
8130       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel = dchannels)] + (gint32) (scale * source[(current_schannel = schannels)])));
8131       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
8132       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
8133       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
8134       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
8135       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
8136       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
8137 
8138       /* iterate destination */
8139       destination += (current_dchannel + dchannels);
8140 
8141       /* iterate source */
8142       source += (current_schannel + schannels);
8143     }
8144   }
8145 #endif
8146 
8147   for(; i < count; i++){
8148     destination[0] = 0xffffffff & ((gint32) (destination[0] + (gint32) (scale * source[0])));
8149 
8150     destination += dchannels;
8151     source += schannels;
8152   }
8153 }
8154 
8155 /**
8156  * ags_audio_buffer_util_copy_s8_to_s32:
8157  * @destination: destination buffer
8158  * @dchannels: destination buffer's count of channels
8159  * @source: source buffer
8160  * @schannels: source buffer's count of channels
8161  * @count: number of frames to copy
8162  *
8163  * Copy audio data using additive strategy.
8164  *
8165  * Since: 3.0.0
8166  */
8167 void
ags_audio_buffer_util_copy_s8_to_s32(gint32 * destination,guint dchannels,gint8 * source,guint schannels,guint count)8168 ags_audio_buffer_util_copy_s8_to_s32(gint32 *destination, guint dchannels,
8169 				     gint8 *source, guint schannels,
8170 				     guint count)
8171 {
8172   //NOTE:JK: scale = (2^bits_destination / 2.0 - 1.0) / (2^bits_source / 2.0 - 1.0)
8173   static const gdouble scale = 1690931.99212598425196850393;
8174   guint limit;
8175   guint current_dchannel, current_schannel;
8176   guint i;
8177 
8178   if(destination == NULL ||
8179      source == NULL){
8180     return;
8181   }
8182 
8183   i = 0;
8184 
8185 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
8186   /* vectorized function */
8187   if(count > 8){
8188     limit = count - (count % 8);
8189 
8190     for(; i < limit; i += 8){
8191       ags_v8double v_destination;
8192       ags_v8double v_source;
8193 
8194       current_dchannel = 0;
8195       current_schannel = 0;
8196 
8197       v_destination = (ags_v8double) {(gdouble) destination[0],
8198 				      (gdouble) destination[(current_dchannel = dchannels)],
8199 				      (gdouble) destination[(current_dchannel += dchannels)],
8200 				      (gdouble) destination[(current_dchannel += dchannels)],
8201 				      (gdouble) destination[(current_dchannel += dchannels)],
8202 				      (gdouble) destination[(current_dchannel += dchannels)],
8203 				      (gdouble) destination[(current_dchannel += dchannels)],
8204 				      (gdouble) destination[(current_dchannel += dchannels)]};
8205 
8206       v_source = (ags_v8double) {(gdouble) source[0],
8207 				 (gdouble) source[(current_schannel = schannels)],
8208 				 (gdouble) source[(current_schannel += schannels)],
8209 				 (gdouble) source[(current_schannel += schannels)],
8210 				 (gdouble) source[(current_schannel += schannels)],
8211 				 (gdouble) source[(current_schannel += schannels)],
8212 				 (gdouble) source[(current_schannel += schannels)],
8213 				 (gdouble) source[(current_schannel += schannels)]};
8214 
8215       /* scale and copy */
8216       v_source *= scale;
8217       v_destination += v_source;
8218 
8219       current_dchannel = 0;
8220 
8221       destination[0] = (gint32) v_destination[0];
8222       destination[(current_dchannel = dchannels)] = (gint32) v_destination[1];
8223       destination[(current_dchannel += dchannels)] = (gint32) v_destination[2];
8224       destination[(current_dchannel += dchannels)] = (gint32) v_destination[3];
8225       destination[(current_dchannel += dchannels)] = (gint32) v_destination[4];
8226       destination[(current_dchannel += dchannels)] = (gint32) v_destination[5];
8227       destination[(current_dchannel += dchannels)] = (gint32) v_destination[6];
8228       destination[(current_dchannel += dchannels)] = (gint32) v_destination[7];
8229 
8230       /* iterate destination */
8231       destination += (current_dchannel + dchannels);
8232 
8233       /* iterate source */
8234       source += (current_schannel + schannels);
8235     }
8236   }
8237 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
8238   /* vectorized function */
8239   if(count > 8){
8240     limit = count - (count % 8);
8241 
8242     for(; i < limit; i += 8){
8243       double v_scaled[8];
8244       double v_result[8];
8245       static const double v_scale[1] = { (double) scale };
8246 
8247       current_dchannel = 0;
8248       current_schannel = 0;
8249 
8250       double v_destination[] = {(double) destination[0],
8251 				(double) destination[(current_dchannel = dchannels)],
8252 				(double) destination[(current_dchannel += dchannels)],
8253 				(double) destination[(current_dchannel += dchannels)],
8254 				(double) destination[(current_dchannel += dchannels)],
8255 				(double) destination[(current_dchannel += dchannels)],
8256 				(double) destination[(current_dchannel += dchannels)],
8257 				(double) destination[(current_dchannel += dchannels)]};
8258 
8259       double v_source[] = {(double) source[0],
8260 			   (double) source[(current_schannel = schannels)],
8261 			   (double) source[(current_schannel += schannels)],
8262 			   (double) source[(current_schannel += schannels)],
8263 			   (double) source[(current_schannel += schannels)],
8264 			   (double) source[(current_schannel += schannels)],
8265 			   (double) source[(current_schannel += schannels)],
8266 			   (double) source[(current_schannel += schannels)]};
8267 
8268       /* no scale, just copy */
8269       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
8270       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
8271 
8272       current_dchannel = 0;
8273 
8274       destination[0] = (gint32) v_result[0];
8275       destination[(current_dchannel = dchannels)] = (gint32) v_result[1];
8276       destination[(current_dchannel += dchannels)] = (gint32) v_result[2];
8277       destination[(current_dchannel += dchannels)] = (gint32) v_result[3];
8278       destination[(current_dchannel += dchannels)] = (gint32) v_result[4];
8279       destination[(current_dchannel += dchannels)] = (gint32) v_result[5];
8280       destination[(current_dchannel += dchannels)] = (gint32) v_result[6];
8281       destination[(current_dchannel += dchannels)] = (gint32) v_result[7];
8282 
8283       /* iterate destination */
8284       destination += (current_dchannel + dchannels);
8285 
8286       /* iterate source */
8287       source += (current_schannel + schannels);
8288     }
8289   }
8290 #else
8291   /* unrolled function */
8292   if(count > 8){
8293     limit = count - (count % 8);
8294 
8295     for(; i < limit; i += 8){
8296       current_dchannel = 0;
8297       current_schannel = 0;
8298 
8299       destination[0] = 0xffffffff & ((gint64) (destination[0] + (gint32) (scale * source[0])));
8300       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel = dchannels)] + (gint32) (scale * source[(current_schannel = schannels)])));
8301       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
8302       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
8303       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
8304       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
8305       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
8306       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
8307 
8308       /* iterate destination */
8309       destination += (current_dchannel + dchannels);
8310 
8311       /* iterate source */
8312       source += (current_schannel + schannels);
8313     }
8314   }
8315 #endif
8316 
8317   for(; i < count; i++){
8318     destination[0] = 0xffffffff & ((gint64) (destination[0] + (gint32) (scale * source[0])));
8319 
8320     destination += dchannels;
8321     source += schannels;
8322   }
8323 }
8324 
8325 /**
8326  * ags_audio_buffer_util_copy_s8_to_s64:
8327  * @destination: destination buffer
8328  * @dchannels: destination buffer's count of channels
8329  * @source: source buffer
8330  * @schannels: source buffer's count of channels
8331  * @count: number of frames to copy
8332  *
8333  * Copy audio data using additive strategy.
8334  *
8335  * Since: 3.0.0
8336  */
8337 void
ags_audio_buffer_util_copy_s8_to_s64(gint64 * destination,guint dchannels,gint8 * source,guint schannels,guint count)8338 ags_audio_buffer_util_copy_s8_to_s64(gint64 *destination, guint dchannels,
8339 				     gint8 *source, guint schannels,
8340 				     guint count)
8341 {
8342   //NOTE:JK: scale = (2^bits_destination / 2.0 - 1.0) / (2^bits_source / 2.0 - 1.0)
8343   static const gdouble scale = 72624976668147841.00000000000000000000;
8344   guint limit;
8345   guint current_dchannel, current_schannel;
8346   guint i;
8347 
8348   if(destination == NULL ||
8349      source == NULL){
8350     return;
8351   }
8352 
8353   i = 0;
8354 
8355 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
8356   /* vectorized function */
8357   if(count > 8){
8358     limit = count - (count % 8);
8359 
8360     for(; i < limit; i += 8){
8361       ags_v8double v_destination;
8362       ags_v8double v_source;
8363 
8364       current_dchannel = 0;
8365       current_schannel = 0;
8366 
8367       v_destination = (ags_v8double) {(gdouble) destination[0],
8368 				      (gdouble) destination[(current_dchannel = dchannels)],
8369 				      (gdouble) destination[(current_dchannel += dchannels)],
8370 				      (gdouble) destination[(current_dchannel += dchannels)],
8371 				      (gdouble) destination[(current_dchannel += dchannels)],
8372 				      (gdouble) destination[(current_dchannel += dchannels)],
8373 				      (gdouble) destination[(current_dchannel += dchannels)],
8374 				      (gdouble) destination[(current_dchannel += dchannels)]};
8375 
8376       v_source = (ags_v8double) {(gdouble) source[0],
8377 				 (gdouble) source[(current_schannel = schannels)],
8378 				 (gdouble) source[(current_schannel += schannels)],
8379 				 (gdouble) source[(current_schannel += schannels)],
8380 				 (gdouble) source[(current_schannel += schannels)],
8381 				 (gdouble) source[(current_schannel += schannels)],
8382 				 (gdouble) source[(current_schannel += schannels)],
8383 				 (gdouble) source[(current_schannel += schannels)]};
8384 
8385       /* scale and copy */
8386       v_source *= scale;
8387       v_destination += v_source;
8388 
8389       current_dchannel = 0;
8390 
8391       destination[0] = (gint64) v_destination[0];
8392       destination[(current_dchannel += dchannels)] = (gint64) v_destination[1];
8393       destination[(current_dchannel += dchannels)] = (gint64) v_destination[2];
8394       destination[(current_dchannel += dchannels)] = (gint64) v_destination[3];
8395       destination[(current_dchannel += dchannels)] = (gint64) v_destination[4];
8396       destination[(current_dchannel += dchannels)] = (gint64) v_destination[5];
8397       destination[(current_dchannel += dchannels)] = (gint64) v_destination[6];
8398       destination[(current_dchannel += dchannels)] = (gint64) v_destination[7];
8399 
8400       /* iterate destination */
8401       destination += (current_dchannel + dchannels);
8402 
8403       /* iterate source */
8404       source += (current_schannel + schannels);
8405     }
8406   }
8407 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
8408   /* vectorized function */
8409   if(count > 8){
8410     limit = count - (count % 8);
8411 
8412     for(; i < limit; i += 8){
8413       double v_scaled[8];
8414       double v_result[8];
8415       static const double v_scale[1] = { (double) scale };
8416 
8417       current_dchannel = 0;
8418       current_schannel = 0;
8419 
8420       double v_destination[] = {(double) destination[0],
8421 				(double) destination[(current_dchannel = dchannels)],
8422 				(double) destination[(current_dchannel += dchannels)],
8423 				(double) destination[(current_dchannel += dchannels)],
8424 				(double) destination[(current_dchannel += dchannels)],
8425 				(double) destination[(current_dchannel += dchannels)],
8426 				(double) destination[(current_dchannel += dchannels)],
8427 				(double) destination[(current_dchannel += dchannels)]};
8428 
8429       double v_source[] = {(double) source[0],
8430 			   (double) source[(current_schannel = schannels)],
8431 			   (double) source[(current_schannel += schannels)],
8432 			   (double) source[(current_schannel += schannels)],
8433 			   (double) source[(current_schannel += schannels)],
8434 			   (double) source[(current_schannel += schannels)],
8435 			   (double) source[(current_schannel += schannels)],
8436 			   (double) source[(current_schannel += schannels)]};
8437 
8438       /* no scale, just copy */
8439       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
8440       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
8441 
8442       current_dchannel = 0;
8443 
8444       destination[0] = (gint64) v_result[0];
8445       destination[(current_dchannel = dchannels)] = (gint64) v_result[1];
8446       destination[(current_dchannel += dchannels)] = (gint64) v_result[2];
8447       destination[(current_dchannel += dchannels)] = (gint64) v_result[3];
8448       destination[(current_dchannel += dchannels)] = (gint64) v_result[4];
8449       destination[(current_dchannel += dchannels)] = (gint64) v_result[5];
8450       destination[(current_dchannel += dchannels)] = (gint64) v_result[6];
8451       destination[(current_dchannel += dchannels)] = (gint64) v_result[7];
8452 
8453       /* iterate destination */
8454       destination += (current_dchannel + dchannels);
8455 
8456       /* iterate source */
8457       source += (current_schannel + schannels);
8458     }
8459   }
8460 #else
8461   /* unrolled function */
8462   if(count > 8){
8463     limit = count - (count % 8);
8464 
8465     for(; i < limit; i += 8){
8466       current_dchannel = 0;
8467       current_schannel = 0;
8468 
8469       destination[0] = 0xffffffffffffffff & ((gint64) (destination[0] + (gint64) (scale * source[0])));
8470       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel = dchannels)] + (gint64) (scale * source[(current_schannel = schannels)])));
8471       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (gint64) (scale * source[(current_schannel += schannels)])));
8472       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (gint64) (scale * source[(current_schannel += schannels)])));
8473       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (gint64) (scale * source[(current_schannel += schannels)])));
8474       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (gint64) (scale * source[(current_schannel += schannels)])));
8475       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (gint64) (scale * source[(current_schannel += schannels)])));
8476       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (gint64) (scale * source[(current_schannel += schannels)])));
8477 
8478       /* iterate destination */
8479       destination += (current_dchannel + dchannels);
8480 
8481       /* iterate source */
8482       source += (current_schannel + schannels);
8483     }
8484   }
8485 #endif
8486 
8487   for(; i < count; i++){
8488     destination[0] = 0xffffffffffffffff & ((gint64) (destination[0] + (gint64) (scale * source[0])));
8489 
8490     destination += dchannels;
8491     source += schannels;
8492   }
8493 }
8494 
8495 /**
8496  * ags_audio_buffer_util_copy_s8_to_float:
8497  * @destination: destination buffer
8498  * @dchannels: destination buffer's count of channels
8499  * @source: source buffer
8500  * @schannels: source buffer's count of channels
8501  * @count: number of frames to copy
8502  *
8503  * Copy audio data using additive strategy.
8504  *
8505  * Since: 3.0.0
8506  */
8507 void
ags_audio_buffer_util_copy_s8_to_float(gfloat * destination,guint dchannels,gint8 * source,guint schannels,guint count)8508 ags_audio_buffer_util_copy_s8_to_float(gfloat *destination, guint dchannels,
8509 				       gint8 *source, guint schannels,
8510 				       guint count)
8511 {
8512   //NOTE:JK: scale = 1.0 / (2^bits_source / 2.0 - 1.0)
8513   //  static const gdouble scale = 0.00787401574803149606;
8514   static const gdouble normalize_divisor = 127.0;
8515   guint limit;
8516   guint current_dchannel, current_schannel;
8517   guint i;
8518 
8519   if(destination == NULL ||
8520      source == NULL){
8521     return;
8522   }
8523 
8524   i = 0;
8525 
8526 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
8527   /* vectorized function */
8528   if(count > 8){
8529     limit = count - (count % 8);
8530 
8531     for(; i < limit; i += 8){
8532       ags_v8float v_destination;
8533       ags_v8float v_source;
8534 
8535       current_dchannel = 0;
8536       current_schannel = 0;
8537 
8538       v_destination = (ags_v8float) {(gfloat) destination[0],
8539 				     (gfloat) destination[(current_dchannel = dchannels)],
8540 				     (gfloat) destination[(current_dchannel += dchannels)],
8541 				     (gfloat) destination[(current_dchannel += dchannels)],
8542 				     (gfloat) destination[(current_dchannel += dchannels)],
8543 				     (gfloat) destination[(current_dchannel += dchannels)],
8544 				     (gfloat) destination[(current_dchannel += dchannels)],
8545 				     (gfloat) destination[(current_dchannel += dchannels)]};
8546 
8547       v_source = (ags_v8float) {(gfloat) source[0],
8548 				(gfloat) source[(current_schannel = schannels)],
8549 				(gfloat) source[(current_schannel += schannels)],
8550 				(gfloat) source[(current_schannel += schannels)],
8551 				(gfloat) source[(current_schannel += schannels)],
8552 				(gfloat) source[(current_schannel += schannels)],
8553 				(gfloat) source[(current_schannel += schannels)],
8554 				(gfloat) source[(current_schannel += schannels)]};
8555 
8556       /* normalize and copy */
8557       v_source /= (gfloat) normalize_divisor;
8558       v_destination += v_source;
8559 
8560       current_dchannel = 0;
8561 
8562       destination[0] = (gfloat) v_destination[0];
8563       destination[(current_dchannel = dchannels)] = (gfloat) v_destination[1];
8564       destination[(current_dchannel += dchannels)] = (gfloat) v_destination[2];
8565       destination[(current_dchannel += dchannels)] = (gfloat) v_destination[3];
8566       destination[(current_dchannel += dchannels)] = (gfloat) v_destination[4];
8567       destination[(current_dchannel += dchannels)] = (gfloat) v_destination[5];
8568       destination[(current_dchannel += dchannels)] = (gfloat) v_destination[6];
8569       destination[(current_dchannel += dchannels)] = (gfloat) v_destination[7];
8570 
8571       /* iterate destination */
8572       destination += (current_dchannel + dchannels);
8573 
8574       /* iterate source */
8575       source += (current_schannel + schannels);
8576     }
8577   }
8578 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
8579   /* vectorized function */
8580   if(count > 8){
8581     limit = count - (count % 8);
8582 
8583     for(; i < limit; i += 8){
8584       double v_normalized[8];
8585       double v_result[8];
8586       static const double v_normalize_divisor[1] = { (double) normalize_divisor };
8587 
8588       current_dchannel = 0;
8589       current_schannel = 0;
8590 
8591       double v_destination[] = {(double) destination[0],
8592 				(double) destination[(current_dchannel = dchannels)],
8593 				(double) destination[(current_dchannel += dchannels)],
8594 				(double) destination[(current_dchannel += dchannels)],
8595 				(double) destination[(current_dchannel += dchannels)],
8596 				(double) destination[(current_dchannel += dchannels)],
8597 				(double) destination[(current_dchannel += dchannels)],
8598 				(double) destination[(current_dchannel += dchannels)]};
8599 
8600       double v_source[] = {(double) source[0],
8601 			   (double) source[(current_schannel = schannels)],
8602 			   (double) source[(current_schannel += schannels)],
8603 			   (double) source[(current_schannel += schannels)],
8604 			   (double) source[(current_schannel += schannels)],
8605 			   (double) source[(current_schannel += schannels)],
8606 			   (double) source[(current_schannel += schannels)],
8607 			   (double) source[(current_schannel += schannels)]};
8608 
8609       /* scale and copy */
8610       vDSP_vdivD(v_normalize_divisor, 0, v_source, 1, v_normalized, 1, 8);
8611       vDSP_vaddD(v_destination, 1, v_normalized, 1, v_result, 1, 8);
8612 
8613       current_dchannel = 0;
8614 
8615       destination[0] = (gfloat) v_result[0];
8616       destination[(current_dchannel = dchannels)] = (gfloat) v_result[1];
8617       destination[(current_dchannel += dchannels)] = (gfloat) v_result[2];
8618       destination[(current_dchannel += dchannels)] = (gfloat) v_result[3];
8619       destination[(current_dchannel += dchannels)] = (gfloat) v_result[4];
8620       destination[(current_dchannel += dchannels)] = (gfloat) v_result[5];
8621       destination[(current_dchannel += dchannels)] = (gfloat) v_result[6];
8622       destination[(current_dchannel += dchannels)] = (gfloat) v_result[7];
8623 
8624       /* iterate destination */
8625       destination += (current_dchannel + dchannels);
8626 
8627       /* iterate source */
8628       source += (current_schannel + schannels);
8629     }
8630   }
8631 #else
8632   /* unrolled function */
8633   if(count > 8){
8634     limit = count - (count % 8);
8635 
8636     for(; i < limit; i += 8){
8637       current_dchannel = 0;
8638       current_schannel = 0;
8639 
8640       destination[0] = (gfloat) ((gdouble) (destination[0] + (gdouble) (source[0] / normalize_divisor)));
8641       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (source[(current_schannel = schannels)] / normalize_divisor)));
8642       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
8643       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
8644       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
8645       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
8646       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
8647       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
8648 
8649       /* iterate destination */
8650       destination += (current_dchannel + dchannels);
8651 
8652       /* iterate source */
8653       source += (current_schannel + schannels);
8654     }
8655   }
8656 #endif
8657 
8658   for(; i < count; i++){
8659     destination[0] = (gfloat) ((gdouble) (destination[0] + (gdouble) (source[0] / normalize_divisor)));
8660 
8661     destination += dchannels;
8662     source += schannels;
8663   }
8664 }
8665 
8666 /**
8667  * ags_audio_buffer_util_copy_s8_to_double:
8668  * @destination: destination buffer
8669  * @dchannels: destination buffer's count of channels
8670  * @source: source buffer
8671  * @schannels: source buffer's count of channels
8672  * @count: number of frames to copy
8673  *
8674  * Copy audio data using additive strategy.
8675  *
8676  * Since: 3.0.0
8677  */
8678 void
ags_audio_buffer_util_copy_s8_to_double(gdouble * destination,guint dchannels,gint8 * source,guint schannels,guint count)8679 ags_audio_buffer_util_copy_s8_to_double(gdouble *destination, guint dchannels,
8680 					gint8 *source, guint schannels,
8681 					guint count)
8682 {
8683   //NOTE:JK: scale = 1.0 / (2^bits_source / 2.0 - 1.0)
8684   //  static const gdouble scale = 0.00787401574803149606;
8685   static const gdouble normalize_divisor = 127.0;
8686   guint limit;
8687   guint current_dchannel, current_schannel;
8688   guint i;
8689 
8690   if(destination == NULL ||
8691      source == NULL){
8692     return;
8693   }
8694 
8695   i = 0;
8696 
8697 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
8698   /* vectorized function */
8699   if(count > 8){
8700     limit = count - (count % 8);
8701 
8702     for(; i < limit; i += 8){
8703       ags_v8double v_destination;
8704       ags_v8double v_source;
8705 
8706       current_dchannel = 0;
8707       current_schannel = 0;
8708 
8709       v_destination = (ags_v8double) {(gdouble) destination[0],
8710 				      (gdouble) destination[(current_dchannel = dchannels)],
8711 				      (gdouble) destination[(current_dchannel += dchannels)],
8712 				      (gdouble) destination[(current_dchannel += dchannels)],
8713 				      (gdouble) destination[(current_dchannel += dchannels)],
8714 				      (gdouble) destination[(current_dchannel += dchannels)],
8715 				      (gdouble) destination[(current_dchannel += dchannels)],
8716 				      (gdouble) destination[(current_dchannel += dchannels)]};
8717 
8718       v_source = (ags_v8double) {(gdouble) source[0],
8719 				 (gdouble) source[(current_schannel = schannels)],
8720 				 (gdouble) source[(current_schannel += schannels)],
8721 				 (gdouble) source[(current_schannel += schannels)],
8722 				 (gdouble) source[(current_schannel += schannels)],
8723 				 (gdouble) source[(current_schannel += schannels)],
8724 				 (gdouble) source[(current_schannel += schannels)],
8725 				 (gdouble) source[(current_schannel += schannels)]};
8726 
8727       /* normalize and copy */
8728       v_source /= normalize_divisor;
8729       v_destination += v_source;
8730 
8731       current_dchannel = 0;
8732 
8733       destination[0] = v_destination[0];
8734       destination[(current_dchannel = dchannels)] = v_destination[1];
8735       destination[(current_dchannel += dchannels)] = v_destination[2];
8736       destination[(current_dchannel += dchannels)] = v_destination[3];
8737       destination[(current_dchannel += dchannels)] = v_destination[4];
8738       destination[(current_dchannel += dchannels)] = v_destination[5];
8739       destination[(current_dchannel += dchannels)] = v_destination[6];
8740       destination[(current_dchannel += dchannels)] = v_destination[7];
8741 
8742       /* iterate destination */
8743       destination += (current_dchannel + dchannels);
8744 
8745       /* iterate source */
8746       source += (current_schannel + schannels);
8747     }
8748   }
8749 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
8750   /* vectorized function */
8751   if(count > 8){
8752     limit = count - (count % 8);
8753 
8754     for(; i < limit; i += 8){
8755       double v_normalized[8];
8756       double v_result[8];
8757       static const double v_normalize_divisor[1] = { (double) normalize_divisor };
8758 
8759       current_dchannel = 0;
8760       current_schannel = 0;
8761 
8762       double v_destination[] = {(double) destination[0],
8763 				(double) destination[(current_dchannel = dchannels)],
8764 				(double) destination[(current_dchannel += dchannels)],
8765 				(double) destination[(current_dchannel += dchannels)],
8766 				(double) destination[(current_dchannel += dchannels)],
8767 				(double) destination[(current_dchannel += dchannels)],
8768 				(double) destination[(current_dchannel += dchannels)],
8769 				(double) destination[(current_dchannel += dchannels)]};
8770 
8771       double v_source[] = {(double) source[0],
8772 			   (double) source[(current_schannel = schannels)],
8773 			   (double) source[(current_schannel += schannels)],
8774 			   (double) source[(current_schannel += schannels)],
8775 			   (double) source[(current_schannel += schannels)],
8776 			   (double) source[(current_schannel += schannels)],
8777 			   (double) source[(current_schannel += schannels)],
8778 			   (double) source[(current_schannel += schannels)]};
8779 
8780       /* no scale, just copy */
8781       vDSP_vdivD(v_normalize_divisor, 0, v_source, 1, v_normalized, 1, 8);
8782       vDSP_vaddD(v_destination, 1, v_normalized, 1, v_result, 1, 8);
8783 
8784       current_dchannel = 0;
8785 
8786       destination[0] = (gdouble) v_result[0];
8787       destination[(current_dchannel = dchannels)] = (gdouble) v_result[1];
8788       destination[(current_dchannel += dchannels)] = (gdouble) v_result[2];
8789       destination[(current_dchannel += dchannels)] = (gdouble) v_result[3];
8790       destination[(current_dchannel += dchannels)] = (gdouble) v_result[4];
8791       destination[(current_dchannel += dchannels)] = (gdouble) v_result[5];
8792       destination[(current_dchannel += dchannels)] = (gdouble) v_result[6];
8793       destination[(current_dchannel += dchannels)] = (gdouble) v_result[7];
8794 
8795       /* iterate destination */
8796       destination += (current_dchannel + dchannels);
8797 
8798       /* iterate source */
8799       source += (current_schannel + schannels);
8800     }
8801   }
8802 #else
8803   /* unrolled function */
8804   if(count > 8){
8805     limit = count - (count % 8);
8806 
8807     for(; i < limit; i += 8){
8808       current_dchannel = 0;
8809       current_schannel = 0;
8810 
8811       destination[0] = ((gdouble) (destination[0] + (gdouble) (source[0] / normalize_divisor)));
8812       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (source[(current_schannel = schannels)] / normalize_divisor)));
8813       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
8814       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
8815       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
8816       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
8817       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
8818       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
8819 
8820       /* iterate destination */
8821       destination += (current_dchannel + dchannels);
8822 
8823       /* iterate source */
8824       source += (current_schannel + schannels);
8825     }
8826   }
8827 #endif
8828 
8829   for(; i < count; i++){
8830     destination[0] = ((gdouble) (destination[0] + (gdouble) (source[0] / normalize_divisor)));
8831 
8832     destination += dchannels;
8833     source += schannels;
8834   }
8835 }
8836 
8837 /**
8838  * ags_audio_buffer_util_copy_s16_to_s8:
8839  * @destination: destination buffer
8840  * @dchannels: destination buffer's count of channels
8841  * @source: source buffer
8842  * @schannels: source buffer's count of channels
8843  * @count: number of frames to copy
8844  *
8845  * Copy audio data using additive strategy.
8846  *
8847  * Since: 3.0.0
8848  */
8849 void
ags_audio_buffer_util_copy_s16_to_s8(gint8 * destination,guint dchannels,gint16 * source,guint schannels,guint count)8850 ags_audio_buffer_util_copy_s16_to_s8(gint8 *destination, guint dchannels,
8851 				     gint16 *source, guint schannels,
8852 				     guint count)
8853 {
8854   //NOTE:JK: scale = (2^bits_destination / 2.0 - 1.0) / (2^bits_source / 2.0 - 1.0)
8855   static const gdouble scale = 0.00387585070345164342;
8856   guint limit;
8857   guint current_dchannel, current_schannel;
8858   guint i;
8859 
8860   if(destination == NULL ||
8861      source == NULL){
8862     return;
8863   }
8864 
8865   i = 0;
8866 
8867 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
8868   /* vectorized function */
8869   if(count > 8){
8870     limit = count - (count % 8);
8871 
8872     for(; i < limit; i += 8){
8873       ags_v8double v_destination;
8874       ags_v8double v_source;
8875 
8876       current_dchannel = 0;
8877       current_schannel = 0;
8878 
8879       v_destination = (ags_v8double) {(gdouble) destination[0],
8880 				      (gdouble) destination[(current_dchannel = dchannels)],
8881 				      (gdouble) destination[(current_dchannel += dchannels)],
8882 				      (gdouble) destination[(current_dchannel += dchannels)],
8883 				      (gdouble) destination[(current_dchannel += dchannels)],
8884 				      (gdouble) destination[(current_dchannel += dchannels)],
8885 				      (gdouble) destination[(current_dchannel += dchannels)],
8886 				      (gdouble) destination[(current_dchannel += dchannels)]};
8887 
8888       v_source = (ags_v8double) {(gdouble) source[0],
8889 				 (gdouble) source[(current_schannel = schannels)],
8890 				 (gdouble) source[(current_schannel += schannels)],
8891 				 (gdouble) source[(current_schannel += schannels)],
8892 				 (gdouble) source[(current_schannel += schannels)],
8893 				 (gdouble) source[(current_schannel += schannels)],
8894 				 (gdouble) source[(current_schannel += schannels)],
8895 				 (gdouble) source[(current_schannel += schannels)]};
8896 
8897       /* scale and copy */
8898       v_source *= scale;
8899       v_destination += v_source;
8900 
8901       current_dchannel = 0;
8902 
8903       destination[0] = (gint8) v_destination[0];
8904       destination[(current_dchannel = dchannels)] = (gint8) v_destination[1];
8905       destination[(current_dchannel += dchannels)] = (gint8) v_destination[2];
8906       destination[(current_dchannel += dchannels)] = (gint8) v_destination[3];
8907       destination[(current_dchannel += dchannels)] = (gint8) v_destination[4];
8908       destination[(current_dchannel += dchannels)] = (gint8) v_destination[5];
8909       destination[(current_dchannel += dchannels)] = (gint8) v_destination[6];
8910       destination[(current_dchannel += dchannels)] = (gint8) v_destination[7];
8911 
8912       /* iterate destination */
8913       destination += (current_dchannel + dchannels);
8914 
8915       /* iterate source */
8916       source += (current_schannel + schannels);
8917     }
8918   }
8919 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
8920   /* vectorized function */
8921   if(count > 8){
8922     limit = count - (count % 8);
8923 
8924     for(; i < limit; i += 8){
8925       double v_scaled[8];
8926       double v_result[8];
8927       static const double v_scale[1] = { (double) scale };
8928 
8929       current_dchannel = 0;
8930       current_schannel = 0;
8931 
8932       double v_destination[] = {(double) destination[0],
8933 				(double) destination[(current_dchannel = dchannels)],
8934 				(double) destination[(current_dchannel += dchannels)],
8935 				(double) destination[(current_dchannel += dchannels)],
8936 				(double) destination[(current_dchannel += dchannels)],
8937 				(double) destination[(current_dchannel += dchannels)],
8938 				(double) destination[(current_dchannel += dchannels)],
8939 				(double) destination[(current_dchannel += dchannels)]};
8940 
8941       double v_source[] = {(double) source[0],
8942 			   (double) source[(current_schannel = schannels)],
8943 			   (double) source[(current_schannel += schannels)],
8944 			   (double) source[(current_schannel += schannels)],
8945 			   (double) source[(current_schannel += schannels)],
8946 			   (double) source[(current_schannel += schannels)],
8947 			   (double) source[(current_schannel += schannels)],
8948 			   (double) source[(current_schannel += schannels)]};
8949 
8950       /* no scale, just copy */
8951       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
8952       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
8953 
8954       current_dchannel = 0;
8955 
8956       destination[0] = (gint8) v_result[0];
8957       destination[(current_dchannel = dchannels)] = (gint8) v_result[1];
8958       destination[(current_dchannel += dchannels)] = (gint8) v_result[2];
8959       destination[(current_dchannel += dchannels)] = (gint8) v_result[3];
8960       destination[(current_dchannel += dchannels)] = (gint8) v_result[4];
8961       destination[(current_dchannel += dchannels)] = (gint8) v_result[5];
8962       destination[(current_dchannel += dchannels)] = (gint8) v_result[6];
8963       destination[(current_dchannel += dchannels)] = (gint8) v_result[7];
8964 
8965       /* iterate destination */
8966       destination += (current_dchannel + dchannels);
8967 
8968       /* iterate source */
8969       source += (current_schannel + schannels);
8970     }
8971   }
8972 #else
8973   /* unrolled function */
8974   if(count > 8){
8975     limit = count - (count % 8);
8976 
8977     for(; i < limit; i += 8){
8978       current_dchannel = 0;
8979       current_schannel = 0;
8980 
8981       destination[0] = 0xff & ((gint16) (destination[0] + (scale * source[0])));
8982       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel = dchannels)] + (scale * source[(current_schannel = schannels)])));
8983       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
8984       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
8985       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
8986       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
8987       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
8988       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
8989 
8990       /* iterate destination */
8991       destination += (current_dchannel + dchannels);
8992 
8993       /* iterate source */
8994       source += (current_schannel + schannels);
8995     }
8996   }
8997 #endif
8998 
8999   for(; i < count; i++){
9000     destination[0] = 0xff & ((gint16) (destination[0] + (scale * source[0])));
9001 
9002     destination += dchannels;
9003     source += schannels;
9004   }
9005 }
9006 
9007 /**
9008  * ags_audio_buffer_util_copy_s16_to_s16:
9009  * @destination: destination buffer
9010  * @dchannels: destination buffer's count of channels
9011  * @source: source buffer
9012  * @schannels: source buffer's count of channels
9013  * @count: number of frames to copy
9014  *
9015  * Copy audio data using additive strategy.
9016  *
9017  * Since: 3.0.0
9018  */
9019 void
ags_audio_buffer_util_copy_s16_to_s16(gint16 * destination,guint dchannels,gint16 * source,guint schannels,guint count)9020 ags_audio_buffer_util_copy_s16_to_s16(gint16 *destination, guint dchannels,
9021 				      gint16 *source, guint schannels,
9022 				      guint count)
9023 {
9024   guint limit;
9025   guint current_dchannel, current_schannel;
9026   guint i;
9027 
9028   if(destination == NULL ||
9029      source == NULL){
9030     return;
9031   }
9032 
9033   i = 0;
9034 
9035 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
9036   /* vectorized function */
9037   if(count > 8){
9038     limit = count - (count % 8);
9039 
9040     for(; i < limit; i += 8){
9041       ags_v8s16 v_destination;
9042       ags_v8s16 v_source;
9043 
9044       current_dchannel = 0;
9045       current_schannel = 0;
9046 
9047       v_destination = (ags_v8s16) {destination[0],
9048 				   destination[(current_dchannel = dchannels)],
9049 				   destination[(current_dchannel += dchannels)],
9050 				   destination[(current_dchannel += dchannels)],
9051 				   destination[(current_dchannel += dchannels)],
9052 				   destination[(current_dchannel += dchannels)],
9053 				   destination[(current_dchannel += dchannels)],
9054 				   destination[(current_dchannel += dchannels)]};
9055       v_source = (ags_v8s16) {source[0],
9056 			      source[(current_schannel = schannels)],
9057 			      source[(current_schannel += schannels)],
9058 			      source[(current_schannel += schannels)],
9059 			      source[(current_schannel += schannels)],
9060 			      source[(current_schannel += schannels)],
9061 			      source[(current_schannel += schannels)],
9062 			      source[(current_schannel += schannels)]};
9063 
9064       /* no scale, just copy */
9065       v_destination += v_source;
9066 
9067       current_dchannel = 0;
9068 
9069       destination[0] = v_destination[0];
9070       destination[(current_dchannel = dchannels)] = v_destination[1];
9071       destination[(current_dchannel += dchannels)] = v_destination[2];
9072       destination[(current_dchannel += dchannels)] = v_destination[3];
9073       destination[(current_dchannel += dchannels)] = v_destination[4];
9074       destination[(current_dchannel += dchannels)] = v_destination[5];
9075       destination[(current_dchannel += dchannels)] = v_destination[6];
9076       destination[(current_dchannel += dchannels)] = v_destination[7];
9077 
9078       /* iterate destination */
9079       destination += (current_dchannel + dchannels);
9080 
9081       /* iterate source */
9082       source += (current_schannel + schannels);
9083     }
9084   }
9085 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
9086   /* vectorized function */
9087   if(count > 8){
9088     limit = count - (count % 8);
9089 
9090     for(; i < limit; i += 8){
9091       int v_result[8];
9092 
9093       current_dchannel = 0;
9094       current_schannel = 0;
9095 
9096       int v_destination[] = {(int) destination[0],
9097 			     (int) destination[(current_dchannel = dchannels)],
9098 			     (int) destination[(current_dchannel += dchannels)],
9099 			     (int) destination[(current_dchannel += dchannels)],
9100 			     (int) destination[(current_dchannel += dchannels)],
9101 			     (int) destination[(current_dchannel += dchannels)],
9102 			     (int) destination[(current_dchannel += dchannels)],
9103 			     (int) destination[(current_dchannel += dchannels)]};
9104 
9105       int v_source[] = {(int) source[0],
9106 			(int) source[(current_schannel = schannels)],
9107 			(int) source[(current_schannel += schannels)],
9108 			(int) source[(current_schannel += schannels)],
9109 			(int) source[(current_schannel += schannels)],
9110 			(int) source[(current_schannel += schannels)],
9111 			(int) source[(current_schannel += schannels)],
9112 			(int) source[(current_schannel += schannels)]};
9113 
9114       /* no scale, just copy */
9115       vDSP_vaddi(v_destination, 1, v_source, 1, v_result, 1, 8);
9116 
9117       current_dchannel = 0;
9118 
9119       destination[0] = (gint16) v_result[0];
9120       destination[(current_dchannel = dchannels)] = (gint16) v_result[1];
9121       destination[(current_dchannel += dchannels)] = (gint16) v_result[2];
9122       destination[(current_dchannel += dchannels)] = (gint16) v_result[3];
9123       destination[(current_dchannel += dchannels)] = (gint16) v_result[4];
9124       destination[(current_dchannel += dchannels)] = (gint16) v_result[5];
9125       destination[(current_dchannel += dchannels)] = (gint16) v_result[6];
9126       destination[(current_dchannel += dchannels)] = (gint16) v_result[7];
9127 
9128       /* iterate destination */
9129       destination += (current_dchannel + dchannels);
9130 
9131       /* iterate source */
9132       source += (current_schannel + schannels);
9133     }
9134   }
9135 #else
9136   /* unrolled function */
9137   if(count > 8){
9138     limit = count - (count % 8);
9139 
9140     for(; i < limit; i += 8){
9141       current_dchannel = 0;
9142       current_schannel = 0;
9143 
9144       destination[0] = (gint16) 0xffff & ((gint32) (destination[0] + source[0]));
9145       destination[current_dchannel] = (gint16) 0xffff & ((gint32) (destination[(current_dchannel = dchannels)] + source[(current_schannel = schannels)]));
9146       destination[current_dchannel] = (gint16) 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + source[(current_schannel += schannels)]));
9147       destination[current_dchannel] = (gint16) 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + source[(current_schannel += schannels)]));
9148       destination[current_dchannel] = (gint16) 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + source[(current_schannel += schannels)]));
9149       destination[current_dchannel] = (gint16) 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + source[(current_schannel += schannels)]));
9150       destination[current_dchannel] = (gint16) 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + source[(current_schannel += schannels)]));
9151       destination[current_dchannel] = (gint16) 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + source[(current_schannel += schannels)]));
9152 
9153       /* iterate destination */
9154       destination += (current_dchannel + dchannels);
9155 
9156       /* iterate source */
9157       source += (current_schannel + schannels);
9158     }
9159   }
9160 #endif
9161 
9162   for(; i < count; i++){
9163     destination[0] = (gint16) 0xffff & ((gint32) (destination[0] + source[0]));
9164 
9165     destination += dchannels;
9166     source += schannels;
9167   }
9168 }
9169 
9170 /**
9171  * ags_audio_buffer_util_copy_s16_to_s24:
9172  * @destination: destination buffer
9173  * @dchannels: destination buffer's count of channels
9174  * @source: source buffer
9175  * @schannels: source buffer's count of channels
9176  * @count: number of frames to copy
9177  *
9178  * Copy audio data using additive strategy.
9179  *
9180  * Since: 3.0.0
9181  */
9182 void
ags_audio_buffer_util_copy_s16_to_s24(gint32 * destination,guint dchannels,gint16 * source,guint schannels,guint count)9183 ags_audio_buffer_util_copy_s16_to_s24(gint32 *destination, guint dchannels,
9184 				      gint16 *source, guint schannels,
9185 				      guint count)
9186 {
9187   //NOTE:JK: scale = (2^bits_destination / 2.0 - 1.0) / (2^bits_source / 2.0 - 1.0)
9188   static const gdouble scale = 256.00778221991637928403;
9189   guint limit;
9190   guint current_dchannel, current_schannel;
9191   guint i;
9192 
9193   if(destination == NULL ||
9194      source == NULL){
9195     return;
9196   }
9197 
9198   i = 0;
9199 
9200 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
9201   /* vectorized function */
9202   if(count > 8){
9203     limit = count - (count % 8);
9204 
9205     for(; i < limit; i += 8){
9206       ags_v8double v_destination;
9207       ags_v8double v_source;
9208 
9209       current_dchannel = 0;
9210       current_schannel = 0;
9211 
9212       v_destination = (ags_v8double) {(gdouble) destination[0],
9213 				      (gdouble) destination[(current_dchannel = dchannels)],
9214 				      (gdouble) destination[(current_dchannel += dchannels)],
9215 				      (gdouble) destination[(current_dchannel += dchannels)],
9216 				      (gdouble) destination[(current_dchannel += dchannels)],
9217 				      (gdouble) destination[(current_dchannel += dchannels)],
9218 				      (gdouble) destination[(current_dchannel += dchannels)],
9219 				      (gdouble) destination[(current_dchannel += dchannels)]};
9220 
9221       v_source = (ags_v8double) {(gdouble) source[0],
9222 				 (gdouble) source[(current_schannel = schannels)],
9223 				 (gdouble) source[(current_schannel += schannels)],
9224 				 (gdouble) source[(current_schannel += schannels)],
9225 				 (gdouble) source[(current_schannel += schannels)],
9226 				 (gdouble) source[(current_schannel += schannels)],
9227 				 (gdouble) source[(current_schannel += schannels)],
9228 				 (gdouble) source[(current_schannel += schannels)]};
9229 
9230       /* scale and copy */
9231       v_source *= scale;
9232       v_destination += v_source;
9233 
9234       current_dchannel = 0;
9235 
9236       destination[0] = (gint32) v_destination[0];
9237       destination[(current_dchannel = dchannels)] = (gint32) v_destination[1];
9238       destination[(current_dchannel += dchannels)] = (gint32) v_destination[2];
9239       destination[(current_dchannel += dchannels)] = (gint32) v_destination[3];
9240       destination[(current_dchannel += dchannels)] = (gint32) v_destination[4];
9241       destination[(current_dchannel += dchannels)] = (gint32) v_destination[5];
9242       destination[(current_dchannel += dchannels)] = (gint32) v_destination[6];
9243       destination[(current_dchannel += dchannels)] = (gint32) v_destination[7];
9244 
9245       /* iterate destination */
9246       destination += (current_dchannel + dchannels);
9247 
9248       /* iterate source */
9249       source += (current_schannel + schannels);
9250     }
9251   }
9252 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
9253   /* vectorized function */
9254   if(count > 8){
9255     limit = count - (count % 8);
9256 
9257     for(; i < limit; i += 8){
9258       double v_scaled[8];
9259       double v_result[8];
9260       static const double v_scale[1] = { (double) scale };
9261 
9262       current_dchannel = 0;
9263       current_schannel = 0;
9264 
9265       double v_destination[] = {(double) destination[0],
9266 				(double) destination[(current_dchannel = dchannels)],
9267 				(double) destination[(current_dchannel += dchannels)],
9268 				(double) destination[(current_dchannel += dchannels)],
9269 				(double) destination[(current_dchannel += dchannels)],
9270 				(double) destination[(current_dchannel += dchannels)],
9271 				(double) destination[(current_dchannel += dchannels)],
9272 				(double) destination[(current_dchannel += dchannels)]};
9273 
9274       double v_source[] = {(double) source[0],
9275 			   (double) source[(current_schannel = schannels)],
9276 			   (double) source[(current_schannel += schannels)],
9277 			   (double) source[(current_schannel += schannels)],
9278 			   (double) source[(current_schannel += schannels)],
9279 			   (double) source[(current_schannel += schannels)],
9280 			   (double) source[(current_schannel += schannels)],
9281 			   (double) source[(current_schannel += schannels)]};
9282 
9283       /* no scale, just copy */
9284       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
9285       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
9286 
9287       current_dchannel = 0;
9288 
9289       destination[0] = (gint32) v_result[0];
9290       destination[(current_dchannel = dchannels)] = (gint32) v_result[1];
9291       destination[(current_dchannel += dchannels)] = (gint32) v_result[2];
9292       destination[(current_dchannel += dchannels)] = (gint32) v_result[3];
9293       destination[(current_dchannel += dchannels)] = (gint32) v_result[4];
9294       destination[(current_dchannel += dchannels)] = (gint32) v_result[5];
9295       destination[(current_dchannel += dchannels)] = (gint32) v_result[6];
9296       destination[(current_dchannel += dchannels)] = (gint32) v_result[7];
9297 
9298       /* iterate destination */
9299       destination += (current_dchannel + dchannels);
9300 
9301       /* iterate source */
9302       source += (current_schannel + schannels);
9303     }
9304   }
9305 #else
9306   /* unrolled function */
9307   if(count > 8){
9308     limit = count - (count % 8);
9309 
9310     for(; i < limit; i += 8){
9311       current_dchannel = 0;
9312       current_schannel = 0;
9313 
9314       destination[0] = 0xffffffff & ((gint32) (destination[0] + (gint32) (scale * source[0])));
9315       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel = dchannels)] + (gint32) (scale * source[(current_schannel = schannels)])));
9316       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
9317       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
9318       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
9319       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
9320       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
9321       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
9322 
9323       /* iterate destination */
9324       destination += (current_dchannel + dchannels);
9325 
9326       /* iterate source */
9327       source += (current_schannel + schannels);
9328     }
9329   }
9330 #endif
9331 
9332   for(; i < count; i++){
9333     destination[0] = 0xffffffff & ((gint32) (destination[0] + (gint32) (scale * source[0])));
9334 
9335     destination += dchannels;
9336     source += schannels;
9337   }
9338 }
9339 
9340 /**
9341  * ags_audio_buffer_util_copy_s16_to_s32:
9342  * @destination: destination buffer
9343  * @dchannels: destination buffer's count of channels
9344  * @source: source buffer
9345  * @schannels: source buffer's count of channels
9346  * @count: number of frames to copy
9347  *
9348  * Copy audio data using additive strategy.
9349  *
9350  * Since: 3.0.0
9351  */
9352 void
ags_audio_buffer_util_copy_s16_to_s32(gint32 * destination,guint dchannels,gint16 * source,guint schannels,guint count)9353 ags_audio_buffer_util_copy_s16_to_s32(gint32 *destination, guint dchannels,
9354 				      gint16 *source, guint schannels,
9355 				      guint count)
9356 {
9357   //NOTE:JK: scale = (2^bits_destination / 2.0 - 1.0) / (2^bits_source / 2.0 - 1.0)
9358   static const gdouble scale = 6553.79995117038483840449;
9359   guint limit;
9360   guint current_dchannel, current_schannel;
9361   guint i;
9362 
9363   if(destination == NULL ||
9364      source == NULL){
9365     return;
9366   }
9367 
9368   i = 0;
9369 
9370 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
9371   /* vectorized function */
9372   if(count > 8){
9373     limit = count - (count % 8);
9374 
9375     for(; i < limit; i += 8){
9376       ags_v8double v_destination;
9377       ags_v8double v_source;
9378 
9379       current_dchannel = 0;
9380       current_schannel = 0;
9381 
9382       v_destination = (ags_v8double) {(gdouble) destination[0],
9383 				      (gdouble) destination[(current_dchannel = dchannels)],
9384 				      (gdouble) destination[(current_dchannel += dchannels)],
9385 				      (gdouble) destination[(current_dchannel += dchannels)],
9386 				      (gdouble) destination[(current_dchannel += dchannels)],
9387 				      (gdouble) destination[(current_dchannel += dchannels)],
9388 				      (gdouble) destination[(current_dchannel += dchannels)],
9389 				      (gdouble) destination[(current_dchannel += dchannels)]};
9390 
9391       v_source = (ags_v8double) {(gdouble) source[0],
9392 				 (gdouble) source[(current_schannel = schannels)],
9393 				 (gdouble) source[(current_schannel += schannels)],
9394 				 (gdouble) source[(current_schannel += schannels)],
9395 				 (gdouble) source[(current_schannel += schannels)],
9396 				 (gdouble) source[(current_schannel += schannels)],
9397 				 (gdouble) source[(current_schannel += schannels)],
9398 				 (gdouble) source[(current_schannel += schannels)]};
9399 
9400       /* scale and copy */
9401       v_source *= scale;
9402       v_destination += v_source;
9403 
9404       current_dchannel = 0;
9405 
9406       destination[0] = (gint32) v_destination[0];
9407       destination[(current_dchannel = dchannels)] = (gint32) v_destination[1];
9408       destination[(current_dchannel += dchannels)] = (gint32) v_destination[2];
9409       destination[(current_dchannel += dchannels)] = (gint32) v_destination[3];
9410       destination[(current_dchannel += dchannels)] = (gint32) v_destination[4];
9411       destination[(current_dchannel += dchannels)] = (gint32) v_destination[5];
9412       destination[(current_dchannel += dchannels)] = (gint32) v_destination[6];
9413       destination[(current_dchannel += dchannels)] = (gint32) v_destination[7];
9414 
9415       /* iterate destination */
9416       destination += (current_dchannel + dchannels);
9417 
9418       /* iterate source */
9419       source += (current_schannel + schannels);
9420     }
9421   }
9422 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
9423   /* vectorized function */
9424   if(count > 8){
9425     limit = count - (count % 8);
9426 
9427     for(; i < limit; i += 8){
9428       double v_scaled[8];
9429       double v_result[8];
9430       static const double v_scale[1] = { (double) scale };
9431 
9432       current_dchannel = 0;
9433       current_schannel = 0;
9434 
9435       double v_destination[] = {(double) destination[0],
9436 				(double) destination[(current_dchannel = dchannels)],
9437 				(double) destination[(current_dchannel += dchannels)],
9438 				(double) destination[(current_dchannel += dchannels)],
9439 				(double) destination[(current_dchannel += dchannels)],
9440 				(double) destination[(current_dchannel += dchannels)],
9441 				(double) destination[(current_dchannel += dchannels)],
9442 				(double) destination[(current_dchannel += dchannels)]};
9443 
9444       double v_source[] = {(double) source[0],
9445 			   (double) source[(current_schannel = schannels)],
9446 			   (double) source[(current_schannel += schannels)],
9447 			   (double) source[(current_schannel += schannels)],
9448 			   (double) source[(current_schannel += schannels)],
9449 			   (double) source[(current_schannel += schannels)],
9450 			   (double) source[(current_schannel += schannels)],
9451 			   (double) source[(current_schannel += schannels)]};
9452 
9453       /* no scale, just copy */
9454       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
9455       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
9456 
9457       current_dchannel = 0;
9458 
9459       destination[0] = (gint32) v_result[0];
9460       destination[(current_dchannel = dchannels)] = (gint32) v_result[1];
9461       destination[(current_dchannel += dchannels)] = (gint32) v_result[2];
9462       destination[(current_dchannel += dchannels)] = (gint32) v_result[3];
9463       destination[(current_dchannel += dchannels)] = (gint32) v_result[4];
9464       destination[(current_dchannel += dchannels)] = (gint32) v_result[5];
9465       destination[(current_dchannel += dchannels)] = (gint32) v_result[6];
9466       destination[(current_dchannel += dchannels)] = (gint32) v_result[7];
9467 
9468       /* iterate destination */
9469       destination += (current_dchannel + dchannels);
9470 
9471       /* iterate source */
9472       source += (current_schannel + schannels);
9473     }
9474   }
9475 #else
9476   /* unrolled function */
9477   if(count > 8){
9478     limit = count - (count % 8);
9479 
9480     for(; i < limit; i += 8){
9481       current_dchannel = 0;
9482       current_schannel = 0;
9483 
9484       destination[0] = 0xffffffff & ((gint64) (destination[0] + (gint32) (scale * source[0])));
9485       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel = dchannels)] + (gint32) (scale * source[(current_schannel = schannels)])));
9486       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
9487       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
9488       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
9489       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
9490       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
9491       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
9492 
9493       /* iterate destination */
9494       destination += (current_dchannel + dchannels);
9495 
9496       /* iterate source */
9497       source += (current_schannel + schannels);
9498     }
9499   }
9500 #endif
9501 
9502   for(; i < count; i++){
9503     destination[0] = 0xffffffff & ((gint64) (destination[0] + (gint32) (scale * source[0])));
9504 
9505     destination += dchannels;
9506     source += schannels;
9507   }
9508 }
9509 
9510 /**
9511  * ags_audio_buffer_util_copy_s16_to_s64:
9512  * @destination: destination buffer
9513  * @dchannels: destination buffer's count of channels
9514  * @source: source buffer
9515  * @schannels: source buffer's count of channels
9516  * @count: number of frames to copy
9517  *
9518  * Copy audio data using additive strategy.
9519  *
9520  * Since: 3.0.0
9521  */
9522 void
ags_audio_buffer_util_copy_s16_to_s64(gint64 * destination,guint dchannels,gint16 * source,guint schannels,guint count)9523 ags_audio_buffer_util_copy_s16_to_s64(gint64 *destination, guint dchannels,
9524 				      gint16 *source, guint schannels,
9525 				      guint count)
9526 {
9527   //NOTE:JK: scale = (2^bits_destination / 2.0 - 1.0) / (2^bits_source / 2.0 - 1.0)
9528   static const gdouble scale = 281483566907400.00021362956633198034;
9529   guint limit;
9530   guint current_dchannel, current_schannel;
9531   guint i;
9532 
9533   if(destination == NULL ||
9534      source == NULL){
9535     return;
9536   }
9537 
9538   i = 0;
9539 
9540 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
9541   /* vectorized function */
9542   if(count > 8){
9543     limit = count - (count % 8);
9544 
9545     for(; i < limit; i += 8){
9546       ags_v8double v_destination;
9547       ags_v8double v_source;
9548 
9549       current_dchannel = 0;
9550       current_schannel = 0;
9551 
9552       v_destination = (ags_v8double) {(gdouble) destination[0],
9553 				      (gdouble) destination[(current_dchannel = dchannels)],
9554 				      (gdouble) destination[(current_dchannel += dchannels)],
9555 				      (gdouble) destination[(current_dchannel += dchannels)],
9556 				      (gdouble) destination[(current_dchannel += dchannels)],
9557 				      (gdouble) destination[(current_dchannel += dchannels)],
9558 				      (gdouble) destination[(current_dchannel += dchannels)],
9559 				      (gdouble) destination[(current_dchannel += dchannels)]};
9560 
9561       v_source = (ags_v8double) {(gdouble) source[0],
9562 				 (gdouble) source[(current_schannel = schannels)],
9563 				 (gdouble) source[(current_schannel += schannels)],
9564 				 (gdouble) source[(current_schannel += schannels)],
9565 				 (gdouble) source[(current_schannel += schannels)],
9566 				 (gdouble) source[(current_schannel += schannels)],
9567 				 (gdouble) source[(current_schannel += schannels)],
9568 				 (gdouble) source[(current_schannel += schannels)]};
9569 
9570       /* scale and copy */
9571       v_source *= scale;
9572       v_destination += v_source;
9573 
9574       current_dchannel = 0;
9575 
9576       destination[0] = (gint64) v_destination[0];
9577       destination[(current_dchannel = dchannels)] = (gint64) v_destination[1];
9578       destination[(current_dchannel += dchannels)] = (gint64) v_destination[2];
9579       destination[(current_dchannel += dchannels)] = (gint64) v_destination[3];
9580       destination[(current_dchannel += dchannels)] = (gint64) v_destination[4];
9581       destination[(current_dchannel += dchannels)] = (gint64) v_destination[5];
9582       destination[(current_dchannel += dchannels)] = (gint64) v_destination[6];
9583       destination[(current_dchannel += dchannels)] = (gint64) v_destination[7];
9584 
9585       /* iterate destination */
9586       destination += (current_dchannel + dchannels);
9587 
9588       /* iterate source */
9589       source += (current_schannel + schannels);
9590     }
9591   }
9592 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
9593   /* vectorized function */
9594   if(count > 8){
9595     limit = count - (count % 8);
9596 
9597     for(; i < limit; i += 8){
9598       double v_scaled[8];
9599       double v_result[8];
9600       static const double v_scale[1] = { (double) scale };
9601 
9602       current_dchannel = 0;
9603       current_schannel = 0;
9604 
9605       double v_destination[] = {(double) destination[0],
9606 				(double) destination[(current_dchannel = dchannels)],
9607 				(double) destination[(current_dchannel += dchannels)],
9608 				(double) destination[(current_dchannel += dchannels)],
9609 				(double) destination[(current_dchannel += dchannels)],
9610 				(double) destination[(current_dchannel += dchannels)],
9611 				(double) destination[(current_dchannel += dchannels)],
9612 				(double) destination[(current_dchannel += dchannels)]};
9613 
9614       double v_source[] = {(double) source[0],
9615 			   (double) source[(current_schannel = schannels)],
9616 			   (double) source[(current_schannel += schannels)],
9617 			   (double) source[(current_schannel += schannels)],
9618 			   (double) source[(current_schannel += schannels)],
9619 			   (double) source[(current_schannel += schannels)],
9620 			   (double) source[(current_schannel += schannels)],
9621 			   (double) source[(current_schannel += schannels)]};
9622 
9623       /* no scale, just copy */
9624       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
9625       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
9626 
9627       current_dchannel = 0;
9628 
9629       destination[0] = (gint64) v_result[0];
9630       destination[(current_dchannel = dchannels)] = (gint64) v_result[1];
9631       destination[(current_dchannel += dchannels)] = (gint64) v_result[2];
9632       destination[(current_dchannel += dchannels)] = (gint64) v_result[3];
9633       destination[(current_dchannel += dchannels)] = (gint64) v_result[4];
9634       destination[(current_dchannel += dchannels)] = (gint64) v_result[5];
9635       destination[(current_dchannel += dchannels)] = (gint64) v_result[6];
9636       destination[(current_dchannel += dchannels)] = (gint64) v_result[7];
9637 
9638       /* iterate destination */
9639       destination += (current_dchannel + dchannels);
9640 
9641       /* iterate source */
9642       source += (current_schannel + schannels);
9643     }
9644   }
9645 #else
9646   /* unrolled function */
9647   if(count > 8){
9648     limit = count - (count % 8);
9649 
9650     for(; i < limit; i += 8){
9651       current_dchannel = 0;
9652       current_schannel = 0;
9653 
9654       destination[0] = 0xffffffffffffffff & ((gint64) (destination[0] + (gint64) (scale * source[0])));
9655       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel = dchannels)] + (gint64) (scale * source[(current_schannel = schannels)])));
9656       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (gint64) (scale * source[(current_schannel += schannels)])));
9657       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (gint64) (scale * source[(current_schannel += schannels)])));
9658       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (gint64) (scale * source[(current_schannel += schannels)])));
9659       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (gint64) (scale * source[(current_schannel += schannels)])));
9660       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (gint64) (scale * source[(current_schannel += schannels)])));
9661       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (gint64) (scale * source[(current_schannel += schannels)])));
9662 
9663       /* iterate destination */
9664       destination += (current_dchannel + dchannels);
9665 
9666       /* iterate source */
9667       source += (current_schannel + schannels);
9668     }
9669   }
9670 #endif
9671 
9672   for(; i < count; i++){
9673     destination[0] = 0xffffffffffffffff & ((gint64) (destination[0] + (gint64) (scale * source[0])));
9674 
9675     destination += dchannels;
9676     source += schannels;
9677   }
9678 }
9679 
9680 /**
9681  * ags_audio_buffer_util_copy_s16_to_float:
9682  * @destination: destination buffer
9683  * @dchannels: destination buffer's count of channels
9684  * @source: source buffer
9685  * @schannels: source buffer's count of channels
9686  * @count: number of frames to copy
9687  *
9688  * Copy audio data using additive strategy.
9689  *
9690  * Since: 3.0.0
9691  */
9692 void
ags_audio_buffer_util_copy_s16_to_float(gfloat * destination,guint dchannels,gint16 * source,guint schannels,guint count)9693 ags_audio_buffer_util_copy_s16_to_float(gfloat *destination, guint dchannels,
9694 					gint16 *source, guint schannels,
9695 					guint count)
9696 {
9697   //NOTE:JK: scale = 1.0 / (2^bits_source / 2.0 - 1.0)
9698   //  static const gdouble scale = 0.00003051850947599719;
9699   static const gdouble normalize_divisor = 32767.0;
9700   guint limit;
9701   guint current_dchannel, current_schannel;
9702   guint i;
9703 
9704   if(destination == NULL ||
9705      source == NULL){
9706     return;
9707   }
9708 
9709   i = 0;
9710 
9711 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
9712   /* vectorized function */
9713   if(count > 8){
9714     limit = count - (count % 8);
9715 
9716     for(; i < limit; i += 8){
9717       ags_v8float v_destination;
9718       ags_v8float v_source;
9719 
9720       current_dchannel = 0;
9721       current_schannel = 0;
9722 
9723       v_destination = (ags_v8float) {(gfloat) destination[0],
9724 				     (gfloat) destination[(current_dchannel = dchannels)],
9725 				     (gfloat) destination[(current_dchannel += dchannels)],
9726 				     (gfloat) destination[(current_dchannel += dchannels)],
9727 				     (gfloat) destination[(current_dchannel += dchannels)],
9728 				     (gfloat) destination[(current_dchannel += dchannels)],
9729 				     (gfloat) destination[(current_dchannel += dchannels)],
9730 				     (gfloat) destination[(current_dchannel += dchannels)]};
9731 
9732       v_source = (ags_v8float) {(gfloat) source[0],
9733 				(gfloat) source[(current_schannel = schannels)],
9734 				(gfloat) source[(current_schannel += schannels)],
9735 				(gfloat) source[(current_schannel += schannels)],
9736 				(gfloat) source[(current_schannel += schannels)],
9737 				(gfloat) source[(current_schannel += schannels)],
9738 				(gfloat) source[(current_schannel += schannels)],
9739 				(gfloat) source[(current_schannel += schannels)]};
9740 
9741       /* normalize and copy */
9742       v_source /= (gfloat) normalize_divisor;
9743       v_destination += v_source;
9744 
9745       current_dchannel = 0;
9746 
9747       destination[0] = (gfloat) v_destination[0];
9748       destination[(current_dchannel = dchannels)] = (gfloat) v_destination[1];
9749       destination[(current_dchannel += dchannels)] = (gfloat) v_destination[2];
9750       destination[(current_dchannel += dchannels)] = (gfloat) v_destination[3];
9751       destination[(current_dchannel += dchannels)] = (gfloat) v_destination[4];
9752       destination[(current_dchannel += dchannels)] = (gfloat) v_destination[5];
9753       destination[(current_dchannel += dchannels)] = (gfloat) v_destination[6];
9754       destination[(current_dchannel += dchannels)] = (gfloat) v_destination[7];
9755 
9756       /* iterate destination */
9757       destination += (current_dchannel + dchannels);
9758 
9759       /* iterate source */
9760       source += (current_schannel + schannels);
9761     }
9762   }
9763 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
9764   /* vectorized function */
9765   if(count > 8){
9766     limit = count - (count % 8);
9767 
9768     for(; i < limit; i += 8){
9769       double v_normalized[8];
9770       double v_result[8];
9771       static const double v_normalize_divisor[1] = { (double) normalize_divisor };
9772 
9773       current_dchannel = 0;
9774       current_schannel = 0;
9775 
9776       double v_destination[] = {(double) destination[0],
9777 				(double) destination[(current_dchannel = dchannels)],
9778 				(double) destination[(current_dchannel += dchannels)],
9779 				(double) destination[(current_dchannel += dchannels)],
9780 				(double) destination[(current_dchannel += dchannels)],
9781 				(double) destination[(current_dchannel += dchannels)],
9782 				(double) destination[(current_dchannel += dchannels)],
9783 				(double) destination[(current_dchannel += dchannels)]};
9784 
9785       double v_source[] = {(double) source[0],
9786 			   (double) source[(current_schannel = schannels)],
9787 			   (double) source[(current_schannel += schannels)],
9788 			   (double) source[(current_schannel += schannels)],
9789 			   (double) source[(current_schannel += schannels)],
9790 			   (double) source[(current_schannel += schannels)],
9791 			   (double) source[(current_schannel += schannels)],
9792 			   (double) source[(current_schannel += schannels)]};
9793 
9794       /* no scale, just copy */
9795       vDSP_vdivD(v_normalize_divisor, 0, v_source, 1, v_normalized, 1, 8);
9796       vDSP_vaddD(v_destination, 1, v_normalized, 1, v_result, 1, 8);
9797 
9798       current_dchannel = 0;
9799 
9800       destination[0] = (gfloat) v_result[0];
9801       destination[(current_dchannel = dchannels)] = (gfloat) v_result[1];
9802       destination[(current_dchannel += dchannels)] = (gfloat) v_result[2];
9803       destination[(current_dchannel += dchannels)] = (gfloat) v_result[3];
9804       destination[(current_dchannel += dchannels)] = (gfloat) v_result[4];
9805       destination[(current_dchannel += dchannels)] = (gfloat) v_result[5];
9806       destination[(current_dchannel += dchannels)] = (gfloat) v_result[6];
9807       destination[(current_dchannel += dchannels)] = (gfloat) v_result[7];
9808 
9809       /* iterate destination */
9810       destination += (current_dchannel + dchannels);
9811 
9812       /* iterate source */
9813       source += (current_schannel + schannels);
9814     }
9815   }
9816 #else
9817   /* unrolled function */
9818   if(count > 8){
9819     limit = count - (count % 8);
9820 
9821     for(; i < limit; i += 8){
9822       current_dchannel = 0;
9823       current_schannel = 0;
9824 
9825       destination[0] = (gfloat) ((gdouble) (destination[0] + (gdouble) (source[0] / normalize_divisor)));
9826       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (source[(current_schannel = schannels)] / normalize_divisor)));
9827       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
9828       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
9829       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
9830       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
9831       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
9832       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
9833 
9834       /* iterate destination */
9835       destination += (current_dchannel + dchannels);
9836 
9837       /* iterate source */
9838       source += (current_schannel + schannels);
9839     }
9840   }
9841 #endif
9842 
9843   for(; i < count; i++){
9844     destination[0] = (gfloat) ((gdouble) (destination[0] + (gdouble) (source[0] / normalize_divisor)));
9845 
9846     destination += dchannels;
9847     source += schannels;
9848   }
9849 }
9850 
9851 /**
9852  * ags_audio_buffer_util_copy_s16_to_double:
9853  * @destination: destination buffer
9854  * @dchannels: destination buffer's count of channels
9855  * @source: source buffer
9856  * @schannels: source buffer's count of channels
9857  * @count: number of frames to copy
9858  *
9859  * Copy audio data using additive strategy.
9860  *
9861  * Since: 3.0.0
9862  */
9863 void
ags_audio_buffer_util_copy_s16_to_double(gdouble * destination,guint dchannels,gint16 * source,guint schannels,guint count)9864 ags_audio_buffer_util_copy_s16_to_double(gdouble *destination, guint dchannels,
9865 					 gint16 *source, guint schannels,
9866 					 guint count)
9867 {
9868   //NOTE:JK: scale = 1.0 / (2^bits_source / 2.0 - 1.0)
9869   //  static const gdouble scale = 0.00003051850947599719;
9870   static const gdouble normalize_divisor = 32767.0;
9871   guint limit;
9872   guint current_dchannel, current_schannel;
9873   guint i;
9874 
9875   if(destination == NULL ||
9876      source == NULL){
9877     return;
9878   }
9879 
9880   i = 0;
9881 
9882 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
9883   /* vectorized function */
9884   if(count > 8){
9885     limit = count - (count % 8);
9886 
9887     for(; i < limit; i += 8){
9888       ags_v8double v_destination;
9889       ags_v8double v_source;
9890 
9891       current_dchannel = 0;
9892       current_schannel = 0;
9893 
9894       v_destination = (ags_v8double) {(gdouble) destination[0],
9895 				      (gdouble) destination[(current_dchannel = dchannels)],
9896 				      (gdouble) destination[(current_dchannel += dchannels)],
9897 				      (gdouble) destination[(current_dchannel += dchannels)],
9898 				      (gdouble) destination[(current_dchannel += dchannels)],
9899 				      (gdouble) destination[(current_dchannel += dchannels)],
9900 				      (gdouble) destination[(current_dchannel += dchannels)],
9901 				      (gdouble) destination[(current_dchannel += dchannels)]};
9902 
9903       v_source = (ags_v8double) {(gdouble) source[0],
9904 				 (gdouble) source[(current_schannel = schannels)],
9905 				 (gdouble) source[(current_schannel += schannels)],
9906 				 (gdouble) source[(current_schannel += schannels)],
9907 				 (gdouble) source[(current_schannel += schannels)],
9908 				 (gdouble) source[(current_schannel += schannels)],
9909 				 (gdouble) source[(current_schannel += schannels)],
9910 				 (gdouble) source[(current_schannel += schannels)]};
9911 
9912       /* normalize and copy */
9913       v_source /= normalize_divisor;
9914       v_destination += v_source;
9915 
9916       current_dchannel = 0;
9917 
9918       destination[0] = v_destination[0];
9919       destination[(current_dchannel = dchannels)] = v_destination[1];
9920       destination[(current_dchannel += dchannels)] = v_destination[2];
9921       destination[(current_dchannel += dchannels)] = v_destination[3];
9922       destination[(current_dchannel += dchannels)] = v_destination[4];
9923       destination[(current_dchannel += dchannels)] = v_destination[5];
9924       destination[(current_dchannel += dchannels)] = v_destination[6];
9925       destination[(current_dchannel += dchannels)] = v_destination[7];
9926 
9927       /* iterate destination */
9928       destination += (current_dchannel + dchannels);
9929 
9930       /* iterate source */
9931       source += (current_schannel + schannels);
9932     }
9933   }
9934 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
9935   /* vectorized function */
9936   if(count > 8){
9937     limit = count - (count % 8);
9938 
9939     for(; i < limit; i += 8){
9940       double v_normalized[8];
9941       double v_result[8];
9942       static const double v_normalize_divisor[1] = { (double) normalize_divisor };
9943 
9944       current_dchannel = 0;
9945       current_schannel = 0;
9946 
9947       double v_destination[] = {(double) destination[0],
9948 				(double) destination[(current_dchannel = dchannels)],
9949 				(double) destination[(current_dchannel += dchannels)],
9950 				(double) destination[(current_dchannel += dchannels)],
9951 				(double) destination[(current_dchannel += dchannels)],
9952 				(double) destination[(current_dchannel += dchannels)],
9953 				(double) destination[(current_dchannel += dchannels)],
9954 				(double) destination[(current_dchannel += dchannels)]};
9955 
9956       double v_source[] = {(double) source[0],
9957 			   (double) source[(current_schannel = schannels)],
9958 			   (double) source[(current_schannel += schannels)],
9959 			   (double) source[(current_schannel += schannels)],
9960 			   (double) source[(current_schannel += schannels)],
9961 			   (double) source[(current_schannel += schannels)],
9962 			   (double) source[(current_schannel += schannels)],
9963 			   (double) source[(current_schannel += schannels)]};
9964 
9965       /* no scale, just copy */
9966       vDSP_vdivD(v_normalize_divisor, 0, v_source, 1, v_normalized, 1, 8);
9967       vDSP_vaddD(v_destination, 1, v_normalized, 1, v_result, 1, 8);
9968 
9969       current_dchannel = 0;
9970 
9971       destination[0] = (gdouble) v_result[0];
9972       destination[(current_dchannel = dchannels)] = (gdouble) v_result[1];
9973       destination[(current_dchannel += dchannels)] = (gdouble) v_result[2];
9974       destination[(current_dchannel += dchannels)] = (gdouble) v_result[3];
9975       destination[(current_dchannel += dchannels)] = (gdouble) v_result[4];
9976       destination[(current_dchannel += dchannels)] = (gdouble) v_result[5];
9977       destination[(current_dchannel += dchannels)] = (gdouble) v_result[6];
9978       destination[(current_dchannel += dchannels)] = (gdouble) v_result[7];
9979 
9980       /* iterate destination */
9981       destination += (current_dchannel + dchannels);
9982 
9983       /* iterate source */
9984       source += (current_schannel + schannels);
9985     }
9986   }
9987 #else
9988   /* unrolled function */
9989   if(count > 8){
9990     limit = count - (count % 8);
9991 
9992     for(; i < limit; i += 8){
9993       current_dchannel = 0;
9994       current_schannel = 0;
9995 
9996       destination[0] = ((gdouble) (destination[0] + (gdouble) (source[0] / normalize_divisor)));
9997       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (source[(current_schannel = schannels)] / normalize_divisor)));
9998       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
9999       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
10000       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
10001       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
10002       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
10003       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
10004 
10005       /* iterate destination */
10006       destination += (current_dchannel + dchannels);
10007 
10008       /* iterate source */
10009       source += (current_schannel + schannels);
10010     }
10011   }
10012 #endif
10013 
10014   for(; i < count; i++){
10015     destination[0] = ((gdouble) (destination[0] + (gdouble) (source[0] / normalize_divisor)));
10016 
10017     destination += dchannels;
10018     source += schannels;
10019   }
10020 }
10021 
10022 /**
10023  * ags_audio_buffer_util_copy_s24_to_s8:
10024  * @destination: destination buffer
10025  * @dchannels: destination buffer's count of channels
10026  * @source: source buffer
10027  * @schannels: source buffer's count of channels
10028  * @count: number of frames to copy
10029  *
10030  * Copy audio data using additive strategy.
10031  *
10032  * Since: 3.0.0
10033  */
10034 void
ags_audio_buffer_util_copy_s24_to_s8(gint8 * destination,guint dchannels,gint32 * source,guint schannels,guint count)10035 ags_audio_buffer_util_copy_s24_to_s8(gint8 *destination, guint dchannels,
10036 				     gint32 *source, guint schannels,
10037 				     guint count)
10038 {
10039   //NOTE:JK: scale = (2^bits_destination / 2.0 - 1.0) / (2^bits_source / 2.0 - 1.0)
10040   static const gdouble scale = 0.00001513958157772798;
10041   guint limit;
10042   guint current_dchannel, current_schannel;
10043   guint i;
10044 
10045   if(destination == NULL ||
10046      source == NULL){
10047     return;
10048   }
10049 
10050   i = 0;
10051 
10052 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
10053   /* vectorized function */
10054   if(count > 8){
10055     limit = count - (count % 8);
10056 
10057     for(; i < limit; i += 8){
10058       ags_v8double v_destination;
10059       ags_v8double v_source;
10060 
10061       current_dchannel = 0;
10062       current_schannel = 0;
10063 
10064       v_destination = (ags_v8double) {(gdouble) destination[0],
10065 				      (gdouble) destination[(current_dchannel = dchannels)],
10066 				      (gdouble) destination[(current_dchannel += dchannels)],
10067 				      (gdouble) destination[(current_dchannel += dchannels)],
10068 				      (gdouble) destination[(current_dchannel += dchannels)],
10069 				      (gdouble) destination[(current_dchannel += dchannels)],
10070 				      (gdouble) destination[(current_dchannel += dchannels)],
10071 				      (gdouble) destination[(current_dchannel += dchannels)]};
10072 
10073       v_source = (ags_v8double) {(gdouble) source[0],
10074 				 (gdouble) source[(current_schannel = schannels)],
10075 				 (gdouble) source[(current_schannel += schannels)],
10076 				 (gdouble) source[(current_schannel += schannels)],
10077 				 (gdouble) source[(current_schannel += schannels)],
10078 				 (gdouble) source[(current_schannel += schannels)],
10079 				 (gdouble) source[(current_schannel += schannels)],
10080 				 (gdouble) source[(current_schannel += schannels)]};
10081 
10082       /* scale and copy */
10083       v_source *= scale;
10084       v_destination += v_source;
10085 
10086       current_dchannel = 0;
10087 
10088       destination[0] = (gint8) v_destination[0];
10089       destination[(current_dchannel = dchannels)] = (gint8) v_destination[1];
10090       destination[(current_dchannel += dchannels)] = (gint8) v_destination[2];
10091       destination[(current_dchannel += dchannels)] = (gint8) v_destination[3];
10092       destination[(current_dchannel += dchannels)] = (gint8) v_destination[4];
10093       destination[(current_dchannel += dchannels)] = (gint8) v_destination[5];
10094       destination[(current_dchannel += dchannels)] = (gint8) v_destination[6];
10095       destination[(current_dchannel += dchannels)] = (gint8) v_destination[7];
10096 
10097       /* iterate destination */
10098       destination += (current_dchannel + dchannels);
10099 
10100       /* iterate source */
10101       source += (current_schannel + schannels);
10102     }
10103   }
10104 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
10105   /* vectorized function */
10106   if(count > 8){
10107     limit = count - (count % 8);
10108 
10109     for(; i < limit; i += 8){
10110       double v_scaled[8];
10111       double v_result[8];
10112       static const double v_scale[1] = { (double) scale };
10113 
10114       current_dchannel = 0;
10115       current_schannel = 0;
10116 
10117       double v_destination[] = {(double) destination[0],
10118 				(double) destination[(current_dchannel = dchannels)],
10119 				(double) destination[(current_dchannel += dchannels)],
10120 				(double) destination[(current_dchannel += dchannels)],
10121 				(double) destination[(current_dchannel += dchannels)],
10122 				(double) destination[(current_dchannel += dchannels)],
10123 				(double) destination[(current_dchannel += dchannels)],
10124 				(double) destination[(current_dchannel += dchannels)]};
10125 
10126       double v_source[] = {(double) source[0],
10127 			   (double) source[(current_schannel = schannels)],
10128 			   (double) source[(current_schannel += schannels)],
10129 			   (double) source[(current_schannel += schannels)],
10130 			   (double) source[(current_schannel += schannels)],
10131 			   (double) source[(current_schannel += schannels)],
10132 			   (double) source[(current_schannel += schannels)],
10133 			   (double) source[(current_schannel += schannels)]};
10134 
10135       /* no scale, just copy */
10136       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
10137       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
10138 
10139       current_dchannel = 0;
10140 
10141       destination[0] = (gint8) v_result[0];
10142       destination[(current_dchannel = dchannels)] = (gint8) v_result[1];
10143       destination[(current_dchannel += dchannels)] = (gint8) v_result[2];
10144       destination[(current_dchannel += dchannels)] = (gint8) v_result[3];
10145       destination[(current_dchannel += dchannels)] = (gint8) v_result[4];
10146       destination[(current_dchannel += dchannels)] = (gint8) v_result[5];
10147       destination[(current_dchannel += dchannels)] = (gint8) v_result[6];
10148       destination[(current_dchannel += dchannels)] = (gint8) v_result[7];
10149 
10150       /* iterate destination */
10151       destination += (current_dchannel + dchannels);
10152 
10153       /* iterate source */
10154       source += (current_schannel + schannels);
10155     }
10156   }
10157 #else
10158   /* unrolled function */
10159   if(count > 8){
10160     limit = count - (count % 8);
10161 
10162     for(; i < limit; i += 8){
10163       current_dchannel = 0;
10164       current_schannel = 0;
10165 
10166       destination[0] = 0xff & ((gint16) (destination[0] + (scale * source[0])));
10167       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel = dchannels)] + (scale * source[(current_schannel = schannels)])));
10168       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
10169       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
10170       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
10171       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
10172       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
10173       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
10174 
10175       /* iterate destination */
10176       destination += (current_dchannel + dchannels);
10177 
10178       /* iterate source */
10179       source += (current_schannel + schannels);
10180     }
10181   }
10182 #endif
10183 
10184   for(; i < count; i++){
10185     destination[0] = 0xff & ((gint16) (destination[0] + (scale * source[0])));
10186 
10187     destination += dchannels;
10188     source += schannels;
10189   }
10190 }
10191 
10192 /**
10193  * ags_audio_buffer_util_copy_s24_to_s16:
10194  * @destination: destination buffer
10195  * @dchannels: destination buffer's count of channels
10196  * @source: source buffer
10197  * @schannels: source buffer's count of channels
10198  * @count: number of frames to copy
10199  *
10200  * Copy audio data using additive strategy.
10201  *
10202  * Since: 3.0.0
10203  */
10204 void
ags_audio_buffer_util_copy_s24_to_s16(gint16 * destination,guint dchannels,gint32 * source,guint schannels,guint count)10205 ags_audio_buffer_util_copy_s24_to_s16(gint16 *destination, guint dchannels,
10206 				      gint32 *source, guint schannels,
10207 				      guint count)
10208 {
10209   //NOTE:JK: scale = (2^bits_destination / 2.0 - 1.0) / (2^bits_source / 2.0 - 1.0)
10210   static const gdouble scale = 0.00390613125635758118;
10211   guint limit;
10212   guint current_dchannel, current_schannel;
10213   guint i;
10214 
10215   if(destination == NULL ||
10216      source == NULL){
10217     return;
10218   }
10219 
10220   i = 0;
10221 
10222 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
10223   /* vectorized function */
10224   if(count > 8){
10225     limit = count - (count % 8);
10226 
10227     for(; i < limit; i += 8){
10228       ags_v8double v_destination;
10229       ags_v8double v_source;
10230 
10231       current_dchannel = 0;
10232       current_schannel = 0;
10233 
10234       v_destination = (ags_v8double) {(gdouble) destination[0],
10235 				      (gdouble) destination[(current_dchannel = dchannels)],
10236 				      (gdouble) destination[(current_dchannel += dchannels)],
10237 				      (gdouble) destination[(current_dchannel += dchannels)],
10238 				      (gdouble) destination[(current_dchannel += dchannels)],
10239 				      (gdouble) destination[(current_dchannel += dchannels)],
10240 				      (gdouble) destination[(current_dchannel += dchannels)],
10241 				      (gdouble) destination[(current_dchannel += dchannels)]};
10242 
10243       v_source = (ags_v8double) {(gdouble) source[0],
10244 				 (gdouble) source[(current_schannel = schannels)],
10245 				 (gdouble) source[(current_schannel += schannels)],
10246 				 (gdouble) source[(current_schannel += schannels)],
10247 				 (gdouble) source[(current_schannel += schannels)],
10248 				 (gdouble) source[(current_schannel += schannels)],
10249 				 (gdouble) source[(current_schannel += schannels)],
10250 				 (gdouble) source[(current_schannel += schannels)]};
10251 
10252       /* scale and copy */
10253       v_source *= scale;
10254       v_destination += v_source;
10255 
10256       current_dchannel = 0;
10257 
10258       destination[0] = (gint16) v_destination[0];
10259       destination[(current_dchannel = dchannels)] = (gint16) v_destination[1];
10260       destination[(current_dchannel += dchannels)] = (gint16) v_destination[2];
10261       destination[(current_dchannel += dchannels)] = (gint16) v_destination[3];
10262       destination[(current_dchannel += dchannels)] = (gint16) v_destination[4];
10263       destination[(current_dchannel += dchannels)] = (gint16) v_destination[5];
10264       destination[(current_dchannel += dchannels)] = (gint16) v_destination[6];
10265       destination[(current_dchannel += dchannels)] = (gint16) v_destination[7];
10266 
10267       /* iterate destination */
10268       destination += (current_dchannel + dchannels);
10269 
10270       /* iterate source */
10271       source += (current_schannel + schannels);
10272     }
10273   }
10274 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
10275   /* vectorized function */
10276   if(count > 8){
10277     limit = count - (count % 8);
10278 
10279     for(; i < limit; i += 8){
10280       double v_scaled[8];
10281       double v_result[8];
10282       static const double v_scale[1] = { (double) scale };
10283 
10284       current_dchannel = 0;
10285       current_schannel = 0;
10286 
10287       double v_destination[] = {(double) destination[0],
10288 				(double) destination[(current_dchannel = dchannels)],
10289 				(double) destination[(current_dchannel += dchannels)],
10290 				(double) destination[(current_dchannel += dchannels)],
10291 				(double) destination[(current_dchannel += dchannels)],
10292 				(double) destination[(current_dchannel += dchannels)],
10293 				(double) destination[(current_dchannel += dchannels)],
10294 				(double) destination[(current_dchannel += dchannels)]};
10295 
10296       double v_source[] = {(double) source[0],
10297 			   (double) source[(current_schannel = schannels)],
10298 			   (double) source[(current_schannel += schannels)],
10299 			   (double) source[(current_schannel += schannels)],
10300 			   (double) source[(current_schannel += schannels)],
10301 			   (double) source[(current_schannel += schannels)],
10302 			   (double) source[(current_schannel += schannels)],
10303 			   (double) source[(current_schannel += schannels)]};
10304 
10305       /* no scale, just copy */
10306       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
10307       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
10308 
10309       current_dchannel = 0;
10310 
10311       destination[0] = (gint16) v_result[0];
10312       destination[(current_dchannel = dchannels)] = (gint16) v_result[1];
10313       destination[(current_dchannel += dchannels)] = (gint16) v_result[2];
10314       destination[(current_dchannel += dchannels)] = (gint16) v_result[3];
10315       destination[(current_dchannel += dchannels)] = (gint16) v_result[4];
10316       destination[(current_dchannel += dchannels)] = (gint16) v_result[5];
10317       destination[(current_dchannel += dchannels)] = (gint16) v_result[6];
10318       destination[(current_dchannel += dchannels)] = (gint16) v_result[7];
10319 
10320       /* iterate destination */
10321       destination += (current_dchannel + dchannels);
10322 
10323       /* iterate source */
10324       source += (current_schannel + schannels);
10325     }
10326   }
10327 #else
10328   /* unrolled function */
10329   if(count > 8){
10330     limit = count - (count % 8);
10331 
10332     for(; i < limit; i += 8){
10333       current_dchannel = 0;
10334       current_schannel = 0;
10335 
10336       destination[0] = 0xffff & ((gint32) (destination[0] + (gint32) (scale * source[0])));
10337       destination[current_dchannel] = 0xffff & ((gint32) (destination[(current_dchannel = dchannels)] + (gint32) (scale * source[(current_schannel = schannels)])));
10338       destination[current_dchannel] = 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
10339       destination[current_dchannel] = 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
10340       destination[current_dchannel] = 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
10341       destination[current_dchannel] = 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
10342       destination[current_dchannel] = 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
10343       destination[current_dchannel] = 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + (gint32) (scale * source[(current_schannel += schannels)])));
10344 
10345       /* iterate destination */
10346       destination += (current_dchannel + dchannels);
10347 
10348       /* iterate source */
10349       source += (current_schannel + schannels);
10350     }
10351   }
10352 #endif
10353 
10354   for(; i < count; i++){
10355     destination[0] = 0xffff & ((gint32) (destination[0] + (scale * source[0])));
10356 
10357     destination += dchannels;
10358     source += schannels;
10359   }
10360 }
10361 
10362 /**
10363  * ags_audio_buffer_util_copy_s24_to_s24:
10364  * @destination: destination buffer
10365  * @dchannels: destination buffer's count of channels
10366  * @source: source buffer
10367  * @schannels: source buffer's count of channels
10368  * @count: number of frames to copy
10369  *
10370  * Copy audio data using additive strategy.
10371  *
10372  * Since: 3.0.0
10373  */
10374 void
ags_audio_buffer_util_copy_s24_to_s24(gint32 * destination,guint dchannels,gint32 * source,guint schannels,guint count)10375 ags_audio_buffer_util_copy_s24_to_s24(gint32 *destination, guint dchannels,
10376 				      gint32 *source, guint schannels,
10377 				      guint count)
10378 {
10379   guint limit;
10380   guint current_dchannel, current_schannel;
10381   guint i;
10382 
10383   if(destination == NULL ||
10384      source == NULL){
10385     return;
10386   }
10387 
10388   i = 0;
10389 
10390 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
10391   /* vectorized function */
10392   if(count > 8){
10393     limit = count - (count % 8);
10394 
10395     for(; i < limit; i += 8){
10396       ags_v8s32 v_destination;
10397       ags_v8s32 v_source;
10398 
10399       current_dchannel = 0;
10400       current_schannel = 0;
10401 
10402       v_destination = (ags_v8s32) {destination[0],
10403 				   destination[(current_dchannel = dchannels)],
10404 				   destination[(current_dchannel += dchannels)],
10405 				   destination[(current_dchannel += dchannels)],
10406 				   destination[(current_dchannel += dchannels)],
10407 				   destination[(current_dchannel += dchannels)],
10408 				   destination[(current_dchannel += dchannels)],
10409 				   destination[(current_dchannel += dchannels)]};
10410 
10411       v_source = (ags_v8s32) {source[0],
10412 			      source[(current_schannel = schannels)],
10413 			      source[(current_schannel += schannels)],
10414 			      source[(current_schannel += schannels)],
10415 			      source[(current_schannel += schannels)],
10416 			      source[(current_schannel += schannels)],
10417 			      source[(current_schannel += schannels)],
10418 			      source[(current_schannel += schannels)]};
10419 
10420       /* no scale, just copy */
10421       v_destination += v_source;
10422 
10423       current_dchannel = 0;
10424 
10425       destination[0] = v_destination[0];
10426       destination[(current_dchannel = dchannels)] = v_destination[1];
10427       destination[(current_dchannel += dchannels)] = v_destination[2];
10428       destination[(current_dchannel += dchannels)] = v_destination[3];
10429       destination[(current_dchannel += dchannels)] = v_destination[4];
10430       destination[(current_dchannel += dchannels)] = v_destination[5];
10431       destination[(current_dchannel += dchannels)] = v_destination[6];
10432       destination[(current_dchannel += dchannels)] = v_destination[7];
10433 
10434       /* iterate destination */
10435       destination += (current_dchannel + dchannels);
10436 
10437       /* iterate source */
10438       source += (current_schannel + schannels);
10439     }
10440   }
10441 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
10442   /* vectorized function */
10443   if(count > 8){
10444     limit = count - (count % 8);
10445 
10446     for(; i < limit; i += 8){
10447       int v_result[8];
10448 
10449       current_dchannel = 0;
10450       current_schannel = 0;
10451 
10452       int v_destination[] = {(int) destination[0],
10453 			     (int) destination[(current_dchannel = dchannels)],
10454 			     (int) destination[(current_dchannel += dchannels)],
10455 			     (int) destination[(current_dchannel += dchannels)],
10456 			     (int) destination[(current_dchannel += dchannels)],
10457 			     (int) destination[(current_dchannel += dchannels)],
10458 			     (int) destination[(current_dchannel += dchannels)],
10459 			     (int) destination[(current_dchannel += dchannels)]};
10460 
10461       int v_source[] = {(int) source[0],
10462 			(int) source[(current_schannel = schannels)],
10463 			(int) source[(current_schannel += schannels)],
10464 			(int) source[(current_schannel += schannels)],
10465 			(int) source[(current_schannel += schannels)],
10466 			(int) source[(current_schannel += schannels)],
10467 			(int) source[(current_schannel += schannels)],
10468 			(int) source[(current_schannel += schannels)]};
10469 
10470       /* no scale, just copy */
10471       vDSP_vaddi(v_destination, 1, v_source, 1, v_result, 1, 8);
10472 
10473       current_dchannel = 0;
10474 
10475       destination[0] = (gint32) v_result[0];
10476       destination[(current_dchannel = dchannels)] = (gint32) v_result[1];
10477       destination[(current_dchannel += dchannels)] = (gint32) v_result[2];
10478       destination[(current_dchannel += dchannels)] = (gint32) v_result[3];
10479       destination[(current_dchannel += dchannels)] = (gint32) v_result[4];
10480       destination[(current_dchannel += dchannels)] = (gint32) v_result[5];
10481       destination[(current_dchannel += dchannels)] = (gint32) v_result[6];
10482       destination[(current_dchannel += dchannels)] = (gint32) v_result[7];
10483 
10484       /* iterate destination */
10485       destination += (current_dchannel + dchannels);
10486 
10487       /* iterate source */
10488       source += (current_schannel + schannels);
10489     }
10490   }
10491 #else
10492   /* unrolled function */
10493   if(count > 8){
10494     limit = count - (count % 8);
10495 
10496     for(; i < limit; i += 8){
10497       current_dchannel = 0;
10498       current_schannel = 0;
10499 
10500       destination[0] = 0xffffffff & ((gint32) (destination[0] + source[0]));
10501       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel = dchannels)] + source[(current_schannel = schannels)]));
10502       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + source[(current_schannel += schannels)]));
10503       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + source[(current_schannel += schannels)]));
10504       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + source[(current_schannel += schannels)]));
10505       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + source[(current_schannel += schannels)]));
10506       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + source[(current_schannel += schannels)]));
10507       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + source[(current_schannel += schannels)]));
10508 
10509       /* iterate destination */
10510       destination += (current_dchannel + dchannels);
10511 
10512       /* iterate source */
10513       source += (current_schannel + schannels);
10514     }
10515   }
10516 #endif
10517 
10518   for(; i < count; i++){
10519     destination[0] = 0xffffffff & ((gint32) (destination[0] + source[0]));
10520 
10521     destination += dchannels;
10522     source += schannels;
10523   }
10524 }
10525 
10526 /**
10527  * ags_audio_buffer_util_copy_s24_to_s32:
10528  * @destination: destination buffer
10529  * @dchannels: destination buffer's count of channels
10530  * @source: source buffer
10531  * @schannels: source buffer's count of channels
10532  * @count: number of frames to copy
10533  *
10534  * Copy audio data using additive strategy.
10535  *
10536  * Since: 3.0.0
10537  */
10538 void
ags_audio_buffer_util_copy_s24_to_s32(gint32 * destination,guint dchannels,gint32 * source,guint schannels,guint count)10539 ags_audio_buffer_util_copy_s24_to_s32(gint32 *destination, guint dchannels,
10540 				      gint32 *source, guint schannels,
10541 				      guint count)
10542 {
10543   //NOTE:JK: scale = (2^bits_destination / 2.0 - 1.0) / (2^bits_source / 2.0 - 1.0)
10544   static const gdouble scale = 25.60000283718142952697;
10545   guint limit;
10546   guint current_dchannel, current_schannel;
10547   guint i;
10548 
10549   if(destination == NULL ||
10550      source == NULL){
10551     return;
10552   }
10553 
10554   i = 0;
10555 
10556 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
10557   /* vectorized function */
10558   if(count > 8){
10559     limit = count - (count % 8);
10560 
10561     for(; i < limit; i += 8){
10562       ags_v8double v_destination;
10563       ags_v8double v_source;
10564 
10565       current_dchannel = 0;
10566       current_schannel = 0;
10567 
10568       v_destination = (ags_v8double) {(gdouble) destination[0],
10569 				      (gdouble) destination[(current_dchannel = dchannels)],
10570 				      (gdouble) destination[(current_dchannel += dchannels)],
10571 				      (gdouble) destination[(current_dchannel += dchannels)],
10572 				      (gdouble) destination[(current_dchannel += dchannels)],
10573 				      (gdouble) destination[(current_dchannel += dchannels)],
10574 				      (gdouble) destination[(current_dchannel += dchannels)],
10575 				      (gdouble) destination[(current_dchannel += dchannels)]};
10576 
10577       v_source = (ags_v8double) {(gdouble) source[0],
10578 				 (gdouble) source[(current_schannel = schannels)],
10579 				 (gdouble) source[(current_schannel += schannels)],
10580 				 (gdouble) source[(current_schannel += schannels)],
10581 				 (gdouble) source[(current_schannel += schannels)],
10582 				 (gdouble) source[(current_schannel += schannels)],
10583 				 (gdouble) source[(current_schannel += schannels)],
10584 				 (gdouble) source[(current_schannel += schannels)]};
10585 
10586       /* scale and copy */
10587       v_source *= scale;
10588       v_destination += v_source;
10589 
10590       current_dchannel = 0;
10591 
10592       destination[0] = (gint32) v_destination[0];
10593       destination[(current_dchannel = dchannels)] = (gint32) v_destination[1];
10594       destination[(current_dchannel += dchannels)] = (gint32) v_destination[2];
10595       destination[(current_dchannel += dchannels)] = (gint32) v_destination[3];
10596       destination[(current_dchannel += dchannels)] = (gint32) v_destination[4];
10597       destination[(current_dchannel += dchannels)] = (gint32) v_destination[5];
10598       destination[(current_dchannel += dchannels)] = (gint32) v_destination[6];
10599       destination[(current_dchannel += dchannels)] = (gint32) v_destination[7];
10600 
10601       /* iterate destination */
10602       destination += (current_dchannel + dchannels);
10603 
10604       /* iterate source */
10605       source += (current_schannel + schannels);
10606     }
10607   }
10608 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
10609   /* vectorized function */
10610   if(count > 8){
10611     limit = count - (count % 8);
10612 
10613     for(; i < limit; i += 8){
10614       double v_scaled[8];
10615       double v_result[8];
10616       static const double v_scale[1] = { (double) scale };
10617 
10618       current_dchannel = 0;
10619       current_schannel = 0;
10620 
10621       double v_destination[] = {(double) destination[0],
10622 				(double) destination[(current_dchannel = dchannels)],
10623 				(double) destination[(current_dchannel += dchannels)],
10624 				(double) destination[(current_dchannel += dchannels)],
10625 				(double) destination[(current_dchannel += dchannels)],
10626 				(double) destination[(current_dchannel += dchannels)],
10627 				(double) destination[(current_dchannel += dchannels)],
10628 				(double) destination[(current_dchannel += dchannels)]};
10629 
10630       double v_source[] = {(double) source[0],
10631 			   (double) source[(current_schannel = schannels)],
10632 			   (double) source[(current_schannel += schannels)],
10633 			   (double) source[(current_schannel += schannels)],
10634 			   (double) source[(current_schannel += schannels)],
10635 			   (double) source[(current_schannel += schannels)],
10636 			   (double) source[(current_schannel += schannels)],
10637 			   (double) source[(current_schannel += schannels)]};
10638 
10639       /* no scale, just copy */
10640       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
10641       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
10642 
10643       current_dchannel = 0;
10644 
10645       destination[0] = (gint32) v_result[0];
10646       destination[(current_dchannel = dchannels)] = (gint32) v_result[1];
10647       destination[(current_dchannel += dchannels)] = (gint32) v_result[2];
10648       destination[(current_dchannel += dchannels)] = (gint32) v_result[3];
10649       destination[(current_dchannel += dchannels)] = (gint32) v_result[4];
10650       destination[(current_dchannel += dchannels)] = (gint32) v_result[5];
10651       destination[(current_dchannel += dchannels)] = (gint32) v_result[6];
10652       destination[(current_dchannel += dchannels)] = (gint32) v_result[7];
10653 
10654       /* iterate destination */
10655       destination += (current_dchannel + dchannels);
10656 
10657       /* iterate source */
10658       source += (current_schannel + schannels);
10659     }
10660   }
10661 #else
10662   /* unrolled function */
10663   if(count > 8){
10664     limit = count - (count % 8);
10665 
10666     for(; i < limit; i += 8){
10667       current_dchannel = 0;
10668       current_schannel = 0;
10669 
10670       destination[0] = 0xffffffff & ((gint64) (destination[0] + (scale * source[0])));
10671       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel = dchannels)] + (scale * source[(current_schannel = schannels)])));
10672       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
10673       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
10674       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
10675       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
10676       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
10677       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
10678 
10679       /* iterate destination */
10680       destination += (current_dchannel + dchannels);
10681 
10682       /* iterate source */
10683       source += (current_schannel + schannels);
10684     }
10685   }
10686 #endif
10687 
10688   for(; i < count; i++){
10689     destination[0] = 0xffffffff & ((gint64) (destination[0] + (scale * source[0])));
10690 
10691     destination += dchannels;
10692     source += schannels;
10693   }
10694 }
10695 
10696 /**
10697  * ags_audio_buffer_util_copy_s24_to_s64:
10698  * @destination: destination buffer
10699  * @dchannels: destination buffer's count of channels
10700  * @source: source buffer
10701  * @schannels: source buffer's count of channels
10702  * @count: number of frames to copy
10703  *
10704  * Copy audio data using additive strategy.
10705  *
10706  * Since: 3.0.0
10707  */
10708 void
ags_audio_buffer_util_copy_s24_to_s64(gint64 * destination,guint dchannels,gint32 * source,guint schannels,guint count)10709 ags_audio_buffer_util_copy_s24_to_s64(gint64 *destination, guint dchannels,
10710 				      gint32 *source, guint schannels,
10711 				      guint count)
10712 {
10713   //NOTE:JK: scale = (2^bits_destination / 2.0 - 1.0) / (2^bits_source / 2.0 - 1.0)
10714   static const gdouble scale = 1099511758848.01562488265334160963;
10715   guint limit;
10716   guint current_dchannel, current_schannel;
10717   guint i;
10718 
10719   if(destination == NULL ||
10720      source == NULL){
10721     return;
10722   }
10723 
10724   i = 0;
10725 
10726 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
10727   /* vectorized function */
10728   if(count > 8){
10729     limit = count - (count % 8);
10730 
10731     for(; i < limit; i += 8){
10732       ags_v8double v_destination;
10733       ags_v8double v_source;
10734 
10735       current_dchannel = 0;
10736       current_schannel = 0;
10737 
10738       v_destination = (ags_v8double) {(gdouble) destination[0],
10739 				      (gdouble) destination[(current_dchannel = dchannels)],
10740 				      (gdouble) destination[(current_dchannel += dchannels)],
10741 				      (gdouble) destination[(current_dchannel += dchannels)],
10742 				      (gdouble) destination[(current_dchannel += dchannels)],
10743 				      (gdouble) destination[(current_dchannel += dchannels)],
10744 				      (gdouble) destination[(current_dchannel += dchannels)],
10745 				      (gdouble) destination[(current_dchannel += dchannels)]};
10746 
10747       v_source = (ags_v8double) {(gdouble) source[0],
10748 				 (gdouble) source[(current_schannel = schannels)],
10749 				 (gdouble) source[(current_schannel += schannels)],
10750 				 (gdouble) source[(current_schannel += schannels)],
10751 				 (gdouble) source[(current_schannel += schannels)],
10752 				 (gdouble) source[(current_schannel += schannels)],
10753 				 (gdouble) source[(current_schannel += schannels)],
10754 				 (gdouble) source[(current_schannel += schannels)]};
10755 
10756       /* scale and copy */
10757       v_source *= scale;
10758       v_destination += v_source;
10759 
10760       current_dchannel = 0;
10761 
10762       destination[0] = (gint64) v_destination[0];
10763       destination[(current_dchannel = dchannels)] = (gint64) v_destination[1];
10764       destination[(current_dchannel += dchannels)] = (gint64) v_destination[2];
10765       destination[(current_dchannel += dchannels)] = (gint64) v_destination[3];
10766       destination[(current_dchannel += dchannels)] = (gint64) v_destination[4];
10767       destination[(current_dchannel += dchannels)] = (gint64) v_destination[5];
10768       destination[(current_dchannel += dchannels)] = (gint64) v_destination[6];
10769       destination[(current_dchannel += dchannels)] = (gint64) v_destination[7];
10770 
10771       /* iterate destination */
10772       destination += (current_dchannel + dchannels);
10773 
10774       /* iterate source */
10775       source += (current_schannel + schannels);
10776     }
10777   }
10778 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
10779   /* vectorized function */
10780   if(count > 8){
10781     limit = count - (count % 8);
10782 
10783     for(; i < limit; i += 8){
10784       double v_scaled[8];
10785       double v_result[8];
10786       static const double v_scale[1] = { (double) scale };
10787 
10788       current_dchannel = 0;
10789       current_schannel = 0;
10790 
10791       double v_destination[] = {(double) destination[0],
10792 				(double) destination[(current_dchannel = dchannels)],
10793 				(double) destination[(current_dchannel += dchannels)],
10794 				(double) destination[(current_dchannel += dchannels)],
10795 				(double) destination[(current_dchannel += dchannels)],
10796 				(double) destination[(current_dchannel += dchannels)],
10797 				(double) destination[(current_dchannel += dchannels)],
10798 				(double) destination[(current_dchannel += dchannels)]};
10799 
10800       double v_source[] = {(double) source[0],
10801 			   (double) source[(current_schannel = schannels)],
10802 			   (double) source[(current_schannel += schannels)],
10803 			   (double) source[(current_schannel += schannels)],
10804 			   (double) source[(current_schannel += schannels)],
10805 			   (double) source[(current_schannel += schannels)],
10806 			   (double) source[(current_schannel += schannels)],
10807 			   (double) source[(current_schannel += schannels)]};
10808 
10809       /* no scale, just copy */
10810       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
10811       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
10812 
10813       current_dchannel = 0;
10814 
10815       destination[0] = (gint64) v_result[0];
10816       destination[(current_dchannel = dchannels)] = (gint64) v_result[1];
10817       destination[(current_dchannel += dchannels)] = (gint64) v_result[2];
10818       destination[(current_dchannel += dchannels)] = (gint64) v_result[3];
10819       destination[(current_dchannel += dchannels)] = (gint64) v_result[4];
10820       destination[(current_dchannel += dchannels)] = (gint64) v_result[5];
10821       destination[(current_dchannel += dchannels)] = (gint64) v_result[6];
10822       destination[(current_dchannel += dchannels)] = (gint64) v_result[7];
10823 
10824       /* iterate destination */
10825       destination += (current_dchannel + dchannels);
10826 
10827       /* iterate source */
10828       source += (current_schannel + schannels);
10829     }
10830   }
10831 #else
10832   /* unrolled function */
10833   if(count > 8){
10834     limit = count - (count % 8);
10835 
10836     for(; i < limit; i += 8){
10837       current_dchannel = 0;
10838       current_schannel = 0;
10839 
10840       destination[0] = 0xffffffffffffffff & ((gint64) (destination[0] + (scale * source[0])));
10841       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel = dchannels)] + (scale * source[(current_schannel = schannels)])));
10842       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
10843       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
10844       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
10845       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
10846       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
10847       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
10848 
10849       /* iterate destination */
10850       destination += (current_dchannel + dchannels);
10851 
10852       /* iterate source */
10853       source += (current_schannel + schannels);
10854     }
10855   }
10856 #endif
10857 
10858   for(; i < count; i++){
10859     destination[0] = 0xffffffffffffffff & ((gint64) (destination[0] + (scale * source[0])));
10860 
10861     destination += dchannels;
10862     source += schannels;
10863   }
10864 }
10865 
10866 /**
10867  * ags_audio_buffer_util_copy_s24_to_float:
10868  * @destination: destination buffer
10869  * @dchannels: destination buffer's count of channels
10870  * @source: source buffer
10871  * @schannels: source buffer's count of channels
10872  * @count: number of frames to copy
10873  *
10874  * Copy audio data using additive strategy.
10875  *
10876  * Since: 3.0.0
10877  */
10878 void
ags_audio_buffer_util_copy_s24_to_float(gfloat * destination,guint dchannels,gint32 * source,guint schannels,guint count)10879 ags_audio_buffer_util_copy_s24_to_float(gfloat *destination, guint dchannels,
10880 					gint32 *source, guint schannels,
10881 					guint count)
10882 {
10883   //NOTE:JK: scale = 1.0 / (2^bits_source / 2.0 - 1.0)
10884   //  static const gdouble scale = 0.00000011920930376163;
10885   static const gdouble normalize_divisor = 8388607.0;
10886   guint limit;
10887   guint current_dchannel, current_schannel;
10888   guint i;
10889 
10890   if(destination == NULL ||
10891      source == NULL){
10892     return;
10893   }
10894 
10895   i = 0;
10896 
10897 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
10898   /* vectorized function */
10899   if(count > 8){
10900     limit = count - (count % 8);
10901 
10902     for(; i < limit; i += 8){
10903       ags_v8float v_destination;
10904       ags_v8float v_source;
10905 
10906       current_dchannel = 0;
10907       current_schannel = 0;
10908 
10909       v_destination = (ags_v8float) {(gfloat) destination[0],
10910 				     (gfloat) destination[(current_dchannel = dchannels)],
10911 				     (gfloat) destination[(current_dchannel += dchannels)],
10912 				     (gfloat) destination[(current_dchannel += dchannels)],
10913 				     (gfloat) destination[(current_dchannel += dchannels)],
10914 				     (gfloat) destination[(current_dchannel += dchannels)],
10915 				     (gfloat) destination[(current_dchannel += dchannels)],
10916 				     (gfloat) destination[(current_dchannel += dchannels)]};
10917 
10918       v_source = (ags_v8float) {(gfloat) source[0],
10919 				(gfloat) source[(current_schannel = schannels)],
10920 				(gfloat) source[(current_schannel += schannels)],
10921 				(gfloat) source[(current_schannel += schannels)],
10922 				(gfloat) source[(current_schannel += schannels)],
10923 				(gfloat) source[(current_schannel += schannels)],
10924 				(gfloat) source[(current_schannel += schannels)],
10925 				(gfloat) source[(current_schannel += schannels)]};
10926 
10927       /* normalize and copy */
10928       v_source /= (gfloat) normalize_divisor;
10929       v_destination += v_source;
10930 
10931       current_dchannel = 0;
10932 
10933       destination[0] = (gfloat) v_destination[0];
10934       destination[(current_dchannel = dchannels)] = (gfloat) v_destination[1];
10935       destination[(current_dchannel += dchannels)] = (gfloat) v_destination[2];
10936       destination[(current_dchannel += dchannels)] = (gfloat) v_destination[3];
10937       destination[(current_dchannel += dchannels)] = (gfloat) v_destination[4];
10938       destination[(current_dchannel += dchannels)] = (gfloat) v_destination[5];
10939       destination[(current_dchannel += dchannels)] = (gfloat) v_destination[6];
10940       destination[(current_dchannel += dchannels)] = (gfloat) v_destination[7];
10941 
10942       /* iterate destination */
10943       destination += (current_dchannel + dchannels);
10944 
10945       /* iterate source */
10946       source += (current_schannel + schannels);
10947     }
10948   }
10949 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
10950   /* vectorized function */
10951   if(count > 8){
10952     limit = count - (count % 8);
10953 
10954     for(; i < limit; i += 8){
10955       double v_normalized[8];
10956       double v_result[8];
10957       static const double v_normalize_divisor[1] = { (double) normalize_divisor };
10958 
10959       current_dchannel = 0;
10960       current_schannel = 0;
10961 
10962       double v_destination[] = {(double) destination[0],
10963 				(double) destination[(current_dchannel = dchannels)],
10964 				(double) destination[(current_dchannel += dchannels)],
10965 				(double) destination[(current_dchannel += dchannels)],
10966 				(double) destination[(current_dchannel += dchannels)],
10967 				(double) destination[(current_dchannel += dchannels)],
10968 				(double) destination[(current_dchannel += dchannels)],
10969 				(double) destination[(current_dchannel += dchannels)]};
10970 
10971       double v_source[] = {(double) source[0],
10972 			   (double) source[(current_schannel = schannels)],
10973 			   (double) source[(current_schannel += schannels)],
10974 			   (double) source[(current_schannel += schannels)],
10975 			   (double) source[(current_schannel += schannels)],
10976 			   (double) source[(current_schannel += schannels)],
10977 			   (double) source[(current_schannel += schannels)],
10978 			   (double) source[(current_schannel += schannels)]};
10979 
10980       /* no scale, just copy */
10981       vDSP_vdivD(v_normalize_divisor, 0, v_source, 1, v_normalized, 1, 8);
10982       vDSP_vaddD(v_destination, 1, v_normalized, 1, v_result, 1, 8);
10983 
10984       current_dchannel = 0;
10985 
10986       destination[0] = (gfloat) v_result[0];
10987       destination[(current_dchannel = dchannels)] = (gfloat) v_result[1];
10988       destination[(current_dchannel += dchannels)] = (gfloat) v_result[2];
10989       destination[(current_dchannel += dchannels)] = (gfloat) v_result[3];
10990       destination[(current_dchannel += dchannels)] = (gfloat) v_result[4];
10991       destination[(current_dchannel += dchannels)] = (gfloat) v_result[5];
10992       destination[(current_dchannel += dchannels)] = (gfloat) v_result[6];
10993       destination[(current_dchannel += dchannels)] = (gfloat) v_result[7];
10994 
10995       /* iterate destination */
10996       destination += (current_dchannel + dchannels);
10997 
10998       /* iterate source */
10999       source += (current_schannel + schannels);
11000     }
11001   }
11002 #else
11003   /* unrolled function */
11004   if(count > 8){
11005     limit = count - (count % 8);
11006 
11007     for(; i < limit; i += 8){
11008       current_dchannel = 0;
11009       current_schannel = 0;
11010 
11011       destination[0] = (gfloat) ((gdouble) (destination[0] + (gdouble) (source[0] / normalize_divisor)));
11012       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (source[(current_schannel = schannels)] / normalize_divisor)));
11013       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
11014       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
11015       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
11016       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
11017       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
11018       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
11019 
11020       /* iterate destination */
11021       destination += (current_dchannel + dchannels);
11022 
11023       /* iterate source */
11024       source += (current_schannel + schannels);
11025     }
11026   }
11027 #endif
11028 
11029   for(; i < count; i++){
11030     destination[0] = (gfloat) ((gdouble) (destination[0] + (gdouble) (source[0] / normalize_divisor)));
11031 
11032     destination += dchannels;
11033     source += schannels;
11034   }
11035 }
11036 
11037 /**
11038  * ags_audio_buffer_util_copy_s24_to_double:
11039  * @destination: destination buffer
11040  * @dchannels: destination buffer's count of channels
11041  * @source: source buffer
11042  * @schannels: source buffer's count of channels
11043  * @count: number of frames to copy
11044  *
11045  * Copy audio data using additive strategy.
11046  *
11047  * Since: 3.0.0
11048  */
11049 void
ags_audio_buffer_util_copy_s24_to_double(gdouble * destination,guint dchannels,gint32 * source,guint schannels,guint count)11050 ags_audio_buffer_util_copy_s24_to_double(gdouble *destination, guint dchannels,
11051 					 gint32 *source, guint schannels,
11052 					 guint count)
11053 {
11054   //NOTE:JK: scale = 1.0 / (2^bits_source / 2.0 - 1.0)
11055   //  static const gdouble scale = 0.00000011920930376163;
11056   static const gdouble normalize_divisor = 8388607.0;
11057   guint limit;
11058   guint current_dchannel, current_schannel;
11059   guint i;
11060 
11061   if(destination == NULL ||
11062      source == NULL){
11063     return;
11064   }
11065 
11066   i = 0;
11067 
11068 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
11069   /* vectorized function */
11070   if(count > 8){
11071     limit = count - (count % 8);
11072 
11073     for(; i < limit; i += 8){
11074       ags_v8double v_destination;
11075       ags_v8double v_source;
11076 
11077       current_dchannel = 0;
11078       current_schannel = 0;
11079 
11080       v_destination = (ags_v8double) {(gdouble) destination[0],
11081 				      (gdouble) destination[(current_dchannel = dchannels)],
11082 				      (gdouble) destination[(current_dchannel += dchannels)],
11083 				      (gdouble) destination[(current_dchannel += dchannels)],
11084 				      (gdouble) destination[(current_dchannel += dchannels)],
11085 				      (gdouble) destination[(current_dchannel += dchannels)],
11086 				      (gdouble) destination[(current_dchannel += dchannels)],
11087 				      (gdouble) destination[(current_dchannel += dchannels)]};
11088 
11089       v_source = (ags_v8double) {(gdouble) source[0],
11090 				 (gdouble) source[(current_schannel = schannels)],
11091 				 (gdouble) source[(current_schannel += schannels)],
11092 				 (gdouble) source[(current_schannel += schannels)],
11093 				 (gdouble) source[(current_schannel += schannels)],
11094 				 (gdouble) source[(current_schannel += schannels)],
11095 				 (gdouble) source[(current_schannel += schannels)],
11096 				 (gdouble) source[(current_schannel += schannels)]};
11097 
11098       /* normalize and copy */
11099       v_source /= normalize_divisor;
11100       v_destination += v_source;
11101 
11102       current_dchannel = 0;
11103 
11104       destination[0] = v_destination[0];
11105       destination[(current_dchannel = dchannels)] = v_destination[1];
11106       destination[(current_dchannel += dchannels)] = v_destination[2];
11107       destination[(current_dchannel += dchannels)] = v_destination[3];
11108       destination[(current_dchannel += dchannels)] = v_destination[4];
11109       destination[(current_dchannel += dchannels)] = v_destination[5];
11110       destination[(current_dchannel += dchannels)] = v_destination[6];
11111       destination[(current_dchannel += dchannels)] = v_destination[7];
11112 
11113       /* iterate destination */
11114       destination += (current_dchannel + dchannels);
11115 
11116       /* iterate source */
11117       source += (current_schannel + schannels);
11118     }
11119   }
11120 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
11121   /* vectorized function */
11122   if(count > 8){
11123     limit = count - (count % 8);
11124 
11125     for(; i < limit; i += 8){
11126       double v_normalized[8];
11127       double v_result[8];
11128       static const double v_normalize_divisor[1] = { (double) normalize_divisor };
11129 
11130       current_dchannel = 0;
11131       current_schannel = 0;
11132 
11133       double v_destination[] = {(double) destination[0],
11134 				(double) destination[(current_dchannel = dchannels)],
11135 				(double) destination[(current_dchannel += dchannels)],
11136 				(double) destination[(current_dchannel += dchannels)],
11137 				(double) destination[(current_dchannel += dchannels)],
11138 				(double) destination[(current_dchannel += dchannels)],
11139 				(double) destination[(current_dchannel += dchannels)],
11140 				(double) destination[(current_dchannel += dchannels)]};
11141 
11142       double v_source[] = {(double) source[0],
11143 			   (double) source[(current_schannel = schannels)],
11144 			   (double) source[(current_schannel += schannels)],
11145 			   (double) source[(current_schannel += schannels)],
11146 			   (double) source[(current_schannel += schannels)],
11147 			   (double) source[(current_schannel += schannels)],
11148 			   (double) source[(current_schannel += schannels)],
11149 			   (double) source[(current_schannel += schannels)]};
11150 
11151       /* no scale, just copy */
11152       vDSP_vdivD(v_normalize_divisor, 0, v_source, 1, v_normalized, 1, 8);
11153       vDSP_vaddD(v_destination, 1, v_normalized, 1, v_result, 1, 8);
11154 
11155       current_dchannel = 0;
11156 
11157       destination[0] = (gdouble) v_result[0];
11158       destination[(current_dchannel = dchannels)] = (gdouble) v_result[1];
11159       destination[(current_dchannel += dchannels)] = (gdouble) v_result[2];
11160       destination[(current_dchannel += dchannels)] = (gdouble) v_result[3];
11161       destination[(current_dchannel += dchannels)] = (gdouble) v_result[4];
11162       destination[(current_dchannel += dchannels)] = (gdouble) v_result[5];
11163       destination[(current_dchannel += dchannels)] = (gdouble) v_result[6];
11164       destination[(current_dchannel += dchannels)] = (gdouble) v_result[7];
11165 
11166       /* iterate destination */
11167       destination += (current_dchannel + dchannels);
11168 
11169       /* iterate source */
11170       source += (current_schannel + schannels);
11171     }
11172   }
11173 #else
11174   /* unrolled function */
11175   if(count > 8){
11176     limit = count - (count % 8);
11177 
11178     for(; i < limit; i += 8){
11179       current_dchannel = 0;
11180       current_schannel = 0;
11181 
11182       destination[0] = ((gdouble) (destination[0] + (gdouble) (source[0] / normalize_divisor)));
11183       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (source[(current_schannel = schannels)] / normalize_divisor)));
11184       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
11185       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
11186       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
11187       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
11188       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
11189       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
11190 
11191       /* iterate destination */
11192       destination += (current_dchannel + dchannels);
11193 
11194       /* iterate source */
11195       source += (current_schannel + schannels);
11196     }
11197   }
11198 #endif
11199 
11200   for(; i < count; i++){
11201     destination[0] = ((gdouble) (destination[0] + (gdouble) (source[0] / normalize_divisor)));
11202 
11203     destination += dchannels;
11204     source += schannels;
11205   }
11206 }
11207 
11208 /**
11209  * ags_audio_buffer_util_copy_s32_to_s8:
11210  * @destination: destination buffer
11211  * @dchannels: destination buffer's count of channels
11212  * @source: source buffer
11213  * @schannels: source buffer's count of channels
11214  * @count: number of frames to copy
11215  *
11216  * Copy audio data using additive strategy.
11217  *
11218  * Since: 3.0.0
11219  */
11220 void
ags_audio_buffer_util_copy_s32_to_s8(gint8 * destination,guint dchannels,gint32 * source,guint schannels,guint count)11221 ags_audio_buffer_util_copy_s32_to_s8(gint8 *destination, guint dchannels,
11222 				     gint32 *source, guint schannels,
11223 				     guint count)
11224 {
11225   //NOTE:JK: scale = (2^bits_destination / 2.0 - 1.0) / (2^bits_source / 2.0 - 1.0)
11226   static const gdouble scale = 0.00000059138983983780;
11227   guint limit;
11228   guint current_dchannel, current_schannel;
11229   guint i;
11230 
11231   if(destination == NULL ||
11232      source == NULL){
11233     return;
11234   }
11235 
11236   i = 0;
11237 
11238 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
11239   /* vectorized function */
11240   if(count > 8){
11241     limit = count - (count % 8);
11242 
11243     for(; i < limit; i += 8){
11244       ags_v8double v_destination;
11245       ags_v8double v_source;
11246 
11247       current_dchannel = 0;
11248       current_schannel = 0;
11249 
11250       v_destination = (ags_v8double) {(gdouble) destination[0],
11251 				      (gdouble) destination[(current_dchannel = dchannels)],
11252 				      (gdouble) destination[(current_dchannel += dchannels)],
11253 				      (gdouble) destination[(current_dchannel += dchannels)],
11254 				      (gdouble) destination[(current_dchannel += dchannels)],
11255 				      (gdouble) destination[(current_dchannel += dchannels)],
11256 				      (gdouble) destination[(current_dchannel += dchannels)],
11257 				      (gdouble) destination[(current_dchannel += dchannels)]};
11258 
11259       v_source = (ags_v8double) {(gdouble) source[0],
11260 				 (gdouble) source[(current_schannel = schannels)],
11261 				 (gdouble) source[(current_schannel += schannels)],
11262 				 (gdouble) source[(current_schannel += schannels)],
11263 				 (gdouble) source[(current_schannel += schannels)],
11264 				 (gdouble) source[(current_schannel += schannels)],
11265 				 (gdouble) source[(current_schannel += schannels)],
11266 				 (gdouble) source[(current_schannel += schannels)]};
11267 
11268       /* scale and copy */
11269       v_source *= scale;
11270       v_destination += v_source;
11271 
11272       current_dchannel = 0;
11273 
11274       destination[0] = (gint8) v_destination[0];
11275       destination[(current_dchannel = dchannels)] = (gint8) v_destination[1];
11276       destination[(current_dchannel += dchannels)] = (gint8) v_destination[2];
11277       destination[(current_dchannel += dchannels)] = (gint8) v_destination[3];
11278       destination[(current_dchannel += dchannels)] = (gint8) v_destination[4];
11279       destination[(current_dchannel += dchannels)] = (gint8) v_destination[5];
11280       destination[(current_dchannel += dchannels)] = (gint8) v_destination[6];
11281       destination[(current_dchannel += dchannels)] = (gint8) v_destination[7];
11282 
11283       /* iterate destination */
11284       destination += (current_dchannel + dchannels);
11285 
11286       /* iterate source */
11287       source += (current_schannel + schannels);
11288     }
11289   }
11290 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
11291   /* vectorized function */
11292   if(count > 8){
11293     limit = count - (count % 8);
11294 
11295     for(; i < limit; i += 8){
11296       double v_scaled[8];
11297       double v_result[8];
11298       static const double v_scale[1] = { (double) scale };
11299 
11300       current_dchannel = 0;
11301       current_schannel = 0;
11302 
11303       double v_destination[] = {(double) destination[0],
11304 				(double) destination[(current_dchannel = dchannels)],
11305 				(double) destination[(current_dchannel += dchannels)],
11306 				(double) destination[(current_dchannel += dchannels)],
11307 				(double) destination[(current_dchannel += dchannels)],
11308 				(double) destination[(current_dchannel += dchannels)],
11309 				(double) destination[(current_dchannel += dchannels)],
11310 				(double) destination[(current_dchannel += dchannels)]};
11311 
11312       double v_source[] = {(double) source[0],
11313 			   (double) source[(current_schannel = schannels)],
11314 			   (double) source[(current_schannel += schannels)],
11315 			   (double) source[(current_schannel += schannels)],
11316 			   (double) source[(current_schannel += schannels)],
11317 			   (double) source[(current_schannel += schannels)],
11318 			   (double) source[(current_schannel += schannels)],
11319 			   (double) source[(current_schannel += schannels)]};
11320 
11321       /* scale and copy */
11322       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
11323       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
11324 
11325       current_dchannel = 0;
11326 
11327       destination[0] = (gint8) v_result[0];
11328       destination[(current_dchannel = dchannels)] = (gint8) v_result[1];
11329       destination[(current_dchannel += dchannels)] = (gint8) v_result[2];
11330       destination[(current_dchannel += dchannels)] = (gint8) v_result[3];
11331       destination[(current_dchannel += dchannels)] = (gint8) v_result[4];
11332       destination[(current_dchannel += dchannels)] = (gint8) v_result[5];
11333       destination[(current_dchannel += dchannels)] = (gint8) v_result[6];
11334       destination[(current_dchannel += dchannels)] = (gint8) v_result[7];
11335 
11336       /* iterate destination */
11337       destination += (current_dchannel + dchannels);
11338 
11339       /* iterate source */
11340       source += (current_schannel + schannels);
11341     }
11342   }
11343 #else
11344   /* unrolled function */
11345   if(count > 8){
11346     limit = count - (count % 8);
11347 
11348     for(; i < limit; i += 8){
11349       current_dchannel = 0;
11350       current_schannel = 0;
11351 
11352       destination[0] = 0xff & ((gint16) (destination[0] + (scale * source[0])));
11353       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel = dchannels)] + (scale * source[(current_schannel = schannels)])));
11354       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
11355       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
11356       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
11357       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
11358       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
11359       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
11360 
11361       /* iterate destination */
11362       destination += (current_dchannel + dchannels);
11363 
11364       /* iterate source */
11365       source += (current_schannel + schannels);
11366     }
11367   }
11368 #endif
11369 
11370   for(; i < count; i++){
11371     destination[0] = 0xff & ((gint16) (destination[0] + (scale * source[0])));
11372 
11373     destination += dchannels;
11374     source += schannels;
11375   }
11376 }
11377 
11378 /**
11379  * ags_audio_buffer_util_copy_s32_to_s16:
11380  * @destination: destination buffer
11381  * @dchannels: destination buffer's count of channels
11382  * @source: source buffer
11383  * @schannels: source buffer's count of channels
11384  * @count: number of frames to copy
11385  *
11386  * Copy audio data using additive strategy.
11387  *
11388  * Since: 3.0.0
11389  */
11390 void
ags_audio_buffer_util_copy_s32_to_s16(gint16 * destination,guint dchannels,gint32 * source,guint schannels,guint count)11391 ags_audio_buffer_util_copy_s32_to_s16(gint16 *destination, guint dchannels,
11392 				      gint32 *source, guint schannels,
11393 				      guint count)
11394 {
11395   //NOTE:JK: scale = (2^bits_destination / 2.0 - 1.0) / (2^bits_source / 2.0 - 1.0)
11396   static const gdouble scale = 0.00015258323529106482;
11397   guint limit;
11398   guint current_dchannel, current_schannel;
11399   guint i;
11400 
11401   if(destination == NULL ||
11402      source == NULL){
11403     return;
11404   }
11405 
11406   i = 0;
11407 
11408 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
11409   /* vectorized function */
11410   if(count > 8){
11411     limit = count - (count % 8);
11412 
11413     for(; i < limit; i += 8){
11414       ags_v8double v_destination;
11415       ags_v8double v_source;
11416 
11417       current_dchannel = 0;
11418       current_schannel = 0;
11419 
11420       v_destination = (ags_v8double) {(gdouble) destination[0],
11421 				      (gdouble) destination[(current_dchannel = dchannels)],
11422 				      (gdouble) destination[(current_dchannel += dchannels)],
11423 				      (gdouble) destination[(current_dchannel += dchannels)],
11424 				      (gdouble) destination[(current_dchannel += dchannels)],
11425 				      (gdouble) destination[(current_dchannel += dchannels)],
11426 				      (gdouble) destination[(current_dchannel += dchannels)],
11427 				      (gdouble) destination[(current_dchannel += dchannels)]};
11428 
11429       v_source = (ags_v8double) {(gdouble) source[0],
11430 				 (gdouble) source[(current_schannel = schannels)],
11431 				 (gdouble) source[(current_schannel += schannels)],
11432 				 (gdouble) source[(current_schannel += schannels)],
11433 				 (gdouble) source[(current_schannel += schannels)],
11434 				 (gdouble) source[(current_schannel += schannels)],
11435 				 (gdouble) source[(current_schannel += schannels)],
11436 				 (gdouble) source[(current_schannel += schannels)]};
11437 
11438       /* scale and copy */
11439       v_source *= scale;
11440       v_destination += v_source;
11441 
11442       current_dchannel = 0;
11443 
11444       destination[0] = (gint16) v_destination[0];
11445       destination[(current_dchannel = dchannels)] = (gint16) v_destination[1];
11446       destination[(current_dchannel += dchannels)] = (gint16) v_destination[2];
11447       destination[(current_dchannel += dchannels)] = (gint16) v_destination[3];
11448       destination[(current_dchannel += dchannels)] = (gint16) v_destination[4];
11449       destination[(current_dchannel += dchannels)] = (gint16) v_destination[5];
11450       destination[(current_dchannel += dchannels)] = (gint16) v_destination[6];
11451       destination[(current_dchannel += dchannels)] = (gint16) v_destination[7];
11452 
11453       /* iterate destination */
11454       destination += (current_dchannel + dchannels);
11455 
11456       /* iterate source */
11457       source += (current_schannel + schannels);
11458     }
11459   }
11460 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
11461   /* vectorized function */
11462   if(count > 8){
11463     limit = count - (count % 8);
11464 
11465     for(; i < limit; i += 8){
11466       double v_scaled[8];
11467       double v_result[8];
11468       static const double v_scale[1] = { (double) scale };
11469 
11470       current_dchannel = 0;
11471       current_schannel = 0;
11472 
11473       double v_destination[] = {(double) destination[0],
11474 				(double) destination[(current_dchannel = dchannels)],
11475 				(double) destination[(current_dchannel += dchannels)],
11476 				(double) destination[(current_dchannel += dchannels)],
11477 				(double) destination[(current_dchannel += dchannels)],
11478 				(double) destination[(current_dchannel += dchannels)],
11479 				(double) destination[(current_dchannel += dchannels)],
11480 				(double) destination[(current_dchannel += dchannels)]};
11481 
11482       double v_source[] = {(double) source[0],
11483 			   (double) source[(current_schannel = schannels)],
11484 			   (double) source[(current_schannel += schannels)],
11485 			   (double) source[(current_schannel += schannels)],
11486 			   (double) source[(current_schannel += schannels)],
11487 			   (double) source[(current_schannel += schannels)],
11488 			   (double) source[(current_schannel += schannels)],
11489 			   (double) source[(current_schannel += schannels)]};
11490 
11491       /* scale and copy */
11492       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
11493       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
11494 
11495       current_dchannel = 0;
11496 
11497       destination[0] = (gint16) v_result[0];
11498       destination[(current_dchannel = dchannels)] = (gint16) v_result[1];
11499       destination[(current_dchannel += dchannels)] = (gint16) v_result[2];
11500       destination[(current_dchannel += dchannels)] = (gint16) v_result[3];
11501       destination[(current_dchannel += dchannels)] = (gint16) v_result[4];
11502       destination[(current_dchannel += dchannels)] = (gint16) v_result[5];
11503       destination[(current_dchannel += dchannels)] = (gint16) v_result[6];
11504       destination[(current_dchannel += dchannels)] = (gint16) v_result[7];
11505 
11506       /* iterate destination */
11507       destination += (current_dchannel + dchannels);
11508 
11509       /* iterate source */
11510       source += (current_schannel + schannels);
11511     }
11512   }
11513 #else
11514   /* unrolled function */
11515   if(count > 8){
11516     limit = count - (count % 8);
11517 
11518     for(; i < limit; i += 8){
11519       current_dchannel = 0;
11520       current_schannel = 0;
11521 
11522       destination[0] = 0xffff & ((gint32) (destination[0] + (scale * source[0])));
11523       destination[current_dchannel] = 0xffff & ((gint32) (destination[(current_dchannel = dchannels)] + (scale * source[(current_schannel = schannels)])));
11524       destination[current_dchannel] = 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
11525       destination[current_dchannel] = 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
11526       destination[current_dchannel] = 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
11527       destination[current_dchannel] = 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
11528       destination[current_dchannel] = 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
11529       destination[current_dchannel] = 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
11530 
11531       /* iterate destination */
11532       destination += (current_dchannel + dchannels);
11533 
11534       /* iterate source */
11535       source += (current_schannel + schannels);
11536     }
11537   }
11538 #endif
11539 
11540   for(; i < count; i++){
11541     destination[0] = (gint16) ((gint32) (destination[0] + (scale * source[0])));
11542 
11543     destination += dchannels;
11544     source += schannels;
11545   }
11546 }
11547 
11548 /**
11549  * ags_audio_buffer_util_copy_s32_to_s24:
11550  * @destination: destination buffer
11551  * @dchannels: destination buffer's count of channels
11552  * @source: source buffer
11553  * @schannels: source buffer's count of channels
11554  * @count: number of frames to copy
11555  *
11556  * Copy audio data using additive strategy.
11557  *
11558  * Since: 3.0.0
11559  */
11560 void
ags_audio_buffer_util_copy_s32_to_s24(gint32 * destination,guint dchannels,gint32 * source,guint schannels,guint count)11561 ags_audio_buffer_util_copy_s32_to_s24(gint32 *destination, guint dchannels,
11562 				      gint32 *source, guint schannels,
11563 				      guint count)
11564 {
11565   //NOTE:JK: scale = (2^bits_destination / 2.0 - 1.0) / (2^bits_source / 2.0 - 1.0)
11566   static const gdouble scale = 0.03906249548890626240;
11567   guint limit;
11568   guint current_dchannel, current_schannel;
11569   guint i;
11570 
11571   if(destination == NULL ||
11572      source == NULL){
11573     return;
11574   }
11575 
11576   i = 0;
11577 
11578 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
11579   /* vectorized function */
11580   if(count > 8){
11581     limit = count - (count % 8);
11582 
11583     for(; i < limit; i += 8){
11584       ags_v8double v_destination;
11585       ags_v8double v_source;
11586 
11587       current_dchannel = 0;
11588       current_schannel = 0;
11589 
11590       v_destination = (ags_v8double) {(gdouble) destination[0],
11591 				      (gdouble) destination[(current_dchannel = dchannels)],
11592 				      (gdouble) destination[(current_dchannel += dchannels)],
11593 				      (gdouble) destination[(current_dchannel += dchannels)],
11594 				      (gdouble) destination[(current_dchannel += dchannels)],
11595 				      (gdouble) destination[(current_dchannel += dchannels)],
11596 				      (gdouble) destination[(current_dchannel += dchannels)],
11597 				      (gdouble) destination[(current_dchannel += dchannels)]};
11598 
11599       v_source = (ags_v8double) {(gdouble) source[0],
11600 				 (gdouble) source[(current_schannel = schannels)],
11601 				 (gdouble) source[(current_schannel += schannels)],
11602 				 (gdouble) source[(current_schannel += schannels)],
11603 				 (gdouble) source[(current_schannel += schannels)],
11604 				 (gdouble) source[(current_schannel += schannels)],
11605 				 (gdouble) source[(current_schannel += schannels)],
11606 				 (gdouble) source[(current_schannel += schannels)]};
11607 
11608       /* scale and copy */
11609       v_source *= scale;
11610       v_destination += v_source;
11611 
11612       current_dchannel = 0;
11613 
11614       destination[0] = (gint32) v_destination[0];
11615       destination[(current_dchannel = dchannels)] = (gint32) v_destination[1];
11616       destination[(current_dchannel += dchannels)] = (gint32) v_destination[2];
11617       destination[(current_dchannel += dchannels)] = (gint32) v_destination[3];
11618       destination[(current_dchannel += dchannels)] = (gint32) v_destination[4];
11619       destination[(current_dchannel += dchannels)] = (gint32) v_destination[5];
11620       destination[(current_dchannel += dchannels)] = (gint32) v_destination[6];
11621       destination[(current_dchannel += dchannels)] = (gint32) v_destination[7];
11622 
11623       /* iterate destination */
11624       destination += (current_dchannel + dchannels);
11625 
11626       /* iterate source */
11627       source += (current_schannel + schannels);
11628     }
11629   }
11630 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
11631   /* vectorized function */
11632   if(count > 8){
11633     limit = count - (count % 8);
11634 
11635     for(; i < limit; i += 8){
11636       double v_scaled[8];
11637       double v_result[8];
11638       static const double v_scale[1] = { (double) scale };
11639 
11640       current_dchannel = 0;
11641       current_schannel = 0;
11642 
11643       double v_destination[] = {(double) destination[0],
11644 				(double) destination[(current_dchannel = dchannels)],
11645 				(double) destination[(current_dchannel += dchannels)],
11646 				(double) destination[(current_dchannel += dchannels)],
11647 				(double) destination[(current_dchannel += dchannels)],
11648 				(double) destination[(current_dchannel += dchannels)],
11649 				(double) destination[(current_dchannel += dchannels)],
11650 				(double) destination[(current_dchannel += dchannels)]};
11651 
11652       double v_source[] = {(double) source[0],
11653 			   (double) source[(current_schannel = schannels)],
11654 			   (double) source[(current_schannel += schannels)],
11655 			   (double) source[(current_schannel += schannels)],
11656 			   (double) source[(current_schannel += schannels)],
11657 			   (double) source[(current_schannel += schannels)],
11658 			   (double) source[(current_schannel += schannels)],
11659 			   (double) source[(current_schannel += schannels)]};
11660 
11661       /* no scale, just copy */
11662       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
11663       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
11664 
11665       current_dchannel = 0;
11666 
11667       destination[0] = (gint32) v_result[0];
11668       destination[(current_dchannel = dchannels)] = (gint32) v_result[1];
11669       destination[(current_dchannel += dchannels)] = (gint32) v_result[2];
11670       destination[(current_dchannel += dchannels)] = (gint32) v_result[3];
11671       destination[(current_dchannel += dchannels)] = (gint32) v_result[4];
11672       destination[(current_dchannel += dchannels)] = (gint32) v_result[5];
11673       destination[(current_dchannel += dchannels)] = (gint32) v_result[6];
11674       destination[(current_dchannel += dchannels)] = (gint32) v_result[7];
11675 
11676       /* iterate destination */
11677       destination += (current_dchannel + dchannels);
11678 
11679       /* iterate source */
11680       source += (current_schannel + schannels);
11681     }
11682   }
11683 #else
11684   /* unrolled function */
11685   if(count > 8){
11686     limit = count - (count % 8);
11687 
11688     for(; i < limit; i += 8){
11689       current_dchannel = 0;
11690       current_schannel = 0;
11691 
11692       destination[0] = 0xffffffff & ((gint32) (destination[0] + (scale * source[0])));
11693       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel = dchannels)] + (scale * source[(current_schannel = schannels)])));
11694       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
11695       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
11696       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
11697       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
11698       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
11699       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
11700 
11701       /* iterate destination */
11702       destination += (current_dchannel + dchannels);
11703 
11704       /* iterate source */
11705       source += (current_schannel + schannels);
11706     }
11707   }
11708 #endif
11709 
11710   for(; i < count; i++){
11711     destination[0] = 0xffffffff & ((gint32) (destination[0] + (scale * source[0])));
11712 
11713     destination += dchannels;
11714     source += schannels;
11715   }
11716 }
11717 
11718 /**
11719  * ags_audio_buffer_util_copy_s32_to_s32:
11720  * @destination: destination buffer
11721  * @dchannels: destination buffer's count of channels
11722  * @source: source buffer
11723  * @schannels: source buffer's count of channels
11724  * @count: number of frames to copy
11725  *
11726  * Copy audio data using additive strategy.
11727  *
11728  * Since: 3.0.0
11729  */
11730 void
ags_audio_buffer_util_copy_s32_to_s32(gint32 * destination,guint dchannels,gint32 * source,guint schannels,guint count)11731 ags_audio_buffer_util_copy_s32_to_s32(gint32 *destination, guint dchannels,
11732 				      gint32 *source, guint schannels,
11733 				      guint count)
11734 {
11735   guint limit;
11736   guint current_dchannel, current_schannel;
11737   guint i;
11738 
11739   if(destination == NULL ||
11740      source == NULL){
11741     return;
11742   }
11743 
11744   i = 0;
11745 
11746 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
11747   /* vectorized function */
11748   if(count > 8){
11749     limit = count - (count % 8);
11750 
11751     for(; i < limit; i += 8){
11752       ags_v8s32 v_destination;
11753       ags_v8s32 v_source;
11754 
11755       current_dchannel = 0;
11756       current_schannel = 0;
11757 
11758       v_destination = (ags_v8s32) {destination[0],
11759 				   destination[(current_dchannel = dchannels)],
11760 				   destination[(current_dchannel += dchannels)],
11761 				   destination[(current_dchannel += dchannels)],
11762 				   destination[(current_dchannel += dchannels)],
11763 				   destination[(current_dchannel += dchannels)],
11764 				   destination[(current_dchannel += dchannels)],
11765 				   destination[(current_dchannel += dchannels)]};
11766 
11767       v_source = (ags_v8s32) {source[0],
11768 			      source[(current_schannel = schannels)],
11769 			      source[(current_schannel += schannels)],
11770 			      source[(current_schannel += schannels)],
11771 			      source[(current_schannel += schannels)],
11772 			      source[(current_schannel += schannels)],
11773 			      source[(current_schannel += schannels)],
11774 			      source[(current_schannel += schannels)]};
11775 
11776       /* no scale, just copy */
11777       v_destination += v_source;
11778 
11779       current_dchannel = 0;
11780 
11781       destination[0] = v_destination[0];
11782       destination[(current_dchannel = dchannels)] = v_destination[1];
11783       destination[(current_dchannel += dchannels)] = v_destination[2];
11784       destination[(current_dchannel += dchannels)] = v_destination[3];
11785       destination[(current_dchannel += dchannels)] = v_destination[4];
11786       destination[(current_dchannel += dchannels)] = v_destination[5];
11787       destination[(current_dchannel += dchannels)] = v_destination[6];
11788       destination[(current_dchannel += dchannels)] = v_destination[7];
11789 
11790       /* iterate destination */
11791       destination += (current_dchannel + dchannels);
11792 
11793       /* iterate source */
11794       source += (current_schannel + schannels);
11795     }
11796   }
11797 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
11798   /* vectorized function */
11799   if(count > 8){
11800     limit = count - (count % 8);
11801 
11802     for(; i < limit; i += 8){
11803       int v_result[8];
11804 
11805       current_dchannel = 0;
11806       current_schannel = 0;
11807 
11808       int v_destination[] = {(int) destination[0],
11809 			     (int) destination[(current_dchannel = dchannels)],
11810 			     (int) destination[(current_dchannel += dchannels)],
11811 			     (int) destination[(current_dchannel += dchannels)],
11812 			     (int) destination[(current_dchannel += dchannels)],
11813 			     (int) destination[(current_dchannel += dchannels)],
11814 			     (int) destination[(current_dchannel += dchannels)],
11815 			     (int) destination[(current_dchannel += dchannels)]};
11816 
11817       int v_source[] = {(int) source[0],
11818 			(int) source[(current_schannel = schannels)],
11819 			(int) source[(current_schannel += schannels)],
11820 			(int) source[(current_schannel += schannels)],
11821 			(int) source[(current_schannel += schannels)],
11822 			(int) source[(current_schannel += schannels)],
11823 			(int) source[(current_schannel += schannels)],
11824 			(int) source[(current_schannel += schannels)]};
11825 
11826       /* no scale, just copy */
11827       vDSP_vaddi(v_destination, 1, v_source, 1, v_result, 1, 8);
11828 
11829       current_dchannel = 0;
11830 
11831       destination[0] = (gint32) v_result[0];
11832       destination[(current_dchannel = dchannels)] = (gint32) v_result[1];
11833       destination[(current_dchannel += dchannels)] = (gint32) v_result[2];
11834       destination[(current_dchannel += dchannels)] = (gint32) v_result[3];
11835       destination[(current_dchannel += dchannels)] = (gint32) v_result[4];
11836       destination[(current_dchannel += dchannels)] = (gint32) v_result[5];
11837       destination[(current_dchannel += dchannels)] = (gint32) v_result[6];
11838       destination[(current_dchannel += dchannels)] = (gint32) v_result[7];
11839 
11840       /* iterate destination */
11841       destination += (current_dchannel + dchannels);
11842 
11843       /* iterate source */
11844       source += (current_schannel + schannels);
11845     }
11846   }
11847 #else
11848   /* unrolled function */
11849   if(count > 8){
11850     limit = count - (count % 8);
11851 
11852     for(; i < limit; i += 8){
11853       destination[0] = 0xffffffff & ((gint64) (destination[0] + source[0]));
11854       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel = dchannels)] + source[(current_schannel = schannels)]));
11855       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + source[(current_schannel += schannels)]));
11856       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + source[(current_schannel += schannels)]));
11857       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + source[(current_schannel += schannels)]));
11858       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + source[(current_schannel += schannels)]));
11859       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + source[(current_schannel += schannels)]));
11860       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + source[(current_schannel += schannels)]));
11861 
11862       /* iterate destination */
11863       destination += (current_dchannel + dchannels);
11864 
11865       /* iterate source */
11866       source += (current_schannel + schannels);
11867     }
11868   }
11869 #endif
11870 
11871   for(; i < count; i++){
11872     destination[0] = 0xffffffff & ((gint64) (destination[0] + source[0]));
11873 
11874     destination += dchannels;
11875     source += schannels;
11876   }
11877 }
11878 
11879 /**
11880  * ags_audio_buffer_util_copy_s32_to_s64:
11881  * @destination: destination buffer
11882  * @dchannels: destination buffer's count of channels
11883  * @source: source buffer
11884  * @schannels: source buffer's count of channels
11885  * @count: number of frames to copy
11886  *
11887  * Copy audio data using additive strategy.
11888  *
11889  * Since: 3.0.0
11890  */
11891 void
ags_audio_buffer_util_copy_s32_to_s64(gint64 * destination,guint dchannels,gint32 * source,guint schannels,guint count)11892 ags_audio_buffer_util_copy_s32_to_s64(gint64 *destination, guint dchannels,
11893 				      gint32 *source, guint schannels,
11894 				      guint count)
11895 {
11896   //NOTE:JK: scale = (2^bits_destination / 2.0 - 1.0) / (2^bits_source / 2.0 - 1.0)
11897   static const gdouble scale = 0.00000000002328306417;
11898   guint limit;
11899   guint current_dchannel, current_schannel;
11900   guint i;
11901 
11902   if(destination == NULL ||
11903      source == NULL){
11904     return;
11905   }
11906 
11907   i = 0;
11908 
11909 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
11910   /* vectorized function */
11911   if(count > 8){
11912     limit = count - (count % 8);
11913 
11914     for(; i < limit; i += 8){
11915       ags_v8double v_destination;
11916       ags_v8double v_source;
11917 
11918       current_dchannel = 0;
11919       current_schannel = 0;
11920 
11921       v_destination = (ags_v8double) {(gdouble) destination[0],
11922 				      (gdouble) destination[(current_dchannel = dchannels)],
11923 				      (gdouble) destination[(current_dchannel += dchannels)],
11924 				      (gdouble) destination[(current_dchannel += dchannels)],
11925 				      (gdouble) destination[(current_dchannel += dchannels)],
11926 				      (gdouble) destination[(current_dchannel += dchannels)],
11927 				      (gdouble) destination[(current_dchannel += dchannels)],
11928 				      (gdouble) destination[(current_dchannel += dchannels)]};
11929 
11930       v_source = (ags_v8double) {(gdouble) source[0],
11931 				 (gdouble) source[(current_schannel = schannels)],
11932 				 (gdouble) source[(current_schannel += schannels)],
11933 				 (gdouble) source[(current_schannel += schannels)],
11934 				 (gdouble) source[(current_schannel += schannels)],
11935 				 (gdouble) source[(current_schannel += schannels)],
11936 				 (gdouble) source[(current_schannel += schannels)],
11937 				 (gdouble) source[(current_schannel += schannels)]};
11938 
11939       /* scale and copy */
11940       v_source *= scale;
11941       v_destination += v_source;
11942 
11943       current_dchannel = 0;
11944 
11945       destination[0] = (gint64) v_destination[0];
11946       destination[(current_dchannel = dchannels)] = (gint64) v_destination[1];
11947       destination[(current_dchannel += dchannels)] = (gint64) v_destination[2];
11948       destination[(current_dchannel += dchannels)] = (gint64) v_destination[3];
11949       destination[(current_dchannel += dchannels)] = (gint64) v_destination[4];
11950       destination[(current_dchannel += dchannels)] = (gint64) v_destination[5];
11951       destination[(current_dchannel += dchannels)] = (gint64) v_destination[6];
11952       destination[(current_dchannel += dchannels)] = (gint64) v_destination[7];
11953 
11954       /* iterate destination */
11955       destination += (current_dchannel + dchannels);
11956 
11957       /* iterate source */
11958       source += (current_schannel + schannels);
11959     }
11960   }
11961 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
11962   /* vectorized function */
11963   if(count > 8){
11964     limit = count - (count % 8);
11965 
11966     for(; i < limit; i += 8){
11967       double v_scaled[8];
11968       double v_result[8];
11969       static const double v_scale[1] = { (double) scale };
11970 
11971       current_dchannel = 0;
11972       current_schannel = 0;
11973 
11974       double v_destination[] = {(double) destination[0],
11975 				(double) destination[(current_dchannel = dchannels)],
11976 				(double) destination[(current_dchannel += dchannels)],
11977 				(double) destination[(current_dchannel += dchannels)],
11978 				(double) destination[(current_dchannel += dchannels)],
11979 				(double) destination[(current_dchannel += dchannels)],
11980 				(double) destination[(current_dchannel += dchannels)],
11981 				(double) destination[(current_dchannel += dchannels)]};
11982 
11983       double v_source[] = {(double) source[0],
11984 			   (double) source[(current_schannel = schannels)],
11985 			   (double) source[(current_schannel += schannels)],
11986 			   (double) source[(current_schannel += schannels)],
11987 			   (double) source[(current_schannel += schannels)],
11988 			   (double) source[(current_schannel += schannels)],
11989 			   (double) source[(current_schannel += schannels)],
11990 			   (double) source[(current_schannel += schannels)]};
11991 
11992       /* no scale, just copy */
11993       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
11994       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
11995 
11996       current_dchannel = 0;
11997 
11998       destination[0] = (gint64) v_result[0];
11999       destination[(current_dchannel = dchannels)] = (gint64) v_result[1];
12000       destination[(current_dchannel += dchannels)] = (gint64) v_result[2];
12001       destination[(current_dchannel += dchannels)] = (gint64) v_result[3];
12002       destination[(current_dchannel += dchannels)] = (gint64) v_result[4];
12003       destination[(current_dchannel += dchannels)] = (gint64) v_result[5];
12004       destination[(current_dchannel += dchannels)] = (gint64) v_result[6];
12005       destination[(current_dchannel += dchannels)] = (gint64) v_result[7];
12006 
12007       /* iterate destination */
12008       destination += (current_dchannel + dchannels);
12009 
12010       /* iterate source */
12011       source += (current_schannel + schannels);
12012     }
12013   }
12014 #else
12015   /* unrolled function */
12016   if(count > 8){
12017     limit = count - (count % 8);
12018 
12019     for(; i < limit; i += 8){
12020       current_dchannel = 0;
12021       current_schannel = 0;
12022 
12023       destination[0] = 0xffffffffffffffff & ((gint64) (destination[0] + (scale * source[0])));
12024       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel = dchannels)] + (scale * source[(current_schannel = schannels)])));
12025       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
12026       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
12027       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
12028       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
12029       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
12030       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
12031 
12032       /* iterate destination */
12033       destination += (current_dchannel + dchannels);
12034 
12035       /* iterate source */
12036       source += (current_schannel + schannels);
12037     }
12038   }
12039 #endif
12040 
12041   for(; i < count; i++){
12042     destination[0] = 0xffffffffffffffff & ((gint64) (destination[0] + (scale * source[0])));
12043 
12044     destination += dchannels;
12045     source += schannels;
12046   }
12047 }
12048 
12049 /**
12050  * ags_audio_buffer_util_copy_s32_to_float:
12051  * @destination: destination buffer
12052  * @dchannels: destination buffer's count of channels
12053  * @source: source buffer
12054  * @schannels: source buffer's count of channels
12055  * @count: number of frames to copy
12056  *
12057  * Copy audio data using additive strategy.
12058  *
12059  * Since: 3.0.0
12060  */
12061 void
ags_audio_buffer_util_copy_s32_to_float(gfloat * destination,guint dchannels,gint32 * source,guint schannels,guint count)12062 ags_audio_buffer_util_copy_s32_to_float(gfloat *destination, guint dchannels,
12063 					gint32 *source, guint schannels,
12064 					guint count)
12065 {
12066   //NOTE:JK: scale = 1.0 / (2^bits_source / 2.0 - 1.0)
12067   //  static const gdouble scale = 0.00000000465661291210;
12068   static const gdouble normalize_divisor = 214748363.0;
12069   guint limit;
12070   guint current_dchannel, current_schannel;
12071   guint i;
12072 
12073   if(destination == NULL ||
12074      source == NULL){
12075     return;
12076   }
12077 
12078   i = 0;
12079 
12080 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
12081   /* vectorized function */
12082   if(count > 8){
12083     limit = count - (count % 8);
12084 
12085     for(; i < limit; i += 8){
12086       ags_v8float v_destination;
12087       ags_v8float v_source;
12088 
12089       current_dchannel = 0;
12090       current_schannel = 0;
12091 
12092       v_destination = (ags_v8float) {(gfloat) destination[0],
12093 				     (gfloat) destination[(current_dchannel = dchannels)],
12094 				     (gfloat) destination[(current_dchannel += dchannels)],
12095 				     (gfloat) destination[(current_dchannel += dchannels)],
12096 				     (gfloat) destination[(current_dchannel += dchannels)],
12097 				     (gfloat) destination[(current_dchannel += dchannels)],
12098 				     (gfloat) destination[(current_dchannel += dchannels)],
12099 				     (gfloat) destination[(current_dchannel += dchannels)]};
12100 
12101       v_source = (ags_v8float) {(gfloat) source[0],
12102 				(gfloat) source[(current_schannel = schannels)],
12103 				(gfloat) source[(current_schannel += schannels)],
12104 				(gfloat) source[(current_schannel += schannels)],
12105 				(gfloat) source[(current_schannel += schannels)],
12106 				(gfloat) source[(current_schannel += schannels)],
12107 				(gfloat) source[(current_schannel += schannels)],
12108 				(gfloat) source[(current_schannel += schannels)]};
12109 
12110       /* normalize and copy */
12111       v_source /= (gfloat) normalize_divisor;
12112       v_destination += v_source;
12113 
12114       current_dchannel = 0;
12115 
12116       destination[0] = (gfloat) v_destination[0];
12117       destination[(current_dchannel = dchannels)] = (gfloat) v_destination[1];
12118       destination[(current_dchannel += dchannels)] = (gfloat) v_destination[2];
12119       destination[(current_dchannel += dchannels)] = (gfloat) v_destination[3];
12120       destination[(current_dchannel += dchannels)] = (gfloat) v_destination[4];
12121       destination[(current_dchannel += dchannels)] = (gfloat) v_destination[5];
12122       destination[(current_dchannel += dchannels)] = (gfloat) v_destination[6];
12123       destination[(current_dchannel += dchannels)] = (gfloat) v_destination[7];
12124 
12125       /* iterate destination */
12126       destination += (current_dchannel + dchannels);
12127 
12128       /* iterate source */
12129       source += (current_schannel + schannels);
12130     }
12131   }
12132 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
12133   /* vectorized function */
12134   if(count > 8){
12135     limit = count - (count % 8);
12136 
12137     for(; i < limit; i += 8){
12138       double v_normalized[8];
12139       double v_result[8];
12140       static const double v_normalize_divisor[1] = { (double) normalize_divisor };
12141 
12142       current_dchannel = 0;
12143       current_schannel = 0;
12144 
12145       double v_destination[] = {(double) destination[0],
12146 				(double) destination[(current_dchannel = dchannels)],
12147 				(double) destination[(current_dchannel += dchannels)],
12148 				(double) destination[(current_dchannel += dchannels)],
12149 				(double) destination[(current_dchannel += dchannels)],
12150 				(double) destination[(current_dchannel += dchannels)],
12151 				(double) destination[(current_dchannel += dchannels)],
12152 				(double) destination[(current_dchannel += dchannels)]};
12153 
12154       double v_source[] = {(double) source[0],
12155 			   (double) source[(current_schannel = schannels)],
12156 			   (double) source[(current_schannel += schannels)],
12157 			   (double) source[(current_schannel += schannels)],
12158 			   (double) source[(current_schannel += schannels)],
12159 			   (double) source[(current_schannel += schannels)],
12160 			   (double) source[(current_schannel += schannels)],
12161 			   (double) source[(current_schannel += schannels)]};
12162 
12163       /* no scale, just copy */
12164       vDSP_vdivD(v_normalize_divisor, 0, v_source, 1, v_normalized, 1, 8);
12165       vDSP_vaddD(v_destination, 1, v_normalized, 1, v_result, 1, 8);
12166 
12167       current_dchannel = 0;
12168 
12169       destination[0] = (gfloat) v_result[0];
12170       destination[(current_dchannel = dchannels)] = (gfloat) v_result[1];
12171       destination[(current_dchannel += dchannels)] = (gfloat) v_result[2];
12172       destination[(current_dchannel += dchannels)] = (gfloat) v_result[3];
12173       destination[(current_dchannel += dchannels)] = (gfloat) v_result[4];
12174       destination[(current_dchannel += dchannels)] = (gfloat) v_result[5];
12175       destination[(current_dchannel += dchannels)] = (gfloat) v_result[6];
12176       destination[(current_dchannel += dchannels)] = (gfloat) v_result[7];
12177 
12178       /* iterate destination */
12179       destination += (current_dchannel + dchannels);
12180 
12181       /* iterate source */
12182       source += (current_schannel + schannels);
12183     }
12184   }
12185 #else
12186   /* unrolled function */
12187   if(count > 8){
12188     limit = count - (count % 8);
12189 
12190     for(; i < limit; i += 8){
12191       current_dchannel = 0;
12192       current_schannel = 0;
12193 
12194       destination[0] = (gfloat) ((gdouble) (destination[0] + (gdouble) (source[0] / normalize_divisor)));
12195       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (source[(current_schannel = schannels)] / normalize_divisor)));
12196       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
12197       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
12198       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
12199       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
12200       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
12201       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
12202 
12203       /* iterate destination */
12204       destination += (current_dchannel + dchannels);
12205 
12206       /* iterate source */
12207       source += (current_schannel + schannels);
12208     }
12209   }
12210 #endif
12211 
12212   for(; i < count; i++){
12213     destination[0] = (gfloat) ((gdouble) (destination[0] + (gdouble) (source[0] / normalize_divisor)));
12214 
12215     destination += dchannels;
12216     source += schannels;
12217   }
12218 }
12219 
12220 /**
12221  * ags_audio_buffer_util_copy_s32_to_double:
12222  * @destination: destination buffer
12223  * @dchannels: destination buffer's count of channels
12224  * @source: source buffer
12225  * @schannels: source buffer's count of channels
12226  * @count: number of frames to copy
12227  *
12228  * Copy audio data using additive strategy.
12229  *
12230  * Since: 3.0.0
12231  */
12232 void
ags_audio_buffer_util_copy_s32_to_double(gdouble * destination,guint dchannels,gint32 * source,guint schannels,guint count)12233 ags_audio_buffer_util_copy_s32_to_double(gdouble *destination, guint dchannels,
12234 					 gint32 *source, guint schannels,
12235 					 guint count)
12236 {
12237   //NOTE:JK: scale = 1.0 / (2^bits_source / 2.0 - 1.0)
12238   //  static const gdouble scale = 0.00000000465661291210;
12239   static const gdouble normalize_divisor = 214748363.0;
12240   guint limit;
12241   guint current_dchannel, current_schannel;
12242   guint i;
12243 
12244   if(destination == NULL ||
12245      source == NULL){
12246     return;
12247   }
12248 
12249   i = 0;
12250 
12251 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
12252   /* vectorized function */
12253   if(count > 8){
12254     limit = count - (count % 8);
12255 
12256     for(; i < limit; i += 8){
12257       ags_v8double v_destination;
12258       ags_v8double v_source;
12259 
12260       current_dchannel = 0;
12261       current_schannel = 0;
12262 
12263       v_destination = (ags_v8double) {(gdouble) destination[0],
12264 				      (gdouble) destination[(current_dchannel = dchannels)],
12265 				      (gdouble) destination[(current_dchannel += dchannels)],
12266 				      (gdouble) destination[(current_dchannel += dchannels)],
12267 				      (gdouble) destination[(current_dchannel += dchannels)],
12268 				      (gdouble) destination[(current_dchannel += dchannels)],
12269 				      (gdouble) destination[(current_dchannel += dchannels)],
12270 				      (gdouble) destination[(current_dchannel += dchannels)]};
12271 
12272       v_source = (ags_v8double) {(gdouble) source[0],
12273 				 (gdouble) source[(current_schannel = schannels)],
12274 				 (gdouble) source[(current_schannel += schannels)],
12275 				 (gdouble) source[(current_schannel += schannels)],
12276 				 (gdouble) source[(current_schannel += schannels)],
12277 				 (gdouble) source[(current_schannel += schannels)],
12278 				 (gdouble) source[(current_schannel += schannels)],
12279 				 (gdouble) source[(current_schannel += schannels)]};
12280 
12281       /* normalize and copy */
12282       v_source /= normalize_divisor;
12283       v_destination += v_source;
12284 
12285       current_dchannel = 0;
12286 
12287       destination[0] = v_destination[0];
12288       destination[(current_dchannel = dchannels)] = v_destination[1];
12289       destination[(current_dchannel += dchannels)] = v_destination[2];
12290       destination[(current_dchannel += dchannels)] = v_destination[3];
12291       destination[(current_dchannel += dchannels)] = v_destination[4];
12292       destination[(current_dchannel += dchannels)] = v_destination[5];
12293       destination[(current_dchannel += dchannels)] = v_destination[6];
12294       destination[(current_dchannel += dchannels)] = v_destination[7];
12295 
12296       /* iterate destination */
12297       destination += (current_dchannel + dchannels);
12298 
12299       /* iterate source */
12300       source += (current_schannel + schannels);
12301     }
12302   }
12303 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
12304   /* vectorized function */
12305   if(count > 8){
12306     limit = count - (count % 8);
12307 
12308     for(; i < limit; i += 8){
12309       double v_normalized[8];
12310       double v_result[8];
12311       static const double v_normalize_divisor[1] = { (double) normalize_divisor };
12312 
12313       current_dchannel = 0;
12314       current_schannel = 0;
12315 
12316       double v_destination[] = {(double) destination[0],
12317 				(double) destination[(current_dchannel = dchannels)],
12318 				(double) destination[(current_dchannel += dchannels)],
12319 				(double) destination[(current_dchannel += dchannels)],
12320 				(double) destination[(current_dchannel += dchannels)],
12321 				(double) destination[(current_dchannel += dchannels)],
12322 				(double) destination[(current_dchannel += dchannels)],
12323 				(double) destination[(current_dchannel += dchannels)]};
12324 
12325       double v_source[] = {(double) source[0],
12326 			   (double) source[(current_schannel = schannels)],
12327 			   (double) source[(current_schannel += schannels)],
12328 			   (double) source[(current_schannel += schannels)],
12329 			   (double) source[(current_schannel += schannels)],
12330 			   (double) source[(current_schannel += schannels)],
12331 			   (double) source[(current_schannel += schannels)],
12332 			   (double) source[(current_schannel += schannels)]};
12333 
12334       /* no scale, just copy */
12335       vDSP_vdivD(v_normalize_divisor, 0, v_source, 1, v_normalized, 1, 8);
12336       vDSP_vaddD(v_destination, 1, v_normalized, 1, v_result, 1, 8);
12337 
12338       current_dchannel = 0;
12339 
12340       destination[0] = (gdouble) v_result[0];
12341       destination[(current_dchannel = dchannels)] = (gdouble) v_result[1];
12342       destination[(current_dchannel += dchannels)] = (gdouble) v_result[2];
12343       destination[(current_dchannel += dchannels)] = (gdouble) v_result[3];
12344       destination[(current_dchannel += dchannels)] = (gdouble) v_result[4];
12345       destination[(current_dchannel += dchannels)] = (gdouble) v_result[5];
12346       destination[(current_dchannel += dchannels)] = (gdouble) v_result[6];
12347       destination[(current_dchannel += dchannels)] = (gdouble) v_result[7];
12348 
12349       /* iterate destination */
12350       destination += (current_dchannel + dchannels);
12351 
12352       /* iterate source */
12353       source += (current_schannel + schannels);
12354     }
12355   }
12356 #else
12357   /* unrolled function */
12358   if(count > 8){
12359     limit = count - (count % 8);
12360 
12361     for(; i < limit; i += 8){
12362       current_dchannel = 0;
12363       current_schannel = 0;
12364 
12365       destination[0] = ((gdouble) (destination[0] + (gdouble) (source[0] / normalize_divisor)));
12366       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (source[(current_schannel = schannels)] / normalize_divisor)));
12367       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
12368       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
12369       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
12370       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
12371       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
12372       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
12373 
12374       /* iterate destination */
12375       destination += (current_dchannel + dchannels);
12376 
12377       /* iterate source */
12378       source += (current_schannel + schannels);
12379     }
12380   }
12381 #endif
12382 
12383   for(; i < count; i++){
12384     destination[0] = ((gdouble) (destination[0] + (gdouble) (source[0] / normalize_divisor)));
12385 
12386     destination += dchannels;
12387     source += schannels;
12388   }
12389 }
12390 
12391 /**
12392  * ags_audio_buffer_util_copy_s64_to_s8:
12393  * @destination: destination buffer
12394  * @dchannels: destination buffer's count of channels
12395  * @source: source buffer
12396  * @schannels: source buffer's count of channels
12397  * @count: number of frames to copy
12398  *
12399  * Copy audio data using additive strategy.
12400  *
12401  * Since: 3.0.0
12402  */
12403 void
ags_audio_buffer_util_copy_s64_to_s8(gint8 * destination,guint dchannels,gint64 * source,guint schannels,guint count)12404 ags_audio_buffer_util_copy_s64_to_s8(gint8 *destination, guint dchannels,
12405 				     gint64 *source, guint schannels,
12406 				     guint count)
12407 {
12408   //NOTE:JK: scale = (2^bits_destination / 2.0 - 1.0) / (2^bits_source / 2.0 - 1.0)
12409   static const gdouble scale = 0.00000000000000001376;
12410   guint limit;
12411   guint current_dchannel, current_schannel;
12412   guint i;
12413 
12414   if(destination == NULL ||
12415      source == NULL){
12416     return;
12417   }
12418 
12419   i = 0;
12420 
12421 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
12422   /* vectorized function */
12423   if(count > 8){
12424     limit = count - (count % 8);
12425 
12426     for(; i < limit; i += 8){
12427       ags_v8double v_destination;
12428       ags_v8double v_source;
12429 
12430       current_dchannel = 0;
12431       current_schannel = 0;
12432 
12433       v_destination = (ags_v8double) {(gdouble) destination[0],
12434 				      (gdouble) destination[(current_dchannel = dchannels)],
12435 				      (gdouble) destination[(current_dchannel += dchannels)],
12436 				      (gdouble) destination[(current_dchannel += dchannels)],
12437 				      (gdouble) destination[(current_dchannel += dchannels)],
12438 				      (gdouble) destination[(current_dchannel += dchannels)],
12439 				      (gdouble) destination[(current_dchannel += dchannels)],
12440 				      (gdouble) destination[(current_dchannel += dchannels)]};
12441 
12442       v_source = (ags_v8double) {(gdouble) source[0],
12443 				 (gdouble) source[(current_schannel = schannels)],
12444 				 (gdouble) source[(current_schannel += schannels)],
12445 				 (gdouble) source[(current_schannel += schannels)],
12446 				 (gdouble) source[(current_schannel += schannels)],
12447 				 (gdouble) source[(current_schannel += schannels)],
12448 				 (gdouble) source[(current_schannel += schannels)],
12449 				 (gdouble) source[(current_schannel += schannels)]};
12450 
12451       /* scale and copy */
12452       v_source *= scale;
12453       v_destination += v_source;
12454 
12455       current_dchannel = 0;
12456 
12457       destination[0] = (gint8) v_destination[0];
12458       destination[(current_dchannel = dchannels)] = (gint8) v_destination[1];
12459       destination[(current_dchannel += dchannels)] = (gint8) v_destination[2];
12460       destination[(current_dchannel += dchannels)] = (gint8) v_destination[3];
12461       destination[(current_dchannel += dchannels)] = (gint8) v_destination[4];
12462       destination[(current_dchannel += dchannels)] = (gint8) v_destination[5];
12463       destination[(current_dchannel += dchannels)] = (gint8) v_destination[6];
12464       destination[(current_dchannel += dchannels)] = (gint8) v_destination[7];
12465 
12466       /* iterate destination */
12467       destination += (current_dchannel + dchannels);
12468 
12469       /* iterate source */
12470       source += (current_schannel + schannels);
12471     }
12472   }
12473 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
12474   /* vectorized function */
12475   if(count > 8){
12476     limit = count - (count % 8);
12477 
12478     for(; i < limit; i += 8){
12479       double v_scaled[8];
12480       double v_result[8];
12481       static const double v_scale[1] = { (double) scale };
12482 
12483       current_dchannel = 0;
12484       current_schannel = 0;
12485 
12486       double v_destination[] = {(double) destination[0],
12487 				(double) destination[(current_dchannel = dchannels)],
12488 				(double) destination[(current_dchannel += dchannels)],
12489 				(double) destination[(current_dchannel += dchannels)],
12490 				(double) destination[(current_dchannel += dchannels)],
12491 				(double) destination[(current_dchannel += dchannels)],
12492 				(double) destination[(current_dchannel += dchannels)],
12493 				(double) destination[(current_dchannel += dchannels)]};
12494 
12495       double v_source[] = {(double) source[0],
12496 			   (double) source[(current_schannel = schannels)],
12497 			   (double) source[(current_schannel += schannels)],
12498 			   (double) source[(current_schannel += schannels)],
12499 			   (double) source[(current_schannel += schannels)],
12500 			   (double) source[(current_schannel += schannels)],
12501 			   (double) source[(current_schannel += schannels)],
12502 			   (double) source[(current_schannel += schannels)]};
12503 
12504       /* no scale, just copy */
12505       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
12506       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
12507 
12508       current_dchannel = 0;
12509 
12510       destination[0] = (gint8) v_result[0];
12511       destination[(current_dchannel = dchannels)] = (gint8) v_result[1];
12512       destination[(current_dchannel += dchannels)] = (gint8) v_result[2];
12513       destination[(current_dchannel += dchannels)] = (gint8) v_result[3];
12514       destination[(current_dchannel += dchannels)] = (gint8) v_result[4];
12515       destination[(current_dchannel += dchannels)] = (gint8) v_result[5];
12516       destination[(current_dchannel += dchannels)] = (gint8) v_result[6];
12517       destination[(current_dchannel += dchannels)] = (gint8) v_result[7];
12518 
12519       /* iterate destination */
12520       destination += (current_dchannel + dchannels);
12521 
12522       /* iterate source */
12523       source += (current_schannel + schannels);
12524     }
12525   }
12526 #else
12527   /* unrolled function */
12528   if(count > 8){
12529     limit = count - (count % 8);
12530 
12531     for(; i < limit; i += 8){
12532       current_dchannel = 0;
12533       current_schannel = 0;
12534 
12535       destination[0] = 0xff & ((gint16) (destination[0] + (scale * source[0])));
12536       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel = dchannels)] + (scale * source[(current_schannel = schannels)])));
12537       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
12538       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
12539       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
12540       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
12541       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
12542       destination[current_dchannel] = 0xff & ((gint16) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
12543 
12544       /* iterate destination */
12545       destination += (current_dchannel + dchannels);
12546 
12547       /* iterate source */
12548       source += (current_schannel + schannels);
12549     }
12550   }
12551 #endif
12552 
12553   for(; i < count; i++){
12554     destination[0] = 0xff & ((gint16) (destination[0] + (scale * source[0])));
12555 
12556     destination += dchannels;
12557     source += schannels;
12558   }
12559 }
12560 
12561 /**
12562  * ags_audio_buffer_util_copy_s64_to_s16:
12563  * @destination: destination buffer
12564  * @dchannels: destination buffer's count of channels
12565  * @source: source buffer
12566  * @schannels: source buffer's count of channels
12567  * @count: number of frames to copy
12568  *
12569  * Copy audio data using additive strategy.
12570  *
12571  * Since: 3.0.0
12572  */
12573 void
ags_audio_buffer_util_copy_s64_to_s16(gint16 * destination,guint dchannels,gint64 * source,guint schannels,guint count)12574 ags_audio_buffer_util_copy_s64_to_s16(gint16 *destination, guint dchannels,
12575 				      gint64 *source, guint schannels,
12576 				      guint count)
12577 {
12578   //NOTE:JK: scale = (2^bits_destination / 2.0 - 1.0) / (2^bits_source / 2.0 - 1.0)
12579   static const gdouble scale = 0.00000000000000355260;
12580   guint limit;
12581   guint current_dchannel, current_schannel;
12582   guint i;
12583 
12584   if(destination == NULL ||
12585      source == NULL){
12586     return;
12587   }
12588 
12589   i = 0;
12590 
12591 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
12592   /* vectorized function */
12593   if(count > 8){
12594     limit = count - (count % 8);
12595 
12596     for(; i < limit; i += 8){
12597       ags_v8double v_destination;
12598       ags_v8double v_source;
12599 
12600       current_dchannel = 0;
12601       current_schannel = 0;
12602 
12603       v_destination = (ags_v8double) {(gdouble) destination[0],
12604 				      (gdouble) destination[(current_dchannel = dchannels)],
12605 				      (gdouble) destination[(current_dchannel += dchannels)],
12606 				      (gdouble) destination[(current_dchannel += dchannels)],
12607 				      (gdouble) destination[(current_dchannel += dchannels)],
12608 				      (gdouble) destination[(current_dchannel += dchannels)],
12609 				      (gdouble) destination[(current_dchannel += dchannels)],
12610 				      (gdouble) destination[(current_dchannel += dchannels)]};
12611 
12612       v_source = (ags_v8double) {(gdouble) source[0],
12613 				 (gdouble) source[(current_schannel = schannels)],
12614 				 (gdouble) source[(current_schannel += schannels)],
12615 				 (gdouble) source[(current_schannel += schannels)],
12616 				 (gdouble) source[(current_schannel += schannels)],
12617 				 (gdouble) source[(current_schannel += schannels)],
12618 				 (gdouble) source[(current_schannel += schannels)],
12619 				 (gdouble) source[(current_schannel += schannels)]};
12620 
12621       /* scale and copy */
12622       v_source *= scale;
12623       v_destination += v_source;
12624 
12625       current_dchannel = 0;
12626 
12627       destination[0] = (gint16) v_destination[0];
12628       destination[(current_dchannel = dchannels)] = (gint16) v_destination[1];
12629       destination[(current_dchannel += dchannels)] = (gint16) v_destination[2];
12630       destination[(current_dchannel += dchannels)] = (gint16) v_destination[3];
12631       destination[(current_dchannel += dchannels)] = (gint16) v_destination[4];
12632       destination[(current_dchannel += dchannels)] = (gint16) v_destination[5];
12633       destination[(current_dchannel += dchannels)] = (gint16) v_destination[6];
12634       destination[(current_dchannel += dchannels)] = (gint16) v_destination[7];
12635 
12636       /* iterate destination */
12637       destination += (current_dchannel + dchannels);
12638 
12639       /* iterate source */
12640       source += (current_schannel + schannels);
12641     }
12642   }
12643 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
12644   /* vectorized function */
12645   if(count > 8){
12646     limit = count - (count % 8);
12647 
12648     for(; i < limit; i += 8){
12649       double v_scaled[8];
12650       double v_result[8];
12651       static const double v_scale[1] = { (double) scale };
12652 
12653       current_dchannel = 0;
12654       current_schannel = 0;
12655 
12656       double v_destination[] = {(double) destination[0],
12657 				(double) destination[(current_dchannel = dchannels)],
12658 				(double) destination[(current_dchannel += dchannels)],
12659 				(double) destination[(current_dchannel += dchannels)],
12660 				(double) destination[(current_dchannel += dchannels)],
12661 				(double) destination[(current_dchannel += dchannels)],
12662 				(double) destination[(current_dchannel += dchannels)],
12663 				(double) destination[(current_dchannel += dchannels)]};
12664 
12665       double v_source[] = {(double) source[0],
12666 			   (double) source[(current_schannel = schannels)],
12667 			   (double) source[(current_schannel += schannels)],
12668 			   (double) source[(current_schannel += schannels)],
12669 			   (double) source[(current_schannel += schannels)],
12670 			   (double) source[(current_schannel += schannels)],
12671 			   (double) source[(current_schannel += schannels)],
12672 			   (double) source[(current_schannel += schannels)]};
12673 
12674       /* no scale, just copy */
12675       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
12676       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
12677 
12678       current_dchannel = 0;
12679 
12680       destination[0] = (gint16) v_result[0];
12681       destination[(current_dchannel = dchannels)] = (gint16) v_result[1];
12682       destination[(current_dchannel += dchannels)] = (gint16) v_result[2];
12683       destination[(current_dchannel += dchannels)] = (gint16) v_result[3];
12684       destination[(current_dchannel += dchannels)] = (gint16) v_result[4];
12685       destination[(current_dchannel += dchannels)] = (gint16) v_result[5];
12686       destination[(current_dchannel += dchannels)] = (gint16) v_result[6];
12687       destination[(current_dchannel += dchannels)] = (gint16) v_result[7];
12688 
12689       /* iterate destination */
12690       destination += (current_dchannel + dchannels);
12691 
12692       /* iterate source */
12693       source += (current_schannel + schannels);
12694     }
12695   }
12696 #else
12697   /* unrolled function */
12698   if(count > 8){
12699     limit = count - (count % 8);
12700 
12701     for(; i < limit; i += 8){
12702       current_dchannel = 0;
12703       current_schannel = 0;
12704 
12705       destination[0] = 0xffff & ((gint32) (destination[0] + (scale * source[0])));
12706       destination[current_dchannel] = 0xffff & ((gint32) (destination[(current_dchannel = dchannels)] + (scale * source[(current_schannel = schannels)])));
12707       destination[current_dchannel] = 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
12708       destination[current_dchannel] = 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
12709       destination[current_dchannel] = 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
12710       destination[current_dchannel] = 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
12711       destination[current_dchannel] = 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
12712       destination[current_dchannel] = 0xffff & ((gint32) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
12713 
12714       /* iterate destination */
12715       destination += (current_dchannel + dchannels);
12716 
12717       /* iterate source */
12718       source += (current_schannel + schannels);
12719     }
12720   }
12721 #endif
12722 
12723   for(; i < count; i++){
12724     destination[0] = 0xffff & ((gint32) (destination[0] + (scale * source[0])));
12725 
12726     destination += dchannels;
12727     source += schannels;
12728   }
12729 }
12730 
12731 /**
12732  * ags_audio_buffer_util_copy_s64_to_s24:
12733  * @destination: destination buffer
12734  * @dchannels: destination buffer's count of channels
12735  * @source: source buffer
12736  * @schannels: source buffer's count of channels
12737  * @count: number of frames to copy
12738  *
12739  * Copy audio data using additive strategy.
12740  *
12741  * Since: 3.0.0
12742  */
12743 void
ags_audio_buffer_util_copy_s64_to_s24(gint32 * destination,guint dchannels,gint64 * source,guint schannels,guint count)12744 ags_audio_buffer_util_copy_s64_to_s24(gint32 *destination, guint dchannels,
12745 				      gint64 *source, guint schannels,
12746 				      guint count)
12747 {
12748   //NOTE:JK: scale = (2^bits_destination / 2.0 - 1.0) / (2^bits_source / 2.0 - 1.0)
12749   static const gdouble scale = 0.00000000000090949459;
12750   guint limit;
12751   guint current_dchannel, current_schannel;
12752   guint i;
12753 
12754   if(destination == NULL ||
12755      source == NULL){
12756     return;
12757   }
12758 
12759   i = 0;
12760 
12761 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
12762   /* vectorized function */
12763   if(count > 8){
12764     limit = count - (count % 8);
12765 
12766     for(; i < limit; i += 8){
12767       ags_v8double v_destination;
12768       ags_v8double v_source;
12769 
12770       current_dchannel = 0;
12771       current_schannel = 0;
12772 
12773       v_destination = (ags_v8double) {(gdouble) destination[0],
12774 				      (gdouble) destination[(current_dchannel = dchannels)],
12775 				      (gdouble) destination[(current_dchannel += dchannels)],
12776 				      (gdouble) destination[(current_dchannel += dchannels)],
12777 				      (gdouble) destination[(current_dchannel += dchannels)],
12778 				      (gdouble) destination[(current_dchannel += dchannels)],
12779 				      (gdouble) destination[(current_dchannel += dchannels)],
12780 				      (gdouble) destination[(current_dchannel += dchannels)]};
12781 
12782       v_source = (ags_v8double) {(gdouble) source[0],
12783 				 (gdouble) source[(current_schannel = schannels)],
12784 				 (gdouble) source[(current_schannel += schannels)],
12785 				 (gdouble) source[(current_schannel += schannels)],
12786 				 (gdouble) source[(current_schannel += schannels)],
12787 				 (gdouble) source[(current_schannel += schannels)],
12788 				 (gdouble) source[(current_schannel += schannels)],
12789 				 (gdouble) source[(current_schannel += schannels)]};
12790 
12791       /* scale and copy */
12792       v_source *= scale;
12793       v_destination += v_source;
12794 
12795       current_dchannel = 0;
12796 
12797       destination[0] = (gint32) v_destination[0];
12798       destination[(current_dchannel = dchannels)] = (gint32) v_destination[1];
12799       destination[(current_dchannel += dchannels)] = (gint32) v_destination[2];
12800       destination[(current_dchannel += dchannels)] = (gint32) v_destination[3];
12801       destination[(current_dchannel += dchannels)] = (gint32) v_destination[4];
12802       destination[(current_dchannel += dchannels)] = (gint32) v_destination[5];
12803       destination[(current_dchannel += dchannels)] = (gint32) v_destination[6];
12804       destination[(current_dchannel += dchannels)] = (gint32) v_destination[7];
12805 
12806       /* iterate destination */
12807       destination += (current_dchannel + dchannels);
12808 
12809       /* iterate source */
12810       source += (current_schannel + schannels);
12811     }
12812   }
12813 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
12814   /* vectorized function */
12815   if(count > 8){
12816     limit = count - (count % 8);
12817 
12818     for(; i < limit; i += 8){
12819       double v_scaled[8];
12820       double v_result[8];
12821       static const double v_scale[1] = { (double) scale };
12822 
12823       current_dchannel = 0;
12824       current_schannel = 0;
12825 
12826       double v_destination[] = {(double) destination[0],
12827 				(double) destination[(current_dchannel = dchannels)],
12828 				(double) destination[(current_dchannel += dchannels)],
12829 				(double) destination[(current_dchannel += dchannels)],
12830 				(double) destination[(current_dchannel += dchannels)],
12831 				(double) destination[(current_dchannel += dchannels)],
12832 				(double) destination[(current_dchannel += dchannels)],
12833 				(double) destination[(current_dchannel += dchannels)]};
12834 
12835       double v_source[] = {(double) source[0],
12836 			   (double) source[(current_schannel = schannels)],
12837 			   (double) source[(current_schannel += schannels)],
12838 			   (double) source[(current_schannel += schannels)],
12839 			   (double) source[(current_schannel += schannels)],
12840 			   (double) source[(current_schannel += schannels)],
12841 			   (double) source[(current_schannel += schannels)],
12842 			   (double) source[(current_schannel += schannels)]};
12843 
12844       /* no scale, just copy */
12845       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
12846       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
12847 
12848       current_dchannel = 0;
12849 
12850       destination[0] = (gint32) v_result[0];
12851       destination[(current_dchannel = dchannels)] = (gint32) v_result[1];
12852       destination[(current_dchannel += dchannels)] = (gint32) v_result[2];
12853       destination[(current_dchannel += dchannels)] = (gint32) v_result[3];
12854       destination[(current_dchannel += dchannels)] = (gint32) v_result[4];
12855       destination[(current_dchannel += dchannels)] = (gint32) v_result[5];
12856       destination[(current_dchannel += dchannels)] = (gint32) v_result[6];
12857       destination[(current_dchannel += dchannels)] = (gint32) v_result[7];
12858 
12859       /* iterate destination */
12860       destination += (current_dchannel + dchannels);
12861 
12862       /* iterate source */
12863       source += (current_schannel + schannels);
12864     }
12865   }
12866 #else
12867   /* unrolled function */
12868   if(count > 8){
12869     limit = count - (count % 8);
12870 
12871     for(; i < limit; i += 8){
12872       current_dchannel = 0;
12873       current_schannel = 0;
12874 
12875       destination[0] = 0xffffffff & ((gint32) (destination[0] + (scale * source[0])));
12876       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel = dchannels)] + (scale * source[(current_schannel = schannels)])));
12877       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
12878       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
12879       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
12880       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
12881       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
12882       destination[current_dchannel] = 0xffffffff & ((gint32) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
12883 
12884       /* iterate destination */
12885       destination += (current_dchannel + dchannels);
12886 
12887       /* iterate source */
12888       source += (current_schannel + schannels);
12889     }
12890   }
12891 #endif
12892 
12893   for(; i < count; i++){
12894     destination[0] = 0xffffffff & ((gint32) (destination[0] + (scale * source[0])));
12895 
12896     destination += dchannels;
12897     source += schannels;
12898   }
12899 }
12900 
12901 /**
12902  * ags_audio_buffer_util_copy_s64_to_s32:
12903  * @destination: destination buffer
12904  * @dchannels: destination buffer's count of channels
12905  * @source: source buffer
12906  * @schannels: source buffer's count of channels
12907  * @count: number of frames to copy
12908  *
12909  * Copy audio data using additive strategy.
12910  *
12911  * Since: 3.0.0
12912  */
12913 void
ags_audio_buffer_util_copy_s64_to_s32(gint32 * destination,guint dchannels,gint64 * source,guint schannels,guint count)12914 ags_audio_buffer_util_copy_s64_to_s32(gint32 *destination, guint dchannels,
12915 				      gint64 *source, guint schannels,
12916 				      guint count)
12917 {
12918   //NOTE:JK: scale = (2^bits_destination / 2.0 - 1.0) / (2^bits_source / 2.0 - 1.0)
12919   static const gdouble scale = 0.00000000002328306417;
12920   guint limit;
12921   guint current_dchannel, current_schannel;
12922   guint i;
12923 
12924   if(destination == NULL ||
12925      source == NULL){
12926     return;
12927   }
12928 
12929   i = 0;
12930 
12931 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
12932   /* vectorized function */
12933   if(count > 8){
12934     limit = count - (count % 8);
12935 
12936     for(; i < limit; i += 8){
12937       ags_v8double v_destination;
12938       ags_v8double v_source;
12939 
12940       current_dchannel = 0;
12941       current_schannel = 0;
12942 
12943       v_destination = (ags_v8double) {(gdouble) destination[0],
12944 				      (gdouble) destination[(current_dchannel = dchannels)],
12945 				      (gdouble) destination[(current_dchannel += dchannels)],
12946 				      (gdouble) destination[(current_dchannel += dchannels)],
12947 				      (gdouble) destination[(current_dchannel += dchannels)],
12948 				      (gdouble) destination[(current_dchannel += dchannels)],
12949 				      (gdouble) destination[(current_dchannel += dchannels)],
12950 				      (gdouble) destination[(current_dchannel += dchannels)]};
12951 
12952       v_source = (ags_v8double) {(gdouble) source[0],
12953 				 (gdouble) source[(current_schannel = schannels)],
12954 				 (gdouble) source[(current_schannel += schannels)],
12955 				 (gdouble) source[(current_schannel += schannels)],
12956 				 (gdouble) source[(current_schannel += schannels)],
12957 				 (gdouble) source[(current_schannel += schannels)],
12958 				 (gdouble) source[(current_schannel += schannels)],
12959 				 (gdouble) source[(current_schannel += schannels)]};
12960 
12961       /* scale and copy */
12962       v_source *= scale;
12963       v_destination += v_source;
12964 
12965       current_dchannel = 0;
12966 
12967       destination[0] = (gint32) v_destination[0];
12968       destination[(current_dchannel = dchannels)] = (gint32) v_destination[1];
12969       destination[(current_dchannel += dchannels)] = (gint32) v_destination[2];
12970       destination[(current_dchannel += dchannels)] = (gint32) v_destination[3];
12971       destination[(current_dchannel += dchannels)] = (gint32) v_destination[4];
12972       destination[(current_dchannel += dchannels)] = (gint32) v_destination[5];
12973       destination[(current_dchannel += dchannels)] = (gint32) v_destination[6];
12974       destination[(current_dchannel += dchannels)] = (gint32) v_destination[7];
12975 
12976       /* iterate destination */
12977       destination += (current_dchannel + dchannels);
12978 
12979       /* iterate source */
12980       source += (current_schannel + schannels);
12981     }
12982   }
12983 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
12984   /* vectorized function */
12985   if(count > 8){
12986     limit = count - (count % 8);
12987 
12988     for(; i < limit; i += 8){
12989       double v_scaled[8];
12990       double v_result[8];
12991       static const double v_scale[1] = { (double) scale };
12992 
12993       current_dchannel = 0;
12994       current_schannel = 0;
12995 
12996       double v_destination[] = {(double) destination[0],
12997 				(double) destination[(current_dchannel = dchannels)],
12998 				(double) destination[(current_dchannel += dchannels)],
12999 				(double) destination[(current_dchannel += dchannels)],
13000 				(double) destination[(current_dchannel += dchannels)],
13001 				(double) destination[(current_dchannel += dchannels)],
13002 				(double) destination[(current_dchannel += dchannels)],
13003 				(double) destination[(current_dchannel += dchannels)]};
13004 
13005       double v_source[] = {(double) source[0],
13006 			   (double) source[(current_schannel = schannels)],
13007 			   (double) source[(current_schannel += schannels)],
13008 			   (double) source[(current_schannel += schannels)],
13009 			   (double) source[(current_schannel += schannels)],
13010 			   (double) source[(current_schannel += schannels)],
13011 			   (double) source[(current_schannel += schannels)],
13012 			   (double) source[(current_schannel += schannels)]};
13013 
13014       /* no scale, just copy */
13015       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
13016       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
13017 
13018       current_dchannel = 0;
13019 
13020       destination[0] = (gint32) v_result[0];
13021       destination[(current_dchannel = dchannels)] = (gint32) v_result[1];
13022       destination[(current_dchannel += dchannels)] = (gint32) v_result[2];
13023       destination[(current_dchannel += dchannels)] = (gint32) v_result[3];
13024       destination[(current_dchannel += dchannels)] = (gint32) v_result[4];
13025       destination[(current_dchannel += dchannels)] = (gint32) v_result[5];
13026       destination[(current_dchannel += dchannels)] = (gint32) v_result[6];
13027       destination[(current_dchannel += dchannels)] = (gint32) v_result[7];
13028 
13029       /* iterate destination */
13030       destination += (current_dchannel + dchannels);
13031 
13032       /* iterate source */
13033       source += (current_schannel + schannels);
13034     }
13035   }
13036 #else
13037   /* unrolled function */
13038   if(count > 8){
13039     limit = count - (count % 8);
13040 
13041     for(; i < limit; i += 8){
13042       current_dchannel = 0;
13043       current_schannel = 0;
13044 
13045       destination[0] = 0xffffffff & ((gint64) (destination[0] + (scale * source[0])));
13046       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel = dchannels)] + (scale * source[(current_schannel = schannels)])));
13047       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
13048       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
13049       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
13050       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
13051       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
13052       destination[current_dchannel] = 0xffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + (scale * source[(current_schannel += schannels)])));
13053 
13054       /* iterate destination */
13055       destination += (current_dchannel + dchannels);
13056 
13057       /* iterate source */
13058       source += (current_schannel + schannels);
13059     }
13060   }
13061 #endif
13062 
13063   for(; i < count; i++){
13064     destination[0] = 0xffffffff & ((gint64) (destination[0] + (scale * source[0])));
13065 
13066     destination += dchannels;
13067     source += schannels;
13068   }
13069 }
13070 
13071 /**
13072  * ags_audio_buffer_util_copy_s64_to_s64:
13073  * @destination: destination buffer
13074  * @dchannels: destination buffer's count of channels
13075  * @source: source buffer
13076  * @schannels: source buffer's count of channels
13077  * @count: number of frames to copy
13078  *
13079  * Copy audio data using additive strategy.
13080  *
13081  * Since: 3.0.0
13082  */
13083 void
ags_audio_buffer_util_copy_s64_to_s64(gint64 * destination,guint dchannels,gint64 * source,guint schannels,guint count)13084 ags_audio_buffer_util_copy_s64_to_s64(gint64 *destination, guint dchannels,
13085 				      gint64 *source, guint schannels,
13086 				      guint count)
13087 {
13088   guint limit;
13089   guint current_dchannel, current_schannel;
13090   guint i;
13091 
13092   if(destination == NULL ||
13093      source == NULL){
13094     return;
13095   }
13096 
13097   i = 0;
13098 
13099 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
13100   /* vectorized function */
13101   if(count > 8){
13102     limit = count - (count % 8);
13103 
13104     for(; i < limit; i += 8){
13105       ags_v8s64 v_destination;
13106       ags_v8s64 v_source;
13107 
13108       current_dchannel = 0;
13109       current_schannel = 0;
13110 
13111       v_destination = (ags_v8s64) {destination[0],
13112 				   destination[(current_dchannel = dchannels)],
13113 				   destination[(current_dchannel += dchannels)],
13114 				   destination[(current_dchannel += dchannels)],
13115 				   destination[(current_dchannel += dchannels)],
13116 				   destination[(current_dchannel += dchannels)],
13117 				   destination[(current_dchannel += dchannels)],
13118 				   destination[(current_dchannel += dchannels)]};
13119 
13120       v_source = (ags_v8s64) {source[0],
13121 			      source[(current_schannel = schannels)],
13122 			      source[(current_schannel += schannels)],
13123 			      source[(current_schannel += schannels)],
13124 			      source[(current_schannel += schannels)],
13125 			      source[(current_schannel += schannels)],
13126 			      source[(current_schannel += schannels)],
13127 			      source[(current_schannel += schannels)]};
13128 
13129       /* no scale, just copy */
13130       v_destination += v_source;
13131 
13132       current_dchannel = 0;
13133 
13134       destination[0] = v_destination[0];
13135       destination[(current_dchannel = dchannels)] = v_destination[1];
13136       destination[(current_dchannel += dchannels)] = v_destination[2];
13137       destination[(current_dchannel += dchannels)] = v_destination[3];
13138       destination[(current_dchannel += dchannels)] = v_destination[4];
13139       destination[(current_dchannel += dchannels)] = v_destination[5];
13140       destination[(current_dchannel += dchannels)] = v_destination[6];
13141       destination[(current_dchannel += dchannels)] = v_destination[7];
13142 
13143       /* iterate destination */
13144       destination += (current_dchannel + dchannels);
13145 
13146       /* iterate source */
13147       source += (current_schannel + schannels);
13148     }
13149   }
13150 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
13151   /* vectorized function */
13152   if(count > 8){
13153     limit = count - (count % 8);
13154 
13155     for(; i < limit; i += 8){
13156       int v_result[8];
13157 
13158       current_dchannel = 0;
13159       current_schannel = 0;
13160 
13161       int v_destination[] = {(int) destination[0],
13162 			     (int) destination[(current_dchannel = dchannels)],
13163 			     (int) destination[(current_dchannel += dchannels)],
13164 			     (int) destination[(current_dchannel += dchannels)],
13165 			     (int) destination[(current_dchannel += dchannels)],
13166 			     (int) destination[(current_dchannel += dchannels)],
13167 			     (int) destination[(current_dchannel += dchannels)],
13168 			     (int) destination[(current_dchannel += dchannels)]};
13169 
13170       int v_source[] = {(int) source[0],
13171 			(int) source[(current_schannel = schannels)],
13172 			(int) source[(current_schannel += schannels)],
13173 			(int) source[(current_schannel += schannels)],
13174 			(int) source[(current_schannel += schannels)],
13175 			(int) source[(current_schannel += schannels)],
13176 			(int) source[(current_schannel += schannels)],
13177 			(int) source[(current_schannel += schannels)]};
13178 
13179       /* no scale, just copy */
13180       vDSP_vaddi(v_destination, 1, v_source, 1, v_result, 1, 8);
13181 
13182       current_dchannel = 0;
13183 
13184       destination[0] = (gint64) v_result[0];
13185       destination[(current_dchannel = dchannels)] = (gint64) v_result[1];
13186       destination[(current_dchannel += dchannels)] = (gint64) v_result[2];
13187       destination[(current_dchannel += dchannels)] = (gint64) v_result[3];
13188       destination[(current_dchannel += dchannels)] = (gint64) v_result[4];
13189       destination[(current_dchannel += dchannels)] = (gint64) v_result[5];
13190       destination[(current_dchannel += dchannels)] = (gint64) v_result[6];
13191       destination[(current_dchannel += dchannels)] = (gint64) v_result[7];
13192 
13193       /* iterate destination */
13194       destination += (current_dchannel + dchannels);
13195 
13196       /* iterate source */
13197       source += (current_schannel + schannels);
13198     }
13199   }
13200 #else
13201   /* unrolled function */
13202   if(count > 8){
13203     limit = count - (count % 8);
13204 
13205     for(; i < limit; i += 8){
13206       current_dchannel = 0;
13207       current_schannel = 0;
13208 
13209       destination[0] = 0xffffffffffffffff & ((gint64) (destination[0] + source[0]));
13210       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel = dchannels)] + source[(current_schannel = schannels)]));
13211       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + source[(current_schannel += schannels)]));
13212       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + source[(current_schannel += schannels)]));
13213       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + source[(current_schannel += schannels)]));
13214       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + source[(current_schannel += schannels)]));
13215       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + source[(current_schannel += schannels)]));
13216       destination[current_dchannel] = 0xffffffffffffffff & ((gint64) (destination[(current_dchannel += dchannels)] + source[(current_schannel += schannels)]));
13217 
13218       /* iterate destination */
13219       destination += (current_dchannel + dchannels);
13220 
13221       /* iterate source */
13222       source += (current_schannel + schannels);
13223     }
13224   }
13225 #endif
13226 
13227   for(; i < count; i++){
13228     destination[0] = 0xffffffffffffffff & ((gint64) (destination[0] + source[0]));
13229 
13230     destination += dchannels;
13231     source += schannels;
13232   }
13233 }
13234 
13235 /**
13236  * ags_audio_buffer_util_copy_s64_to_float:
13237  * @destination: destination buffer
13238  * @dchannels: destination buffer's count of channels
13239  * @source: source buffer
13240  * @schannels: source buffer's count of channels
13241  * @count: number of frames to copy
13242  *
13243  * Copy audio data using additive strategy.
13244  *
13245  * Since: 3.0.0
13246  */
13247 void
ags_audio_buffer_util_copy_s64_to_float(gfloat * destination,guint dchannels,gint64 * source,guint schannels,guint count)13248 ags_audio_buffer_util_copy_s64_to_float(gfloat *destination, guint dchannels,
13249 					gint64 *source, guint schannels,
13250 					guint count)
13251 {
13252   //NOTE:JK: scale = 1.0 / (2^bits_source / 2.0 - 1.0)
13253   //  static const gdouble scale = 0.00000000000000000010;
13254   static const gdouble normalize_divisor = 9223372036854775807.0;
13255   guint limit;
13256   guint current_dchannel, current_schannel;
13257   guint i;
13258 
13259   if(destination == NULL ||
13260      source == NULL){
13261     return;
13262   }
13263 
13264   i = 0;
13265 
13266 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
13267   /* vectorized function */
13268   if(count > 8){
13269     limit = count - (count % 8);
13270 
13271     for(; i < limit; i += 8){
13272       ags_v8float v_destination;
13273       ags_v8float v_source;
13274 
13275       current_dchannel = 0;
13276       current_schannel = 0;
13277 
13278       v_destination = (ags_v8float) {(gfloat) destination[0],
13279 				     (gfloat) destination[(current_dchannel = dchannels)],
13280 				     (gfloat) destination[(current_dchannel += dchannels)],
13281 				     (gfloat) destination[(current_dchannel += dchannels)],
13282 				     (gfloat) destination[(current_dchannel += dchannels)],
13283 				     (gfloat) destination[(current_dchannel += dchannels)],
13284 				     (gfloat) destination[(current_dchannel += dchannels)],
13285 				     (gfloat) destination[(current_dchannel += dchannels)]};
13286 
13287       v_source = (ags_v8float) {(gfloat) source[0],
13288 				(gfloat) source[(current_schannel = schannels)],
13289 				(gfloat) source[(current_schannel += schannels)],
13290 				(gfloat) source[(current_schannel += schannels)],
13291 				(gfloat) source[(current_schannel += schannels)],
13292 				(gfloat) source[(current_schannel += schannels)],
13293 				(gfloat) source[(current_schannel += schannels)],
13294 				(gfloat) source[(current_schannel += schannels)]};
13295 
13296       /* normalize and copy */
13297       v_source /= (gfloat) normalize_divisor;
13298       v_destination += v_source;
13299 
13300       current_dchannel = 0;
13301 
13302       destination[0] = (gfloat) v_destination[0];
13303       destination[(current_dchannel = dchannels)] = (gfloat) v_destination[1];
13304       destination[(current_dchannel += dchannels)] = (gfloat) v_destination[2];
13305       destination[(current_dchannel += dchannels)] = (gfloat) v_destination[3];
13306       destination[(current_dchannel += dchannels)] = (gfloat) v_destination[4];
13307       destination[(current_dchannel += dchannels)] = (gfloat) v_destination[5];
13308       destination[(current_dchannel += dchannels)] = (gfloat) v_destination[6];
13309       destination[(current_dchannel += dchannels)] = (gfloat) v_destination[7];
13310 
13311       /* iterate destination */
13312       destination += (current_dchannel + dchannels);
13313 
13314       /* iterate source */
13315       source += (current_schannel + schannels);
13316     }
13317   }
13318 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
13319   /* vectorized function */
13320   if(count > 8){
13321     limit = count - (count % 8);
13322 
13323     for(; i < limit; i += 8){
13324       double v_normalized[8];
13325       double v_result[8];
13326       static const double v_normalize_divisor[1] = { (double) normalize_divisor };
13327 
13328       current_dchannel = 0;
13329       current_schannel = 0;
13330 
13331       double v_destination[] = {(double) destination[0],
13332 				(double) destination[(current_dchannel = dchannels)],
13333 				(double) destination[(current_dchannel += dchannels)],
13334 				(double) destination[(current_dchannel += dchannels)],
13335 				(double) destination[(current_dchannel += dchannels)],
13336 				(double) destination[(current_dchannel += dchannels)],
13337 				(double) destination[(current_dchannel += dchannels)],
13338 				(double) destination[(current_dchannel += dchannels)]};
13339 
13340       double v_source[] = {(double) source[0],
13341 			   (double) source[(current_schannel = schannels)],
13342 			   (double) source[(current_schannel += schannels)],
13343 			   (double) source[(current_schannel += schannels)],
13344 			   (double) source[(current_schannel += schannels)],
13345 			   (double) source[(current_schannel += schannels)],
13346 			   (double) source[(current_schannel += schannels)],
13347 			   (double) source[(current_schannel += schannels)]};
13348 
13349       /* no scale, just copy */
13350       vDSP_vdivD(v_normalize_divisor, 0, v_source, 1, v_normalized, 1, 8);
13351       vDSP_vaddD(v_destination, 1, v_normalized, 1, v_result, 1, 8);
13352 
13353       current_dchannel = 0;
13354 
13355       destination[0] = (gfloat) v_result[0];
13356       destination[(current_dchannel = dchannels)] = (gfloat) v_result[1];
13357       destination[(current_dchannel += dchannels)] = (gfloat) v_result[2];
13358       destination[(current_dchannel += dchannels)] = (gfloat) v_result[3];
13359       destination[(current_dchannel += dchannels)] = (gfloat) v_result[4];
13360       destination[(current_dchannel += dchannels)] = (gfloat) v_result[5];
13361       destination[(current_dchannel += dchannels)] = (gfloat) v_result[6];
13362       destination[(current_dchannel += dchannels)] = (gfloat) v_result[7];
13363 
13364       /* iterate destination */
13365       destination += (current_dchannel + dchannels);
13366 
13367       /* iterate source */
13368       source += (current_schannel + schannels);
13369     }
13370   }
13371 #else
13372   /* unrolled function */
13373   if(count > 8){
13374     limit = count - (count % 8);
13375 
13376     for(; i < limit; i += 8){
13377       current_dchannel = 0;
13378       current_schannel = 0;
13379 
13380       destination[0] = (gfloat) ((gdouble) (destination[0] + (gdouble) (source[0] / normalize_divisor)));
13381       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (source[(current_schannel = schannels)] / normalize_divisor)));
13382       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
13383       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
13384       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
13385       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
13386       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
13387       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
13388 
13389       /* iterate destination */
13390       destination += (current_dchannel + dchannels);
13391 
13392       /* iterate source */
13393       source += (current_schannel + schannels);
13394     }
13395   }
13396 #endif
13397 
13398   for(; i < count; i++){
13399     destination[0] = (gfloat) ((gdouble) (destination[0] + (gdouble) (source[0] / normalize_divisor)));
13400 
13401     destination += dchannels;
13402     source += schannels;
13403   }
13404 }
13405 
13406 /**
13407  * ags_audio_buffer_util_copy_s64_to_double:
13408  * @destination: destination buffer
13409  * @dchannels: destination buffer's count of channels
13410  * @source: source buffer
13411  * @schannels: source buffer's count of channels
13412  * @count: number of frames to copy
13413  *
13414  * Copy audio data using additive strategy.
13415  *
13416  * Since: 3.0.0
13417  */
13418 void
ags_audio_buffer_util_copy_s64_to_double(gdouble * destination,guint dchannels,gint64 * source,guint schannels,guint count)13419 ags_audio_buffer_util_copy_s64_to_double(gdouble *destination, guint dchannels,
13420 					 gint64 *source, guint schannels,
13421 					 guint count)
13422 {
13423   //NOTE:JK: scale = 1.0 / (2^bits_source / 2.0 - 1.0)
13424   //  static const gdouble scale = 0.00000000000000000010;
13425   static const gdouble normalize_divisor = 9223372036854775807.0;
13426   guint limit;
13427   guint current_dchannel, current_schannel;
13428   guint i;
13429 
13430   if(destination == NULL ||
13431      source == NULL){
13432     return;
13433   }
13434 
13435   i = 0;
13436 
13437 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
13438   /* vectorized function */
13439   if(count > 8){
13440     limit = count - (count % 8);
13441 
13442     for(; i < limit; i += 8){
13443       ags_v8double v_destination;
13444       ags_v8double v_source;
13445 
13446       current_dchannel = 0;
13447       current_schannel = 0;
13448 
13449       v_destination = (ags_v8double) {(gdouble) destination[0],
13450 				      (gdouble) destination[(current_dchannel = dchannels)],
13451 				      (gdouble) destination[(current_dchannel += dchannels)],
13452 				      (gdouble) destination[(current_dchannel += dchannels)],
13453 				      (gdouble) destination[(current_dchannel += dchannels)],
13454 				      (gdouble) destination[(current_dchannel += dchannels)],
13455 				      (gdouble) destination[(current_dchannel += dchannels)],
13456 				      (gdouble) destination[(current_dchannel += dchannels)]};
13457 
13458       v_source = (ags_v8double) {(gdouble) source[0],
13459 				 (gdouble) source[(current_schannel = schannels)],
13460 				 (gdouble) source[(current_schannel += schannels)],
13461 				 (gdouble) source[(current_schannel += schannels)],
13462 				 (gdouble) source[(current_schannel += schannels)],
13463 				 (gdouble) source[(current_schannel += schannels)],
13464 				 (gdouble) source[(current_schannel += schannels)],
13465 				 (gdouble) source[(current_schannel += schannels)]};
13466 
13467       /* normalize and copy */
13468       v_source /= normalize_divisor;
13469       v_destination += v_source;
13470 
13471       current_dchannel = 0;
13472 
13473       destination[0] = v_destination[0];
13474       destination[(current_dchannel = dchannels)] = v_destination[1];
13475       destination[(current_dchannel += dchannels)] = v_destination[2];
13476       destination[(current_dchannel += dchannels)] = v_destination[3];
13477       destination[(current_dchannel += dchannels)] = v_destination[4];
13478       destination[(current_dchannel += dchannels)] = v_destination[5];
13479       destination[(current_dchannel += dchannels)] = v_destination[6];
13480       destination[(current_dchannel += dchannels)] = v_destination[7];
13481 
13482       /* iterate destination */
13483       destination += (current_dchannel + dchannels);
13484 
13485       /* iterate source */
13486       source += (current_schannel + schannels);
13487     }
13488   }
13489 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
13490   /* vectorized function */
13491   if(count > 8){
13492     limit = count - (count % 8);
13493 
13494     for(; i < limit; i += 8){
13495       double v_normalized[8];
13496       double v_result[8];
13497       static const double v_normalize_divisor[1] = { (double) normalize_divisor };
13498 
13499       current_dchannel = 0;
13500       current_schannel = 0;
13501 
13502       double v_destination[] = {(double) destination[0],
13503 				(double) destination[(current_dchannel = dchannels)],
13504 				(double) destination[(current_dchannel += dchannels)],
13505 				(double) destination[(current_dchannel += dchannels)],
13506 				(double) destination[(current_dchannel += dchannels)],
13507 				(double) destination[(current_dchannel += dchannels)],
13508 				(double) destination[(current_dchannel += dchannels)],
13509 				(double) destination[(current_dchannel += dchannels)]};
13510 
13511       double v_source[] = {(double) source[0],
13512 			   (double) source[(current_schannel = schannels)],
13513 			   (double) source[(current_schannel += schannels)],
13514 			   (double) source[(current_schannel += schannels)],
13515 			   (double) source[(current_schannel += schannels)],
13516 			   (double) source[(current_schannel += schannels)],
13517 			   (double) source[(current_schannel += schannels)],
13518 			   (double) source[(current_schannel += schannels)]};
13519 
13520       /* no scale, just copy */
13521       vDSP_vdivD(v_normalize_divisor, 0, v_source, 1, v_normalized, 1, 8);
13522       vDSP_vaddD(v_destination, 1, v_normalized, 1, v_result, 1, 8);
13523 
13524       current_dchannel = 0;
13525 
13526       destination[0] = (gdouble) v_result[0];
13527       destination[(current_dchannel = dchannels)] = (gdouble) v_result[1];
13528       destination[(current_dchannel += dchannels)] = (gdouble) v_result[2];
13529       destination[(current_dchannel += dchannels)] = (gdouble) v_result[3];
13530       destination[(current_dchannel += dchannels)] = (gdouble) v_result[4];
13531       destination[(current_dchannel += dchannels)] = (gdouble) v_result[5];
13532       destination[(current_dchannel += dchannels)] = (gdouble) v_result[6];
13533       destination[(current_dchannel += dchannels)] = (gdouble) v_result[7];
13534 
13535       /* iterate destination */
13536       destination += (current_dchannel + dchannels);
13537 
13538       /* iterate source */
13539       source += (current_schannel + schannels);
13540     }
13541   }
13542 #else
13543   /* unrolled function */
13544   if(count > 8){
13545     limit = count - (count % 8);
13546 
13547     for(; i < limit; i += 8){
13548       current_dchannel = 0;
13549       current_schannel = 0;
13550 
13551       destination[0] = ((gdouble) (destination[0] + (gdouble) (source[0] / normalize_divisor)));
13552       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (source[(current_schannel = schannels)] / normalize_divisor)));
13553       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
13554       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
13555       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
13556       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
13557       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
13558       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)] / normalize_divisor)));
13559 
13560       /* iterate destination */
13561       destination += (current_dchannel + dchannels);
13562 
13563       /* iterate source */
13564       source += (current_schannel + schannels);
13565     }
13566   }
13567 #endif
13568 
13569   for(; i < count; i++){
13570     destination[0] = ((gdouble) (destination[0] + (gdouble) (source[0] / normalize_divisor)));
13571 
13572     destination += dchannels;
13573     source += schannels;
13574   }
13575 }
13576 
13577 /**
13578  * ags_audio_buffer_util_copy_float_to_s8:
13579  * @destination: destination buffer
13580  * @dchannels: destination buffer's count of channels
13581  * @source: source buffer
13582  * @schannels: source buffer's count of channels
13583  * @count: number of frames to copy
13584  *
13585  * Copy audio data using additive strategy.
13586  *
13587  * Since: 3.0.0
13588  */
13589 void
ags_audio_buffer_util_copy_float_to_s8(gint8 * destination,guint dchannels,gfloat * source,guint schannels,guint count)13590 ags_audio_buffer_util_copy_float_to_s8(gint8 *destination, guint dchannels,
13591 				       gfloat *source, guint schannels,
13592 				       guint count)
13593 {
13594   //NOTE:JK: scale = (2^bits_source / 2.0 - 1.0)
13595   static const gdouble scale = 127.0;
13596   guint limit;
13597   guint current_dchannel, current_schannel;
13598   guint i;
13599 
13600   if(destination == NULL ||
13601      source == NULL){
13602     return;
13603   }
13604 
13605   i = 0;
13606 
13607 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
13608   /* vectorized function */
13609   if(count > 8){
13610     limit = count - (count % 8);
13611 
13612     for(; i < limit; i += 8){
13613       ags_v8float v_destination;
13614       ags_v8float v_source;
13615 
13616       current_dchannel = 0;
13617       current_schannel = 0;
13618 
13619       v_destination = (ags_v8float) {(gfloat) destination[0],
13620 				     (gfloat) destination[(current_dchannel = dchannels)],
13621 				     (gfloat) destination[(current_dchannel += dchannels)],
13622 				     (gfloat) destination[(current_dchannel += dchannels)],
13623 				     (gfloat) destination[(current_dchannel += dchannels)],
13624 				     (gfloat) destination[(current_dchannel += dchannels)],
13625 				     (gfloat) destination[(current_dchannel += dchannels)],
13626 				     (gfloat) destination[(current_dchannel += dchannels)]};
13627 
13628       v_source = (ags_v8float) {source[0],
13629 				source[(current_schannel = schannels)],
13630 				source[(current_schannel += schannels)],
13631 				source[(current_schannel += schannels)],
13632 				source[(current_schannel += schannels)],
13633 				source[(current_schannel += schannels)],
13634 				source[(current_schannel += schannels)],
13635 				source[(current_schannel += schannels)]};
13636 
13637       /* scale and copy */
13638       v_source *= (gfloat) scale;
13639       v_destination += v_source;
13640 
13641       current_dchannel = 0;
13642 
13643       destination[0] = (gint8) v_destination[0];
13644       destination[(current_dchannel = dchannels)] = (gint8) v_destination[1];
13645       destination[(current_dchannel += dchannels)] = (gint8) v_destination[2];
13646       destination[(current_dchannel += dchannels)] = (gint8) v_destination[3];
13647       destination[(current_dchannel += dchannels)] = (gint8) v_destination[4];
13648       destination[(current_dchannel += dchannels)] = (gint8) v_destination[5];
13649       destination[(current_dchannel += dchannels)] = (gint8) v_destination[6];
13650       destination[(current_dchannel += dchannels)] = (gint8) v_destination[7];
13651 
13652       /* iterate destination */
13653       destination += (current_dchannel + dchannels);
13654 
13655       /* iterate source */
13656       source += (current_schannel + schannels);
13657     }
13658   }
13659 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
13660   /* vectorized function */
13661   if(count > 8){
13662     limit = count - (count % 8);
13663 
13664     for(; i < limit; i += 8){
13665       double v_scaled[8];
13666       double v_result[8];
13667       static const double v_scale[1] = { (double) scale };
13668 
13669       current_dchannel = 0;
13670       current_schannel = 0;
13671 
13672       double v_destination[] = {(double) destination[0],
13673 				(double) destination[(current_dchannel = dchannels)],
13674 				(double) destination[(current_dchannel += dchannels)],
13675 				(double) destination[(current_dchannel += dchannels)],
13676 				(double) destination[(current_dchannel += dchannels)],
13677 				(double) destination[(current_dchannel += dchannels)],
13678 				(double) destination[(current_dchannel += dchannels)],
13679 				(double) destination[(current_dchannel += dchannels)]};
13680 
13681       double v_source[] = {(double) source[0],
13682 			   (double) source[(current_schannel = schannels)],
13683 			   (double) source[(current_schannel += schannels)],
13684 			   (double) source[(current_schannel += schannels)],
13685 			   (double) source[(current_schannel += schannels)],
13686 			   (double) source[(current_schannel += schannels)],
13687 			   (double) source[(current_schannel += schannels)],
13688 			   (double) source[(current_schannel += schannels)]};
13689 
13690       /* scale and copy */
13691       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
13692       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
13693 
13694       current_dchannel = 0;
13695 
13696       destination[0] = (gint8) v_result[0];
13697       destination[(current_dchannel = dchannels)] = (gint8) v_result[1];
13698       destination[(current_dchannel += dchannels)] = (gint8) v_result[2];
13699       destination[(current_dchannel += dchannels)] = (gint8) v_result[3];
13700       destination[(current_dchannel += dchannels)] = (gint8) v_result[4];
13701       destination[(current_dchannel += dchannels)] = (gint8) v_result[5];
13702       destination[(current_dchannel += dchannels)] = (gint8) v_result[6];
13703       destination[(current_dchannel += dchannels)] = (gint8) v_result[7];
13704 
13705       /* iterate destination */
13706       destination += (current_dchannel + dchannels);
13707 
13708       /* iterate source */
13709       source += (current_schannel + schannels);
13710     }
13711   }
13712 #else
13713   /* unrolled function */
13714   if(count > 8){
13715     limit = count - (count % 8);
13716 
13717     for(; i < limit; i += 8){
13718       current_dchannel = 0;
13719       current_schannel = 0;
13720 
13721       destination[0] = 0xff & (gint8) ((gdouble) (destination[0] + (gdouble) (scale * source[0])));
13722       destination[current_dchannel] = 0xff & (gint8) ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (scale * source[(current_schannel = schannels)])));
13723       destination[current_dchannel] = 0xff & (gint8) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
13724       destination[current_dchannel] = 0xff & (gint8) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
13725       destination[current_dchannel] = 0xff & (gint8) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
13726       destination[current_dchannel] = 0xff & (gint8) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
13727       destination[current_dchannel] = 0xff & (gint8) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
13728       destination[current_dchannel] = 0xff & (gint8) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
13729 
13730       /* iterate destination */
13731       destination += (current_dchannel + dchannels);
13732 
13733       /* iterate source */
13734       source += (current_schannel + schannels);
13735     }
13736   }
13737 #endif
13738 
13739   for(; i < count; i++){
13740     destination[0] = 0xff & (gint8) ((gdouble) (destination[0] + (gdouble) (scale * source[0])));
13741 
13742     destination += dchannels;
13743     source += schannels;
13744   }
13745 }
13746 
13747 /**
13748  * ags_audio_buffer_util_copy_float_to_s16:
13749  * @destination: destination buffer
13750  * @dchannels: destination buffer's count of channels
13751  * @source: source buffer
13752  * @schannels: source buffer's count of channels
13753  * @count: number of frames to copy
13754  *
13755  * Copy audio data using additive strategy.
13756  *
13757  * Since: 3.0.0
13758  */
13759 void
ags_audio_buffer_util_copy_float_to_s16(gint16 * destination,guint dchannels,gfloat * source,guint schannels,guint count)13760 ags_audio_buffer_util_copy_float_to_s16(gint16 *destination, guint dchannels,
13761 					gfloat *source, guint schannels,
13762 					guint count)
13763 {
13764   //NOTE:JK: scale = (2^bits_source / 2.0 - 1.0)
13765   static const gdouble scale = 32767.0;
13766   guint limit;
13767   guint current_dchannel, current_schannel;
13768   guint i;
13769 
13770   if(destination == NULL ||
13771      source == NULL){
13772     return;
13773   }
13774 
13775   i = 0;
13776 
13777 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
13778   /* vectorized function */
13779   if(count > 8){
13780     limit = count - (count % 8);
13781 
13782     for(; i < limit; i += 8){
13783       ags_v8float v_destination;
13784       ags_v8float v_source;
13785 
13786       current_dchannel = 0;
13787       current_schannel = 0;
13788 
13789       v_destination = (ags_v8float) {(gfloat) destination[0],
13790 				     (gfloat) destination[(current_dchannel = dchannels)],
13791 				     (gfloat) destination[(current_dchannel += dchannels)],
13792 				     (gfloat) destination[(current_dchannel += dchannels)],
13793 				     (gfloat) destination[(current_dchannel += dchannels)],
13794 				     (gfloat) destination[(current_dchannel += dchannels)],
13795 				     (gfloat) destination[(current_dchannel += dchannels)],
13796 				     (gfloat) destination[(current_dchannel += dchannels)]};
13797 
13798       v_source = (ags_v8float) {source[0],
13799 				source[(current_schannel = schannels)],
13800 				source[(current_schannel += schannels)],
13801 				source[(current_schannel += schannels)],
13802 				source[(current_schannel += schannels)],
13803 				source[(current_schannel += schannels)],
13804 				source[(current_schannel += schannels)],
13805 				source[(current_schannel += schannels)]};
13806 
13807       /* scale and copy */
13808       v_source *= (gfloat) scale;
13809       v_destination += v_source;
13810 
13811       current_dchannel = 0;
13812 
13813       destination[0] = (gint16) v_destination[0];
13814       destination[(current_dchannel = dchannels)] = (gint16) v_destination[1];
13815       destination[(current_dchannel += dchannels)] = (gint16) v_destination[2];
13816       destination[(current_dchannel += dchannels)] = (gint16) v_destination[3];
13817       destination[(current_dchannel += dchannels)] = (gint16) v_destination[4];
13818       destination[(current_dchannel += dchannels)] = (gint16) v_destination[5];
13819       destination[(current_dchannel += dchannels)] = (gint16) v_destination[6];
13820       destination[(current_dchannel += dchannels)] = (gint16) v_destination[7];
13821 
13822       /* iterate destination */
13823       destination += (current_dchannel + dchannels);
13824 
13825       /* iterate source */
13826       source += (current_schannel + schannels);
13827     }
13828   }
13829 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
13830   /* vectorized function */
13831   if(count > 8){
13832     limit = count - (count % 8);
13833 
13834     for(; i < limit; i += 8){
13835       double v_scaled[8];
13836       double v_result[8];
13837       static const double v_scale[1] = { (double) scale };
13838 
13839       current_dchannel = 0;
13840       current_schannel = 0;
13841 
13842       double v_destination[] = {(double) destination[0],
13843 				(double) destination[(current_dchannel = dchannels)],
13844 				(double) destination[(current_dchannel += dchannels)],
13845 				(double) destination[(current_dchannel += dchannels)],
13846 				(double) destination[(current_dchannel += dchannels)],
13847 				(double) destination[(current_dchannel += dchannels)],
13848 				(double) destination[(current_dchannel += dchannels)],
13849 				(double) destination[(current_dchannel += dchannels)]};
13850 
13851       double v_source[] = {(double) source[0],
13852 			   (double) source[(current_schannel = schannels)],
13853 			   (double) source[(current_schannel += schannels)],
13854 			   (double) source[(current_schannel += schannels)],
13855 			   (double) source[(current_schannel += schannels)],
13856 			   (double) source[(current_schannel += schannels)],
13857 			   (double) source[(current_schannel += schannels)],
13858 			   (double) source[(current_schannel += schannels)]};
13859 
13860       /* scale and copy */
13861       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
13862       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
13863 
13864       current_dchannel = 0;
13865 
13866       destination[0] = (gint16) v_result[0];
13867       destination[(current_dchannel = dchannels)] = (gint16) v_result[1];
13868       destination[(current_dchannel += dchannels)] = (gint16) v_result[2];
13869       destination[(current_dchannel += dchannels)] = (gint16) v_result[3];
13870       destination[(current_dchannel += dchannels)] = (gint16) v_result[4];
13871       destination[(current_dchannel += dchannels)] = (gint16) v_result[5];
13872       destination[(current_dchannel += dchannels)] = (gint16) v_result[6];
13873       destination[(current_dchannel += dchannels)] = (gint16) v_result[7];
13874 
13875       /* iterate destination */
13876       destination += (current_dchannel + dchannels);
13877 
13878       /* iterate source */
13879       source += (current_schannel + schannels);
13880     }
13881   }
13882 #else
13883   /* unrolled function */
13884   if(count > 8){
13885     limit = count - (count % 8);
13886 
13887     for(; i < limit; i += 8){
13888       current_dchannel = 0;
13889       current_schannel = 0;
13890 
13891       destination[0] = 0xffff & (gint16) ((gdouble) (destination[0] + (gdouble) (scale * source[0])));
13892       destination[current_dchannel] = 0xffff & (gint16) ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (scale * source[(current_schannel = schannels)])));
13893       destination[current_dchannel] = 0xffff & (gint16) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
13894       destination[current_dchannel] = 0xffff & (gint16) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
13895       destination[current_dchannel] = 0xffff & (gint16) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
13896       destination[current_dchannel] = 0xffff & (gint16) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
13897       destination[current_dchannel] = 0xffff & (gint16) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
13898       destination[current_dchannel] = 0xffff & (gint16) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
13899 
13900       /* iterate destination */
13901       destination += (current_dchannel + dchannels);
13902 
13903       /* iterate source */
13904       source += (current_schannel + schannels);
13905     }
13906   }
13907 #endif
13908 
13909   for(; i < count; i++){
13910     destination[0] = 0xffff & (gint16) ((gdouble) (destination[0] + (gdouble) (scale * source[0])));
13911 
13912     destination += dchannels;
13913     source += schannels;
13914   }
13915 }
13916 
13917 /**
13918  * ags_audio_buffer_util_copy_float_to_s24:
13919  * @destination: destination buffer
13920  * @dchannels: destination buffer's count of channels
13921  * @source: source buffer
13922  * @schannels: source buffer's count of channels
13923  * @count: number of frames to copy
13924  *
13925  * Copy audio data using additive strategy.
13926  *
13927  * Since: 3.0.0
13928  */
13929 void
ags_audio_buffer_util_copy_float_to_s24(gint32 * destination,guint dchannels,gfloat * source,guint schannels,guint count)13930 ags_audio_buffer_util_copy_float_to_s24(gint32 *destination, guint dchannels,
13931 					gfloat *source, guint schannels,
13932 					guint count)
13933 {
13934   //NOTE:JK: scale = (2^bits_source / 2.0 - 1.0)
13935   static const gdouble scale = 8388607.0;
13936   guint limit;
13937   guint current_dchannel, current_schannel;
13938   guint i;
13939 
13940   if(destination == NULL ||
13941      source == NULL){
13942     return;
13943   }
13944 
13945   i = 0;
13946 
13947 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
13948   /* vectorized function */
13949   if(count > 8){
13950     limit = count - (count % 8);
13951 
13952     for(; i < limit; i += 8){
13953       ags_v8float v_destination;
13954       ags_v8float v_source;
13955 
13956       current_dchannel = 0;
13957       current_schannel = 0;
13958 
13959       v_destination = (ags_v8float) {(gfloat) destination[0],
13960 				     (gfloat) destination[(current_dchannel = dchannels)],
13961 				     (gfloat) destination[(current_dchannel += dchannels)],
13962 				     (gfloat) destination[(current_dchannel += dchannels)],
13963 				     (gfloat) destination[(current_dchannel += dchannels)],
13964 				     (gfloat) destination[(current_dchannel += dchannels)],
13965 				     (gfloat) destination[(current_dchannel += dchannels)],
13966 				     (gfloat) destination[(current_dchannel += dchannels)]};
13967 
13968       v_source = (ags_v8float) {source[0],
13969 				source[(current_schannel = schannels)],
13970 				source[(current_schannel += schannels)],
13971 				source[(current_schannel += schannels)],
13972 				source[(current_schannel += schannels)],
13973 				source[(current_schannel += schannels)],
13974 				source[(current_schannel += schannels)],
13975 				source[(current_schannel += schannels)]};
13976 
13977       /* scale and copy */
13978       v_source *= (gfloat) scale;
13979       v_destination += v_source;
13980 
13981       current_dchannel = 0;
13982 
13983       destination[0] = (gint32) v_destination[0];
13984       destination[(current_dchannel = dchannels)] = (gint32) v_destination[1];
13985       destination[(current_dchannel += dchannels)] = (gint32) v_destination[2];
13986       destination[(current_dchannel += dchannels)] = (gint32) v_destination[3];
13987       destination[(current_dchannel += dchannels)] = (gint32) v_destination[4];
13988       destination[(current_dchannel += dchannels)] = (gint32) v_destination[5];
13989       destination[(current_dchannel += dchannels)] = (gint32) v_destination[6];
13990       destination[(current_dchannel += dchannels)] = (gint32) v_destination[7];
13991 
13992       /* iterate destination */
13993       destination += (current_dchannel + dchannels);
13994 
13995       /* iterate source */
13996       source += (current_schannel + schannels);
13997     }
13998   }
13999 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
14000   /* vectorized function */
14001   if(count > 8){
14002     limit = count - (count % 8);
14003 
14004     for(; i < limit; i += 8){
14005       double v_scaled[8];
14006       double v_result[8];
14007       static const double v_scale[1] = { (double) scale };
14008 
14009       current_dchannel = 0;
14010       current_schannel = 0;
14011 
14012       double v_destination[] = {(double) destination[0],
14013 				(double) destination[(current_dchannel = dchannels)],
14014 				(double) destination[(current_dchannel += dchannels)],
14015 				(double) destination[(current_dchannel += dchannels)],
14016 				(double) destination[(current_dchannel += dchannels)],
14017 				(double) destination[(current_dchannel += dchannels)],
14018 				(double) destination[(current_dchannel += dchannels)],
14019 				(double) destination[(current_dchannel += dchannels)]};
14020 
14021       double v_source[] = {(double) source[0],
14022 			   (double) source[(current_schannel = schannels)],
14023 			   (double) source[(current_schannel += schannels)],
14024 			   (double) source[(current_schannel += schannels)],
14025 			   (double) source[(current_schannel += schannels)],
14026 			   (double) source[(current_schannel += schannels)],
14027 			   (double) source[(current_schannel += schannels)],
14028 			   (double) source[(current_schannel += schannels)]};
14029 
14030       /* scale and copy */
14031       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
14032       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
14033 
14034       current_dchannel = 0;
14035 
14036       destination[0] = (gint32) v_result[0];
14037       destination[(current_dchannel = dchannels)] = (gint32) v_result[1];
14038       destination[(current_dchannel += dchannels)] = (gint32) v_result[2];
14039       destination[(current_dchannel += dchannels)] = (gint32) v_result[3];
14040       destination[(current_dchannel += dchannels)] = (gint32) v_result[4];
14041       destination[(current_dchannel += dchannels)] = (gint32) v_result[5];
14042       destination[(current_dchannel += dchannels)] = (gint32) v_result[6];
14043       destination[(current_dchannel += dchannels)] = (gint32) v_result[7];
14044 
14045       /* iterate destination */
14046       destination += (current_dchannel + dchannels);
14047 
14048       /* iterate source */
14049       source += (current_schannel + schannels);
14050     }
14051   }
14052 #else
14053   /* unrolled function */
14054   if(count > 8){
14055     limit = count - (count % 8);
14056 
14057     for(; i < limit; i += 8){
14058       current_dchannel = 0;
14059       current_schannel = 0;
14060 
14061       destination[0] = 0xffffffff & (gint32) ((gdouble) (destination[0] + (gdouble) (scale * source[0])));
14062       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (scale * source[(current_schannel = schannels)])));
14063       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
14064       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
14065       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
14066       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
14067       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
14068       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
14069 
14070       /* iterate destination */
14071       destination += (current_dchannel + dchannels);
14072 
14073       /* iterate source */
14074       source += (current_schannel + schannels);
14075     }
14076   }
14077 #endif
14078 
14079   for(; i < count; i++){
14080     destination[0] = 0xffffffff & (gint32) ((gdouble) (destination[0] + (gdouble) (scale * source[0])));
14081 
14082     destination += dchannels;
14083     source += schannels;
14084   }
14085 }
14086 
14087 /**
14088  * ags_audio_buffer_util_copy_float_to_s32:
14089  * @destination: destination buffer
14090  * @dchannels: destination buffer's count of channels
14091  * @source: source buffer
14092  * @schannels: source buffer's count of channels
14093  * @count: number of frames to copy
14094  *
14095  * Copy audio data using additive strategy.
14096  *
14097  * Since: 3.0.0
14098  */
14099 void
ags_audio_buffer_util_copy_float_to_s32(gint32 * destination,guint dchannels,gfloat * source,guint schannels,guint count)14100 ags_audio_buffer_util_copy_float_to_s32(gint32 *destination, guint dchannels,
14101 					gfloat *source, guint schannels,
14102 					guint count)
14103 {
14104   //NOTE:JK: scale = (2^bits_source / 2.0 - 1.0)
14105   static const gdouble scale = 214748363.0;
14106   guint limit;
14107   guint current_dchannel, current_schannel;
14108   guint i;
14109 
14110   if(destination == NULL ||
14111      source == NULL){
14112     return;
14113   }
14114 
14115   i = 0;
14116 
14117 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
14118   /* vectorized function */
14119   if(count > 8){
14120     limit = count - (count % 8);
14121 
14122     for(; i < limit; i += 8){
14123       ags_v8float v_destination;
14124       ags_v8float v_source;
14125 
14126       current_dchannel = 0;
14127       current_schannel = 0;
14128 
14129       v_destination = (ags_v8float) {(gfloat) destination[0],
14130 				     (gfloat) destination[(current_dchannel = dchannels)],
14131 				     (gfloat) destination[(current_dchannel += dchannels)],
14132 				     (gfloat) destination[(current_dchannel += dchannels)],
14133 				     (gfloat) destination[(current_dchannel += dchannels)],
14134 				     (gfloat) destination[(current_dchannel += dchannels)],
14135 				     (gfloat) destination[(current_dchannel += dchannels)],
14136 				     (gfloat) destination[(current_dchannel += dchannels)]};
14137 
14138       v_source = (ags_v8float) {source[0],
14139 				source[(current_schannel = schannels)],
14140 				source[(current_schannel += schannels)],
14141 				source[(current_schannel += schannels)],
14142 				source[(current_schannel += schannels)],
14143 				source[(current_schannel += schannels)],
14144 				source[(current_schannel += schannels)],
14145 				source[(current_schannel += schannels)]};
14146 
14147       /* scale and copy */
14148       v_source *= (gfloat) scale;
14149       v_destination += v_source;
14150 
14151       current_dchannel = 0;
14152 
14153       destination[0] = (gint32) v_destination[0];
14154       destination[(current_dchannel = dchannels)] = (gint32) v_destination[1];
14155       destination[(current_dchannel += dchannels)] = (gint32) v_destination[2];
14156       destination[(current_dchannel += dchannels)] = (gint32) v_destination[3];
14157       destination[(current_dchannel += dchannels)] = (gint32) v_destination[4];
14158       destination[(current_dchannel += dchannels)] = (gint32) v_destination[5];
14159       destination[(current_dchannel += dchannels)] = (gint32) v_destination[6];
14160       destination[(current_dchannel += dchannels)] = (gint32) v_destination[7];
14161 
14162       /* iterate destination */
14163       destination += (current_dchannel + dchannels);
14164 
14165       /* iterate source */
14166       source += (current_schannel + schannels);
14167     }
14168   }
14169 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
14170   /* vectorized function */
14171   if(count > 8){
14172     limit = count - (count % 8);
14173 
14174     for(; i < limit; i += 8){
14175       double v_scaled[8];
14176       double v_result[8];
14177       static const double v_scale[1] = { (double) scale };
14178 
14179       current_dchannel = 0;
14180       current_schannel = 0;
14181 
14182       double v_destination[] = {(double) destination[0],
14183 				(double) destination[(current_dchannel = dchannels)],
14184 				(double) destination[(current_dchannel += dchannels)],
14185 				(double) destination[(current_dchannel += dchannels)],
14186 				(double) destination[(current_dchannel += dchannels)],
14187 				(double) destination[(current_dchannel += dchannels)],
14188 				(double) destination[(current_dchannel += dchannels)],
14189 				(double) destination[(current_dchannel += dchannels)]};
14190 
14191       double v_source[] = {(double) source[0],
14192 			   (double) source[(current_schannel = schannels)],
14193 			   (double) source[(current_schannel += schannels)],
14194 			   (double) source[(current_schannel += schannels)],
14195 			   (double) source[(current_schannel += schannels)],
14196 			   (double) source[(current_schannel += schannels)],
14197 			   (double) source[(current_schannel += schannels)],
14198 			   (double) source[(current_schannel += schannels)]};
14199 
14200       /* scale and copy */
14201       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
14202       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
14203 
14204       current_dchannel = 0;
14205 
14206       destination[0] = (gint32) v_result[0];
14207       destination[(current_dchannel = dchannels)] = (gint32) v_result[1];
14208       destination[(current_dchannel += dchannels)] = (gint32) v_result[2];
14209       destination[(current_dchannel += dchannels)] = (gint32) v_result[3];
14210       destination[(current_dchannel += dchannels)] = (gint32) v_result[4];
14211       destination[(current_dchannel += dchannels)] = (gint32) v_result[5];
14212       destination[(current_dchannel += dchannels)] = (gint32) v_result[6];
14213       destination[(current_dchannel += dchannels)] = (gint32) v_result[7];
14214 
14215       /* iterate destination */
14216       destination += (current_dchannel + dchannels);
14217 
14218       /* iterate source */
14219       source += (current_schannel + schannels);
14220     }
14221   }
14222 #else
14223   /* unrolled function */
14224   if(count > 8){
14225     limit = count - (count % 8);
14226 
14227     for(; i < limit; i += 8){
14228       current_dchannel = 0;
14229       current_schannel = 0;
14230 
14231       destination[0] = 0xffffffff & (gint32) ((gdouble) (destination[0] + (gdouble) (scale * source[0])));
14232       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (scale * source[(current_schannel = schannels)])));
14233       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
14234       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
14235       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
14236       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
14237       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
14238       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
14239 
14240       /* iterate destination */
14241       destination += (current_dchannel + dchannels);
14242 
14243       /* iterate source */
14244       source += (current_schannel + schannels);
14245     }
14246   }
14247 #endif
14248 
14249   for(; i < count; i++){
14250     destination[0] = 0xffffffff & (gint32) ((gdouble) (destination[0] + (gdouble) (scale * source[0])));
14251 
14252     destination += dchannels;
14253     source += schannels;
14254   }
14255 }
14256 
14257 /**
14258  * ags_audio_buffer_util_copy_float_to_s64:
14259  * @destination: destination buffer
14260  * @dchannels: destination buffer's count of channels
14261  * @source: source buffer
14262  * @schannels: source buffer's count of channels
14263  * @count: number of frames to copy
14264  *
14265  * Copy audio data using additive strategy.
14266  *
14267  * Since: 3.0.0
14268  */
14269 void
ags_audio_buffer_util_copy_float_to_s64(gint64 * destination,guint dchannels,gfloat * source,guint schannels,guint count)14270 ags_audio_buffer_util_copy_float_to_s64(gint64 *destination, guint dchannels,
14271 					gfloat *source, guint schannels,
14272 					guint count)
14273 {
14274   //NOTE:JK: scale = (2^bits_source / 2.0 - 1.0)
14275   static const gdouble scale = 9223372036854775807.0;
14276   guint limit;
14277   guint current_dchannel, current_schannel;
14278   guint i;
14279 
14280   if(destination == NULL ||
14281      source == NULL){
14282     return;
14283   }
14284 
14285   i = 0;
14286 
14287 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
14288   /* vectorized function */
14289   if(count > 8){
14290     limit = count - (count % 8);
14291 
14292     for(; i < limit; i += 8){
14293       ags_v8float v_destination;
14294       ags_v8float v_source;
14295 
14296       current_dchannel = 0;
14297       current_schannel = 0;
14298 
14299       v_destination = (ags_v8float) {(gfloat) destination[0],
14300 				     (gfloat) destination[(current_dchannel = dchannels)],
14301 				     (gfloat) destination[(current_dchannel += dchannels)],
14302 				     (gfloat) destination[(current_dchannel += dchannels)],
14303 				     (gfloat) destination[(current_dchannel += dchannels)],
14304 				     (gfloat) destination[(current_dchannel += dchannels)],
14305 				     (gfloat) destination[(current_dchannel += dchannels)],
14306 				     (gfloat) destination[(current_dchannel += dchannels)]};
14307 
14308       v_source = (ags_v8float) {source[0],
14309 				source[(current_schannel = schannels)],
14310 				source[(current_schannel += schannels)],
14311 				source[(current_schannel += schannels)],
14312 				source[(current_schannel += schannels)],
14313 				source[(current_schannel += schannels)],
14314 				source[(current_schannel += schannels)],
14315 				source[(current_schannel += schannels)]};
14316 
14317       /* scale and copy */
14318       v_source *= (gfloat) scale;
14319       v_destination += v_source;
14320 
14321       current_dchannel = 0;
14322 
14323       destination[0] = (gint64) v_destination[0];
14324       destination[(current_dchannel = dchannels)] = (gint64) v_destination[1];
14325       destination[(current_dchannel += dchannels)] = (gint64) v_destination[2];
14326       destination[(current_dchannel += dchannels)] = (gint64) v_destination[3];
14327       destination[(current_dchannel += dchannels)] = (gint64) v_destination[4];
14328       destination[(current_dchannel += dchannels)] = (gint64) v_destination[5];
14329       destination[(current_dchannel += dchannels)] = (gint64) v_destination[6];
14330       destination[(current_dchannel += dchannels)] = (gint64) v_destination[7];
14331 
14332       /* iterate destination */
14333       destination += (current_dchannel + dchannels);
14334 
14335       /* iterate source */
14336       source += (current_schannel + schannels);
14337     }
14338   }
14339 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
14340   /* vectorized function */
14341   if(count > 8){
14342     limit = count - (count % 8);
14343 
14344     for(; i < limit; i += 8){
14345       double v_scaled[8];
14346       double v_result[8];
14347       static const double v_scale[1] = { (double) scale };
14348 
14349       current_dchannel = 0;
14350       current_schannel = 0;
14351 
14352       double v_destination[] = {(double) destination[0],
14353 				(double) destination[(current_dchannel = dchannels)],
14354 				(double) destination[(current_dchannel += dchannels)],
14355 				(double) destination[(current_dchannel += dchannels)],
14356 				(double) destination[(current_dchannel += dchannels)],
14357 				(double) destination[(current_dchannel += dchannels)],
14358 				(double) destination[(current_dchannel += dchannels)],
14359 				(double) destination[(current_dchannel += dchannels)]};
14360 
14361       double v_source[] = {(double) source[0],
14362 			   (double) source[(current_schannel = schannels)],
14363 			   (double) source[(current_schannel += schannels)],
14364 			   (double) source[(current_schannel += schannels)],
14365 			   (double) source[(current_schannel += schannels)],
14366 			   (double) source[(current_schannel += schannels)],
14367 			   (double) source[(current_schannel += schannels)],
14368 			   (double) source[(current_schannel += schannels)]};
14369 
14370       /* scale and copy */
14371       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
14372       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
14373 
14374       current_dchannel = 0;
14375 
14376       destination[0] = (gint64) v_result[0];
14377       destination[(current_dchannel = dchannels)] = (gint64) v_result[1];
14378       destination[(current_dchannel += dchannels)] = (gint64) v_result[2];
14379       destination[(current_dchannel += dchannels)] = (gint64) v_result[3];
14380       destination[(current_dchannel += dchannels)] = (gint64) v_result[4];
14381       destination[(current_dchannel += dchannels)] = (gint64) v_result[5];
14382       destination[(current_dchannel += dchannels)] = (gint64) v_result[6];
14383       destination[(current_dchannel += dchannels)] = (gint64) v_result[7];
14384 
14385       /* iterate destination */
14386       destination += (current_dchannel + dchannels);
14387 
14388       /* iterate source */
14389       source += (current_schannel + schannels);
14390     }
14391   }
14392 #else
14393   /* unrolled function */
14394   if(count > 8){
14395     limit = count - (count % 8);
14396 
14397     for(; i < limit; i += 8){
14398       current_dchannel = 0;
14399       current_schannel = 0;
14400 
14401       destination[0] = 0xffffffffffffffff & (gint64) ((gdouble) (destination[0] + (gdouble) (scale * source[0])));
14402       destination[current_dchannel] = 0xffffffffffffffff & (gint64) ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (scale * source[(current_schannel = schannels)])));
14403       destination[current_dchannel] = 0xffffffffffffffff & (gint64) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
14404       destination[current_dchannel] = 0xffffffffffffffff & (gint64) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
14405       destination[current_dchannel] = 0xffffffffffffffff & (gint64) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
14406       destination[current_dchannel] = 0xffffffffffffffff & (gint64) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
14407       destination[current_dchannel] = 0xffffffffffffffff & (gint64) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
14408       destination[current_dchannel] = 0xffffffffffffffff & (gint64) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
14409 
14410       /* iterate destination */
14411       destination += (current_dchannel + dchannels);
14412 
14413       /* iterate source */
14414       source += (current_schannel + schannels);
14415     }
14416   }
14417 #endif
14418 
14419   for(; i < count; i++){
14420     destination[0] = 0xffffffffffffffff & (gint64) ((gdouble) (destination[0] + (gdouble) (scale * source[0])));
14421 
14422     destination += dchannels;
14423     source += schannels;
14424   }
14425 }
14426 
14427 /**
14428  * ags_audio_buffer_util_copy_float_to_float:
14429  * @destination: destination buffer
14430  * @dchannels: destination buffer's count of channels
14431  * @source: source buffer
14432  * @schannels: source buffer's count of channels
14433  * @count: number of frames to copy
14434  *
14435  * Copy audio data using additive strategy.
14436  *
14437  * Since: 3.0.0
14438  */
14439 void
ags_audio_buffer_util_copy_float_to_float(gfloat * destination,guint dchannels,gfloat * source,guint schannels,guint count)14440 ags_audio_buffer_util_copy_float_to_float(gfloat *destination, guint dchannels,
14441 					  gfloat *source, guint schannels,
14442 					  guint count)
14443 {
14444   guint limit;
14445   guint current_dchannel, current_schannel;
14446   guint i;
14447 
14448   if(destination == NULL ||
14449      source == NULL){
14450     return;
14451   }
14452 
14453   i = 0;
14454 
14455 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
14456   /* vectorized function */
14457   if(count > 8){
14458     limit = count - (count % 8);
14459 
14460     for(; i < limit; i += 8){
14461       ags_v8float v_destination;
14462       ags_v8float v_source;
14463 
14464       current_dchannel = 0;
14465       current_schannel = 0;
14466 
14467       v_destination = (ags_v8float) {destination[0],
14468 				     destination[(current_dchannel = dchannels)],
14469 				     destination[(current_dchannel += dchannels)],
14470 				     destination[(current_dchannel += dchannels)],
14471 				     destination[(current_dchannel += dchannels)],
14472 				     destination[(current_dchannel += dchannels)],
14473 				     destination[(current_dchannel += dchannels)],
14474 				     destination[(current_dchannel += dchannels)]};
14475 
14476       v_source = (ags_v8float) {source[0],
14477 				source[(current_schannel = schannels)],
14478 				source[(current_schannel += schannels)],
14479 				source[(current_schannel += schannels)],
14480 				source[(current_schannel += schannels)],
14481 				source[(current_schannel += schannels)],
14482 				source[(current_schannel += schannels)],
14483 				source[(current_schannel += schannels)]};
14484 
14485       /* just copy */
14486       v_destination += v_source;
14487 
14488       current_dchannel = 0;
14489 
14490       destination[0] = v_destination[0];
14491       destination[(current_dchannel = dchannels)] = v_destination[1];
14492       destination[(current_dchannel += dchannels)] = v_destination[2];
14493       destination[(current_dchannel += dchannels)] = v_destination[3];
14494       destination[(current_dchannel += dchannels)] = v_destination[4];
14495       destination[(current_dchannel += dchannels)] = v_destination[5];
14496       destination[(current_dchannel += dchannels)] = v_destination[6];
14497       destination[(current_dchannel += dchannels)] = v_destination[7];
14498 
14499       /* iterate destination */
14500       destination += (current_dchannel + dchannels);
14501 
14502       /* iterate source */
14503       source += (current_schannel + schannels);
14504     }
14505   }
14506 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
14507   /* vectorized function */
14508   if(count > 8){
14509     limit = count - (count % 8);
14510 
14511     for(; i < limit; i += 8){
14512       double v_result[8];
14513 
14514       current_dchannel = 0;
14515       current_schannel = 0;
14516 
14517       double v_destination[] = {(double) destination[0],
14518 				(double) destination[(current_dchannel = dchannels)],
14519 				(double) destination[(current_dchannel += dchannels)],
14520 				(double) destination[(current_dchannel += dchannels)],
14521 				(double) destination[(current_dchannel += dchannels)],
14522 				(double) destination[(current_dchannel += dchannels)],
14523 				(double) destination[(current_dchannel += dchannels)],
14524 				(double) destination[(current_dchannel += dchannels)]};
14525 
14526       double v_source[] = {(double) source[0],
14527 			   (double) source[(current_schannel = schannels)],
14528 			   (double) source[(current_schannel += schannels)],
14529 			   (double) source[(current_schannel += schannels)],
14530 			   (double) source[(current_schannel += schannels)],
14531 			   (double) source[(current_schannel += schannels)],
14532 			   (double) source[(current_schannel += schannels)],
14533 			   (double) source[(current_schannel += schannels)]};
14534 
14535       /* just copy */
14536       vDSP_vaddD(v_destination, 1, v_source, 1, v_result, 1, 8);
14537 
14538       current_dchannel = 0;
14539 
14540       destination[0] = (gfloat) v_result[0];
14541       destination[(current_dchannel = dchannels)] = (gfloat) v_result[1];
14542       destination[(current_dchannel += dchannels)] = (gfloat) v_result[2];
14543       destination[(current_dchannel += dchannels)] = (gfloat) v_result[3];
14544       destination[(current_dchannel += dchannels)] = (gfloat) v_result[4];
14545       destination[(current_dchannel += dchannels)] = (gfloat) v_result[5];
14546       destination[(current_dchannel += dchannels)] = (gfloat) v_result[6];
14547       destination[(current_dchannel += dchannels)] = (gfloat) v_result[7];
14548 
14549       /* iterate destination */
14550       destination += (current_dchannel + dchannels);
14551 
14552       /* iterate source */
14553       source += (current_schannel + schannels);
14554     }
14555   }
14556 #else
14557   /* unrolled function */
14558   if(count > 8){
14559     limit = count - (count % 8);
14560 
14561     for(; i < limit; i += 8){
14562       destination[0] = (gfloat) ((gdouble) (destination[0] + (gdouble) (source[0])));
14563       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (source[(current_schannel = schannels)])));
14564       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
14565       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
14566       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
14567       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
14568       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
14569       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
14570 
14571       /* iterate destination */
14572       destination += (current_dchannel + dchannels);
14573 
14574       /* iterate source */
14575       source += (current_schannel + schannels);
14576     }
14577   }
14578 #endif
14579 
14580   for(; i < count; i++){
14581     destination[0] = (gfloat) ((gdouble) (destination[0] + (gdouble) (source[0])));
14582 
14583     destination += dchannels;
14584     source += schannels;
14585   }
14586 }
14587 
14588 /**
14589  * ags_audio_buffer_util_copy_float_to_double:
14590  * @destination: destination buffer
14591  * @dchannels: destination buffer's count of channels
14592  * @source: source buffer
14593  * @schannels: source buffer's count of channels
14594  * @count: number of frames to copy
14595  *
14596  * Copy audio data using additive strategy.
14597  *
14598  * Since: 3.0.0
14599  */
14600 void
ags_audio_buffer_util_copy_float_to_double(gdouble * destination,guint dchannels,gfloat * source,guint schannels,guint count)14601 ags_audio_buffer_util_copy_float_to_double(gdouble *destination, guint dchannels,
14602 					   gfloat *source, guint schannels,
14603 					   guint count)
14604 {
14605   guint limit;
14606   guint current_dchannel, current_schannel;
14607   guint i;
14608 
14609   if(destination == NULL ||
14610      source == NULL){
14611     return;
14612   }
14613 
14614   i = 0;
14615 
14616 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
14617   /* vectorized function */
14618   if(count > 8){
14619     limit = count - (count % 8);
14620 
14621     for(; i < limit; i += 8){
14622       ags_v8double v_destination;
14623       ags_v8double v_source;
14624 
14625       current_dchannel = 0;
14626       current_schannel = 0;
14627 
14628       v_destination = (ags_v8double) {destination[0],
14629 				      destination[(current_dchannel = dchannels)],
14630 				      destination[(current_dchannel += dchannels)],
14631 				      destination[(current_dchannel += dchannels)],
14632 				      destination[(current_dchannel += dchannels)],
14633 				      destination[(current_dchannel += dchannels)],
14634 				      destination[(current_dchannel += dchannels)],
14635 				      destination[(current_dchannel += dchannels)]};
14636 
14637       v_source = (ags_v8double) {(gdouble) source[0],
14638 				 (gdouble) source[(current_schannel = schannels)],
14639 				 (gdouble) source[(current_schannel += schannels)],
14640 				 (gdouble) source[(current_schannel += schannels)],
14641 				 (gdouble) source[(current_schannel += schannels)],
14642 				 (gdouble) source[(current_schannel += schannels)],
14643 				 (gdouble) source[(current_schannel += schannels)],
14644 				 (gdouble) source[(current_schannel += schannels)]};
14645 
14646       /* just copy */
14647       v_destination += v_source;
14648 
14649       current_dchannel = 0;
14650 
14651       destination[0] = v_destination[0];
14652       destination[(current_dchannel = dchannels)] = v_destination[1];
14653       destination[(current_dchannel += dchannels)] = v_destination[2];
14654       destination[(current_dchannel += dchannels)] = v_destination[3];
14655       destination[(current_dchannel += dchannels)] = v_destination[4];
14656       destination[(current_dchannel += dchannels)] = v_destination[5];
14657       destination[(current_dchannel += dchannels)] = v_destination[6];
14658       destination[(current_dchannel += dchannels)] = v_destination[7];
14659 
14660       /* iterate destination */
14661       destination += (current_dchannel + dchannels);
14662 
14663       /* iterate source */
14664       source += (current_schannel + schannels);
14665     }
14666   }
14667 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
14668   /* vectorized function */
14669   if(count > 8){
14670     limit = count - (count % 8);
14671 
14672     for(; i < limit; i += 8){
14673       double v_result[8];
14674 
14675       current_dchannel = 0;
14676       current_schannel = 0;
14677 
14678       double v_destination[] = {(double) destination[0],
14679 				(double) destination[(current_dchannel = dchannels)],
14680 				(double) destination[(current_dchannel += dchannels)],
14681 				(double) destination[(current_dchannel += dchannels)],
14682 				(double) destination[(current_dchannel += dchannels)],
14683 				(double) destination[(current_dchannel += dchannels)],
14684 				(double) destination[(current_dchannel += dchannels)],
14685 				(double) destination[(current_dchannel += dchannels)]};
14686 
14687       double v_source[] = {(double) source[0],
14688 			   (double) source[(current_schannel = schannels)],
14689 			   (double) source[(current_schannel += schannels)],
14690 			   (double) source[(current_schannel += schannels)],
14691 			   (double) source[(current_schannel += schannels)],
14692 			   (double) source[(current_schannel += schannels)],
14693 			   (double) source[(current_schannel += schannels)],
14694 			   (double) source[(current_schannel += schannels)]};
14695 
14696       /* just copy */
14697       vDSP_vaddD(v_destination, 1, v_source, 1, v_result, 1, 8);
14698 
14699       current_dchannel = 0;
14700 
14701       destination[0] = (gdouble) v_result[0];
14702       destination[(current_dchannel = dchannels)] = (gdouble) v_result[1];
14703       destination[(current_dchannel += dchannels)] = (gdouble) v_result[2];
14704       destination[(current_dchannel += dchannels)] = (gdouble) v_result[3];
14705       destination[(current_dchannel += dchannels)] = (gdouble) v_result[4];
14706       destination[(current_dchannel += dchannels)] = (gdouble) v_result[5];
14707       destination[(current_dchannel += dchannels)] = (gdouble) v_result[6];
14708       destination[(current_dchannel += dchannels)] = (gdouble) v_result[7];
14709 
14710       /* iterate destination */
14711       destination += (current_dchannel + dchannels);
14712 
14713       /* iterate source */
14714       source += (current_schannel + schannels);
14715     }
14716   }
14717 #else
14718   /* unrolled function */
14719   if(count > 8){
14720     limit = count - (count % 8);
14721 
14722     for(; i < limit; i += 8){
14723       destination[0] = ((gdouble) (destination[0] + (gdouble) (source[0])));
14724       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (source[(current_schannel = schannels)])));
14725       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
14726       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
14727       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
14728       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
14729       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
14730       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
14731 
14732       /* iterate destination */
14733       destination += (current_dchannel + dchannels);
14734 
14735       /* iterate source */
14736       source += (current_schannel + schannels);
14737     }
14738   }
14739 #endif
14740 
14741   for(; i < count; i++){
14742     destination[0] = ((gdouble) (destination[0] + (gdouble) (source[0])));
14743 
14744     destination += dchannels;
14745     source += schannels;
14746   }
14747 }
14748 
14749 /**
14750  * ags_audio_buffer_util_copy_double_to_s8:
14751  * @destination: destination buffer
14752  * @dchannels: destination buffer's count of channels
14753  * @source: source buffer
14754  * @schannels: source buffer's count of channels
14755  * @count: number of frames to copy
14756  *
14757  * Copy audio data using additive strategy.
14758  *
14759  * Since: 3.0.0
14760  */
14761 void
ags_audio_buffer_util_copy_double_to_s8(gint8 * destination,guint dchannels,gdouble * source,guint schannels,guint count)14762 ags_audio_buffer_util_copy_double_to_s8(gint8 *destination, guint dchannels,
14763 					gdouble *source, guint schannels,
14764 					guint count)
14765 {
14766   //NOTE:JK: scale = (2^bits_source / 2.0 - 1.0)
14767   static const gdouble scale = 127.0;
14768   guint limit;
14769   guint current_dchannel, current_schannel;
14770   guint i;
14771 
14772   if(destination == NULL ||
14773      source == NULL){
14774     return;
14775   }
14776 
14777   i = 0;
14778 
14779 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
14780   /* vectorized function */
14781   if(count > 8){
14782     limit = count - (count % 8);
14783 
14784     for(; i < limit; i += 8){
14785       ags_v8double v_destination;
14786       ags_v8double v_source;
14787 
14788       current_dchannel = 0;
14789       current_schannel = 0;
14790 
14791       v_destination = (ags_v8double) {(gdouble) destination[0],
14792 				      (gdouble) destination[(current_dchannel = dchannels)],
14793 				      (gdouble) destination[(current_dchannel += dchannels)],
14794 				      (gdouble) destination[(current_dchannel += dchannels)],
14795 				      (gdouble) destination[(current_dchannel += dchannels)],
14796 				      (gdouble) destination[(current_dchannel += dchannels)],
14797 				      (gdouble) destination[(current_dchannel += dchannels)],
14798 				      (gdouble) destination[(current_dchannel += dchannels)]};
14799 
14800       v_source = (ags_v8double) {source[0],
14801 				 source[(current_schannel = schannels)],
14802 				 source[(current_schannel += schannels)],
14803 				 source[(current_schannel += schannels)],
14804 				 source[(current_schannel += schannels)],
14805 				 source[(current_schannel += schannels)],
14806 				 source[(current_schannel += schannels)],
14807 				 source[(current_schannel += schannels)]};
14808 
14809       /* scale and copy */
14810       v_source *= scale;
14811       v_destination += v_source;
14812 
14813       current_dchannel = 0;
14814 
14815       destination[0] = (gint8) v_destination[0];
14816       destination[(current_dchannel = dchannels)] = (gint8) v_destination[1];
14817       destination[(current_dchannel += dchannels)] = (gint8) v_destination[2];
14818       destination[(current_dchannel += dchannels)] = (gint8) v_destination[3];
14819       destination[(current_dchannel += dchannels)] = (gint8) v_destination[4];
14820       destination[(current_dchannel += dchannels)] = (gint8) v_destination[5];
14821       destination[(current_dchannel += dchannels)] = (gint8) v_destination[6];
14822       destination[(current_dchannel += dchannels)] = (gint8) v_destination[7];
14823 
14824       /* iterate destination */
14825       destination += (current_dchannel + dchannels);
14826 
14827       /* iterate source */
14828       source += (current_schannel + schannels);
14829     }
14830   }
14831 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
14832   /* vectorized function */
14833   if(count > 8){
14834     limit = count - (count % 8);
14835 
14836     for(; i < limit; i += 8){
14837       double v_scaled[8];
14838       double v_result[8];
14839       static const double v_scale[1] = { (double) scale };
14840 
14841       current_dchannel = 0;
14842       current_schannel = 0;
14843 
14844       double v_destination[] = {(double) destination[0],
14845 				(double) destination[(current_dchannel = dchannels)],
14846 				(double) destination[(current_dchannel += dchannels)],
14847 				(double) destination[(current_dchannel += dchannels)],
14848 				(double) destination[(current_dchannel += dchannels)],
14849 				(double) destination[(current_dchannel += dchannels)],
14850 				(double) destination[(current_dchannel += dchannels)],
14851 				(double) destination[(current_dchannel += dchannels)]};
14852 
14853       double v_source[] = {(double) source[0],
14854 			   (double) source[(current_schannel = schannels)],
14855 			   (double) source[(current_schannel += schannels)],
14856 			   (double) source[(current_schannel += schannels)],
14857 			   (double) source[(current_schannel += schannels)],
14858 			   (double) source[(current_schannel += schannels)],
14859 			   (double) source[(current_schannel += schannels)],
14860 			   (double) source[(current_schannel += schannels)]};
14861 
14862       /* scale and copy */
14863       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
14864       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
14865 
14866       current_dchannel = 0;
14867 
14868       destination[0] = (gint8) v_result[0];
14869       destination[(current_dchannel = dchannels)] = (gint8) v_result[1];
14870       destination[(current_dchannel += dchannels)] = (gint8) v_result[2];
14871       destination[(current_dchannel += dchannels)] = (gint8) v_result[3];
14872       destination[(current_dchannel += dchannels)] = (gint8) v_result[4];
14873       destination[(current_dchannel += dchannels)] = (gint8) v_result[5];
14874       destination[(current_dchannel += dchannels)] = (gint8) v_result[6];
14875       destination[(current_dchannel += dchannels)] = (gint8) v_result[7];
14876 
14877       /* iterate destination */
14878       destination += (current_dchannel + dchannels);
14879 
14880       /* iterate source */
14881       source += (current_schannel + schannels);
14882     }
14883   }
14884 #else
14885   /* unrolled function */
14886   if(count > 8){
14887     limit = count - (count % 8);
14888 
14889     for(; i < limit; i += 8){
14890       current_dchannel = 0;
14891       current_schannel = 0;
14892 
14893       destination[0] = 0xff & (gint8) ((gdouble) (destination[0] + (gdouble) (scale * source[0])));
14894       destination[current_dchannel] = 0xff & (gint8) ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (scale * source[(current_schannel = schannels)])));
14895       destination[current_dchannel] = 0xff & (gint8) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
14896       destination[current_dchannel] = 0xff & (gint8) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
14897       destination[current_dchannel] = 0xff & (gint8) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
14898       destination[current_dchannel] = 0xff & (gint8) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
14899       destination[current_dchannel] = 0xff & (gint8) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
14900       destination[current_dchannel] = 0xff & (gint8) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
14901 
14902       /* iterate destination */
14903       destination += (current_dchannel + dchannels);
14904 
14905       /* iterate source */
14906       source += (current_schannel + schannels);
14907     }
14908   }
14909 #endif
14910 
14911   for(; i < count; i++){
14912     destination[0] = 0xff & (gint8) ((gdouble) (destination[0] + (gdouble) (scale * source[0])));
14913 
14914     destination += dchannels;
14915     source += schannels;
14916   }
14917 }
14918 
14919 /**
14920  * ags_audio_buffer_util_copy_double_to_s16:
14921  * @destination: destination buffer
14922  * @dchannels: destination buffer's count of channels
14923  * @source: source buffer
14924  * @schannels: source buffer's count of channels
14925  * @count: number of frames to copy
14926  *
14927  * Copy audio data using additive strategy.
14928  *
14929  * Since: 3.0.0
14930  */
14931 void
ags_audio_buffer_util_copy_double_to_s16(gint16 * destination,guint dchannels,gdouble * source,guint schannels,guint count)14932 ags_audio_buffer_util_copy_double_to_s16(gint16 *destination, guint dchannels,
14933 					 gdouble *source, guint schannels,
14934 					 guint count)
14935 {
14936   //NOTE:JK: scale = (2^bits_source / 2.0 - 1.0)
14937   static const gdouble scale = 32767.0;
14938   guint limit;
14939   guint current_dchannel, current_schannel;
14940   guint i;
14941 
14942   if(destination == NULL ||
14943      source == NULL){
14944     return;
14945   }
14946 
14947   i = 0;
14948 
14949 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
14950   /* vectorized function */
14951   if(count > 8){
14952     limit = count - (count % 8);
14953 
14954     for(; i < limit; i += 8){
14955       ags_v8double v_destination;
14956       ags_v8double v_source;
14957 
14958       current_dchannel = 0;
14959       current_schannel = 0;
14960 
14961       v_destination = (ags_v8double) {(gdouble) destination[0],
14962 				      (gdouble) destination[(current_dchannel = dchannels)],
14963 				      (gdouble) destination[(current_dchannel += dchannels)],
14964 				      (gdouble) destination[(current_dchannel += dchannels)],
14965 				      (gdouble) destination[(current_dchannel += dchannels)],
14966 				      (gdouble) destination[(current_dchannel += dchannels)],
14967 				      (gdouble) destination[(current_dchannel += dchannels)],
14968 				      (gdouble) destination[(current_dchannel += dchannels)]};
14969 
14970       v_source = (ags_v8double) {source[0],
14971 				 source[(current_schannel = schannels)],
14972 				 source[(current_schannel += schannels)],
14973 				 source[(current_schannel += schannels)],
14974 				 source[(current_schannel += schannels)],
14975 				 source[(current_schannel += schannels)],
14976 				 source[(current_schannel += schannels)],
14977 				 source[(current_schannel += schannels)]};
14978 
14979       /* scale and copy */
14980       v_source *= scale;
14981       v_destination += v_source;
14982 
14983       current_dchannel = 0;
14984 
14985       destination[0] = (gint16) v_destination[0];
14986       destination[(current_dchannel = dchannels)] = (gint16) v_destination[1];
14987       destination[(current_dchannel += dchannels)] = (gint16) v_destination[2];
14988       destination[(current_dchannel += dchannels)] = (gint16) v_destination[3];
14989       destination[(current_dchannel += dchannels)] = (gint16) v_destination[4];
14990       destination[(current_dchannel += dchannels)] = (gint16) v_destination[5];
14991       destination[(current_dchannel += dchannels)] = (gint16) v_destination[6];
14992       destination[(current_dchannel += dchannels)] = (gint16) v_destination[7];
14993 
14994       /* iterate destination */
14995       destination += (current_dchannel + dchannels);
14996 
14997       /* iterate source */
14998       source += (current_schannel + schannels);
14999     }
15000   }
15001 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
15002   /* vectorized function */
15003   if(count > 8){
15004     limit = count - (count % 8);
15005 
15006     for(; i < limit; i += 8){
15007       double v_scaled[8];
15008       double v_result[8];
15009       static const double v_scale[1] = { (double) scale };
15010 
15011       current_dchannel = 0;
15012       current_schannel = 0;
15013 
15014       double v_destination[] = {(double) destination[0],
15015 				(double) destination[(current_dchannel = dchannels)],
15016 				(double) destination[(current_dchannel += dchannels)],
15017 				(double) destination[(current_dchannel += dchannels)],
15018 				(double) destination[(current_dchannel += dchannels)],
15019 				(double) destination[(current_dchannel += dchannels)],
15020 				(double) destination[(current_dchannel += dchannels)],
15021 				(double) destination[(current_dchannel += dchannels)]};
15022 
15023       double v_source[] = {(double) source[0],
15024 			   (double) source[(current_schannel = schannels)],
15025 			   (double) source[(current_schannel += schannels)],
15026 			   (double) source[(current_schannel += schannels)],
15027 			   (double) source[(current_schannel += schannels)],
15028 			   (double) source[(current_schannel += schannels)],
15029 			   (double) source[(current_schannel += schannels)],
15030 			   (double) source[(current_schannel += schannels)]};
15031 
15032       /* scale and copy */
15033       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
15034       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
15035 
15036       current_dchannel = 0;
15037 
15038       destination[0] = (gint16) v_result[0];
15039       destination[(current_dchannel = dchannels)] = (gint16) v_result[1];
15040       destination[(current_dchannel += dchannels)] = (gint16) v_result[2];
15041       destination[(current_dchannel += dchannels)] = (gint16) v_result[3];
15042       destination[(current_dchannel += dchannels)] = (gint16) v_result[4];
15043       destination[(current_dchannel += dchannels)] = (gint16) v_result[5];
15044       destination[(current_dchannel += dchannels)] = (gint16) v_result[6];
15045       destination[(current_dchannel += dchannels)] = (gint16) v_result[7];
15046 
15047       /* iterate destination */
15048       destination += (current_dchannel + dchannels);
15049 
15050       /* iterate source */
15051       source += (current_schannel + schannels);
15052     }
15053   }
15054 #else
15055   /* unrolled function */
15056   if(count > 8){
15057     limit = count - (count % 8);
15058 
15059     for(; i < limit; i += 8){
15060       current_dchannel = 0;
15061       current_schannel = 0;
15062 
15063       destination[0] = 0xffff & (gint16) ((gdouble) (destination[0] + (gdouble) (scale * source[0])));
15064       destination[current_dchannel] = 0xffff & (gint16) ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (scale * source[(current_schannel = schannels)])));
15065       destination[current_dchannel] = 0xffff & (gint16) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
15066       destination[current_dchannel] = 0xffff & (gint16) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
15067       destination[current_dchannel] = 0xffff & (gint16) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
15068       destination[current_dchannel] = 0xffff & (gint16) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
15069       destination[current_dchannel] = 0xffff & (gint16) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
15070       destination[current_dchannel] = 0xffff & (gint16) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
15071 
15072       /* iterate destination */
15073       destination += (current_dchannel + dchannels);
15074 
15075       /* iterate source */
15076       source += (current_schannel + schannels);
15077     }
15078   }
15079 #endif
15080 
15081   for(; i < count; i++){
15082     destination[0] = 0xffff & (gint16) ((gdouble) (destination[0] + (gdouble) (scale * source[0])));
15083 
15084     destination += dchannels;
15085     source += schannels;
15086   }
15087 }
15088 
15089 /**
15090  * ags_audio_buffer_util_copy_double_to_s24:
15091  * @destination: destination buffer
15092  * @dchannels: destination buffer's count of channels
15093  * @source: source buffer
15094  * @schannels: source buffer's count of channels
15095  * @count: number of frames to copy
15096  *
15097  * Copy audio data using additive strategy.
15098  *
15099  * Since: 3.0.0
15100  */
15101 void
ags_audio_buffer_util_copy_double_to_s24(gint32 * destination,guint dchannels,gdouble * source,guint schannels,guint count)15102 ags_audio_buffer_util_copy_double_to_s24(gint32 *destination, guint dchannels,
15103 					 gdouble *source, guint schannels,
15104 					 guint count)
15105 {
15106   //NOTE:JK: scale = (2^bits_source / 2.0 - 1.0)
15107   static const gdouble scale = 8388607.0;
15108   guint limit;
15109   guint current_dchannel, current_schannel;
15110   guint i;
15111 
15112   if(destination == NULL ||
15113      source == NULL){
15114     return;
15115   }
15116 
15117   i = 0;
15118 
15119 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
15120   /* vectorized function */
15121   if(count > 8){
15122     limit = count - (count % 8);
15123 
15124     for(; i < limit; i += 8){
15125       ags_v8double v_destination;
15126       ags_v8double v_source;
15127 
15128       current_dchannel = 0;
15129       current_schannel = 0;
15130 
15131       v_destination = (ags_v8double) {(gdouble) destination[0],
15132 				      (gdouble) destination[(current_dchannel = dchannels)],
15133 				      (gdouble) destination[(current_dchannel += dchannels)],
15134 				      (gdouble) destination[(current_dchannel += dchannels)],
15135 				      (gdouble) destination[(current_dchannel += dchannels)],
15136 				      (gdouble) destination[(current_dchannel += dchannels)],
15137 				      (gdouble) destination[(current_dchannel += dchannels)],
15138 				      (gdouble) destination[(current_dchannel += dchannels)]};
15139 
15140       v_source = (ags_v8double) {source[0],
15141 				 source[(current_schannel = schannels)],
15142 				 source[(current_schannel += schannels)],
15143 				 source[(current_schannel += schannels)],
15144 				 source[(current_schannel += schannels)],
15145 				 source[(current_schannel += schannels)],
15146 				 source[(current_schannel += schannels)],
15147 				 source[(current_schannel += schannels)]};
15148 
15149       /* scale and copy */
15150       v_source *= scale;
15151       v_destination += v_source;
15152 
15153       current_dchannel = 0;
15154 
15155       destination[0] = (gint32) v_destination[0];
15156       destination[(current_dchannel = dchannels)] = (gint32) v_destination[1];
15157       destination[(current_dchannel += dchannels)] = (gint32) v_destination[2];
15158       destination[(current_dchannel += dchannels)] = (gint32) v_destination[3];
15159       destination[(current_dchannel += dchannels)] = (gint32) v_destination[4];
15160       destination[(current_dchannel += dchannels)] = (gint32) v_destination[5];
15161       destination[(current_dchannel += dchannels)] = (gint32) v_destination[6];
15162       destination[(current_dchannel += dchannels)] = (gint32) v_destination[7];
15163 
15164       /* iterate destination */
15165       destination += (current_dchannel + dchannels);
15166 
15167       /* iterate source */
15168       source += (current_schannel + schannels);
15169     }
15170   }
15171 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
15172   /* vectorized function */
15173   if(count > 8){
15174     limit = count - (count % 8);
15175 
15176     for(; i < limit; i += 8){
15177       double v_scaled[8];
15178       double v_result[8];
15179       static const double v_scale[1] = { (double) scale };
15180 
15181       current_dchannel = 0;
15182       current_schannel = 0;
15183 
15184       double v_destination[] = {(double) destination[0],
15185 				(double) destination[(current_dchannel = dchannels)],
15186 				(double) destination[(current_dchannel += dchannels)],
15187 				(double) destination[(current_dchannel += dchannels)],
15188 				(double) destination[(current_dchannel += dchannels)],
15189 				(double) destination[(current_dchannel += dchannels)],
15190 				(double) destination[(current_dchannel += dchannels)],
15191 				(double) destination[(current_dchannel += dchannels)]};
15192 
15193       double v_source[] = {(double) source[0],
15194 			   (double) source[(current_schannel = schannels)],
15195 			   (double) source[(current_schannel += schannels)],
15196 			   (double) source[(current_schannel += schannels)],
15197 			   (double) source[(current_schannel += schannels)],
15198 			   (double) source[(current_schannel += schannels)],
15199 			   (double) source[(current_schannel += schannels)],
15200 			   (double) source[(current_schannel += schannels)]};
15201 
15202       /* scale and copy */
15203       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
15204       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
15205 
15206       current_dchannel = 0;
15207 
15208       destination[0] = (gint32) v_result[0];
15209       destination[(current_dchannel = dchannels)] = (gint32) v_result[1];
15210       destination[(current_dchannel += dchannels)] = (gint32) v_result[2];
15211       destination[(current_dchannel += dchannels)] = (gint32) v_result[3];
15212       destination[(current_dchannel += dchannels)] = (gint32) v_result[4];
15213       destination[(current_dchannel += dchannels)] = (gint32) v_result[5];
15214       destination[(current_dchannel += dchannels)] = (gint32) v_result[6];
15215       destination[(current_dchannel += dchannels)] = (gint32) v_result[7];
15216 
15217       /* iterate destination */
15218       destination += (current_dchannel + dchannels);
15219 
15220       /* iterate source */
15221       source += (current_schannel + schannels);
15222     }
15223   }
15224 #else
15225   /* unrolled function */
15226   if(count > 8){
15227     limit = count - (count % 8);
15228 
15229     for(; i < limit; i += 8){
15230       current_dchannel = 0;
15231       current_schannel = 0;
15232 
15233       destination[0] = 0xffffffff & (gint32) ((gdouble) (destination[0] + (gdouble) (scale * source[0])));
15234       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (scale * source[(current_schannel = schannels)])));
15235       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
15236       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
15237       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
15238       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
15239       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
15240       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
15241 
15242       /* iterate destination */
15243       destination += (current_dchannel + dchannels);
15244 
15245       /* iterate source */
15246       source += (current_schannel + schannels);
15247     }
15248   }
15249 #endif
15250 
15251   for(; i < count; i++){
15252     destination[0] = 0xffffffff & (gint32) ((gdouble) (destination[0] + (gdouble) (scale * source[0])));
15253 
15254     destination += dchannels;
15255     source += schannels;
15256   }
15257 }
15258 
15259 /**
15260  * ags_audio_buffer_util_copy_double_to_s32:
15261  * @destination: destination buffer
15262  * @dchannels: destination buffer's count of channels
15263  * @source: source buffer
15264  * @schannels: source buffer's count of channels
15265  * @count: number of frames to copy
15266  *
15267  * Copy audio data using additive strategy.
15268  *
15269  * Since: 3.0.0
15270  */
15271 void
ags_audio_buffer_util_copy_double_to_s32(gint32 * destination,guint dchannels,gdouble * source,guint schannels,guint count)15272 ags_audio_buffer_util_copy_double_to_s32(gint32 *destination, guint dchannels,
15273 					 gdouble *source, guint schannels,
15274 					 guint count)
15275 {
15276   //NOTE:JK: scale = (2^bits_source / 2.0 - 1.0)
15277   static const gdouble scale = 214748363.0;
15278   guint limit;
15279   guint current_dchannel, current_schannel;
15280   guint i;
15281 
15282   if(destination == NULL ||
15283      source == NULL){
15284     return;
15285   }
15286 
15287   i = 0;
15288 
15289 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
15290   /* vectorized function */
15291   if(count > 8){
15292     limit = count - (count % 8);
15293 
15294     for(; i < limit; i += 8){
15295       ags_v8double v_destination;
15296       ags_v8double v_source;
15297 
15298       current_dchannel = 0;
15299       current_schannel = 0;
15300 
15301       v_destination = (ags_v8double) {(gdouble) destination[0],
15302 				      (gdouble) destination[(current_dchannel = dchannels)],
15303 				      (gdouble) destination[(current_dchannel += dchannels)],
15304 				      (gdouble) destination[(current_dchannel += dchannels)],
15305 				      (gdouble) destination[(current_dchannel += dchannels)],
15306 				      (gdouble) destination[(current_dchannel += dchannels)],
15307 				      (gdouble) destination[(current_dchannel += dchannels)],
15308 				      (gdouble) destination[(current_dchannel += dchannels)]};
15309 
15310       v_source = (ags_v8double) {source[0],
15311 				 source[(current_schannel = schannels)],
15312 				 source[(current_schannel += schannels)],
15313 				 source[(current_schannel += schannels)],
15314 				 source[(current_schannel += schannels)],
15315 				 source[(current_schannel += schannels)],
15316 				 source[(current_schannel += schannels)],
15317 				 source[(current_schannel += schannels)]};
15318 
15319       /* scale and copy */
15320       v_source *= scale;
15321       v_destination += v_source;
15322 
15323       current_dchannel = 0;
15324 
15325       destination[0] = (gint32) v_destination[0];
15326       destination[(current_dchannel = dchannels)] = (gint32) v_destination[1];
15327       destination[(current_dchannel += dchannels)] = (gint32) v_destination[2];
15328       destination[(current_dchannel += dchannels)] = (gint32) v_destination[3];
15329       destination[(current_dchannel += dchannels)] = (gint32) v_destination[4];
15330       destination[(current_dchannel += dchannels)] = (gint32) v_destination[5];
15331       destination[(current_dchannel += dchannels)] = (gint32) v_destination[6];
15332       destination[(current_dchannel += dchannels)] = (gint32) v_destination[7];
15333 
15334       /* iterate destination */
15335       destination += (current_dchannel + dchannels);
15336 
15337       /* iterate source */
15338       source += (current_schannel + schannels);
15339     }
15340   }
15341 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
15342   /* vectorized function */
15343   if(count > 8){
15344     limit = count - (count % 8);
15345 
15346     for(; i < limit; i += 8){
15347       double v_scaled[8];
15348       double v_result[8];
15349       static const double v_scale[1] = { (double) scale };
15350 
15351       current_dchannel = 0;
15352       current_schannel = 0;
15353 
15354       double v_destination[] = {(double) destination[0],
15355 				(double) destination[(current_dchannel = dchannels)],
15356 				(double) destination[(current_dchannel += dchannels)],
15357 				(double) destination[(current_dchannel += dchannels)],
15358 				(double) destination[(current_dchannel += dchannels)],
15359 				(double) destination[(current_dchannel += dchannels)],
15360 				(double) destination[(current_dchannel += dchannels)],
15361 				(double) destination[(current_dchannel += dchannels)]};
15362 
15363       double v_source[] = {(double) source[0],
15364 			   (double) source[(current_schannel = schannels)],
15365 			   (double) source[(current_schannel += schannels)],
15366 			   (double) source[(current_schannel += schannels)],
15367 			   (double) source[(current_schannel += schannels)],
15368 			   (double) source[(current_schannel += schannels)],
15369 			   (double) source[(current_schannel += schannels)],
15370 			   (double) source[(current_schannel += schannels)]};
15371 
15372       /* scale and copy */
15373       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
15374       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
15375 
15376       current_dchannel = 0;
15377 
15378       destination[0] = (gint32) v_result[0];
15379       destination[(current_dchannel = dchannels)] = (gint32) v_result[1];
15380       destination[(current_dchannel += dchannels)] = (gint32) v_result[2];
15381       destination[(current_dchannel += dchannels)] = (gint32) v_result[3];
15382       destination[(current_dchannel += dchannels)] = (gint32) v_result[4];
15383       destination[(current_dchannel += dchannels)] = (gint32) v_result[5];
15384       destination[(current_dchannel += dchannels)] = (gint32) v_result[6];
15385       destination[(current_dchannel += dchannels)] = (gint32) v_result[7];
15386 
15387       /* iterate destination */
15388       destination += (current_dchannel + dchannels);
15389 
15390       /* iterate source */
15391       source += (current_schannel + schannels);
15392     }
15393   }
15394 #else
15395   /* unrolled function */
15396   if(count > 8){
15397     limit = count - (count % 8);
15398 
15399     for(; i < limit; i += 8){
15400       current_dchannel = 0;
15401       current_schannel = 0;
15402 
15403       destination[0] = 0xffffffff & (gint32) ((gdouble) (destination[0] + (gdouble) (scale * source[0])));
15404       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (scale * source[(current_schannel = schannels)])));
15405       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
15406       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
15407       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
15408       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
15409       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
15410       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
15411 
15412       /* iterate destination */
15413       destination += (current_dchannel + dchannels);
15414 
15415       /* iterate source */
15416       source += (current_schannel + schannels);
15417     }
15418   }
15419 #endif
15420 
15421   for(; i < count; i++){
15422     destination[0] = 0xffffffff & (gint32) ((gdouble) (destination[0] + (gdouble) (scale * source[0])));
15423 
15424     destination += dchannels;
15425     source += schannels;
15426   }
15427 }
15428 
15429 /**
15430  * ags_audio_buffer_util_copy_double_to_s64:
15431  * @destination: destination buffer
15432  * @dchannels: destination buffer's count of channels
15433  * @source: source buffer
15434  * @schannels: source buffer's count of channels
15435  * @count: number of frames to copy
15436  *
15437  * Copy audio data using additive strategy.
15438  *
15439  * Since: 3.0.0
15440  */
15441 void
ags_audio_buffer_util_copy_double_to_s64(gint64 * destination,guint dchannels,gdouble * source,guint schannels,guint count)15442 ags_audio_buffer_util_copy_double_to_s64(gint64 *destination, guint dchannels,
15443 					 gdouble *source, guint schannels,
15444 					 guint count)
15445 {
15446   //NOTE:JK: scale = (2^bits_source / 2.0 - 1.0)
15447   static const gdouble scale = 9223372036854775807.0;
15448   guint limit;
15449   guint current_dchannel, current_schannel;
15450   guint i;
15451 
15452   if(destination == NULL ||
15453      source == NULL){
15454     return;
15455   }
15456 
15457   i = 0;
15458 
15459 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
15460   /* vectorized function */
15461   if(count > 8){
15462     limit = count - (count % 8);
15463 
15464     for(; i < limit; i += 8){
15465       ags_v8double v_destination;
15466       ags_v8double v_source;
15467 
15468       current_dchannel = 0;
15469       current_schannel = 0;
15470 
15471       v_destination = (ags_v8double) {(gdouble) destination[0],
15472 				      (gdouble) destination[(current_dchannel = dchannels)],
15473 				      (gdouble) destination[(current_dchannel += dchannels)],
15474 				      (gdouble) destination[(current_dchannel += dchannels)],
15475 				      (gdouble) destination[(current_dchannel += dchannels)],
15476 				      (gdouble) destination[(current_dchannel += dchannels)],
15477 				      (gdouble) destination[(current_dchannel += dchannels)],
15478 				      (gdouble) destination[(current_dchannel += dchannels)]};
15479 
15480       v_source = (ags_v8double) {source[0],
15481 				 source[(current_schannel = schannels)],
15482 				 source[(current_schannel += schannels)],
15483 				 source[(current_schannel += schannels)],
15484 				 source[(current_schannel += schannels)],
15485 				 source[(current_schannel += schannels)],
15486 				 source[(current_schannel += schannels)],
15487 				 source[(current_schannel += schannels)]};
15488 
15489       /* scale and copy */
15490       v_source *= scale;
15491       v_destination += v_source;
15492 
15493       current_dchannel = 0;
15494 
15495       destination[0] = (gint64) v_destination[0];
15496       destination[(current_dchannel = dchannels)] = (gint64) v_destination[1];
15497       destination[(current_dchannel += dchannels)] = (gint64) v_destination[2];
15498       destination[(current_dchannel += dchannels)] = (gint64) v_destination[3];
15499       destination[(current_dchannel += dchannels)] = (gint64) v_destination[4];
15500       destination[(current_dchannel += dchannels)] = (gint64) v_destination[5];
15501       destination[(current_dchannel += dchannels)] = (gint64) v_destination[6];
15502       destination[(current_dchannel += dchannels)] = (gint64) v_destination[7];
15503 
15504       /* iterate destination */
15505       destination += (current_dchannel + dchannels);
15506 
15507       /* iterate source */
15508       source += (current_schannel + schannels);
15509     }
15510   }
15511 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
15512   /* vectorized function */
15513   if(count > 8){
15514     limit = count - (count % 8);
15515 
15516     for(; i < limit; i += 8){
15517       double v_scaled[8];
15518       double v_result[8];
15519       static const double v_scale[1] = { (double) scale };
15520 
15521       current_dchannel = 0;
15522       current_schannel = 0;
15523 
15524       double v_destination[] = {(double) destination[0],
15525 				(double) destination[(current_dchannel = dchannels)],
15526 				(double) destination[(current_dchannel += dchannels)],
15527 				(double) destination[(current_dchannel += dchannels)],
15528 				(double) destination[(current_dchannel += dchannels)],
15529 				(double) destination[(current_dchannel += dchannels)],
15530 				(double) destination[(current_dchannel += dchannels)],
15531 				(double) destination[(current_dchannel += dchannels)]};
15532 
15533       double v_source[] = {(double) source[0],
15534 			   (double) source[(current_schannel = schannels)],
15535 			   (double) source[(current_schannel += schannels)],
15536 			   (double) source[(current_schannel += schannels)],
15537 			   (double) source[(current_schannel += schannels)],
15538 			   (double) source[(current_schannel += schannels)],
15539 			   (double) source[(current_schannel += schannels)],
15540 			   (double) source[(current_schannel += schannels)]};
15541 
15542       /* scale and copy */
15543       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
15544       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
15545 
15546       current_dchannel = 0;
15547 
15548       destination[0] = (gint64) v_result[0];
15549       destination[(current_dchannel = dchannels)] = (gint64) v_result[1];
15550       destination[(current_dchannel += dchannels)] = (gint64) v_result[2];
15551       destination[(current_dchannel += dchannels)] = (gint64) v_result[3];
15552       destination[(current_dchannel += dchannels)] = (gint64) v_result[4];
15553       destination[(current_dchannel += dchannels)] = (gint64) v_result[5];
15554       destination[(current_dchannel += dchannels)] = (gint64) v_result[6];
15555       destination[(current_dchannel += dchannels)] = (gint64) v_result[7];
15556 
15557       /* iterate destination */
15558       destination += (current_dchannel + dchannels);
15559 
15560       /* iterate source */
15561       source += (current_schannel + schannels);
15562     }
15563   }
15564 #else
15565   /* unrolled function */
15566   if(count > 8){
15567     limit = count - (count % 8);
15568 
15569     for(; i < limit; i += 8){
15570       current_dchannel = 0;
15571       current_schannel = 0;
15572 
15573       destination[0] = 0xffffffffffffffff & (gint64) ((gdouble) (destination[0] + (gdouble) (scale * source[0])));
15574       destination[current_dchannel] = 0xffffffffffffffff & (gint64) ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (scale * source[(current_schannel = schannels)])));
15575       destination[current_dchannel] = 0xffffffffffffffff & (gint64) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
15576       destination[current_dchannel] = 0xffffffffffffffff & (gint64) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
15577       destination[current_dchannel] = 0xffffffffffffffff & (gint64) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
15578       destination[current_dchannel] = 0xffffffffffffffff & (gint64) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
15579       destination[current_dchannel] = 0xffffffffffffffff & (gint64) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
15580       destination[current_dchannel] = 0xffffffffffffffff & (gint64) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
15581 
15582       /* iterate destination */
15583       destination += (current_dchannel + dchannels);
15584 
15585       /* iterate source */
15586       source += (current_schannel + schannels);
15587     }
15588   }
15589 #endif
15590 
15591   for(; i < count; i++){
15592     destination[0] = 0xffffffffffffffff & (gint64) ((gdouble) (destination[0] + (gdouble) (scale * source[0])));
15593 
15594     destination += dchannels;
15595     source += schannels;
15596   }
15597 }
15598 
15599 /**
15600  * ags_audio_buffer_util_copy_double_to_float:
15601  * @destination: destination buffer
15602  * @dchannels: destination buffer's count of channels
15603  * @source: source buffer
15604  * @schannels: source buffer's count of channels
15605  * @count: number of frames to copy
15606  *
15607  * Copy audio data using additive strategy.
15608  *
15609  * Since: 3.0.0
15610  */
15611 void
ags_audio_buffer_util_copy_double_to_float(gfloat * destination,guint dchannels,gdouble * source,guint schannels,guint count)15612 ags_audio_buffer_util_copy_double_to_float(gfloat *destination, guint dchannels,
15613 					   gdouble *source, guint schannels,
15614 					   guint count)
15615 {
15616   guint limit;
15617   guint current_dchannel, current_schannel;
15618   guint i;
15619 
15620   if(destination == NULL ||
15621      source == NULL){
15622     return;
15623   }
15624 
15625   i = 0;
15626 
15627 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
15628   /* vectorized function */
15629   if(count > 8){
15630     limit = count - (count % 8);
15631 
15632     for(; i < limit; i += 8){
15633       ags_v8float v_destination;
15634       ags_v8float v_source;
15635 
15636       current_dchannel = 0;
15637       current_schannel = 0;
15638 
15639       v_destination = (ags_v8float) {destination[0],
15640 				     destination[(current_dchannel = dchannels)],
15641 				     destination[(current_dchannel += dchannels)],
15642 				     destination[(current_dchannel += dchannels)],
15643 				     destination[(current_dchannel += dchannels)],
15644 				     destination[(current_dchannel += dchannels)],
15645 				     destination[(current_dchannel += dchannels)],
15646 				     destination[(current_dchannel += dchannels)]};
15647 
15648       v_source = (ags_v8float) {(gfloat) source[0],
15649 				(gfloat) source[(current_schannel = schannels)],
15650 				(gfloat) source[(current_schannel += schannels)],
15651 				(gfloat) source[(current_schannel += schannels)],
15652 				(gfloat) source[(current_schannel += schannels)],
15653 				(gfloat) source[(current_schannel += schannels)],
15654 				(gfloat) source[(current_schannel += schannels)],
15655 				(gfloat) source[(current_schannel += schannels)]};
15656 
15657       /* no scale, just copy */
15658       v_destination += v_source;
15659 
15660       current_dchannel = 0;
15661 
15662       destination[0] = v_destination[0];
15663       destination[(current_dchannel = dchannels)] = v_destination[1];
15664       destination[(current_dchannel += dchannels)] = v_destination[2];
15665       destination[(current_dchannel += dchannels)] = v_destination[3];
15666       destination[(current_dchannel += dchannels)] = v_destination[4];
15667       destination[(current_dchannel += dchannels)] = v_destination[5];
15668       destination[(current_dchannel += dchannels)] = v_destination[6];
15669       destination[(current_dchannel += dchannels)] = v_destination[7];
15670 
15671       /* iterate destination */
15672       destination += (current_dchannel + dchannels);
15673 
15674       /* iterate source */
15675       source += (current_schannel + schannels);
15676     }
15677   }
15678 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
15679   /* vectorized function */
15680   if(count > 8){
15681     limit = count - (count % 8);
15682 
15683     for(; i < limit; i += 8){
15684       double v_result[8];
15685 
15686       current_dchannel = 0;
15687       current_schannel = 0;
15688 
15689       double v_destination[] = {(double) destination[0],
15690 				(double) destination[(current_dchannel = dchannels)],
15691 				(double) destination[(current_dchannel += dchannels)],
15692 				(double) destination[(current_dchannel += dchannels)],
15693 				(double) destination[(current_dchannel += dchannels)],
15694 				(double) destination[(current_dchannel += dchannels)],
15695 				(double) destination[(current_dchannel += dchannels)],
15696 				(double) destination[(current_dchannel += dchannels)]};
15697 
15698       double v_source[] = {(double) source[0],
15699 			   (double) source[(current_schannel = schannels)],
15700 			   (double) source[(current_schannel += schannels)],
15701 			   (double) source[(current_schannel += schannels)],
15702 			   (double) source[(current_schannel += schannels)],
15703 			   (double) source[(current_schannel += schannels)],
15704 			   (double) source[(current_schannel += schannels)],
15705 			   (double) source[(current_schannel += schannels)]};
15706 
15707       /* no scale, just copy */
15708       vDSP_vaddD(v_destination, 1, v_source, 1, v_result, 1, 8);
15709 
15710       current_dchannel = 0;
15711 
15712       destination[0] = (gfloat) v_result[0];
15713       destination[(current_dchannel = dchannels)] = (gfloat) v_result[1];
15714       destination[(current_dchannel += dchannels)] = (gfloat) v_result[2];
15715       destination[(current_dchannel += dchannels)] = (gfloat) v_result[3];
15716       destination[(current_dchannel += dchannels)] = (gfloat) v_result[4];
15717       destination[(current_dchannel += dchannels)] = (gfloat) v_result[5];
15718       destination[(current_dchannel += dchannels)] = (gfloat) v_result[6];
15719       destination[(current_dchannel += dchannels)] = (gfloat) v_result[7];
15720 
15721       /* iterate destination */
15722       destination += (current_dchannel + dchannels);
15723 
15724       /* iterate source */
15725       source += (current_schannel + schannels);
15726     }
15727   }
15728 #else
15729   /* unrolled function */
15730   if(count > 8){
15731     limit = count - (count % 8);
15732 
15733     for(; i < limit; i += 8){
15734       current_dchannel = 0;
15735       current_schannel = 0;
15736 
15737       destination[0] = (gfloat) ((gdouble) (destination[0] + (gdouble) (source[0])));
15738       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (source[(current_schannel = schannels)])));
15739       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
15740       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
15741       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
15742       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
15743       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
15744       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
15745 
15746       /* iterate destination */
15747       destination += (current_dchannel + dchannels);
15748 
15749       /* iterate source */
15750       source += (current_schannel + schannels);
15751     }
15752   }
15753 #endif
15754 
15755   for(; i < count; i++){
15756     destination[0] = (gfloat) ((gdouble) (destination[0] + (gdouble) (source[0])));
15757 
15758     destination += dchannels;
15759     source += schannels;
15760   }
15761 }
15762 
15763 /**
15764  * ags_audio_buffer_util_copy_double_to_double:
15765  * @destination: destination buffer
15766  * @dchannels: destination buffer's count of channels
15767  * @source: source buffer
15768  * @schannels: source buffer's count of channels
15769  * @count: number of frames to copy
15770  *
15771  * Copy audio data using additive strategy.
15772  *
15773  * Since: 3.0.0
15774  */
15775 void
ags_audio_buffer_util_copy_double_to_double(gdouble * destination,guint dchannels,gdouble * source,guint schannels,guint count)15776 ags_audio_buffer_util_copy_double_to_double(gdouble *destination, guint dchannels,
15777 					    gdouble *source, guint schannels,
15778 					    guint count)
15779 {
15780   guint limit;
15781   guint current_dchannel, current_schannel;
15782   guint i;
15783 
15784   if(destination == NULL ||
15785      source == NULL){
15786     return;
15787   }
15788 
15789   i = 0;
15790 
15791 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
15792   /* vectorized function */
15793   if(count > 8){
15794     limit = count - (count % 8);
15795 
15796     for(; i < limit; i += 8){
15797       ags_v8double v_destination;
15798       ags_v8double v_source;
15799 
15800       current_dchannel = 0;
15801       current_schannel = 0;
15802 
15803       v_destination = (ags_v8double) {destination[0],
15804 				      destination[(current_dchannel = dchannels)],
15805 				      destination[(current_dchannel += dchannels)],
15806 				      destination[(current_dchannel += dchannels)],
15807 				      destination[(current_dchannel += dchannels)],
15808 				      destination[(current_dchannel += dchannels)],
15809 				      destination[(current_dchannel += dchannels)],
15810 				      destination[(current_dchannel += dchannels)]};
15811 
15812       v_source = (ags_v8double) {source[0],
15813 				 source[(current_schannel = schannels)],
15814 				 source[(current_schannel += schannels)],
15815 				 source[(current_schannel += schannels)],
15816 				 source[(current_schannel += schannels)],
15817 				 source[(current_schannel += schannels)],
15818 				 source[(current_schannel += schannels)],
15819 				 source[(current_schannel += schannels)]};
15820 
15821       /* just copy */
15822       v_destination += v_source;
15823 
15824       current_dchannel = 0;
15825 
15826       destination[0] = v_destination[0];
15827       destination[(current_dchannel = dchannels)] = v_destination[1];
15828       destination[(current_dchannel += dchannels)] = v_destination[2];
15829       destination[(current_dchannel += dchannels)] = v_destination[3];
15830       destination[(current_dchannel += dchannels)] = v_destination[4];
15831       destination[(current_dchannel += dchannels)] = v_destination[5];
15832       destination[(current_dchannel += dchannels)] = v_destination[6];
15833       destination[(current_dchannel += dchannels)] = v_destination[7];
15834 
15835       /* iterate destination */
15836       destination += (current_dchannel + dchannels);
15837 
15838       /* iterate source */
15839       source += (current_schannel + schannels);
15840     }
15841   }
15842 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
15843   /* vectorized function */
15844   if(count > 8){
15845     limit = count - (count % 8);
15846 
15847     for(; i < limit; i += 8){
15848       double v_result[8];
15849 
15850       current_dchannel = 0;
15851       current_schannel = 0;
15852 
15853       double v_destination[] = {(double) destination[0],
15854 				(double) destination[(current_dchannel = dchannels)],
15855 				(double) destination[(current_dchannel += dchannels)],
15856 				(double) destination[(current_dchannel += dchannels)],
15857 				(double) destination[(current_dchannel += dchannels)],
15858 				(double) destination[(current_dchannel += dchannels)],
15859 				(double) destination[(current_dchannel += dchannels)],
15860 				(double) destination[(current_dchannel += dchannels)]};
15861 
15862       double v_source[] = {(double) source[0],
15863 			   (double) source[(current_schannel = schannels)],
15864 			   (double) source[(current_schannel += schannels)],
15865 			   (double) source[(current_schannel += schannels)],
15866 			   (double) source[(current_schannel += schannels)],
15867 			   (double) source[(current_schannel += schannels)],
15868 			   (double) source[(current_schannel += schannels)],
15869 			   (double) source[(current_schannel += schannels)]};
15870 
15871       /* just copy */
15872       vDSP_vaddD(v_destination, 1, v_source, 1, v_result, 1, 8);
15873 
15874       current_dchannel = 0;
15875 
15876       destination[0] = (gdouble) v_result[0];
15877       destination[(current_dchannel = dchannels)] = (gdouble) v_result[1];
15878       destination[(current_dchannel += dchannels)] = (gdouble) v_result[2];
15879       destination[(current_dchannel += dchannels)] = (gdouble) v_result[3];
15880       destination[(current_dchannel += dchannels)] = (gdouble) v_result[4];
15881       destination[(current_dchannel += dchannels)] = (gdouble) v_result[5];
15882       destination[(current_dchannel += dchannels)] = (gdouble) v_result[6];
15883       destination[(current_dchannel += dchannels)] = (gdouble) v_result[7];
15884 
15885       /* iterate destination */
15886       destination += (current_dchannel + dchannels);
15887 
15888       /* iterate source */
15889       source += (current_schannel + schannels);
15890     }
15891   }
15892 #else
15893   /* unrolled function */
15894   if(count > 8){
15895     limit = count - (count % 8);
15896 
15897     for(; i < limit; i += 8){
15898       current_dchannel = 0;
15899       current_schannel = 0;
15900 
15901       destination[0] = ((gdouble) (destination[0] + (gdouble) (source[0])));
15902       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (source[(current_schannel = schannels)])));
15903       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
15904       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
15905       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
15906       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
15907       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
15908       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
15909 
15910       /* iterate destination */
15911       destination += (current_dchannel + dchannels);
15912 
15913       /* iterate source */
15914       source += (current_schannel + schannels);
15915     }
15916   }
15917 #endif
15918 
15919   for(; i < count; i++){
15920     destination[0] = ((gdouble) ((destination[0]) + (gdouble) (source[0])));
15921 
15922     destination += dchannels;
15923     source += schannels;
15924   }
15925 }
15926 
15927 #ifdef __APPLE__
15928 /**
15929  * ags_audio_buffer_util_copy_s8_to_float32:
15930  * @destination: destination buffer
15931  * @dchannels: destination buffer's count of channels
15932  * @source: source buffer
15933  * @schannels: source buffer's count of channels
15934  * @count: number of frames to copy
15935  *
15936  * Copy audio data using additive strategy.
15937  *
15938  * Since: 3.0.0
15939  */
15940 void
ags_audio_buffer_util_copy_s8_to_float32(Float32 * destination,guint dchannels,gint8 * source,guint schannels,guint count)15941 ags_audio_buffer_util_copy_s8_to_float32(Float32 *destination, guint dchannels,
15942 					 gint8 *source, guint schannels,
15943 					 guint count)
15944 {
15945   //NOTE:JK: scale = 1.0 / (2^bits_source / 2.0 - 1.0)
15946   //  static const Float64 scale = 0.0078740157480314960629854564334861866115034L;
15947   static const gdouble normalize_divisor = 128.0;
15948   guint limit;
15949   guint current_dchannel, current_schannel;
15950   guint i;
15951 
15952   if(destination == NULL ||
15953      source == NULL){
15954     return;
15955   }
15956 
15957   i = 0;
15958 
15959 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
15960   /* vectorized function */
15961   if(count > 8){
15962     limit = count - (count % 8);
15963 
15964     for(; i < limit; i += 8){
15965       ags_v8float v_destination;
15966       ags_v8float v_source;
15967 
15968       current_dchannel = 0;
15969       current_schannel = 0;
15970 
15971       v_destination = (ags_v8float) {(gfloat) destination[0],
15972 				     (gfloat) destination[(current_dchannel = dchannels)],
15973 				     (gfloat) destination[(current_dchannel += dchannels)],
15974 				     (gfloat) destination[(current_dchannel += dchannels)],
15975 				     (gfloat) destination[(current_dchannel += dchannels)],
15976 				     (gfloat) destination[(current_dchannel += dchannels)],
15977 				     (gfloat) destination[(current_dchannel += dchannels)],
15978 				     (gfloat) destination[(current_dchannel += dchannels)]};
15979 
15980       v_source = (ags_v8float) {(gfloat) source[0],
15981 				(gfloat) source[(current_schannel = schannels)],
15982 				(gfloat) source[(current_schannel += schannels)],
15983 				(gfloat) source[(current_schannel += schannels)],
15984 				(gfloat) source[(current_schannel += schannels)],
15985 				(gfloat) source[(current_schannel += schannels)],
15986 				(gfloat) source[(current_schannel += schannels)],
15987 				(gfloat) source[(current_schannel += schannels)]};
15988 
15989       /* normalize and copy */
15990       v_source /= (gfloat) normalize_divisor;
15991       v_destination += v_source;
15992 
15993       current_dchannel = 0;
15994 
15995       destination[0] = (Float32) v_destination[0];
15996       destination[(current_dchannel = dchannels)] = (Float32) v_destination[1];
15997       destination[(current_dchannel += dchannels)] = (Float32) v_destination[2];
15998       destination[(current_dchannel += dchannels)] = (Float32) v_destination[3];
15999       destination[(current_dchannel += dchannels)] = (Float32) v_destination[4];
16000       destination[(current_dchannel += dchannels)] = (Float32) v_destination[5];
16001       destination[(current_dchannel += dchannels)] = (Float32) v_destination[6];
16002       destination[(current_dchannel += dchannels)] = (Float32) v_destination[7];
16003 
16004       /* iterate destination */
16005       destination += (current_dchannel + dchannels);
16006 
16007       /* iterate source */
16008       source += (current_schannel + schannels);
16009     }
16010   }
16011 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
16012   /* vectorized function */
16013   if(count > 8){
16014     limit = count - (count % 8);
16015 
16016     for(; i < limit; i += 8){
16017       double v_normalized[8];
16018       double v_result[8];
16019       static const double v_normalize_divisor[1] = { (double) normalize_divisor };
16020 
16021       current_dchannel = 0;
16022       current_schannel = 0;
16023 
16024       double v_destination[] = {(double) destination[0],
16025 				(double) destination[(current_dchannel = dchannels)],
16026 				(double) destination[(current_dchannel += dchannels)],
16027 				(double) destination[(current_dchannel += dchannels)],
16028 				(double) destination[(current_dchannel += dchannels)],
16029 				(double) destination[(current_dchannel += dchannels)],
16030 				(double) destination[(current_dchannel += dchannels)],
16031 				(double) destination[(current_dchannel += dchannels)]};
16032 
16033       double v_source[] = {(double) source[0],
16034 			   (double) source[(current_schannel = schannels)],
16035 			   (double) source[(current_schannel += schannels)],
16036 			   (double) source[(current_schannel += schannels)],
16037 			   (double) source[(current_schannel += schannels)],
16038 			   (double) source[(current_schannel += schannels)],
16039 			   (double) source[(current_schannel += schannels)],
16040 			   (double) source[(current_schannel += schannels)]};
16041 
16042       /* scale and copy */
16043       vDSP_vdivD(v_normalize_divisor, 0, v_source, 1, v_normalized, 1, 8);
16044       vDSP_vaddD(v_destination, 1, v_normalized, 1, v_result, 1, 8);
16045 
16046       current_dchannel = 0;
16047 
16048       destination[0] = (Float32) v_result[0];
16049       destination[(current_dchannel = dchannels)] = (Float32) v_result[1];
16050       destination[(current_dchannel += dchannels)] = (Float32) v_result[2];
16051       destination[(current_dchannel += dchannels)] = (Float32) v_result[3];
16052       destination[(current_dchannel += dchannels)] = (Float32) v_result[4];
16053       destination[(current_dchannel += dchannels)] = (Float32) v_result[5];
16054       destination[(current_dchannel += dchannels)] = (Float32) v_result[6];
16055       destination[(current_dchannel += dchannels)] = (Float32) v_result[7];
16056 
16057       /* iterate destination */
16058       destination += (current_dchannel + dchannels);
16059 
16060       /* iterate source */
16061       source += (current_schannel + schannels);
16062     }
16063   }
16064 #else
16065   /* unrolled function */
16066   if(count > 8){
16067     limit = count - (count % 8);
16068 
16069     for(; i < limit; i += 8){
16070       current_dchannel = 0;
16071       current_schannel = 0;
16072 
16073       destination[0] = (Float32) ((Float64) (destination[0] + (Float64) (source[0] / normalize_divisor)));
16074       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel = dchannels)] + (Float64) (source[(current_schannel = schannels)] / normalize_divisor)));
16075       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)] / normalize_divisor)));
16076       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)] / normalize_divisor)));
16077       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)] / normalize_divisor)));
16078       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)] / normalize_divisor)));
16079       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)] / normalize_divisor)));
16080       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)] / normalize_divisor)));
16081 
16082       /* iterate destination */
16083       destination += (current_dchannel + dchannels);
16084 
16085       /* iterate source */
16086       source += (current_schannel + schannels);
16087     }
16088   }
16089 #endif
16090 
16091   for(; i < count; i++){
16092     destination[0] = (Float32) ((Float64) (destination[0] + (Float64) (source[0] / normalize_divisor)));
16093 
16094     destination += dchannels;
16095     source += schannels;
16096   }
16097 }
16098 
16099 /**
16100  * ags_audio_buffer_util_copy_s16_to_float32:
16101  * @destination: destination buffer
16102  * @dchannels: destination buffer's count of channels
16103  * @source: source buffer
16104  * @schannels: source buffer's count of channels
16105  * @count: number of frames to copy
16106  *
16107  * Copy audio data using additive strategy.
16108  *
16109  * Since: 3.0.0
16110  */
16111 void
ags_audio_buffer_util_copy_s16_to_float32(Float32 * destination,guint dchannels,gint16 * source,guint schannels,guint count)16112 ags_audio_buffer_util_copy_s16_to_float32(Float32 *destination, guint dchannels,
16113 					  gint16 *source, guint schannels,
16114 					  guint count)
16115 {
16116   //NOTE:JK: scale = 1.0 / (2^bits_source / 2.0 - 1.0)
16117   //  static const Float64 scale = 0.0000305185094759971922971274004400890622613L;
16118   static const gdouble normalize_divisor = 32767.0;
16119   guint limit;
16120   guint current_dchannel, current_schannel;
16121   guint i;
16122 
16123   if(destination == NULL ||
16124      source == NULL){
16125     return;
16126   }
16127 
16128   i = 0;
16129 
16130 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
16131   /* vectorized function */
16132   if(count > 8){
16133     limit = count - (count % 8);
16134 
16135     for(; i < limit; i += 8){
16136       ags_v8float v_destination;
16137       ags_v8float v_source;
16138 
16139       current_dchannel = 0;
16140       current_schannel = 0;
16141 
16142       v_destination = (ags_v8float) {(gfloat) destination[0],
16143 				     (gfloat) destination[(current_dchannel = dchannels)],
16144 				     (gfloat) destination[(current_dchannel += dchannels)],
16145 				     (gfloat) destination[(current_dchannel += dchannels)],
16146 				     (gfloat) destination[(current_dchannel += dchannels)],
16147 				     (gfloat) destination[(current_dchannel += dchannels)],
16148 				     (gfloat) destination[(current_dchannel += dchannels)],
16149 				     (gfloat) destination[(current_dchannel += dchannels)]};
16150 
16151       v_source = (ags_v8float) {(gfloat) source[0],
16152 				(gfloat) source[(current_schannel = schannels)],
16153 				(gfloat) source[(current_schannel += schannels)],
16154 				(gfloat) source[(current_schannel += schannels)],
16155 				(gfloat) source[(current_schannel += schannels)],
16156 				(gfloat) source[(current_schannel += schannels)],
16157 				(gfloat) source[(current_schannel += schannels)],
16158 				(gfloat) source[(current_schannel += schannels)]};
16159 
16160       /* normalize and copy */
16161       v_source /= (gfloat) normalize_divisor;
16162       v_destination += v_source;
16163 
16164       current_dchannel = 0;
16165 
16166       destination[0] = (Float32) v_destination[0];
16167       destination[(current_dchannel = dchannels)] = (Float32) v_destination[1];
16168       destination[(current_dchannel += dchannels)] = (Float32) v_destination[2];
16169       destination[(current_dchannel += dchannels)] = (Float32) v_destination[3];
16170       destination[(current_dchannel += dchannels)] = (Float32) v_destination[4];
16171       destination[(current_dchannel += dchannels)] = (Float32) v_destination[5];
16172       destination[(current_dchannel += dchannels)] = (Float32) v_destination[6];
16173       destination[(current_dchannel += dchannels)] = (Float32) v_destination[7];
16174 
16175       /* iterate destination */
16176       destination += (current_dchannel + dchannels);
16177 
16178       /* iterate source */
16179       source += (current_schannel + schannels);
16180     }
16181   }
16182 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
16183   /* vectorized function */
16184   if(count > 8){
16185     limit = count - (count % 8);
16186 
16187     for(; i < limit; i += 8){
16188       double v_normalized[8];
16189       double v_result[8];
16190       static const double v_normalize_divisor[1] = { (double) normalize_divisor };
16191 
16192       current_dchannel = 0;
16193       current_schannel = 0;
16194 
16195       double v_destination[] = {(double) destination[0],
16196 				(double) destination[(current_dchannel = dchannels)],
16197 				(double) destination[(current_dchannel += dchannels)],
16198 				(double) destination[(current_dchannel += dchannels)],
16199 				(double) destination[(current_dchannel += dchannels)],
16200 				(double) destination[(current_dchannel += dchannels)],
16201 				(double) destination[(current_dchannel += dchannels)],
16202 				(double) destination[(current_dchannel += dchannels)]};
16203 
16204       double v_source[] = {(double) source[0],
16205 			   (double) source[(current_schannel = schannels)],
16206 			   (double) source[(current_schannel += schannels)],
16207 			   (double) source[(current_schannel += schannels)],
16208 			   (double) source[(current_schannel += schannels)],
16209 			   (double) source[(current_schannel += schannels)],
16210 			   (double) source[(current_schannel += schannels)],
16211 			   (double) source[(current_schannel += schannels)]};
16212 
16213       /* scale and copy */
16214       vDSP_vdivD(v_normalize_divisor, 0, v_source, 1, v_normalized, 1, 8);
16215       vDSP_vaddD(v_destination, 1, v_normalized, 1, v_result, 1, 8);
16216 
16217       current_dchannel = 0;
16218 
16219       destination[0] = (Float32) v_result[0];
16220       destination[(current_dchannel = dchannels)] = (Float32) v_result[1];
16221       destination[(current_dchannel += dchannels)] = (Float32) v_result[2];
16222       destination[(current_dchannel += dchannels)] = (Float32) v_result[3];
16223       destination[(current_dchannel += dchannels)] = (Float32) v_result[4];
16224       destination[(current_dchannel += dchannels)] = (Float32) v_result[5];
16225       destination[(current_dchannel += dchannels)] = (Float32) v_result[6];
16226       destination[(current_dchannel += dchannels)] = (Float32) v_result[7];
16227 
16228       /* iterate destination */
16229       destination += (current_dchannel + dchannels);
16230 
16231       /* iterate source */
16232       source += (current_schannel + schannels);
16233     }
16234   }
16235 #else
16236   /* unrolled function */
16237   if(count > 8){
16238     limit = count - (count % 8);
16239 
16240     for(; i < limit; i += 8){
16241       current_dchannel = 0;
16242       current_schannel = 0;
16243 
16244       destination[0] = (Float32) ((Float64) (destination[0] + (Float64) (source[0] / normalize_divisor)));
16245       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel = dchannels)] + (Float64) (source[(current_schannel = schannels)] / normalize_divisor)));
16246       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)] / normalize_divisor)));
16247       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)] / normalize_divisor)));
16248       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)] / normalize_divisor)));
16249       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)] / normalize_divisor)));
16250       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)] / normalize_divisor)));
16251       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)] / normalize_divisor)));
16252 
16253       /* iterate destination */
16254       destination += (current_dchannel + dchannels);
16255 
16256       /* iterate source */
16257       source += (current_schannel + schannels);
16258     }
16259   }
16260 #endif
16261 
16262   for(; i < count; i++){
16263     destination[0] = (Float32) ((Float64) (destination[0] + (Float64) (source[0] / normalize_divisor)));
16264 
16265     destination += dchannels;
16266     source += schannels;
16267   }
16268 }
16269 
16270 /**
16271  * ags_audio_buffer_util_copy_s24_to_float32:
16272  * @destination: destination buffer
16273  * @dchannels: destination buffer's count of channels
16274  * @source: source buffer
16275  * @schannels: source buffer's count of channels
16276  * @count: number of frames to copy
16277  *
16278  * Copy audio data using additive strategy.
16279  *
16280  * Since: 3.0.0
16281  */
16282 void
ags_audio_buffer_util_copy_s24_to_float32(Float32 * destination,guint dchannels,gint32 * source,guint schannels,guint count)16283 ags_audio_buffer_util_copy_s24_to_float32(Float32 *destination, guint dchannels,
16284 					  gint32 *source, guint schannels,
16285 					  guint count)
16286 {
16287   //NOTE:JK: scale = 1.0 / (2^bits_source / 2.0 - 1.0)
16288   //  static const Float64 scale = 0.0000001192093037616376592678982260231634882L;
16289   static const gdouble normalize_divisor = 8388607.0;
16290   guint limit;
16291   guint current_dchannel, current_schannel;
16292   guint i;
16293 
16294   if(destination == NULL ||
16295      source == NULL){
16296     return;
16297   }
16298 
16299   i = 0;
16300 
16301 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
16302   /* vectorized function */
16303   if(count > 8){
16304     limit = count - (count % 8);
16305 
16306     for(; i < limit; i += 8){
16307       ags_v8float v_destination;
16308       ags_v8float v_source;
16309 
16310       current_dchannel = 0;
16311       current_schannel = 0;
16312 
16313       v_destination = (ags_v8float) {(gfloat) destination[0],
16314 				     (gfloat) destination[(current_dchannel = dchannels)],
16315 				     (gfloat) destination[(current_dchannel += dchannels)],
16316 				     (gfloat) destination[(current_dchannel += dchannels)],
16317 				     (gfloat) destination[(current_dchannel += dchannels)],
16318 				     (gfloat) destination[(current_dchannel += dchannels)],
16319 				     (gfloat) destination[(current_dchannel += dchannels)],
16320 				     (gfloat) destination[(current_dchannel += dchannels)]};
16321 
16322       v_source = (ags_v8float) {(gfloat) source[0],
16323 				(gfloat) source[(current_schannel = schannels)],
16324 				(gfloat) source[(current_schannel += schannels)],
16325 				(gfloat) source[(current_schannel += schannels)],
16326 				(gfloat) source[(current_schannel += schannels)],
16327 				(gfloat) source[(current_schannel += schannels)],
16328 				(gfloat) source[(current_schannel += schannels)],
16329 				(gfloat) source[(current_schannel += schannels)]};
16330 
16331       /* normalize and copy */
16332       v_source /= (gfloat) normalize_divisor;
16333       v_destination += v_source;
16334 
16335       current_dchannel = 0;
16336 
16337       destination[0] = (Float32) v_destination[0];
16338       destination[(current_dchannel = dchannels)] = (Float32) v_destination[1];
16339       destination[(current_dchannel += dchannels)] = (Float32) v_destination[2];
16340       destination[(current_dchannel += dchannels)] = (Float32) v_destination[3];
16341       destination[(current_dchannel += dchannels)] = (Float32) v_destination[4];
16342       destination[(current_dchannel += dchannels)] = (Float32) v_destination[5];
16343       destination[(current_dchannel += dchannels)] = (Float32) v_destination[6];
16344       destination[(current_dchannel += dchannels)] = (Float32) v_destination[7];
16345 
16346       /* iterate destination */
16347       destination += (current_dchannel + dchannels);
16348 
16349       /* iterate source */
16350       source += (current_schannel + schannels);
16351     }
16352   }
16353 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
16354   /* vectorized function */
16355   if(count > 8){
16356     limit = count - (count % 8);
16357 
16358     for(; i < limit; i += 8){
16359       double v_normalized[8];
16360       double v_result[8];
16361       static const double v_normalize_divisor[1] = { (double) normalize_divisor };
16362 
16363       current_dchannel = 0;
16364       current_schannel = 0;
16365 
16366       double v_destination[] = {(double) destination[0],
16367 				(double) destination[(current_dchannel = dchannels)],
16368 				(double) destination[(current_dchannel += dchannels)],
16369 				(double) destination[(current_dchannel += dchannels)],
16370 				(double) destination[(current_dchannel += dchannels)],
16371 				(double) destination[(current_dchannel += dchannels)],
16372 				(double) destination[(current_dchannel += dchannels)],
16373 				(double) destination[(current_dchannel += dchannels)]};
16374 
16375       double v_source[] = {(double) source[0],
16376 			   (double) source[(current_schannel = schannels)],
16377 			   (double) source[(current_schannel += schannels)],
16378 			   (double) source[(current_schannel += schannels)],
16379 			   (double) source[(current_schannel += schannels)],
16380 			   (double) source[(current_schannel += schannels)],
16381 			   (double) source[(current_schannel += schannels)],
16382 			   (double) source[(current_schannel += schannels)]};
16383 
16384       /* scale and copy */
16385       vDSP_vdivD(v_normalize_divisor, 0, v_source, 1, v_normalized, 1, 8);
16386       vDSP_vaddD(v_destination, 1, v_normalized, 1, v_result, 1, 8);
16387 
16388       current_dchannel = 0;
16389 
16390       destination[0] = (Float32) v_result[0];
16391       destination[(current_dchannel = dchannels)] = (Float32) v_result[1];
16392       destination[(current_dchannel += dchannels)] = (Float32) v_result[2];
16393       destination[(current_dchannel += dchannels)] = (Float32) v_result[3];
16394       destination[(current_dchannel += dchannels)] = (Float32) v_result[4];
16395       destination[(current_dchannel += dchannels)] = (Float32) v_result[5];
16396       destination[(current_dchannel += dchannels)] = (Float32) v_result[6];
16397       destination[(current_dchannel += dchannels)] = (Float32) v_result[7];
16398 
16399       /* iterate destination */
16400       destination += (current_dchannel + dchannels);
16401 
16402       /* iterate source */
16403       source += (current_schannel + schannels);
16404     }
16405   }
16406 #else
16407   /* unrolled function */
16408   if(count > 8){
16409     limit = count - (count % 8);
16410 
16411     for(; i < limit; i += 8){
16412       current_dchannel = 0;
16413       current_schannel = 0;
16414 
16415       destination[0] = (Float32) ((Float64) (destination[0] + (Float64) (source[0] / normalize_divisor)));
16416       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel = dchannels)] + (Float64) (source[(current_schannel = schannels)] / normalize_divisor)));
16417       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)] / normalize_divisor)));
16418       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)] / normalize_divisor)));
16419       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)] / normalize_divisor)));
16420       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)] / normalize_divisor)));
16421       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)] / normalize_divisor)));
16422       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)] / normalize_divisor)));
16423 
16424       /* iterate destination */
16425       destination += (current_dchannel + dchannels);
16426 
16427       /* iterate source */
16428       source += (current_schannel + schannels);
16429     }
16430   }
16431 #endif
16432 
16433   for(; i < count; i++){
16434     destination[0] = (Float32) ((Float64) (destination[0] + (Float64) (source[0] / normalize_divisor)));
16435 
16436     destination += dchannels;
16437     source += schannels;
16438   }
16439 }
16440 
16441 /**
16442  * ags_audio_buffer_util_copy_s32_to_float32:
16443  * @destination: destination buffer
16444  * @dchannels: destination buffer's count of channels
16445  * @source: source buffer
16446  * @schannels: source buffer's count of channels
16447  * @count: number of frames to copy
16448  *
16449  * Copy audio data using additive strategy.
16450  *
16451  * Since: 3.0.0
16452  */
16453 void
ags_audio_buffer_util_copy_s32_to_float32(Float32 * destination,guint dchannels,gint32 * source,guint schannels,guint count)16454 ags_audio_buffer_util_copy_s32_to_float32(Float32 *destination, guint dchannels,
16455 					  gint32 *source, guint schannels,
16456 					  guint count)
16457 {
16458   //NOTE:JK: scale = 1.0 / (2^bits_source / 2.0 - 1.0)
16459   //  static const Float64 scale = 0.0000000004656612875245796924105750826697801L;
16460   static const gdouble normalize_divisor = 214748363.0;
16461   guint limit;
16462   guint current_dchannel, current_schannel;
16463   guint i;
16464 
16465   if(destination == NULL ||
16466      source == NULL){
16467     return;
16468   }
16469 
16470   i = 0;
16471 
16472 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
16473   /* vectorized function */
16474   if(count > 8){
16475     limit = count - (count % 8);
16476 
16477     for(; i < limit; i += 8){
16478       ags_v8float v_destination;
16479       ags_v8float v_source;
16480 
16481       current_dchannel = 0;
16482       current_schannel = 0;
16483 
16484       v_destination = (ags_v8float) {(gfloat) destination[0],
16485 				     (gfloat) destination[(current_dchannel = dchannels)],
16486 				     (gfloat) destination[(current_dchannel += dchannels)],
16487 				     (gfloat) destination[(current_dchannel += dchannels)],
16488 				     (gfloat) destination[(current_dchannel += dchannels)],
16489 				     (gfloat) destination[(current_dchannel += dchannels)],
16490 				     (gfloat) destination[(current_dchannel += dchannels)],
16491 				     (gfloat) destination[(current_dchannel += dchannels)]};
16492 
16493       v_source = (ags_v8float) {(gfloat) source[0],
16494 				(gfloat) source[(current_schannel = schannels)],
16495 				(gfloat) source[(current_schannel += schannels)],
16496 				(gfloat) source[(current_schannel += schannels)],
16497 				(gfloat) source[(current_schannel += schannels)],
16498 				(gfloat) source[(current_schannel += schannels)],
16499 				(gfloat) source[(current_schannel += schannels)],
16500 				(gfloat) source[(current_schannel += schannels)]};
16501 
16502       /* normalize and copy */
16503       v_source /= (gfloat) normalize_divisor;
16504       v_destination += v_source;
16505 
16506       current_dchannel = 0;
16507 
16508       destination[0] = (Float32) v_destination[0];
16509       destination[(current_dchannel = dchannels)] = (Float32) v_destination[1];
16510       destination[(current_dchannel += dchannels)] = (Float32) v_destination[2];
16511       destination[(current_dchannel += dchannels)] = (Float32) v_destination[3];
16512       destination[(current_dchannel += dchannels)] = (Float32) v_destination[4];
16513       destination[(current_dchannel += dchannels)] = (Float32) v_destination[5];
16514       destination[(current_dchannel += dchannels)] = (Float32) v_destination[6];
16515       destination[(current_dchannel += dchannels)] = (Float32) v_destination[7];
16516 
16517       /* iterate destination */
16518       destination += (current_dchannel + dchannels);
16519 
16520       /* iterate source */
16521       source += (current_schannel + schannels);
16522     }
16523   }
16524 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
16525   /* vectorized function */
16526   if(count > 8){
16527     limit = count - (count % 8);
16528 
16529     for(; i < limit; i += 8){
16530       double v_normalized[8];
16531       double v_result[8];
16532       static const double v_normalize_divisor[1] = { (double) normalize_divisor };
16533 
16534       current_dchannel = 0;
16535       current_schannel = 0;
16536 
16537       double v_destination[] = {(double) destination[0],
16538 				(double) destination[(current_dchannel = dchannels)],
16539 				(double) destination[(current_dchannel += dchannels)],
16540 				(double) destination[(current_dchannel += dchannels)],
16541 				(double) destination[(current_dchannel += dchannels)],
16542 				(double) destination[(current_dchannel += dchannels)],
16543 				(double) destination[(current_dchannel += dchannels)],
16544 				(double) destination[(current_dchannel += dchannels)]};
16545 
16546       double v_source[] = {(double) source[0],
16547 			   (double) source[(current_schannel = schannels)],
16548 			   (double) source[(current_schannel += schannels)],
16549 			   (double) source[(current_schannel += schannels)],
16550 			   (double) source[(current_schannel += schannels)],
16551 			   (double) source[(current_schannel += schannels)],
16552 			   (double) source[(current_schannel += schannels)],
16553 			   (double) source[(current_schannel += schannels)]};
16554 
16555       /* scale and copy */
16556       vDSP_vdivD(v_normalize_divisor, 0, v_source, 1, v_normalized, 1, 8);
16557       vDSP_vaddD(v_destination, 1, v_normalized, 1, v_result, 1, 8);
16558 
16559       current_dchannel = 0;
16560 
16561       destination[0] = (Float32) v_result[0];
16562       destination[(current_dchannel = dchannels)] = (Float32) v_result[1];
16563       destination[(current_dchannel += dchannels)] = (Float32) v_result[2];
16564       destination[(current_dchannel += dchannels)] = (Float32) v_result[3];
16565       destination[(current_dchannel += dchannels)] = (Float32) v_result[4];
16566       destination[(current_dchannel += dchannels)] = (Float32) v_result[5];
16567       destination[(current_dchannel += dchannels)] = (Float32) v_result[6];
16568       destination[(current_dchannel += dchannels)] = (Float32) v_result[7];
16569 
16570       /* iterate destination */
16571       destination += (current_dchannel + dchannels);
16572 
16573       /* iterate source */
16574       source += (current_schannel + schannels);
16575     }
16576   }
16577 #else
16578   /* unrolled function */
16579   if(count > 8){
16580     limit = count - (count % 8);
16581 
16582     for(; i < limit; i += 8){
16583       current_dchannel = 0;
16584       current_schannel = 0;
16585 
16586       destination[0] = (Float32) ((Float64) (destination[0] + (Float64) (source[0] / normalize_divisor)));
16587       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel = dchannels)] + (Float64) (source[(current_schannel = schannels)] / normalize_divisor)));
16588       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)] / normalize_divisor)));
16589       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)] / normalize_divisor)));
16590       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)] / normalize_divisor)));
16591       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)] / normalize_divisor)));
16592       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)] / normalize_divisor)));
16593       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)] / normalize_divisor)));
16594 
16595       /* iterate destination */
16596       destination += (current_dchannel + dchannels);
16597 
16598       /* iterate source */
16599       source += (current_schannel + schannels);
16600     }
16601   }
16602 #endif
16603 
16604   for(; i < count; i++){
16605     destination[0] = (Float32) ((Float64) (destination[0] + (Float64) (source[0] / normalize_divisor)));
16606 
16607     destination += dchannels;
16608     source += schannels;
16609   }
16610 }
16611 
16612 /**
16613  * ags_audio_buffer_util_copy_s64_to_float32:
16614  * @destination: destination buffer
16615  * @dchannels: destination buffer's count of channels
16616  * @source: source buffer
16617  * @schannels: source buffer's count of channels
16618  * @count: number of frames to copy
16619  *
16620  * Copy audio data using additive strategy.
16621  *
16622  * Since: 3.0.0
16623  */
16624 void
ags_audio_buffer_util_copy_s64_to_float32(Float32 * destination,guint dchannels,gint64 * source,guint schannels,guint count)16625 ags_audio_buffer_util_copy_s64_to_float32(Float32 *destination, guint dchannels,
16626 					  gint64 *source, guint schannels,
16627 					  guint count)
16628 {
16629   //NOTE:JK: scale = 1.0 / (2^bits_source / 2.0 - 1.0)
16630   //  static const Float64 scale = 0.0000000000000000000722801448323667726912712L;
16631   static const gdouble normalize_divisor = 9223372036854775807.0;
16632   guint limit;
16633   guint current_dchannel, current_schannel;
16634   guint i;
16635 
16636   if(destination == NULL ||
16637      source == NULL){
16638     return;
16639   }
16640 
16641   i = 0;
16642 
16643 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
16644   /* vectorized function */
16645   if(count > 8){
16646     limit = count - (count % 8);
16647 
16648     for(; i < limit; i += 8){
16649       ags_v8float v_destination;
16650       ags_v8float v_source;
16651 
16652       current_dchannel = 0;
16653       current_schannel = 0;
16654 
16655       v_destination = (ags_v8float) {(gfloat) destination[0],
16656 				     (gfloat) destination[(current_dchannel = dchannels)],
16657 				     (gfloat) destination[(current_dchannel += dchannels)],
16658 				     (gfloat) destination[(current_dchannel += dchannels)],
16659 				     (gfloat) destination[(current_dchannel += dchannels)],
16660 				     (gfloat) destination[(current_dchannel += dchannels)],
16661 				     (gfloat) destination[(current_dchannel += dchannels)],
16662 				     (gfloat) destination[(current_dchannel += dchannels)]};
16663 
16664       v_source = (ags_v8float) {(gfloat) source[0],
16665 				(gfloat) source[(current_schannel = schannels)],
16666 				(gfloat) source[(current_schannel += schannels)],
16667 				(gfloat) source[(current_schannel += schannels)],
16668 				(gfloat) source[(current_schannel += schannels)],
16669 				(gfloat) source[(current_schannel += schannels)],
16670 				(gfloat) source[(current_schannel += schannels)],
16671 				(gfloat) source[(current_schannel += schannels)]};
16672 
16673       /* normalize and copy */
16674       v_source /= (gfloat) normalize_divisor;
16675       v_destination += v_source;
16676 
16677       current_dchannel = 0;
16678 
16679       destination[0] = (Float32) v_destination[0];
16680       destination[(current_dchannel = dchannels)] = (Float32) v_destination[1];
16681       destination[(current_dchannel += dchannels)] = (Float32) v_destination[2];
16682       destination[(current_dchannel += dchannels)] = (Float32) v_destination[3];
16683       destination[(current_dchannel += dchannels)] = (Float32) v_destination[4];
16684       destination[(current_dchannel += dchannels)] = (Float32) v_destination[5];
16685       destination[(current_dchannel += dchannels)] = (Float32) v_destination[6];
16686       destination[(current_dchannel += dchannels)] = (Float32) v_destination[7];
16687 
16688       /* iterate destination */
16689       destination += (current_dchannel + dchannels);
16690 
16691       /* iterate source */
16692       source += (current_schannel + schannels);
16693     }
16694   }
16695 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
16696   /* vectorized function */
16697   if(count > 8){
16698     limit = count - (count % 8);
16699 
16700     for(; i < limit; i += 8){
16701       double v_normalized[8];
16702       double v_result[8];
16703       static const double v_normalize_divisor[1] = { (double) normalize_divisor };
16704 
16705       current_dchannel = 0;
16706       current_schannel = 0;
16707 
16708       double v_destination[] = {(double) destination[0],
16709 				(double) destination[(current_dchannel = dchannels)],
16710 				(double) destination[(current_dchannel += dchannels)],
16711 				(double) destination[(current_dchannel += dchannels)],
16712 				(double) destination[(current_dchannel += dchannels)],
16713 				(double) destination[(current_dchannel += dchannels)],
16714 				(double) destination[(current_dchannel += dchannels)],
16715 				(double) destination[(current_dchannel += dchannels)]};
16716 
16717       double v_source[] = {(double) source[0],
16718 			   (double) source[(current_schannel = schannels)],
16719 			   (double) source[(current_schannel += schannels)],
16720 			   (double) source[(current_schannel += schannels)],
16721 			   (double) source[(current_schannel += schannels)],
16722 			   (double) source[(current_schannel += schannels)],
16723 			   (double) source[(current_schannel += schannels)],
16724 			   (double) source[(current_schannel += schannels)]};
16725 
16726       /* scale and copy */
16727       vDSP_vdivD(v_normalize_divisor, 0, v_source, 1, v_normalized, 1, 8);
16728       vDSP_vaddD(v_destination, 1, v_normalized, 1, v_result, 1, 8);
16729 
16730       current_dchannel = 0;
16731 
16732       destination[0] = (Float32) v_result[0];
16733       destination[(current_dchannel = dchannels)] = (Float32) v_result[1];
16734       destination[(current_dchannel += dchannels)] = (Float32) v_result[2];
16735       destination[(current_dchannel += dchannels)] = (Float32) v_result[3];
16736       destination[(current_dchannel += dchannels)] = (Float32) v_result[4];
16737       destination[(current_dchannel += dchannels)] = (Float32) v_result[5];
16738       destination[(current_dchannel += dchannels)] = (Float32) v_result[6];
16739       destination[(current_dchannel += dchannels)] = (Float32) v_result[7];
16740 
16741       /* iterate destination */
16742       destination += (current_dchannel + dchannels);
16743 
16744       /* iterate source */
16745       source += (current_schannel + schannels);
16746     }
16747   }
16748 #else
16749   /* unrolled function */
16750   if(count > 8){
16751     limit = count - (count % 8);
16752 
16753     for(; i < limit; i += 8){
16754       current_dchannel = 0;
16755       current_schannel = 0;
16756 
16757       destination[0] = (Float32) ((Float64) (destination[0] + (Float64) (source[0] / normalize_divisor)));
16758       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel = dchannels)] + (Float64) (source[(current_schannel = schannels)] / normalize_divisor)));
16759       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)] / normalize_divisor)));
16760       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)] / normalize_divisor)));
16761       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)] / normalize_divisor)));
16762       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)] / normalize_divisor)));
16763       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)] / normalize_divisor)));
16764       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)] / normalize_divisor)));
16765 
16766       /* iterate destination */
16767       destination += (current_dchannel + dchannels);
16768 
16769       /* iterate source */
16770       source += (current_schannel + schannels);
16771     }
16772   }
16773 #endif
16774 
16775   for(; i < count; i++){
16776     destination[0] = (Float32) ((Float64) (destination[0] + (Float64) (source[0] / normalize_divisor)));
16777 
16778     destination += dchannels;
16779     source += schannels;
16780   }
16781 }
16782 
16783 /**
16784  * ags_audio_buffer_util_copy_float_to_float32:
16785  * @destination: destination buffer
16786  * @dchannels: destination buffer's count of channels
16787  * @source: source buffer
16788  * @schannels: source buffer's count of channels
16789  * @count: number of frames to copy
16790  *
16791  * Copy audio data using additive strategy.
16792  *
16793  * Since: 3.0.0
16794  */
16795 void
ags_audio_buffer_util_copy_float_to_float32(Float32 * destination,guint dchannels,float * source,guint schannels,guint count)16796 ags_audio_buffer_util_copy_float_to_float32(Float32 *destination, guint dchannels,
16797 					    float *source, guint schannels,
16798 					    guint count)
16799 {
16800   guint limit;
16801   guint current_dchannel, current_schannel;
16802   guint i;
16803 
16804   if(destination == NULL ||
16805      source == NULL){
16806     return;
16807   }
16808 
16809   i = 0;
16810 
16811 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
16812   /* vectorized function */
16813   if(count > 8){
16814     limit = count - (count % 8);
16815 
16816     for(; i < limit; i += 8){
16817       ags_v8float v_destination;
16818       ags_v8float v_source;
16819 
16820       current_dchannel = 0;
16821       current_schannel = 0;
16822 
16823       v_destination = (ags_v8float) {(gfloat) destination[0],
16824 				     (gfloat) destination[(current_dchannel = dchannels)],
16825 				     (gfloat) destination[(current_dchannel += dchannels)],
16826 				     (gfloat) destination[(current_dchannel += dchannels)],
16827 				     (gfloat) destination[(current_dchannel += dchannels)],
16828 				     (gfloat) destination[(current_dchannel += dchannels)],
16829 				     (gfloat) destination[(current_dchannel += dchannels)],
16830 				     (gfloat) destination[(current_dchannel += dchannels)]};
16831 
16832       v_source = (ags_v8float) {source[0],
16833 				source[(current_schannel = schannels)],
16834 				source[(current_schannel += schannels)],
16835 				source[(current_schannel += schannels)],
16836 				source[(current_schannel += schannels)],
16837 				source[(current_schannel += schannels)],
16838 				source[(current_schannel += schannels)],
16839 				source[(current_schannel += schannels)]};
16840 
16841       /* just copy */
16842       v_destination += v_source;
16843 
16844       current_dchannel = 0;
16845 
16846       destination[0] = (Float32) v_destination[0];
16847       destination[(current_dchannel = dchannels)] = (Float32) v_destination[1];
16848       destination[(current_dchannel += dchannels)] = (Float32) v_destination[2];
16849       destination[(current_dchannel += dchannels)] = (Float32) v_destination[3];
16850       destination[(current_dchannel += dchannels)] = (Float32) v_destination[4];
16851       destination[(current_dchannel += dchannels)] = (Float32) v_destination[5];
16852       destination[(current_dchannel += dchannels)] = (Float32) v_destination[6];
16853       destination[(current_dchannel += dchannels)] = (Float32) v_destination[7];
16854 
16855       /* iterate destination */
16856       destination += (current_dchannel + dchannels);
16857 
16858       /* iterate source */
16859       source += (current_schannel + schannels);
16860     }
16861   }
16862 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
16863   /* vectorized function */
16864   if(count > 8){
16865     limit = count - (count % 8);
16866 
16867     for(; i < limit; i += 8){
16868       double v_result[8];
16869 
16870       current_dchannel = 0;
16871       current_schannel = 0;
16872 
16873       double v_destination[] = {(double) destination[0],
16874 				(double) destination[(current_dchannel = dchannels)],
16875 				(double) destination[(current_dchannel += dchannels)],
16876 				(double) destination[(current_dchannel += dchannels)],
16877 				(double) destination[(current_dchannel += dchannels)],
16878 				(double) destination[(current_dchannel += dchannels)],
16879 				(double) destination[(current_dchannel += dchannels)],
16880 				(double) destination[(current_dchannel += dchannels)]};
16881 
16882       double v_source[] = {(double) source[0],
16883 			   (double) source[(current_schannel = schannels)],
16884 			   (double) source[(current_schannel += schannels)],
16885 			   (double) source[(current_schannel += schannels)],
16886 			   (double) source[(current_schannel += schannels)],
16887 			   (double) source[(current_schannel += schannels)],
16888 			   (double) source[(current_schannel += schannels)],
16889 			   (double) source[(current_schannel += schannels)]};
16890 
16891       /* just copy */
16892       vDSP_vaddD(v_destination, 1, v_source, 1, v_result, 1, 8);
16893 
16894       current_dchannel = 0;
16895 
16896       destination[0] = (Float32) v_result[0];
16897       destination[(current_dchannel = dchannels)] = (Float32) v_result[1];
16898       destination[(current_dchannel += dchannels)] = (Float32) v_result[2];
16899       destination[(current_dchannel += dchannels)] = (Float32) v_result[3];
16900       destination[(current_dchannel += dchannels)] = (Float32) v_result[4];
16901       destination[(current_dchannel += dchannels)] = (Float32) v_result[5];
16902       destination[(current_dchannel += dchannels)] = (Float32) v_result[6];
16903       destination[(current_dchannel += dchannels)] = (Float32) v_result[7];
16904 
16905       /* iterate destination */
16906       destination += (current_dchannel + dchannels);
16907 
16908       /* iterate source */
16909       source += (current_schannel + schannels);
16910     }
16911   }
16912 #else
16913   /* unrolled function */
16914   if(count > 8){
16915     limit = count - (count % 8);
16916 
16917     for(; i < limit; i += 8){
16918       destination[0] = (Float32) ((Float64) (destination[0] + (Float64) (source[0])));
16919       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel = dchannels)] + (Float64) (source[(current_schannel = schannels)])));
16920       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)])));
16921       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)])));
16922       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)])));
16923       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)])));
16924       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)])));
16925       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)])));
16926 
16927       /* iterate destination */
16928       destination += (current_dchannel + dchannels);
16929 
16930       /* iterate source */
16931       source += (current_schannel + schannels);
16932     }
16933   }
16934 #endif
16935 
16936   for(; i < count; i++){
16937     destination[0] = (Float32) ((Float64) (destination[0] + (Float64) (source[0])));
16938 
16939     destination += dchannels;
16940     source += schannels;
16941   }
16942 }
16943 
16944 /**
16945  * ags_audio_buffer_util_copy_double_to_float32:
16946  * @destination: destination buffer
16947  * @dchannels: destination buffer's count of channels
16948  * @source: source buffer
16949  * @schannels: source buffer's count of channels
16950  * @count: number of frames to copy
16951  *
16952  * Copy audio data using additive strategy.
16953  *
16954  * Since: 3.0.0
16955  */
16956 void
ags_audio_buffer_util_copy_double_to_float32(Float32 * destination,guint dchannels,gdouble * source,guint schannels,guint count)16957 ags_audio_buffer_util_copy_double_to_float32(Float32 *destination, guint dchannels,
16958 					     gdouble *source, guint schannels,
16959 					     guint count)
16960 {
16961   guint limit;
16962   guint current_dchannel, current_schannel;
16963   guint i;
16964 
16965   if(destination == NULL ||
16966      source == NULL){
16967     return;
16968   }
16969 
16970   i = 0;
16971 
16972 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
16973   /* vectorized function */
16974   if(count > 8){
16975     limit = count - (count % 8);
16976 
16977     for(; i < limit; i += 8){
16978       ags_v8float v_destination;
16979       ags_v8float v_source;
16980 
16981       current_dchannel = 0;
16982       current_schannel = 0;
16983 
16984       v_destination = (ags_v8float) {(gfloat) destination[0],
16985 				     (gfloat) destination[(current_dchannel = dchannels)],
16986 				     (gfloat) destination[(current_dchannel += dchannels)],
16987 				     (gfloat) destination[(current_dchannel += dchannels)],
16988 				     (gfloat) destination[(current_dchannel += dchannels)],
16989 				     (gfloat) destination[(current_dchannel += dchannels)],
16990 				     (gfloat) destination[(current_dchannel += dchannels)],
16991 				     (gfloat) destination[(current_dchannel += dchannels)]};
16992 
16993       v_source = (ags_v8float) {(gfloat) source[0],
16994 				(gfloat) source[(current_schannel = schannels)],
16995 				(gfloat) source[(current_schannel += schannels)],
16996 				(gfloat) source[(current_schannel += schannels)],
16997 				(gfloat) source[(current_schannel += schannels)],
16998 				(gfloat) source[(current_schannel += schannels)],
16999 				(gfloat) source[(current_schannel += schannels)],
17000 				(gfloat) source[(current_schannel += schannels)]};
17001 
17002       /* just copy */
17003       v_destination += v_source;
17004 
17005       current_dchannel = 0;
17006 
17007       destination[0] = (Float32) v_destination[0];
17008       destination[(current_dchannel = dchannels)] = (Float32) v_destination[1];
17009       destination[(current_dchannel += dchannels)] = (Float32) v_destination[2];
17010       destination[(current_dchannel += dchannels)] = (Float32) v_destination[3];
17011       destination[(current_dchannel += dchannels)] = (Float32) v_destination[4];
17012       destination[(current_dchannel += dchannels)] = (Float32) v_destination[5];
17013       destination[(current_dchannel += dchannels)] = (Float32) v_destination[6];
17014       destination[(current_dchannel += dchannels)] = (Float32) v_destination[7];
17015 
17016       /* iterate destination */
17017       destination += (current_dchannel + dchannels);
17018 
17019       /* iterate source */
17020       source += (current_schannel + schannels);
17021     }
17022   }
17023 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
17024   /* vectorized function */
17025   if(count > 8){
17026     limit = count - (count % 8);
17027 
17028     for(; i < limit; i += 8){
17029       double v_result[8];
17030 
17031       current_dchannel = 0;
17032       current_schannel = 0;
17033 
17034       double v_destination[] = {(double) destination[0],
17035 				(double) destination[(current_dchannel = dchannels)],
17036 				(double) destination[(current_dchannel += dchannels)],
17037 				(double) destination[(current_dchannel += dchannels)],
17038 				(double) destination[(current_dchannel += dchannels)],
17039 				(double) destination[(current_dchannel += dchannels)],
17040 				(double) destination[(current_dchannel += dchannels)],
17041 				(double) destination[(current_dchannel += dchannels)]};
17042 
17043       double v_source[] = {(double) source[0],
17044 			   (double) source[(current_schannel = schannels)],
17045 			   (double) source[(current_schannel += schannels)],
17046 			   (double) source[(current_schannel += schannels)],
17047 			   (double) source[(current_schannel += schannels)],
17048 			   (double) source[(current_schannel += schannels)],
17049 			   (double) source[(current_schannel += schannels)],
17050 			   (double) source[(current_schannel += schannels)]};
17051 
17052       /* just copy */
17053       vDSP_vaddD(v_destination, 1, v_source, 1, v_result, 1, 8);
17054 
17055       current_dchannel = 0;
17056 
17057       destination[0] = (Float32) v_result[0];
17058       destination[(current_dchannel = dchannels)] = (Float32) v_result[1];
17059       destination[(current_dchannel += dchannels)] = (Float32) v_result[2];
17060       destination[(current_dchannel += dchannels)] = (Float32) v_result[3];
17061       destination[(current_dchannel += dchannels)] = (Float32) v_result[4];
17062       destination[(current_dchannel += dchannels)] = (Float32) v_result[5];
17063       destination[(current_dchannel += dchannels)] = (Float32) v_result[6];
17064       destination[(current_dchannel += dchannels)] = (Float32) v_result[7];
17065 
17066       /* iterate destination */
17067       destination += (current_dchannel + dchannels);
17068 
17069       /* iterate source */
17070       source += (current_schannel + schannels);
17071     }
17072   }
17073 #else
17074   /* unrolled function */
17075   if(count > 8){
17076     limit = count - (count % 8);
17077 
17078     for(; i < limit; i += 8){
17079       destination[0] = (Float32) ((Float64) (destination[0] + (Float64) (source[0])));
17080       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel = dchannels)] + (Float64) (source[(current_schannel = schannels)])));
17081       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)])));
17082       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)])));
17083       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)])));
17084       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)])));
17085       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)])));
17086       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)])));
17087 
17088       /* iterate destination */
17089       destination += (current_dchannel + dchannels);
17090 
17091       /* iterate source */
17092       source += (current_schannel + schannels);
17093     }
17094   }
17095 #endif
17096 
17097   for(; i < count; i++){
17098     destination[0] = (Float32) ((Float64) (destination[0] + (Float64) (source[0])));
17099 
17100     destination += dchannels;
17101     source += schannels;
17102   }
17103 }
17104 
17105 /**
17106  * ags_audio_buffer_util_copy_float32_to_float32:
17107  * @destination: destination buffer
17108  * @dchannels: destination buffer's count of channels
17109  * @source: source buffer
17110  * @schannels: source buffer's count of channels
17111  * @count: number of frames to copy
17112  *
17113  * Copy audio data using additive strategy.
17114  *
17115  * Since: 3.0.0
17116  */
17117 void
ags_audio_buffer_util_copy_float32_to_float32(Float32 * destination,guint dchannels,Float32 * source,guint schannels,guint count)17118 ags_audio_buffer_util_copy_float32_to_float32(Float32 *destination, guint dchannels,
17119 					      Float32 *source, guint schannels,
17120 					      guint count)
17121 {
17122   guint limit;
17123   guint current_dchannel, current_schannel;
17124   guint i;
17125 
17126   if(destination == NULL ||
17127      source == NULL){
17128     return;
17129   }
17130 
17131   i = 0;
17132 
17133 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
17134   /* vectorized function */
17135   if(count > 8){
17136     limit = count - (count % 8);
17137 
17138     for(; i < limit; i += 8){
17139       ags_v8float v_destination;
17140       ags_v8float v_source;
17141 
17142       current_dchannel = 0;
17143       current_schannel = 0;
17144 
17145       v_destination = (ags_v8float) {(gfloat) destination[0],
17146 				     (gfloat) destination[(current_dchannel = dchannels)],
17147 				     (gfloat) destination[(current_dchannel += dchannels)],
17148 				     (gfloat) destination[(current_dchannel += dchannels)],
17149 				     (gfloat) destination[(current_dchannel += dchannels)],
17150 				     (gfloat) destination[(current_dchannel += dchannels)],
17151 				     (gfloat) destination[(current_dchannel += dchannels)],
17152 				     (gfloat) destination[(current_dchannel += dchannels)]};
17153 
17154       v_source = (ags_v8float) {(gfloat) source[0],
17155 				(gfloat) source[(current_schannel = schannels)],
17156 				(gfloat) source[(current_schannel += schannels)],
17157 				(gfloat) source[(current_schannel += schannels)],
17158 				(gfloat) source[(current_schannel += schannels)],
17159 				(gfloat) source[(current_schannel += schannels)],
17160 				(gfloat) source[(current_schannel += schannels)],
17161 				(gfloat) source[(current_schannel += schannels)]};
17162 
17163       /* just copy */
17164       v_destination += v_source;
17165 
17166       current_dchannel = 0;
17167 
17168       destination[0] = v_destination[0];
17169       destination[(current_dchannel = dchannels)] = (Float32) v_destination[1];
17170       destination[(current_dchannel += dchannels)] = (Float32) v_destination[2];
17171       destination[(current_dchannel += dchannels)] = (Float32) v_destination[3];
17172       destination[(current_dchannel += dchannels)] = (Float32) v_destination[4];
17173       destination[(current_dchannel += dchannels)] = (Float32) v_destination[5];
17174       destination[(current_dchannel += dchannels)] = (Float32) v_destination[6];
17175       destination[(current_dchannel += dchannels)] = (Float32) v_destination[7];
17176 
17177       /* iterate destination */
17178       destination += (current_dchannel + dchannels);
17179 
17180       /* iterate source */
17181       source += (current_schannel + schannels);
17182     }
17183   }
17184 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
17185   /* vectorized function */
17186   if(count > 8){
17187     limit = count - (count % 8);
17188 
17189     for(; i < limit; i += 8){
17190       double v_result[8];
17191 
17192       current_dchannel = 0;
17193       current_schannel = 0;
17194 
17195       double v_destination[] = {(double) destination[0],
17196 				(double) destination[(current_dchannel = dchannels)],
17197 				(double) destination[(current_dchannel += dchannels)],
17198 				(double) destination[(current_dchannel += dchannels)],
17199 				(double) destination[(current_dchannel += dchannels)],
17200 				(double) destination[(current_dchannel += dchannels)],
17201 				(double) destination[(current_dchannel += dchannels)],
17202 				(double) destination[(current_dchannel += dchannels)]};
17203 
17204       double v_source[] = {(double) source[0],
17205 			   (double) source[(current_schannel = schannels)],
17206 			   (double) source[(current_schannel += schannels)],
17207 			   (double) source[(current_schannel += schannels)],
17208 			   (double) source[(current_schannel += schannels)],
17209 			   (double) source[(current_schannel += schannels)],
17210 			   (double) source[(current_schannel += schannels)],
17211 			   (double) source[(current_schannel += schannels)]};
17212 
17213       /* just copy */
17214       vDSP_vaddD(v_destination, 1, v_source, 1, v_result, 1, 8);
17215 
17216       current_dchannel = 0;
17217 
17218       destination[0] = (Float32) v_result[0];
17219       destination[(current_dchannel = dchannels)] = (Float32) v_result[1];
17220       destination[(current_dchannel += dchannels)] = (Float32) v_result[2];
17221       destination[(current_dchannel += dchannels)] = (Float32) v_result[3];
17222       destination[(current_dchannel += dchannels)] = (Float32) v_result[4];
17223       destination[(current_dchannel += dchannels)] = (Float32) v_result[5];
17224       destination[(current_dchannel += dchannels)] = (Float32) v_result[6];
17225       destination[(current_dchannel += dchannels)] = (Float32) v_result[7];
17226 
17227       /* iterate destination */
17228       destination += (current_dchannel + dchannels);
17229 
17230       /* iterate source */
17231       source += (current_schannel + schannels);
17232     }
17233   }
17234 #else
17235   /* unrolled function */
17236   if(count > 8){
17237     limit = count - (count % 8);
17238 
17239     for(; i < limit; i += 8){
17240       destination[0] = (Float32) ((Float64) (destination[0] + (Float64) (source[0])));
17241       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel = dchannels)] + (Float64) (source[(current_schannel = schannels)])));
17242       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)])));
17243       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)])));
17244       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)])));
17245       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)])));
17246       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)])));
17247       destination[current_dchannel] = (Float32) ((Float64) (destination[(current_dchannel += dchannels)] + (Float64) (source[(current_schannel += schannels)])));
17248 
17249       /* iterate destination */
17250       destination += (current_dchannel + dchannels);
17251 
17252       /* iterate source */
17253       source += (current_schannel + schannels);
17254     }
17255   }
17256 #endif
17257 
17258   for(; i < count; i++){
17259     destination[0] = (Float32) ((Float64) (destination[0] + (Float64) (source[0])));
17260 
17261     destination += dchannels;
17262     source += schannels;
17263   }
17264 }
17265 
17266 /**
17267  * ags_audio_buffer_util_copy_float32_to_s8:
17268  * @destination: destination buffer
17269  * @dchannels: destination buffer's count of channels
17270  * @source: source buffer
17271  * @schannels: source buffer's count of channels
17272  * @count: number of frames to copy
17273  *
17274  * Copy audio data using additive strategy.
17275  *
17276  * Since: 3.0.0
17277  */
17278 void
ags_audio_buffer_util_copy_float32_to_s8(gint8 * destination,guint dchannels,Float32 * source,guint schannels,guint count)17279 ags_audio_buffer_util_copy_float32_to_s8(gint8 *destination, guint dchannels,
17280 					 Float32 *source, guint schannels,
17281 					 guint count)
17282 {
17283   //NOTE:JK: scale = (2^bits_source / 2.0 - 1.0)
17284   static const gdouble scale = 127.0;
17285   guint limit;
17286   guint current_dchannel, current_schannel;
17287   guint i;
17288 
17289   if(destination == NULL ||
17290      source == NULL){
17291     return;
17292   }
17293 
17294   i = 0;
17295 
17296 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
17297   /* vectorized function */
17298   if(count > 8){
17299     limit = count - (count % 8);
17300 
17301     for(; i < limit; i += 8){
17302       ags_v8float v_destination;
17303       ags_v8float v_source;
17304 
17305       current_dchannel = 0;
17306       current_schannel = 0;
17307 
17308       v_destination = (ags_v8float) {(gfloat) destination[0],
17309 				     (gfloat) destination[(current_dchannel = dchannels)],
17310 				     (gfloat) destination[(current_dchannel += dchannels)],
17311 				     (gfloat) destination[(current_dchannel += dchannels)],
17312 				     (gfloat) destination[(current_dchannel += dchannels)],
17313 				     (gfloat) destination[(current_dchannel += dchannels)],
17314 				     (gfloat) destination[(current_dchannel += dchannels)],
17315 				     (gfloat) destination[(current_dchannel += dchannels)]};
17316 
17317       v_source = (ags_v8float) {(gfloat) source[0],
17318 				(gfloat) source[(current_schannel = schannels)],
17319 				(gfloat) source[(current_schannel += schannels)],
17320 				(gfloat) source[(current_schannel += schannels)],
17321 				(gfloat) source[(current_schannel += schannels)],
17322 				(gfloat) source[(current_schannel += schannels)],
17323 				(gfloat) source[(current_schannel += schannels)],
17324 				(gfloat) source[(current_schannel += schannels)]};
17325 
17326       /* scale and copy */
17327       v_source *= (gfloat) scale;
17328       v_destination += v_source;
17329 
17330       current_dchannel = 0;
17331 
17332       destination[0] = (gint8) v_destination[0];
17333       destination[(current_dchannel = dchannels)] = (gint8) v_destination[1];
17334       destination[(current_dchannel += dchannels)] = (gint8) v_destination[2];
17335       destination[(current_dchannel += dchannels)] = (gint8) v_destination[3];
17336       destination[(current_dchannel += dchannels)] = (gint8) v_destination[4];
17337       destination[(current_dchannel += dchannels)] = (gint8) v_destination[5];
17338       destination[(current_dchannel += dchannels)] = (gint8) v_destination[6];
17339       destination[(current_dchannel += dchannels)] = (gint8) v_destination[7];
17340 
17341       /* iterate destination */
17342       destination += (current_dchannel + dchannels);
17343 
17344       /* iterate source */
17345       source += (current_schannel + schannels);
17346     }
17347   }
17348 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
17349   /* vectorized function */
17350   if(count > 8){
17351     limit = count - (count % 8);
17352 
17353     for(; i < limit; i += 8){
17354       double v_scaled[8];
17355       double v_result[8];
17356       static const double v_scale[1] = { (double) scale };
17357 
17358       current_dchannel = 0;
17359       current_schannel = 0;
17360 
17361       double v_destination[] = {(double) destination[0],
17362 				(double) destination[(current_dchannel = dchannels)],
17363 				(double) destination[(current_dchannel += dchannels)],
17364 				(double) destination[(current_dchannel += dchannels)],
17365 				(double) destination[(current_dchannel += dchannels)],
17366 				(double) destination[(current_dchannel += dchannels)],
17367 				(double) destination[(current_dchannel += dchannels)],
17368 				(double) destination[(current_dchannel += dchannels)]};
17369 
17370       double v_source[] = {(double) source[0],
17371 			   (double) source[(current_schannel = schannels)],
17372 			   (double) source[(current_schannel += schannels)],
17373 			   (double) source[(current_schannel += schannels)],
17374 			   (double) source[(current_schannel += schannels)],
17375 			   (double) source[(current_schannel += schannels)],
17376 			   (double) source[(current_schannel += schannels)],
17377 			   (double) source[(current_schannel += schannels)]};
17378 
17379       /* scale and copy */
17380       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
17381       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
17382 
17383       current_dchannel = 0;
17384 
17385       destination[0] = (gint8) v_result[0];
17386       destination[(current_dchannel = dchannels)] = (gint8) v_result[1];
17387       destination[(current_dchannel += dchannels)] = (gint8) v_result[2];
17388       destination[(current_dchannel += dchannels)] = (gint8) v_result[3];
17389       destination[(current_dchannel += dchannels)] = (gint8) v_result[4];
17390       destination[(current_dchannel += dchannels)] = (gint8) v_result[5];
17391       destination[(current_dchannel += dchannels)] = (gint8) v_result[6];
17392       destination[(current_dchannel += dchannels)] = (gint8) v_result[7];
17393 
17394       /* iterate destination */
17395       destination += (current_dchannel + dchannels);
17396 
17397       /* iterate source */
17398       source += (current_schannel + schannels);
17399     }
17400   }
17401 #else
17402   /* unrolled function */
17403   if(count > 8){
17404     limit = count - (count % 8);
17405 
17406     for(; i < limit; i += 8){
17407       current_dchannel = 0;
17408       current_schannel = 0;
17409 
17410       destination[0] = 0xff & (gint8) ((gdouble) (destination[0] + (gdouble) (scale * source[0])));
17411       destination[current_dchannel] = 0xff & (gint8) ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (scale * source[(current_schannel = schannels)])));
17412       destination[current_dchannel] = 0xff & (gint8) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
17413       destination[current_dchannel] = 0xff & (gint8) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
17414       destination[current_dchannel] = 0xff & (gint8) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
17415       destination[current_dchannel] = 0xff & (gint8) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
17416       destination[current_dchannel] = 0xff & (gint8) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
17417       destination[current_dchannel] = 0xff & (gint8) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
17418 
17419       /* iterate destination */
17420       destination += (current_dchannel + dchannels);
17421 
17422       /* iterate source */
17423       source += (current_schannel + schannels);
17424     }
17425   }
17426 #endif
17427 
17428   for(; i < count; i++){
17429     destination[0] = 0xff & (gint8) ((gdouble) (destination[0] + (gdouble) (scale * source[0])));
17430 
17431     destination += dchannels;
17432     source += schannels;
17433   }
17434 }
17435 
17436 /**
17437  * ags_audio_buffer_util_copy_float32_to_s16:
17438  * @destination: destination buffer
17439  * @dchannels: destination buffer's count of channels
17440  * @source: source buffer
17441  * @schannels: source buffer's count of channels
17442  * @count: number of frames to copy
17443  *
17444  * Copy audio data using additive strategy.
17445  *
17446  * Since: 3.0.0
17447  */
17448 void
ags_audio_buffer_util_copy_float32_to_s16(gint16 * destination,guint dchannels,Float32 * source,guint schannels,guint count)17449 ags_audio_buffer_util_copy_float32_to_s16(gint16 *destination, guint dchannels,
17450 					  Float32 *source, guint schannels,
17451 					  guint count)
17452 {
17453   //NOTE:JK: scale = (2^bits_source / 2.0 - 1.0)
17454   static const gdouble scale = 32767.0;
17455   guint limit;
17456   guint current_dchannel, current_schannel;
17457   guint i;
17458 
17459   if(destination == NULL ||
17460      source == NULL){
17461     return;
17462   }
17463 
17464   i = 0;
17465 
17466 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
17467   /* vectorized function */
17468   if(count > 8){
17469     limit = count - (count % 8);
17470 
17471     for(; i < limit; i += 8){
17472       ags_v8float v_destination;
17473       ags_v8float v_source;
17474 
17475       current_dchannel = 0;
17476       current_schannel = 0;
17477 
17478       v_destination = (ags_v8float) {(gfloat) destination[0],
17479 				     (gfloat) destination[(current_dchannel = dchannels)],
17480 				     (gfloat) destination[(current_dchannel += dchannels)],
17481 				     (gfloat) destination[(current_dchannel += dchannels)],
17482 				     (gfloat) destination[(current_dchannel += dchannels)],
17483 				     (gfloat) destination[(current_dchannel += dchannels)],
17484 				     (gfloat) destination[(current_dchannel += dchannels)],
17485 				     (gfloat) destination[(current_dchannel += dchannels)]};
17486 
17487       v_source = (ags_v8float) {(gfloat) source[0],
17488 				(gfloat) source[(current_schannel = schannels)],
17489 				(gfloat) source[(current_schannel += schannels)],
17490 				(gfloat) source[(current_schannel += schannels)],
17491 				(gfloat) source[(current_schannel += schannels)],
17492 				(gfloat) source[(current_schannel += schannels)],
17493 				(gfloat) source[(current_schannel += schannels)],
17494 				(gfloat) source[(current_schannel += schannels)]};
17495 
17496       /* scale and copy */
17497       v_source *= (gfloat) scale;
17498       v_destination += v_source;
17499 
17500       current_dchannel = 0;
17501 
17502       destination[0] = (gint16) v_destination[0];
17503       destination[(current_dchannel = dchannels)] = (gint16) v_destination[1];
17504       destination[(current_dchannel += dchannels)] = (gint16) v_destination[2];
17505       destination[(current_dchannel += dchannels)] = (gint16) v_destination[3];
17506       destination[(current_dchannel += dchannels)] = (gint16) v_destination[4];
17507       destination[(current_dchannel += dchannels)] = (gint16) v_destination[5];
17508       destination[(current_dchannel += dchannels)] = (gint16) v_destination[6];
17509       destination[(current_dchannel += dchannels)] = (gint16) v_destination[7];
17510 
17511       /* iterate destination */
17512       destination += (current_dchannel + dchannels);
17513 
17514       /* iterate source */
17515       source += (current_schannel + schannels);
17516     }
17517   }
17518 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
17519   /* vectorized function */
17520   if(count > 8){
17521     limit = count - (count % 8);
17522 
17523     for(; i < limit; i += 8){
17524       double v_scaled[8];
17525       double v_result[8];
17526       static const double v_scale[1] = { (double) scale };
17527 
17528       current_dchannel = 0;
17529       current_schannel = 0;
17530 
17531       double v_destination[] = {(double) destination[0],
17532 				(double) destination[(current_dchannel = dchannels)],
17533 				(double) destination[(current_dchannel += dchannels)],
17534 				(double) destination[(current_dchannel += dchannels)],
17535 				(double) destination[(current_dchannel += dchannels)],
17536 				(double) destination[(current_dchannel += dchannels)],
17537 				(double) destination[(current_dchannel += dchannels)],
17538 				(double) destination[(current_dchannel += dchannels)]};
17539 
17540       double v_source[] = {(double) source[0],
17541 			   (double) source[(current_schannel = schannels)],
17542 			   (double) source[(current_schannel += schannels)],
17543 			   (double) source[(current_schannel += schannels)],
17544 			   (double) source[(current_schannel += schannels)],
17545 			   (double) source[(current_schannel += schannels)],
17546 			   (double) source[(current_schannel += schannels)],
17547 			   (double) source[(current_schannel += schannels)]};
17548 
17549       /* scale and copy */
17550       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
17551       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
17552 
17553       current_dchannel = 0;
17554 
17555       destination[0] = (gint16) v_result[0];
17556       destination[(current_dchannel = dchannels)] = (gint16) v_result[1];
17557       destination[(current_dchannel += dchannels)] = (gint16) v_result[2];
17558       destination[(current_dchannel += dchannels)] = (gint16) v_result[3];
17559       destination[(current_dchannel += dchannels)] = (gint16) v_result[4];
17560       destination[(current_dchannel += dchannels)] = (gint16) v_result[5];
17561       destination[(current_dchannel += dchannels)] = (gint16) v_result[6];
17562       destination[(current_dchannel += dchannels)] = (gint16) v_result[7];
17563 
17564       /* iterate destination */
17565       destination += (current_dchannel + dchannels);
17566 
17567       /* iterate source */
17568       source += (current_schannel + schannels);
17569     }
17570   }
17571 #else
17572   /* unrolled function */
17573   if(count > 8){
17574     limit = count - (count % 8);
17575 
17576     for(; i < limit; i += 8){
17577       current_dchannel = 0;
17578       current_schannel = 0;
17579 
17580       destination[0] = 0xffff & (gint16) ((gdouble) (destination[0] + (gdouble) (scale * source[0])));
17581       destination[current_dchannel] = 0xffff & (gint16) ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (scale * source[(current_schannel = schannels)])));
17582       destination[current_dchannel] = 0xffff & (gint16) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
17583       destination[current_dchannel] = 0xffff & (gint16) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
17584       destination[current_dchannel] = 0xffff & (gint16) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
17585       destination[current_dchannel] = 0xffff & (gint16) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
17586       destination[current_dchannel] = 0xffff & (gint16) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
17587       destination[current_dchannel] = 0xffff & (gint16) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
17588 
17589       /* iterate destination */
17590       destination += (current_dchannel + dchannels);
17591 
17592       /* iterate source */
17593       source += (current_schannel + schannels);
17594     }
17595   }
17596 #endif
17597 
17598   for(; i < count; i++){
17599     destination[0] = 0xffff & (gint16) ((gdouble) (destination[0] + (gdouble) (scale * source[0])));
17600 
17601     destination += dchannels;
17602     source += schannels;
17603   }
17604 }
17605 
17606 /**
17607  * ags_audio_buffer_util_copy_float32_to_s24:
17608  * @destination: destination buffer
17609  * @dchannels: destination buffer's count of channels
17610  * @source: source buffer
17611  * @schannels: source buffer's count of channels
17612  * @count: number of frames to copy
17613  *
17614  * Copy audio data using additive strategy.
17615  *
17616  * Since: 3.0.0
17617  */
17618 void
ags_audio_buffer_util_copy_float32_to_s24(gint32 * destination,guint dchannels,Float32 * source,guint schannels,guint count)17619 ags_audio_buffer_util_copy_float32_to_s24(gint32 *destination, guint dchannels,
17620 					  Float32 *source, guint schannels,
17621 					  guint count)
17622 {
17623   //NOTE:JK: scale = (2^bits_source / 2.0 - 1.0)
17624   static const gdouble scale = 8388607.0;
17625   guint limit;
17626   guint current_dchannel, current_schannel;
17627   guint i;
17628 
17629   if(destination == NULL ||
17630      source == NULL){
17631     return;
17632   }
17633 
17634   i = 0;
17635 
17636 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
17637   /* vectorized function */
17638   if(count > 8){
17639     limit = count - (count % 8);
17640 
17641     for(; i < limit; i += 8){
17642       ags_v8float v_destination;
17643       ags_v8float v_source;
17644 
17645       current_dchannel = 0;
17646       current_schannel = 0;
17647 
17648       v_destination = (ags_v8float) {(gfloat) destination[0],
17649 				     (gfloat) destination[(current_dchannel = dchannels)],
17650 				     (gfloat) destination[(current_dchannel += dchannels)],
17651 				     (gfloat) destination[(current_dchannel += dchannels)],
17652 				     (gfloat) destination[(current_dchannel += dchannels)],
17653 				     (gfloat) destination[(current_dchannel += dchannels)],
17654 				     (gfloat) destination[(current_dchannel += dchannels)],
17655 				     (gfloat) destination[(current_dchannel += dchannels)]};
17656 
17657       v_source = (ags_v8float) {(gfloat) source[0],
17658 				(gfloat) source[(current_schannel = schannels)],
17659 				(gfloat) source[(current_schannel += schannels)],
17660 				(gfloat) source[(current_schannel += schannels)],
17661 				(gfloat) source[(current_schannel += schannels)],
17662 				(gfloat) source[(current_schannel += schannels)],
17663 				(gfloat) source[(current_schannel += schannels)],
17664 				(gfloat) source[(current_schannel += schannels)]};
17665 
17666       /* scale and copy */
17667       v_source *= (gfloat) scale;
17668       v_destination += v_source;
17669 
17670       current_dchannel = 0;
17671 
17672       destination[0] = (gint32) v_destination[0];
17673       destination[(current_dchannel = dchannels)] = (gint32) v_destination[1];
17674       destination[(current_dchannel += dchannels)] = (gint32) v_destination[2];
17675       destination[(current_dchannel += dchannels)] = (gint32) v_destination[3];
17676       destination[(current_dchannel += dchannels)] = (gint32) v_destination[4];
17677       destination[(current_dchannel += dchannels)] = (gint32) v_destination[5];
17678       destination[(current_dchannel += dchannels)] = (gint32) v_destination[6];
17679       destination[(current_dchannel += dchannels)] = (gint32) v_destination[7];
17680 
17681       /* iterate destination */
17682       destination += (current_dchannel + dchannels);
17683 
17684       /* iterate source */
17685       source += (current_schannel + schannels);
17686     }
17687   }
17688 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
17689   /* vectorized function */
17690   if(count > 8){
17691     limit = count - (count % 8);
17692 
17693     for(; i < limit; i += 8){
17694       double v_scaled[8];
17695       double v_result[8];
17696       static const double v_scale[1] = { (double) scale };
17697 
17698       current_dchannel = 0;
17699       current_schannel = 0;
17700 
17701       double v_destination[] = {(double) destination[0],
17702 				(double) destination[(current_dchannel = dchannels)],
17703 				(double) destination[(current_dchannel += dchannels)],
17704 				(double) destination[(current_dchannel += dchannels)],
17705 				(double) destination[(current_dchannel += dchannels)],
17706 				(double) destination[(current_dchannel += dchannels)],
17707 				(double) destination[(current_dchannel += dchannels)],
17708 				(double) destination[(current_dchannel += dchannels)]};
17709 
17710       double v_source[] = {(double) source[0],
17711 			   (double) source[(current_schannel = schannels)],
17712 			   (double) source[(current_schannel += schannels)],
17713 			   (double) source[(current_schannel += schannels)],
17714 			   (double) source[(current_schannel += schannels)],
17715 			   (double) source[(current_schannel += schannels)],
17716 			   (double) source[(current_schannel += schannels)],
17717 			   (double) source[(current_schannel += schannels)]};
17718 
17719       /* scale and copy */
17720       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
17721       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
17722 
17723       current_dchannel = 0;
17724 
17725       destination[0] = (gint32) v_result[0];
17726       destination[(current_dchannel = dchannels)] = (gint32) v_result[1];
17727       destination[(current_dchannel += dchannels)] = (gint32) v_result[2];
17728       destination[(current_dchannel += dchannels)] = (gint32) v_result[3];
17729       destination[(current_dchannel += dchannels)] = (gint32) v_result[4];
17730       destination[(current_dchannel += dchannels)] = (gint32) v_result[5];
17731       destination[(current_dchannel += dchannels)] = (gint32) v_result[6];
17732       destination[(current_dchannel += dchannels)] = (gint32) v_result[7];
17733 
17734       /* iterate destination */
17735       destination += (current_dchannel + dchannels);
17736 
17737       /* iterate source */
17738       source += (current_schannel + schannels);
17739     }
17740   }
17741 #else
17742   /* unrolled function */
17743   if(count > 8){
17744     limit = count - (count % 8);
17745 
17746     for(; i < limit; i += 8){
17747       current_dchannel = 0;
17748       current_schannel = 0;
17749 
17750       destination[0] = 0xffffffff & (gint32) ((gdouble) (destination[0] + (gdouble) (scale * source[0])));
17751       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (scale * source[(current_schannel = schannels)])));
17752       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
17753       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
17754       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
17755       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
17756       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
17757       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
17758 
17759       /* iterate destination */
17760       destination += (current_dchannel + dchannels);
17761 
17762       /* iterate source */
17763       source += (current_schannel + schannels);
17764     }
17765   }
17766 #endif
17767 
17768   for(; i < count; i++){
17769     destination[0] = 0xffffffff & (gint32) ((gdouble) (destination[0] + (gdouble) (scale * source[0])));
17770 
17771     destination += dchannels;
17772     source += schannels;
17773   }
17774 }
17775 
17776 /**
17777  * ags_audio_buffer_util_copy_float32_to_s32:
17778  * @destination: destination buffer
17779  * @dchannels: destination buffer's count of channels
17780  * @source: source buffer
17781  * @schannels: source buffer's count of channels
17782  * @count: number of frames to copy
17783  *
17784  * Copy audio data using additive strategy.
17785  *
17786  * Since: 3.0.0
17787  */
17788 void
ags_audio_buffer_util_copy_float32_to_s32(gint32 * destination,guint dchannels,Float32 * source,guint schannels,guint count)17789 ags_audio_buffer_util_copy_float32_to_s32(gint32 *destination, guint dchannels,
17790 					  Float32 *source, guint schannels,
17791 					  guint count)
17792 {
17793   //NOTE:JK: scale = (2^bits_source / 2.0 - 1.0)
17794   static const gdouble scale = 214748363.0;
17795   guint limit;
17796   guint current_dchannel, current_schannel;
17797   guint i;
17798 
17799   if(destination == NULL ||
17800      source == NULL){
17801     return;
17802   }
17803 
17804   i = 0;
17805 
17806 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
17807   /* vectorized function */
17808   if(count > 8){
17809     limit = count - (count % 8);
17810 
17811     for(; i < limit; i += 8){
17812       ags_v8float v_destination;
17813       ags_v8float v_source;
17814 
17815       current_dchannel = 0;
17816       current_schannel = 0;
17817 
17818       v_destination = (ags_v8float) {(gfloat) destination[0],
17819 				     (gfloat) destination[(current_dchannel = dchannels)],
17820 				     (gfloat) destination[(current_dchannel += dchannels)],
17821 				     (gfloat) destination[(current_dchannel += dchannels)],
17822 				     (gfloat) destination[(current_dchannel += dchannels)],
17823 				     (gfloat) destination[(current_dchannel += dchannels)],
17824 				     (gfloat) destination[(current_dchannel += dchannels)],
17825 				     (gfloat) destination[(current_dchannel += dchannels)]};
17826 
17827       v_source = (ags_v8float) {(gfloat) source[0],
17828 				(gfloat) source[(current_schannel = schannels)],
17829 				(gfloat) source[(current_schannel += schannels)],
17830 				(gfloat) source[(current_schannel += schannels)],
17831 				(gfloat) source[(current_schannel += schannels)],
17832 				(gfloat) source[(current_schannel += schannels)],
17833 				(gfloat) source[(current_schannel += schannels)],
17834 				(gfloat) source[(current_schannel += schannels)]};
17835 
17836       /* scale and copy */
17837       v_source *= (gfloat) scale;
17838       v_destination += v_source;
17839 
17840       current_dchannel = 0;
17841 
17842       destination[0] = (gint32) v_destination[0];
17843       destination[(current_dchannel = dchannels)] = (gint32) v_destination[1];
17844       destination[(current_dchannel += dchannels)] = (gint32) v_destination[2];
17845       destination[(current_dchannel += dchannels)] = (gint32) v_destination[3];
17846       destination[(current_dchannel += dchannels)] = (gint32) v_destination[4];
17847       destination[(current_dchannel += dchannels)] = (gint32) v_destination[5];
17848       destination[(current_dchannel += dchannels)] = (gint32) v_destination[6];
17849       destination[(current_dchannel += dchannels)] = (gint32) v_destination[7];
17850 
17851       /* iterate destination */
17852       destination += (current_dchannel + dchannels);
17853 
17854       /* iterate source */
17855       source += (current_schannel + schannels);
17856     }
17857   }
17858 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
17859   /* vectorized function */
17860   if(count > 8){
17861     limit = count - (count % 8);
17862 
17863     for(; i < limit; i += 8){
17864       double v_scaled[8];
17865       double v_result[8];
17866       static const double v_scale[1] = { (double) scale };
17867 
17868       current_dchannel = 0;
17869       current_schannel = 0;
17870 
17871       double v_destination[] = {(double) destination[0],
17872 				(double) destination[(current_dchannel = dchannels)],
17873 				(double) destination[(current_dchannel += dchannels)],
17874 				(double) destination[(current_dchannel += dchannels)],
17875 				(double) destination[(current_dchannel += dchannels)],
17876 				(double) destination[(current_dchannel += dchannels)],
17877 				(double) destination[(current_dchannel += dchannels)],
17878 				(double) destination[(current_dchannel += dchannels)]};
17879 
17880       double v_source[] = {(double) source[0],
17881 			   (double) source[(current_schannel = schannels)],
17882 			   (double) source[(current_schannel += schannels)],
17883 			   (double) source[(current_schannel += schannels)],
17884 			   (double) source[(current_schannel += schannels)],
17885 			   (double) source[(current_schannel += schannels)],
17886 			   (double) source[(current_schannel += schannels)],
17887 			   (double) source[(current_schannel += schannels)]};
17888 
17889       /* scale and copy */
17890       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
17891       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
17892 
17893       current_dchannel = 0;
17894 
17895       destination[0] = (gint32) v_result[0];
17896       destination[(current_dchannel = dchannels)] = (gint32) v_result[1];
17897       destination[(current_dchannel += dchannels)] = (gint32) v_result[2];
17898       destination[(current_dchannel += dchannels)] = (gint32) v_result[3];
17899       destination[(current_dchannel += dchannels)] = (gint32) v_result[4];
17900       destination[(current_dchannel += dchannels)] = (gint32) v_result[5];
17901       destination[(current_dchannel += dchannels)] = (gint32) v_result[6];
17902       destination[(current_dchannel += dchannels)] = (gint32) v_result[7];
17903 
17904       /* iterate destination */
17905       destination += (current_dchannel + dchannels);
17906 
17907       /* iterate source */
17908       source += (current_schannel + schannels);
17909     }
17910   }
17911 #else
17912   /* unrolled function */
17913   if(count > 8){
17914     limit = count - (count % 8);
17915 
17916     for(; i < limit; i += 8){
17917       current_dchannel = 0;
17918       current_schannel = 0;
17919 
17920       destination[0] = 0xffffffff & (gint32) ((gdouble) (destination[0] + (gdouble) (scale * source[0])));
17921       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (scale * source[(current_schannel = schannels)])));
17922       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
17923       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
17924       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
17925       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
17926       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
17927       destination[current_dchannel] = 0xffffffff & (gint32) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
17928 
17929       /* iterate destination */
17930       destination += (current_dchannel + dchannels);
17931 
17932       /* iterate source */
17933       source += (current_schannel + schannels);
17934     }
17935   }
17936 #endif
17937 
17938   for(; i < count; i++){
17939     destination[0] = 0xffffffff & (gint32) ((gdouble) (destination[0] + (gdouble) (scale * source[0])));
17940 
17941     destination += dchannels;
17942     source += schannels;
17943   }
17944 }
17945 
17946 /**
17947  * ags_audio_buffer_util_copy_float32_to_s64:
17948  * @destination: destination buffer
17949  * @dchannels: destination buffer's count of channels
17950  * @source: source buffer
17951  * @schannels: source buffer's count of channels
17952  * @count: number of frames to copy
17953  *
17954  * Copy audio data using additive strategy.
17955  *
17956  * Since: 3.0.0
17957  */
17958 void
ags_audio_buffer_util_copy_float32_to_s64(gint64 * destination,guint dchannels,Float32 * source,guint schannels,guint count)17959 ags_audio_buffer_util_copy_float32_to_s64(gint64 *destination, guint dchannels,
17960 					  Float32 *source, guint schannels,
17961 					  guint count)
17962 {
17963   //NOTE:JK: scale = (2^bits_source / 2.0 - 1.0)
17964   static const gdouble scale = 9223372036854775807.0;
17965   guint limit;
17966   guint current_dchannel, current_schannel;
17967   guint i;
17968 
17969   if(destination == NULL ||
17970      source == NULL){
17971     return;
17972   }
17973 
17974   i = 0;
17975 
17976 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
17977   /* vectorized function */
17978   if(count > 8){
17979     limit = count - (count % 8);
17980 
17981     for(; i < limit; i += 8){
17982       ags_v8float v_destination;
17983       ags_v8float v_source;
17984 
17985       current_dchannel = 0;
17986       current_schannel = 0;
17987 
17988       v_destination = (ags_v8float) {(gfloat) destination[0],
17989 				     (gfloat) destination[(current_dchannel = dchannels)],
17990 				     (gfloat) destination[(current_dchannel += dchannels)],
17991 				     (gfloat) destination[(current_dchannel += dchannels)],
17992 				     (gfloat) destination[(current_dchannel += dchannels)],
17993 				     (gfloat) destination[(current_dchannel += dchannels)],
17994 				     (gfloat) destination[(current_dchannel += dchannels)],
17995 				     (gfloat) destination[(current_dchannel += dchannels)]};
17996 
17997       v_source = (ags_v8float) {(gfloat) source[0],
17998 				(gfloat) source[(current_schannel = schannels)],
17999 				(gfloat) source[(current_schannel += schannels)],
18000 				(gfloat) source[(current_schannel += schannels)],
18001 				(gfloat) source[(current_schannel += schannels)],
18002 				(gfloat) source[(current_schannel += schannels)],
18003 				(gfloat) source[(current_schannel += schannels)],
18004 				(gfloat) source[(current_schannel += schannels)]};
18005 
18006       /* scale and copy */
18007       v_source *= (gfloat) scale;
18008       v_destination += v_source;
18009 
18010       current_dchannel = 0;
18011 
18012       destination[0] = (gint64) v_destination[0];
18013       destination[(current_dchannel = dchannels)] = (gint64) v_destination[1];
18014       destination[(current_dchannel += dchannels)] = (gint64) v_destination[2];
18015       destination[(current_dchannel += dchannels)] = (gint64) v_destination[3];
18016       destination[(current_dchannel += dchannels)] = (gint64) v_destination[4];
18017       destination[(current_dchannel += dchannels)] = (gint64) v_destination[5];
18018       destination[(current_dchannel += dchannels)] = (gint64) v_destination[6];
18019       destination[(current_dchannel += dchannels)] = (gint64) v_destination[7];
18020 
18021       /* iterate destination */
18022       destination += (current_dchannel + dchannels);
18023 
18024       /* iterate source */
18025       source += (current_schannel + schannels);
18026     }
18027   }
18028 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
18029   /* vectorized function */
18030   if(count > 8){
18031     limit = count - (count % 8);
18032 
18033     for(; i < limit; i += 8){
18034       double v_scaled[8];
18035       double v_result[8];
18036       static const double v_scale[1] = { (double) scale };
18037 
18038       current_dchannel = 0;
18039       current_schannel = 0;
18040 
18041       double v_destination[] = {(double) destination[0],
18042 				(double) destination[(current_dchannel = dchannels)],
18043 				(double) destination[(current_dchannel += dchannels)],
18044 				(double) destination[(current_dchannel += dchannels)],
18045 				(double) destination[(current_dchannel += dchannels)],
18046 				(double) destination[(current_dchannel += dchannels)],
18047 				(double) destination[(current_dchannel += dchannels)],
18048 				(double) destination[(current_dchannel += dchannels)]};
18049 
18050       double v_source[] = {(double) source[0],
18051 			   (double) source[(current_schannel = schannels)],
18052 			   (double) source[(current_schannel += schannels)],
18053 			   (double) source[(current_schannel += schannels)],
18054 			   (double) source[(current_schannel += schannels)],
18055 			   (double) source[(current_schannel += schannels)],
18056 			   (double) source[(current_schannel += schannels)],
18057 			   (double) source[(current_schannel += schannels)]};
18058 
18059       /* scale and copy */
18060       vDSP_vmulD(v_source, 1, v_scale, 0, v_scaled, 1, 8);
18061       vDSP_vaddD(v_destination, 1, v_scaled, 1, v_result, 1, 8);
18062 
18063       current_dchannel = 0;
18064 
18065       destination[0] = (gint64) v_result[0];
18066       destination[(current_dchannel = dchannels)] = (gint64) v_result[1];
18067       destination[(current_dchannel += dchannels)] = (gint64) v_result[2];
18068       destination[(current_dchannel += dchannels)] = (gint64) v_result[3];
18069       destination[(current_dchannel += dchannels)] = (gint64) v_result[4];
18070       destination[(current_dchannel += dchannels)] = (gint64) v_result[5];
18071       destination[(current_dchannel += dchannels)] = (gint64) v_result[6];
18072       destination[(current_dchannel += dchannels)] = (gint64) v_result[7];
18073 
18074       /* iterate destination */
18075       destination += (current_dchannel + dchannels);
18076 
18077       /* iterate source */
18078       source += (current_schannel + schannels);
18079     }
18080   }
18081 #else
18082   /* unrolled function */
18083   if(count > 8){
18084     limit = count - (count % 8);
18085 
18086     for(; i < limit; i += 8){
18087       current_dchannel = 0;
18088       current_schannel = 0;
18089 
18090       destination[0] = 0xffffffffffffffff & (gint64) ((gdouble) (destination[0] + (gdouble) (scale * source[0])));
18091       destination[current_dchannel] = 0xffffffffffffffff & (gint64) ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (scale * source[(current_schannel = schannels)])));
18092       destination[current_dchannel] = 0xffffffffffffffff & (gint64) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
18093       destination[current_dchannel] = 0xffffffffffffffff & (gint64) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
18094       destination[current_dchannel] = 0xffffffffffffffff & (gint64) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
18095       destination[current_dchannel] = 0xffffffffffffffff & (gint64) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
18096       destination[current_dchannel] = 0xffffffffffffffff & (gint64) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
18097       destination[current_dchannel] = 0xffffffffffffffff & (gint64) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (scale * source[(current_schannel += schannels)])));
18098 
18099       /* iterate destination */
18100       destination += (current_dchannel + dchannels);
18101 
18102       /* iterate source */
18103       source += (current_schannel + schannels);
18104     }
18105   }
18106 #endif
18107 
18108   for(; i < count; i++){
18109     destination[0] = 0xffffffffffffffff & (gint64) ((gdouble) (destination[0] + (gdouble) (scale * source[0])));
18110 
18111     destination += dchannels;
18112     source += schannels;
18113   }
18114 }
18115 
18116 /**
18117  * ags_audio_buffer_util_copy_float32_to_float:
18118  * @destination: destination buffer
18119  * @dchannels: destination buffer's count of channels
18120  * @source: source buffer
18121  * @schannels: source buffer's count of channels
18122  * @count: number of frames to copy
18123  *
18124  * Copy audio data using additive strategy.
18125  *
18126  * Since: 3.0.0
18127  */
18128 void
ags_audio_buffer_util_copy_float32_to_float(gfloat * destination,guint dchannels,Float32 * source,guint schannels,guint count)18129 ags_audio_buffer_util_copy_float32_to_float(gfloat *destination, guint dchannels,
18130 					    Float32 *source, guint schannels,
18131 					    guint count)
18132 {
18133   guint limit;
18134   guint current_dchannel, current_schannel;
18135   guint i;
18136 
18137   if(destination == NULL ||
18138      source == NULL){
18139     return;
18140   }
18141 
18142   i = 0;
18143 
18144 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
18145   /* vectorized function */
18146   if(count > 8){
18147     limit = count - (count % 8);
18148 
18149     for(; i < limit; i += 8){
18150       ags_v8float v_destination;
18151       ags_v8float v_source;
18152 
18153       current_dchannel = 0;
18154       current_schannel = 0;
18155 
18156       v_destination = (ags_v8float) {destination[0],
18157 				     destination[(current_dchannel = dchannels)],
18158 				     destination[(current_dchannel += dchannels)],
18159 				     destination[(current_dchannel += dchannels)],
18160 				     destination[(current_dchannel += dchannels)],
18161 				     destination[(current_dchannel += dchannels)],
18162 				     destination[(current_dchannel += dchannels)],
18163 				     destination[(current_dchannel += dchannels)]};
18164 
18165       v_source = (ags_v8float) {(gfloat) source[0],
18166 				(gfloat) source[(current_schannel = schannels)],
18167 				(gfloat) source[(current_schannel += schannels)],
18168 				(gfloat) source[(current_schannel += schannels)],
18169 				(gfloat) source[(current_schannel += schannels)],
18170 				(gfloat) source[(current_schannel += schannels)],
18171 				(gfloat) source[(current_schannel += schannels)],
18172 				(gfloat) source[(current_schannel += schannels)]};
18173 
18174       /* just copy */
18175       v_destination += v_source;
18176 
18177       current_dchannel = 0;
18178 
18179       destination[0] = v_destination[0];
18180       destination[(current_dchannel = dchannels)] = v_destination[1];
18181       destination[(current_dchannel += dchannels)] = v_destination[2];
18182       destination[(current_dchannel += dchannels)] = v_destination[3];
18183       destination[(current_dchannel += dchannels)] = v_destination[4];
18184       destination[(current_dchannel += dchannels)] = v_destination[5];
18185       destination[(current_dchannel += dchannels)] = v_destination[6];
18186       destination[(current_dchannel += dchannels)] = v_destination[7];
18187 
18188       /* iterate destination */
18189       destination += (current_dchannel + dchannels);
18190 
18191       /* iterate source */
18192       source += (current_schannel + schannels);
18193     }
18194   }
18195 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
18196   /* vectorized function */
18197   if(count > 8){
18198     limit = count - (count % 8);
18199 
18200     for(; i < limit; i += 8){
18201       double v_result[8];
18202 
18203       current_dchannel = 0;
18204       current_schannel = 0;
18205 
18206       double v_destination[] = {(double) destination[0],
18207 				(double) destination[(current_dchannel = dchannels)],
18208 				(double) destination[(current_dchannel += dchannels)],
18209 				(double) destination[(current_dchannel += dchannels)],
18210 				(double) destination[(current_dchannel += dchannels)],
18211 				(double) destination[(current_dchannel += dchannels)],
18212 				(double) destination[(current_dchannel += dchannels)],
18213 				(double) destination[(current_dchannel += dchannels)]};
18214 
18215       double v_source[] = {(double) source[0],
18216 			   (double) source[(current_schannel = schannels)],
18217 			   (double) source[(current_schannel += schannels)],
18218 			   (double) source[(current_schannel += schannels)],
18219 			   (double) source[(current_schannel += schannels)],
18220 			   (double) source[(current_schannel += schannels)],
18221 			   (double) source[(current_schannel += schannels)],
18222 			   (double) source[(current_schannel += schannels)]};
18223 
18224       /* just copy */
18225       vDSP_vaddD(v_destination, 1, v_source, 1, v_result, 1, 8);
18226 
18227       current_dchannel = 0;
18228 
18229       destination[0] = (gfloat) v_result[0];
18230       destination[(current_dchannel = dchannels)] = (gfloat) v_result[1];
18231       destination[(current_dchannel += dchannels)] = (gfloat) v_result[2];
18232       destination[(current_dchannel += dchannels)] = (gfloat) v_result[3];
18233       destination[(current_dchannel += dchannels)] = (gfloat) v_result[4];
18234       destination[(current_dchannel += dchannels)] = (gfloat) v_result[5];
18235       destination[(current_dchannel += dchannels)] = (gfloat) v_result[6];
18236       destination[(current_dchannel += dchannels)] = (gfloat) v_result[7];
18237 
18238       /* iterate destination */
18239       destination += (current_dchannel + dchannels);
18240 
18241       /* iterate source */
18242       source += (current_schannel + schannels);
18243     }
18244   }
18245 #else
18246   /* unrolled function */
18247   if(count > 8){
18248     limit = count - (count % 8);
18249 
18250     for(; i < limit; i += 8){
18251       destination[0] = (gfloat) ((gdouble) (destination[0] + (gdouble) (source[0])));
18252       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (source[(current_schannel = schannels)])));
18253       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
18254       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
18255       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
18256       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
18257       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
18258       destination[current_dchannel] = (gfloat) ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
18259 
18260       /* iterate destination */
18261       destination += (current_dchannel + dchannels);
18262 
18263       /* iterate source */
18264       source += (current_schannel + schannels);
18265     }
18266   }
18267 #endif
18268 
18269   for(; i < count; i++){
18270     destination[0] = (gfloat) ((gdouble) (destination[0] + (gdouble) (source[0])));
18271 
18272     destination += dchannels;
18273     source += schannels;
18274   }
18275 }
18276 
18277 /**
18278  * ags_audio_buffer_util_copy_float32_to_double:
18279  * @destination: destination buffer
18280  * @dchannels: destination buffer's count of channels
18281  * @source: source buffer
18282  * @schannels: source buffer's count of channels
18283  * @count: number of frames to copy
18284  *
18285  * Copy audio data using additive strategy.
18286  *
18287  * Since: 3.0.0
18288  */
18289 void
ags_audio_buffer_util_copy_float32_to_double(gdouble * destination,guint dchannels,Float32 * source,guint schannels,guint count)18290 ags_audio_buffer_util_copy_float32_to_double(gdouble *destination, guint dchannels,
18291 					     Float32 *source, guint schannels,
18292 					     guint count)
18293 {
18294   guint limit;
18295   guint current_dchannel, current_schannel;
18296   guint i;
18297 
18298   if(destination == NULL ||
18299      source == NULL){
18300     return;
18301   }
18302 
18303   i = 0;
18304 
18305 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
18306   /* vectorized function */
18307   if(count > 8){
18308     limit = count - (count % 8);
18309 
18310     for(; i < limit; i += 8){
18311       ags_v8double v_destination;
18312       ags_v8double v_source;
18313 
18314       current_dchannel = 0;
18315       current_schannel = 0;
18316 
18317       v_destination = (ags_v8double) {destination[0],
18318 				      destination[(current_dchannel = dchannels)],
18319 				      destination[(current_dchannel += dchannels)],
18320 				      destination[(current_dchannel += dchannels)],
18321 				      destination[(current_dchannel += dchannels)],
18322 				      destination[(current_dchannel += dchannels)],
18323 				      destination[(current_dchannel += dchannels)],
18324 				      destination[(current_dchannel += dchannels)]};
18325 
18326       v_source = (ags_v8double) {(gdouble) source[0],
18327 				 (gdouble) source[(current_schannel = schannels)],
18328 				 (gdouble) source[(current_schannel += schannels)],
18329 				 (gdouble) source[(current_schannel += schannels)],
18330 				 (gdouble) source[(current_schannel += schannels)],
18331 				 (gdouble) source[(current_schannel += schannels)],
18332 				 (gdouble) source[(current_schannel += schannels)],
18333 				 (gdouble) source[(current_schannel += schannels)]};
18334 
18335       /* just copy */
18336       v_destination += v_source;
18337 
18338       current_dchannel = 0;
18339 
18340       destination[0] = v_destination[0];
18341       destination[(current_dchannel = dchannels)] = v_destination[1];
18342       destination[(current_dchannel += dchannels)] = v_destination[2];
18343       destination[(current_dchannel += dchannels)] = v_destination[3];
18344       destination[(current_dchannel += dchannels)] = v_destination[4];
18345       destination[(current_dchannel += dchannels)] = v_destination[5];
18346       destination[(current_dchannel += dchannels)] = v_destination[6];
18347       destination[(current_dchannel += dchannels)] = v_destination[7];
18348 
18349       /* iterate destination */
18350       destination += (current_dchannel + dchannels);
18351 
18352       /* iterate source */
18353       source += (current_schannel + schannels);
18354     }
18355   }
18356 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
18357   /* vectorized function */
18358   if(count > 8){
18359     limit = count - (count % 8);
18360 
18361     for(; i < limit; i += 8){
18362       double v_result[8];
18363 
18364       current_dchannel = 0;
18365       current_schannel = 0;
18366 
18367       double v_destination[] = {(double) destination[0],
18368 				(double) destination[(current_dchannel = dchannels)],
18369 				(double) destination[(current_dchannel += dchannels)],
18370 				(double) destination[(current_dchannel += dchannels)],
18371 				(double) destination[(current_dchannel += dchannels)],
18372 				(double) destination[(current_dchannel += dchannels)],
18373 				(double) destination[(current_dchannel += dchannels)],
18374 				(double) destination[(current_dchannel += dchannels)]};
18375 
18376       double v_source[] = {(double) source[0],
18377 			   (double) source[(current_schannel = schannels)],
18378 			   (double) source[(current_schannel += schannels)],
18379 			   (double) source[(current_schannel += schannels)],
18380 			   (double) source[(current_schannel += schannels)],
18381 			   (double) source[(current_schannel += schannels)],
18382 			   (double) source[(current_schannel += schannels)],
18383 			   (double) source[(current_schannel += schannels)]};
18384 
18385       /* just copy */
18386       vDSP_vaddD(v_destination, 1, v_source, 1, v_result, 1, 8);
18387 
18388       current_dchannel = 0;
18389 
18390       destination[0] = (gdouble) v_result[0];
18391       destination[(current_dchannel = dchannels)] = (gdouble) v_result[1];
18392       destination[(current_dchannel += dchannels)] = (gdouble) v_result[2];
18393       destination[(current_dchannel += dchannels)] = (gdouble) v_result[3];
18394       destination[(current_dchannel += dchannels)] = (gdouble) v_result[4];
18395       destination[(current_dchannel += dchannels)] = (gdouble) v_result[5];
18396       destination[(current_dchannel += dchannels)] = (gdouble) v_result[6];
18397       destination[(current_dchannel += dchannels)] = (gdouble) v_result[7];
18398 
18399       /* iterate destination */
18400       destination += (current_dchannel + dchannels);
18401 
18402       /* iterate source */
18403       source += (current_schannel + schannels);
18404     }
18405   }
18406 #else
18407   /* unrolled function */
18408   if(count > 8){
18409     limit = count - (count % 8);
18410 
18411     for(; i < limit; i += 8){
18412       destination[0] = ((gdouble) (destination[0] + (gdouble) (source[0])));
18413       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel = dchannels)] + (gdouble) (source[(current_schannel = schannels)])));
18414       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
18415       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
18416       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
18417       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
18418       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
18419       destination[current_dchannel] = ((gdouble) (destination[(current_dchannel += dchannels)] + (gdouble) (source[(current_schannel += schannels)])));
18420 
18421       /* iterate destination */
18422       destination += (current_dchannel + dchannels);
18423 
18424       /* iterate source */
18425       source += (current_schannel + schannels);
18426     }
18427   }
18428 #endif
18429 
18430   for(; i < count; i++){
18431     destination[0] = ((gdouble) (destination[0] + (gdouble) (source[0])));
18432 
18433     destination += dchannels;
18434     source += schannels;
18435   }
18436 }
18437 #endif
18438 
18439 /**
18440  * ags_audio_buffer_util_copy_s8_to_complex:
18441  * @destination: destination buffer
18442  * @dchannels: destination buffer's count of channels
18443  * @source: source buffer
18444  * @schannels: source buffer's count of channels
18445  * @count: number of frames to copy
18446  *
18447  * Copy audio data using additive strategy.
18448  *
18449  * Since: 3.0.0
18450  */
18451 void
ags_audio_buffer_util_copy_s8_to_complex(AgsComplex * destination,guint dchannels,gint8 * source,guint schannels,guint count)18452 ags_audio_buffer_util_copy_s8_to_complex(AgsComplex *destination, guint dchannels,
18453 					 gint8 *source, guint schannels,
18454 					 guint count)
18455 {
18456   AgsComplex *c_ptr;
18457   AgsComplex **c_ptr_ptr;
18458   AgsComplex c_value;
18459 
18460   guint limit;
18461   guint current_dchannel, current_schannel;
18462   guint i;
18463 
18464   if(destination == NULL ||
18465      source == NULL){
18466     return;
18467   }
18468 
18469   c_ptr = &c_value;
18470   c_ptr_ptr = &c_ptr;
18471 
18472   i = 0;
18473 
18474   for(; i < count; i++){
18475     double _Complex z0, z1;
18476 
18477     AGS_AUDIO_BUFFER_UTIL_S8_TO_COMPLEX(source[0], c_ptr_ptr);
18478 
18479     z0 = ags_complex_get(destination);
18480     z1 = ags_complex_get(c_ptr);
18481 
18482     ags_complex_set(destination,
18483 		    z0 + z1);
18484 
18485     destination += dchannels;
18486     source += schannels;
18487   }
18488 }
18489 
18490 /**
18491  * ags_audio_buffer_util_copy_s16_to_complex:
18492  * @destination: destination buffer
18493  * @dchannels: destination buffer's count of channels
18494  * @source: source buffer
18495  * @schannels: source buffer's count of channels
18496  * @count: number of frames to copy
18497  *
18498  * Copy audio data using additive strategy.
18499  *
18500  * Since: 3.0.0
18501  */
18502 void
ags_audio_buffer_util_copy_s16_to_complex(AgsComplex * destination,guint dchannels,gint16 * source,guint schannels,guint count)18503 ags_audio_buffer_util_copy_s16_to_complex(AgsComplex *destination, guint dchannels,
18504 					  gint16 *source, guint schannels,
18505 					  guint count)
18506 {
18507   AgsComplex *c_ptr;
18508   AgsComplex **c_ptr_ptr;
18509   AgsComplex c_value;
18510 
18511   guint limit;
18512   guint current_dchannel, current_schannel;
18513   guint i;
18514 
18515   if(destination == NULL ||
18516      source == NULL){
18517     return;
18518   }
18519 
18520   c_ptr = &c_value;
18521   c_ptr_ptr = &c_ptr;
18522 
18523   i = 0;
18524 
18525   for(; i < count; i++){
18526     double _Complex z0, z1;
18527 
18528     AGS_AUDIO_BUFFER_UTIL_S16_TO_COMPLEX(source[0], c_ptr_ptr);
18529 
18530     z0 = ags_complex_get(destination);
18531     z1 = ags_complex_get(c_ptr);
18532 
18533     ags_complex_set(destination,
18534 		    z0 + z1);
18535 
18536     destination += dchannels;
18537     source += schannels;
18538   }
18539 }
18540 
18541 /**
18542  * ags_audio_buffer_util_copy_s24_to_complex:
18543  * @destination: destination buffer
18544  * @dchannels: destination buffer's count of channels
18545  * @source: source buffer
18546  * @schannels: source buffer's count of channels
18547  * @count: number of frames to copy
18548  *
18549  * Copy audio data using additive strategy.
18550  *
18551  * Since: 3.0.0
18552  */
18553 void
ags_audio_buffer_util_copy_s24_to_complex(AgsComplex * destination,guint dchannels,gint32 * source,guint schannels,guint count)18554 ags_audio_buffer_util_copy_s24_to_complex(AgsComplex *destination, guint dchannels,
18555 					  gint32 *source, guint schannels,
18556 					  guint count)
18557 {
18558   AgsComplex *c_ptr;
18559   AgsComplex **c_ptr_ptr;
18560   AgsComplex c_value;
18561 
18562   guint limit;
18563   guint current_dchannel, current_schannel;
18564   guint i;
18565 
18566   if(destination == NULL ||
18567      source == NULL){
18568     return;
18569   }
18570 
18571   c_ptr = &c_value;
18572   c_ptr_ptr = &c_ptr;
18573 
18574   i = 0;
18575 
18576   for(; i < count; i++){
18577     double _Complex z0, z1;
18578 
18579     AGS_AUDIO_BUFFER_UTIL_S24_TO_COMPLEX(source[0], c_ptr_ptr);
18580 
18581     z0 = ags_complex_get(destination);
18582     z1 = ags_complex_get(c_ptr);
18583 
18584     ags_complex_set(destination,
18585 		    z0 + z1);
18586 
18587     destination += dchannels;
18588     source += schannels;
18589   }
18590 }
18591 
18592 /**
18593  * ags_audio_buffer_util_copy_s32_to_complex:
18594  * @destination: destination buffer
18595  * @dchannels: destination buffer's count of channels
18596  * @source: source buffer
18597  * @schannels: source buffer's count of channels
18598  * @count: number of frames to copy
18599  *
18600  * Copy audio data using additive strategy.
18601  *
18602  * Since: 3.0.0
18603  */
18604 void
ags_audio_buffer_util_copy_s32_to_complex(AgsComplex * destination,guint dchannels,gint32 * source,guint schannels,guint count)18605 ags_audio_buffer_util_copy_s32_to_complex(AgsComplex *destination, guint dchannels,
18606 					  gint32 *source, guint schannels,
18607 					  guint count)
18608 {
18609   AgsComplex *c_ptr;
18610   AgsComplex **c_ptr_ptr;
18611   AgsComplex c_value;
18612 
18613   guint limit;
18614   guint current_dchannel, current_schannel;
18615   guint i;
18616 
18617   if(destination == NULL ||
18618      source == NULL){
18619     return;
18620   }
18621 
18622   c_ptr = &c_value;
18623   c_ptr_ptr = &c_ptr;
18624 
18625   i = 0;
18626 
18627   for(; i < count; i++){
18628     double _Complex z0, z1;
18629 
18630     AGS_AUDIO_BUFFER_UTIL_S32_TO_COMPLEX(source[0], c_ptr_ptr);
18631 
18632     z0 = ags_complex_get(destination);
18633     z1 = ags_complex_get(c_ptr);
18634 
18635     ags_complex_set(destination,
18636 		    z0 + z1);
18637 
18638     destination += dchannels;
18639     source += schannels;
18640   }
18641 }
18642 
18643 /**
18644  * ags_audio_buffer_util_copy_s64_to_complex:
18645  * @destination: destination buffer
18646  * @dchannels: destination buffer's count of channels
18647  * @source: source buffer
18648  * @schannels: source buffer's count of channels
18649  * @count: number of frames to copy
18650  *
18651  * Copy audio data using additive strategy.
18652  *
18653  * Since: 3.0.0
18654  */
18655 void
ags_audio_buffer_util_copy_s64_to_complex(AgsComplex * destination,guint dchannels,gint64 * source,guint schannels,guint count)18656 ags_audio_buffer_util_copy_s64_to_complex(AgsComplex *destination, guint dchannels,
18657 					  gint64 *source, guint schannels,
18658 					  guint count)
18659 {
18660   AgsComplex *c_ptr;
18661   AgsComplex **c_ptr_ptr;
18662   AgsComplex c_value;
18663 
18664   guint limit;
18665   guint current_dchannel, current_schannel;
18666   guint i;
18667 
18668   if(destination == NULL ||
18669      source == NULL){
18670     return;
18671   }
18672 
18673   c_ptr = &c_value;
18674   c_ptr_ptr = &c_ptr;
18675 
18676   i = 0;
18677 
18678   for(; i < count; i++){
18679     double _Complex z0, z1;
18680 
18681     AGS_AUDIO_BUFFER_UTIL_S64_TO_COMPLEX(source[0], c_ptr_ptr);
18682 
18683     z0 = ags_complex_get(destination);
18684     z1 = ags_complex_get(c_ptr);
18685 
18686     ags_complex_set(destination,
18687 		    z0 + z1);
18688 
18689     destination += dchannels;
18690     source += schannels;
18691   }
18692 }
18693 
18694 /**
18695  * ags_audio_buffer_util_copy_float_to_complex:
18696  * @destination: destination buffer
18697  * @dchannels: destination buffer's count of channels
18698  * @source: source buffer
18699  * @schannels: source buffer's count of channels
18700  * @count: number of frames to copy
18701  *
18702  * Copy audio data using additive strategy.
18703  *
18704  * Since: 3.0.0
18705  */
18706 void
ags_audio_buffer_util_copy_float_to_complex(AgsComplex * destination,guint dchannels,gfloat * source,guint schannels,guint count)18707 ags_audio_buffer_util_copy_float_to_complex(AgsComplex *destination, guint dchannels,
18708 					    gfloat *source, guint schannels,
18709 					    guint count)
18710 {
18711   AgsComplex *c_ptr;
18712   AgsComplex **c_ptr_ptr;
18713   AgsComplex c_value;
18714 
18715   guint limit;
18716   guint current_dchannel, current_schannel;
18717   guint i;
18718 
18719   if(destination == NULL ||
18720      source == NULL){
18721     return;
18722   }
18723 
18724   c_ptr = &c_value;
18725   c_ptr_ptr = &c_ptr;
18726 
18727   i = 0;
18728 
18729   for(; i < count; i++){
18730     double _Complex z0, z1;
18731 
18732     AGS_AUDIO_BUFFER_UTIL_FLOAT_TO_COMPLEX(source[0], c_ptr_ptr);
18733 
18734     z0 = ags_complex_get(destination);
18735     z1 = ags_complex_get(c_ptr);
18736 
18737     ags_complex_set(destination,
18738 		    z0 + z1);
18739 
18740     destination += dchannels;
18741     source += schannels;
18742   }
18743 }
18744 
18745 /**
18746  * ags_audio_buffer_util_copy_double_to_complex:
18747  * @destination: destination buffer
18748  * @dchannels: destination buffer's count of channels
18749  * @source: source buffer
18750  * @schannels: source buffer's count of channels
18751  * @count: number of frames to copy
18752  *
18753  * Copy audio data using additive strategy.
18754  *
18755  * Since: 3.0.0
18756  */
18757 void
ags_audio_buffer_util_copy_double_to_complex(AgsComplex * destination,guint dchannels,gdouble * source,guint schannels,guint count)18758 ags_audio_buffer_util_copy_double_to_complex(AgsComplex *destination, guint dchannels,
18759 					     gdouble *source, guint schannels,
18760 					     guint count)
18761 {
18762   AgsComplex *c_ptr;
18763   AgsComplex **c_ptr_ptr;
18764   AgsComplex c_value;
18765 
18766   guint limit;
18767   guint current_dchannel, current_schannel;
18768   guint i;
18769 
18770   if(destination == NULL ||
18771      source == NULL){
18772     return;
18773   }
18774 
18775   c_ptr = &c_value;
18776   c_ptr_ptr = &c_ptr;
18777 
18778   i = 0;
18779 
18780   for(; i < count; i++){
18781     double _Complex z0, z1;
18782 
18783     AGS_AUDIO_BUFFER_UTIL_DOUBLE_TO_COMPLEX(source[0], c_ptr_ptr);
18784 
18785     z0 = ags_complex_get(destination);
18786     z1 = ags_complex_get(c_ptr);
18787 
18788     ags_complex_set(destination,
18789 		    z0 + z1);
18790 
18791     destination += dchannels;
18792     source += schannels;
18793   }
18794 }
18795 
18796 #ifdef __APPLE__
18797 /**
18798  * ags_audio_buffer_util_copy_float32_to_complex:
18799  * @destination: destination buffer
18800  * @dchannels: destination buffer's count of channels
18801  * @source: source buffer
18802  * @schannels: source buffer's count of channels
18803  * @count: number of frames to copy
18804  *
18805  * Copy audio data using additive strategy.
18806  *
18807  * Since: 3.0.0
18808  */
18809 void
ags_audio_buffer_util_copy_float32_to_complex(AgsComplex * destination,guint dchannels,Float32 * source,guint schannels,guint count)18810 ags_audio_buffer_util_copy_float32_to_complex(AgsComplex *destination, guint dchannels,
18811 					      Float32 *source, guint schannels,
18812 					      guint count)
18813 {
18814   AgsComplex *c_ptr;
18815   AgsComplex **c_ptr_ptr;
18816   AgsComplex c_value;
18817 
18818   gfloat *f_ptr;
18819   gfloat f_value;
18820 
18821   guint limit;
18822   guint current_dchannel, current_schannel;
18823   guint i;
18824 
18825   if(destination == NULL ||
18826      source == NULL){
18827     return;
18828   }
18829 
18830   c_ptr = &c_value;
18831   c_ptr_ptr = &c_ptr;
18832 
18833   f_ptr = &f_value;
18834 
18835   i = 0;
18836 
18837   for(; i < count; i++){
18838     double _Complex z0, z1;
18839 
18840     f_value = source[0];
18841 
18842     AGS_AUDIO_BUFFER_UTIL_DOUBLE_TO_COMPLEX(f_value, c_ptr_ptr);
18843 
18844     z0 = ags_complex_get(destination);
18845     z1 = ags_complex_get(c_ptr);
18846 
18847     ags_complex_set(destination,
18848 		    z0 + z1);
18849 
18850     destination += dchannels;
18851     source += schannels;
18852   }
18853 }
18854 #endif
18855 
18856 /**
18857  * ags_audio_buffer_util_copy_complex_to_complex:
18858  * @destination: destination buffer
18859  * @dchannels: destination buffer's count of channels
18860  * @source: source buffer
18861  * @schannels: source buffer's count of channels
18862  * @count: number of frames to copy
18863  *
18864  * Copy audio data using additive strategy.
18865  *
18866  * Since: 3.0.0
18867  */
18868 void
ags_audio_buffer_util_copy_complex_to_complex(AgsComplex * destination,guint dchannels,AgsComplex * source,guint schannels,guint count)18869 ags_audio_buffer_util_copy_complex_to_complex(AgsComplex *destination, guint dchannels,
18870 					      AgsComplex *source, guint schannels,
18871 					      guint count)
18872 {
18873   guint limit;
18874   guint current_dchannel, current_schannel;
18875   guint i;
18876 
18877   if(destination == NULL ||
18878      source == NULL){
18879     return;
18880   }
18881 
18882   i = 0;
18883 
18884   for(; i < count; i++){
18885     double _Complex z0, z1;
18886 
18887     z0 = ags_complex_get(destination);
18888     z1 = ags_complex_get(source);
18889 
18890     ags_complex_set(destination,
18891 		    z0 + z1);
18892 
18893     destination += dchannels;
18894     source += schannels;
18895   }
18896 }
18897 
18898 /**
18899  * ags_audio_buffer_util_copy_complex_to_s8:
18900  * @destination: destination buffer
18901  * @dchannels: destination buffer's count of channels
18902  * @source: source buffer
18903  * @schannels: source buffer's count of channels
18904  * @count: number of frames to copy
18905  *
18906  * Copy audio data using additive strategy.
18907  *
18908  * Since: 3.0.0
18909  */
18910 void
ags_audio_buffer_util_copy_complex_to_s8(gint8 * destination,guint dchannels,AgsComplex * source,guint schannels,guint count)18911 ags_audio_buffer_util_copy_complex_to_s8(gint8 *destination, guint dchannels,
18912 					 AgsComplex *source, guint schannels,
18913 					 guint count)
18914 {
18915   gint8 *ptr;
18916 
18917   gint8 value;
18918   guint limit;
18919   guint current_dchannel, current_schannel;
18920   guint i;
18921 
18922   if(destination == NULL ||
18923      source == NULL){
18924     return;
18925   }
18926 
18927   i = 0;
18928 
18929   ptr = &value;
18930 
18931   for(; i < count; i++){
18932     AGS_AUDIO_BUFFER_UTIL_COMPLEX_TO_S8(source, ptr);
18933 
18934     destination[0] = 0xff & ((gint16) (destination[0] + value));
18935 
18936     destination += dchannels;
18937     source += schannels;
18938   }
18939 }
18940 
18941 /**
18942  * ags_audio_buffer_util_copy_complex_to_s16:
18943  * @destination: destination buffer
18944  * @dchannels: destination buffer's count of channels
18945  * @source: source buffer
18946  * @schannels: source buffer's count of channels
18947  * @count: number of frames to copy
18948  *
18949  * Copy audio data using additive strategy.
18950  *
18951  * Since: 3.0.0
18952  */
18953 void
ags_audio_buffer_util_copy_complex_to_s16(gint16 * destination,guint dchannels,AgsComplex * source,guint schannels,guint count)18954 ags_audio_buffer_util_copy_complex_to_s16(gint16 *destination, guint dchannels,
18955 					  AgsComplex *source, guint schannels,
18956 					  guint count)
18957 {
18958   gint16 *ptr;
18959 
18960   gint16 value;
18961   guint limit;
18962   guint current_dchannel, current_schannel;
18963   guint i;
18964 
18965   if(destination == NULL ||
18966      source == NULL){
18967     return;
18968   }
18969 
18970   i = 0;
18971 
18972   ptr = &value;
18973 
18974   for(; i < count; i++){
18975     AGS_AUDIO_BUFFER_UTIL_COMPLEX_TO_S16(source, ptr);
18976 
18977     destination[0] = (gint16) 0xffff & ((gint32) (destination[0] + value));
18978 
18979     destination += dchannels;
18980     source += schannels;
18981   }
18982 }
18983 
18984 /**
18985  * ags_audio_buffer_util_copy_complex_to_s24:
18986  * @destination: destination buffer
18987  * @dchannels: destination buffer's count of channels
18988  * @source: source buffer
18989  * @schannels: source buffer's count of channels
18990  * @count: number of frames to copy
18991  *
18992  * Copy audio data using additive strategy.
18993  *
18994  * Since: 3.0.0
18995  */
18996 void
ags_audio_buffer_util_copy_complex_to_s24(gint32 * destination,guint dchannels,AgsComplex * source,guint schannels,guint count)18997 ags_audio_buffer_util_copy_complex_to_s24(gint32 *destination, guint dchannels,
18998 					  AgsComplex *source, guint schannels,
18999 					  guint count)
19000 {
19001   gint32 *ptr;
19002 
19003   gint32 value;
19004   guint limit;
19005   guint current_dchannel, current_schannel;
19006   guint i;
19007 
19008   if(destination == NULL ||
19009      source == NULL){
19010     return;
19011   }
19012 
19013   i = 0;
19014 
19015   ptr = &value;
19016 
19017   for(; i < count; i++){
19018     AGS_AUDIO_BUFFER_UTIL_COMPLEX_TO_S24(source, ptr);
19019 
19020     destination[0] = 0xffffffff & ((gint32) (destination[0] + value));
19021 
19022     destination += dchannels;
19023     source += schannels;
19024   }
19025 }
19026 
19027 /**
19028  * ags_audio_buffer_util_copy_complex_to_s32:
19029  * @destination: destination buffer
19030  * @dchannels: destination buffer's count of channels
19031  * @source: source buffer
19032  * @schannels: source buffer's count of channels
19033  * @count: number of frames to copy
19034  *
19035  * Copy audio data using additive strategy.
19036  *
19037  * Since: 3.0.0
19038  */
19039 void
ags_audio_buffer_util_copy_complex_to_s32(gint32 * destination,guint dchannels,AgsComplex * source,guint schannels,guint count)19040 ags_audio_buffer_util_copy_complex_to_s32(gint32 *destination, guint dchannels,
19041 					  AgsComplex *source, guint schannels,
19042 					  guint count)
19043 {
19044   gint32 *ptr;
19045 
19046   gint32 value;
19047   guint limit;
19048   guint current_dchannel, current_schannel;
19049   guint i;
19050 
19051   if(destination == NULL ||
19052      source == NULL){
19053     return;
19054   }
19055 
19056   i = 0;
19057 
19058   ptr = &value;
19059 
19060   for(; i < count; i++){
19061     AGS_AUDIO_BUFFER_UTIL_COMPLEX_TO_S32(source, ptr);
19062 
19063     destination[0] = 0xffffffff & ((gint64) (destination[0] + value));
19064 
19065     destination += dchannels;
19066     source += schannels;
19067   }
19068 }
19069 
19070 /**
19071  * ags_audio_buffer_util_copy_complex_to_s64:
19072  * @destination: destination buffer
19073  * @dchannels: destination buffer's count of channels
19074  * @source: source buffer
19075  * @schannels: source buffer's count of channels
19076  * @count: number of frames to copy
19077  *
19078  * Copy audio data using additive strategy.
19079  *
19080  * Since: 3.0.0
19081  */
19082 void
ags_audio_buffer_util_copy_complex_to_s64(gint64 * destination,guint dchannels,AgsComplex * source,guint schannels,guint count)19083 ags_audio_buffer_util_copy_complex_to_s64(gint64 *destination, guint dchannels,
19084 					  AgsComplex *source, guint schannels,
19085 					  guint count)
19086 {
19087   gint64 *ptr;
19088 
19089   gint64 value;
19090   guint limit;
19091   guint current_dchannel, current_schannel;
19092   guint i;
19093 
19094   if(destination == NULL ||
19095      source == NULL){
19096     return;
19097   }
19098 
19099   i = 0;
19100 
19101   ptr = &value;
19102 
19103   for(; i < count; i++){
19104     AGS_AUDIO_BUFFER_UTIL_COMPLEX_TO_S64(source, ptr);
19105 
19106     destination[0] = 0xffffffffffffffff & ((gint64) (destination[0] + value));
19107 
19108     destination += dchannels;
19109     source += schannels;
19110   }
19111 }
19112 
19113 /**
19114  * ags_audio_buffer_util_copy_complex_to_float:
19115  * @destination: destination buffer
19116  * @dchannels: destination buffer's count of channels
19117  * @source: source buffer
19118  * @schannels: source buffer's count of channels
19119  * @count: number of frames to copy
19120  *
19121  * Copy audio data using additive strategy.
19122  *
19123  * Since: 3.0.0
19124  */
19125 void
ags_audio_buffer_util_copy_complex_to_float(gfloat * destination,guint dchannels,AgsComplex * source,guint schannels,guint count)19126 ags_audio_buffer_util_copy_complex_to_float(gfloat *destination, guint dchannels,
19127 					    AgsComplex *source, guint schannels,
19128 					    guint count)
19129 {
19130   gfloat *ptr;
19131 
19132   gfloat value;
19133   guint limit;
19134   guint current_dchannel, current_schannel;
19135   guint i;
19136 
19137   if(destination == NULL ||
19138      source == NULL){
19139     return;
19140   }
19141 
19142   i = 0;
19143 
19144   ptr = &value;
19145 
19146   for(; i < count; i++){
19147     AGS_AUDIO_BUFFER_UTIL_COMPLEX_TO_FLOAT(source, ptr);
19148 
19149     destination[0] = (gfloat) ((gdouble) (destination[0] + (gdouble) (value)));
19150 
19151     destination += dchannels;
19152     source += schannels;
19153   }
19154 }
19155 
19156 /**
19157  * ags_audio_buffer_util_copy_complex_to_double:
19158  * @destination: destination buffer
19159  * @dchannels: destination buffer's count of channels
19160  * @source: source buffer
19161  * @schannels: source buffer's count of channels
19162  * @count: number of frames to copy
19163  *
19164  * Copy audio data using additive strategy.
19165  *
19166  * Since: 3.0.0
19167  */
19168 void
ags_audio_buffer_util_copy_complex_to_double(gdouble * destination,guint dchannels,AgsComplex * source,guint schannels,guint count)19169 ags_audio_buffer_util_copy_complex_to_double(gdouble *destination, guint dchannels,
19170 					     AgsComplex *source, guint schannels,
19171 					     guint count)
19172 {
19173   gdouble *ptr;
19174 
19175   gdouble value;
19176   guint limit;
19177   guint current_dchannel, current_schannel;
19178   guint i;
19179 
19180   if(destination == NULL ||
19181      source == NULL){
19182     return;
19183   }
19184 
19185   i = 0;
19186 
19187   ptr = &value;
19188 
19189   for(; i < count; i++){
19190     AGS_AUDIO_BUFFER_UTIL_COMPLEX_TO_DOUBLE(source, ptr);
19191 
19192     destination[0] = ((gdouble) ((destination[0]) + (value)));
19193 
19194     destination += dchannels;
19195     source += schannels;
19196   }
19197 }
19198 
19199 #ifdef __APPLE__
19200 /**
19201  * ags_audio_buffer_util_copy_complex_to_float32:
19202  * @destination: destination buffer
19203  * @dchannels: destination buffer's count of channels
19204  * @source: source buffer
19205  * @schannels: source buffer's count of channels
19206  * @count: number of frames to copy
19207  *
19208  * Copy audio data using additive strategy.
19209  *
19210  * Since: 3.0.0
19211  */
19212 void
ags_audio_buffer_util_copy_complex_to_float32(Float32 * destination,guint dchannels,AgsComplex * source,guint schannels,guint count)19213 ags_audio_buffer_util_copy_complex_to_float32(Float32 *destination, guint dchannels,
19214 					      AgsComplex *source, guint schannels,
19215 					      guint count)
19216 {
19217   gdouble *ptr;
19218 
19219   gdouble value;
19220   guint limit;
19221   guint current_dchannel, current_schannel;
19222   guint i;
19223 
19224   if(destination == NULL ||
19225      source == NULL){
19226     return;
19227   }
19228 
19229   i = 0;
19230 
19231   ptr = &value;
19232 
19233   for(; i < count; i++){
19234     AGS_AUDIO_BUFFER_UTIL_COMPLEX_TO_DOUBLE(source, ptr);
19235 
19236     destination[0] = ((Float32) ((gdouble) (destination[0]) + (value)));
19237 
19238     destination += dchannels;
19239     source += schannels;
19240   }
19241 }
19242 #endif
19243 
19244 /**
19245  * ags_audio_buffer_util_copy_buffer_to_buffer:
19246  * @destination: destination buffer
19247  * @dchannels: destination buffer's count of channels
19248  * @doffset: start frame of destination
19249  * @source: source buffer
19250  * @schannels: source buffer's count of channels
19251  * @soffset: start frame of source
19252  * @count: number of frames to copy
19253  * @mode: specified type conversion as described
19254  *
19255  * Wrapper function to copy functions. Doing type conversion.
19256  *
19257  * Since: 3.0.0
19258  */
19259 void
ags_audio_buffer_util_copy_buffer_to_buffer(void * destination,guint dchannels,guint doffset,void * source,guint schannels,guint soffset,guint count,guint mode)19260 ags_audio_buffer_util_copy_buffer_to_buffer(void *destination, guint dchannels, guint doffset,
19261 					    void *source, guint schannels, guint soffset,
19262 					    guint count, guint mode)
19263 {
19264   if(destination == NULL ||
19265      source == NULL){
19266     return;
19267   }
19268 
19269   switch(mode){
19270   case AGS_AUDIO_BUFFER_UTIL_COPY_S8_TO_S8:
19271     {
19272       ags_audio_buffer_util_copy_s8_to_s8((gint8 *) destination + doffset, dchannels,
19273 					  (gint8 *) source + soffset, schannels,
19274 					  count);
19275     }
19276     break;
19277   case AGS_AUDIO_BUFFER_UTIL_COPY_S8_TO_S16:
19278     {
19279       ags_audio_buffer_util_copy_s8_to_s16((gint16 *) destination + doffset, dchannels,
19280 					   (gint8 *) source + soffset, schannels,
19281 					   count);
19282     }
19283     break;
19284   case AGS_AUDIO_BUFFER_UTIL_COPY_S8_TO_S24:
19285     {
19286       ags_audio_buffer_util_copy_s8_to_s24((gint32 *) destination + doffset, dchannels,
19287 					   (gint8 *) source + soffset, schannels,
19288 					   count);
19289     }
19290     break;
19291   case AGS_AUDIO_BUFFER_UTIL_COPY_S8_TO_S32:
19292     {
19293       ags_audio_buffer_util_copy_s8_to_s32((gint32 *) destination + doffset, dchannels,
19294 					   (gint8 *) source + soffset, schannels,
19295 					   count);
19296     }
19297     break;
19298   case AGS_AUDIO_BUFFER_UTIL_COPY_S8_TO_S64:
19299     {
19300       ags_audio_buffer_util_copy_s8_to_s64((gint64 *) destination + doffset, dchannels,
19301 					   (gint8 *) source + soffset, schannels,
19302 					   count);
19303     }
19304     break;
19305   case AGS_AUDIO_BUFFER_UTIL_COPY_S8_TO_FLOAT:
19306     {
19307       ags_audio_buffer_util_copy_s8_to_float((gfloat *) destination + doffset, dchannels,
19308 					     (gint8 *) source + soffset, schannels,
19309 					     count);
19310     }
19311     break;
19312   case AGS_AUDIO_BUFFER_UTIL_COPY_S8_TO_DOUBLE:
19313     {
19314       ags_audio_buffer_util_copy_s8_to_double((gdouble *) destination + doffset, dchannels,
19315 					      (gint8 *) source + soffset, schannels,
19316 					      count);
19317     }
19318     break;
19319   case AGS_AUDIO_BUFFER_UTIL_COPY_S8_TO_COMPLEX:
19320     {
19321       ags_audio_buffer_util_copy_s8_to_complex((AgsComplex *) destination + doffset, dchannels,
19322 					       (gint8 *) source + soffset, schannels,
19323 					       count);
19324     }
19325     break;
19326 
19327   case AGS_AUDIO_BUFFER_UTIL_COPY_S16_TO_S8:
19328     {
19329       ags_audio_buffer_util_copy_s16_to_s8((gint8 *) destination + doffset, dchannels,
19330 					   (gint16 *) source + soffset, schannels,
19331 					   count);
19332     }
19333     break;
19334   case AGS_AUDIO_BUFFER_UTIL_COPY_S16_TO_S16:
19335     {
19336       ags_audio_buffer_util_copy_s16_to_s16(((gint16 *) destination) + doffset, dchannels,
19337 					    ((gint16 *) source) + soffset, schannels,
19338 					    count);
19339     }
19340     break;
19341   case AGS_AUDIO_BUFFER_UTIL_COPY_S16_TO_S24:
19342     {
19343       ags_audio_buffer_util_copy_s16_to_s24((gint32 *) destination + doffset, dchannels,
19344 					    (gint16 *) source + soffset, schannels,
19345 					    count);
19346     }
19347     break;
19348   case AGS_AUDIO_BUFFER_UTIL_COPY_S16_TO_S32:
19349     {
19350       ags_audio_buffer_util_copy_s16_to_s32((gint32 *) destination + doffset, dchannels,
19351 					    (gint16 *) source + soffset, schannels,
19352 					    count);
19353     }
19354     break;
19355   case AGS_AUDIO_BUFFER_UTIL_COPY_S16_TO_S64:
19356     {
19357       ags_audio_buffer_util_copy_s16_to_s64((gint64 *) destination + doffset, dchannels,
19358 					    (gint16 *) source + soffset, schannels,
19359 					    count);
19360     }
19361     break;
19362   case AGS_AUDIO_BUFFER_UTIL_COPY_S16_TO_FLOAT:
19363     {
19364       ags_audio_buffer_util_copy_s16_to_float((gfloat *) destination + doffset, dchannels,
19365 					      (gint16 *) source + soffset, schannels,
19366 					      count);
19367     }
19368     break;
19369   case AGS_AUDIO_BUFFER_UTIL_COPY_S16_TO_DOUBLE:
19370     {
19371       ags_audio_buffer_util_copy_s16_to_double((gdouble *) destination + doffset, dchannels,
19372 					       (gint16 *) source + soffset, schannels,
19373 					       count);
19374     }
19375     break;
19376   case AGS_AUDIO_BUFFER_UTIL_COPY_S16_TO_COMPLEX:
19377     {
19378       ags_audio_buffer_util_copy_s16_to_complex((AgsComplex *) destination + doffset, dchannels,
19379 						(gint16 *) source + soffset, schannels,
19380 						count);
19381     }
19382     break;
19383 
19384   case AGS_AUDIO_BUFFER_UTIL_COPY_S24_TO_S8:
19385     {
19386       ags_audio_buffer_util_copy_s24_to_s8((gint8 *) destination + doffset, dchannels,
19387 					   (gint32 *) source + soffset, schannels,
19388 					   count);
19389     }
19390     break;
19391   case AGS_AUDIO_BUFFER_UTIL_COPY_S24_TO_S16:
19392     {
19393       ags_audio_buffer_util_copy_s24_to_s16((gint16 *) destination + doffset, dchannels,
19394 					    (gint32 *) source + soffset, schannels,
19395 					    count);
19396     }
19397     break;
19398   case AGS_AUDIO_BUFFER_UTIL_COPY_S24_TO_S24:
19399     {
19400       ags_audio_buffer_util_copy_s24_to_s24((gint32 *) destination + doffset, dchannels,
19401 					    (gint32 *) source + soffset, schannels,
19402 					    count);
19403     }
19404     break;
19405   case AGS_AUDIO_BUFFER_UTIL_COPY_S24_TO_S32:
19406     {
19407       ags_audio_buffer_util_copy_s24_to_s32((gint32 *) destination + doffset, dchannels,
19408 					    (gint32 *) source + soffset, schannels,
19409 					    count);
19410     }
19411     break;
19412   case AGS_AUDIO_BUFFER_UTIL_COPY_S24_TO_S64:
19413     {
19414       ags_audio_buffer_util_copy_s24_to_s64((gint64 *) destination + doffset, dchannels,
19415 					    (gint32 *) source + soffset, schannels,
19416 					    count);
19417     }
19418     break;
19419   case AGS_AUDIO_BUFFER_UTIL_COPY_S24_TO_FLOAT:
19420     {
19421       ags_audio_buffer_util_copy_s24_to_float((gfloat *) destination + doffset, dchannels,
19422 					      (gint32 *) source + soffset, schannels,
19423 					      count);
19424     }
19425     break;
19426   case AGS_AUDIO_BUFFER_UTIL_COPY_S24_TO_DOUBLE:
19427     {
19428       ags_audio_buffer_util_copy_s24_to_double((gdouble *) destination + doffset, dchannels,
19429 					       (gint32 *) source + soffset, schannels,
19430 					       count);
19431     }
19432     break;
19433   case AGS_AUDIO_BUFFER_UTIL_COPY_S24_TO_COMPLEX:
19434     {
19435       ags_audio_buffer_util_copy_s24_to_complex((AgsComplex *) destination + doffset, dchannels,
19436 						(gint32 *) source + soffset, schannels,
19437 						count);
19438     }
19439     break;
19440 
19441   case AGS_AUDIO_BUFFER_UTIL_COPY_S32_TO_S8:
19442     {
19443       ags_audio_buffer_util_copy_s32_to_s8((gint8 *) destination + doffset, dchannels,
19444 					   (gint32 *) source + soffset, schannels,
19445 					   count);
19446     }
19447     break;
19448   case AGS_AUDIO_BUFFER_UTIL_COPY_S32_TO_S16:
19449     {
19450       ags_audio_buffer_util_copy_s32_to_s16((gint16 *) destination + doffset, dchannels,
19451 					    (gint32 *) source + soffset, schannels,
19452 					    count);
19453     }
19454     break;
19455   case AGS_AUDIO_BUFFER_UTIL_COPY_S32_TO_S24:
19456     {
19457       ags_audio_buffer_util_copy_s32_to_s24((gint32 *) destination + doffset, dchannels,
19458 					    (gint32 *) source + soffset, schannels,
19459 					    count);
19460     }
19461     break;
19462   case AGS_AUDIO_BUFFER_UTIL_COPY_S32_TO_S32:
19463     {
19464       ags_audio_buffer_util_copy_s32_to_s32((gint32 *) destination + doffset, dchannels,
19465 					    (gint32 *) source + soffset, schannels,
19466 					    count);
19467     }
19468     break;
19469   case AGS_AUDIO_BUFFER_UTIL_COPY_S32_TO_S64:
19470     {
19471       ags_audio_buffer_util_copy_s32_to_s64((gint64 *) destination + doffset, dchannels,
19472 					    (gint32 *) source + soffset, schannels,
19473 					    count);
19474     }
19475     break;
19476   case AGS_AUDIO_BUFFER_UTIL_COPY_S32_TO_FLOAT:
19477     {
19478       ags_audio_buffer_util_copy_s32_to_s8((gint8 *) destination + doffset, dchannels,
19479 					   (gint32 *) source + soffset, schannels,
19480 					   count);
19481     }
19482     break;
19483   case AGS_AUDIO_BUFFER_UTIL_COPY_S32_TO_DOUBLE:
19484     {
19485       ags_audio_buffer_util_copy_s32_to_double((gdouble *) destination + doffset, dchannels,
19486 					       (gint32 *) source + soffset, schannels,
19487 					       count);
19488     }
19489     break;
19490   case AGS_AUDIO_BUFFER_UTIL_COPY_S32_TO_COMPLEX:
19491     {
19492       ags_audio_buffer_util_copy_s32_to_complex((AgsComplex *) destination + doffset, dchannels,
19493 						(gint32 *) source + soffset, schannels,
19494 						count);
19495     }
19496     break;
19497 
19498   case AGS_AUDIO_BUFFER_UTIL_COPY_S64_TO_S8:
19499     {
19500       ags_audio_buffer_util_copy_s64_to_s8((gint8 *) destination + doffset, dchannels,
19501 					   (gint64 *) source + soffset, schannels,
19502 					   count);
19503     }
19504     break;
19505   case AGS_AUDIO_BUFFER_UTIL_COPY_S64_TO_S16:
19506     {
19507       ags_audio_buffer_util_copy_s64_to_s16((gint16 *) destination + doffset, dchannels,
19508 					    (gint64 *) source + soffset, schannels,
19509 					    count);
19510     }
19511     break;
19512   case AGS_AUDIO_BUFFER_UTIL_COPY_S64_TO_S24:
19513     {
19514       ags_audio_buffer_util_copy_s64_to_s24((gint32 *) destination + doffset, dchannels,
19515 					    (gint64 *) source + soffset, schannels,
19516 					    count);
19517     }
19518     break;
19519   case AGS_AUDIO_BUFFER_UTIL_COPY_S64_TO_S32:
19520     {
19521       ags_audio_buffer_util_copy_s64_to_s32((gint32 *) destination + doffset, dchannels,
19522 					    (gint64 *) source + soffset, schannels,
19523 					    count);
19524     }
19525     break;
19526   case AGS_AUDIO_BUFFER_UTIL_COPY_S64_TO_S64:
19527     {
19528       ags_audio_buffer_util_copy_s64_to_s64((gint64 *) destination + doffset, dchannels,
19529 					    (gint64 *) source + soffset, schannels,
19530 					    count);
19531     }
19532     break;
19533   case AGS_AUDIO_BUFFER_UTIL_COPY_S64_TO_FLOAT:
19534     {
19535       ags_audio_buffer_util_copy_s64_to_float((gfloat *) destination + doffset, dchannels,
19536 					      (gint64 *) source + soffset, schannels,
19537 					      count);
19538     }
19539     break;
19540   case AGS_AUDIO_BUFFER_UTIL_COPY_S64_TO_DOUBLE:
19541     {
19542       ags_audio_buffer_util_copy_s64_to_double((gdouble *) destination + doffset, dchannels,
19543 					       (gint64 *) source + soffset, schannels,
19544 					       count);
19545     }
19546     break;
19547   case AGS_AUDIO_BUFFER_UTIL_COPY_S64_TO_COMPLEX:
19548     {
19549       ags_audio_buffer_util_copy_s64_to_complex((AgsComplex *) destination + doffset, dchannels,
19550 						(gint64 *) source + soffset, schannels,
19551 						count);
19552     }
19553     break;
19554 
19555   case AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT_TO_S8:
19556     {
19557       ags_audio_buffer_util_copy_float_to_s8((gint8 *) destination + doffset, dchannels,
19558 					     (gfloat *) source + soffset, schannels,
19559 					     count);
19560     }
19561     break;
19562   case AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT_TO_S16:
19563     {
19564       ags_audio_buffer_util_copy_float_to_s16((gint16 *) destination + doffset, dchannels,
19565 					      (gfloat *) source + soffset, schannels,
19566 					      count);
19567     }
19568     break;
19569   case AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT_TO_S24:
19570     {
19571       ags_audio_buffer_util_copy_float_to_s24((gint32 *) destination + doffset, dchannels,
19572 					      (gfloat *) source + soffset, schannels,
19573 					      count);
19574     }
19575     break;
19576   case AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT_TO_S32:
19577     {
19578       ags_audio_buffer_util_copy_float_to_s32((gint32 *) destination + doffset, dchannels,
19579 					      (gfloat *) source + soffset, schannels,
19580 					      count);
19581     }
19582     break;
19583   case AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT_TO_S64:
19584     {
19585       ags_audio_buffer_util_copy_float_to_s64((gint64 *) destination + doffset, dchannels,
19586 					      (gfloat *) source + soffset, schannels,
19587 					      count);
19588     }
19589     break;
19590   case AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT_TO_FLOAT:
19591     {
19592       ags_audio_buffer_util_copy_float_to_float((gfloat *) destination + doffset, dchannels,
19593 						(gfloat *) source + soffset, schannels,
19594 						count);
19595     }
19596     break;
19597   case AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT_TO_DOUBLE:
19598     {
19599       ags_audio_buffer_util_copy_float_to_double((gdouble *) destination + doffset, dchannels,
19600 						 (gfloat *) source + soffset, schannels,
19601 						 count);
19602     }
19603     break;
19604   case AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT_TO_COMPLEX:
19605     {
19606       ags_audio_buffer_util_copy_float_to_complex((AgsComplex *) destination + doffset, dchannels,
19607 						  (gfloat *) source + soffset, schannels,
19608 						  count);
19609     }
19610     break;
19611 
19612   case AGS_AUDIO_BUFFER_UTIL_COPY_DOUBLE_TO_S8:
19613     {
19614       ags_audio_buffer_util_copy_double_to_s8((gint8 *) destination + doffset, dchannels,
19615 					      (gdouble *) source + soffset, schannels,
19616 					      count);
19617     }
19618     break;
19619   case AGS_AUDIO_BUFFER_UTIL_COPY_DOUBLE_TO_S16:
19620     {
19621       ags_audio_buffer_util_copy_double_to_s16((gint16 *) destination + doffset, dchannels,
19622 					       (gdouble *) source + soffset, schannels,
19623 					       count);
19624     }
19625     break;
19626   case AGS_AUDIO_BUFFER_UTIL_COPY_DOUBLE_TO_S24:
19627     {
19628       ags_audio_buffer_util_copy_double_to_s24((gint32 *) destination + doffset, dchannels,
19629 					       (gdouble *) source + soffset, schannels,
19630 					       count);
19631     }
19632     break;
19633   case AGS_AUDIO_BUFFER_UTIL_COPY_DOUBLE_TO_S32:
19634     {
19635       ags_audio_buffer_util_copy_double_to_s32((gint32 *) destination + doffset, dchannels,
19636 					       (gdouble *) source + soffset, schannels,
19637 					       count);
19638     }
19639     break;
19640   case AGS_AUDIO_BUFFER_UTIL_COPY_DOUBLE_TO_S64:
19641     {
19642       ags_audio_buffer_util_copy_double_to_s64((gint64 *) destination + doffset, dchannels,
19643 					       (gdouble *) source + soffset, schannels,
19644 					       count);
19645     }
19646     break;
19647   case AGS_AUDIO_BUFFER_UTIL_COPY_DOUBLE_TO_FLOAT:
19648     {
19649       ags_audio_buffer_util_copy_double_to_float((gfloat *) destination + doffset, dchannels,
19650 						 (gdouble *) source + soffset, schannels,
19651 						 count);
19652     }
19653     break;
19654   case AGS_AUDIO_BUFFER_UTIL_COPY_DOUBLE_TO_DOUBLE:
19655     {
19656       ags_audio_buffer_util_copy_double_to_double((gdouble *) destination + doffset, dchannels,
19657 						  (gdouble *) source + soffset, schannels,
19658 						  count);
19659     }
19660     break;
19661   case AGS_AUDIO_BUFFER_UTIL_COPY_DOUBLE_TO_COMPLEX:
19662     {
19663       ags_audio_buffer_util_copy_double_to_complex((AgsComplex *) destination + doffset, dchannels,
19664 						   (gdouble *) source + soffset, schannels,
19665 						   count);
19666     }
19667     break;
19668 
19669   case AGS_AUDIO_BUFFER_UTIL_COPY_COMPLEX_TO_S8:
19670     {
19671       ags_audio_buffer_util_copy_complex_to_s8((gint8 *) destination + doffset, dchannels,
19672 					       (AgsComplex *) source + soffset, schannels,
19673 					       count);
19674     }
19675     break;
19676   case AGS_AUDIO_BUFFER_UTIL_COPY_COMPLEX_TO_S16:
19677     {
19678       ags_audio_buffer_util_copy_complex_to_s16((gint16 *) destination + doffset, dchannels,
19679 						(AgsComplex *) source + soffset, schannels,
19680 						count);
19681     }
19682     break;
19683   case AGS_AUDIO_BUFFER_UTIL_COPY_COMPLEX_TO_S24:
19684     {
19685       ags_audio_buffer_util_copy_complex_to_s24((gint32 *) destination + doffset, dchannels,
19686 						(AgsComplex *) source + soffset, schannels,
19687 						count);
19688     }
19689     break;
19690   case AGS_AUDIO_BUFFER_UTIL_COPY_COMPLEX_TO_S32:
19691     {
19692       ags_audio_buffer_util_copy_complex_to_s32((gint32 *) destination + doffset, dchannels,
19693 						(AgsComplex *) source + soffset, schannels,
19694 						count);
19695     }
19696     break;
19697   case AGS_AUDIO_BUFFER_UTIL_COPY_COMPLEX_TO_S64:
19698     {
19699       ags_audio_buffer_util_copy_complex_to_s64((gint64 *) destination + doffset, dchannels,
19700 						(AgsComplex *) source + soffset, schannels,
19701 						count);
19702     }
19703     break;
19704   case AGS_AUDIO_BUFFER_UTIL_COPY_COMPLEX_TO_FLOAT:
19705     {
19706       ags_audio_buffer_util_copy_complex_to_float((gfloat *) destination + doffset, dchannels,
19707 						  (AgsComplex *) source + soffset, schannels,
19708 						  count);
19709     }
19710     break;
19711   case AGS_AUDIO_BUFFER_UTIL_COPY_COMPLEX_TO_DOUBLE:
19712     {
19713       ags_audio_buffer_util_copy_complex_to_double((gdouble *) destination + doffset, dchannels,
19714 						   (AgsComplex *) source + soffset, schannels,
19715 						   count);
19716     }
19717     break;
19718   case AGS_AUDIO_BUFFER_UTIL_COPY_COMPLEX_TO_COMPLEX:
19719     {
19720       ags_audio_buffer_util_copy_complex_to_complex((AgsComplex *) destination + doffset, dchannels,
19721 						    (AgsComplex *) source + soffset, schannels,
19722 						    count);
19723     }
19724     break;
19725 
19726 #ifdef __APPLE__
19727   case AGS_AUDIO_BUFFER_UTIL_COPY_S8_TO_FLOAT32:
19728     {
19729       ags_audio_buffer_util_copy_s8_to_float32((Float32 *) destination + doffset, dchannels,
19730 					       (gint8 *) source + soffset, schannels,
19731 					       count);
19732     }
19733     break;
19734   case AGS_AUDIO_BUFFER_UTIL_COPY_S16_TO_FLOAT32:
19735     {
19736       ags_audio_buffer_util_copy_s16_to_float32((Float32 *) destination + doffset, dchannels,
19737 						((gint16 *) source) + soffset, schannels,
19738 						count);
19739     }
19740     break;
19741   case AGS_AUDIO_BUFFER_UTIL_COPY_S24_TO_FLOAT32:
19742     {
19743       ags_audio_buffer_util_copy_s24_to_float32((Float32 *) destination + doffset, dchannels,
19744 						(gint32 *) source + soffset, schannels,
19745 						count);
19746     }
19747     break;
19748   case AGS_AUDIO_BUFFER_UTIL_COPY_S32_TO_FLOAT32:
19749     {
19750       ags_audio_buffer_util_copy_s32_to_float32((Float32 *) destination + doffset, dchannels,
19751 						(gint32 *) source + soffset, schannels,
19752 						count);
19753     }
19754     break;
19755   case AGS_AUDIO_BUFFER_UTIL_COPY_S64_TO_FLOAT32:
19756     {
19757       ags_audio_buffer_util_copy_s64_to_float32((Float32 *) destination + doffset, dchannels,
19758 						(gint64 *) source + soffset, schannels,
19759 						count);
19760     }
19761     break;
19762   case AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT_TO_FLOAT32:
19763     {
19764       ags_audio_buffer_util_copy_float_to_float32((Float32 *) destination + doffset, dchannels,
19765 						  (gfloat *) source + soffset, schannels,
19766 						  count);
19767     }
19768     break;
19769   case AGS_AUDIO_BUFFER_UTIL_COPY_DOUBLE_TO_FLOAT32:
19770     {
19771       ags_audio_buffer_util_copy_double_to_float32((Float32 *) destination + doffset, dchannels,
19772 						   (gdouble *) source + soffset, schannels,
19773 						   count);
19774     }
19775     break;
19776   case AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT32_TO_FLOAT32:
19777     {
19778       ags_audio_buffer_util_copy_float32_to_float32((Float32 *) destination + doffset, dchannels,
19779 						    (Float32 *) source + soffset, schannels,
19780 						    count);
19781     }
19782     break;
19783   case AGS_AUDIO_BUFFER_UTIL_COPY_COMPLEX_TO_FLOAT32:
19784     {
19785       ags_audio_buffer_util_copy_complex_to_float32((Float32 *) destination + doffset, dchannels,
19786 						    (AgsComplex *) source + soffset, schannels,
19787 						    count);
19788     }
19789     break;
19790 
19791   case AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT32_TO_S8:
19792     {
19793       ags_audio_buffer_util_copy_float32_to_s8((gint8 *) destination + doffset, dchannels,
19794 					       (Float32 *) source + soffset, schannels,
19795 					       count);
19796     }
19797     break;
19798   case AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT32_TO_S16:
19799     {
19800       ags_audio_buffer_util_copy_float32_to_s16((gint16 *) destination + doffset, dchannels,
19801 						(Float32 *) source + soffset, schannels,
19802 						count);
19803     }
19804     break;
19805   case AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT32_TO_S24:
19806     {
19807       ags_audio_buffer_util_copy_float32_to_s24((gint32 *) destination + doffset, dchannels,
19808 						(Float32 *) source + soffset, schannels,
19809 						count);
19810     }
19811     break;
19812   case AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT32_TO_S32:
19813     {
19814       ags_audio_buffer_util_copy_float32_to_s32((gint32 *) destination + doffset, dchannels,
19815 						(Float32 *) source + soffset, schannels,
19816 						count);
19817     }
19818     break;
19819   case AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT32_TO_S64:
19820     {
19821       ags_audio_buffer_util_copy_float32_to_s64((gint64 *) destination + doffset, dchannels,
19822 						(Float32 *) source + soffset, schannels,
19823 						count);
19824     }
19825     break;
19826   case AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT32_TO_FLOAT:
19827     {
19828       ags_audio_buffer_util_copy_float32_to_float((gfloat *) destination + doffset, dchannels,
19829 						  (Float32 *) source + soffset, schannels,
19830 						  count);
19831     }
19832     break;
19833   case AGS_AUDIO_BUFFER_UTIL_COPY_FLOAT32_TO_COMPLEX:
19834     {
19835       ags_audio_buffer_util_copy_float32_to_complex((AgsComplex *) destination + doffset, dchannels,
19836 						    (Float32 *) source + soffset, schannels,
19837 						    count);
19838     }
19839     break;
19840 #endif
19841   default:
19842     {
19843       g_warning("ags_audio_buffer_util.c - unknown copy mode");
19844     }
19845   }
19846 }
19847