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", ¬e,
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