1 /* GSequencer - Advanced GTK Sequencer
2 * Copyright (C) 2005-2020 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/fx/ags_fx_playback_audio_processor.h>
21
22 #include <ags/audio/ags_wave.h>
23 #include <ags/audio/ags_audio_buffer_util.h>
24
25 #include <ags/audio/fx/ags_fx_playback_audio.h>
26
27 #include <ags/i18n.h>
28
29 void ags_fx_playback_audio_processor_class_init(AgsFxPlaybackAudioProcessorClass *fx_playback_audio_processor);
30 void ags_fx_playback_audio_processor_seekable_interface_init(AgsSeekableInterface *seekable);
31 void ags_fx_playback_audio_processor_countable_interface_init(AgsCountableInterface *countable);
32 void ags_fx_playback_audio_processor_tactable_interface_init(AgsTactableInterface *tactable);
33 void ags_fx_playback_audio_processor_init(AgsFxPlaybackAudioProcessor *fx_playback_audio_processor);
34 void ags_fx_playback_audio_processor_dispose(GObject *gobject);
35 void ags_fx_playback_audio_processor_finalize(GObject *gobject);
36
37 void ags_fx_playback_audio_processor_seek(AgsSeekable *seekable,
38 gint64 offset,
39 guint whence);
40
41 guint64 ags_fx_playback_audio_processor_get_wave_counter(AgsCountable *countable);
42
43 gdouble ags_fx_playback_audio_processor_get_bpm(AgsTactable *tactable);
44 gdouble ags_fx_playback_audio_processor_get_tact(AgsTactable *tactable);
45 void ags_fx_playback_audio_processor_change_bpm(AgsTactable *tactable, gdouble new_bpm, gdouble old_bpm);
46 void ags_fx_playback_audio_processor_change_tact(AgsTactable *tactable, gdouble new_tact, gdouble old_tact);
47
48 void ags_fx_playback_audio_processor_run_init_pre(AgsRecall *recall);
49 void ags_fx_playback_audio_processor_run_inter(AgsRecall *recall);
50
51 void ags_fx_playback_audio_processor_real_data_put(AgsFxPlaybackAudioProcessor *fx_playback_audio_processor,
52 AgsBuffer *buffer,
53 guint data_mode);
54 void ags_fx_playback_audio_processor_real_data_get(AgsFxPlaybackAudioProcessor *fx_playback_audio_processor,
55 AgsBuffer *buffer,
56 guint data_mode);
57
58 void ags_fx_playback_audio_processor_real_play(AgsFxPlaybackAudioProcessor *fx_playback_audio_processor);
59 void ags_fx_playback_audio_processor_real_record(AgsFxPlaybackAudioProcessor *fx_playback_audio_processor);
60 void ags_fx_playback_audio_processor_real_feed(AgsFxPlaybackAudioProcessor *fx_playback_audio_processor);
61 void ags_fx_playback_audio_processor_real_master(AgsFxPlaybackAudioProcessor *fx_playback_audio_processor);
62
63 void ags_fx_playback_audio_processor_real_counter_change(AgsFxPlaybackAudioProcessor *fx_playback_audio_processor);
64
65 /**
66 * SECTION:ags_fx_playback_audio_processor
67 * @short_description: fx playback audio processor
68 * @title: AgsFxPlaybackAudioProcessor
69 * @section_id:
70 * @include: ags/audio/fx/ags_fx_playback_audio_processor.h
71 *
72 * The #AgsFxPlaybackAudioProcessor class provides ports to the effect processor.
73 */
74
75 static gpointer ags_fx_playback_audio_processor_parent_class = NULL;
76
77 GType
ags_fx_playback_audio_processor_get_type()78 ags_fx_playback_audio_processor_get_type()
79 {
80 static volatile gsize g_define_type_id__volatile = 0;
81
82 if(g_once_init_enter (&g_define_type_id__volatile)){
83 GType ags_type_fx_playback_audio_processor = 0;
84
85 static const GTypeInfo ags_fx_playback_audio_processor_info = {
86 sizeof (AgsFxPlaybackAudioProcessorClass),
87 NULL, /* base_init */
88 NULL, /* base_finalize */
89 (GClassInitFunc) ags_fx_playback_audio_processor_class_init,
90 NULL, /* class_finalize */
91 NULL, /* class_audio_processor */
92 sizeof (AgsFxPlaybackAudioProcessor),
93 0, /* n_preallocs */
94 (GInstanceInitFunc) ags_fx_playback_audio_processor_init,
95 };
96
97 static const GInterfaceInfo ags_seekable_interface_info = {
98 (GInterfaceInitFunc) ags_fx_playback_audio_processor_seekable_interface_init,
99 NULL, /* interface_finalize */
100 NULL, /* interface_data */
101 };
102
103 static const GInterfaceInfo ags_countable_interface_info = {
104 (GInterfaceInitFunc) ags_fx_playback_audio_processor_countable_interface_init,
105 NULL, /* interface_finalize */
106 NULL, /* interface_data */
107 };
108
109 static const GInterfaceInfo ags_tactable_interface_info = {
110 (GInterfaceInitFunc) ags_fx_playback_audio_processor_tactable_interface_init,
111 NULL, /* interface_finalize */
112 NULL, /* interface_data */
113 };
114
115 ags_type_fx_playback_audio_processor = g_type_register_static(AGS_TYPE_RECALL_AUDIO_RUN,
116 "AgsFxPlaybackAudioProcessor",
117 &ags_fx_playback_audio_processor_info,
118 0);
119
120 g_type_add_interface_static(ags_type_fx_playback_audio_processor,
121 AGS_TYPE_COUNTABLE,
122 &ags_countable_interface_info);
123
124 g_type_add_interface_static(ags_type_fx_playback_audio_processor,
125 AGS_TYPE_SEEKABLE,
126 &ags_seekable_interface_info);
127
128 g_type_add_interface_static(ags_type_fx_playback_audio_processor,
129 AGS_TYPE_TACTABLE,
130 &ags_tactable_interface_info);
131
132 g_once_init_leave(&g_define_type_id__volatile, ags_type_fx_playback_audio_processor);
133 }
134
135 return g_define_type_id__volatile;
136 }
137
138 void
ags_fx_playback_audio_processor_class_init(AgsFxPlaybackAudioProcessorClass * fx_playback_audio_processor)139 ags_fx_playback_audio_processor_class_init(AgsFxPlaybackAudioProcessorClass *fx_playback_audio_processor)
140 {
141 GObjectClass *gobject;
142 AgsRecallClass *recall;
143
144 ags_fx_playback_audio_processor_parent_class = g_type_class_peek_parent(fx_playback_audio_processor);
145
146 /* GObjectClass */
147 gobject = (GObjectClass *) fx_playback_audio_processor;
148
149 gobject->dispose = ags_fx_playback_audio_processor_dispose;
150 gobject->finalize = ags_fx_playback_audio_processor_finalize;
151
152 /* AgsRecallClass */
153 recall = (AgsRecallClass *) fx_playback_audio_processor;
154
155 recall->run_init_pre = ags_fx_playback_audio_processor_run_init_pre;
156 recall->run_inter = ags_fx_playback_audio_processor_run_inter;
157
158 /* AgsFxPlaybackAudioProcessorClass */
159 fx_playback_audio_processor->data_put = ags_fx_playback_audio_processor_real_data_put;
160 fx_playback_audio_processor->data_get = ags_fx_playback_audio_processor_real_data_get;
161
162 fx_playback_audio_processor->play = ags_fx_playback_audio_processor_real_play;
163 fx_playback_audio_processor->record = ags_fx_playback_audio_processor_real_record;
164 fx_playback_audio_processor->feed = ags_fx_playback_audio_processor_real_feed;
165 fx_playback_audio_processor->master = ags_fx_playback_audio_processor_real_master;
166
167 fx_playback_audio_processor->counter_change = ags_fx_playback_audio_processor_real_counter_change;
168 }
169
170 void
ags_fx_playback_audio_processor_seekable_interface_init(AgsSeekableInterface * seekable)171 ags_fx_playback_audio_processor_seekable_interface_init(AgsSeekableInterface *seekable)
172 {
173 seekable->seek = ags_fx_playback_audio_processor_seek;
174 }
175
176 void
ags_fx_playback_audio_processor_countable_interface_init(AgsCountableInterface * countable)177 ags_fx_playback_audio_processor_countable_interface_init(AgsCountableInterface *countable)
178 {
179 countable->get_sequencer_counter = NULL;
180 countable->get_notation_counter = NULL;
181 countable->get_wave_counter = ags_fx_playback_audio_processor_get_wave_counter;
182 countable->get_midi_counter = NULL;
183 }
184
185 void
ags_fx_playback_audio_processor_tactable_interface_init(AgsTactableInterface * tactable)186 ags_fx_playback_audio_processor_tactable_interface_init(AgsTactableInterface *tactable)
187 {
188 tactable->get_bpm = ags_fx_playback_audio_processor_get_bpm;
189 tactable->get_tact = ags_fx_playback_audio_processor_get_tact;
190
191 tactable->get_sequencer_duration = NULL;
192 tactable->get_notation_duration = NULL;
193 tactable->get_wave_duration = NULL;
194 tactable->get_midi_duration = NULL;
195
196 tactable->change_sequencer_duration = NULL;
197 tactable->change_notation_duration = NULL;
198 tactable->change_wave_duration = NULL;
199 tactable->change_midi_duration = NULL;
200
201 tactable->change_bpm = ags_fx_playback_audio_processor_change_bpm;
202 tactable->change_tact = ags_fx_playback_audio_processor_change_tact;
203 }
204
205 void
ags_fx_playback_audio_processor_init(AgsFxPlaybackAudioProcessor * fx_playback_audio_processor)206 ags_fx_playback_audio_processor_init(AgsFxPlaybackAudioProcessor *fx_playback_audio_processor)
207 {
208 AGS_RECALL(fx_playback_audio_processor)->name = "ags-fx-playback";
209 AGS_RECALL(fx_playback_audio_processor)->version = AGS_RECALL_DEFAULT_VERSION;
210 AGS_RECALL(fx_playback_audio_processor)->build_id = AGS_RECALL_DEFAULT_BUILD_ID;
211 AGS_RECALL(fx_playback_audio_processor)->xml_type = "ags-fx-playback-audio-processor";
212
213 /* counter */
214 fx_playback_audio_processor->delay_completion = 0.0;
215
216 fx_playback_audio_processor->delay_counter = 0.0;
217 fx_playback_audio_processor->offset_counter = 0;
218
219 fx_playback_audio_processor->current_delay_counter = 0.0;
220 fx_playback_audio_processor->current_offset_counter = 0;
221
222 fx_playback_audio_processor->x_offset = 0;
223 fx_playback_audio_processor->current_x_offset = 0;
224
225 /* timestamp */
226 fx_playback_audio_processor->timestamp = ags_timestamp_new();
227 g_object_ref(fx_playback_audio_processor->timestamp);
228
229 fx_playback_audio_processor->timestamp->flags &= (~AGS_TIMESTAMP_UNIX);
230 fx_playback_audio_processor->timestamp->flags |= AGS_TIMESTAMP_OFFSET;
231
232 fx_playback_audio_processor->timestamp->timer.ags_offset.offset = 0;
233
234 /* playing */
235 fx_playback_audio_processor->playing_buffer = NULL;
236 fx_playback_audio_processor->playing_audio_signal = NULL;
237
238 /* recording */
239 fx_playback_audio_processor->recording_buffer = NULL;
240 fx_playback_audio_processor->recording_audio_signal = NULL;
241
242 /* feeding */
243 fx_playback_audio_processor->feeding_audio_signal = NULL;
244
245 /* mastering */
246 fx_playback_audio_processor->mastering_audio_signal = NULL;
247
248 /* capture */
249 fx_playback_audio_processor->capture_audio_signal = NULL;
250 }
251
252 void
ags_fx_playback_audio_processor_dispose(GObject * gobject)253 ags_fx_playback_audio_processor_dispose(GObject *gobject)
254 {
255 AgsFxPlaybackAudioProcessor *fx_playback_audio_processor;
256
257 fx_playback_audio_processor = AGS_FX_PLAYBACK_AUDIO_PROCESSOR(gobject);
258
259 /* call parent */
260 G_OBJECT_CLASS(ags_fx_playback_audio_processor_parent_class)->dispose(gobject);
261 }
262
263 void
ags_fx_playback_audio_processor_finalize(GObject * gobject)264 ags_fx_playback_audio_processor_finalize(GObject *gobject)
265 {
266 AgsFxPlaybackAudioProcessor *fx_playback_audio_processor;
267
268 fx_playback_audio_processor = AGS_FX_PLAYBACK_AUDIO_PROCESSOR(gobject);
269
270 /* timestamp */
271 if(fx_playback_audio_processor->timestamp != NULL){
272 g_object_unref((GObject *) fx_playback_audio_processor->timestamp);
273 }
274
275 /* playing - buffer and audio signal */
276 if(fx_playback_audio_processor->playing_buffer != NULL){
277 g_list_free_full(fx_playback_audio_processor->playing_buffer,
278 (GDestroyNotify) g_object_unref);
279 }
280
281 if(fx_playback_audio_processor->playing_audio_signal != NULL){
282 g_list_free_full(fx_playback_audio_processor->playing_audio_signal,
283 (GDestroyNotify) g_object_unref);
284 }
285
286 /* recording - buffer and audio signal */
287 if(fx_playback_audio_processor->recording_buffer != NULL){
288 g_list_free_full(fx_playback_audio_processor->recording_buffer,
289 (GDestroyNotify) g_object_unref);
290 }
291
292 if(fx_playback_audio_processor->recording_audio_signal != NULL){
293 g_list_free_full(fx_playback_audio_processor->recording_audio_signal,
294 (GDestroyNotify) g_object_unref);
295 }
296
297 /* feeding - audio signal */
298 if(fx_playback_audio_processor->feeding_audio_signal != NULL){
299 g_list_free_full(fx_playback_audio_processor->feeding_audio_signal,
300 (GDestroyNotify) g_object_unref);
301 }
302
303 /* mastering - audio signal */
304 if(fx_playback_audio_processor->mastering_audio_signal != NULL){
305 g_list_free_full(fx_playback_audio_processor->mastering_audio_signal,
306 (GDestroyNotify) g_object_unref);
307 }
308
309 /* capture - audio signal */
310 if(fx_playback_audio_processor->capture_audio_signal != NULL){
311 g_list_free_full(fx_playback_audio_processor->capture_audio_signal,
312 (GDestroyNotify) g_object_unref);
313 }
314
315 /* call parent */
316 G_OBJECT_CLASS(ags_fx_playback_audio_processor_parent_class)->finalize(gobject);
317 }
318
319 void
ags_fx_playback_audio_processor_seek(AgsSeekable * seekable,gint64 offset,guint whence)320 ags_fx_playback_audio_processor_seek(AgsSeekable *seekable,
321 gint64 offset,
322 guint whence)
323 {
324 AgsFxPlaybackAudio *fx_playback_audio;
325 AgsFxPlaybackAudioProcessor *fx_playback_audio_processor;
326 AgsPort *port;
327
328 gdouble playback_duration;
329
330 GRecMutex *recall_mutex;
331
332 gdouble delay;
333 guint64 playback_counter;
334 guint buffer_size;
335
336 GValue value = {0,};
337
338 fx_playback_audio = NULL;
339
340 fx_playback_audio_processor = AGS_FX_PLAYBACK_AUDIO_PROCESSOR(seekable);
341
342 /* get recall mutex */
343 recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(fx_playback_audio_processor);
344
345 buffer_size = AGS_SOUNDCARD_DEFAULT_BUFFER_SIZE;
346
347 g_object_get(fx_playback_audio_processor,
348 "recall-audio", &fx_playback_audio,
349 "buffer-size", &buffer_size,
350 NULL);
351
352 /* delay */
353 port = NULL;
354
355 delay = AGS_SOUNDCARD_DEFAULT_DELAY;
356
357 playback_duration = ceil(AGS_NOTATION_DEFAULT_DURATION * delay);
358
359 g_object_get(fx_playback_audio,
360 "delay", &port,
361 NULL);
362
363 if(port != NULL){
364 g_value_init(&value, G_TYPE_DOUBLE);
365
366 ags_port_safe_read(port, &value);
367
368 delay = g_value_get_double(&value);
369
370 g_value_unset(&value);
371
372 g_object_unref(port);
373 }
374
375 /* duration */
376 port = NULL;
377
378 g_object_get(fx_playback_audio,
379 "duration", &port,
380 NULL);
381
382 if(port != NULL){
383 g_value_init(&value, G_TYPE_UINT64);
384
385 ags_port_safe_read(port, &value);
386
387 playback_duration = g_value_get_uint64(&value);
388
389 g_value_unset(&value);
390
391 g_object_unref(port);
392 }
393
394 switch(whence){
395 case AGS_SEEK_CUR:
396 {
397 g_rec_mutex_lock(recall_mutex);
398
399 playback_counter = fx_playback_audio_processor->offset_counter;
400
401 if(playback_counter + offset < 0){
402 playback_counter = (guint64) playback_duration - (guint64) ((offset - playback_counter) % (guint64) playback_duration);
403 }else{
404 playback_counter = (guint64) (playback_counter + offset) % (guint64) playback_duration;
405 }
406
407 fx_playback_audio_processor->delay_counter =
408 fx_playback_audio_processor->current_delay_counter = 0.0;
409
410 fx_playback_audio_processor->offset_counter =
411 fx_playback_audio_processor->current_offset_counter = playback_counter;
412
413 fx_playback_audio_processor->x_offset =
414 fx_playback_audio_processor->current_x_offset = (guint64) floor(playback_counter * delay) * buffer_size;
415
416 g_rec_mutex_unlock(recall_mutex);
417 }
418 break;
419 case AGS_SEEK_END:
420 {
421 g_rec_mutex_lock(recall_mutex);
422
423 playback_counter = fx_playback_audio_processor->offset_counter;
424
425 /* playback */
426 if(playback_duration + offset < 0){
427 playback_counter = (guint64) playback_duration - ((guint64) (offset - playback_duration) % (guint64) playback_duration);
428 }else{
429 playback_counter = (guint64) (playback_duration + offset) % (guint64) playback_duration;
430 }
431
432 fx_playback_audio_processor->delay_counter =
433 fx_playback_audio_processor->current_delay_counter = 0.0;
434
435 fx_playback_audio_processor->offset_counter =
436 fx_playback_audio_processor->current_offset_counter = playback_counter;
437
438 fx_playback_audio_processor->x_offset =
439 fx_playback_audio_processor->current_x_offset = (guint64) floor(playback_counter * delay) * buffer_size;
440
441 g_rec_mutex_unlock(recall_mutex);
442 }
443 break;
444 case AGS_SEEK_SET:
445 {
446 g_rec_mutex_lock(recall_mutex);
447
448 fx_playback_audio_processor->delay_counter =
449 fx_playback_audio_processor->current_delay_counter = 0.0;
450
451 fx_playback_audio_processor->offset_counter =
452 fx_playback_audio_processor->current_offset_counter = offset;
453
454 fx_playback_audio_processor->x_offset =
455 fx_playback_audio_processor->current_x_offset = (guint64) floor(offset * delay) * buffer_size;
456
457 g_rec_mutex_unlock(recall_mutex);
458 }
459 break;
460 }
461
462 if(fx_playback_audio != NULL){
463 g_object_unref(fx_playback_audio);
464 }
465 }
466
467 guint64
ags_fx_playback_audio_processor_get_wave_counter(AgsCountable * countable)468 ags_fx_playback_audio_processor_get_wave_counter(AgsCountable *countable)
469 {
470 AgsFxPlaybackAudioProcessor *fx_playback_audio_processor;
471
472 guint64 playback_counter;
473
474 GRecMutex *recall_mutex;
475
476 fx_playback_audio_processor = AGS_FX_PLAYBACK_AUDIO_PROCESSOR(countable);
477
478 /* get recall mutex */
479 recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(fx_playback_audio_processor);
480
481 /* bpm */
482 g_rec_mutex_lock(recall_mutex);
483
484 playback_counter = fx_playback_audio_processor->offset_counter;
485
486 g_rec_mutex_unlock(recall_mutex);
487
488 return(playback_counter);
489 }
490
491 gdouble
ags_fx_playback_audio_processor_get_bpm(AgsTactable * tactable)492 ags_fx_playback_audio_processor_get_bpm(AgsTactable *tactable)
493 {
494 AgsFxPlaybackAudio *fx_playback_audio;
495 AgsFxPlaybackAudioProcessor *fx_playback_audio_processor;
496 AgsPort *port;
497
498 gdouble bpm;
499
500 GValue value = {0,};
501
502 fx_playback_audio = NULL;
503
504 fx_playback_audio_processor = AGS_FX_PLAYBACK_AUDIO_PROCESSOR(tactable);
505
506 port = NULL;
507
508 bpm = AGS_SOUNDCARD_DEFAULT_BPM;
509
510 g_object_get(fx_playback_audio_processor,
511 "recall-audio", &fx_playback_audio,
512 NULL);
513
514 if(fx_playback_audio != NULL){
515 g_object_get(fx_playback_audio,
516 "bpm", &port,
517 NULL);
518
519 if(port != NULL){
520 g_value_init(&value, G_TYPE_DOUBLE);
521
522 ags_port_safe_read(port, &value);
523
524 bpm = g_value_get_double(&value);
525
526 g_value_unset(&value);
527
528 g_object_unref(port);
529 }
530 }
531
532 if(fx_playback_audio != NULL){
533 g_object_unref(fx_playback_audio);
534 }
535
536 return(bpm);
537 }
538
539 gdouble
ags_fx_playback_audio_processor_get_tact(AgsTactable * tactable)540 ags_fx_playback_audio_processor_get_tact(AgsTactable *tactable)
541 {
542 AgsFxPlaybackAudio *fx_playback_audio;
543 AgsFxPlaybackAudioProcessor *fx_playback_audio_processor;
544 AgsPort *port;
545
546 gdouble tact;
547
548 GValue value = {0,};
549
550 fx_playback_audio = NULL;
551
552 fx_playback_audio_processor = AGS_FX_PLAYBACK_AUDIO_PROCESSOR(tactable);
553
554 port = NULL;
555
556 tact = AGS_SOUNDCARD_DEFAULT_TACT;
557
558 g_object_get(fx_playback_audio_processor,
559 "recall-audio", &fx_playback_audio,
560 NULL);
561
562 if(fx_playback_audio != NULL){
563 g_object_get(fx_playback_audio,
564 "tact", &port,
565 NULL);
566
567 if(port != NULL){
568 g_value_init(&value, G_TYPE_DOUBLE);
569
570 ags_port_safe_read(port, &value);
571
572 tact = g_value_get_double(&value);
573
574 g_value_unset(&value);
575
576 g_object_unref(port);
577 }
578 }
579
580 if(fx_playback_audio != NULL){
581 g_object_unref(fx_playback_audio);
582 }
583
584 return(tact);
585 }
586
587 void
ags_fx_playback_audio_processor_change_bpm(AgsTactable * tactable,gdouble new_bpm,gdouble old_bpm)588 ags_fx_playback_audio_processor_change_bpm(AgsTactable *tactable, gdouble new_bpm, gdouble old_bpm)
589 {
590 AgsFxPlaybackAudio *fx_playback_audio;
591 AgsFxPlaybackAudioProcessor *fx_playback_audio_processor;
592 AgsPort *port;
593
594 GObject *output_soundcard;
595
596 GValue value = {0,};
597
598 output_soundcard = NULL;
599
600 fx_playback_audio = NULL;
601
602 fx_playback_audio_processor = AGS_FX_PLAYBACK_AUDIO_PROCESSOR(tactable);
603
604 port = NULL;
605
606 g_object_get(fx_playback_audio_processor,
607 "output-soundcard", &output_soundcard,
608 "recall-audio", &fx_playback_audio,
609 NULL);
610
611 /* delay */
612 if(fx_playback_audio != NULL){
613 port = NULL;
614
615 g_object_get(fx_playback_audio,
616 "delay", &port,
617 NULL);
618
619 if(port != NULL){
620 g_value_init(&value, G_TYPE_DOUBLE);
621
622 g_value_set_double(&value, ags_soundcard_get_absolute_delay(AGS_SOUNDCARD(output_soundcard)));
623
624 ags_port_safe_write(port, &value);
625
626 g_value_unset(&value);
627
628 g_object_unref(port);
629 }
630 }
631
632 /* bpm */
633 if(fx_playback_audio != NULL){
634 port = NULL;
635
636 g_object_get(fx_playback_audio,
637 "bpm", &port,
638 NULL);
639
640 if(port != NULL){
641 g_value_init(&value, G_TYPE_DOUBLE);
642
643 g_value_set_double(&value, new_bpm);
644
645 ags_port_safe_write(port, &value);
646
647 g_value_unset(&value);
648
649 g_object_unref(port);
650 }
651 }
652
653 if(fx_playback_audio != NULL){
654 g_object_unref(fx_playback_audio);
655 }
656 }
657
658 void
ags_fx_playback_audio_processor_change_tact(AgsTactable * tactable,gdouble new_tact,gdouble old_tact)659 ags_fx_playback_audio_processor_change_tact(AgsTactable *tactable, gdouble new_tact, gdouble old_tact)
660 {
661 AgsFxPlaybackAudio *fx_playback_audio;
662 AgsFxPlaybackAudioProcessor *fx_playback_audio_processor;
663 AgsPort *port;
664
665 GObject *output_soundcard;
666
667 GValue value = {0,};
668
669 output_soundcard = NULL;
670
671 fx_playback_audio = NULL;
672
673 fx_playback_audio_processor = AGS_FX_PLAYBACK_AUDIO_PROCESSOR(tactable);
674
675 port = NULL;
676
677 g_object_get(fx_playback_audio_processor,
678 "output-soundcard", &output_soundcard,
679 "recall-audio", &fx_playback_audio,
680 NULL);
681 /* delay */
682 if(fx_playback_audio != NULL){
683 port = NULL;
684
685 g_object_get(fx_playback_audio,
686 "delay", &port,
687 NULL);
688
689 if(port != NULL){
690 g_value_init(&value, G_TYPE_DOUBLE);
691
692 g_value_set_double(&value, ags_soundcard_get_absolute_delay(AGS_SOUNDCARD(output_soundcard)));
693
694 ags_port_safe_write(port, &value);
695
696 g_value_unset(&value);
697
698 g_object_unref(port);
699 }
700 }
701
702 /* tact */
703 if(fx_playback_audio != NULL){
704 port = NULL;
705
706 g_object_get(fx_playback_audio,
707 "tact", &port,
708 NULL);
709
710 if(port != NULL){
711 g_value_init(&value, G_TYPE_DOUBLE);
712
713 g_value_set_double(&value, new_tact);
714
715 ags_port_safe_write(port, &value);
716
717 g_value_unset(&value);
718
719 g_object_unref(port);
720 }
721 }
722
723 if(fx_playback_audio != NULL){
724 g_object_unref(fx_playback_audio);
725 }
726 }
727
728 void
ags_fx_playback_audio_processor_run_init_pre(AgsRecall * recall)729 ags_fx_playback_audio_processor_run_init_pre(AgsRecall *recall)
730 {
731 AgsFxPlaybackAudioProcessor *fx_playback_audio_processor;
732
733 gdouble delay_counter;
734
735 GRecMutex *fx_playback_audio_processor_mutex;
736
737 fx_playback_audio_processor = AGS_FX_PLAYBACK_AUDIO_PROCESSOR(recall);
738
739 fx_playback_audio_processor_mutex = AGS_RECALL_GET_OBJ_MUTEX(fx_playback_audio_processor);
740
741 /* get delay counter */
742 g_rec_mutex_lock(fx_playback_audio_processor_mutex);
743
744 fx_playback_audio_processor->delay_counter = 0;
745 fx_playback_audio_processor->offset_counter = 0;
746 fx_playback_audio_processor->x_offset = 0;
747
748 fx_playback_audio_processor->current_delay_counter = 0;
749 fx_playback_audio_processor->current_offset_counter = 0;
750 fx_playback_audio_processor->current_x_offset = 0;
751
752 g_rec_mutex_unlock(fx_playback_audio_processor_mutex);
753
754 /* call parent */
755 AGS_RECALL_CLASS(ags_fx_playback_audio_processor_parent_class)->run_init_pre(recall);
756 }
757
758 void
ags_fx_playback_audio_processor_run_inter(AgsRecall * recall)759 ags_fx_playback_audio_processor_run_inter(AgsRecall *recall)
760 {
761 AgsFxPlaybackAudioProcessor *fx_playback_audio_processor;
762 AgsRecallID *recall_id;
763 AgsRecyclingContext *parent_recycling_context, *recycling_context;
764
765 GList *start_playing_audio_signal, *playing_audio_signal;
766 GList *start_recording_audio_signal, *recording_audio_signal;
767
768 gint sound_scope;
769 gdouble delay_counter;
770
771 GRecMutex *fx_playback_audio_processor_mutex;
772
773 fx_playback_audio_processor = AGS_FX_PLAYBACK_AUDIO_PROCESSOR(recall);
774
775 fx_playback_audio_processor_mutex = AGS_RECALL_GET_OBJ_MUTEX(fx_playback_audio_processor);
776
777 recall_id = NULL;
778
779 sound_scope = ags_recall_get_sound_scope(recall);
780
781 g_object_get(recall,
782 "recall-id", &recall_id,
783 NULL);
784
785 if(!ags_recall_id_check_sound_scope(recall_id, sound_scope)){
786 if(recall_id != NULL){
787 g_object_unref(recall_id);
788 }
789
790 AGS_RECALL_CLASS(ags_fx_playback_audio_processor_parent_class)->run_inter(recall);
791
792 return;
793 }
794
795 recycling_context = NULL;
796 parent_recycling_context = NULL;
797
798 g_object_get(recall_id,
799 "recycling-context", &recycling_context,
800 NULL);
801
802 g_object_get(recycling_context,
803 "parent", &parent_recycling_context,
804 NULL);
805
806 /* get delay counter */
807 g_rec_mutex_lock(fx_playback_audio_processor_mutex);
808
809 fx_playback_audio_processor->delay_counter = fx_playback_audio_processor->current_delay_counter;
810 fx_playback_audio_processor->offset_counter = fx_playback_audio_processor->current_offset_counter;
811
812 fx_playback_audio_processor->x_offset = fx_playback_audio_processor->current_x_offset;
813
814 delay_counter = fx_playback_audio_processor->delay_counter;
815
816 g_rec_mutex_unlock(fx_playback_audio_processor_mutex);
817
818 /* run */
819 g_rec_mutex_lock(fx_playback_audio_processor_mutex);
820
821 start_playing_audio_signal = g_list_copy_deep(fx_playback_audio_processor->playing_audio_signal,
822 (GCopyFunc) g_object_ref,
823 NULL);
824
825 start_recording_audio_signal = g_list_copy_deep(fx_playback_audio_processor->recording_audio_signal,
826 (GCopyFunc) g_object_ref,
827 NULL);
828
829 g_rec_mutex_unlock(fx_playback_audio_processor_mutex);
830
831 /* clear playing audio signal */
832 playing_audio_signal = start_playing_audio_signal;
833
834 while(playing_audio_signal != NULL){
835 AgsAudioSignal *audio_signal;
836
837 guint buffer_size;
838 guint format;
839
840 GRecMutex *stream_mutex;
841
842 audio_signal = AGS_AUDIO_SIGNAL(playing_audio_signal->data);
843
844 stream_mutex = AGS_AUDIO_SIGNAL_GET_STREAM_MUTEX(audio_signal);
845
846 g_object_get(audio_signal,
847 "buffer-size", &buffer_size,
848 "format", &format,
849 NULL);
850
851 g_rec_mutex_lock(stream_mutex);
852
853 ags_audio_buffer_util_clear_buffer(audio_signal->stream_current->data, 1,
854 buffer_size, ags_audio_buffer_util_format_from_soundcard(format));
855
856
857 g_rec_mutex_unlock(stream_mutex);
858
859 playing_audio_signal = playing_audio_signal->next;
860 }
861
862 /* clear recording audio signal */
863 recording_audio_signal = start_recording_audio_signal;
864
865 while(recording_audio_signal != NULL){
866 AgsAudioSignal *audio_signal;
867
868 guint buffer_size;
869 guint format;
870
871 GRecMutex *stream_mutex;
872
873 audio_signal = AGS_AUDIO_SIGNAL(recording_audio_signal->data);
874
875 stream_mutex = AGS_AUDIO_SIGNAL_GET_STREAM_MUTEX(audio_signal);
876
877 g_object_get(audio_signal,
878 "buffer-size", &buffer_size,
879 "format", &format,
880 NULL);
881
882 g_rec_mutex_lock(stream_mutex);
883
884 ags_audio_buffer_util_clear_buffer(audio_signal->stream_current->data, 1,
885 buffer_size, ags_audio_buffer_util_format_from_soundcard(format));
886
887
888 g_rec_mutex_unlock(stream_mutex);
889
890 recording_audio_signal = recording_audio_signal->next;
891 }
892
893 /* play/record/feed/master */
894 if(ags_recall_id_check_sound_scope(recall_id, AGS_SOUND_SCOPE_WAVE)){
895 if(parent_recycling_context != NULL){
896 ags_fx_playback_audio_processor_play(fx_playback_audio_processor);
897 }
898 }
899
900 if(ags_recall_id_check_sound_scope(recall_id, AGS_SOUND_SCOPE_WAVE)){
901 if(parent_recycling_context != NULL){
902 ags_fx_playback_audio_processor_record(fx_playback_audio_processor);
903 }
904 }
905
906 if(ags_recall_id_check_sound_scope(recall_id, AGS_SOUND_SCOPE_PLAYBACK) ||
907 ags_recall_id_check_sound_scope(recall_id, AGS_SOUND_SCOPE_MIDI)){
908 if(parent_recycling_context == NULL){
909 ags_fx_playback_audio_processor_feed(fx_playback_audio_processor);
910 }
911 }
912
913 if(ags_recall_id_check_sound_scope(recall_id, AGS_SOUND_SCOPE_SEQUENCER) ||
914 ags_recall_id_check_sound_scope(recall_id, AGS_SOUND_SCOPE_NOTATION) ||
915 ags_recall_id_check_sound_scope(recall_id, AGS_SOUND_SCOPE_MIDI)){
916 if(parent_recycling_context == NULL){
917 ags_fx_playback_audio_processor_master(fx_playback_audio_processor);
918 }
919 }
920
921 /* counter change */
922 ags_fx_playback_audio_processor_counter_change(fx_playback_audio_processor);
923
924 if(recall_id != NULL){
925 g_object_unref(recall_id);
926 }
927
928 if(recycling_context != NULL){
929 g_object_unref(recycling_context);
930 }
931
932 if(parent_recycling_context != NULL){
933 g_object_unref(parent_recycling_context);
934 }
935
936 g_list_free_full(start_playing_audio_signal,
937 (GDestroyNotify) g_object_unref);
938
939 g_list_free_full(start_recording_audio_signal,
940 (GDestroyNotify) g_object_unref);
941
942 /* call parent */
943 AGS_RECALL_CLASS(ags_fx_playback_audio_processor_parent_class)->run_inter(recall);
944 }
945
946 void
ags_fx_playback_audio_processor_real_data_put(AgsFxPlaybackAudioProcessor * fx_playback_audio_processor,AgsBuffer * buffer,guint data_mode)947 ags_fx_playback_audio_processor_real_data_put(AgsFxPlaybackAudioProcessor *fx_playback_audio_processor,
948 AgsBuffer *buffer,
949 guint data_mode)
950 {
951 AgsAudioSignal *current_audio_signal;
952 AgsRecallID *recall_id;
953 AgsFxPlaybackAudio *fx_playback_audio;
954
955 GList *start_audio_signal, *audio_signal;
956
957 gpointer buffer_data;
958
959 guint buffer_x_offset, x_offset;
960 guint buffer_samplerate, samplerate;
961 guint buffer_buffer_size, buffer_size;
962 guint buffer_format, format;
963 guint copy_mode;
964 guint attack;
965 gboolean do_resample;
966
967 GRecMutex *fx_playback_audio_processor_mutex;
968 GRecMutex *buffer_mutex;
969 GRecMutex *stream_mutex;
970
971 fx_playback_audio_processor_mutex = AGS_RECALL_GET_OBJ_MUTEX(fx_playback_audio_processor);
972
973 samplerate = AGS_SOUNDCARD_DEFAULT_SAMPLERATE;
974 buffer_size = AGS_SOUNDCARD_DEFAULT_BUFFER_SIZE;
975 format = AGS_SOUNDCARD_DEFAULT_FORMAT;
976
977 g_object_get(fx_playback_audio_processor,
978 "recall-id", &recall_id,
979 "samplerate", &samplerate,
980 "buffer-size", &buffer_size,
981 "format", &format,
982 NULL);
983
984 buffer_samplerate = AGS_SOUNDCARD_DEFAULT_SAMPLERATE;
985 buffer_buffer_size = AGS_SOUNDCARD_DEFAULT_BUFFER_SIZE;
986 buffer_format = AGS_SOUNDCARD_DEFAULT_FORMAT;
987
988 g_object_get(buffer,
989 "x", &buffer_x_offset,
990 "samplerate", &buffer_samplerate,
991 "buffer-size", &buffer_buffer_size,
992 "format", &buffer_format,
993 NULL);
994
995 /* get audio signal */
996 current_audio_signal = NULL;
997
998 start_audio_signal = NULL;
999
1000 g_rec_mutex_lock(fx_playback_audio_processor_mutex);
1001
1002 x_offset = fx_playback_audio_processor->x_offset;
1003
1004 if(data_mode == AGS_FX_PLAYBACK_AUDIO_PROCESSOR_DATA_MODE_PLAY){
1005 start_audio_signal = fx_playback_audio_processor->playing_audio_signal;
1006 }else if(data_mode == AGS_FX_PLAYBACK_AUDIO_PROCESSOR_DATA_MODE_RECORD){
1007 start_audio_signal = fx_playback_audio_processor->recording_audio_signal;
1008 }
1009
1010 audio_signal = ags_audio_signal_find_by_recall_id(start_audio_signal, (GObject *) recall_id);
1011
1012 if(audio_signal != NULL){
1013 current_audio_signal = audio_signal->data;
1014 g_object_ref(current_audio_signal);
1015 }
1016
1017 g_rec_mutex_unlock(fx_playback_audio_processor_mutex);
1018
1019 /* create audio signal */
1020 if(current_audio_signal == NULL){
1021 AgsAudio *audio;
1022 AgsChannel *start_input, *input;
1023 AgsRecycling *recycling;
1024 AgsPort *port;
1025
1026 GObject *output_soundcard;
1027
1028 guint audio_channel;
1029 gdouble delay;
1030
1031 GValue value = {0,};
1032
1033 output_soundcard = NULL;
1034
1035 audio = NULL;
1036
1037 recall_id = NULL;
1038
1039 fx_playback_audio = NULL;
1040
1041 audio_channel = 0;
1042
1043 g_object_get(fx_playback_audio_processor,
1044 "output-soundcard", &output_soundcard,
1045 "audio", &audio,
1046 "recall-id", &recall_id,
1047 "recall-audio", &fx_playback_audio,
1048 "audio-channel", &audio_channel,
1049 NULL);
1050
1051 start_input = NULL;
1052
1053 g_object_get(audio,
1054 "input", &start_input,
1055 NULL);
1056
1057 input = ags_channel_nth(start_input, audio_channel);
1058
1059 recycling = NULL;
1060
1061 if(input != NULL){
1062 g_object_get(input,
1063 "first-recycling", &recycling,
1064 NULL);
1065 }
1066
1067 /* get delay */
1068 delay = AGS_SOUNDCARD_DEFAULT_DELAY;
1069
1070 if(fx_playback_audio != NULL){
1071 port = NULL;
1072
1073 g_object_get(fx_playback_audio,
1074 "delay", &port,
1075 NULL);
1076
1077 if(port != NULL){
1078 g_value_init(&value,
1079 G_TYPE_DOUBLE);
1080
1081 ags_port_safe_read(port,
1082 &value);
1083
1084 delay = g_value_get_double(&value);
1085 g_value_unset(&value);
1086
1087 g_object_unref(port);
1088 }
1089 }
1090
1091 current_audio_signal = ags_audio_signal_new(output_soundcard,
1092 (GObject *) recycling,
1093 (GObject *) recall_id);
1094 g_object_ref(current_audio_signal);
1095
1096 g_object_set(current_audio_signal,
1097 "samplerate", samplerate,
1098 "buffer-size", buffer_size,
1099 "format", format,
1100 NULL);
1101
1102 ags_audio_signal_stream_resize(current_audio_signal,
1103 2);
1104 current_audio_signal->stream_current = current_audio_signal->stream;
1105
1106 g_rec_mutex_lock(fx_playback_audio_processor_mutex);
1107
1108 if(data_mode == AGS_FX_PLAYBACK_AUDIO_PROCESSOR_DATA_MODE_PLAY){
1109 fx_playback_audio_processor->playing_audio_signal = g_list_prepend(fx_playback_audio_processor->playing_audio_signal,
1110 current_audio_signal);
1111 }else if(data_mode == AGS_FX_PLAYBACK_AUDIO_PROCESSOR_DATA_MODE_RECORD){
1112 fx_playback_audio_processor->recording_audio_signal = g_list_prepend(fx_playback_audio_processor->recording_audio_signal,
1113 current_audio_signal);
1114 }
1115
1116 g_rec_mutex_unlock(fx_playback_audio_processor_mutex);
1117
1118 ags_connectable_connect(AGS_CONNECTABLE(current_audio_signal));
1119 ags_recycling_add_audio_signal(recycling,
1120 current_audio_signal);
1121
1122 if(output_soundcard != NULL){
1123 g_object_unref(output_soundcard);
1124 }
1125
1126 if(audio != NULL){
1127 g_object_unref(audio);
1128 }
1129
1130 if(start_input != NULL){
1131 g_object_unref(start_input);
1132 }
1133
1134 if(input != NULL){
1135 g_object_unref(input);
1136 }
1137
1138 if(recycling != NULL){
1139 g_object_unref(recycling);
1140 }
1141
1142 if(fx_playback_audio != NULL){
1143 g_object_unref(fx_playback_audio);
1144 }
1145 }
1146
1147 buffer_mutex = AGS_BUFFER_GET_OBJ_MUTEX(buffer);
1148 stream_mutex = AGS_AUDIO_SIGNAL_GET_STREAM_MUTEX(current_audio_signal);
1149
1150 copy_mode = ags_audio_buffer_util_get_copy_mode(ags_audio_buffer_util_format_from_soundcard(format),
1151 ags_audio_buffer_util_format_from_soundcard(buffer_format));
1152
1153 do_resample = FALSE;
1154
1155 if(samplerate != buffer_samplerate){
1156 do_resample = TRUE;
1157
1158 buffer_data = ags_stream_alloc(buffer_size,
1159 buffer_format);
1160
1161 g_rec_mutex_lock(buffer_mutex);
1162
1163 ags_audio_buffer_util_resample_with_buffer(buffer->data, 1,
1164 buffer_format, buffer_samplerate,
1165 buffer_buffer_size,
1166 samplerate,
1167 buffer_size,
1168 buffer_data);
1169
1170 g_rec_mutex_unlock(buffer_mutex);
1171
1172 g_rec_mutex_lock(stream_mutex);
1173
1174 if(x_offset < buffer_x_offset){
1175 attack = (samplerate / buffer_samplerate) * (buffer_x_offset - x_offset);
1176
1177 ags_audio_buffer_util_copy_buffer_to_buffer(current_audio_signal->stream_current->data, 1, attack,
1178 buffer_data, 1, 0,
1179 buffer_size - attack, copy_mode);
1180 }else{
1181 attack = (samplerate / buffer_samplerate) * (x_offset - buffer_x_offset);
1182
1183 ags_audio_buffer_util_copy_buffer_to_buffer(current_audio_signal->stream_current->data, 1, 0,
1184 buffer_data, 1, attack,
1185 buffer_size - attack, copy_mode);
1186 }
1187
1188 g_rec_mutex_unlock(stream_mutex);
1189
1190 ags_stream_free(buffer_data);
1191 }else{
1192 g_rec_mutex_lock(buffer_mutex);
1193 g_rec_mutex_lock(stream_mutex);
1194
1195 if(x_offset < buffer_x_offset){
1196 attack = buffer_x_offset - x_offset;
1197
1198 ags_audio_buffer_util_copy_buffer_to_buffer(current_audio_signal->stream_current->data, 1, attack,
1199 buffer->data, 1, 0,
1200 buffer_size - attack, copy_mode);
1201 }else{
1202 attack = x_offset - buffer_x_offset;
1203
1204 ags_audio_buffer_util_copy_buffer_to_buffer(current_audio_signal->stream_current->data, 1, 0,
1205 buffer->data, 1, attack,
1206 buffer_size - attack, copy_mode);
1207 }
1208
1209 g_rec_mutex_unlock(stream_mutex);
1210 g_rec_mutex_unlock(buffer_mutex);
1211 }
1212
1213 /* unref */
1214 if(current_audio_signal != NULL){
1215 g_object_unref(current_audio_signal);
1216 }
1217
1218 if(recall_id != NULL){
1219 g_object_unref(recall_id);
1220 }
1221 }
1222
1223 void
ags_fx_playback_audio_processor_data_put(AgsFxPlaybackAudioProcessor * fx_playback_audio_processor,AgsBuffer * buffer,guint data_mode)1224 ags_fx_playback_audio_processor_data_put(AgsFxPlaybackAudioProcessor *fx_playback_audio_processor,
1225 AgsBuffer *buffer,
1226 guint data_mode)
1227 {
1228 g_return_if_fail(AGS_IS_FX_PLAYBACK_AUDIO_PROCESSOR(fx_playback_audio_processor));
1229
1230 g_object_ref(fx_playback_audio_processor);
1231
1232 if(AGS_FX_PLAYBACK_AUDIO_PROCESSOR_GET_CLASS(fx_playback_audio_processor)->data_put != NULL){
1233 AGS_FX_PLAYBACK_AUDIO_PROCESSOR_GET_CLASS(fx_playback_audio_processor)->data_put(fx_playback_audio_processor,
1234 buffer,
1235 data_mode);
1236 }
1237
1238 g_object_unref(fx_playback_audio_processor);
1239 }
1240
1241 void
ags_fx_playback_audio_processor_real_data_get(AgsFxPlaybackAudioProcessor * fx_playback_audio_processor,AgsBuffer * buffer,guint data_mode)1242 ags_fx_playback_audio_processor_real_data_get(AgsFxPlaybackAudioProcessor *fx_playback_audio_processor,
1243 AgsBuffer *buffer,
1244 guint data_mode)
1245 {
1246 //TODO:JK: implement me
1247 }
1248
1249 void
ags_fx_playback_audio_processor_data_get(AgsFxPlaybackAudioProcessor * fx_playback_audio_processor,AgsBuffer * buffer,guint data_mode)1250 ags_fx_playback_audio_processor_data_get(AgsFxPlaybackAudioProcessor *fx_playback_audio_processor,
1251 AgsBuffer *buffer,
1252 guint data_mode)
1253 {
1254 g_return_if_fail(AGS_IS_FX_PLAYBACK_AUDIO_PROCESSOR(fx_playback_audio_processor));
1255
1256 g_object_ref(fx_playback_audio_processor);
1257
1258 if(AGS_FX_PLAYBACK_AUDIO_PROCESSOR_GET_CLASS(fx_playback_audio_processor)->data_get != NULL){
1259 AGS_FX_PLAYBACK_AUDIO_PROCESSOR_GET_CLASS(fx_playback_audio_processor)->data_get(fx_playback_audio_processor,
1260 buffer,
1261 data_mode);
1262 }
1263
1264 g_object_unref(fx_playback_audio_processor);
1265 }
1266
1267 void
ags_fx_playback_audio_processor_real_play(AgsFxPlaybackAudioProcessor * fx_playback_audio_processor)1268 ags_fx_playback_audio_processor_real_play(AgsFxPlaybackAudioProcessor *fx_playback_audio_processor)
1269 {
1270 AgsAudio *audio;
1271
1272 AgsTimestamp *timestamp;
1273
1274 GList *start_wave, *wave;
1275
1276 guint audio_channel;
1277 guint64 relative_offset;
1278 guint64 x_offset;
1279 guint attack;
1280 guint samplerate;
1281 guint buffer_size;
1282 guint frame_count;
1283
1284 GRecMutex *fx_playback_audio_processor_mutex;
1285
1286 fx_playback_audio_processor_mutex = AGS_RECALL_GET_OBJ_MUTEX(fx_playback_audio_processor);
1287
1288 audio = NULL;
1289
1290 g_object_get(fx_playback_audio_processor,
1291 "audio", &audio,
1292 "audio-channel", &audio_channel,
1293 "samplerate", &samplerate,
1294 "buffer-size", &buffer_size,
1295 NULL);
1296
1297 g_rec_mutex_lock(fx_playback_audio_processor_mutex);
1298
1299 timestamp = fx_playback_audio_processor->timestamp;
1300
1301 x_offset = fx_playback_audio_processor->x_offset;
1302
1303 g_rec_mutex_unlock(fx_playback_audio_processor_mutex);
1304
1305 /* time stamp offset */
1306 relative_offset = AGS_WAVE_DEFAULT_BUFFER_LENGTH * samplerate;
1307
1308 ags_timestamp_set_ags_offset(timestamp,
1309 (guint64) (relative_offset * floor((double) x_offset / (double) relative_offset)));
1310
1311 attack = (x_offset % relative_offset) % buffer_size;
1312
1313 frame_count = buffer_size - attack;
1314
1315 if(x_offset + frame_count > relative_offset * floor(x_offset / relative_offset) + relative_offset){
1316 frame_count = relative_offset * floor((x_offset + frame_count) / relative_offset) - x_offset;
1317 }
1318
1319 /* find wave - attempt #0 */
1320 start_wave = NULL;
1321
1322 g_object_get(audio,
1323 "wave", &start_wave,
1324 NULL);
1325
1326 wave = ags_wave_find_near_timestamp(start_wave, audio_channel,
1327 timestamp);
1328
1329 if(wave != NULL){
1330 AgsBuffer *buffer;
1331
1332 buffer = ags_wave_find_point(wave->data,
1333 x_offset,
1334 FALSE);
1335
1336 if(buffer != NULL){
1337 ags_fx_playback_audio_processor_data_put(fx_playback_audio_processor,
1338 buffer,
1339 AGS_FX_PLAYBACK_AUDIO_PROCESSOR_DATA_MODE_PLAY);
1340 }
1341 }
1342
1343 /* find wave - attempt #1 */
1344 if(attack != 0 ||
1345 frame_count != buffer_size){
1346 ags_timestamp_set_ags_offset(timestamp,
1347 (guint64) (relative_offset * floor((double) (x_offset + frame_count) / (double) relative_offset)));
1348
1349 wave = ags_wave_find_near_timestamp(start_wave, audio_channel,
1350 timestamp);
1351
1352 if(wave != NULL){
1353 AgsBuffer *buffer;
1354
1355 buffer = ags_wave_find_point(wave->data,
1356 x_offset + frame_count,
1357 FALSE);
1358
1359 if(buffer != NULL){
1360 ags_fx_playback_audio_processor_data_put(fx_playback_audio_processor,
1361 buffer,
1362 AGS_FX_PLAYBACK_AUDIO_PROCESSOR_DATA_MODE_PLAY);
1363 }
1364 }
1365 }
1366
1367 /* unref */
1368 if(audio != NULL){
1369 g_object_unref(audio);
1370 }
1371
1372 g_list_free_full(start_wave,
1373 (GDestroyNotify) g_object_unref);
1374 }
1375
1376 void
ags_fx_playback_audio_processor_play(AgsFxPlaybackAudioProcessor * fx_playback_audio_processor)1377 ags_fx_playback_audio_processor_play(AgsFxPlaybackAudioProcessor *fx_playback_audio_processor)
1378 {
1379 g_return_if_fail(AGS_IS_FX_PLAYBACK_AUDIO_PROCESSOR(fx_playback_audio_processor));
1380
1381 g_object_ref(fx_playback_audio_processor);
1382
1383 if(AGS_FX_PLAYBACK_AUDIO_PROCESSOR_GET_CLASS(fx_playback_audio_processor)->play != NULL){
1384 AGS_FX_PLAYBACK_AUDIO_PROCESSOR_GET_CLASS(fx_playback_audio_processor)->play(fx_playback_audio_processor);
1385 }
1386
1387 g_object_unref(fx_playback_audio_processor);
1388 }
1389
1390 void
ags_fx_playback_audio_processor_real_record(AgsFxPlaybackAudioProcessor * fx_playback_audio_processor)1391 ags_fx_playback_audio_processor_real_record(AgsFxPlaybackAudioProcessor *fx_playback_audio_processor)
1392 {
1393 AgsAudio *audio;
1394 AgsChannel *start_input, *input;
1395 AgsPort *port;
1396 AgsWave *current_wave;
1397 AgsBuffer *buffer;
1398 AgsFxPlaybackAudio *fx_playback_audio;
1399 AgsRecallID *recall_id;
1400
1401 AgsTimestamp *timestamp;
1402
1403 GObject *output_soundcard, *input_soundcard;
1404
1405 GList *start_wave, *wave;
1406
1407 gpointer data, file_data;
1408
1409 guint audio_channels;
1410 guint audio_channel;
1411 gint input_soundcard_channel;
1412 guint64 relative_offset;
1413 guint64 x_offset;
1414 guint64 x_buffer_offset_0, x_buffer_offset_1;
1415 guint attack;
1416 guint samplerate, target_samplerate, file_samplerate;
1417 guint buffer_size, target_buffer_size, file_buffer_size;
1418 guint format, target_format, file_format;
1419 guint frame_count;
1420 guint target_copy_mode, file_copy_mode;
1421 guint capture_mode;
1422 gboolean create_wave;
1423 gboolean found_buffer;
1424
1425 GValue value = {0,};
1426
1427 GRecMutex *fx_playback_audio_processor_mutex;
1428 GRecMutex *buffer_mutex;
1429
1430 fx_playback_audio_processor_mutex = AGS_RECALL_GET_OBJ_MUTEX(fx_playback_audio_processor);
1431
1432 audio = NULL;
1433
1434 output_soundcard = NULL;
1435 input_soundcard = NULL;
1436
1437 fx_playback_audio = NULL;
1438
1439 recall_id = NULL;
1440
1441 audio_channel = 0;
1442
1443 g_object_get(fx_playback_audio_processor,
1444 "audio", &audio,
1445 "output-soundcard", &output_soundcard,
1446 "recall-audio", &fx_playback_audio,
1447 "audio-channel", &audio_channel,
1448 "recall-id", &recall_id,
1449 NULL);
1450
1451 audio_channels = AGS_SOUNDCARD_DEFAULT_PCM_CHANNELS;
1452 samplerate = AGS_SOUNDCARD_DEFAULT_SAMPLERATE;
1453 buffer_size = AGS_SOUNDCARD_DEFAULT_BUFFER_SIZE;
1454 format = AGS_SOUNDCARD_DEFAULT_FORMAT;
1455
1456 if(input_soundcard != NULL){
1457 ags_soundcard_get_presets(AGS_SOUNDCARD(input_soundcard),
1458 &audio_channels,
1459 &samplerate,
1460 &buffer_size,
1461 &format);
1462 }
1463
1464 start_wave = NULL;
1465
1466 start_input = NULL;
1467
1468 g_object_get(audio,
1469 "wave", &start_wave,
1470 "input", &start_input,
1471 "samplerate", &target_samplerate,
1472 "buffer-size", &target_buffer_size,
1473 "format", &target_format,
1474 NULL);
1475
1476 input = ags_channel_nth(start_input,
1477 audio_channel);
1478
1479 input_soundcard_channel = -1;
1480
1481 g_object_get(input,
1482 "input-soundcard", &input_soundcard,
1483 "input-soundcard-channel", &input_soundcard_channel,
1484 NULL);
1485
1486 g_rec_mutex_lock(fx_playback_audio_processor_mutex);
1487
1488 timestamp = fx_playback_audio_processor->timestamp;
1489
1490 x_offset = fx_playback_audio_processor->x_offset;
1491
1492 g_rec_mutex_unlock(fx_playback_audio_processor_mutex);
1493
1494 /* time stamp offset */
1495 relative_offset = AGS_WAVE_DEFAULT_BUFFER_LENGTH * target_samplerate;
1496
1497 ags_timestamp_set_ags_offset(timestamp,
1498 (guint64) (relative_offset * floor((double) x_offset / (double) relative_offset)));
1499
1500 attack = (x_offset % relative_offset) % target_buffer_size;
1501
1502 frame_count = target_buffer_size - attack;
1503
1504 create_wave = FALSE;
1505
1506 if(x_offset + frame_count > relative_offset * floor(x_offset / relative_offset) + relative_offset){
1507 frame_count = relative_offset * floor((x_offset + frame_count) / relative_offset) - x_offset;
1508
1509 create_wave = TRUE;
1510 }else if(x_offset + frame_count == relative_offset * floor(x_offset / relative_offset) + relative_offset){
1511 create_wave = TRUE;
1512 }
1513
1514 /* capture mode */
1515 capture_mode = AGS_FX_PLAYBACK_AUDIO_CAPTURE_MODE_NONE;
1516
1517 if(fx_playback_audio != NULL){
1518 g_object_get(fx_playback_audio,
1519 "capture-mode", &port,
1520 NULL);
1521
1522 if(port != NULL){
1523 g_value_init(&value, G_TYPE_UINT64);
1524
1525 ags_port_safe_read(port, &value);
1526
1527 capture_mode = g_value_get_uint64(&value);
1528
1529 g_object_unref(port);
1530
1531 g_value_unset(&value);
1532 }
1533 }
1534
1535 if(capture_mode == AGS_FX_PLAYBACK_AUDIO_CAPTURE_MODE_DISCARD){
1536 //empty
1537 }else if(capture_mode == AGS_FX_PLAYBACK_AUDIO_CAPTURE_MODE_NONE){
1538 AgsAudioSignal *current_audio_signal;
1539
1540 GList *start_audio_signal, *audio_signal;
1541
1542 GRecMutex *stream_mutex;
1543
1544 /* get audio signal */
1545 current_audio_signal = NULL;
1546
1547 start_audio_signal = NULL;
1548
1549 g_rec_mutex_lock(fx_playback_audio_processor_mutex);
1550
1551 start_audio_signal = fx_playback_audio_processor->capture_audio_signal;
1552
1553 audio_signal = ags_audio_signal_find_by_recall_id(start_audio_signal, (GObject *) recall_id);
1554
1555 if(audio_signal != NULL){
1556 current_audio_signal = audio_signal->data;
1557 g_object_ref(current_audio_signal);
1558 }
1559
1560 g_rec_mutex_unlock(fx_playback_audio_processor_mutex);
1561
1562 /* create audio signal */
1563 if(current_audio_signal == NULL){
1564 AgsChannel *start_input, *input;
1565 AgsRecycling *recycling;
1566
1567 gdouble delay;
1568
1569 GValue value = {0,};
1570
1571 start_input = NULL;
1572
1573 g_object_get(audio,
1574 "input", &start_input,
1575 NULL);
1576
1577 input = ags_channel_nth(start_input, audio_channel);
1578
1579 recycling = NULL;
1580
1581 if(input != NULL){
1582 g_object_get(input,
1583 "first-recycling", &recycling,
1584 NULL);
1585 }
1586
1587 /* get delay */
1588 delay = AGS_SOUNDCARD_DEFAULT_DELAY;
1589
1590 if(fx_playback_audio != NULL){
1591 port = NULL;
1592
1593 g_object_get(fx_playback_audio,
1594 "delay", &port,
1595 NULL);
1596
1597 if(port != NULL){
1598 g_value_init(&value,
1599 G_TYPE_DOUBLE);
1600
1601 ags_port_safe_read(port,
1602 &value);
1603
1604 delay = g_value_get_double(&value);
1605 g_value_unset(&value);
1606
1607 g_object_unref(port);
1608 }
1609 }
1610
1611 current_audio_signal = ags_audio_signal_new(output_soundcard,
1612 (GObject *) recycling,
1613 (GObject *) recall_id);
1614 g_object_ref(current_audio_signal);
1615
1616 g_object_set(current_audio_signal,
1617 "samplerate", target_samplerate,
1618 "buffer-size", target_buffer_size,
1619 "format", target_format,
1620 NULL);
1621
1622 ags_audio_signal_stream_resize(current_audio_signal,
1623 2);
1624 current_audio_signal->stream_current = current_audio_signal->stream;
1625
1626 g_rec_mutex_lock(fx_playback_audio_processor_mutex);
1627
1628 fx_playback_audio_processor->capture_audio_signal = g_list_prepend(fx_playback_audio_processor->capture_audio_signal,
1629 current_audio_signal);
1630
1631 g_rec_mutex_unlock(fx_playback_audio_processor_mutex);
1632
1633 ags_connectable_connect(AGS_CONNECTABLE(current_audio_signal));
1634 ags_recycling_add_audio_signal(recycling,
1635 current_audio_signal);
1636
1637 if(start_input != NULL){
1638 g_object_unref(start_input);
1639 }
1640
1641 if(input != NULL){
1642 g_object_unref(input);
1643 }
1644
1645 if(recycling != NULL){
1646 g_object_unref(recycling);
1647 }
1648 }
1649
1650 target_copy_mode = ags_audio_buffer_util_get_copy_mode(ags_audio_buffer_util_format_from_soundcard(target_format),
1651 ags_audio_buffer_util_format_from_soundcard(format));
1652
1653 if(input_soundcard != NULL){
1654 stream_mutex = AGS_AUDIO_SIGNAL_GET_STREAM_MUTEX(current_audio_signal);
1655
1656 data = ags_soundcard_get_prev_buffer(AGS_SOUNDCARD(input_soundcard));
1657
1658 g_rec_mutex_lock(stream_mutex);
1659 ags_soundcard_lock_buffer(AGS_SOUNDCARD(input_soundcard), data);
1660
1661 ags_audio_buffer_util_clear_buffer(current_audio_signal->stream_current->data, 1,
1662 target_buffer_size, ags_audio_buffer_util_format_from_soundcard(target_format));
1663
1664 ags_audio_buffer_util_copy_buffer_to_buffer(current_audio_signal->stream_current->data, 1, 0,
1665 data, audio_channels, input_soundcard_channel,
1666 target_buffer_size, target_copy_mode);
1667
1668 ags_soundcard_unlock_buffer(AGS_SOUNDCARD(input_soundcard), data);
1669 g_rec_mutex_unlock(stream_mutex);
1670 }
1671
1672 /* unref */
1673 if(current_audio_signal != NULL){
1674 g_object_unref(current_audio_signal);
1675 }
1676 }else{
1677 /* find wave - attempt #0 */
1678 current_wave = NULL;
1679
1680 wave = ags_wave_find_near_timestamp(start_wave, audio_channel,
1681 timestamp);
1682
1683 buffer = NULL;
1684
1685 x_buffer_offset_0 = x_offset - attack;
1686
1687 found_buffer = FALSE;
1688
1689 if(wave == NULL){
1690 AgsTimestamp *current_timestamp;
1691
1692 /* instantiate */
1693 current_wave = ags_wave_new((GObject *) audio,
1694 audio_channel);
1695
1696 g_object_get(current_wave,
1697 "timestamp", ¤t_timestamp,
1698 NULL);
1699 ags_timestamp_set_ags_offset(current_timestamp,
1700 ags_timestamp_get_ags_offset(timestamp));
1701
1702 ags_audio_add_wave(audio,
1703 (GObject *) current_wave);
1704
1705 g_object_unref(current_timestamp);
1706 }else{
1707 current_wave = wave->data;
1708
1709 buffer = ags_wave_find_point(current_wave,
1710 x_buffer_offset_0,
1711 FALSE);
1712 }
1713
1714 if(buffer == NULL){
1715 /* instantiate buffer */
1716 buffer = ags_buffer_new();
1717 buffer->x = x_buffer_offset_0;
1718
1719 ags_wave_add_buffer(current_wave,
1720 buffer,
1721 FALSE);
1722 }else{
1723 found_buffer = TRUE;
1724 }
1725
1726 /* record */
1727 data = NULL;
1728
1729 target_copy_mode = ags_audio_buffer_util_get_copy_mode(ags_audio_buffer_util_format_from_soundcard(target_format),
1730 ags_audio_buffer_util_format_from_soundcard(format));
1731
1732 if(input_soundcard != NULL){
1733 buffer_mutex = AGS_BUFFER_GET_OBJ_MUTEX(buffer);
1734
1735 data = ags_soundcard_get_prev_buffer(AGS_SOUNDCARD(input_soundcard));
1736
1737 g_rec_mutex_lock(buffer_mutex);
1738 ags_soundcard_lock_buffer(AGS_SOUNDCARD(input_soundcard), data);
1739
1740 if(found_buffer &&
1741 capture_mode == AGS_FX_PLAYBACK_AUDIO_CAPTURE_MODE_REPLACE){
1742 void *data;
1743
1744 data = buffer->data;
1745
1746 switch(target_format){
1747 case AGS_SOUNDCARD_SIGNED_8_BIT:
1748 data = ((gint8 *) data) + attack;
1749 break;
1750 case AGS_SOUNDCARD_SIGNED_16_BIT:
1751 data = ((gint16 *) data) + attack;
1752 break;
1753 case AGS_SOUNDCARD_SIGNED_24_BIT:
1754 data = ((gint32 *) data) + attack;
1755 break;
1756 case AGS_SOUNDCARD_SIGNED_32_BIT:
1757 data = ((gint32 *) data) + attack;
1758 break;
1759 case AGS_SOUNDCARD_SIGNED_64_BIT:
1760 data = ((gint64 *) data) + attack;
1761 break;
1762 case AGS_SOUNDCARD_FLOAT:
1763 data = ((gfloat *) data) + attack;
1764 break;
1765 case AGS_SOUNDCARD_DOUBLE:
1766 data = ((gdouble *) data) + attack;
1767 break;
1768 case AGS_SOUNDCARD_COMPLEX:
1769 data = ((AgsComplex *) data) + attack;
1770 break;
1771 }
1772
1773 ags_audio_buffer_util_clear_buffer(data, 1,
1774 frame_count, ags_audio_buffer_util_format_from_soundcard(target_format));
1775 }
1776
1777 ags_audio_buffer_util_copy_buffer_to_buffer(buffer->data, 1, attack,
1778 data, audio_channels, input_soundcard_channel,
1779 frame_count, target_copy_mode);
1780
1781 ags_soundcard_unlock_buffer(AGS_SOUNDCARD(input_soundcard), data);
1782 g_rec_mutex_unlock(buffer_mutex);
1783
1784 /* data put */
1785 ags_fx_playback_audio_processor_data_put(fx_playback_audio_processor,
1786 buffer,
1787 AGS_FX_PLAYBACK_AUDIO_PROCESSOR_DATA_MODE_PLAY);
1788 }
1789
1790 /* find wave - attempt #1 */
1791 if(attack != 0 ||
1792 frame_count != target_buffer_size){
1793 ags_timestamp_set_ags_offset(timestamp,
1794 (guint64) (relative_offset * floor((double) (x_offset + frame_count) / (double) relative_offset)));
1795
1796 wave = ags_wave_find_near_timestamp(start_wave, audio_channel,
1797 timestamp);
1798
1799 buffer = NULL;
1800
1801 x_buffer_offset_1 = x_offset + frame_count;
1802
1803 found_buffer = FALSE;
1804
1805 if(wave == NULL){
1806 AgsTimestamp *current_timestamp;
1807
1808 /* instantiate */
1809 current_wave = ags_wave_new((GObject *) audio,
1810 audio_channel);
1811
1812 g_object_get(current_wave,
1813 "timestamp", ¤t_timestamp,
1814 NULL);
1815 ags_timestamp_set_ags_offset(current_timestamp,
1816 ags_timestamp_get_ags_offset(timestamp));
1817
1818 ags_audio_add_wave(audio,
1819 (GObject *) current_wave);
1820
1821 g_object_unref(current_timestamp);
1822 }else{
1823 current_wave = wave->data;
1824
1825 buffer = ags_wave_find_point(current_wave,
1826 x_buffer_offset_1,
1827 FALSE);
1828 }
1829
1830 if(buffer == NULL){
1831 /* instantiate buffer */
1832 buffer = ags_buffer_new();
1833 buffer->x = x_buffer_offset_1;
1834
1835 ags_wave_add_buffer(current_wave,
1836 buffer,
1837 FALSE);
1838 }else{
1839 found_buffer = TRUE;
1840 }
1841
1842 /* record */
1843 if(input_soundcard != NULL){
1844 buffer_mutex = AGS_BUFFER_GET_OBJ_MUTEX(buffer);
1845
1846 g_rec_mutex_lock(buffer_mutex);
1847 ags_soundcard_lock_buffer(AGS_SOUNDCARD(input_soundcard), data);
1848
1849 if(found_buffer &&
1850 capture_mode == AGS_FX_PLAYBACK_AUDIO_CAPTURE_MODE_REPLACE){
1851 ags_audio_buffer_util_clear_buffer(buffer->data, 1,
1852 attack, ags_audio_buffer_util_format_from_soundcard(target_format));
1853 }
1854
1855 ags_audio_buffer_util_copy_buffer_to_buffer(buffer->data, 1, 0,
1856 data, audio_channels, (frame_count * audio_channels) + input_soundcard_channel,
1857 attack, target_copy_mode);
1858
1859 ags_soundcard_unlock_buffer(AGS_SOUNDCARD(input_soundcard), data);
1860 g_rec_mutex_unlock(buffer_mutex);
1861
1862 /* data put */
1863 ags_fx_playback_audio_processor_data_put(fx_playback_audio_processor,
1864 buffer,
1865 AGS_FX_PLAYBACK_AUDIO_PROCESSOR_DATA_MODE_PLAY);
1866 }
1867 }
1868 }
1869
1870 /* unref */
1871 if(output_soundcard != NULL){
1872 g_object_unref(output_soundcard);
1873 }
1874
1875 if(input_soundcard != NULL){
1876 g_object_unref(input_soundcard);
1877 }
1878
1879 if(audio != NULL){
1880 g_object_unref(audio);
1881 }
1882
1883 if(start_input != NULL){
1884 g_object_unref(start_input);
1885 }
1886
1887 if(input != NULL){
1888 g_object_unref(input);
1889 }
1890
1891 g_list_free_full(start_wave,
1892 (GDestroyNotify) g_object_unref);
1893
1894 if(fx_playback_audio != NULL){
1895 g_object_unref(fx_playback_audio);
1896 }
1897
1898 if(recall_id != NULL){
1899 g_object_unref(recall_id);
1900 }
1901 }
1902
1903 void
ags_fx_playback_audio_processor_record(AgsFxPlaybackAudioProcessor * fx_playback_audio_processor)1904 ags_fx_playback_audio_processor_record(AgsFxPlaybackAudioProcessor *fx_playback_audio_processor)
1905 {
1906 g_return_if_fail(AGS_IS_FX_PLAYBACK_AUDIO_PROCESSOR(fx_playback_audio_processor));
1907
1908 g_object_ref(fx_playback_audio_processor);
1909
1910 if(AGS_FX_PLAYBACK_AUDIO_PROCESSOR_GET_CLASS(fx_playback_audio_processor)->record != NULL){
1911 AGS_FX_PLAYBACK_AUDIO_PROCESSOR_GET_CLASS(fx_playback_audio_processor)->record(fx_playback_audio_processor);
1912 }
1913
1914 g_object_unref(fx_playback_audio_processor);
1915 }
1916
1917 void
ags_fx_playback_audio_processor_real_feed(AgsFxPlaybackAudioProcessor * fx_playback_audio_processor)1918 ags_fx_playback_audio_processor_real_feed(AgsFxPlaybackAudioProcessor *fx_playback_audio_processor)
1919 {
1920 AgsFxPlaybackAudio *fx_playback_audio;
1921
1922 GList *start_feed_audio_signal, *feed_audio_signal;
1923 GList *start_feeding_audio_signal, *feeding_audio_signal;
1924
1925 gboolean done;
1926
1927 GRecMutex *fx_playback_audio_processor_mutex;
1928
1929 fx_playback_audio_processor_mutex = AGS_RECALL_GET_OBJ_MUTEX(fx_playback_audio_processor);
1930
1931 fx_playback_audio = NULL;
1932
1933 g_object_get(fx_playback_audio_processor,
1934 "recall-audio", &fx_playback_audio,
1935 NULL);
1936
1937 done = FALSE;
1938
1939 /* get feed audio signal */
1940 feed_audio_signal =
1941 start_feed_audio_signal = ags_fx_playback_audio_get_feed_audio_signal(fx_playback_audio);
1942
1943 /* check new */
1944 while(feed_audio_signal != NULL){
1945 gboolean is_new;
1946
1947 g_rec_mutex_lock(fx_playback_audio_processor_mutex);
1948
1949 is_new = (g_list_find(fx_playback_audio_processor->feeding_audio_signal, feed_audio_signal->data) == NULL) ? TRUE: FALSE;
1950
1951 g_rec_mutex_unlock(fx_playback_audio_processor_mutex);
1952
1953 if(is_new){
1954 g_rec_mutex_lock(fx_playback_audio_processor_mutex);
1955
1956 fx_playback_audio_processor->feeding_audio_signal = g_list_prepend(fx_playback_audio_processor->feeding_audio_signal,
1957 feed_audio_signal->data);
1958
1959 g_rec_mutex_unlock(fx_playback_audio_processor_mutex);
1960
1961 g_object_ref(feed_audio_signal->data);
1962 }
1963
1964 feed_audio_signal = feed_audio_signal->next;
1965 }
1966
1967 /* check removed and update */
1968 g_rec_mutex_lock(fx_playback_audio_processor_mutex);
1969
1970 feeding_audio_signal =
1971 start_feeding_audio_signal = g_list_copy_deep(fx_playback_audio_processor->feeding_audio_signal,
1972 (GCopyFunc) g_object_ref,
1973 NULL);
1974
1975 g_rec_mutex_unlock(fx_playback_audio_processor_mutex);
1976
1977 while(feeding_audio_signal != NULL){
1978 gboolean is_removed;
1979
1980 is_removed = (g_list_find(start_feed_audio_signal, feeding_audio_signal->data) == NULL) ? TRUE: FALSE;
1981
1982 if(is_removed){
1983 g_rec_mutex_lock(fx_playback_audio_processor_mutex);
1984
1985 fx_playback_audio_processor->feeding_audio_signal = g_list_remove(fx_playback_audio_processor->feeding_audio_signal,
1986 feeding_audio_signal->data);
1987
1988 done = (fx_playback_audio_processor->feeding_audio_signal == NULL) ? TRUE: FALSE;
1989
1990 g_object_unref(feeding_audio_signal->data);
1991
1992 g_rec_mutex_unlock(fx_playback_audio_processor_mutex);
1993 }
1994
1995 feeding_audio_signal = feeding_audio_signal->next;
1996 }
1997
1998 if(done){
1999 ags_recall_done((AgsRecall *) fx_playback_audio_processor);
2000 }
2001
2002 if(fx_playback_audio != NULL){
2003 g_object_unref(fx_playback_audio);
2004 }
2005
2006 g_list_free_full(start_feed_audio_signal,
2007 (GDestroyNotify) g_object_unref);
2008
2009 g_list_free_full(start_feeding_audio_signal,
2010 (GDestroyNotify) g_object_unref);
2011 }
2012
2013 void
ags_fx_playback_audio_processor_feed(AgsFxPlaybackAudioProcessor * fx_playback_audio_processor)2014 ags_fx_playback_audio_processor_feed(AgsFxPlaybackAudioProcessor *fx_playback_audio_processor)
2015 {
2016 g_return_if_fail(AGS_IS_FX_PLAYBACK_AUDIO_PROCESSOR(fx_playback_audio_processor));
2017
2018 g_object_ref(fx_playback_audio_processor);
2019
2020 if(AGS_FX_PLAYBACK_AUDIO_PROCESSOR_GET_CLASS(fx_playback_audio_processor)->feed != NULL){
2021 AGS_FX_PLAYBACK_AUDIO_PROCESSOR_GET_CLASS(fx_playback_audio_processor)->feed(fx_playback_audio_processor);
2022 }
2023
2024 g_object_unref(fx_playback_audio_processor);
2025 }
2026
2027 void
ags_fx_playback_audio_processor_real_master(AgsFxPlaybackAudioProcessor * fx_playback_audio_processor)2028 ags_fx_playback_audio_processor_real_master(AgsFxPlaybackAudioProcessor *fx_playback_audio_processor)
2029 {
2030 AgsFxPlaybackAudio *fx_playback_audio;
2031
2032 GList *start_master_audio_signal, *master_audio_signal;
2033 GList *start_mastering_audio_signal, *mastering_audio_signal;
2034
2035 gboolean done;
2036
2037 GRecMutex *fx_playback_audio_processor_mutex;
2038
2039 fx_playback_audio_processor_mutex = AGS_RECALL_GET_OBJ_MUTEX(fx_playback_audio_processor);
2040
2041 fx_playback_audio = NULL;
2042
2043 g_object_get(fx_playback_audio_processor,
2044 "recall-audio", &fx_playback_audio,
2045 NULL);
2046
2047 done = FALSE;
2048
2049 /* get master audio signal */
2050 master_audio_signal =
2051 start_master_audio_signal = ags_fx_playback_audio_get_master_audio_signal(fx_playback_audio);
2052
2053 /* check new */
2054 while(master_audio_signal != NULL){
2055 gboolean is_new;
2056
2057 g_rec_mutex_lock(fx_playback_audio_processor_mutex);
2058
2059 is_new = (g_list_find(fx_playback_audio_processor->mastering_audio_signal, master_audio_signal->data) == NULL) ? TRUE: FALSE;
2060
2061 g_rec_mutex_unlock(fx_playback_audio_processor_mutex);
2062
2063 if(is_new){
2064 g_rec_mutex_lock(fx_playback_audio_processor_mutex);
2065
2066 fx_playback_audio_processor->mastering_audio_signal = g_list_prepend(fx_playback_audio_processor->mastering_audio_signal,
2067 master_audio_signal->data);
2068
2069 g_rec_mutex_unlock(fx_playback_audio_processor_mutex);
2070
2071 g_object_ref(master_audio_signal->data);
2072 }
2073
2074 master_audio_signal = master_audio_signal->next;
2075 }
2076
2077 /* check removed and update */
2078 g_rec_mutex_lock(fx_playback_audio_processor_mutex);
2079
2080 mastering_audio_signal =
2081 start_mastering_audio_signal = g_list_copy_deep(fx_playback_audio_processor->mastering_audio_signal,
2082 (GCopyFunc) g_object_ref,
2083 NULL);
2084
2085 g_rec_mutex_unlock(fx_playback_audio_processor_mutex);
2086
2087 while(mastering_audio_signal != NULL){
2088 gboolean is_removed;
2089
2090 is_removed = (g_list_find(start_master_audio_signal, mastering_audio_signal->data) == NULL) ? TRUE: FALSE;
2091
2092 if(is_removed){
2093 g_rec_mutex_lock(fx_playback_audio_processor_mutex);
2094
2095 fx_playback_audio_processor->mastering_audio_signal = g_list_remove(fx_playback_audio_processor->mastering_audio_signal,
2096 mastering_audio_signal->data);
2097
2098 done = (fx_playback_audio_processor->mastering_audio_signal == NULL) ? TRUE: FALSE;
2099
2100 g_rec_mutex_unlock(fx_playback_audio_processor_mutex);
2101
2102 g_object_unref(mastering_audio_signal->data);
2103 }
2104
2105 mastering_audio_signal = mastering_audio_signal->next;
2106 }
2107
2108 if(done){
2109 ags_recall_done((AgsRecall *) fx_playback_audio_processor);
2110 }
2111
2112 if(fx_playback_audio != NULL){
2113 g_object_unref(fx_playback_audio);
2114 }
2115
2116 g_list_free_full(start_master_audio_signal,
2117 (GDestroyNotify) g_object_unref);
2118
2119 g_list_free_full(start_mastering_audio_signal,
2120 (GDestroyNotify) g_object_unref);
2121 }
2122
2123 void
ags_fx_playback_audio_processor_master(AgsFxPlaybackAudioProcessor * fx_playback_audio_processor)2124 ags_fx_playback_audio_processor_master(AgsFxPlaybackAudioProcessor *fx_playback_audio_processor)
2125 {
2126 g_return_if_fail(AGS_IS_FX_PLAYBACK_AUDIO_PROCESSOR(fx_playback_audio_processor));
2127
2128 g_object_ref(fx_playback_audio_processor);
2129
2130 if(AGS_FX_PLAYBACK_AUDIO_PROCESSOR_GET_CLASS(fx_playback_audio_processor)->master != NULL){
2131 AGS_FX_PLAYBACK_AUDIO_PROCESSOR_GET_CLASS(fx_playback_audio_processor)->master(fx_playback_audio_processor);
2132 }
2133
2134 g_object_unref(fx_playback_audio_processor);
2135 }
2136
2137 void
ags_fx_playback_audio_processor_real_counter_change(AgsFxPlaybackAudioProcessor * fx_playback_audio_processor)2138 ags_fx_playback_audio_processor_real_counter_change(AgsFxPlaybackAudioProcessor *fx_playback_audio_processor)
2139 {
2140 AgsFxPlaybackAudio *fx_playback_audio;
2141
2142 GObject *output_soundcard;
2143
2144 gdouble delay;
2145 guint delay_counter;
2146 guint offset_counter;
2147 gboolean loop;
2148 guint64 loop_start, loop_end;
2149 guint buffer_size;
2150
2151 GValue value = {0,};
2152
2153 GRecMutex *fx_playback_audio_processor_mutex;
2154
2155 fx_playback_audio_processor_mutex = AGS_RECALL_GET_OBJ_MUTEX(fx_playback_audio_processor);
2156
2157 output_soundcard = NULL;
2158
2159 fx_playback_audio = NULL;
2160
2161 buffer_size = AGS_SOUNDCARD_DEFAULT_BUFFER_SIZE;
2162
2163 g_object_get(fx_playback_audio_processor,
2164 "output-soundcard", &output_soundcard,
2165 "recall-audio", &fx_playback_audio,
2166 "buffer-size", &buffer_size,
2167 NULL);
2168
2169 delay = AGS_SOUNDCARD_DEFAULT_DELAY;
2170
2171 loop = FALSE;
2172
2173 loop_start = AGS_FX_PLAYBACK_AUDIO_DEFAULT_LOOP_START;
2174 loop_end = AGS_FX_PLAYBACK_AUDIO_DEFAULT_LOOP_END;
2175
2176 if(fx_playback_audio != NULL){
2177 AgsPort *port;
2178
2179 /* delay */
2180 g_object_get(fx_playback_audio,
2181 "delay", &port,
2182 NULL);
2183
2184 if(port != NULL){
2185 g_value_init(&value,
2186 G_TYPE_DOUBLE);
2187
2188 ags_port_safe_read(port,
2189 &value);
2190
2191 delay = g_value_get_double(&value);
2192 g_value_unset(&value);
2193
2194 g_object_unref(port);
2195 }
2196
2197 /* loop */
2198 g_object_get(fx_playback_audio,
2199 "loop", &port,
2200 NULL);
2201
2202 if(port != NULL){
2203 g_value_init(&value,
2204 G_TYPE_BOOLEAN);
2205
2206 ags_port_safe_read(port,
2207 &value);
2208
2209 loop = g_value_get_boolean(&value);
2210 g_value_unset(&value);
2211
2212 g_object_unref(port);
2213 }
2214
2215 /* loop-start */
2216 g_object_get(fx_playback_audio,
2217 "loop-start", &port,
2218 NULL);
2219
2220 if(port != NULL){
2221 g_value_init(&value,
2222 G_TYPE_UINT64);
2223
2224 ags_port_safe_read(port,
2225 &value);
2226
2227 loop_start = g_value_get_uint64(&value);
2228 g_value_unset(&value);
2229
2230 g_object_unref(port);
2231 }
2232
2233 /* loop-end */
2234 g_object_get(fx_playback_audio,
2235 "loop-end", &port,
2236 NULL);
2237
2238 if(port != NULL){
2239 g_value_init(&value,
2240 G_TYPE_UINT64);
2241
2242 ags_port_safe_read(port,
2243 &value);
2244
2245 loop_end = g_value_get_uint64(&value);
2246 g_value_unset(&value);
2247
2248 g_object_unref(port);
2249 }
2250 }
2251
2252 g_rec_mutex_lock(fx_playback_audio_processor_mutex);
2253
2254 delay_counter = floor(fx_playback_audio_processor->delay_counter);
2255
2256 offset_counter = fx_playback_audio_processor->offset_counter;
2257
2258 g_rec_mutex_unlock(fx_playback_audio_processor_mutex);
2259
2260 if(output_soundcard != NULL){
2261 delay = ags_soundcard_get_delay(AGS_SOUNDCARD(output_soundcard));
2262
2263 delay_counter = ags_soundcard_get_delay_counter(AGS_SOUNDCARD(output_soundcard));
2264 }
2265
2266 if(delay_counter + 1.0 >= floor(delay)){
2267 g_rec_mutex_lock(fx_playback_audio_processor_mutex);
2268
2269 fx_playback_audio_processor->current_delay_counter = 0.0;
2270
2271 if(loop &&
2272 offset_counter + 1 >= loop_end){
2273 fx_playback_audio_processor->current_offset_counter = loop_start;
2274
2275 fx_playback_audio_processor->current_x_offset = (guint64) floor(loop_start * delay) * buffer_size;
2276 }else{
2277 fx_playback_audio_processor->current_offset_counter += 1;
2278
2279 fx_playback_audio_processor->current_x_offset += buffer_size;
2280 }
2281
2282 g_rec_mutex_unlock(fx_playback_audio_processor_mutex);
2283 }else{
2284 g_rec_mutex_lock(fx_playback_audio_processor_mutex);
2285
2286 fx_playback_audio_processor->current_delay_counter += 1.0;
2287
2288 fx_playback_audio_processor->current_x_offset += buffer_size;
2289
2290 g_rec_mutex_unlock(fx_playback_audio_processor_mutex);
2291 }
2292
2293 if(output_soundcard != NULL){
2294 g_object_unref(output_soundcard);
2295 }
2296
2297 if(fx_playback_audio != NULL){
2298 g_object_unref(fx_playback_audio);
2299 }
2300 }
2301
2302 void
ags_fx_playback_audio_processor_counter_change(AgsFxPlaybackAudioProcessor * fx_playback_audio_processor)2303 ags_fx_playback_audio_processor_counter_change(AgsFxPlaybackAudioProcessor *fx_playback_audio_processor)
2304 {
2305 g_return_if_fail(AGS_IS_FX_PLAYBACK_AUDIO_PROCESSOR(fx_playback_audio_processor));
2306
2307 g_object_ref(fx_playback_audio_processor);
2308
2309 if(AGS_FX_PLAYBACK_AUDIO_PROCESSOR_GET_CLASS(fx_playback_audio_processor)->counter_change != NULL){
2310 AGS_FX_PLAYBACK_AUDIO_PROCESSOR_GET_CLASS(fx_playback_audio_processor)->counter_change(fx_playback_audio_processor);
2311 }
2312
2313 g_object_unref(fx_playback_audio_processor);
2314 }
2315
2316 /**
2317 * ags_fx_playback_audio_processor_new:
2318 * @audio: the #AgsAudio
2319 *
2320 * Create a new instance of #AgsFxPlaybackAudioProcessor
2321 *
2322 * Returns: the new #AgsFxPlaybackAudioProcessor
2323 *
2324 * Since: 3.3.0
2325 */
2326 AgsFxPlaybackAudioProcessor*
ags_fx_playback_audio_processor_new(AgsAudio * audio)2327 ags_fx_playback_audio_processor_new(AgsAudio *audio)
2328 {
2329 AgsFxPlaybackAudioProcessor *fx_playback_audio_processor;
2330
2331 fx_playback_audio_processor = (AgsFxPlaybackAudioProcessor *) g_object_new(AGS_TYPE_FX_PLAYBACK_AUDIO_PROCESSOR,
2332 "audio", audio,
2333 NULL);
2334
2335 return(fx_playback_audio_processor);
2336 }
2337