1 /* GSequencer - Advanced GTK Sequencer
2  * Copyright (C) 2005-2021 Joël Krähemann
3  *
4  * This file is part of GSequencer.
5  *
6  * GSequencer is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GSequencer is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with GSequencer.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <ags/audio/ags_audio_signal.h>
21 
22 #include <ags/audio/ags_recycling.h>
23 #include <ags/audio/ags_recall_id.h>
24 #include <ags/audio/ags_audio_buffer_util.h>
25 #include <ags/audio/ags_note.h>
26 
27 #include <libxml/tree.h>
28 
29 #include <stdint.h>
30 
31 #include <stdlib.h>
32 #include <string.h>
33 
34 #include <math.h>
35 #include <complex.h>
36 
37 #include <ags/i18n.h>
38 
39 void ags_audio_signal_class_init(AgsAudioSignalClass *audio_signal_class);
40 void ags_audio_signal_connectable_interface_init(AgsConnectableInterface *connectable);
41 void ags_audio_signal_init(AgsAudioSignal *audio_signal);
42 void ags_audio_signal_set_property(GObject *gobject,
43 				   guint prop_id,
44 				   const GValue *value,
45 				   GParamSpec *param_spec);
46 void ags_audio_signal_get_property(GObject *gobject,
47 				   guint prop_id,
48 				   GValue *value,
49 				   GParamSpec *param_spec);
50 void ags_audio_signal_dispose(GObject *gobject);
51 void ags_audio_signal_finalize(GObject *gobject);
52 
53 AgsUUID* ags_audio_signal_get_uuid(AgsConnectable *connectable);
54 gboolean ags_audio_signal_has_resource(AgsConnectable *connectable);
55 gboolean ags_audio_signal_is_ready(AgsConnectable *connectable);
56 void ags_audio_signal_add_to_registry(AgsConnectable *connectable);
57 void ags_audio_signal_remove_from_registry(AgsConnectable *connectable);
58 xmlNode* ags_audio_signal_list_resource(AgsConnectable *connectable);
59 xmlNode* ags_audio_signal_xml_compose(AgsConnectable *connectable);
60 void ags_audio_signal_xml_parse(AgsConnectable *connectable,
61 				xmlNode *node);
62 gboolean ags_audio_signal_is_connected(AgsConnectable *connectable);
63 void ags_audio_signal_connect(AgsConnectable *connectable);
64 void ags_audio_signal_disconnect(AgsConnectable *connectable);
65 
66 void ags_audio_signal_real_set_output_soundcard(AgsAudioSignal *audio_signal, GObject *output_soundcard);
67 
68 void ags_audio_signal_real_set_input_soundcard(AgsAudioSignal *audio_signal, GObject *input_soundcard);
69 
70 void ags_audio_signal_real_add_note(AgsAudioSignal *audio_signal,
71 				    GObject *note);
72 void ags_audio_signal_real_remove_note(AgsAudioSignal *audio_signal,
73 				       GObject *note);
74 
75 /**
76  * SECTION:ags_audio_signal
77  * @short_description: Contains the audio data and its alignment
78  * @title: AgsAudioSignal
79  * @section_id:
80  * @include: ags/audio/ags_audio_signal.h
81  *
82  * #AgsAudioSignal organizes audio data within a #GList-struct whereby data
83  * pointing to the buffer.
84  */
85 
86 enum{
87   PROP_0,
88   PROP_RECYCLING,
89   PROP_OUTPUT_SOUNDCARD,
90   PROP_OUTPUT_SOUNDCARD_CHANNEL,
91   PROP_INPUT_SOUNDCARD,
92   PROP_INPUT_SOUNDCARD_CHANNEL,
93   PROP_SAMPLERATE,
94   PROP_BUFFER_SIZE,
95   PROP_FORMAT,
96   PROP_WORD_SIZE,
97   PROP_LENGTH,
98   PROP_FIRST_FRAME,
99   PROP_LAST_FRAME,
100   PROP_FRAME_COUNT,
101   PROP_LOOP_START,
102   PROP_LOOP_END,
103   PROP_DELAY,
104   PROP_ATTACK,
105   PROP_DAMPING,
106   PROP_VIBRATION,
107   PROP_TIMBRE_START,
108   PROP_TIMBRE_END,
109   PROP_TEMPLATE,
110   PROP_RT_TEMPLATE,
111   PROP_NOTE,
112   PROP_RECALL_ID,
113   PROP_STREAM,
114   PROP_STREAM_END,
115   PROP_STREAM_CURRENT,
116 };
117 
118 enum{
119   ADD_NOTE,
120   REMOVE_NOTE,
121   REFRESH_DATA,
122   LAST_SIGNAL,
123 };
124 
125 static gpointer ags_audio_signal_parent_class = NULL;
126 static guint audio_signal_signals[LAST_SIGNAL];
127 
128 GType
ags_audio_signal_get_type(void)129 ags_audio_signal_get_type(void)
130 {
131   static volatile gsize g_define_type_id__volatile = 0;
132 
133   if(g_once_init_enter (&g_define_type_id__volatile)){
134     GType ags_type_audio_signal = 0;
135 
136     static const GTypeInfo ags_audio_signal_info = {
137       sizeof (AgsAudioSignalClass),
138       NULL, /* base_init */
139       NULL, /* base_finalize */
140       (GClassInitFunc) ags_audio_signal_class_init,
141       NULL, /* class_finalize */
142       NULL, /* class_data */
143       sizeof (AgsAudioSignal),
144       0,    /* n_preallocs */
145       (GInstanceInitFunc) ags_audio_signal_init,
146     };
147 
148     static const GInterfaceInfo ags_connectable_interface_info = {
149       (GInterfaceInitFunc) ags_audio_signal_connectable_interface_init,
150       NULL, /* interface_finalize */
151       NULL, /* interface_data */
152     };
153 
154     ags_type_audio_signal = g_type_register_static(G_TYPE_OBJECT,
155 						   "AgsAudioSignal",
156 						   &ags_audio_signal_info,
157 						   0);
158 
159     g_type_add_interface_static(ags_type_audio_signal,
160 				AGS_TYPE_CONNECTABLE,
161 				&ags_connectable_interface_info);
162 
163     g_once_init_leave(&g_define_type_id__volatile, ags_type_audio_signal);
164   }
165 
166   return g_define_type_id__volatile;
167 }
168 
169 GType
ags_audio_signal_flags_get_type()170 ags_audio_signal_flags_get_type()
171 {
172   static volatile gsize g_flags_type_id__volatile;
173 
174   if(g_once_init_enter (&g_flags_type_id__volatile)){
175     static const GFlagsValue values[] = {
176       { AGS_AUDIO_SIGNAL_ADDED_TO_REGISTRY, "AGS_AUDIO_SIGNAL_ADDED_TO_REGISTRY", "audio-signal-added-to-registry" },
177       { AGS_AUDIO_SIGNAL_CONNECTED, "AGS_AUDIO_SIGNAL_CONNECTED", "audio-signal-connected" },
178       { AGS_AUDIO_SIGNAL_TEMPLATE, "AGS_AUDIO_SIGNAL_template", "audio-signal-template" },
179       { AGS_AUDIO_SIGNAL_RT_TEMPLATE, "AGS_AUDIO_SIGNAL_RT_TEMPLATE", "audio-signal-rt-template" },
180       { AGS_AUDIO_SIGNAL_MASTER, "AGS_AUDIO_SIGNAL_MASTER", "audio-signal-master" },
181       { AGS_AUDIO_SIGNAL_FEED, "AGS_AUDIO_SIGNAL_FEED", "audio-signal-feed" },
182       { AGS_AUDIO_SIGNAL_RECYCLED, "AGS_AUDIO_SIGNAL_RECYCLED", "audio-signal-recycled" },
183       { AGS_AUDIO_SIGNAL_STREAM, "AGS_AUDIO_SIGNAL_STREAM", "audio-signal-stream" },
184       { AGS_AUDIO_SIGNAL_SLICE_ALLOC, "AGS_AUDIO_SIGNAL_SLICE_ALLOC", "audio-signal-slice-alloc" },
185       { 0, NULL, NULL }
186     };
187 
188     GType g_flags_type_id = g_flags_register_static(g_intern_static_string("AgsAudioSignalFlags"), values);
189 
190     g_once_init_leave (&g_flags_type_id__volatile, g_flags_type_id);
191   }
192 
193   return g_flags_type_id__volatile;
194 }
195 
196 void
ags_audio_signal_class_init(AgsAudioSignalClass * audio_signal)197 ags_audio_signal_class_init(AgsAudioSignalClass *audio_signal)
198 {
199   GObjectClass *gobject;
200 
201   GParamSpec *param_spec;
202 
203   ags_audio_signal_parent_class = g_type_class_peek_parent(audio_signal);
204 
205   /* GObjectClass */
206   gobject = (GObjectClass *) audio_signal;
207 
208   gobject->set_property = ags_audio_signal_set_property;
209   gobject->get_property = ags_audio_signal_get_property;
210 
211   gobject->dispose = ags_audio_signal_dispose;
212   gobject->finalize = ags_audio_signal_finalize;
213 
214   /* properties */
215   /**
216    * AgsAudioSignal:recycling:
217    *
218    * The assigned #AgsRecycling linking tree.
219    *
220    * Since: 3.0.0
221    */
222   param_spec = g_param_spec_object("recycling",
223 				   i18n_pspec("assigned recycling"),
224 				   i18n_pspec("The recycling it is assigned with"),
225 				   AGS_TYPE_RECYCLING,
226 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
227   g_object_class_install_property(gobject,
228 				  PROP_RECYCLING,
229 				  param_spec);
230 
231   /**
232    * AgsAudioSignal:output-soundcard:
233    *
234    * The assigned output #AgsSoundcard providing default settings.
235    *
236    * Since: 3.0.0
237    */
238   param_spec = g_param_spec_object("output-soundcard",
239 				   i18n_pspec("assigned output soundcard"),
240 				   i18n_pspec("The output soundcard it is assigned with"),
241 				   G_TYPE_OBJECT,
242 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
243   g_object_class_install_property(gobject,
244 				  PROP_OUTPUT_SOUNDCARD,
245 				  param_spec);
246 
247   /**
248    * AgsAudioSignal:output-soundcard-channel:
249    *
250    * The output soundcard channel.
251    *
252    * Since: 3.0.0
253    */
254   param_spec =  g_param_spec_int("output-soundcard-channel",
255 				 i18n_pspec("output soundcard channel"),
256 				 i18n_pspec("The output soundcard channel"),
257 				 -1,
258 				 G_MAXINT32,
259 				 0,
260 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
261   g_object_class_install_property(gobject,
262 				  PROP_OUTPUT_SOUNDCARD_CHANNEL,
263 				  param_spec);
264 
265   /**
266    * AgsAudioSignal:input-soundcard:
267    *
268    * The assigned input #AgsSoundcard.
269    *
270    * Since: 3.0.0
271    */
272   param_spec = g_param_spec_object("input-soundcard",
273 				   i18n_pspec("assigned input soundcard"),
274 				   i18n_pspec("The input soundcard it is assigned with"),
275 				   G_TYPE_OBJECT,
276 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
277   g_object_class_install_property(gobject,
278 				  PROP_INPUT_SOUNDCARD,
279 				  param_spec);
280 
281   /**
282    * AgsAudioSignal:input-soundcard-channel:
283    *
284    * The input soundcard channel.
285    *
286    * Since: 3.0.0
287    */
288   param_spec =  g_param_spec_int("input-soundcard-channel",
289 				 i18n_pspec("input soundcard channel"),
290 				 i18n_pspec("The input soundcard channel"),
291 				 -1,
292 				 G_MAXINT32,
293 				 0,
294 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
295   g_object_class_install_property(gobject,
296 				  PROP_INPUT_SOUNDCARD_CHANNEL,
297 				  param_spec);
298 
299   /**
300    * AgsAudioSignal:samplerate:
301    *
302    * The samplerate to be used.
303    *
304    * Since: 3.0.0
305    */
306   param_spec = g_param_spec_uint("samplerate",
307 				 i18n_pspec("using samplerate"),
308 				 i18n_pspec("The samplerate to be used"),
309 				 0,
310 				 G_MAXUINT32,
311 				 0,
312 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
313   g_object_class_install_property(gobject,
314 				  PROP_SAMPLERATE,
315 				  param_spec);
316 
317   /**
318    * AgsAudioSignal:buffer-size:
319    *
320    * The buffer size to be used.
321    *
322    * Since: 3.0.0
323    */
324   param_spec = g_param_spec_uint("buffer-size",
325 				 i18n_pspec("using buffer size"),
326 				 i18n_pspec("The buffer size to be used"),
327 				 0,
328 				 G_MAXUINT32,
329 				 0,
330 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
331   g_object_class_install_property(gobject,
332 				  PROP_BUFFER_SIZE,
333 				  param_spec);
334 
335   /**
336    * AgsAudioSignal:format:
337    *
338    * The format to be used.
339    *
340    * Since: 3.0.0
341    */
342   param_spec = g_param_spec_uint("format",
343 				 i18n_pspec("using format"),
344 				 i18n_pspec("The format to be used"),
345 				 0,
346 				 G_MAXUINT32,
347 				 0,
348 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
349   g_object_class_install_property(gobject,
350 				  PROP_FORMAT,
351 				  param_spec);
352 
353   /**
354    * AgsAudioSignal:word-size:
355    *
356    * The word size of frame.
357    *
358    * Since: 3.0.0
359    */
360   param_spec = g_param_spec_uint("word-size",
361 				 i18n_pspec("frame word size"),
362 				 i18n_pspec("The word size of a frame"),
363 				 0,
364 				 G_MAXUINT32,
365 				 0,
366 				 G_PARAM_READABLE);
367   g_object_class_install_property(gobject,
368 				  PROP_WORD_SIZE,
369 				  param_spec);
370 
371   /**
372    * AgsAudioSignal:length:
373    *
374    * The length of the stream.
375    *
376    * Since: 3.0.0
377    */
378   param_spec = g_param_spec_uint("length",
379 				 i18n_pspec("stream length"),
380 				 i18n_pspec("The length of the stream"),
381 				 0,
382 				 G_MAXUINT32,
383 				 0,
384 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
385   g_object_class_install_property(gobject,
386 				  PROP_LENGTH,
387 				  param_spec);
388 
389   /**
390    * AgsAudioSignal:first-frame:
391    *
392    * The first frame of stream.
393    *
394    * Since: 3.0.0
395    */
396   param_spec = g_param_spec_uint("first-frame",
397 				 i18n_pspec("stream's first frame"),
398 				 i18n_pspec("The first frame of the stream"),
399 				 0,
400 				 G_MAXUINT32,
401 				 0,
402 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
403   g_object_class_install_property(gobject,
404 				  PROP_FIRST_FRAME,
405 				  param_spec);
406 
407   /**
408    * AgsAudioSignal:last-frame:
409    *
410    * The last frame of stream.
411    *
412    * Since: 3.0.0
413    */
414   param_spec = g_param_spec_uint("last-frame",
415 				 i18n_pspec("stream's last frame"),
416 				 i18n_pspec("The last frame of the stream"),
417 				 0,
418 				 G_MAXUINT32,
419 				 0,
420 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
421   g_object_class_install_property(gobject,
422 				  PROP_LAST_FRAME,
423 				  param_spec);
424 
425   /**
426    * AgsAudioSignal:frame-count:
427    *
428    * The initial size of audio data.
429    *
430    * Since: 3.0.0
431    */
432   param_spec = g_param_spec_uint("frame-count",
433 				 i18n_pspec("frame count of audio data"),
434 				 i18n_pspec("The initial frame count of audio data"),
435 				 0,
436 				 G_MAXUINT32,
437 				 0,
438 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
439   g_object_class_install_property(gobject,
440 				  PROP_FRAME_COUNT,
441 				  param_spec);
442 
443   /**
444    * AgsAudioSignal:loop-start:
445    *
446    * The loop start of stream.
447    *
448    * Since: 3.0.0
449    */
450   param_spec = g_param_spec_uint("loop-start",
451 				 i18n_pspec("stream's loop start"),
452 				 i18n_pspec("The loop start of the stream"),
453 				 0,
454 				 G_MAXUINT32,
455 				 0,
456 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
457   g_object_class_install_property(gobject,
458 				  PROP_LOOP_START,
459 				  param_spec);
460 
461   /**
462    * AgsAudioSignal:loop-end:
463    *
464    * The loop end of stream.
465    *
466    * Since: 3.0.0
467    */
468   param_spec = g_param_spec_uint("loop-end",
469 				 i18n_pspec("stream's loop end"),
470 				 i18n_pspec("The loop end of the stream"),
471 				 0,
472 				 G_MAXUINT32,
473 				 0,
474 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
475   g_object_class_install_property(gobject,
476 				  PROP_LOOP_END,
477 				  param_spec);
478 
479   /**
480    * AgsAudioSignal:delay:
481    *
482    * The delay to be used.
483    *
484    * Since: 3.0.0
485    */
486   param_spec = g_param_spec_double("delay",
487 				   i18n_pspec("using delay"),
488 				   i18n_pspec("The delay to be used"),
489 				   0.0,
490 				   G_MAXDOUBLE,
491 				   0.0,
492 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
493   g_object_class_install_property(gobject,
494 				  PROP_DELAY,
495 				  param_spec);
496 
497   /**
498    * AgsAudioSignal:attack:
499    *
500    * The attack to be used.
501    *
502    * Since: 3.0.0
503    */
504   param_spec = g_param_spec_uint("attack",
505 				 i18n_pspec("using attack"),
506 				 i18n_pspec("The attack to be used"),
507 				 0,
508 				 G_MAXUINT32,
509 				 0,
510 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
511   g_object_class_install_property(gobject,
512 				  PROP_ATTACK,
513 				  param_spec);
514 
515   /**
516    * AgsAudioSignal:damping:
517    *
518    * Damping of timbre.
519    *
520    * Since: 3.0.0
521    */
522   param_spec = g_param_spec_boxed("damping",
523 				  i18n_pspec("damping"),
524 				  i18n_pspec("The timbre's damping"),
525 				  AGS_TYPE_COMPLEX,
526 				  G_PARAM_READABLE | G_PARAM_WRITABLE);
527   g_object_class_install_property(gobject,
528 				  PROP_DAMPING,
529 				  param_spec);
530 
531   /**
532    * AgsAudioSignal:vibration:
533    *
534    * Vibration of timbre.
535    *
536    * Since: 3.0.0
537    */
538   param_spec = g_param_spec_boxed("vibration",
539 				  i18n_pspec("vibration"),
540 				  i18n_pspec("The timbre's vibration"),
541 				  AGS_TYPE_COMPLEX,
542 				  G_PARAM_READABLE | G_PARAM_WRITABLE);
543   g_object_class_install_property(gobject,
544 				  PROP_VIBRATION,
545 				  param_spec);
546 
547   /**
548    * AgsAudioSignal:timbre-start:
549    *
550    * The timbre's start frame.
551    *
552    * Since: 3.0.0
553    */
554   param_spec = g_param_spec_uint("timbre-start",
555 				 i18n_pspec("timbre's start"),
556 				 i18n_pspec("The timbre's start frame"),
557 				 0,
558 				 G_MAXUINT32,
559 				 0,
560 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
561   g_object_class_install_property(gobject,
562 				  PROP_TIMBRE_START,
563 				  param_spec);
564 
565   /**
566    * AgsAudioSignal:timbre-end:
567    *
568    * The timbre's end frame.
569    *
570    * Since: 3.0.0
571    */
572   param_spec = g_param_spec_uint("timbre-end",
573 				 i18n_pspec("timbre's end"),
574 				 i18n_pspec("The timbre's end frame"),
575 				 0,
576 				 G_MAXUINT32,
577 				 0,
578 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
579   g_object_class_install_property(gobject,
580 				  PROP_TIMBRE_END,
581 				  param_spec);
582 
583   /**
584    * AgsAudioSignal:template:
585    *
586    * The assigned #AgsAudioSignal template.
587    *
588    * Since: 3.0.0
589    */
590   param_spec = g_param_spec_object("template",
591 				   i18n_pspec("assigned template"),
592 				   i18n_pspec("The assigend template"),
593 				   AGS_TYPE_AUDIO_SIGNAL,
594 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
595   g_object_class_install_property(gobject,
596 				  PROP_TEMPLATE,
597 				  param_spec);
598 
599   /**
600    * AgsAudioSignal:rt-template:
601    *
602    * The assigned #AgsAudioSignal realtime template.
603    *
604    * Since: 3.0.0
605    */
606   param_spec = g_param_spec_object("rt-template",
607 				   i18n_pspec("assigned realtime template"),
608 				   i18n_pspec("The assigend realtime template"),
609 				   AGS_TYPE_AUDIO_SIGNAL,
610 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
611   g_object_class_install_property(gobject,
612 				  PROP_RT_TEMPLATE,
613 				  param_spec);
614 
615   /**
616    * AgsAudioSignal:note: (type GList(AgsNote)) (transfer full)
617    *
618    * The assigned #AgsNote providing default settings.
619    *
620    * Since: 3.0.0
621    */
622   param_spec = g_param_spec_pointer("note",
623 				    i18n_pspec("assigned note"),
624 				    i18n_pspec("The note it is assigned with"),
625 				    G_PARAM_READABLE | G_PARAM_WRITABLE);
626   g_object_class_install_property(gobject,
627 				  PROP_NOTE,
628 				  param_spec);
629 
630   /**
631    * AgsAudioSignal:recall-id:
632    *
633    * The assigned #AgsRecallID providing context.
634    *
635    * Since: 3.0.0
636    */
637   param_spec = g_param_spec_object("recall-id",
638 				   i18n_pspec("assigned recall id"),
639 				   i18n_pspec("The recall id it is assigned with"),
640 				   AGS_TYPE_RECALL_ID,
641 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
642   g_object_class_install_property(gobject,
643 				  PROP_RECALL_ID,
644 				  param_spec);
645 
646   /**
647    * AgsAudioSignal:stream:
648    *
649    * The stream it contains.
650    *
651    * Since: 3.0.0
652    */
653   param_spec = g_param_spec_pointer("stream",
654 				    i18n_pspec("containing stream"),
655 				    i18n_pspec("The stream it contains"),
656 				    G_PARAM_READABLE);
657   g_object_class_install_property(gobject,
658 				  PROP_STREAM,
659 				  param_spec);
660 
661   /**
662    * AgsAudioSignal:stream-end:
663    *
664    * The end of stream.
665    *
666    * Since: 3.0.0
667    */
668   param_spec = g_param_spec_pointer("stream-end",
669 				    i18n_pspec("end of stream"),
670 				    i18n_pspec("The stream's end"),
671 				    G_PARAM_READABLE);
672   g_object_class_install_property(gobject,
673 				  PROP_STREAM_END,
674 				  param_spec);
675 
676   /**
677    * AgsAudioSignal:stream-current:
678    *
679    * The current stream.
680    *
681    * Since: 3.0.0
682    */
683   param_spec = g_param_spec_pointer("stream-current",
684 				    i18n_pspec("current stream"),
685 				    i18n_pspec("The current stream"),
686 				    G_PARAM_READABLE);
687   g_object_class_install_property(gobject,
688 				  PROP_STREAM_CURRENT,
689 				  param_spec);
690 
691   /* AgsAudioSignalClass */
692   audio_signal->add_note = ags_audio_signal_real_add_note;
693   audio_signal->remove_note = ags_audio_signal_real_remove_note;
694 
695   /* signals */
696   /**
697    * AgsAudioSignal::add-note:
698    * @audio_signal: the #AgsAudioSignal
699    * @note: the #AgsNote
700    *
701    * The ::add-note signal notifies about adding @note.
702    *
703    * Since: 3.0.0
704    */
705   audio_signal_signals[ADD_NOTE] =
706     g_signal_new("add-note",
707 		 G_TYPE_FROM_CLASS(audio_signal),
708 		 G_SIGNAL_RUN_LAST,
709 		 G_STRUCT_OFFSET(AgsAudioSignalClass, add_note),
710 		 NULL, NULL,
711 		 g_cclosure_marshal_VOID__OBJECT,
712 		 G_TYPE_NONE, 1,
713 		 G_TYPE_OBJECT);
714 
715   /**
716    * AgsAudioSignal::remove-note:
717    * @audio_signal: the #AgsAudioSignal
718    * @note: the #AgsNote
719    *
720    * The ::remove-note signal notifies about removing @note.
721    *
722    * Since: 3.0.0
723    */
724   audio_signal_signals[REMOVE_NOTE] =
725     g_signal_new("remove-note",
726 		 G_TYPE_FROM_CLASS(audio_signal),
727 		 G_SIGNAL_RUN_LAST,
728 		 G_STRUCT_OFFSET(AgsAudioSignalClass, remove_note),
729 		 NULL, NULL,
730 		 g_cclosure_marshal_VOID__OBJECT,
731 		 G_TYPE_NONE, 1,
732 		 G_TYPE_OBJECT);
733 
734 
735   /**
736    * AgsAudioSignal::refresh-data:
737    * @audio_signal: the #AgsAudioSignal
738    *
739    * The ::refresh-data signal notifies about requesting to refresh data.
740    *
741    * Since: 3.0.0
742    */
743   audio_signal_signals[REFRESH_DATA] =
744     g_signal_new("refresh-data",
745 		 G_TYPE_FROM_CLASS(audio_signal),
746 		 G_SIGNAL_RUN_LAST,
747 		 G_STRUCT_OFFSET(AgsAudioSignalClass, refresh_data),
748 		 NULL, NULL,
749 		 g_cclosure_marshal_VOID__VOID,
750 		 G_TYPE_NONE, 0);
751 }
752 
753 void
ags_audio_signal_connectable_interface_init(AgsConnectableInterface * connectable)754 ags_audio_signal_connectable_interface_init(AgsConnectableInterface *connectable)
755 {
756   connectable->get_uuid = ags_audio_signal_get_uuid;
757   connectable->has_resource = ags_audio_signal_has_resource;
758   connectable->is_ready = ags_audio_signal_is_ready;
759 
760   connectable->add_to_registry = ags_audio_signal_add_to_registry;
761   connectable->remove_from_registry = ags_audio_signal_remove_from_registry;
762 
763   connectable->list_resource = ags_audio_signal_list_resource;
764   connectable->xml_compose = ags_audio_signal_xml_compose;
765   connectable->xml_parse = ags_audio_signal_xml_parse;
766 
767   connectable->is_connected = ags_audio_signal_is_connected;
768 
769   connectable->connect = ags_audio_signal_connect;
770   connectable->disconnect = ags_audio_signal_disconnect;
771 
772   connectable->connect_connection = NULL;
773   connectable->disconnect_connection = NULL;
774 }
775 
776 void
ags_audio_signal_init(AgsAudioSignal * audio_signal)777 ags_audio_signal_init(AgsAudioSignal *audio_signal)
778 {
779   AgsConfig *config;
780 
781   double _Complex z;
782 
783   audio_signal->flags = 0;
784 
785   /* audio signal mutex */
786   g_rec_mutex_init(&(audio_signal->obj_mutex));
787 
788   /* uuid */
789 #if 0
790   audio_signal->uuid = ags_uuid_alloc();
791   ags_uuid_generate(audio_signal->uuid);
792 #else
793   audio_signal->uuid = NULL;
794 #endif
795 
796   /* recycling */
797   audio_signal->recycling = NULL;
798 
799   /* base init */
800   audio_signal->output_soundcard = NULL;
801   audio_signal->output_soundcard_channel = 0;
802 
803   audio_signal->input_soundcard = NULL;
804   audio_signal->input_soundcard_channel = 0;
805 
806 #if 1
807   /* config */
808   config = ags_config_get_instance();
809 
810   /* presets */
811   audio_signal->samplerate = (guint) ags_soundcard_helper_config_get_samplerate(config);
812   audio_signal->buffer_size = (guint) ags_soundcard_helper_config_get_buffer_size(config);
813   audio_signal->format = (guint) ags_soundcard_helper_config_get_format(config);
814 #else
815   /* presets */
816   audio_signal->samplerate = AGS_SOUNDCARD_DEFAULT_SAMPLERATE;
817   audio_signal->buffer_size = AGS_SOUNDCARD_DEFAULT_BUFFER_SIZE;
818   audio_signal->format = AGS_SOUNDCARD_DEFAULT_FORMAT;
819 #endif
820 
821   audio_signal->word_size = sizeof(gint16);
822 
823   /* format */
824   switch(audio_signal->format){
825   case AGS_SOUNDCARD_SIGNED_8_BIT:
826   {
827     audio_signal->word_size = sizeof(gint8);
828   }
829   break;
830   case AGS_SOUNDCARD_SIGNED_16_BIT:
831   {
832     audio_signal->word_size = sizeof(gint16);
833   }
834   break;
835   case AGS_SOUNDCARD_SIGNED_24_BIT:
836   {
837     audio_signal->word_size = sizeof(gint32);
838   }
839   break;
840   case AGS_SOUNDCARD_SIGNED_32_BIT:
841   {
842     audio_signal->word_size = sizeof(gint32);
843   }
844   break;
845   case AGS_SOUNDCARD_SIGNED_64_BIT:
846   {
847     audio_signal->word_size = sizeof(gint64);
848   }
849   break;
850   case AGS_SOUNDCARD_FLOAT:
851   {
852     audio_signal->word_size = sizeof(gfloat);
853   }
854   break;
855   case AGS_SOUNDCARD_DOUBLE:
856   {
857     audio_signal->word_size = sizeof(gdouble);
858   }
859   break;
860   }
861 
862   /* duration */
863   audio_signal->length = 0;
864   audio_signal->first_frame = 0;
865   audio_signal->last_frame = 0;
866 
867   audio_signal->frame_count = 0;
868   audio_signal->loop_start = 0;
869   audio_signal->loop_end = 0;
870 
871   /* offset */
872   audio_signal->delay = 0.0;
873   audio_signal->attack = 0;
874 
875   /* timbre */
876   z = 0.0 + I * 1.0;
877   ags_complex_set(&(audio_signal->damping),
878 		  z);
879 
880   z = 0.0 + I * 1.0;
881   ags_complex_set(&(audio_signal->vibration),
882 		  z);
883 
884   audio_signal->timbre_start = 0;
885   audio_signal->timbre_end = 0;
886 
887   /* template */
888   audio_signal->template = NULL;
889 
890   /* realtime fields */
891   audio_signal->rt_template = NULL;
892   audio_signal->note = NULL;
893 
894   /* recall id */
895   audio_signal->recall_id = NULL;
896 
897   /* stream */
898   g_rec_mutex_init(&(audio_signal->stream_mutex));
899 
900   audio_signal->stream = NULL;
901   audio_signal->stream_current = NULL;
902   audio_signal->stream_end = NULL;
903 }
904 
905 void
ags_audio_signal_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)906 ags_audio_signal_set_property(GObject *gobject,
907 			      guint prop_id,
908 			      const GValue *value,
909 			      GParamSpec *param_spec)
910 {
911   AgsAudioSignal *audio_signal;
912 
913   GRecMutex *audio_signal_mutex;
914 
915   audio_signal = AGS_AUDIO_SIGNAL(gobject);
916 
917   /* get audio signal mutex */
918   audio_signal_mutex = AGS_AUDIO_SIGNAL_GET_OBJ_MUTEX(audio_signal);
919 
920   switch(prop_id){
921   case PROP_RECYCLING:
922   {
923     GObject *recycling;
924 
925     recycling = g_value_get_object(value);
926 
927     g_rec_mutex_lock(audio_signal_mutex);
928 
929     if(audio_signal->recycling == recycling){
930       g_rec_mutex_unlock(audio_signal_mutex);
931 
932       return;
933     }
934 
935     if(audio_signal->recycling != NULL){
936       g_object_unref(audio_signal->recycling);
937     }
938 
939     if(recycling != NULL){
940       g_object_ref(recycling);
941     }
942 
943     audio_signal->recycling = recycling;
944 
945     g_rec_mutex_unlock(audio_signal_mutex);
946   }
947   break;
948   case PROP_OUTPUT_SOUNDCARD:
949   {
950     GObject *output_soundcard;
951 
952     output_soundcard = g_value_get_object(value);
953 
954     ags_audio_signal_real_set_output_soundcard(audio_signal,
955 					       output_soundcard);
956   }
957   break;
958   case PROP_OUTPUT_SOUNDCARD_CHANNEL:
959   {
960     g_rec_mutex_lock(audio_signal_mutex);
961 
962     audio_signal->output_soundcard_channel = g_value_get_int(value);
963 
964     g_rec_mutex_unlock(audio_signal_mutex);
965   }
966   break;
967   case PROP_INPUT_SOUNDCARD:
968   {
969     GObject *input_soundcard;
970 
971     input_soundcard = g_value_get_object(value);
972 
973     ags_audio_signal_real_set_input_soundcard(audio_signal,
974 					      input_soundcard);
975   }
976   break;
977   case PROP_INPUT_SOUNDCARD_CHANNEL:
978   {
979     g_rec_mutex_lock(audio_signal_mutex);
980 
981     audio_signal->input_soundcard_channel = g_value_get_int(value);
982 
983     g_rec_mutex_unlock(audio_signal_mutex);
984   }
985   break;
986   case PROP_SAMPLERATE:
987   {
988     guint samplerate;
989 
990     samplerate = g_value_get_uint(value);
991 
992     ags_audio_signal_set_samplerate(audio_signal,
993 				    samplerate);
994   }
995   break;
996   case PROP_BUFFER_SIZE:
997   {
998     guint buffer_size;
999 
1000     buffer_size = g_value_get_uint(value);
1001 
1002     ags_audio_signal_set_buffer_size(audio_signal,
1003 				     buffer_size);
1004   }
1005   break;
1006   case PROP_FORMAT:
1007   {
1008     guint format;
1009 
1010     format = g_value_get_uint(value);
1011 
1012     ags_audio_signal_set_format(audio_signal,
1013 				format);
1014   }
1015   break;
1016   case PROP_LENGTH:
1017   {
1018     guint length;
1019 
1020     length = g_value_get_uint(value);
1021 
1022     g_rec_mutex_lock(audio_signal_mutex);
1023 
1024     audio_signal->length = length;
1025 
1026     g_rec_mutex_unlock(audio_signal_mutex);
1027   }
1028   break;
1029   case PROP_FIRST_FRAME:
1030   {
1031     guint first_frame;
1032 
1033     first_frame = g_value_get_uint(value);
1034 
1035     g_rec_mutex_lock(audio_signal_mutex);
1036 
1037     audio_signal->first_frame = first_frame;
1038 
1039     g_rec_mutex_unlock(audio_signal_mutex);
1040   }
1041   break;
1042   case PROP_LAST_FRAME:
1043   {
1044     guint last_frame;
1045 
1046     last_frame = g_value_get_uint(value);
1047 
1048     g_rec_mutex_lock(audio_signal_mutex);
1049 
1050     audio_signal->last_frame = last_frame;
1051 
1052     g_rec_mutex_unlock(audio_signal_mutex);
1053   }
1054   break;
1055   case PROP_FRAME_COUNT:
1056   {
1057     guint frame_count;
1058 
1059     frame_count = g_value_get_uint(value);
1060 
1061     g_rec_mutex_lock(audio_signal_mutex);
1062 
1063     audio_signal->frame_count = frame_count;
1064 
1065     g_rec_mutex_unlock(audio_signal_mutex);
1066   }
1067   break;
1068   case PROP_LOOP_START:
1069   {
1070     guint loop_start;
1071 
1072     loop_start = g_value_get_uint(value);
1073 
1074     g_rec_mutex_lock(audio_signal_mutex);
1075 
1076     audio_signal->loop_start = loop_start;
1077 
1078     g_rec_mutex_unlock(audio_signal_mutex);
1079   }
1080   break;
1081   case PROP_LOOP_END:
1082   {
1083     guint loop_end;
1084 
1085     loop_end = g_value_get_uint(value);
1086 
1087     g_rec_mutex_lock(audio_signal_mutex);
1088 
1089     audio_signal->loop_end = loop_end;
1090 
1091     g_rec_mutex_unlock(audio_signal_mutex);
1092   }
1093   break;
1094   case PROP_DELAY:
1095   {
1096     gdouble delay;
1097 
1098     delay = g_value_get_double(value);
1099 
1100     g_rec_mutex_lock(audio_signal_mutex);
1101 
1102     audio_signal->delay = delay;
1103 
1104     g_rec_mutex_unlock(audio_signal_mutex);
1105   }
1106   break;
1107   case PROP_ATTACK:
1108   {
1109     guint attack;
1110 
1111     attack = g_value_get_uint(value);
1112 
1113     g_rec_mutex_lock(audio_signal_mutex);
1114 
1115     audio_signal->attack = attack;
1116 
1117     g_rec_mutex_unlock(audio_signal_mutex);
1118   }
1119   break;
1120   case PROP_DAMPING:
1121   {
1122     AgsComplex *damping;
1123 
1124     damping = (AgsComplex *) g_value_get_boxed(value);
1125 
1126     g_rec_mutex_lock(audio_signal_mutex);
1127 
1128     ags_complex_set(&(audio_signal->damping),
1129 		    ags_complex_get(damping));
1130 
1131     g_rec_mutex_unlock(audio_signal_mutex);
1132   }
1133   break;
1134   case PROP_VIBRATION:
1135   {
1136     AgsComplex *vibration;
1137 
1138     vibration = (AgsComplex *) g_value_get_boxed(value);
1139 
1140     g_rec_mutex_lock(audio_signal_mutex);
1141 
1142     ags_complex_set(&(audio_signal->vibration),
1143 		    ags_complex_get(vibration));
1144 
1145     g_rec_mutex_unlock(audio_signal_mutex);
1146   }
1147   break;
1148   case PROP_TIMBRE_START:
1149   {
1150     g_rec_mutex_lock(audio_signal_mutex);
1151 
1152     audio_signal->timbre_start = g_value_get_uint(value);
1153 
1154     g_rec_mutex_unlock(audio_signal_mutex);
1155   }
1156   break;
1157   case PROP_TIMBRE_END:
1158   {
1159     g_rec_mutex_lock(audio_signal_mutex);
1160 
1161     audio_signal->timbre_end = g_value_get_uint(value);
1162 
1163     g_rec_mutex_unlock(audio_signal_mutex);
1164   }
1165   break;
1166   case PROP_TEMPLATE:
1167   {
1168     GObject *template;
1169 
1170     template = g_value_get_object(value);
1171 
1172     g_rec_mutex_lock(audio_signal_mutex);
1173 
1174     if(audio_signal->template == template){
1175       g_rec_mutex_unlock(audio_signal_mutex);
1176 
1177       return;
1178     }
1179 
1180     if(audio_signal->template != NULL){
1181       g_object_unref(audio_signal->template);
1182     }
1183 
1184     if(template != NULL){
1185       g_object_ref(template);
1186     }
1187 
1188     audio_signal->template = template;
1189 
1190     g_rec_mutex_unlock(audio_signal_mutex);
1191   }
1192   break;
1193   case PROP_RT_TEMPLATE:
1194   {
1195     GObject *rt_template;
1196 
1197     rt_template = g_value_get_object(value);
1198 
1199     g_rec_mutex_lock(audio_signal_mutex);
1200 
1201     if(audio_signal->rt_template == rt_template){
1202       g_rec_mutex_unlock(audio_signal_mutex);
1203 
1204       return;
1205     }
1206 
1207     if(audio_signal->rt_template != NULL){
1208       g_object_unref(audio_signal->rt_template);
1209     }
1210 
1211     if(rt_template != NULL){
1212       g_object_ref(rt_template);
1213     }
1214 
1215     audio_signal->rt_template = rt_template;
1216 
1217     g_rec_mutex_unlock(audio_signal_mutex);
1218   }
1219   break;
1220   case PROP_NOTE:
1221   {
1222     GObject *note;
1223 
1224     note = g_value_get_pointer(value);
1225 
1226     g_rec_mutex_lock(audio_signal_mutex);
1227 
1228     if(g_list_find(audio_signal->note, note) != NULL){
1229       g_rec_mutex_unlock(audio_signal_mutex);
1230 
1231       return;
1232     }
1233 
1234     g_rec_mutex_unlock(audio_signal_mutex);
1235 
1236     ags_audio_signal_add_note(audio_signal,
1237 			      note);
1238   }
1239   break;
1240   case PROP_RECALL_ID:
1241   {
1242     GObject *recall_id;
1243 
1244     recall_id = g_value_get_object(value);
1245 
1246     g_rec_mutex_lock(audio_signal_mutex);
1247 
1248     if(audio_signal->recall_id == recall_id){
1249       g_rec_mutex_unlock(audio_signal_mutex);
1250 
1251       return;
1252     }
1253 
1254     if(audio_signal->recall_id != NULL){
1255       g_object_unref(audio_signal->recall_id);
1256     }
1257 
1258     if(recall_id != NULL){
1259       g_object_ref(recall_id);
1260     }
1261 
1262     audio_signal->recall_id = recall_id;
1263 
1264     g_rec_mutex_unlock(audio_signal_mutex);
1265   }
1266   break;
1267   default:
1268     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
1269     break;
1270   }
1271 }
1272 
1273 void
ags_audio_signal_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)1274 ags_audio_signal_get_property(GObject *gobject,
1275 			      guint prop_id,
1276 			      GValue *value,
1277 			      GParamSpec *param_spec)
1278 {
1279   AgsAudioSignal *audio_signal;
1280 
1281   GRecMutex *audio_signal_mutex;
1282   GRecMutex *stream_mutex;
1283 
1284   audio_signal = AGS_AUDIO_SIGNAL(gobject);
1285 
1286   /* get audio signal mutex */
1287   audio_signal_mutex = AGS_AUDIO_SIGNAL_GET_OBJ_MUTEX(audio_signal);
1288   stream_mutex = AGS_AUDIO_SIGNAL_GET_STREAM_MUTEX(audio_signal);
1289 
1290   switch(prop_id){
1291   case PROP_RECYCLING:
1292   {
1293     g_rec_mutex_lock(audio_signal_mutex);
1294 
1295     g_value_set_object(value, audio_signal->recycling);
1296 
1297     g_rec_mutex_unlock(audio_signal_mutex);
1298   }
1299   break;
1300   case PROP_OUTPUT_SOUNDCARD:
1301   {
1302     g_rec_mutex_lock(audio_signal_mutex);
1303 
1304     g_value_set_object(value, audio_signal->output_soundcard);
1305 
1306     g_rec_mutex_unlock(audio_signal_mutex);
1307   }
1308   break;
1309   case PROP_OUTPUT_SOUNDCARD_CHANNEL:
1310   {
1311     g_rec_mutex_lock(audio_signal_mutex);
1312 
1313     g_value_set_int(value, audio_signal->output_soundcard_channel);
1314 
1315     g_rec_mutex_unlock(audio_signal_mutex);
1316   }
1317   break;
1318   case PROP_INPUT_SOUNDCARD:
1319   {
1320     g_rec_mutex_lock(audio_signal_mutex);
1321 
1322     g_value_set_object(value, audio_signal->input_soundcard);
1323 
1324     g_rec_mutex_unlock(audio_signal_mutex);
1325   }
1326   break;
1327   case PROP_INPUT_SOUNDCARD_CHANNEL:
1328   {
1329     g_rec_mutex_lock(audio_signal_mutex);
1330 
1331     g_value_set_int(value, audio_signal->input_soundcard_channel);
1332 
1333     g_rec_mutex_unlock(audio_signal_mutex);
1334   }
1335   break;
1336   case PROP_SAMPLERATE:
1337   {
1338     g_rec_mutex_lock(audio_signal_mutex);
1339 
1340     g_value_set_uint(value, audio_signal->samplerate);
1341 
1342     g_rec_mutex_unlock(audio_signal_mutex);
1343   }
1344   break;
1345   case PROP_BUFFER_SIZE:
1346   {
1347     g_rec_mutex_lock(audio_signal_mutex);
1348 
1349     g_value_set_uint(value, audio_signal->buffer_size);
1350 
1351     g_rec_mutex_unlock(audio_signal_mutex);
1352   }
1353   break;
1354   case PROP_FORMAT:
1355   {
1356     g_rec_mutex_lock(audio_signal_mutex);
1357 
1358     g_value_set_uint(value, audio_signal->format);
1359 
1360     g_rec_mutex_unlock(audio_signal_mutex);
1361   }
1362   break;
1363   case PROP_WORD_SIZE:
1364   {
1365     g_rec_mutex_lock(audio_signal_mutex);
1366 
1367     g_value_set_uint(value, audio_signal->word_size);
1368 
1369     g_rec_mutex_unlock(audio_signal_mutex);
1370   }
1371   break;
1372   case PROP_LENGTH:
1373   {
1374     g_rec_mutex_lock(audio_signal_mutex);
1375 
1376     g_value_set_uint(value, audio_signal->length);
1377 
1378     g_rec_mutex_unlock(audio_signal_mutex);
1379   }
1380   break;
1381   case PROP_FIRST_FRAME:
1382   {
1383     g_rec_mutex_lock(audio_signal_mutex);
1384 
1385     g_value_set_uint(value, audio_signal->first_frame);
1386 
1387     g_rec_mutex_unlock(audio_signal_mutex);
1388   }
1389   break;
1390   case PROP_LAST_FRAME:
1391   {
1392     g_rec_mutex_lock(audio_signal_mutex);
1393 
1394     g_value_set_uint(value, audio_signal->last_frame);
1395 
1396     g_rec_mutex_unlock(audio_signal_mutex);
1397   }
1398   break;
1399   case PROP_FRAME_COUNT:
1400   {
1401     g_rec_mutex_lock(audio_signal_mutex);
1402 
1403     g_value_set_uint(value, audio_signal->frame_count);
1404 
1405     g_rec_mutex_unlock(audio_signal_mutex);
1406   }
1407   break;
1408   case PROP_LOOP_START:
1409   {
1410     g_rec_mutex_lock(audio_signal_mutex);
1411 
1412     g_value_set_uint(value, audio_signal->loop_start);
1413 
1414     g_rec_mutex_unlock(audio_signal_mutex);
1415   }
1416   break;
1417   case PROP_LOOP_END:
1418   {
1419     g_rec_mutex_lock(audio_signal_mutex);
1420 
1421     g_value_set_uint(value, audio_signal->loop_end);
1422 
1423     g_rec_mutex_unlock(audio_signal_mutex);
1424   }
1425   break;
1426   case PROP_DELAY:
1427   {
1428     g_rec_mutex_lock(audio_signal_mutex);
1429 
1430     g_value_set_double(value, audio_signal->delay);
1431 
1432     g_rec_mutex_unlock(audio_signal_mutex);
1433   }
1434   break;
1435   case PROP_ATTACK:
1436   {
1437     g_rec_mutex_lock(audio_signal_mutex);
1438 
1439     g_value_set_uint(value, audio_signal->attack);
1440 
1441     g_rec_mutex_unlock(audio_signal_mutex);
1442   }
1443   break;
1444   case PROP_DAMPING:
1445   {
1446     g_rec_mutex_lock(audio_signal_mutex);
1447 
1448     g_value_set_boxed(value, &(audio_signal->damping));
1449 
1450     g_rec_mutex_unlock(audio_signal_mutex);
1451   }
1452   break;
1453   case PROP_VIBRATION:
1454   {
1455     g_rec_mutex_lock(audio_signal_mutex);
1456 
1457     g_value_set_boxed(value, &(audio_signal->vibration));
1458 
1459     g_rec_mutex_unlock(audio_signal_mutex);
1460   }
1461   break;
1462   case PROP_TIMBRE_START:
1463   {
1464     g_rec_mutex_lock(audio_signal_mutex);
1465 
1466     g_value_set_uint(value, audio_signal->timbre_start);
1467 
1468     g_rec_mutex_unlock(audio_signal_mutex);
1469   }
1470   break;
1471   case PROP_TIMBRE_END:
1472   {
1473     g_rec_mutex_lock(audio_signal_mutex);
1474 
1475     g_value_set_uint(value, audio_signal->timbre_end);
1476 
1477     g_rec_mutex_unlock(audio_signal_mutex);
1478   }
1479   break;
1480   case PROP_TEMPLATE:
1481   {
1482     g_rec_mutex_lock(audio_signal_mutex);
1483 
1484     g_value_set_object(value, audio_signal->template);
1485 
1486     g_rec_mutex_unlock(audio_signal_mutex);
1487   }
1488   break;
1489   case PROP_RT_TEMPLATE:
1490   {
1491     g_rec_mutex_lock(audio_signal_mutex);
1492 
1493     g_value_set_object(value, audio_signal->rt_template);
1494 
1495     g_rec_mutex_unlock(audio_signal_mutex);
1496   }
1497   break;
1498   case PROP_NOTE:
1499   {
1500     g_rec_mutex_lock(audio_signal_mutex);
1501 
1502     g_value_set_pointer(value,
1503 			g_list_copy_deep(audio_signal->note,
1504 					 (GCopyFunc) g_object_ref,
1505 					 NULL));
1506 
1507     g_rec_mutex_unlock(audio_signal_mutex);
1508   }
1509   break;
1510   case PROP_RECALL_ID:
1511   {
1512     g_rec_mutex_lock(audio_signal_mutex);
1513 
1514     g_value_set_object(value, audio_signal->recall_id);
1515 
1516     g_rec_mutex_unlock(audio_signal_mutex);
1517   }
1518   break;
1519   case PROP_STREAM:
1520   {
1521     g_rec_mutex_lock(stream_mutex);
1522 
1523     g_value_set_pointer(value, audio_signal->stream);
1524 
1525     g_rec_mutex_unlock(stream_mutex);
1526   }
1527   break;
1528   case PROP_STREAM_END:
1529   {
1530     g_rec_mutex_lock(stream_mutex);
1531 
1532     g_value_set_pointer(value, audio_signal->stream_end);
1533 
1534     g_rec_mutex_unlock(stream_mutex);
1535   }
1536   break;
1537   case PROP_STREAM_CURRENT:
1538   {
1539     g_rec_mutex_lock(stream_mutex);
1540 
1541     g_value_set_pointer(value, audio_signal->stream_current);
1542 
1543     g_rec_mutex_unlock(stream_mutex);
1544   }
1545   break;
1546   default:
1547     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
1548     break;
1549   }
1550 }
1551 
1552 void
ags_audio_signal_dispose(GObject * gobject)1553 ags_audio_signal_dispose(GObject *gobject)
1554 {
1555   AgsAudioSignal *audio_signal;
1556 
1557   audio_signal = AGS_AUDIO_SIGNAL(gobject);
1558 
1559   /* recycling */
1560   if(audio_signal->recycling != NULL){
1561     g_object_unref(audio_signal->recycling);
1562 
1563     audio_signal->recycling = NULL;
1564   }
1565 
1566   /* output soundcard */
1567   if(audio_signal->output_soundcard != NULL){
1568     g_object_unref(audio_signal->output_soundcard);
1569 
1570     audio_signal->output_soundcard = NULL;
1571   }
1572 
1573   /* input soundcard */
1574   if(audio_signal->input_soundcard != NULL){
1575     g_object_unref(audio_signal->input_soundcard);
1576 
1577     audio_signal->input_soundcard = NULL;
1578   }
1579 
1580   /* template */
1581   if(audio_signal->template != NULL){
1582     g_object_unref(audio_signal->template);
1583 
1584     audio_signal->template = NULL;
1585   }
1586 
1587   /* rt-template */
1588   if(audio_signal->rt_template != NULL){
1589     g_object_unref(audio_signal->rt_template);
1590 
1591     audio_signal->rt_template = NULL;
1592   }
1593 
1594   /* note */
1595   if(audio_signal->note != NULL){
1596     g_list_free_full(audio_signal->note,
1597 		     g_object_unref);
1598 
1599     audio_signal->note = NULL;
1600   }
1601 
1602   /* recall id */
1603   if(audio_signal->recall_id != NULL){
1604     g_object_unref(audio_signal->recall_id);
1605 
1606     audio_signal->recall_id = NULL;
1607   }
1608 
1609   /* call parent */
1610   G_OBJECT_CLASS(ags_audio_signal_parent_class)->dispose(gobject);
1611 }
1612 
1613 void
ags_audio_signal_finalize(GObject * gobject)1614 ags_audio_signal_finalize(GObject *gobject)
1615 {
1616   AgsAudioSignal *audio_signal;
1617 
1618   guint *ids;
1619   guint i, n_ids;
1620 
1621   audio_signal = AGS_AUDIO_SIGNAL(gobject);
1622 
1623 #ifdef AGS_DEBUG
1624   g_message("fin %x", audio_signal);
1625 
1626   if((AGS_AUDIO_SIGNAL_TEMPLATE & (audio_signal->flags)) != 0){
1627     g_warning("AGS_AUDIO_SIGNAL_TEMPLATE: destroying\n");
1628   }
1629 #endif
1630 
1631   ags_uuid_free(audio_signal->uuid);
1632 
1633   /* disconnect */
1634 #if 0
1635   ids = g_signal_list_ids(AGS_TYPE_AUDIO_SIGNAL,
1636 			  &n_ids);
1637 
1638   for(i = 0; i < n_ids; i++){
1639     g_signal_handlers_disconnect_matched(gobject,
1640 					 G_SIGNAL_MATCH_ID,
1641 					 ids[i],
1642 					 0,
1643 					 NULL,
1644 					 NULL,
1645 					 NULL);
1646   }
1647 
1648   g_free(ids);
1649 #endif
1650 
1651   /* recycling */
1652   if(audio_signal->recycling != NULL){
1653     g_object_unref(audio_signal->recycling);
1654   }
1655 
1656   /* output soundcard */
1657   if(audio_signal->output_soundcard != NULL){
1658     g_object_unref(audio_signal->output_soundcard);
1659   }
1660 
1661   /* input soundcard */
1662   if(audio_signal->input_soundcard != NULL){
1663     g_object_unref(audio_signal->input_soundcard);
1664   }
1665 
1666   /* template */
1667   if(audio_signal->template != NULL){
1668     g_object_unref(audio_signal->template);
1669   }
1670 
1671   /* rt-template */
1672   if(audio_signal->rt_template != NULL){
1673     g_object_unref(audio_signal->rt_template);
1674   }
1675 
1676   /* note */
1677   if(audio_signal->note != NULL){
1678     g_list_free_full(audio_signal->note,
1679 		     g_object_unref);
1680   }
1681 
1682   /* recall id */
1683   if(audio_signal->recall_id != NULL){
1684     g_object_unref(audio_signal->recall_id);
1685   }
1686 
1687   /* audio data */
1688   if((AGS_AUDIO_SIGNAL_SLICE_ALLOC & (audio_signal->flags)) == 0){
1689     g_list_free_full(audio_signal->stream,
1690 		     (GDestroyNotify) ags_stream_free);
1691   }else{
1692     GList *stream;
1693 
1694     stream = audio_signal->stream;
1695 
1696     while(stream != NULL){
1697       ags_stream_slice_free(audio_signal->buffer_size,
1698 			    audio_signal->format,
1699 			    stream->data);
1700 
1701       stream = stream->next;
1702     }
1703 
1704     g_list_free(audio_signal->stream);
1705   }
1706 
1707   /* call parent */
1708   G_OBJECT_CLASS(ags_audio_signal_parent_class)->finalize(gobject);
1709 }
1710 
1711 AgsUUID*
ags_audio_signal_get_uuid(AgsConnectable * connectable)1712 ags_audio_signal_get_uuid(AgsConnectable *connectable)
1713 {
1714   AgsAudioSignal *audio_signal;
1715 
1716   AgsUUID *ptr;
1717 
1718   GRecMutex *audio_signal_mutex;
1719 
1720   audio_signal = AGS_AUDIO_SIGNAL(connectable);
1721 
1722   /* get audio signal mutex */
1723   audio_signal_mutex = AGS_AUDIO_SIGNAL_GET_OBJ_MUTEX(audio_signal);
1724 
1725   /* get UUID */
1726   g_rec_mutex_lock(audio_signal_mutex);
1727 
1728   ptr = audio_signal->uuid;
1729 
1730   g_rec_mutex_unlock(audio_signal_mutex);
1731 
1732   return(ptr);
1733 }
1734 
1735 gboolean
ags_audio_signal_has_resource(AgsConnectable * connectable)1736 ags_audio_signal_has_resource(AgsConnectable *connectable)
1737 {
1738   return(TRUE);
1739 }
1740 
1741 gboolean
ags_audio_signal_is_ready(AgsConnectable * connectable)1742 ags_audio_signal_is_ready(AgsConnectable *connectable)
1743 {
1744   AgsAudioSignal *audio_signal;
1745 
1746   gboolean is_ready;
1747 
1748   audio_signal = AGS_AUDIO_SIGNAL(connectable);
1749 
1750   is_ready = ags_audio_signal_test_flags(audio_signal, AGS_AUDIO_SIGNAL_ADDED_TO_REGISTRY);
1751 
1752   return(is_ready);
1753 }
1754 
1755 void
ags_audio_signal_add_to_registry(AgsConnectable * connectable)1756 ags_audio_signal_add_to_registry(AgsConnectable *connectable)
1757 {
1758   AgsAudioSignal *audio_signal;
1759 
1760   AgsRegistry *registry;
1761   AgsRegistryEntry *entry;
1762 
1763   AgsApplicationContext *application_context;
1764 
1765   if(ags_connectable_is_ready(connectable)){
1766     return;
1767   }
1768 
1769   audio_signal = AGS_AUDIO_SIGNAL(connectable);
1770 
1771   ags_audio_signal_set_flags(audio_signal, AGS_AUDIO_SIGNAL_ADDED_TO_REGISTRY);
1772 
1773   application_context = ags_application_context_get_instance();
1774 
1775   registry = (AgsRegistry *) ags_service_provider_get_registry(AGS_SERVICE_PROVIDER(application_context));
1776 
1777   if(registry != NULL){
1778     entry = ags_registry_entry_alloc(registry);
1779     g_value_set_object(entry->entry,
1780 		       (gpointer) audio_signal);
1781     ags_registry_add_entry(registry,
1782 			   entry);
1783   }
1784 }
1785 
1786 void
ags_audio_signal_remove_from_registry(AgsConnectable * connectable)1787 ags_audio_signal_remove_from_registry(AgsConnectable *connectable)
1788 {
1789   if(!ags_connectable_is_ready(connectable)){
1790     return;
1791   }
1792 
1793   //TODO:JK: implement me
1794 }
1795 
1796 xmlNode*
ags_audio_signal_list_resource(AgsConnectable * connectable)1797 ags_audio_signal_list_resource(AgsConnectable *connectable)
1798 {
1799   xmlNode *node;
1800 
1801   node = NULL;
1802 
1803   //TODO:JK: implement me
1804 
1805   return(node);
1806 }
1807 
1808 xmlNode*
ags_audio_signal_xml_compose(AgsConnectable * connectable)1809 ags_audio_signal_xml_compose(AgsConnectable *connectable)
1810 {
1811   xmlNode *node;
1812 
1813   node = NULL;
1814 
1815   //TODO:JK: implement me
1816 
1817   return(node);
1818 }
1819 
1820 void
ags_audio_signal_xml_parse(AgsConnectable * connectable,xmlNode * node)1821 ags_audio_signal_xml_parse(AgsConnectable *connectable,
1822 			   xmlNode *node)
1823 {
1824   //TODO:JK: implement me
1825 }
1826 
1827 gboolean
ags_audio_signal_is_connected(AgsConnectable * connectable)1828 ags_audio_signal_is_connected(AgsConnectable *connectable)
1829 {
1830   AgsAudioSignal *audio_signal;
1831 
1832   gboolean is_connected;
1833 
1834   audio_signal = AGS_AUDIO_SIGNAL(connectable);
1835 
1836   is_connected = ags_audio_signal_test_flags(audio_signal, AGS_AUDIO_SIGNAL_CONNECTED);
1837 
1838   return(is_connected);
1839 }
1840 
1841 void
ags_audio_signal_connect(AgsConnectable * connectable)1842 ags_audio_signal_connect(AgsConnectable *connectable)
1843 {
1844   AgsAudioSignal *audio_signal;
1845 
1846   if(ags_connectable_is_connected(connectable)){
1847     return;
1848   }
1849 
1850   audio_signal = AGS_AUDIO_SIGNAL(connectable);
1851 
1852   ags_audio_signal_set_flags(audio_signal, AGS_AUDIO_SIGNAL_CONNECTED);
1853 }
1854 
1855 void
ags_audio_signal_disconnect(AgsConnectable * connectable)1856 ags_audio_signal_disconnect(AgsConnectable *connectable)
1857 {
1858   AgsAudioSignal *audio_signal;
1859 
1860   if(!ags_connectable_is_connected(connectable)){
1861     return;
1862   }
1863 
1864   audio_signal = AGS_AUDIO_SIGNAL(connectable);
1865 
1866   ags_audio_signal_unset_flags(audio_signal, AGS_AUDIO_SIGNAL_CONNECTED);
1867 }
1868 
1869 /**
1870  * ags_audio_signal_get_obj_mutex:
1871  * @audio_signal: the #AgsAudioSignal
1872  *
1873  * Get object mutex.
1874  *
1875  * Returns: the #GRecMutex to lock @audio_signal
1876  *
1877  * Since: 3.1.0
1878  */
1879 GRecMutex*
ags_audio_signal_get_obj_mutex(AgsAudioSignal * audio_signal)1880 ags_audio_signal_get_obj_mutex(AgsAudioSignal *audio_signal)
1881 {
1882   if(!AGS_IS_AUDIO_SIGNAL(audio_signal)){
1883     return(NULL);
1884   }
1885 
1886   return(AGS_AUDIO_SIGNAL_GET_OBJ_MUTEX(audio_signal));
1887 }
1888 
1889 /**
1890  * ags_audio_signal_stream_lock:
1891  * @audio_signal: the #AgsAudioSignal
1892  *
1893  * Lock stream mutex.
1894  *
1895  * Since: 3.1.0
1896  */
1897 void
ags_audio_signal_stream_lock(AgsAudioSignal * audio_signal)1898 ags_audio_signal_stream_lock(AgsAudioSignal *audio_signal)
1899 {
1900   if(!AGS_IS_AUDIO_SIGNAL(audio_signal)){
1901     return;
1902   }
1903 
1904   g_rec_mutex_lock(AGS_AUDIO_SIGNAL_GET_STREAM_MUTEX(audio_signal));
1905 }
1906 
1907 /**
1908  * ags_audio_signal_stream_unlock:
1909  * @audio_signal: the #AgsAudioSignal
1910  *
1911  * Unlock stream mutex.
1912  *
1913  * Since: 3.1.0
1914  */
1915 void
ags_audio_signal_stream_unlock(AgsAudioSignal * audio_signal)1916 ags_audio_signal_stream_unlock(AgsAudioSignal *audio_signal)
1917 {
1918   if(!AGS_IS_AUDIO_SIGNAL(audio_signal)){
1919     return;
1920   }
1921 
1922   g_rec_mutex_unlock(AGS_AUDIO_SIGNAL_GET_STREAM_MUTEX(audio_signal));
1923 }
1924 
1925 /**
1926  * ags_audio_signal_test_flags:
1927  * @audio_signal: the #AgsAudioSignal
1928  * @flags: the flags
1929  *
1930  * Test @flags to be set on @audio_signal.
1931  *
1932  * Returns: %TRUE if flags are set, else %FALSE
1933  *
1934  * Since: 3.0.0
1935  */
1936 gboolean
ags_audio_signal_test_flags(AgsAudioSignal * audio_signal,guint flags)1937 ags_audio_signal_test_flags(AgsAudioSignal *audio_signal, guint flags)
1938 {
1939   gboolean retval;
1940 
1941   GRecMutex *audio_signal_mutex;
1942 
1943   if(!AGS_IS_AUDIO_SIGNAL(audio_signal)){
1944     return(FALSE);
1945   }
1946 
1947   /* get audio_signal mutex */
1948   audio_signal_mutex = AGS_AUDIO_SIGNAL_GET_OBJ_MUTEX(audio_signal);
1949 
1950   /* test */
1951   g_rec_mutex_lock(audio_signal_mutex);
1952 
1953   retval = (flags & (audio_signal->flags)) ? TRUE: FALSE;
1954 
1955   g_rec_mutex_unlock(audio_signal_mutex);
1956 
1957   return(retval);
1958 }
1959 
1960 /**
1961  * ags_audio_signal_set_flags:
1962  * @audio_signal: the #AgsAudioSignal
1963  * @flags: see #AgsAudioSignalFlags-enum
1964  *
1965  * Enable a feature of @audio_signal.
1966  *
1967  * Since: 3.0.0
1968  */
1969 void
ags_audio_signal_set_flags(AgsAudioSignal * audio_signal,guint flags)1970 ags_audio_signal_set_flags(AgsAudioSignal *audio_signal, guint flags)
1971 {
1972   GRecMutex *audio_signal_mutex;
1973 
1974   if(!AGS_IS_AUDIO_SIGNAL(audio_signal)){
1975     return;
1976   }
1977 
1978   /* get audio_signal mutex */
1979   audio_signal_mutex = AGS_AUDIO_SIGNAL_GET_OBJ_MUTEX(audio_signal);
1980 
1981   //TODO:JK: add more?
1982 
1983   /* set flags */
1984   g_rec_mutex_lock(audio_signal_mutex);
1985 
1986   audio_signal->flags |= flags;
1987 
1988   g_rec_mutex_unlock(audio_signal_mutex);
1989 }
1990 
1991 /**
1992  * ags_audio_signal_unset_flags:
1993  * @audio_signal: the #AgsAudioSignal
1994  * @flags: see #AgsAudioSignalFlags-enum
1995  *
1996  * Disable a feature of @audio_signal.
1997  *
1998  * Since: 3.0.0
1999  */
2000 void
ags_audio_signal_unset_flags(AgsAudioSignal * audio_signal,guint flags)2001 ags_audio_signal_unset_flags(AgsAudioSignal *audio_signal, guint flags)
2002 {
2003   GRecMutex *audio_signal_mutex;
2004 
2005   if(!AGS_IS_AUDIO_SIGNAL(audio_signal)){
2006     return;
2007   }
2008 
2009   /* get audio_signal mutex */
2010   audio_signal_mutex = AGS_AUDIO_SIGNAL_GET_OBJ_MUTEX(audio_signal);
2011 
2012   //TODO:JK: add more?
2013 
2014   /* unset flags */
2015   g_rec_mutex_lock(audio_signal_mutex);
2016 
2017   audio_signal->flags &= (~flags);
2018 
2019   g_rec_mutex_unlock(audio_signal_mutex);
2020 }
2021 
2022 /**
2023  * ags_stream_alloc:
2024  * @buffer_size: the buffer size
2025  * @format: the format
2026  *
2027  * Allocs an audio buffer.
2028  *
2029  * Returns: the audio data array
2030  *
2031  * Since: 3.0.0
2032  */
2033 void*
ags_stream_alloc(guint buffer_size,guint format)2034 ags_stream_alloc(guint buffer_size,
2035 		 guint format)
2036 {
2037   void *buffer;
2038 
2039   switch(format){
2040   case AGS_SOUNDCARD_SIGNED_8_BIT:
2041     {
2042       buffer = (gint8 *) g_malloc(buffer_size * sizeof(gint8));
2043       memset(buffer, 0, buffer_size * sizeof(gint8));
2044     }
2045     break;
2046   case AGS_SOUNDCARD_SIGNED_16_BIT:
2047     {
2048       buffer = (gint16 *) g_malloc(buffer_size * sizeof(gint16));
2049       memset(buffer, 0, buffer_size * sizeof(gint16));
2050     }
2051     break;
2052   case AGS_SOUNDCARD_SIGNED_24_BIT:
2053     {
2054       buffer = (gint32 *) g_malloc(buffer_size * sizeof(gint32));
2055       memset(buffer, 0, buffer_size * sizeof(gint32));
2056       //NOTE:JK: The 24-bit linear samples use 32-bit physical space
2057     }
2058     break;
2059   case AGS_SOUNDCARD_SIGNED_32_BIT:
2060     {
2061       buffer = (gint32 *) g_malloc(buffer_size * sizeof(gint32));
2062       memset(buffer, 0, buffer_size * sizeof(gint32));
2063     }
2064     break;
2065   case AGS_SOUNDCARD_SIGNED_64_BIT:
2066     {
2067       buffer = (gint64 *) g_malloc(buffer_size * sizeof(gint64));
2068       memset(buffer, 0, buffer_size * sizeof(gint64));
2069     }
2070     break;
2071   case AGS_SOUNDCARD_FLOAT:
2072     {
2073       buffer = (gfloat *) g_malloc(buffer_size * sizeof(gfloat));
2074       memset(buffer, 0, buffer_size * sizeof(gfloat));
2075     }
2076     break;
2077   case AGS_SOUNDCARD_DOUBLE:
2078     {
2079       buffer = (gdouble *) g_malloc(buffer_size * sizeof(gdouble));
2080       memset(buffer, 0, buffer_size * sizeof(gdouble));
2081     }
2082     break;
2083   case AGS_SOUNDCARD_COMPLEX:
2084     {
2085       guint i;
2086 
2087       buffer = (AgsComplex *) g_malloc(buffer_size * sizeof(AgsComplex));
2088 
2089       for(i = 0; i < buffer_size; i++){
2090 	((AgsComplex *) buffer)[i].real = 0.0;
2091 	((AgsComplex *) buffer)[i].imag = 0.0;
2092       }
2093     }
2094     break;
2095   default:
2096     g_warning("ags_stream_alloc(): unsupported word size");
2097     return(NULL);
2098   }
2099 
2100   return(buffer);
2101 }
2102 
2103 /**
2104  * ags_stream_free:
2105  * @buffer: the buffer
2106  *
2107  * Frees an audio buffer.
2108  *
2109  * Since: 3.0.0
2110  */
2111 void
ags_stream_free(void * buffer)2112 ags_stream_free(void *buffer)
2113 {
2114   if(buffer == NULL){
2115     return;
2116   }
2117 
2118   g_free(buffer);
2119 }
2120 
2121 /**
2122  * ags_stream_slice_alloc:
2123  * @buffer_size: the buffer size
2124  * @format: the format
2125  *
2126  * Allocs an audio buffer.
2127  *
2128  * Returns: the audio data array
2129  *
2130  * Since: 3.3.0
2131  */
2132 void*
ags_stream_slice_alloc(guint buffer_size,guint format)2133 ags_stream_slice_alloc(guint buffer_size,
2134 		       guint format)
2135 {
2136   void *buffer;
2137   guint word_size;
2138 
2139   switch(format){
2140   case AGS_SOUNDCARD_SIGNED_8_BIT:
2141     {
2142       buffer = (gint8 *) g_slice_alloc0(buffer_size * sizeof(gint8));
2143       word_size = sizeof(gint8);
2144     }
2145     break;
2146   case AGS_SOUNDCARD_SIGNED_16_BIT:
2147     {
2148       buffer = (gint16 *) g_slice_alloc0(buffer_size * sizeof(gint16));
2149       word_size = sizeof(gint16);
2150     }
2151     break;
2152   case AGS_SOUNDCARD_SIGNED_24_BIT:
2153     {
2154       buffer = (gint32 *) g_slice_alloc0(buffer_size * sizeof(gint32));
2155       //NOTE:JK: The 24-bit linear samples use 32-bit physical space
2156       word_size = sizeof(gint32);
2157     }
2158     break;
2159   case AGS_SOUNDCARD_SIGNED_32_BIT:
2160     {
2161       buffer = (gint32 *) g_slice_alloc0(buffer_size * sizeof(gint32));
2162       word_size = sizeof(gint32);
2163     }
2164     break;
2165   case AGS_SOUNDCARD_SIGNED_64_BIT:
2166     {
2167       buffer = (gint64 *) g_slice_alloc0(buffer_size * sizeof(gint64));
2168       word_size = sizeof(gint64);
2169     }
2170     break;
2171   case AGS_SOUNDCARD_FLOAT:
2172     {
2173       buffer = (gfloat *) g_slice_alloc0(buffer_size * sizeof(gfloat));
2174       word_size = sizeof(gfloat);
2175     }
2176     break;
2177   case AGS_SOUNDCARD_DOUBLE:
2178     {
2179       buffer = (gdouble *) g_slice_alloc0(buffer_size * sizeof(gdouble));
2180       word_size = sizeof(gdouble);
2181     }
2182     break;
2183   case AGS_SOUNDCARD_COMPLEX:
2184     {
2185       buffer = (AgsComplex *) g_slice_alloc0(buffer_size * sizeof(AgsComplex));
2186     }
2187     break;
2188   default:
2189     g_warning("ags_stream_slice_alloc(): unsupported word size");
2190     return(NULL);
2191   }
2192 
2193   return(buffer);
2194 }
2195 
2196 /**
2197  * ags_stream_slice_free:
2198  * @buffer_size: the buffer size
2199  * @format: the format
2200  * @buffer: the buffer
2201  *
2202  * Frees an audio buffer.
2203  *
2204  * Since: 3.3.0
2205  */
2206 void
ags_stream_slice_free(guint buffer_size,guint format,void * buffer)2207 ags_stream_slice_free(guint buffer_size,
2208 		      guint format,
2209 		      void *buffer)
2210 {
2211   guint word_size;
2212 
2213   if(buffer == NULL){
2214     return;
2215   }
2216 
2217   switch(format){
2218   case AGS_SOUNDCARD_SIGNED_8_BIT:
2219     {
2220       word_size = sizeof(gint8);
2221     }
2222     break;
2223   case AGS_SOUNDCARD_SIGNED_16_BIT:
2224     {
2225       word_size = sizeof(gint16);
2226     }
2227     break;
2228   case AGS_SOUNDCARD_SIGNED_24_BIT:
2229     {
2230       //NOTE:JK: The 24-bit linear samples use 32-bit physical space
2231       word_size = sizeof(gint32);
2232     }
2233     break;
2234   case AGS_SOUNDCARD_SIGNED_32_BIT:
2235     {
2236       word_size = sizeof(gint32);
2237     }
2238     break;
2239   case AGS_SOUNDCARD_SIGNED_64_BIT:
2240     {
2241       word_size = sizeof(gint64);
2242     }
2243     break;
2244   case AGS_SOUNDCARD_FLOAT:
2245     {
2246       word_size = sizeof(gfloat);
2247     }
2248     break;
2249   case AGS_SOUNDCARD_DOUBLE:
2250     {
2251       word_size = sizeof(gdouble);
2252     }
2253     break;
2254   case AGS_SOUNDCARD_COMPLEX:
2255     {
2256       word_size = 2 * sizeof(gdouble);
2257     }
2258     break;
2259   default:
2260     g_warning("ags_stream_slice_alloc(): unsupported word size");
2261     return;
2262   }
2263 
2264   g_slice_free1(buffer_size * word_size,
2265 		buffer);
2266 }
2267 
2268 /**
2269  * ags_audio_signal_get_recycling:
2270  * @audio_signal: the #AgsAudioSignal
2271  *
2272  * Get recycling.
2273  *
2274  * Returns: (transfer full): the #AgsRecycling
2275  *
2276  * Since: 3.1.0
2277  */
2278 GObject*
ags_audio_signal_get_recycling(AgsAudioSignal * audio_signal)2279 ags_audio_signal_get_recycling(AgsAudioSignal *audio_signal)
2280 {
2281   GObject *recycling;
2282 
2283   if(!AGS_IS_AUDIO_SIGNAL(audio_signal)){
2284     return(NULL);
2285   }
2286 
2287   g_object_get(audio_signal,
2288 	       "recycling", &recycling,
2289 	       NULL);
2290 
2291   return(recycling);
2292 }
2293 
2294 /**
2295  * ags_audio_signal_set_recycling:
2296  * @audio_signal: the #AgsAudioSignal
2297  * @recycling: the #AgsRecycling
2298  *
2299  * Set recycling.
2300  *
2301  * Since: 3.1.0
2302  */
2303 void
ags_audio_signal_set_recycling(AgsAudioSignal * audio_signal,GObject * recycling)2304 ags_audio_signal_set_recycling(AgsAudioSignal *audio_signal, GObject *recycling)
2305 {
2306   if(!AGS_IS_AUDIO_SIGNAL(audio_signal)){
2307     return;
2308   }
2309 
2310   g_object_set(audio_signal,
2311 	       "recycling", recycling,
2312 	       NULL);
2313 }
2314 
2315 /**
2316  * ags_audio_signal_get_output_soundcard:
2317  * @audio_signal: the #AgsAudioSignal
2318  *
2319  * Get the output soundcard object of @audio_signal.
2320  *
2321  * Returns: (transfer full): the output soundcard
2322  *
2323  * Since: 3.1.0
2324  */
2325 GObject*
ags_audio_signal_get_output_soundcard(AgsAudioSignal * audio_signal)2326 ags_audio_signal_get_output_soundcard(AgsAudioSignal *audio_signal)
2327 {
2328   GObject *output_soundcard;
2329 
2330   if(!AGS_IS_AUDIO_SIGNAL(audio_signal)){
2331     return(NULL);
2332   }
2333 
2334   g_object_get(audio_signal,
2335 	       "output-soundcard", &output_soundcard,
2336 	       NULL);
2337 
2338   return(output_soundcard);
2339 }
2340 
2341 void
ags_audio_signal_real_set_output_soundcard(AgsAudioSignal * audio_signal,GObject * output_soundcard)2342 ags_audio_signal_real_set_output_soundcard(AgsAudioSignal *audio_signal, GObject *output_soundcard)
2343 {
2344   guint samplerate;
2345   guint buffer_size;
2346   guint format;
2347 
2348   GRecMutex *audio_signal_mutex;
2349 
2350   if(!AGS_IS_AUDIO_SIGNAL(audio_signal) ||
2351      !AGS_IS_SOUNDCARD(output_soundcard)){
2352     return;
2353   }
2354 
2355   /* get audio signal mutex */
2356   audio_signal_mutex = AGS_AUDIO_SIGNAL_GET_OBJ_MUTEX(audio_signal);
2357 
2358   /* set output soundcard */
2359   g_rec_mutex_lock(audio_signal_mutex);
2360 
2361   if(audio_signal->output_soundcard == output_soundcard){
2362     g_rec_mutex_unlock(audio_signal_mutex);
2363 
2364     return;
2365   }
2366 
2367   if(audio_signal->output_soundcard != NULL){
2368     g_object_unref(audio_signal->output_soundcard);
2369   }
2370 
2371   if(output_soundcard != NULL){
2372     g_object_ref(output_soundcard);
2373   }
2374 
2375   audio_signal->output_soundcard = output_soundcard;
2376 
2377   g_rec_mutex_unlock(audio_signal_mutex);
2378 
2379   /* apply presets */
2380   if(output_soundcard != NULL){
2381     ags_soundcard_get_presets(AGS_SOUNDCARD(output_soundcard),
2382 			      NULL,
2383 			      &samplerate,
2384 			      &buffer_size,
2385 			      &format);
2386 
2387     g_object_set(audio_signal,
2388 		 "samplerate", samplerate,
2389 		 "buffer-size", buffer_size,
2390 		 "format", format,
2391 		 NULL);
2392   }
2393 }
2394 
2395 /**
2396  * ags_audio_signal_set_output_soundcard:
2397  * @audio_signal: the #AgsAudioSignal
2398  * @output_soundcard: the #GObject implementing #AgsSoundcard
2399  *
2400  * Set the output soundcard object of @audio_signal.
2401  *
2402  * Since: 3.0.0
2403  */
2404 void
ags_audio_signal_set_output_soundcard(AgsAudioSignal * audio_signal,GObject * output_soundcard)2405 ags_audio_signal_set_output_soundcard(AgsAudioSignal *audio_signal, GObject *output_soundcard)
2406 {
2407   if(!AGS_IS_AUDIO_SIGNAL(audio_signal)){
2408     return;
2409   }
2410 
2411   g_object_set(audio_signal,
2412 	       "output-soundcard", output_soundcard,
2413 	       NULL);
2414 }
2415 
2416 /**
2417  * ags_audio_signal_get_input_soundcard:
2418  * @audio_signal: the #AgsAudioSignal
2419  *
2420  * Get the input soundcard object of @audio_signal.
2421  *
2422  * Returns: (transfer full): the input soundcard
2423  *
2424  * Since: 3.1.0
2425  */
2426 GObject*
ags_audio_signal_get_input_soundcard(AgsAudioSignal * audio_signal)2427 ags_audio_signal_get_input_soundcard(AgsAudioSignal *audio_signal)
2428 {
2429   GObject *input_soundcard;
2430 
2431   if(!AGS_IS_AUDIO_SIGNAL(audio_signal)){
2432     return(NULL);
2433   }
2434 
2435   g_object_get(audio_signal,
2436 	       "input-soundcard", &input_soundcard,
2437 	       NULL);
2438 
2439   return(input_soundcard);
2440 }
2441 
2442 void
ags_audio_signal_real_set_input_soundcard(AgsAudioSignal * audio_signal,GObject * input_soundcard)2443 ags_audio_signal_real_set_input_soundcard(AgsAudioSignal *audio_signal, GObject *input_soundcard)
2444 {
2445   GRecMutex *audio_signal_mutex;
2446 
2447   if(!AGS_IS_AUDIO_SIGNAL(audio_signal) ||
2448      !AGS_IS_SOUNDCARD(input_soundcard)){
2449     return;
2450   }
2451 
2452   /* get audio signal mutex */
2453   audio_signal_mutex = AGS_AUDIO_SIGNAL_GET_OBJ_MUTEX(audio_signal);
2454 
2455   /* set input soundcard */
2456   g_rec_mutex_lock(audio_signal_mutex);
2457 
2458   if(audio_signal->input_soundcard == input_soundcard){
2459     g_rec_mutex_unlock(audio_signal_mutex);
2460 
2461     return;
2462   }
2463 
2464   if(audio_signal->input_soundcard != NULL){
2465     g_object_unref(audio_signal->input_soundcard);
2466   }
2467 
2468   if(input_soundcard != NULL){
2469     g_object_ref(input_soundcard);
2470   }
2471 
2472   audio_signal->input_soundcard = input_soundcard;
2473 
2474   g_rec_mutex_unlock(audio_signal_mutex);
2475 }
2476 
2477 /**
2478  * ags_audio_signal_set_input_soundcard:
2479  * @audio_signal: an #AgsAudioSignal
2480  * @input_soundcard: the #GObject implementing #AgsSoundcard
2481  *
2482  * Set the input soundcard object of @audio_signal.
2483  *
2484  * Since: 3.0.0
2485  */
2486 void
ags_audio_signal_set_input_soundcard(AgsAudioSignal * audio_signal,GObject * input_soundcard)2487 ags_audio_signal_set_input_soundcard(AgsAudioSignal *audio_signal, GObject *input_soundcard)
2488 {
2489   if(!AGS_IS_AUDIO_SIGNAL(audio_signal)){
2490     return;
2491   }
2492 
2493   g_object_set(audio_signal,
2494 	       "input-soundcard", input_soundcard,
2495 	       NULL);
2496 }
2497 
2498 /**
2499  * ags_audio_signal_get_samplerate:
2500  * @audio_signal: the #AgsAudioSignal
2501  *
2502  * Gets samplerate.
2503  *
2504  * Returns: the samplerate
2505  *
2506  * Since: 3.1.0
2507  */
2508 guint
ags_audio_signal_get_samplerate(AgsAudioSignal * audio_signal)2509 ags_audio_signal_get_samplerate(AgsAudioSignal *audio_signal)
2510 {
2511   guint samplerate;
2512 
2513   if(!AGS_IS_AUDIO_SIGNAL(audio_signal)){
2514     return(0);
2515   }
2516 
2517   g_object_get(audio_signal,
2518 	       "samplerate", &samplerate,
2519 	       NULL);
2520 
2521   return(samplerate);
2522 }
2523 
2524 /**
2525  * ags_audio_signal_set_samplerate:
2526  * @audio_signal: the #AgsAudioSignal
2527  * @samplerate: the samplerate
2528  *
2529  * Set samplerate.
2530  *
2531  * Since: 3.0.0
2532  */
2533 void
ags_audio_signal_set_samplerate(AgsAudioSignal * audio_signal,guint samplerate)2534 ags_audio_signal_set_samplerate(AgsAudioSignal *audio_signal, guint samplerate)
2535 {
2536   GList *stream;
2537 
2538   void *data, *resampled_data;
2539 
2540   guint stream_length;
2541   guint end_offset;
2542   guint buffer_size;
2543   guint old_samplerate;
2544   guint format;
2545   guint offset;
2546   guint copy_mode;
2547 
2548   GRecMutex *audio_signal_mutex;
2549   GRecMutex *stream_mutex;
2550 
2551   if(!AGS_IS_AUDIO_SIGNAL(audio_signal)){
2552     return;
2553   }
2554 
2555   /* get audio signal mutex */
2556   audio_signal_mutex = AGS_AUDIO_SIGNAL_GET_OBJ_MUTEX(audio_signal);
2557   stream_mutex = AGS_AUDIO_SIGNAL_GET_STREAM_MUTEX(audio_signal);
2558 
2559   /* check resample */
2560   g_rec_mutex_lock(audio_signal_mutex);
2561 
2562   old_samplerate = audio_signal->samplerate;
2563 
2564   g_rec_mutex_unlock(audio_signal_mutex);
2565 
2566   if(old_samplerate == samplerate){
2567     return;
2568   }
2569 
2570   /* set samplerate */
2571   g_rec_mutex_lock(audio_signal_mutex);
2572 
2573   buffer_size = audio_signal->buffer_size;
2574   format = audio_signal->format;
2575 
2576   audio_signal->samplerate = samplerate;
2577 
2578   audio_signal->loop_start = (guint) floor((double) samplerate * ((double) audio_signal->loop_start / (double) old_samplerate));
2579   audio_signal->loop_end = (guint) floor((double) samplerate * ((double) audio_signal->loop_end / (double) old_samplerate));
2580 
2581   g_rec_mutex_unlock(audio_signal_mutex);
2582 
2583   /* resample buffer */
2584   g_rec_mutex_lock(stream_mutex);
2585 
2586   data = NULL;
2587 
2588   stream_length = g_list_length(audio_signal->stream);
2589 
2590   copy_mode = ags_audio_buffer_util_get_copy_mode(ags_audio_buffer_util_format_from_soundcard(format),
2591 						  ags_audio_buffer_util_format_from_soundcard(format));
2592 
2593   switch(format){
2594   case AGS_SOUNDCARD_SIGNED_8_BIT:
2595     {
2596       data = (gint8 *) g_malloc(stream_length * buffer_size * sizeof(gint8));
2597       memset(data, 0, stream_length * buffer_size * sizeof(gint8));
2598     }
2599     break;
2600   case AGS_SOUNDCARD_SIGNED_16_BIT:
2601     {
2602       data = (gint16 *) g_malloc(stream_length * buffer_size * sizeof(gint16));
2603       memset(data, 0, stream_length * buffer_size * sizeof(gint16));
2604     }
2605     break;
2606   case AGS_SOUNDCARD_SIGNED_24_BIT:
2607     {
2608       data = (gint32 *) g_malloc(stream_length * buffer_size * sizeof(gint32));
2609       memset(data, 0, stream_length * buffer_size * sizeof(gint32));
2610     }
2611     break;
2612   case AGS_SOUNDCARD_SIGNED_32_BIT:
2613     {
2614       data = (gint32 *) g_malloc(stream_length * buffer_size * sizeof(gint32));
2615       memset(data, 0, stream_length * buffer_size * sizeof(gint32));
2616     }
2617     break;
2618   case AGS_SOUNDCARD_SIGNED_64_BIT:
2619     {
2620       data = (gint64 *) g_malloc(stream_length * buffer_size * sizeof(gint64));
2621       memset(data, 0, stream_length * buffer_size * sizeof(gint64));
2622     }
2623     break;
2624   case AGS_SOUNDCARD_FLOAT:
2625     {
2626       data = (gfloat *) g_malloc(stream_length * buffer_size * sizeof(gfloat));
2627       memset(data, 0, stream_length * buffer_size * sizeof(gfloat));
2628     }
2629     break;
2630   case AGS_SOUNDCARD_DOUBLE:
2631     {
2632       data = (gdouble *) g_malloc(stream_length * buffer_size * sizeof(gdouble));
2633       memset(data, 0, stream_length * buffer_size * sizeof(gdouble));
2634     }
2635     break;
2636   default:
2637     g_warning("ags_audio_signal_set_buffer_size() - unsupported format");
2638   }
2639 
2640   stream = audio_signal->stream;
2641 
2642   offset = 0;
2643 
2644   while(stream != NULL){
2645     ags_audio_buffer_util_copy_buffer_to_buffer(data, 1, offset,
2646 						stream->data, 1, 0,
2647 						buffer_size, copy_mode);
2648 
2649     /* iterate */
2650     stream = stream->next;
2651 
2652     offset += buffer_size;
2653   }
2654 
2655   g_rec_mutex_unlock(stream_mutex);
2656 
2657   resampled_data = ags_stream_alloc((guint) (samplerate * (stream_length * buffer_size / old_samplerate)),
2658 				    format);
2659   ags_audio_buffer_util_resample_with_buffer(data, 1,
2660 					     ags_audio_buffer_util_format_from_soundcard(format), old_samplerate,
2661 					     stream_length * buffer_size,
2662 					     samplerate,
2663 					     (guint) (samplerate * (stream_length * buffer_size / old_samplerate)),
2664 					     resampled_data);
2665 
2666   g_free(data);
2667 
2668   ags_audio_signal_stream_resize(audio_signal,
2669 				 (guint) ceil((samplerate * (stream_length * buffer_size / old_samplerate)) / buffer_size));
2670 
2671   g_rec_mutex_lock(stream_mutex);
2672 
2673   stream = audio_signal->stream;
2674 
2675   stream_length = g_list_length(audio_signal->stream);
2676   end_offset = stream_length * buffer_size;
2677 
2678   offset = 0;
2679 
2680   while(stream != NULL && offset < stream_length * buffer_size){
2681     ags_audio_buffer_util_clear_buffer(stream->data, 1,
2682 				       buffer_size, ags_audio_buffer_util_format_from_soundcard(format));
2683 
2684     if(offset + buffer_size < stream_length * buffer_size){
2685       ags_audio_buffer_util_copy_buffer_to_buffer(stream->data, 1, 0,
2686 						  resampled_data, 1, offset,
2687 						  buffer_size, copy_mode);
2688     }else{
2689       if(end_offset > offset){
2690 	ags_audio_buffer_util_copy_buffer_to_buffer(stream->data, 1, 0,
2691 						    resampled_data, 1, offset,
2692 						    end_offset - offset, copy_mode);
2693       }
2694     }
2695 
2696     /* iterate */
2697     stream = stream->next;
2698 
2699     offset += buffer_size;
2700   }
2701 
2702   g_rec_mutex_unlock(stream_mutex);
2703 
2704   ags_stream_free(resampled_data);
2705 }
2706 
2707 /**
2708  * ags_audio_signal_get_buffer_size:
2709  * @audio_signal: the #AgsAudioSignal
2710  *
2711  * Gets buffer size.
2712  *
2713  * Returns: the buffer size
2714  *
2715  * Since: 3.1.0
2716  */
2717 guint
ags_audio_signal_get_buffer_size(AgsAudioSignal * audio_signal)2718 ags_audio_signal_get_buffer_size(AgsAudioSignal *audio_signal)
2719 {
2720   guint buffer_size;
2721 
2722   if(!AGS_IS_AUDIO_SIGNAL(audio_signal)){
2723     return(0);
2724   }
2725 
2726   g_object_get(audio_signal,
2727 	       "buffer-size", &buffer_size,
2728 	       NULL);
2729 
2730   return(buffer_size);
2731 }
2732 
2733 /**
2734  * ags_audio_signal_set_buffer_size:
2735  * @audio_signal: the #AgsAudioSignal
2736  * @buffer_size: the buffer size
2737  *
2738  * Set buffer size.
2739  *
2740  * Since: 3.0.0
2741  */
2742 void
ags_audio_signal_set_buffer_size(AgsAudioSignal * audio_signal,guint buffer_size)2743 ags_audio_signal_set_buffer_size(AgsAudioSignal *audio_signal, guint buffer_size)
2744 {
2745   GList *stream;
2746 
2747   void *data;
2748 
2749   guint stream_length;
2750   guint end_offset;
2751   guint offset;
2752   guint format;
2753   guint old_buffer_size;
2754   guint word_size;
2755   guint copy_mode;
2756 
2757   GRecMutex *audio_signal_mutex;
2758   GRecMutex *stream_mutex;
2759 
2760   if(!AGS_IS_AUDIO_SIGNAL(audio_signal)){
2761     return;
2762   }
2763 
2764   /* get audio signal mutex */
2765   audio_signal_mutex = AGS_AUDIO_SIGNAL_GET_OBJ_MUTEX(audio_signal);
2766   stream_mutex = AGS_AUDIO_SIGNAL_GET_STREAM_MUTEX(audio_signal);
2767 
2768   /* check buffer size */
2769   g_rec_mutex_lock(audio_signal_mutex);
2770 
2771   old_buffer_size = audio_signal->buffer_size;
2772 
2773   g_rec_mutex_unlock(audio_signal_mutex);
2774 
2775   if(old_buffer_size == buffer_size){
2776     return;
2777   }
2778 
2779   /* get some fields and set buffer size */
2780   g_rec_mutex_lock(audio_signal_mutex);
2781 
2782   format = audio_signal->format;
2783 
2784   audio_signal->buffer_size = buffer_size;
2785 
2786   g_rec_mutex_unlock(audio_signal_mutex);
2787 
2788   /* resize buffer */
2789   g_rec_mutex_lock(stream_mutex);
2790 
2791   data = NULL;
2792 
2793   stream_length = g_list_length(audio_signal->stream);
2794   word_size = 1;
2795 
2796   copy_mode = ags_audio_buffer_util_get_copy_mode(ags_audio_buffer_util_format_from_soundcard(format),
2797 						  ags_audio_buffer_util_format_from_soundcard(format));
2798 
2799   switch(format){
2800   case AGS_SOUNDCARD_SIGNED_8_BIT:
2801     {
2802       data = (gint8 *) g_malloc(stream_length * old_buffer_size * sizeof(gint8));
2803       memset(data, 0, stream_length * old_buffer_size * sizeof(gint8));
2804 
2805       word_size = sizeof(gint8);
2806     }
2807     break;
2808   case AGS_SOUNDCARD_SIGNED_16_BIT:
2809     {
2810       data = (gint16 *) g_malloc(stream_length * old_buffer_size * sizeof(gint16));
2811       memset(data, 0, stream_length * old_buffer_size * sizeof(gint16));
2812 
2813       word_size = sizeof(gint16);
2814     }
2815     break;
2816   case AGS_SOUNDCARD_SIGNED_24_BIT:
2817     {
2818       data = (gint32 *) g_malloc(stream_length * old_buffer_size * sizeof(gint32));
2819       memset(data, 0, stream_length * old_buffer_size * sizeof(gint32));
2820 
2821       word_size = sizeof(gint32);
2822     }
2823     break;
2824   case AGS_SOUNDCARD_SIGNED_32_BIT:
2825     {
2826       data = (gint32 *) g_malloc(stream_length * old_buffer_size * sizeof(gint32));
2827       memset(data, 0, stream_length * old_buffer_size * sizeof(gint32));
2828 
2829       word_size = sizeof(gint32);
2830     }
2831     break;
2832   case AGS_SOUNDCARD_SIGNED_64_BIT:
2833     {
2834       data = (gint64 *) g_malloc(stream_length * old_buffer_size * sizeof(gint64));
2835       memset(data, 0, stream_length * old_buffer_size * sizeof(gint64));
2836 
2837       word_size = sizeof(gint64);
2838     }
2839     break;
2840   case AGS_SOUNDCARD_FLOAT:
2841     {
2842       data = (gfloat *) g_malloc(stream_length * old_buffer_size * sizeof(gfloat));
2843       memset(data, 0, stream_length * old_buffer_size * sizeof(gfloat));
2844 
2845       word_size = sizeof(gfloat);
2846     }
2847     break;
2848   case AGS_SOUNDCARD_DOUBLE:
2849     {
2850       data = (gdouble *) g_malloc(stream_length * old_buffer_size * sizeof(gdouble));
2851       memset(data, 0, stream_length * old_buffer_size * sizeof(gdouble));
2852 
2853       word_size = sizeof(gdouble);
2854     }
2855     break;
2856   default:
2857     g_warning("ags_audio_signal_set_buffer_size() - unsupported format");
2858   }
2859 
2860   stream = audio_signal->stream;
2861 
2862   offset = 0;
2863 
2864   while(stream != NULL){
2865     ags_audio_buffer_util_copy_buffer_to_buffer(data, 1, offset,
2866 						stream->data, 1, 0,
2867 						old_buffer_size, copy_mode);
2868 
2869     /* iterate */
2870     stream = stream->next;
2871 
2872     offset += old_buffer_size;
2873   }
2874 
2875   g_rec_mutex_unlock(stream_mutex);
2876 
2877   ags_audio_signal_stream_resize(audio_signal,
2878 				 (guint) ceil(((double) stream_length * (double) old_buffer_size) / buffer_size));
2879 
2880   g_rec_mutex_lock(stream_mutex);
2881 
2882   stream = audio_signal->stream;
2883 
2884   stream_length = g_list_length(audio_signal->stream);
2885   end_offset = stream_length * old_buffer_size;
2886 
2887   offset = 0;
2888 
2889   while(stream != NULL && offset < stream_length * buffer_size){
2890     if(ags_audio_signal_test_flags(audio_signal, AGS_AUDIO_SIGNAL_SLICE_ALLOC)){
2891       ags_stream_slice_free(old_buffer_size,
2892 			    format,
2893 			    stream->data);
2894 
2895       stream->data = ags_stream_slice_alloc(buffer_size,
2896 					    format);
2897     }else{
2898       ags_stream_free(stream->data);
2899 
2900       stream->data = ags_stream_alloc(buffer_size,
2901 				      format);
2902     }
2903 
2904     switch(format){
2905     case AGS_SOUNDCARD_SIGNED_8_BIT:
2906       {
2907 	memset(stream->data, 0, buffer_size * sizeof(gint8));
2908       }
2909       break;
2910     case AGS_SOUNDCARD_SIGNED_16_BIT:
2911       {
2912 	memset(stream->data, 0, buffer_size * sizeof(gint16));
2913       }
2914       break;
2915     case AGS_SOUNDCARD_SIGNED_24_BIT:
2916       {
2917 	memset(stream->data, 0, buffer_size * sizeof(gint32));
2918       }
2919       break;
2920     case AGS_SOUNDCARD_SIGNED_32_BIT:
2921       {
2922 	memset(stream->data, 0, buffer_size * sizeof(gint32));
2923       }
2924       break;
2925     case AGS_SOUNDCARD_SIGNED_64_BIT:
2926       {
2927 	memset(stream->data, 0, buffer_size * sizeof(gint64));
2928       }
2929       break;
2930     case AGS_SOUNDCARD_FLOAT:
2931       {
2932 	memset(stream->data, 0, buffer_size * sizeof(gfloat));
2933       }
2934       break;
2935     case AGS_SOUNDCARD_DOUBLE:
2936       {
2937 	memset(stream->data, 0, buffer_size * sizeof(gdouble));
2938       }
2939       break;
2940     default:
2941       g_warning("ags_audio_signal_set_buffer_size() - unsupported format");
2942     }
2943 
2944     ags_audio_buffer_util_clear_buffer(stream->data, 1,
2945 				       buffer_size, ags_audio_buffer_util_format_from_soundcard(format));
2946 
2947     if(offset + buffer_size < end_offset){
2948       ags_audio_buffer_util_copy_buffer_to_buffer(stream->data, 1, 0,
2949 						  data, 1, offset,
2950 						  buffer_size, copy_mode);
2951     }else{
2952       if(end_offset > offset){
2953 	ags_audio_buffer_util_copy_buffer_to_buffer(stream->data, 1, 0,
2954 						    data, 1, offset,
2955 						    end_offset - offset, copy_mode);
2956       }
2957     }
2958 
2959     /* iterate */
2960     stream = stream->next;
2961 
2962     offset += buffer_size;
2963   }
2964 
2965   g_rec_mutex_unlock(stream_mutex);
2966 
2967   g_free(data);
2968 }
2969 
2970 /**
2971  * ags_audio_signal_get_format:
2972  * @audio_signal: the #AgsAudioSignal
2973  *
2974  * Gets format.
2975  *
2976  * Returns: the format
2977  *
2978  * Since: 3.1.0
2979  */
2980 guint
ags_audio_signal_get_format(AgsAudioSignal * audio_signal)2981 ags_audio_signal_get_format(AgsAudioSignal *audio_signal)
2982 {
2983   guint format;
2984 
2985   if(!AGS_IS_AUDIO_SIGNAL(audio_signal)){
2986     return(0);
2987   }
2988 
2989   g_object_get(audio_signal,
2990 	       "format", &format,
2991 	       NULL);
2992 
2993   return(format);
2994 }
2995 
2996 /**
2997  * ags_audio_signal_set_format:
2998  * @audio_signal: the #AgsAudioSignal
2999  * @format: the format
3000  *
3001  * Set format.
3002  *
3003  * Since: 3.0.0
3004  */
3005 void
ags_audio_signal_set_format(AgsAudioSignal * audio_signal,guint format)3006 ags_audio_signal_set_format(AgsAudioSignal *audio_signal, guint format)
3007 {
3008   GList *stream;
3009 
3010   void *data;
3011 
3012   guint buffer_size;
3013   guint old_format;
3014   guint copy_mode;
3015 
3016   GRecMutex *audio_signal_mutex;
3017   GRecMutex *stream_mutex;
3018 
3019   if(!AGS_IS_AUDIO_SIGNAL(audio_signal)){
3020     return;
3021   }
3022 
3023   /* get audio signal mutex */
3024   audio_signal_mutex = AGS_AUDIO_SIGNAL_GET_OBJ_MUTEX(audio_signal);
3025   stream_mutex = AGS_AUDIO_SIGNAL_GET_STREAM_MUTEX(audio_signal);
3026 
3027   /* get some fields and set format */
3028   g_rec_mutex_lock(audio_signal_mutex);
3029 
3030   buffer_size = audio_signal->buffer_size;
3031   old_format = audio_signal->format;
3032 
3033   audio_signal->format = format;
3034 
3035   /* set word size */
3036   switch(format){
3037   case AGS_SOUNDCARD_SIGNED_8_BIT:
3038     {
3039       audio_signal->word_size = sizeof(gint8);
3040     }
3041     break;
3042   case AGS_SOUNDCARD_SIGNED_16_BIT:
3043     {
3044       audio_signal->word_size = sizeof(gint16);
3045     }
3046     break;
3047   case AGS_SOUNDCARD_SIGNED_24_BIT:
3048     {
3049       audio_signal->word_size = sizeof(gint32);
3050     }
3051     break;
3052   case AGS_SOUNDCARD_SIGNED_32_BIT:
3053     {
3054       audio_signal->word_size = sizeof(gint32);
3055     }
3056     break;
3057   case AGS_SOUNDCARD_SIGNED_64_BIT:
3058     {
3059       audio_signal->word_size = sizeof(gint64);
3060     }
3061     break;
3062   case AGS_SOUNDCARD_FLOAT:
3063     {
3064       audio_signal->word_size = sizeof(gfloat);
3065     }
3066     break;
3067   case AGS_SOUNDCARD_DOUBLE:
3068     {
3069       audio_signal->word_size = sizeof(gdouble);
3070     }
3071     break;
3072   }
3073 
3074   g_rec_mutex_unlock(audio_signal_mutex);
3075 
3076   if(old_format == 0){
3077     return;
3078   }
3079 
3080   /* resize buffer */
3081   g_rec_mutex_lock(stream_mutex);
3082 
3083   stream = audio_signal->stream;
3084 
3085   copy_mode = ags_audio_buffer_util_get_copy_mode(ags_audio_buffer_util_format_from_soundcard(format),
3086 						  ags_audio_buffer_util_format_from_soundcard(old_format));
3087 
3088   while(stream != NULL){
3089     if(ags_audio_signal_test_flags(audio_signal, AGS_AUDIO_SIGNAL_SLICE_ALLOC)){
3090       data = ags_stream_slice_alloc(buffer_size,
3091 				    format);
3092     }else{
3093       data = ags_stream_alloc(buffer_size,
3094 			      format);
3095     }
3096 
3097     ags_audio_buffer_util_copy_buffer_to_buffer(data, 1, 0,
3098 						stream->data, 1, 0,
3099 						buffer_size, copy_mode);
3100 
3101     if(ags_audio_signal_test_flags(audio_signal, AGS_AUDIO_SIGNAL_SLICE_ALLOC)){
3102       ags_stream_slice_free(buffer_size,
3103 			    old_format,
3104 			    stream->data);
3105     }else{
3106       ags_stream_free(stream->data);
3107     }
3108 
3109     stream->data = data;
3110 
3111     /* iterate */
3112     stream = stream->next;
3113   }
3114 
3115   g_rec_mutex_unlock(stream_mutex);
3116 }
3117 
3118 /**
3119  * ags_audio_signal_get_length_till_current:
3120  * @audio_signal: the #AgsAudioSignal
3121  *
3122  * Counts the buffers from :stream upto :stream-current.
3123  *
3124  * Returns: the counted length.
3125  *
3126  * Since: 3.0.0
3127  */
3128 guint
ags_audio_signal_get_length_till_current(AgsAudioSignal * audio_signal)3129 ags_audio_signal_get_length_till_current(AgsAudioSignal *audio_signal)
3130 {
3131   GList *list, *stop;
3132 
3133   guint length;
3134 
3135   GRecMutex *stream_mutex;
3136 
3137   if(!AGS_IS_AUDIO_SIGNAL(audio_signal)){
3138     return(0);
3139   }
3140 
3141   /* get stream mutex */
3142   stream_mutex = AGS_AUDIO_SIGNAL_GET_STREAM_MUTEX(audio_signal);
3143 
3144   /* count entries */
3145   g_rec_mutex_lock(stream_mutex);
3146 
3147   list = audio_signal->stream;
3148   length = 0;
3149 
3150   if(audio_signal->stream_current != NULL){
3151     stop = audio_signal->stream_current->next;
3152 
3153     while(list != stop){
3154       length++;
3155       list = list->next;
3156     }
3157   }
3158 
3159   g_rec_mutex_unlock(stream_mutex);
3160 
3161   return(length);
3162 }
3163 
3164 /**
3165  * ags_audio_signal_contains_note:
3166  * @audio_signal: the #AgsAudioSignal
3167  * @note: the #AgsNote
3168  *
3169  * Check if @audio_signal contains @note.
3170  *
3171  * Returns: %TRUE on success, otherwise %FALSE
3172  *
3173  * Since: 3.3.0
3174  */
3175 gboolean
ags_audio_signal_contains_note(AgsAudioSignal * audio_signal,AgsNote * note)3176 ags_audio_signal_contains_note(AgsAudioSignal *audio_signal,
3177 			       AgsNote *note)
3178 {
3179   gboolean success;
3180 
3181   GRecMutex *audio_signal_mutex;
3182 
3183   if(!AGS_IS_AUDIO_SIGNAL(audio_signal)){
3184     return(FALSE);
3185   }
3186 
3187   /* get audio signal mutex */
3188   audio_signal_mutex = AGS_AUDIO_SIGNAL_GET_OBJ_MUTEX(audio_signal);
3189 
3190   success = FALSE;
3191 
3192   /* check note */
3193   g_rec_mutex_lock(audio_signal_mutex);
3194 
3195   success = (g_list_find(audio_signal->note, note) != NULL) ? TRUE: FALSE;
3196 
3197   g_rec_mutex_unlock(audio_signal_mutex);
3198 
3199   return(success);
3200 }
3201 
3202 /**
3203  * ags_audio_signal_add_stream:
3204  * @audio_signal: the #AgsAudioSignal
3205  *
3206  * Adds a buffer at the end of the stream.
3207  *
3208  * Since: 3.0.0
3209  */
3210 void
ags_audio_signal_add_stream(AgsAudioSignal * audio_signal)3211 ags_audio_signal_add_stream(AgsAudioSignal *audio_signal)
3212 {
3213   GList *stream, *end_old;
3214 
3215   void *buffer;
3216 
3217   gboolean use_slice;
3218   guint buffer_size;
3219   guint format;
3220 
3221   GRecMutex *audio_signal_mutex;
3222   GRecMutex *stream_mutex;
3223 
3224   if(!AGS_IS_AUDIO_SIGNAL(audio_signal)){
3225     return;
3226   }
3227 
3228   /* get audio signal mutex */
3229   audio_signal_mutex = AGS_AUDIO_SIGNAL_GET_OBJ_MUTEX(audio_signal);
3230   stream_mutex = AGS_AUDIO_SIGNAL_GET_STREAM_MUTEX(audio_signal);
3231 
3232   /* get some fields and increment length */
3233   g_rec_mutex_lock(audio_signal_mutex);
3234 
3235   buffer_size = audio_signal->buffer_size;
3236   format = audio_signal->format;
3237 
3238   audio_signal->length += 1;
3239 
3240   use_slice = ((AGS_AUDIO_SIGNAL_SLICE_ALLOC & (audio_signal->flags)) != 0) ? TRUE: FALSE;
3241 
3242   g_rec_mutex_unlock(audio_signal_mutex);
3243 
3244   /* allocate stream and buffer */
3245   g_rec_mutex_lock(stream_mutex);
3246 
3247   stream = g_list_alloc();
3248 
3249   if(!use_slice){
3250     buffer = ags_stream_alloc(buffer_size,
3251 			      format);
3252   }else{
3253     buffer = ags_stream_slice_alloc(buffer_size,
3254 				    format);
3255   }
3256 
3257   stream->data = buffer;
3258 
3259   if(audio_signal->stream_end != NULL){
3260     end_old = audio_signal->stream_end;
3261 
3262     stream->prev = end_old;
3263     end_old->next = stream;
3264   }else{
3265     audio_signal->stream = stream;
3266     audio_signal->stream_current = stream;
3267   }
3268 
3269   audio_signal->stream_end = stream;
3270 
3271   g_rec_mutex_unlock(stream_mutex);
3272 }
3273 
3274 /**
3275  * ags_audio_signal_stream_resize:
3276  * @audio_signal: the #AgsAudioSignal
3277  * @length: the new length
3278  *
3279  * Resize stream of @audio_signal to @length number of buffers.
3280  *
3281  * Since: 3.0.0
3282  */
3283 void
ags_audio_signal_stream_resize(AgsAudioSignal * audio_signal,guint length)3284 ags_audio_signal_stream_resize(AgsAudioSignal *audio_signal, guint length)
3285 {
3286   gboolean use_slice;
3287   guint buffer_size;
3288   guint format;
3289   guint old_length;
3290   guint i;
3291 
3292   GRecMutex *audio_signal_mutex;
3293   GRecMutex *stream_mutex;
3294 
3295   if(!AGS_IS_AUDIO_SIGNAL(audio_signal)){
3296     return;
3297   }
3298 
3299   /* get audio signal mutex */
3300   audio_signal_mutex = AGS_AUDIO_SIGNAL_GET_OBJ_MUTEX(audio_signal);
3301   stream_mutex = AGS_AUDIO_SIGNAL_GET_STREAM_MUTEX(audio_signal);
3302 
3303   /* get some fields and set length */
3304   g_rec_mutex_lock(audio_signal_mutex);
3305 
3306   buffer_size = audio_signal->buffer_size;
3307   format = audio_signal->format;
3308 
3309   old_length = audio_signal->length;
3310 
3311   audio_signal->length = length;
3312 
3313   use_slice = ((AGS_AUDIO_SIGNAL_SLICE_ALLOC & (audio_signal->flags)) != 0) ? TRUE: FALSE;
3314 
3315   g_rec_mutex_unlock(audio_signal_mutex);
3316 
3317   /* resize stream */
3318   if(old_length < length){
3319     GList *stream, *end_old;
3320 
3321     void *buffer;
3322 
3323     stream = NULL;
3324 
3325     for(i = old_length; i < length; i++){
3326       if(!use_slice){
3327 	buffer = ags_stream_alloc(buffer_size,
3328 				  format);
3329       }else{
3330 	buffer = ags_stream_slice_alloc(buffer_size,
3331 					format);
3332       }
3333 
3334       stream = g_list_prepend(stream,
3335 			      buffer);
3336     }
3337 
3338     stream = g_list_reverse(stream);
3339 
3340     /* concat */
3341     g_rec_mutex_lock(stream_mutex);
3342 
3343     if(audio_signal->stream_end != NULL){
3344       end_old = audio_signal->stream_end;
3345       audio_signal->stream_end = g_list_last(stream);
3346 
3347       stream->prev = end_old;
3348       end_old->next = stream;
3349     }else{
3350       audio_signal->stream = stream;
3351       audio_signal->stream_end = g_list_last(stream);
3352       audio_signal->stream_current = stream;
3353     }
3354 
3355     g_rec_mutex_unlock(stream_mutex);
3356   }else if(old_length > length){
3357     GList *stream, *stream_end, *stream_next;
3358 
3359     gboolean check_current;
3360 
3361     g_rec_mutex_lock(stream_mutex);
3362 
3363     stream = audio_signal->stream;
3364     check_current = TRUE;
3365 
3366     for(i = 0; i < length; i++){
3367       if(check_current && stream == audio_signal->stream_current){
3368 	audio_signal->stream_current = NULL;
3369 	check_current = FALSE;
3370       }
3371 
3372       stream = stream->next;
3373     }
3374 
3375     if(length != 0){
3376       stream_end = stream->prev;
3377       stream_end->next = NULL;
3378       audio_signal->stream_end = stream_end;
3379     }else{
3380       audio_signal->stream = NULL;
3381       audio_signal->stream_current = NULL;
3382       audio_signal->stream_end = NULL;
3383     }
3384 
3385     g_rec_mutex_unlock(stream_mutex);
3386 
3387     stream->prev = NULL;
3388     g_list_free_full(stream,
3389 		     ags_stream_free);
3390   }
3391 }
3392 
3393 /**
3394  * ags_audio_signal_stream_safe_resize:
3395  * @audio_signal: the #AgsAudioSignal
3396  * @length: the new length
3397  *
3398  * Resize stream of @audio_signal to @length number of buffers. But doesn't shrink
3399  * more than the current stream position.
3400  *
3401  * Since: 3.0.0
3402  */
3403 void
ags_audio_signal_stream_safe_resize(AgsAudioSignal * audio_signal,guint length)3404 ags_audio_signal_stream_safe_resize(AgsAudioSignal *audio_signal, guint length)
3405 {
3406   guint length_till_current;
3407 
3408   if(!AGS_IS_AUDIO_SIGNAL(audio_signal)){
3409     return;
3410   }
3411 
3412   length_till_current = ags_audio_signal_get_length_till_current(audio_signal);
3413 
3414   if(length_till_current < length){
3415     ags_audio_signal_stream_resize(audio_signal,
3416 				   length);
3417   }else{
3418     ags_audio_signal_stream_resize(audio_signal,
3419 				   length_till_current);
3420   }
3421 }
3422 
3423 /**
3424  * ags_audio_signal_clear:
3425  * @audio_signal: the #AgsAudioSignal
3426  *
3427  * Clear @audio_signal.
3428  *
3429  * Since: 3.4.1
3430  */
3431 void
ags_audio_signal_clear(AgsAudioSignal * audio_signal)3432 ags_audio_signal_clear(AgsAudioSignal *audio_signal)
3433 {
3434   GList *stream;
3435 
3436   guint buffer_size;
3437   guint format;
3438 
3439   GRecMutex *audio_signal_stream_mutex;
3440 
3441   if(!AGS_IS_AUDIO_SIGNAL(audio_signal)){
3442     return;
3443   }
3444 
3445   /* get audio signal mutex */
3446   audio_signal_stream_mutex = AGS_AUDIO_SIGNAL_GET_STREAM_MUTEX(audio_signal);
3447 
3448   g_object_get(audio_signal,
3449 	       "buffer-size", &buffer_size,
3450 	       "format", &format,
3451 	       NULL);
3452 
3453   g_rec_mutex_lock(audio_signal_stream_mutex);
3454 
3455   stream = audio_signal->stream;
3456 
3457   while(stream != NULL){
3458     ags_audio_buffer_util_clear_buffer(stream->data, 1,
3459 				       buffer_size, ags_audio_buffer_util_format_from_soundcard(format));
3460 
3461     /* iterate */
3462     stream = stream->next;
3463   }
3464 
3465   g_rec_mutex_unlock(audio_signal_stream_mutex);
3466 }
3467 
3468 /**
3469  * ags_audio_signal_duplicate_stream:
3470  * @audio_signal: the #AgsAudioSignal
3471  * @template: the template #AgsAudioSignal
3472  *
3473  * Apply @template audio data to @audio_signal. Note should only be invoked
3474  * by proper recall context because only the stream of @template is locked.
3475  *
3476  * Since: 3.0.0
3477  */
3478 void
ags_audio_signal_duplicate_stream(AgsAudioSignal * audio_signal,AgsAudioSignal * template)3479 ags_audio_signal_duplicate_stream(AgsAudioSignal *audio_signal,
3480 				  AgsAudioSignal *template)
3481 {
3482   GList *template_stream, *stream;
3483 
3484   guint samplerate;
3485   guint buffer_size;
3486   guint template_format, format;
3487   guint length;
3488   guint copy_mode;
3489 
3490   GRecMutex *template_mutex;
3491   GRecMutex *audio_signal_mutex;
3492   GRecMutex *template_stream_mutex;
3493 
3494   if(!AGS_IS_AUDIO_SIGNAL(template)){
3495     if(!AGS_IS_AUDIO_SIGNAL(audio_signal)){
3496       return;
3497     }else{
3498       ags_audio_signal_stream_resize(audio_signal,
3499 				     0);
3500       return;
3501     }
3502   }
3503 
3504   /* get audio signal mutex */
3505   template_mutex = AGS_AUDIO_SIGNAL_GET_OBJ_MUTEX(template);
3506   audio_signal_mutex = AGS_AUDIO_SIGNAL_GET_OBJ_MUTEX(audio_signal);
3507 
3508   template_stream_mutex = AGS_AUDIO_SIGNAL_GET_STREAM_MUTEX(template);
3509 
3510   /* check stream presence */
3511   g_rec_mutex_lock(template_stream_mutex);
3512 
3513   if(template->stream == NULL){
3514     g_rec_mutex_unlock(template_stream_mutex);
3515 
3516     ags_audio_signal_stream_resize(audio_signal,
3517 				   0);
3518 
3519     return;
3520   }
3521 
3522   g_rec_mutex_unlock(template_stream_mutex);
3523 
3524   /* get some fields */
3525   g_rec_mutex_lock(template_mutex);
3526 
3527   samplerate = template->samplerate;
3528   buffer_size = template->buffer_size;
3529   template_format = template->format;
3530 
3531   length = template->length;
3532 
3533   g_rec_mutex_unlock(template_mutex);
3534 
3535   /* get some fields */
3536   g_rec_mutex_lock(audio_signal_mutex);
3537 
3538   format = audio_signal->format;
3539 
3540   g_rec_mutex_unlock(audio_signal_mutex);
3541 
3542   /*  */
3543   g_object_set(audio_signal,
3544 	       "samplerate", samplerate,
3545 	       "buffer-size", buffer_size,
3546 	       NULL);
3547   ags_audio_signal_stream_resize(audio_signal,
3548 				 g_list_length(template->stream));
3549 
3550   copy_mode = ags_audio_buffer_util_get_copy_mode(ags_audio_buffer_util_format_from_soundcard(format),
3551 						  ags_audio_buffer_util_format_from_soundcard(template_format));
3552 
3553 
3554   //NOTE:JK: lock only template
3555   g_rec_mutex_lock(template_stream_mutex);
3556 
3557   template_stream = template->stream;
3558   stream = audio_signal->stream;
3559 
3560   while(template_stream != NULL){
3561     ags_audio_buffer_util_copy_buffer_to_buffer(stream->data, 1, 0,
3562 						template_stream->data, 1, 0,
3563 						buffer_size, copy_mode);
3564 
3565     /* iterate */
3566     stream = stream->next;
3567     template_stream = template_stream->next;
3568   }
3569 
3570   g_rec_mutex_unlock(template_stream_mutex);
3571 }
3572 
3573 /**
3574  * ags_audio_signal_feed:
3575  * @audio_signal: the #AgsAudioSignal
3576  * @template: the template #AgsAudioSignal
3577  * @frame_count: the new frame count
3578  *
3579  * Feed audio signal to grow upto frame count.
3580  *
3581  * Since: 3.0.0
3582  */
3583 void
ags_audio_signal_feed(AgsAudioSignal * audio_signal,AgsAudioSignal * template,guint frame_count)3584 ags_audio_signal_feed(AgsAudioSignal *audio_signal,
3585 		      AgsAudioSignal *template,
3586 		      guint frame_count)
3587 {
3588   ags_audio_signal_feed_extended(audio_signal,
3589 				 template,
3590 				 frame_count, 0,
3591 				 TRUE, TRUE);
3592 }
3593 
3594 /**
3595  * ags_audio_signal_feed_extended:
3596  * @audio_signal: the #AgsAudioSignal
3597  * @template: the template #AgsAudioSignal
3598  * @frame_count: the new frame count
3599  * @old_frame_count: the old frame count
3600  * @do_open: open feed
3601  * @do_close: close feed
3602  *
3603  * Feed audio signal to grow upto frame count.
3604  *
3605  * Since: 3.3.0
3606  */
3607 void
ags_audio_signal_feed_extended(AgsAudioSignal * audio_signal,AgsAudioSignal * template,guint frame_count,guint old_frame_count,gboolean do_open,gboolean do_close)3608 ags_audio_signal_feed_extended(AgsAudioSignal *audio_signal,
3609 			       AgsAudioSignal *template,
3610 			       guint frame_count, guint old_frame_count,
3611 			       gboolean do_open, gboolean do_close)
3612 {
3613   GList *stream, *template_stream;
3614 
3615   gdouble delay;
3616   guint attack;
3617   guint old_length;
3618   guint old_last_frame;
3619   guint last_frame;
3620   guint loop_start, loop_end;
3621   guint template_length;
3622   guint template_last_frame;
3623   guint template_loop_start, template_loop_end;
3624   guint template_loop_length;
3625   guint template_loop_frame_count;
3626   guint template_samplerate, samplerate;
3627   guint template_buffer_size, buffer_size;
3628   guint template_format, format;
3629   guint copy_mode;
3630   guint n_frames;
3631   guint copy_n_frames;
3632   guint i, j;
3633   gboolean initial_reset;
3634 
3635   GRecMutex *audio_signal_mutex;
3636   GRecMutex *audio_signal_stream_mutex;
3637   GRecMutex *template_mutex;
3638   GRecMutex *template_stream_mutex;
3639 
3640   if(!AGS_IS_AUDIO_SIGNAL(audio_signal) ||
3641      !AGS_IS_AUDIO_SIGNAL(template)){
3642     return;
3643   }
3644 
3645   /* get audio signal mutex */
3646   audio_signal_mutex = AGS_AUDIO_SIGNAL_GET_OBJ_MUTEX(audio_signal);
3647   audio_signal_stream_mutex = AGS_AUDIO_SIGNAL_GET_STREAM_MUTEX(audio_signal);
3648 
3649   template_mutex = AGS_AUDIO_SIGNAL_GET_OBJ_MUTEX(template);
3650   template_stream_mutex = AGS_AUDIO_SIGNAL_GET_STREAM_MUTEX(template);
3651 
3652   /* audio signal - get some fields */
3653   g_rec_mutex_lock(audio_signal_mutex);
3654 
3655   buffer_size = audio_signal->buffer_size;
3656   format = audio_signal->format;
3657 
3658   samplerate = audio_signal->samplerate;
3659   delay = 0.0; // audio_signal->delay;
3660   attack = 0; // audio_signal->attack; is for parent
3661 
3662   old_length = audio_signal->length;
3663   old_last_frame = audio_signal->last_frame;
3664 
3665   g_rec_mutex_unlock(audio_signal_mutex);
3666 
3667   /* template - get some fields */
3668   g_rec_mutex_lock(template_mutex);
3669 
3670   template_samplerate = template->samplerate;
3671   template_buffer_size = template->buffer_size;
3672   template_format = template->format;
3673 
3674   template_last_frame = template->last_frame;
3675   template_loop_start = template->loop_start;
3676   template_loop_end = template->loop_end;
3677 
3678   template_length = template->length;
3679 
3680   g_rec_mutex_unlock(template_mutex);
3681 
3682   /* resize */
3683   template_loop_length = 0;
3684   template_loop_frame_count = 0;
3685 
3686   if(template_loop_end > template_loop_start){
3687     template_loop_length = template_loop_end - template_loop_start;
3688 
3689     if((frame_count - template_loop_start) > (template_last_frame - template_loop_end) &&
3690        template_last_frame >= template_loop_end){
3691       template_loop_frame_count = (frame_count - template_loop_start) - (template_last_frame - template_loop_end);
3692     }else{
3693       template_loop_frame_count = template_loop_length;
3694     }
3695 
3696     if(old_length < (guint) floor((attack + frame_count) / buffer_size) + 1){
3697       ags_audio_signal_stream_safe_resize(audio_signal,
3698 					  (guint) floor((attack + frame_count) / buffer_size) + 1);
3699     }
3700   }else{
3701     if(old_length < (guint) floor((attack + frame_count) / buffer_size) + 1){
3702       ags_audio_signal_stream_safe_resize(audio_signal,
3703 					  (guint) floor((attack + frame_count) / buffer_size) + 1);
3704     }
3705   }
3706 
3707   if(template_buffer_size != buffer_size ||
3708      template_samplerate != samplerate){
3709     g_warning("can't resample");
3710 
3711     return;
3712   }
3713 
3714   /* apply delay and attack */
3715   loop_start = ((guint) (delay * (gdouble) buffer_size) + attack + template_loop_start);
3716   loop_end = ((guint) (delay * (gdouble) buffer_size) + attack + template_loop_end);
3717 
3718   last_frame = ((guint) (delay * buffer_size) + attack + frame_count) % buffer_size;
3719 
3720   g_object_set(audio_signal,
3721 	       "last-frame", last_frame,
3722 	       NULL);
3723 
3724   if(template_length == 0){
3725 //    g_warning("empty template");
3726 
3727     return;
3728   }
3729 
3730   /* copy mode */
3731   copy_mode = ags_audio_buffer_util_get_copy_mode(ags_audio_buffer_util_format_from_soundcard(format),
3732  						  ags_audio_buffer_util_format_from_soundcard(template_format));
3733 
3734   /* generic copying */
3735   g_rec_mutex_lock(template_stream_mutex);
3736   g_rec_mutex_lock(audio_signal_stream_mutex);
3737 
3738   stream = g_list_nth(audio_signal->stream,
3739 		      (guint) ((delay * buffer_size) + attack) / buffer_size);
3740   template_stream = template->stream;
3741 
3742   initial_reset = TRUE;
3743 
3744   for(i = 0, j = attack; i < frame_count && stream != NULL && template_stream != NULL;){
3745     /* compute count of frames to copy */
3746     copy_n_frames = buffer_size;
3747 
3748     if(loop_start < loop_end &&
3749        i + copy_n_frames < loop_start + template_loop_frame_count){
3750       if(j + copy_n_frames > loop_end){
3751 	copy_n_frames = loop_end - j;
3752       }
3753     }
3754 
3755     if((i % buffer_size) + copy_n_frames > buffer_size){
3756       copy_n_frames = buffer_size - (i % buffer_size);
3757     }
3758 
3759     if((j % buffer_size) + copy_n_frames > buffer_size){
3760       copy_n_frames = buffer_size - (j % buffer_size);
3761     }
3762 
3763     if(i + copy_n_frames > frame_count){
3764       copy_n_frames = frame_count - i;
3765     }
3766 
3767     //NOTE:JK: caused some data not present
3768 #if 0
3769     if(initial_reset &&
3770        i + copy_n_frames >= old_frame_count){
3771       copy_n_frames = old_frame_count - i;
3772 
3773       initial_reset = FALSE;
3774     }
3775 #endif
3776 
3777     /* copy */
3778     if(i + copy_n_frames >= old_frame_count){
3779       ags_audio_buffer_util_copy_buffer_to_buffer(stream->data, 1, i % buffer_size,
3780 						  template_stream->data, 1, j % buffer_size,
3781 						  copy_n_frames, copy_mode);
3782     }
3783 
3784     if((i + copy_n_frames) % buffer_size == 0){
3785       stream = stream->next;
3786     }
3787 
3788     if((j + copy_n_frames) % buffer_size == 0){
3789       template_stream = template_stream->next;
3790     }
3791 
3792     i += copy_n_frames;
3793 
3794     if(loop_start < loop_end){
3795       if(j + copy_n_frames == loop_end &&
3796 	 (!do_close || i + copy_n_frames < loop_start + template_loop_frame_count)){
3797 	template_stream = g_list_nth(template->stream,
3798 				     floor(loop_start / buffer_size));
3799 
3800 	j = loop_start;
3801       }else{
3802 	j += copy_n_frames;
3803       }
3804     }else{
3805       j += copy_n_frames;
3806     }
3807   }
3808 
3809   g_rec_mutex_unlock(audio_signal_stream_mutex);
3810   g_rec_mutex_unlock(template_stream_mutex);
3811 }
3812 
3813 /**
3814  * ags_audio_signal_open_feed:
3815  * @audio_signal: the #AgsAudioSignal
3816  * @template: the template #AgsAudioSignal
3817  * @frame_count: the new frame count
3818  * @old_frame_count: the old frame count
3819  *
3820  * Feed audio signal to grow upto frame count.
3821  *
3822  * Since: 3.3.0
3823  */
3824 void
ags_audio_signal_open_feed(AgsAudioSignal * audio_signal,AgsAudioSignal * template,guint frame_count,guint old_frame_count)3825 ags_audio_signal_open_feed(AgsAudioSignal *audio_signal,
3826 			   AgsAudioSignal *template,
3827 			   guint frame_count, guint old_frame_count)
3828 {
3829   ags_audio_signal_feed_extended(audio_signal,
3830 				 template,
3831 				 frame_count, old_frame_count,
3832 				 TRUE, FALSE);
3833 }
3834 
3835 /**
3836  * ags_audio_signal_continue_feed:
3837  * @audio_signal: the #AgsAudioSignal
3838  * @template: the template #AgsAudioSignal
3839  * @frame_count: the new frame count
3840  * @old_frame_count: the old frame count
3841  *
3842  * Feed audio signal to grow upto frame count.
3843  *
3844  * Since: 3.3.0
3845  */
3846 void
ags_audio_signal_continue_feed(AgsAudioSignal * audio_signal,AgsAudioSignal * template,guint frame_count,guint old_frame_count)3847 ags_audio_signal_continue_feed(AgsAudioSignal *audio_signal,
3848 			       AgsAudioSignal *template,
3849 			       guint frame_count, guint old_frame_count)
3850 {
3851   ags_audio_signal_feed_extended(audio_signal,
3852 				 template,
3853 				 frame_count, old_frame_count,
3854 				 FALSE, FALSE);
3855 }
3856 
3857 /**
3858  * ags_audio_signal_close_feed:
3859  * @audio_signal: the #AgsAudioSignal
3860  * @template: the template #AgsAudioSignal
3861  * @frame_count: the new frame count
3862  * @old_frame_count: the old frame count
3863  *
3864  * Feed audio signal to grow upto frame count.
3865  *
3866  * Since: 3.3.0
3867  */
3868 void
ags_audio_signal_close_feed(AgsAudioSignal * audio_signal,AgsAudioSignal * template,guint frame_count,guint old_frame_count)3869 ags_audio_signal_close_feed(AgsAudioSignal *audio_signal,
3870 			    AgsAudioSignal *template,
3871 			    guint frame_count, guint old_frame_count)
3872 {
3873   ags_audio_signal_feed_extended(audio_signal,
3874 				 template,
3875 				 frame_count, old_frame_count,
3876 				 FALSE, TRUE);
3877 }
3878 
3879 /**
3880  * ags_audio_signal_get_note:
3881  * @audio_signal: the #AgsAudioSignal
3882  *
3883  * Get note.
3884  *
3885  * Returns: (element-type AgsAudio.Note) (transfer full): the #GList-struct containig #AgsNote
3886  *
3887  * Since: 3.1.0
3888  */
3889 GList*
ags_audio_signal_get_note(AgsAudioSignal * audio_signal)3890 ags_audio_signal_get_note(AgsAudioSignal *audio_signal)
3891 {
3892   GList *note;
3893 
3894   if(!AGS_IS_AUDIO_SIGNAL(audio_signal)){
3895     return(NULL);
3896   }
3897 
3898   g_object_get(audio_signal,
3899 	       "note", &note,
3900 	       NULL);
3901 
3902   return(note);
3903 }
3904 
3905 /**
3906  * ags_audio_signal_set_note:
3907  * @audio_signal: the #AgsAudioSignal
3908  * @note: (element-type AgsAudio.Note) (transfer full): the #GList-struct containing #AgsNote
3909  *
3910  * Set note by replacing existing.
3911  *
3912  * Since: 3.1.0
3913  */
3914 void
ags_audio_signal_set_note(AgsAudioSignal * audio_signal,GList * note)3915 ags_audio_signal_set_note(AgsAudioSignal *audio_signal, GList *note)
3916 {
3917   GList *start_note;
3918 
3919   GRecMutex *audio_signal_mutex;
3920 
3921   if(!AGS_IS_AUDIO_SIGNAL(audio_signal)){
3922     return;
3923   }
3924 
3925   /* get audio signal mutex */
3926   audio_signal_mutex = AGS_AUDIO_SIGNAL_GET_OBJ_MUTEX(audio_signal);
3927 
3928   g_rec_mutex_lock(audio_signal_mutex);
3929 
3930   start_note = audio_signal->note;
3931   audio_signal->note = note;
3932 
3933   g_rec_mutex_unlock(audio_signal_mutex);
3934 
3935   g_list_free_full(start_note,
3936 		   (GDestroyNotify) g_object_unref);
3937 }
3938 
3939 void
ags_audio_signal_real_add_note(AgsAudioSignal * audio_signal,GObject * note)3940 ags_audio_signal_real_add_note(AgsAudioSignal *audio_signal,
3941 			       GObject *note)
3942 {
3943   if(g_list_find(audio_signal->note, note) == NULL){
3944     g_object_ref(note);
3945     audio_signal->note = g_list_prepend(audio_signal->note,
3946 					note);
3947   }
3948 }
3949 
3950 /**
3951  * ags_audio_signal_add_note:
3952  * @audio_signal: the #AgsAudioSignal
3953  * @note: the #AgsNote
3954  *
3955  * Add note to @audio_signal.
3956  *
3957  * Since: 3.0.0
3958  */
3959 void
ags_audio_signal_add_note(AgsAudioSignal * audio_signal,GObject * note)3960 ags_audio_signal_add_note(AgsAudioSignal *audio_signal,
3961 			  GObject *note)
3962 {
3963   g_return_if_fail(AGS_IS_AUDIO_SIGNAL(audio_signal));
3964   g_object_ref(G_OBJECT(audio_signal));
3965   g_signal_emit(G_OBJECT(audio_signal),
3966 		audio_signal_signals[ADD_NOTE], 0,
3967 		note);
3968   g_object_unref(G_OBJECT(audio_signal));
3969 }
3970 
3971 void
ags_audio_signal_real_remove_note(AgsAudioSignal * audio_signal,GObject * note)3972 ags_audio_signal_real_remove_note(AgsAudioSignal *audio_signal,
3973 				  GObject *note)
3974 {
3975   if(g_list_find(audio_signal->note, note) != NULL){
3976     audio_signal->note = g_list_remove(audio_signal->note,
3977 				       note);
3978     g_object_unref(note);
3979   }
3980 }
3981 
3982 /**
3983  * ags_audio_signal_remove_note:
3984  * @audio_signal: the #AgsAudioSignal
3985  * @note: the #AgsNote
3986  *
3987  * Remove note from @audio_signal.
3988  *
3989  * Since: 3.0.0
3990  */
3991 void
ags_audio_signal_remove_note(AgsAudioSignal * audio_signal,GObject * note)3992 ags_audio_signal_remove_note(AgsAudioSignal *audio_signal,
3993 			     GObject *note)
3994 {
3995   g_return_if_fail(AGS_IS_AUDIO_SIGNAL(audio_signal));
3996   g_object_ref(G_OBJECT(audio_signal));
3997   g_signal_emit(G_OBJECT(audio_signal),
3998 		audio_signal_signals[REMOVE_NOTE], 0,
3999 		note);
4000   g_object_unref(G_OBJECT(audio_signal));
4001 }
4002 
4003 /**
4004  * ags_audio_signal_get_stream:
4005  * @audio_signal: the #AgsAudioSignal
4006  *
4007  * Get stream.
4008  *
4009  * Returns: (element-type guint8) (transfer none): the #GList-struct containig audio data
4010  *
4011  * Since: 3.8.11
4012  */
4013 GList*
ags_audio_signal_get_stream(AgsAudioSignal * audio_signal)4014 ags_audio_signal_get_stream(AgsAudioSignal *audio_signal)
4015 {
4016   GList *start_stream;
4017 
4018   GRecMutex *stream_mutex;
4019 
4020   if(!AGS_IS_AUDIO_SIGNAL(audio_signal)){
4021     return(NULL);
4022   }
4023 
4024   /* get stream mutex */
4025   stream_mutex = AGS_AUDIO_SIGNAL_GET_STREAM_MUTEX(audio_signal);
4026 
4027   g_rec_mutex_lock(stream_mutex);
4028 
4029   start_stream = audio_signal->stream;
4030 
4031   g_rec_mutex_unlock(stream_mutex);
4032 
4033   return(start_stream);
4034 }
4035 
4036 /**
4037  * ags_audio_signal_set_stream:
4038  * @audio_signal: the #AgsAudioSignal
4039  * @stream: (element-type guint8) (transfer full): the #GList-struct containing audio data
4040  *
4041  * Set stream by replacing existing.
4042  *
4043  * Since: 3.8.11
4044  */
4045 void
ags_audio_signal_set_stream(AgsAudioSignal * audio_signal,GList * stream)4046 ags_audio_signal_set_stream(AgsAudioSignal *audio_signal, GList *stream)
4047 {
4048   GList *start_stream;
4049 
4050   GRecMutex *stream_mutex;
4051 
4052   if(!AGS_IS_AUDIO_SIGNAL(audio_signal)){
4053     return;
4054   }
4055 
4056   /* get stream mutex */
4057   stream_mutex = AGS_AUDIO_SIGNAL_GET_STREAM_MUTEX(audio_signal);
4058 
4059   g_rec_mutex_lock(stream_mutex);
4060 
4061   start_stream = audio_signal->stream;
4062   audio_signal->stream = stream;
4063 
4064   g_rec_mutex_unlock(stream_mutex);
4065 
4066   if(!ags_audio_signal_test_flags(audio_signal,
4067 				  AGS_AUDIO_SIGNAL_SLICE_ALLOC)){
4068     g_list_free_full(start_stream,
4069 		     (GDestroyNotify) ags_stream_free);
4070   }else{
4071     guint buffer_size;
4072 
4073     buffer_size = AGS_SOUNDCARD_DEFAULT_BUFFER_SIZE;
4074 
4075     g_object_get(audio_signal,
4076 		 "buffer-size", &buffer_size,
4077 		 NULL);
4078 
4079     g_list_free_full(start_stream,
4080 		     (GDestroyNotify) ags_stream_slice_free);
4081   }
4082 }
4083 
4084 /**
4085  * ags_audio_signal_get_template:
4086  * @audio_signal: (element-type AgsAudio.AudioSignal) (transfer none): the #GList-struct containing #AgsAudioSignal
4087  *
4088  * Retrieve the template audio signal.
4089  *
4090  * Returns: (transfer full): the template #AgsAudioSignal or %NULL if not found
4091  *
4092  * Since: 3.0.0
4093  */
4094 AgsAudioSignal*
ags_audio_signal_get_template(GList * audio_signal)4095 ags_audio_signal_get_template(GList *audio_signal)
4096 {
4097   while(audio_signal != NULL){
4098     /* check flags */
4099     if(ags_audio_signal_test_flags(audio_signal->data, AGS_AUDIO_SIGNAL_TEMPLATE)){
4100       g_object_ref(audio_signal->data);
4101 
4102       return(audio_signal->data);
4103     }
4104 
4105     /* iterate */
4106     audio_signal = audio_signal->next;
4107   }
4108 
4109   return(NULL);
4110 }
4111 
4112 /**
4113  * ags_audio_signal_get_rt_template:
4114  * @audio_signal: (element-type AgsAudio.AudioSignal) (transfer none): a #GList-struct containing #AgsAudioSignal
4115  *
4116  * Retrieve the realtime template audio signal.
4117  *
4118  * Returns: (element-type AgsAudio.AudioSignal) (transfer full): the rt-templates as #GList-struct containing #AgsAudioSignal
4119  *
4120  * Since: 3.0.0
4121  */
4122 GList*
ags_audio_signal_get_rt_template(GList * audio_signal)4123 ags_audio_signal_get_rt_template(GList *audio_signal)
4124 {
4125   GList *rt_template;
4126 
4127   rt_template = NULL;
4128 
4129   while(audio_signal != NULL){
4130     /* check flags */
4131     if(ags_audio_signal_test_flags(audio_signal->data, AGS_AUDIO_SIGNAL_RT_TEMPLATE)){
4132       g_object_ref(audio_signal->data);
4133 
4134       rt_template = g_list_prepend(rt_template,
4135 				   audio_signal->data);
4136     }
4137 
4138     /* iterate */
4139     audio_signal = audio_signal->next;
4140   }
4141 
4142   rt_template = g_list_reverse(rt_template);
4143 
4144   return(rt_template);
4145 }
4146 
4147 /**
4148  * ags_audio_signal_find_by_recall_id:
4149  * @audio_signal: (element-type AgsAudio.AudioSignal) (transfer none): a #GList-struct containing #AgsAudioSignal
4150  * @recall_id: matching #AgsRecallID
4151  *
4152  * Retrieve next audio signal refering to @recall_id
4153  *
4154  * Returns: (element-type AgsAudio.AudioSignal) (transfer none): matching #GList-struct containing #AgsAudioSignal
4155  *
4156  * Since: 3.0.0
4157  */
4158 GList*
ags_audio_signal_find_by_recall_id(GList * audio_signal,GObject * recall_id)4159 ags_audio_signal_find_by_recall_id(GList *audio_signal,
4160 				   GObject *recall_id)
4161 {
4162   AgsAudioSignal *current_audio_signal;
4163   AgsRecallID *current_recall_id;
4164 
4165   GRecMutex *audio_signal_mutex;
4166 
4167   while(audio_signal != NULL){
4168     current_audio_signal = audio_signal->data;
4169 
4170     /* get audio signal mutex */
4171     audio_signal_mutex = AGS_AUDIO_SIGNAL_GET_OBJ_MUTEX(current_audio_signal);
4172 
4173     /* get some fields */
4174     g_rec_mutex_lock(audio_signal_mutex);
4175 
4176     current_recall_id = (AgsRecallID *) current_audio_signal->recall_id;
4177 
4178     g_rec_mutex_unlock(audio_signal_mutex);
4179 
4180     /* check recall id */
4181     if(current_recall_id == (AgsRecallID *) recall_id){
4182       return(audio_signal);
4183     }
4184 
4185     /* iterate */
4186     audio_signal = audio_signal->next;
4187   }
4188 
4189   return(NULL);
4190 }
4191 
4192 /**
4193  * ags_audio_signal_find_stream_current:
4194  * @audio_signal: (element-type AgsAudio.AudioSignal) (transfer none): the #GList-struct containing #AgsAudioSignal
4195  * @recall_id: the matching #AgsRecallID
4196  *
4197  * Retrieve next current stream of #AgsAudioSignal list. Warning this function does not
4198  * lock the stream mutex.
4199  *
4200  * Returns: (element-type AgsAudio.AudioSignal) (transfer none): next #GList-struct matching #AgsRecallID
4201  *
4202  * Since: 3.0.0
4203  */
4204 GList*
ags_audio_signal_find_stream_current(GList * audio_signal,GObject * recall_id)4205 ags_audio_signal_find_stream_current(GList *audio_signal,
4206 				     GObject *recall_id)
4207 {
4208   AgsAudioSignal *current_audio_signal;
4209   AgsRecallID *current_recall_id;
4210 
4211   GList *stream_current;
4212 
4213   while((audio_signal = ags_audio_signal_find_by_recall_id(audio_signal, recall_id)) != NULL){
4214     current_audio_signal = audio_signal->data;
4215 
4216     /* get some fields */
4217     stream_current = current_audio_signal->stream_current;
4218 
4219     if(stream_current != NULL){
4220       return(audio_signal);
4221     }
4222 
4223     /* iterate */
4224     audio_signal = audio_signal->next;
4225   }
4226 
4227   return(NULL);
4228 }
4229 
4230 /**
4231  * ags_audio_signal_is_active:
4232  * @audio_signal: (element-type AgsAudio.AudioSignal) (transfer none): the #GList-struct containing #AgsAudioSignal
4233  * @recall_id: the #AgsRecallID
4234  *
4235  * Check if is active.
4236  *
4237  * Returns: %TRUE if related audio signal to recall id is available, otherwise %FALSE
4238  *
4239  * Since: 3.0.0
4240  */
4241 gboolean
ags_audio_signal_is_active(GList * audio_signal,GObject * recall_id)4242 ags_audio_signal_is_active(GList *audio_signal,
4243 			   GObject *recall_id)
4244 {
4245   AgsAudioSignal *current_audio_signal;
4246   AgsRecallID *current_recall_id;
4247   AgsRecyclingContext *current_recycling_context, *recycling_context;
4248 
4249   GRecMutex *audio_signal_mutex;
4250   GRecMutex *recall_id_mutex;
4251 
4252   if(!AGS_IS_RECALL_ID(recall_id)){
4253     return(FALSE);
4254   }
4255 
4256   /* get audio signal mutex */
4257   recall_id_mutex = AGS_RECALL_ID_GET_OBJ_MUTEX(recall_id);
4258 
4259   /* get recycling context */
4260   g_rec_mutex_lock(recall_id_mutex);
4261 
4262   recycling_context = AGS_RECALL_ID(recall_id)->recycling_context;
4263 
4264   g_rec_mutex_unlock(recall_id_mutex);
4265 
4266   while(audio_signal != NULL){
4267     current_audio_signal = audio_signal->data;
4268 
4269     /* get audio signal mutex */
4270     audio_signal_mutex = AGS_AUDIO_SIGNAL_GET_OBJ_MUTEX(current_audio_signal);
4271 
4272     /* get some fields */
4273     g_rec_mutex_lock(audio_signal_mutex);
4274 
4275     current_recall_id = (AgsRecallID *) current_audio_signal->recall_id;
4276 
4277     g_rec_mutex_unlock(audio_signal_mutex);
4278 
4279     /* get current recycling context */
4280     current_recycling_context = NULL;
4281 
4282     if(current_recall_id != NULL){
4283       /* get recall id mutex */
4284       recall_id_mutex = AGS_RECALL_ID_GET_OBJ_MUTEX(current_recall_id);
4285 
4286       /* get some fields */
4287       g_rec_mutex_lock(recall_id_mutex);
4288 
4289       current_recycling_context = current_recall_id->recycling_context;
4290 
4291       g_rec_mutex_unlock(recall_id_mutex);
4292     }
4293 
4294     if(current_recycling_context == recycling_context){
4295       return(TRUE);
4296     }
4297 
4298     /* iterate */
4299     audio_signal = audio_signal->next;
4300   }
4301 
4302   return(FALSE);
4303 }
4304 
4305 /**
4306  * ags_audio_signal_new:
4307  * @output_soundcard: the assigned output #AgsSoundcard
4308  * @recycling: the #AgsRecycling
4309  * @recall_id: the #AgsRecallID, it can be NULL if %AGS_AUDIO_SIGNAL_TEMPLATE is set
4310  *
4311  * Creates a #AgsAudioSignal, with defaults of @output_soundcard, linking @recycling tree
4312  * and refering to @recall_id.
4313  *
4314  * Returns: a new #AgsAudioSignal
4315  *
4316  * Since: 3.0.0
4317  */
4318 AgsAudioSignal*
ags_audio_signal_new(GObject * output_soundcard,GObject * recycling,GObject * recall_id)4319 ags_audio_signal_new(GObject *output_soundcard,
4320 		     GObject *recycling,
4321 		     GObject *recall_id)
4322 {
4323   AgsAudioSignal *audio_signal;
4324 
4325   audio_signal = (AgsAudioSignal *) g_object_new(AGS_TYPE_AUDIO_SIGNAL,
4326 						 "output-soundcard", output_soundcard,
4327 						 "recycling", recycling,
4328 						 "recall-id", recall_id,
4329 						 NULL);
4330 
4331   return(audio_signal);
4332 }
4333 
4334 /**
4335  * ags_audio_signal_new_with_length:
4336  * @output_soundcard: the assigned output #AgsSoundcard
4337  * @recycling: the #AgsRecycling
4338  * @recall_id: the #AgsRecallID, it can be NULL if %AGS_AUDIO_SIGNAL_TEMPLATE is set
4339  * @length: audio data frame count
4340  *
4341  * Creates a #AgsAudioSignal, with defaults of @soundcard, linking @recycling tree
4342  * and refering to @recall_id.
4343  * The audio data is tiled to @length frame count.
4344  *
4345  * Returns: a new #AgsAudioSignal
4346  *
4347  * Since: 3.0.0
4348  */
4349 AgsAudioSignal*
ags_audio_signal_new_with_length(GObject * output_soundcard,GObject * recycling,GObject * recall_id,guint length)4350 ags_audio_signal_new_with_length(GObject *output_soundcard,
4351 				 GObject *recycling,
4352 				 GObject *recall_id,
4353 				 guint length)
4354 {
4355   AgsAudioSignal *audio_signal, *template;
4356 
4357   audio_signal = (AgsAudioSignal *) g_object_new(AGS_TYPE_AUDIO_SIGNAL,
4358 						 "output-soundcard", output_soundcard,
4359 						 "recycling", recycling,
4360 						 "recall-id", recall_id,
4361 						 NULL);
4362 
4363   ags_audio_signal_stream_resize(audio_signal,
4364 				 length);
4365 
4366   return(audio_signal);
4367 }
4368