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