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