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_volume_util.h>
21 
22 #include <ags/audio/ags_audio_buffer_util.h>
23 
24 /**
25  * SECTION:ags_volume_util
26  * @short_description: Boxed type of volume util
27  * @title: AgsVolumeUtil
28  * @section_id:
29  * @include: ags/audio/ags_volume_util.h
30  *
31  * Boxed type of volume util data type.
32  */
33 
34 GType
ags_volume_util_get_type(void)35 ags_volume_util_get_type(void)
36 {
37   static volatile gsize g_define_type_id__volatile = 0;
38 
39   if(g_once_init_enter (&g_define_type_id__volatile)){
40     GType ags_type_volume_util = 0;
41 
42     ags_type_volume_util =
43       g_boxed_type_register_static("AgsVolumeUtil",
44 				   (GBoxedCopyFunc) ags_volume_util_copy,
45 				   (GBoxedFreeFunc) ags_volume_util_free);
46 
47     g_once_init_leave(&g_define_type_id__volatile, ags_type_volume_util);
48   }
49 
50   return g_define_type_id__volatile;
51 }
52 
53 /**
54  * ags_volume_util_alloc:
55  *
56  * Allocate #AgsVolumeUtil-struct
57  *
58  * Returns: a new #AgsVolumeUtil-struct
59  *
60  * Since: 3.9.2
61  */
62 AgsVolumeUtil*
ags_volume_util_alloc()63 ags_volume_util_alloc()
64 {
65   AgsVolumeUtil *ptr;
66 
67   ptr = (AgsVolumeUtil *) g_new(AgsVolumeUtil,
68 				1);
69 
70   ptr->destination = NULL;
71   ptr->destination_stride = 1;
72 
73   ptr->source = NULL;
74   ptr->source_stride = 1;
75 
76   ptr->buffer_length = 0;
77   ptr->format = AGS_VOLUME_UTIL_DEFAULT_FORMAT;
78 
79   ptr->audio_buffer_util_format = AGS_VOLUME_UTIL_DEFAULT_AUDIO_BUFFER_UTIL_FORMAT;
80 
81   ptr->volume = 1.0;
82 
83   return(ptr);
84 }
85 
86 /**
87  * ags_volume_util_copy:
88  * @ptr: the original #AgsVolumeUtil-struct
89  *
90  * Create a copy of @ptr.
91  *
92  * Returns: a pointer of the new #AgsVolumeUtil-struct
93  *
94  * Since: 3.9.2
95  */
96 gpointer
ags_volume_util_copy(AgsVolumeUtil * ptr)97 ags_volume_util_copy(AgsVolumeUtil *ptr)
98 {
99   AgsVolumeUtil *new_ptr;
100 
101   new_ptr = (AgsVolumeUtil *) g_new(AgsVolumeUtil,
102 				    1);
103 
104   new_ptr->destination = ptr->destination;
105   new_ptr->destination_stride = ptr->destination_stride;
106 
107   new_ptr->source = ptr->source;
108   new_ptr->source_stride = ptr->source_stride;
109 
110   new_ptr->buffer_length = ptr->buffer_length;
111   new_ptr->format = ptr->format;
112 
113   new_ptr->audio_buffer_util_format = ptr->audio_buffer_util_format;
114 
115   new_ptr->volume = ptr->volume;
116 
117   return(new_ptr);
118 }
119 
120 /**
121  * ags_volume_util_free:
122  * @ptr: the #AgsVolumeUtil-struct
123  *
124  * Free the memory of @ptr.
125  *
126  * Since: 3.9.2
127  */
128 void
ags_volume_util_free(AgsVolumeUtil * ptr)129 ags_volume_util_free(AgsVolumeUtil *ptr)
130 {
131   g_free(ptr->destination);
132 
133   if(ptr->destination != ptr->source){
134     g_free(ptr->source);
135   }
136 
137   g_free(ptr);
138 }
139 
140 /**
141  * ags_volume_util_get_destination:
142  * @volume_util: the #AgsVolumeUtil-struct
143  *
144  * Get destination buffer of @volume_util.
145  *
146  * Returns: the destination buffer
147  *
148  * Since: 3.9.2
149  */
150 gpointer
ags_volume_util_get_destination(AgsVolumeUtil * volume_util)151 ags_volume_util_get_destination(AgsVolumeUtil *volume_util)
152 {
153   if(volume_util == NULL){
154     return(NULL);
155   }
156 
157   return(volume_util->destination);
158 }
159 
160 /**
161  * ags_volume_util_set_destination:
162  * @volume_util: the #AgsVolumeUtil-struct
163  * @destination: the destination buffer
164  *
165  * Set @destination buffer of @volume_util.
166  *
167  * Since: 3.9.2
168  */
169 void
ags_volume_util_set_destination(AgsVolumeUtil * volume_util,gpointer destination)170 ags_volume_util_set_destination(AgsVolumeUtil *volume_util,
171 				gpointer destination)
172 {
173   if(volume_util == NULL){
174     return;
175   }
176 
177   volume_util->destination = destination;
178 }
179 
180 /**
181  * ags_volume_util_get_destination_stride:
182  * @volume_util: the #AgsVolumeUtil-struct
183  *
184  * Get destination stride of @volume_util.
185  *
186  * Returns: the destination buffer stride
187  *
188  * Since: 3.9.2
189  */
190 guint
ags_volume_util_get_destination_stride(AgsVolumeUtil * volume_util)191 ags_volume_util_get_destination_stride(AgsVolumeUtil *volume_util)
192 {
193   if(volume_util == NULL){
194     return(0);
195   }
196 
197   return(volume_util->destination_stride);
198 }
199 
200 /**
201  * ags_volume_util_set_destination_stride:
202  * @volume_util: the #AgsVolumeUtil-struct
203  * @destination_stride: the destination buffer stride
204  *
205  * Set @destination stride of @volume_util.
206  *
207  * Since: 3.9.2
208  */
209 void
ags_volume_util_set_destination_stride(AgsVolumeUtil * volume_util,guint destination_stride)210 ags_volume_util_set_destination_stride(AgsVolumeUtil *volume_util,
211 				       guint destination_stride)
212 {
213   if(volume_util == NULL){
214     return;
215   }
216 
217   volume_util->destination_stride = destination_stride;
218 }
219 
220 /**
221  * ags_volume_util_get_source:
222  * @volume_util: the #AgsVolumeUtil-struct
223  *
224  * Get source buffer of @volume_util.
225  *
226  * Returns: the source buffer
227  *
228  * Since: 3.9.2
229  */
230 gpointer
ags_volume_util_get_source(AgsVolumeUtil * volume_util)231 ags_volume_util_get_source(AgsVolumeUtil *volume_util)
232 {
233   if(volume_util == NULL){
234     return(NULL);
235   }
236 
237   return(volume_util->source);
238 }
239 
240 /**
241  * ags_volume_util_set_source:
242  * @volume_util: the #AgsVolumeUtil-struct
243  * @source: the source buffer
244  *
245  * Set @source buffer of @volume_util.
246  *
247  * Since: 3.9.2
248  */
249 void
ags_volume_util_set_source(AgsVolumeUtil * volume_util,gpointer source)250 ags_volume_util_set_source(AgsVolumeUtil *volume_util,
251 			   gpointer source)
252 {
253   if(volume_util == NULL){
254     return;
255   }
256 
257   volume_util->source = source;
258 }
259 
260 /**
261  * ags_volume_util_get_source_stride:
262  * @volume_util: the #AgsVolumeUtil-struct
263  *
264  * Get source stride of @volume_util.
265  *
266  * Returns: the source buffer stride
267  *
268  * Since: 3.9.2
269  */
270 guint
ags_volume_util_get_source_stride(AgsVolumeUtil * volume_util)271 ags_volume_util_get_source_stride(AgsVolumeUtil *volume_util)
272 {
273   if(volume_util == NULL){
274     return(0);
275   }
276 
277   return(volume_util->source_stride);
278 }
279 
280 /**
281  * ags_volume_util_set_source_stride:
282  * @volume_util: the #AgsVolumeUtil-struct
283  * @source_stride: the source buffer stride
284  *
285  * Set @source stride of @volume_util.
286  *
287  * Since: 3.9.2
288  */
289 void
ags_volume_util_set_source_stride(AgsVolumeUtil * volume_util,guint source_stride)290 ags_volume_util_set_source_stride(AgsVolumeUtil *volume_util,
291 				  guint source_stride)
292 {
293   if(volume_util == NULL){
294     return;
295   }
296 
297   volume_util->source_stride = source_stride;
298 }
299 
300 /**
301  * ags_volume_util_get_buffer_length:
302  * @volume_util: the #AgsVolumeUtil-struct
303  *
304  * Get buffer length of @volume_util.
305  *
306  * Returns: the buffer length
307  *
308  * Since: 3.9.2
309  */
310 guint
ags_volume_util_get_buffer_length(AgsVolumeUtil * volume_util)311 ags_volume_util_get_buffer_length(AgsVolumeUtil *volume_util)
312 {
313   if(volume_util == NULL){
314     return(0);
315   }
316 
317   return(volume_util->buffer_length);
318 }
319 
320 /**
321  * ags_volume_util_set_buffer_length:
322  * @volume_util: the #AgsVolumeUtil-struct
323  * @buffer_length: the buffer length
324  *
325  * Set @buffer_length of @volume_util.
326  *
327  * Since: 3.9.2
328  */
329 void
ags_volume_util_set_buffer_length(AgsVolumeUtil * volume_util,guint buffer_length)330 ags_volume_util_set_buffer_length(AgsVolumeUtil *volume_util,
331 				  guint buffer_length)
332 {
333   if(volume_util == NULL){
334     return;
335   }
336 
337   volume_util->buffer_length = buffer_length;
338 }
339 
340 /**
341  * ags_volume_util_get_format:
342  * @volume_util: the #AgsVolumeUtil-struct
343  *
344  * Get format of @volume_util.
345  *
346  * Returns: the format
347  *
348  * Since: 3.9.6
349  */
350 guint
ags_volume_util_get_format(AgsVolumeUtil * volume_util)351 ags_volume_util_get_format(AgsVolumeUtil *volume_util)
352 {
353   if(volume_util == NULL){
354     return(0);
355   }
356 
357   return(volume_util->format);
358 }
359 
360 /**
361  * ags_volume_util_set_format:
362  * @volume_util: the #AgsVolumeUtil-struct
363  * @format: the format
364  *
365  * Set @format of @volume_util.
366  *
367  * Since: 3.9.6
368  */
369 void
ags_volume_util_set_format(AgsVolumeUtil * volume_util,guint format)370 ags_volume_util_set_format(AgsVolumeUtil *volume_util,
371 			   guint format)
372 {
373   if(volume_util == NULL){
374     return;
375   }
376 
377   volume_util->format = format;
378 
379   volume_util->audio_buffer_util_format = ags_audio_buffer_util_format_from_soundcard(format);
380 }
381 
382 /**
383  * ags_volume_util_get_audio_buffer_util_format:
384  * @volume_util: the #AgsVolumeUtil-struct
385  *
386  * Get audio buffer util format of @volume_util.
387  *
388  * Returns: the audio buffer util format
389  *
390  * Since: 3.9.2
391  */
392 guint
ags_volume_util_get_audio_buffer_util_format(AgsVolumeUtil * volume_util)393 ags_volume_util_get_audio_buffer_util_format(AgsVolumeUtil *volume_util)
394 {
395   if(volume_util == NULL){
396     return(0);
397   }
398 
399   return(volume_util->audio_buffer_util_format);
400 }
401 
402 /**
403  * ags_volume_util_set_audio_buffer_util_format:
404  * @volume_util: the #AgsVolumeUtil-struct
405  * @audio_buffer_util_format: the audio buffer util format
406  *
407  * Set @audio_buffer_util_format of @volume_util.
408  *
409  * Since: 3.9.2
410  */
411 void
ags_volume_util_set_audio_buffer_util_format(AgsVolumeUtil * volume_util,guint audio_buffer_util_format)412 ags_volume_util_set_audio_buffer_util_format(AgsVolumeUtil *volume_util,
413 					     guint audio_buffer_util_format)
414 {
415   if(volume_util == NULL){
416     return;
417   }
418 
419   volume_util->audio_buffer_util_format = audio_buffer_util_format;
420 }
421 
422 /**
423  * ags_volume_util_get_volume:
424  * @volume_util: the #AgsVolumeUtil-struct
425  *
426  * Get volume of @volume_util.
427  *
428  * Returns: the volume
429  *
430  * Since: 3.9.2
431  */
432 gdouble
ags_volume_util_get_volume(AgsVolumeUtil * volume_util)433 ags_volume_util_get_volume(AgsVolumeUtil *volume_util)
434 {
435   if(volume_util == NULL){
436     return(1.0);
437   }
438 
439   return(volume_util->volume);
440 }
441 
442 /**
443  * ags_volume_util_set_volume:
444  * @volume_util: the #AgsVolumeUtil-struct
445  * @volume: the volume
446  *
447  * Set @volume of @volume_util.
448  *
449  * Since: 3.9.2
450  */
451 void
ags_volume_util_set_volume(AgsVolumeUtil * volume_util,gdouble volume)452 ags_volume_util_set_volume(AgsVolumeUtil *volume_util,
453 			   gdouble volume)
454 {
455   if(volume_util == NULL){
456     return;
457   }
458 
459   volume_util->volume = volume;
460 }
461 
462 /**
463  * ags_volume_util_compute_s8:
464  * @volume_util: the #AgsVolumeUtil-struct
465  *
466  * Compute volume of signed 8 bit data.
467  *
468  * Since: 3.9.2
469  */
470 void
ags_volume_util_compute_s8(AgsVolumeUtil * volume_util)471 ags_volume_util_compute_s8(AgsVolumeUtil *volume_util)
472 {
473   gint8 *destination;
474   gint8 *source;
475   guint i, i_stop;
476 
477   if(volume_util == NULL ||
478      volume_util->destination == NULL ||
479      volume_util->source == NULL){
480     return;
481   }
482 
483   destination = (gint8 *) volume_util->destination;
484   source = (gint8 *) volume_util->source;
485 
486   i = 0;
487 
488 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
489   i_stop = volume_util->buffer_length - (volume_util->buffer_length % 8);
490 
491   for(; i < i_stop;){
492     ags_v8double v_buffer;
493 
494     v_buffer = (ags_v8double) {
495       (gdouble) *(source),
496       (gdouble) *(source += volume_util->source_stride),
497       (gdouble) *(source += volume_util->source_stride),
498       (gdouble) *(source += volume_util->source_stride),
499       (gdouble) *(source += volume_util->source_stride),
500       (gdouble) *(source += volume_util->source_stride),
501       (gdouble) *(source += volume_util->source_stride),
502       (gdouble) *(source += volume_util->source_stride)
503     };
504 
505     source += volume_util->source_stride;
506 
507     v_buffer *= volume_util->volume;
508 
509     *(destination) = (gint8) v_buffer[0];
510     *(destination += volume_util->destination_stride) = (gint8) v_buffer[1];
511     *(destination += volume_util->destination_stride) = (gint8) v_buffer[2];
512     *(destination += volume_util->destination_stride) = (gint8) v_buffer[3];
513     *(destination += volume_util->destination_stride) = (gint8) v_buffer[4];
514     *(destination += volume_util->destination_stride) = (gint8) v_buffer[5];
515     *(destination += volume_util->destination_stride) = (gint8) v_buffer[6];
516     *(destination += volume_util->destination_stride) = (gint8) v_buffer[7];
517 
518     destination += volume_util->destination_stride;
519     i += 8;
520   }
521 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
522   i_stop = volume_util->buffer_length - (volume_util->buffer_length % 8);
523 
524   for(; i < i_stop;){
525     double ret_v_buffer[8];
526 
527     double v_buffer[] = {
528       (double) *(source),
529       (double) *(source += volume_util->source_stride),
530       (double) *(source += volume_util->source_stride),
531       (double) *(source += volume_util->source_stride),
532       (double) *(source += volume_util->source_stride),
533       (double) *(source += volume_util->source_stride),
534       (double) *(source += volume_util->source_stride),
535       (double) *(source += volume_util->source_stride)};
536 
537     double v_volume[] = {(double) volume_util->volume};
538 
539     source += volume_util->source_stride;
540 
541     vDSP_vmulD(v_buffer, 1, v_volume, 0, ret_v_buffer, 1, 8);
542 
543     *(destination) = (gint8) ret_v_buffer[0];
544     *(destination += volume_util->destination_stride) = (gint8) ret_v_buffer[1];
545     *(destination += volume_util->destination_stride) = (gint8) ret_v_buffer[2];
546     *(destination += volume_util->destination_stride) = (gint8) ret_v_buffer[3];
547     *(destination += volume_util->destination_stride) = (gint8) ret_v_buffer[4];
548     *(destination += volume_util->destination_stride) = (gint8) ret_v_buffer[5];
549     *(destination += volume_util->destination_stride) = (gint8) ret_v_buffer[6];
550     *(destination += volume_util->destination_stride) = (gint8) ret_v_buffer[7];
551 
552     destination += volume_util->destination_stride;
553     i += 8;
554   }
555 #else
556   i_stop = volume_util->buffer_length - (volume_util->buffer_length % 8);
557 
558   for(; i < i_stop;){
559     *(destination) = (gint8) ((gint16) ((source)[0] * (volume_util->volume)));
560     *(destination += volume_util->destination_stride) = (gint8) ((gint16) ((source += volume_util->source_stride)[0] * volume_util->volume));
561     *(destination += volume_util->destination_stride) = (gint8) ((gint16) ((source += volume_util->source_stride)[0] * volume_util->volume));
562     *(destination += volume_util->destination_stride) = (gint8) ((gint16) ((source += volume_util->source_stride)[0] * volume_util->volume));
563     *(destination += volume_util->destination_stride) = (gint8) ((gint16) ((source += volume_util->source_stride)[0] * volume_util->volume));
564     *(destination += volume_util->destination_stride) = (gint8) ((gint16) ((source += volume_util->source_stride)[0] * volume_util->volume));
565     *(destination += volume_util->destination_stride) = (gint8) ((gint16) ((source += volume_util->source_stride)[0] * volume_util->volume));
566     *(destination += volume_util->destination_stride) = (gint8) ((gint16) ((source += volume_util->source_stride)[0] * volume_util->volume));
567 
568     destination += volume_util->destination_stride;
569     source += volume_util->source_stride;
570     i += 8;
571   }
572 #endif
573 
574   /* loop tail */
575   for(; i < volume_util->buffer_length;){
576     destination[0] = (gint8) ((gint16) (source[0] * volume_util->volume));
577 
578     destination += volume_util->destination_stride;
579     source += volume_util->source_stride;
580     i++;
581   }
582 }
583 
584 /**
585  * ags_volume_util_compute_s16:
586  * @volume_util: the #AgsVolumeUtil-struct
587  *
588  * Compute volume of signed 16 bit data.
589  *
590  * Since: 3.9.2
591  */
592 void
ags_volume_util_compute_s16(AgsVolumeUtil * volume_util)593 ags_volume_util_compute_s16(AgsVolumeUtil *volume_util)
594 {
595   gint16 *destination;
596   gint16 *source;
597   guint i, i_stop;
598 
599   if(volume_util == NULL ||
600      volume_util->destination == NULL ||
601      volume_util->source == NULL){
602     return;
603   }
604 
605   destination = (gint16 *) volume_util->destination;
606   source = (gint16 *) volume_util->source;
607 
608   i = 0;
609 
610 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
611   i_stop = volume_util->buffer_length - (volume_util->buffer_length % 8);
612 
613   for(; i < i_stop;){
614     ags_v8double v_buffer;
615 
616     v_buffer = (ags_v8double) {
617       (gdouble) *(source),
618       (gdouble) *(source += volume_util->source_stride),
619       (gdouble) *(source += volume_util->source_stride),
620       (gdouble) *(source += volume_util->source_stride),
621       (gdouble) *(source += volume_util->source_stride),
622       (gdouble) *(source += volume_util->source_stride),
623       (gdouble) *(source += volume_util->source_stride),
624       (gdouble) *(source += volume_util->source_stride)
625     };
626 
627     source += volume_util->source_stride;
628 
629     v_buffer *= volume_util->volume;
630 
631     *(destination) = (gint16) v_buffer[0];
632     *(destination += volume_util->destination_stride) = (gint16) v_buffer[1];
633     *(destination += volume_util->destination_stride) = (gint16) v_buffer[2];
634     *(destination += volume_util->destination_stride) = (gint16) v_buffer[3];
635     *(destination += volume_util->destination_stride) = (gint16) v_buffer[4];
636     *(destination += volume_util->destination_stride) = (gint16) v_buffer[5];
637     *(destination += volume_util->destination_stride) = (gint16) v_buffer[6];
638     *(destination += volume_util->destination_stride) = (gint16) v_buffer[7];
639 
640     destination += volume_util->destination_stride;
641     i += 8;
642   }
643 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
644   i_stop = volume_util->buffer_length - (volume_util->buffer_length % 8);
645 
646   for(; i < i_stop;){
647     double ret_v_buffer[8];
648 
649     double v_buffer[] = {
650       (double) *(source),
651       (double) *(source += volume_util->source_stride),
652       (double) *(source += volume_util->source_stride),
653       (double) *(source += volume_util->source_stride),
654       (double) *(source += volume_util->source_stride),
655       (double) *(source += volume_util->source_stride),
656       (double) *(source += volume_util->source_stride),
657       (double) *(source += volume_util->source_stride)};
658 
659     double v_volume[] = {(double) volume_util->volume};
660 
661     source += volume_util->source_stride;
662 
663     vDSP_vmulD(v_buffer, 1, v_volume, 0, ret_v_buffer, 1, 8);
664 
665     *(destination) = (gint16) ret_v_buffer[0];
666     *(destination += volume_util->destination_stride) = (gint16) ret_v_buffer[1];
667     *(destination += volume_util->destination_stride) = (gint16) ret_v_buffer[2];
668     *(destination += volume_util->destination_stride) = (gint16) ret_v_buffer[3];
669     *(destination += volume_util->destination_stride) = (gint16) ret_v_buffer[4];
670     *(destination += volume_util->destination_stride) = (gint16) ret_v_buffer[5];
671     *(destination += volume_util->destination_stride) = (gint16) ret_v_buffer[6];
672     *(destination += volume_util->destination_stride) = (gint16) ret_v_buffer[7];
673 
674     destination += volume_util->destination_stride;
675     i += 8;
676   }
677 #else
678   i_stop = volume_util->buffer_length - (volume_util->buffer_length % 8);
679 
680   for(; i < i_stop;){
681     *(destination) = (gint16) ((gint32) ((source)[0] * (volume_util->volume)));
682     *(destination += volume_util->destination_stride) = (gint16) ((gint32) ((source += volume_util->source_stride)[0] * volume_util->volume));
683     *(destination += volume_util->destination_stride) = (gint16) ((gint32) ((source += volume_util->source_stride)[0] * volume_util->volume));
684     *(destination += volume_util->destination_stride) = (gint16) ((gint32) ((source += volume_util->source_stride)[0] * volume_util->volume));
685     *(destination += volume_util->destination_stride) = (gint16) ((gint32) ((source += volume_util->source_stride)[0] * volume_util->volume));
686     *(destination += volume_util->destination_stride) = (gint16) ((gint32) ((source += volume_util->source_stride)[0] * volume_util->volume));
687     *(destination += volume_util->destination_stride) = (gint16) ((gint32) ((source += volume_util->source_stride)[0] * volume_util->volume));
688     *(destination += volume_util->destination_stride) = (gint16) ((gint32) ((source += volume_util->source_stride)[0] * volume_util->volume));
689 
690     destination += volume_util->destination_stride;
691     source += volume_util->source_stride;
692     i += 8;
693   }
694 #endif
695 
696   /* loop tail */
697   for(; i < volume_util->buffer_length;){
698     destination[0] = (gint16) ((gint32) (source[0] * volume_util->volume));
699 
700     destination += volume_util->destination_stride;
701     source += volume_util->source_stride;
702     i++;
703   }
704 }
705 
706 /**
707  * ags_volume_util_compute_s24:
708  * @volume_util: the #AgsVolumeUtil-struct
709  *
710  * Compute volume of signed 24 bit data.
711  *
712  * Since: 3.9.2
713  */
714 void
ags_volume_util_compute_s24(AgsVolumeUtil * volume_util)715 ags_volume_util_compute_s24(AgsVolumeUtil *volume_util)
716 {
717   gint32 *destination;
718   gint32 *source;
719   guint i, i_stop;
720 
721   if(volume_util == NULL ||
722      volume_util->destination == NULL ||
723      volume_util->source == NULL){
724     return;
725   }
726 
727   destination = (gint32 *) volume_util->destination;
728   source = (gint32 *) volume_util->source;
729 
730   i = 0;
731 
732 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
733   i_stop = volume_util->buffer_length - (volume_util->buffer_length % 8);
734 
735   for(; i < i_stop;){
736     ags_v8double v_buffer;
737 
738     v_buffer = (ags_v8double) {
739       (gdouble) *(source),
740       (gdouble) *(source += volume_util->source_stride),
741       (gdouble) *(source += volume_util->source_stride),
742       (gdouble) *(source += volume_util->source_stride),
743       (gdouble) *(source += volume_util->source_stride),
744       (gdouble) *(source += volume_util->source_stride),
745       (gdouble) *(source += volume_util->source_stride),
746       (gdouble) *(source += volume_util->source_stride)
747     };
748 
749     source += volume_util->source_stride;
750 
751     v_buffer *= volume_util->volume;
752 
753     *(destination) = (gint32) v_buffer[0];
754     *(destination += volume_util->destination_stride) = (gint32) v_buffer[1];
755     *(destination += volume_util->destination_stride) = (gint32) v_buffer[2];
756     *(destination += volume_util->destination_stride) = (gint32) v_buffer[3];
757     *(destination += volume_util->destination_stride) = (gint32) v_buffer[4];
758     *(destination += volume_util->destination_stride) = (gint32) v_buffer[5];
759     *(destination += volume_util->destination_stride) = (gint32) v_buffer[6];
760     *(destination += volume_util->destination_stride) = (gint32) v_buffer[7];
761 
762     destination += volume_util->destination_stride;
763     i += 8;
764   }
765 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
766   i_stop = volume_util->buffer_length - (volume_util->buffer_length % 8);
767 
768   for(; i < i_stop;){
769     double ret_v_buffer[8];
770 
771     double v_buffer[] = {
772       (double) *(source),
773       (double) *(source += volume_util->source_stride),
774       (double) *(source += volume_util->source_stride),
775       (double) *(source += volume_util->source_stride),
776       (double) *(source += volume_util->source_stride),
777       (double) *(source += volume_util->source_stride),
778       (double) *(source += volume_util->source_stride),
779       (double) *(source += volume_util->source_stride)};
780 
781     double v_volume[] = {(double) volume_util->volume};
782 
783     source += volume_util->source_stride;
784 
785     vDSP_vmulD(v_buffer, 1, v_volume, 0, ret_v_buffer, 1, 8);
786 
787     *(destination) = (gint32) ret_v_buffer[0];
788     *(destination += volume_util->destination_stride) = (gint32) ret_v_buffer[1];
789     *(destination += volume_util->destination_stride) = (gint32) ret_v_buffer[2];
790     *(destination += volume_util->destination_stride) = (gint32) ret_v_buffer[3];
791     *(destination += volume_util->destination_stride) = (gint32) ret_v_buffer[4];
792     *(destination += volume_util->destination_stride) = (gint32) ret_v_buffer[5];
793     *(destination += volume_util->destination_stride) = (gint32) ret_v_buffer[6];
794     *(destination += volume_util->destination_stride) = (gint32) ret_v_buffer[7];
795 
796     destination += volume_util->destination_stride;
797     i += 8;
798   }
799 #else
800   i_stop = volume_util->buffer_length - (volume_util->buffer_length % 8);
801 
802   for(; i < i_stop;){
803     *(destination) = (gint32) ((gint32) ((source)[0] * (volume_util->volume)));
804     *(destination += volume_util->destination_stride) = (gint32) ((gint32) ((source += volume_util->source_stride)[0] * volume_util->volume));
805     *(destination += volume_util->destination_stride) = (gint32) ((gint32) ((source += volume_util->source_stride)[0] * volume_util->volume));
806     *(destination += volume_util->destination_stride) = (gint32) ((gint32) ((source += volume_util->source_stride)[0] * volume_util->volume));
807     *(destination += volume_util->destination_stride) = (gint32) ((gint32) ((source += volume_util->source_stride)[0] * volume_util->volume));
808     *(destination += volume_util->destination_stride) = (gint32) ((gint32) ((source += volume_util->source_stride)[0] * volume_util->volume));
809     *(destination += volume_util->destination_stride) = (gint32) ((gint32) ((source += volume_util->source_stride)[0] * volume_util->volume));
810     *(destination += volume_util->destination_stride) = (gint32) ((gint32) ((source += volume_util->source_stride)[0] * volume_util->volume));
811 
812     destination += volume_util->destination_stride;
813     source += volume_util->source_stride;
814     i += 8;
815   }
816 #endif
817 
818   /* loop tail */
819   for(; i < volume_util->buffer_length;){
820     destination[0] = (gint32) ((gint32) (source[0] * volume_util->volume));
821 
822     destination += volume_util->destination_stride;
823     source += volume_util->source_stride;
824     i++;
825   }
826 }
827 
828 /**
829  * ags_volume_util_compute_s32:
830  * @volume_util: the #AgsVolumeUtil-struct
831  *
832  * Compute volume of signed 32 bit data.
833  *
834  * Since: 3.9.2
835  */
836 void
ags_volume_util_compute_s32(AgsVolumeUtil * volume_util)837 ags_volume_util_compute_s32(AgsVolumeUtil *volume_util)
838 {
839   gint32 *destination;
840   gint32 *source;
841   guint i, i_stop;
842 
843   if(volume_util == NULL ||
844      volume_util->destination == NULL ||
845      volume_util->source == NULL){
846     return;
847   }
848 
849   destination = (gint32 *) volume_util->destination;
850   source = (gint32 *) volume_util->source;
851 
852   i = 0;
853 
854 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
855   i_stop = volume_util->buffer_length - (volume_util->buffer_length % 8);
856 
857   for(; i < i_stop;){
858     ags_v8double v_buffer;
859 
860     v_buffer = (ags_v8double) {
861       (gdouble) *(source),
862       (gdouble) *(source += volume_util->source_stride),
863       (gdouble) *(source += volume_util->source_stride),
864       (gdouble) *(source += volume_util->source_stride),
865       (gdouble) *(source += volume_util->source_stride),
866       (gdouble) *(source += volume_util->source_stride),
867       (gdouble) *(source += volume_util->source_stride),
868       (gdouble) *(source += volume_util->source_stride)
869     };
870 
871     source += volume_util->source_stride;
872 
873     v_buffer *= volume_util->volume;
874 
875     *(destination) = (gint32) v_buffer[0];
876     *(destination += volume_util->destination_stride) = (gint32) v_buffer[1];
877     *(destination += volume_util->destination_stride) = (gint32) v_buffer[2];
878     *(destination += volume_util->destination_stride) = (gint32) v_buffer[3];
879     *(destination += volume_util->destination_stride) = (gint32) v_buffer[4];
880     *(destination += volume_util->destination_stride) = (gint32) v_buffer[5];
881     *(destination += volume_util->destination_stride) = (gint32) v_buffer[6];
882     *(destination += volume_util->destination_stride) = (gint32) v_buffer[7];
883 
884     destination += volume_util->destination_stride;
885     i += 8;
886   }
887 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
888   i_stop = volume_util->buffer_length - (volume_util->buffer_length % 8);
889 
890   for(; i < i_stop;){
891     double ret_v_buffer[8];
892 
893     double v_buffer[] = {
894       (double) *(source),
895       (double) *(source += volume_util->source_stride),
896       (double) *(source += volume_util->source_stride),
897       (double) *(source += volume_util->source_stride),
898       (double) *(source += volume_util->source_stride),
899       (double) *(source += volume_util->source_stride),
900       (double) *(source += volume_util->source_stride),
901       (double) *(source += volume_util->source_stride)};
902 
903     double v_volume[] = {(double) volume_util->volume};
904 
905     source += volume_util->source_stride;
906 
907     vDSP_vmulD(v_buffer, 1, v_volume, 0, ret_v_buffer, 1, 8);
908 
909     *(destination) = (gint32) ret_v_buffer[0];
910     *(destination += volume_util->destination_stride) = (gint32) ret_v_buffer[1];
911     *(destination += volume_util->destination_stride) = (gint32) ret_v_buffer[2];
912     *(destination += volume_util->destination_stride) = (gint32) ret_v_buffer[3];
913     *(destination += volume_util->destination_stride) = (gint32) ret_v_buffer[4];
914     *(destination += volume_util->destination_stride) = (gint32) ret_v_buffer[5];
915     *(destination += volume_util->destination_stride) = (gint32) ret_v_buffer[6];
916     *(destination += volume_util->destination_stride) = (gint32) ret_v_buffer[7];
917 
918     destination += volume_util->destination_stride;
919     i += 8;
920   }
921 #else
922   i_stop = volume_util->buffer_length - (volume_util->buffer_length % 8);
923 
924   for(; i < i_stop;){
925     *(destination) = (gint32) ((gint64) ((source)[0] * (volume_util->volume)));
926     *(destination += volume_util->destination_stride) = (gint32) ((gint64) ((source += volume_util->source_stride)[0] * volume_util->volume));
927     *(destination += volume_util->destination_stride) = (gint32) ((gint64) ((source += volume_util->source_stride)[0] * volume_util->volume));
928     *(destination += volume_util->destination_stride) = (gint32) ((gint64) ((source += volume_util->source_stride)[0] * volume_util->volume));
929     *(destination += volume_util->destination_stride) = (gint32) ((gint64) ((source += volume_util->source_stride)[0] * volume_util->volume));
930     *(destination += volume_util->destination_stride) = (gint32) ((gint64) ((source += volume_util->source_stride)[0] * volume_util->volume));
931     *(destination += volume_util->destination_stride) = (gint32) ((gint64) ((source += volume_util->source_stride)[0] * volume_util->volume));
932     *(destination += volume_util->destination_stride) = (gint32) ((gint64) ((source += volume_util->source_stride)[0] * volume_util->volume));
933 
934     destination += volume_util->destination_stride;
935     source += volume_util->source_stride;
936     i += 8;
937   }
938 #endif
939 
940   /* loop tail */
941   for(; i < volume_util->buffer_length;){
942     destination[0] = (gint32) ((gint64) (source[0] * volume_util->volume));
943 
944     destination += volume_util->destination_stride;
945     source += volume_util->source_stride;
946     i++;
947   }
948 }
949 
950 /**
951  * ags_volume_util_compute_s64:
952  * @volume_util: the #AgsVolumeUtil-struct
953  *
954  * Compute volume of signed 64 bit data.
955  *
956  * Since: 3.9.2
957  */
958 void
ags_volume_util_compute_s64(AgsVolumeUtil * volume_util)959 ags_volume_util_compute_s64(AgsVolumeUtil *volume_util)
960 {
961   gint64 *destination;
962   gint64 *source;
963   guint i, i_stop;
964 
965   if(volume_util == NULL ||
966      volume_util->destination == NULL ||
967      volume_util->source == NULL){
968     return;
969   }
970 
971   destination = (gint64 *) volume_util->destination;
972   source = (gint64 *) volume_util->source;
973 
974   i = 0;
975 
976 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
977   i_stop = volume_util->buffer_length - (volume_util->buffer_length % 8);
978 
979   for(; i < i_stop;){
980     ags_v8double v_buffer;
981 
982     v_buffer = (ags_v8double) {
983       (gdouble) *(source),
984       (gdouble) *(source += volume_util->source_stride),
985       (gdouble) *(source += volume_util->source_stride),
986       (gdouble) *(source += volume_util->source_stride),
987       (gdouble) *(source += volume_util->source_stride),
988       (gdouble) *(source += volume_util->source_stride),
989       (gdouble) *(source += volume_util->source_stride),
990       (gdouble) *(source += volume_util->source_stride)
991     };
992 
993     source += volume_util->source_stride;
994 
995     v_buffer *= volume_util->volume;
996 
997     *(destination) = (gint64) v_buffer[0];
998     *(destination += volume_util->destination_stride) = (gint64) v_buffer[1];
999     *(destination += volume_util->destination_stride) = (gint64) v_buffer[2];
1000     *(destination += volume_util->destination_stride) = (gint64) v_buffer[3];
1001     *(destination += volume_util->destination_stride) = (gint64) v_buffer[4];
1002     *(destination += volume_util->destination_stride) = (gint64) v_buffer[5];
1003     *(destination += volume_util->destination_stride) = (gint64) v_buffer[6];
1004     *(destination += volume_util->destination_stride) = (gint64) v_buffer[7];
1005 
1006     destination += volume_util->destination_stride;
1007     i += 8;
1008   }
1009 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
1010   i_stop = volume_util->buffer_length - (volume_util->buffer_length % 8);
1011 
1012   for(; i < i_stop;){
1013     double ret_v_buffer[8];
1014 
1015     double v_buffer[] = {
1016       (double) *(source),
1017       (double) *(source += volume_util->source_stride),
1018       (double) *(source += volume_util->source_stride),
1019       (double) *(source += volume_util->source_stride),
1020       (double) *(source += volume_util->source_stride),
1021       (double) *(source += volume_util->source_stride),
1022       (double) *(source += volume_util->source_stride),
1023       (double) *(source += volume_util->source_stride)};
1024 
1025     double v_volume[] = {(double) volume_util->volume};
1026 
1027     source += volume_util->source_stride;
1028 
1029     vDSP_vmulD(v_buffer, 1, v_volume, 0, ret_v_buffer, 1, 8);
1030 
1031     *(destination) = (gint64) ret_v_buffer[0];
1032     *(destination += volume_util->destination_stride) = (gint64) ret_v_buffer[1];
1033     *(destination += volume_util->destination_stride) = (gint64) ret_v_buffer[2];
1034     *(destination += volume_util->destination_stride) = (gint64) ret_v_buffer[3];
1035     *(destination += volume_util->destination_stride) = (gint64) ret_v_buffer[4];
1036     *(destination += volume_util->destination_stride) = (gint64) ret_v_buffer[5];
1037     *(destination += volume_util->destination_stride) = (gint64) ret_v_buffer[6];
1038     *(destination += volume_util->destination_stride) = (gint64) ret_v_buffer[7];
1039 
1040     destination += volume_util->destination_stride;
1041     i += 8;
1042   }
1043 #else
1044   i_stop = volume_util->buffer_length - (volume_util->buffer_length % 8);
1045 
1046   for(; i < i_stop;){
1047     *(destination) = (gint64) ((gint64) ((source)[0] * (volume_util->volume)));
1048     *(destination += volume_util->destination_stride) = (gint64) ((gint64) ((source += volume_util->source_stride)[0] * volume_util->volume));
1049     *(destination += volume_util->destination_stride) = (gint64) ((gint64) ((source += volume_util->source_stride)[0] * volume_util->volume));
1050     *(destination += volume_util->destination_stride) = (gint64) ((gint64) ((source += volume_util->source_stride)[0] * volume_util->volume));
1051     *(destination += volume_util->destination_stride) = (gint64) ((gint64) ((source += volume_util->source_stride)[0] * volume_util->volume));
1052     *(destination += volume_util->destination_stride) = (gint64) ((gint64) ((source += volume_util->source_stride)[0] * volume_util->volume));
1053     *(destination += volume_util->destination_stride) = (gint64) ((gint64) ((source += volume_util->source_stride)[0] * volume_util->volume));
1054     *(destination += volume_util->destination_stride) = (gint64) ((gint64) ((source += volume_util->source_stride)[0] * volume_util->volume));
1055 
1056     destination += volume_util->destination_stride;
1057     source += volume_util->source_stride;
1058     i += 8;
1059   }
1060 #endif
1061 
1062   /* loop tail */
1063   for(; i < volume_util->buffer_length;){
1064     destination[0] = (gint64) ((gint64) (source[0] * volume_util->volume));
1065 
1066     destination += volume_util->destination_stride;
1067     source += volume_util->source_stride;
1068     i++;
1069   }
1070 }
1071 
1072 /**
1073  * ags_volume_util_compute_float:
1074  * @volume_util: the #AgsVolumeUtil-struct
1075  *
1076  * Compute volume of floating point data.
1077  *
1078  * Since: 3.9.2
1079  */
1080 void
ags_volume_util_compute_float(AgsVolumeUtil * volume_util)1081 ags_volume_util_compute_float(AgsVolumeUtil *volume_util)
1082 {
1083   gfloat *destination;
1084   gfloat *source;
1085   guint i, i_stop;
1086 
1087   if(volume_util == NULL ||
1088      volume_util->destination == NULL ||
1089      volume_util->source == NULL){
1090     return;
1091   }
1092 
1093   destination = (gfloat *) volume_util->destination;
1094   source = (gfloat *) volume_util->source;
1095 
1096   i = 0;
1097 
1098 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
1099   i_stop = volume_util->buffer_length - (volume_util->buffer_length % 8);
1100 
1101   for(; i < i_stop;){
1102     ags_v8double v_buffer;
1103 
1104     v_buffer = (ags_v8double) {
1105       (gdouble) *(source),
1106       (gdouble) *(source += volume_util->source_stride),
1107       (gdouble) *(source += volume_util->source_stride),
1108       (gdouble) *(source += volume_util->source_stride),
1109       (gdouble) *(source += volume_util->source_stride),
1110       (gdouble) *(source += volume_util->source_stride),
1111       (gdouble) *(source += volume_util->source_stride),
1112       (gdouble) *(source += volume_util->source_stride)
1113     };
1114 
1115     source += volume_util->source_stride;
1116 
1117     v_buffer *= volume_util->volume;
1118 
1119     *(destination) = (gfloat) v_buffer[0];
1120     *(destination += volume_util->destination_stride) = (gfloat) v_buffer[1];
1121     *(destination += volume_util->destination_stride) = (gfloat) v_buffer[2];
1122     *(destination += volume_util->destination_stride) = (gfloat) v_buffer[3];
1123     *(destination += volume_util->destination_stride) = (gfloat) v_buffer[4];
1124     *(destination += volume_util->destination_stride) = (gfloat) v_buffer[5];
1125     *(destination += volume_util->destination_stride) = (gfloat) v_buffer[6];
1126     *(destination += volume_util->destination_stride) = (gfloat) v_buffer[7];
1127 
1128     destination += volume_util->destination_stride;
1129     i += 8;
1130   }
1131 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
1132   i_stop = volume_util->buffer_length - (volume_util->buffer_length % 8);
1133 
1134   for(; i < i_stop;){
1135     double ret_v_buffer[8];
1136 
1137     double v_buffer[] = {
1138       (double) *(source),
1139       (double) *(source += volume_util->source_stride),
1140       (double) *(source += volume_util->source_stride),
1141       (double) *(source += volume_util->source_stride),
1142       (double) *(source += volume_util->source_stride),
1143       (double) *(source += volume_util->source_stride),
1144       (double) *(source += volume_util->source_stride),
1145       (double) *(source += volume_util->source_stride)};
1146 
1147     double v_volume[] = {(double) volume_util->volume};
1148 
1149     source += volume_util->source_stride;
1150 
1151     vDSP_vmulD(v_buffer, 1, v_volume, 0, ret_v_buffer, 1, 8);
1152 
1153     *(destination) = (gfloat) ret_v_buffer[0];
1154     *(destination += volume_util->destination_stride) = (gfloat) ret_v_buffer[1];
1155     *(destination += volume_util->destination_stride) = (gfloat) ret_v_buffer[2];
1156     *(destination += volume_util->destination_stride) = (gfloat) ret_v_buffer[3];
1157     *(destination += volume_util->destination_stride) = (gfloat) ret_v_buffer[4];
1158     *(destination += volume_util->destination_stride) = (gfloat) ret_v_buffer[5];
1159     *(destination += volume_util->destination_stride) = (gfloat) ret_v_buffer[6];
1160     *(destination += volume_util->destination_stride) = (gfloat) ret_v_buffer[7];
1161 
1162     destination += volume_util->destination_stride;
1163     i += 8;
1164   }
1165 #else
1166   i_stop = volume_util->buffer_length - (volume_util->buffer_length % 8);
1167 
1168   for(; i < i_stop;){
1169     *(destination) = (gfloat) (((source)[0] * (volume_util->volume)));
1170     *(destination += volume_util->destination_stride) = (gfloat) (((source += volume_util->source_stride)[0] * volume_util->volume));
1171     *(destination += volume_util->destination_stride) = (gfloat) (((source += volume_util->source_stride)[0] * volume_util->volume));
1172     *(destination += volume_util->destination_stride) = (gfloat) (((source += volume_util->source_stride)[0] * volume_util->volume));
1173     *(destination += volume_util->destination_stride) = (gfloat) (((source += volume_util->source_stride)[0] * volume_util->volume));
1174     *(destination += volume_util->destination_stride) = (gfloat) (((source += volume_util->source_stride)[0] * volume_util->volume));
1175     *(destination += volume_util->destination_stride) = (gfloat) (((source += volume_util->source_stride)[0] * volume_util->volume));
1176     *(destination += volume_util->destination_stride) = (gfloat) (((source += volume_util->source_stride)[0] * volume_util->volume));
1177 
1178     destination += volume_util->destination_stride;
1179     source += volume_util->source_stride;
1180     i += 8;
1181   }
1182 #endif
1183 
1184   /* loop tail */
1185   for(; i < volume_util->buffer_length;){
1186     destination[0] = (gfloat) ((source[0] * volume_util->volume));
1187 
1188     destination += volume_util->destination_stride;
1189     source += volume_util->source_stride;
1190     i++;
1191   }
1192 }
1193 
1194 /**
1195  * ags_volume_util_compute_double:
1196  * @volume_util: the #AgsVolumeUtil-struct
1197  *
1198  * Compute volume of double floating point data.
1199  *
1200  * Since: 3.9.2
1201  */
1202 void
ags_volume_util_compute_double(AgsVolumeUtil * volume_util)1203 ags_volume_util_compute_double(AgsVolumeUtil *volume_util)
1204 {
1205   gdouble *destination;
1206   gdouble *source;
1207   guint i, i_stop;
1208 
1209   if(volume_util == NULL ||
1210      volume_util->destination == NULL ||
1211      volume_util->source == NULL){
1212     return;
1213   }
1214 
1215   destination = (gdouble *) volume_util->destination;
1216   source = (gdouble *) volume_util->source;
1217 
1218   i = 0;
1219 
1220 #if defined(AGS_VECTORIZED_BUILTIN_FUNCTIONS)
1221   i_stop = volume_util->buffer_length - (volume_util->buffer_length % 8);
1222 
1223   for(; i < i_stop;){
1224     ags_v8double v_buffer;
1225 
1226     v_buffer = (ags_v8double) {
1227       (gdouble) *(source),
1228       (gdouble) *(source += volume_util->source_stride),
1229       (gdouble) *(source += volume_util->source_stride),
1230       (gdouble) *(source += volume_util->source_stride),
1231       (gdouble) *(source += volume_util->source_stride),
1232       (gdouble) *(source += volume_util->source_stride),
1233       (gdouble) *(source += volume_util->source_stride),
1234       (gdouble) *(source += volume_util->source_stride)
1235     };
1236 
1237     source += volume_util->source_stride;
1238 
1239     v_buffer *= volume_util->volume;
1240 
1241     *(destination) = (gdouble) v_buffer[0];
1242     *(destination += volume_util->destination_stride) = (gdouble) v_buffer[1];
1243     *(destination += volume_util->destination_stride) = (gdouble) v_buffer[2];
1244     *(destination += volume_util->destination_stride) = (gdouble) v_buffer[3];
1245     *(destination += volume_util->destination_stride) = (gdouble) v_buffer[4];
1246     *(destination += volume_util->destination_stride) = (gdouble) v_buffer[5];
1247     *(destination += volume_util->destination_stride) = (gdouble) v_buffer[6];
1248     *(destination += volume_util->destination_stride) = (gdouble) v_buffer[7];
1249 
1250     destination += volume_util->destination_stride;
1251     i += 8;
1252   }
1253 #elif defined(AGS_OSX_ACCELERATE_BUILTIN_FUNCTIONS)
1254   i_stop = volume_util->buffer_length - (volume_util->buffer_length % 8);
1255 
1256   for(; i < i_stop;){
1257     double ret_v_buffer[8];
1258 
1259     double v_buffer[] = {
1260       (double) *(source),
1261       (double) *(source += volume_util->source_stride),
1262       (double) *(source += volume_util->source_stride),
1263       (double) *(source += volume_util->source_stride),
1264       (double) *(source += volume_util->source_stride),
1265       (double) *(source += volume_util->source_stride),
1266       (double) *(source += volume_util->source_stride),
1267       (double) *(source += volume_util->source_stride)};
1268 
1269     double v_volume[] = {(double) volume_util->volume};
1270 
1271     source += volume_util->source_stride;
1272 
1273     vDSP_vmulD(v_buffer, 1, v_volume, 0, ret_v_buffer, 1, 8);
1274 
1275     *(destination) = (gdouble) ret_v_buffer[0];
1276     *(destination += volume_util->destination_stride) = (gdouble) ret_v_buffer[1];
1277     *(destination += volume_util->destination_stride) = (gdouble) ret_v_buffer[2];
1278     *(destination += volume_util->destination_stride) = (gdouble) ret_v_buffer[3];
1279     *(destination += volume_util->destination_stride) = (gdouble) ret_v_buffer[4];
1280     *(destination += volume_util->destination_stride) = (gdouble) ret_v_buffer[5];
1281     *(destination += volume_util->destination_stride) = (gdouble) ret_v_buffer[6];
1282     *(destination += volume_util->destination_stride) = (gdouble) ret_v_buffer[7];
1283 
1284     destination += volume_util->destination_stride;
1285     i += 8;
1286   }
1287 #else
1288   i_stop = volume_util->buffer_length - (volume_util->buffer_length % 8);
1289 
1290   for(; i < i_stop;){
1291     *(destination) = (gdouble) (((source)[0] * (volume_util->volume)));
1292     *(destination += volume_util->destination_stride) = (gdouble) (((source += volume_util->source_stride)[0] * volume_util->volume));
1293     *(destination += volume_util->destination_stride) = (gdouble) (((source += volume_util->source_stride)[0] * volume_util->volume));
1294     *(destination += volume_util->destination_stride) = (gdouble) (((source += volume_util->source_stride)[0] * volume_util->volume));
1295     *(destination += volume_util->destination_stride) = (gdouble) (((source += volume_util->source_stride)[0] * volume_util->volume));
1296     *(destination += volume_util->destination_stride) = (gdouble) (((source += volume_util->source_stride)[0] * volume_util->volume));
1297     *(destination += volume_util->destination_stride) = (gdouble) (((source += volume_util->source_stride)[0] * volume_util->volume));
1298     *(destination += volume_util->destination_stride) = (gdouble) (((source += volume_util->source_stride)[0] * volume_util->volume));
1299 
1300     destination += volume_util->destination_stride;
1301     source += volume_util->source_stride;
1302     i += 8;
1303   }
1304 #endif
1305 
1306   /* loop tail */
1307   for(; i < volume_util->buffer_length;){
1308     destination[0] = (gdouble) ((source[0] * volume_util->volume));
1309 
1310     destination += volume_util->destination_stride;
1311     source += volume_util->source_stride;
1312     i++;
1313   }
1314 }
1315 
1316 /**
1317  * ags_volume_util_compute_complex:
1318  * @volume_util: the #AgsVolumeUtil-struct
1319  *
1320  * Compute volume of complex floating point data.
1321  *
1322  * Since: 3.9.2
1323  */
1324 void
ags_volume_util_compute_complex(AgsVolumeUtil * volume_util)1325 ags_volume_util_compute_complex(AgsVolumeUtil *volume_util)
1326 {
1327   AgsComplex *destination;
1328   AgsComplex *source;
1329   guint i;
1330 
1331   if(volume_util == NULL ||
1332      volume_util->destination == NULL ||
1333      volume_util->source == NULL){
1334     return;
1335   }
1336 
1337   destination = (AgsComplex *) volume_util->destination;
1338   source = (AgsComplex *) volume_util->source;
1339 
1340   i = 0;
1341 
1342   for(; i < volume_util->buffer_length;){
1343     double _Complex z;
1344 
1345     z = ags_complex_get(source);
1346 
1347     ags_complex_set(destination,
1348 		    z * (volume_util->volume));
1349 
1350     destination += volume_util->destination_stride;
1351     source += volume_util->source_stride;
1352     i++;
1353   }
1354 }
1355 
1356 /**
1357  * ags_volume_util_compute:
1358  * @volume_util: the #AgsVolumeUtil-struct
1359  *
1360  * Compute volume.
1361  *
1362  * Since: 3.9.2
1363  */
1364 void
ags_volume_util_compute(AgsVolumeUtil * volume_util)1365 ags_volume_util_compute(AgsVolumeUtil *volume_util)
1366 {
1367   if(volume_util == NULL ||
1368      volume_util->destination == NULL ||
1369      volume_util->source == NULL){
1370     return;
1371   }
1372 
1373   switch(volume_util->audio_buffer_util_format){
1374   case AGS_AUDIO_BUFFER_UTIL_S8:
1375   {
1376     ags_volume_util_compute_s8(volume_util);
1377   }
1378   break;
1379   case AGS_AUDIO_BUFFER_UTIL_S16:
1380   {
1381     ags_volume_util_compute_s16(volume_util);
1382   }
1383   break;
1384   case AGS_AUDIO_BUFFER_UTIL_S24:
1385   {
1386     ags_volume_util_compute_s24(volume_util);
1387   }
1388   break;
1389   case AGS_AUDIO_BUFFER_UTIL_S32:
1390   {
1391     ags_volume_util_compute_s32(volume_util);
1392   }
1393   break;
1394   case AGS_AUDIO_BUFFER_UTIL_S64:
1395   {
1396     ags_volume_util_compute_s64(volume_util);
1397   }
1398   break;
1399   case AGS_AUDIO_BUFFER_UTIL_FLOAT:
1400   {
1401     ags_volume_util_compute_float(volume_util);
1402   }
1403   break;
1404   case AGS_AUDIO_BUFFER_UTIL_DOUBLE:
1405   {
1406     ags_volume_util_compute_double(volume_util);
1407   }
1408   break;
1409   case AGS_AUDIO_BUFFER_UTIL_COMPLEX:
1410   {
1411     ags_volume_util_compute_complex(volume_util);
1412   }
1413   break;
1414   }
1415 }
1416