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", &current_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", &current_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