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/task/ags_open_sfz_file.h>
21
22 #include <ags/audio/ags_diatonic_scale.h>
23 #include <ags/audio/ags_audio.h>
24 #include <ags/audio/ags_channel.h>
25 #include <ags/audio/ags_input.h>
26 #include <ags/audio/ags_filter_util.h>
27
28 #include <ags/audio/file/ags_audio_file_link.h>
29 #include <ags/audio/file/ags_sound_container.h>
30 #include <ags/audio/file/ags_sound_resource.h>
31 #include <ags/audio/file/ags_audio_file_link.h>
32 #include <ags/audio/file/ags_audio_container.h>
33 #include <ags/audio/file/ags_sfz_file.h>
34 #include <ags/audio/file/ags_sfz_group.h>
35 #include <ags/audio/file/ags_sfz_region.h>
36 #include <ags/audio/file/ags_sfz_sample.h>
37
38 #include <ags/config.h>
39
40 #include <ags/i18n.h>
41
42 void ags_open_sfz_file_class_init(AgsOpenSFZFileClass *open_sfz_file);
43 void ags_open_sfz_file_init(AgsOpenSFZFile *open_sfz_file);
44 void ags_open_sfz_file_set_property(GObject *gobject,
45 guint prop_id,
46 const GValue *value,
47 GParamSpec *param_spec);
48 void ags_open_sfz_file_get_property(GObject *gobject,
49 guint prop_id,
50 GValue *value,
51 GParamSpec *param_spec);
52 void ags_open_sfz_file_dispose(GObject *gobject);
53 void ags_open_sfz_file_finalize(GObject *gobject);
54
55 void ags_open_sfz_file_launch(AgsTask *task);
56
57
58 /**
59 * SECTION:ags_open_sfz_file
60 * @short_description: open SFZ file
61 * @title: AgsOpenSFZFile
62 * @section_id:
63 * @include: ags/audio/task/ags_open_sfz_file.h
64 *
65 * The #AgsOpenSFZFile task opens SFZ file.
66 */
67
68 static gpointer ags_open_sfz_file_parent_class = NULL;
69
70 enum{
71 PROP_0,
72 PROP_AUDIO,
73 PROP_SFZ_FILE,
74 PROP_FILENAME,
75 PROP_START_PAD,
76 };
77
78 GType
ags_open_sfz_file_get_type()79 ags_open_sfz_file_get_type()
80 {
81 static volatile gsize g_define_type_id__volatile = 0;
82
83 if(g_once_init_enter (&g_define_type_id__volatile)){
84 GType ags_type_open_sfz_file = 0;
85
86 static const GTypeInfo ags_open_sfz_file_info = {
87 sizeof(AgsOpenSFZFileClass),
88 NULL, /* base_init */
89 NULL, /* base_finalize */
90 (GClassInitFunc) ags_open_sfz_file_class_init,
91 NULL, /* class_finalize */
92 NULL, /* class_data */
93 sizeof(AgsOpenSFZFile),
94 0, /* n_preallocs */
95 (GInstanceInitFunc) ags_open_sfz_file_init,
96 };
97
98 ags_type_open_sfz_file = g_type_register_static(AGS_TYPE_TASK,
99 "AgsOpenSFZFile",
100 &ags_open_sfz_file_info,
101 0);
102
103 g_once_init_leave(&g_define_type_id__volatile, ags_type_open_sfz_file);
104 }
105
106 return g_define_type_id__volatile;
107 }
108
109 void
ags_open_sfz_file_class_init(AgsOpenSFZFileClass * open_sfz_file)110 ags_open_sfz_file_class_init(AgsOpenSFZFileClass *open_sfz_file)
111 {
112 GObjectClass *gobject;
113 AgsTaskClass *task;
114
115 GParamSpec *param_spec;
116
117 ags_open_sfz_file_parent_class = g_type_class_peek_parent(open_sfz_file);
118
119 /* GObject */
120 gobject = (GObjectClass *) open_sfz_file;
121
122 gobject->set_property = ags_open_sfz_file_set_property;
123 gobject->get_property = ags_open_sfz_file_get_property;
124
125 gobject->dispose = ags_open_sfz_file_dispose;
126 gobject->finalize = ags_open_sfz_file_finalize;
127
128 /* properties */
129 /**
130 * AgsOpenSFZFile:audio:
131 *
132 * The assigned #AgsAudio
133 *
134 * Since: 3.4.0
135 */
136 param_spec = g_param_spec_object("audio",
137 i18n_pspec("audio of open sf2 instrument"),
138 i18n_pspec("The audio of open sf2 instrument task"),
139 AGS_TYPE_AUDIO,
140 G_PARAM_READABLE | G_PARAM_WRITABLE);
141 g_object_class_install_property(gobject,
142 PROP_AUDIO,
143 param_spec);
144
145 /**
146 * AgsOpenSFZFile:sfz-file:
147 *
148 * The assigned #AgsSFZFile
149 *
150 * Since: 3.4.0
151 */
152 param_spec = g_param_spec_object("sfz-file",
153 i18n_pspec("SFZ file object"),
154 i18n_pspec("The SFZ file object of open task"),
155 AGS_TYPE_SFZ_FILE,
156 G_PARAM_READABLE | G_PARAM_WRITABLE);
157 g_object_class_install_property(gobject,
158 PROP_SFZ_FILE,
159 param_spec);
160
161 /**
162 * AgsOpenSFZFile:filename:
163 *
164 * The assigned filename.
165 *
166 * Since: 3.4.0
167 */
168 param_spec = g_param_spec_string("filename",
169 i18n_pspec("the filename"),
170 i18n_pspec("The filename"),
171 NULL,
172 G_PARAM_READABLE | G_PARAM_WRITABLE);
173 g_object_class_install_property(gobject,
174 PROP_FILENAME,
175 param_spec);
176
177 /**
178 * AgsOpenSFZFile:start-pad:
179 *
180 * The assigned start-pad.
181 *
182 * Since: 3.4.0
183 */
184 param_spec = g_param_spec_uint("start-pad",
185 i18n_pspec("the start pad"),
186 i18n_pspec("The start pad"),
187 0,
188 G_MAXUINT32,
189 0,
190 G_PARAM_READABLE | G_PARAM_WRITABLE);
191 g_object_class_install_property(gobject,
192 PROP_START_PAD,
193 param_spec);
194
195 /* AgsTask */
196 task = (AgsTaskClass *) open_sfz_file;
197
198 task->launch = ags_open_sfz_file_launch;
199 }
200
201 void
ags_open_sfz_file_init(AgsOpenSFZFile * open_sfz_file)202 ags_open_sfz_file_init(AgsOpenSFZFile *open_sfz_file)
203 {
204 open_sfz_file->audio = NULL;
205
206 open_sfz_file->filename = NULL;
207
208 open_sfz_file->start_pad = 0;
209 }
210
211 void
ags_open_sfz_file_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)212 ags_open_sfz_file_set_property(GObject *gobject,
213 guint prop_id,
214 const GValue *value,
215 GParamSpec *param_spec)
216 {
217 AgsOpenSFZFile *open_sfz_file;
218
219 open_sfz_file = AGS_OPEN_SFZ_FILE(gobject);
220
221 switch(prop_id){
222 case PROP_AUDIO:
223 {
224 AgsAudio *audio;
225
226 audio = (AgsAudio *) g_value_get_object(value);
227
228 if(open_sfz_file->audio == audio){
229 return;
230 }
231
232 if(open_sfz_file->audio != NULL){
233 g_object_unref(open_sfz_file->audio);
234 }
235
236 if(audio != NULL){
237 g_object_ref(audio);
238 }
239
240 open_sfz_file->audio = audio;
241 }
242 break;
243 case PROP_SFZ_FILE:
244 {
245 AgsSFZFile *sfz_file;
246
247 sfz_file = (AgsSFZFile *) g_value_get_object(value);
248
249 if(open_sfz_file->sfz_file == sfz_file){
250 return;
251 }
252
253 if(open_sfz_file->sfz_file != NULL){
254 g_object_unref(open_sfz_file->sfz_file);
255 }
256
257 if(sfz_file != NULL){
258 g_object_ref(sfz_file);
259 }
260
261 open_sfz_file->sfz_file = sfz_file;
262 }
263 break;
264 case PROP_FILENAME:
265 {
266 gchar *filename;
267
268 filename = g_value_get_string(value);
269
270 if(open_sfz_file->filename == filename){
271 return;
272 }
273
274 if(open_sfz_file->filename != NULL){
275 g_free(open_sfz_file->filename);
276 }
277
278 open_sfz_file->filename = g_strdup(filename);
279 }
280 break;
281 case PROP_START_PAD:
282 {
283 open_sfz_file->start_pad = g_value_get_uint(value);
284 }
285 break;
286 default:
287 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
288 break;
289 }
290 }
291
292 void
ags_open_sfz_file_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)293 ags_open_sfz_file_get_property(GObject *gobject,
294 guint prop_id,
295 GValue *value,
296 GParamSpec *param_spec)
297 {
298 AgsOpenSFZFile *open_sfz_file;
299
300 open_sfz_file = AGS_OPEN_SFZ_FILE(gobject);
301
302 switch(prop_id){
303 case PROP_AUDIO:
304 {
305 g_value_set_object(value, open_sfz_file->audio);
306 }
307 break;
308 case PROP_SFZ_FILE:
309 {
310 g_value_set_object(value, open_sfz_file->sfz_file);
311 }
312 break;
313 case PROP_FILENAME:
314 {
315 g_value_set_string(value, open_sfz_file->filename);
316 }
317 break;
318 case PROP_START_PAD:
319 {
320 g_value_set_uint(value, open_sfz_file->start_pad);
321 }
322 break;
323 default:
324 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
325 break;
326 }
327 }
328
329 void
ags_open_sfz_file_dispose(GObject * gobject)330 ags_open_sfz_file_dispose(GObject *gobject)
331 {
332 AgsOpenSFZFile *open_sfz_file;
333
334 open_sfz_file = AGS_OPEN_SFZ_FILE(gobject);
335
336 if(open_sfz_file->audio != NULL){
337 g_object_unref(open_sfz_file->audio);
338
339 open_sfz_file->audio = NULL;
340 }
341
342 if(open_sfz_file->sfz_file != NULL){
343 g_object_unref(open_sfz_file->sfz_file);
344
345 open_sfz_file->sfz_file = NULL;
346 }
347
348 /* call parent */
349 G_OBJECT_CLASS(ags_open_sfz_file_parent_class)->dispose(gobject);
350 }
351
352 void
ags_open_sfz_file_finalize(GObject * gobject)353 ags_open_sfz_file_finalize(GObject *gobject)
354 {
355 AgsOpenSFZFile *open_sfz_file;
356
357 open_sfz_file = AGS_OPEN_SFZ_FILE(gobject);
358
359 if(open_sfz_file->audio != NULL){
360 g_object_unref(open_sfz_file->audio);
361 }
362
363 if(open_sfz_file->sfz_file != NULL){
364 g_object_unref(open_sfz_file->sfz_file);
365 }
366
367 g_free(open_sfz_file->filename);
368
369 /* call parent */
370 G_OBJECT_CLASS(ags_open_sfz_file_parent_class)->finalize(gobject);
371 }
372
373 void
ags_open_sfz_file_launch(AgsTask * task)374 ags_open_sfz_file_launch(AgsTask *task)
375 {
376 AgsChannel *start_input, *next_input, *input;
377 AgsSFZGroup *group;
378 AgsSFZRegion *region;
379 AgsOpenSFZFile *open_sfz_file;
380
381 GObject *output_soundcard;
382
383 GList *start_audio_signal, *audio_signal;
384 GList *start_list, *list;
385
386 glong key, current_key;
387 glong hikey, lokey, current_hikey, current_lokey;
388 guint n_pads, current_pads;
389 guint n_audio_channels, current_audio_channels;
390 int retval;
391 guint j_stop;
392 guint i, j;
393
394 open_sfz_file = AGS_OPEN_SFZ_FILE(task);
395
396 g_return_if_fail(AGS_IS_AUDIO(open_sfz_file->audio));
397 g_return_if_fail(AGS_IS_SFZ_FILE(open_sfz_file->sfz_file));
398
399 g_object_get(open_sfz_file->audio,
400 "output-soundcard", &output_soundcard,
401 NULL);
402
403 /* select */
404 start_input = NULL;
405
406 n_pads = 0;
407 n_audio_channels = 0;
408
409 g_object_get(open_sfz_file->audio,
410 "input-pads", &n_pads,
411 "audio-channels", &n_audio_channels,
412 NULL);
413
414 hikey = 0;
415 lokey = 0;
416
417 ags_sfz_file_get_range(AGS_SFZ_FILE(open_sfz_file->sfz_file),
418 &lokey, &hikey);
419
420 /* resize */
421 g_object_get(open_sfz_file->sfz_file,
422 "sample", &start_list,
423 NULL);
424
425 list = start_list;
426 current_audio_channels = n_audio_channels;
427
428 while(list != NULL){
429 guint tmp;
430
431 ags_sound_resource_get_presets(AGS_SOUND_RESOURCE(list->data),
432 &tmp,
433 NULL,
434 NULL,
435 NULL);
436
437 if(tmp > current_audio_channels){
438 current_audio_channels = tmp;
439 }
440
441 /* iterate */
442 list = list->next;
443 }
444
445 if(current_audio_channels > n_audio_channels){
446 n_audio_channels = current_audio_channels;
447
448 ags_audio_set_audio_channels(open_sfz_file->audio,
449 n_audio_channels, 0);
450 }
451
452 current_pads = hikey - lokey + 1;
453
454 if(lokey <= hikey &&
455 current_pads > n_pads){
456 n_pads = current_pads;
457
458 ags_audio_set_pads(open_sfz_file->audio,
459 AGS_TYPE_INPUT,
460 n_pads, 0);
461 }
462
463 g_object_get(open_sfz_file->audio,
464 "input", &start_input,
465 NULL);
466
467 input = start_input;
468
469 audio_signal =
470 start_audio_signal = NULL;
471
472 j_stop = n_audio_channels;
473
474 for(i = 0, j = 0; input != NULL;){
475 AgsRecycling *first_recycling;
476
477 g_object_get(input,
478 "first-recycling", &first_recycling,
479 NULL);
480
481 list = start_list;
482
483 while(list != NULL){
484 gchar *str_key, *str_pitch_keycenter;
485 gchar *str_lokey, *str_hikey;
486
487 gboolean success;
488
489 g_object_get(list->data,
490 "group", &group,
491 "region", ®ion,
492 NULL);
493
494 /* group */
495 str_pitch_keycenter = ags_sfz_group_lookup_control(group,
496 "pitch_keycenter");
497
498 str_key = ags_sfz_group_lookup_control(group,
499 "key");
500
501 str_lokey = ags_sfz_group_lookup_control(group,
502 "lokey");
503
504 str_hikey = ags_sfz_group_lookup_control(group,
505 "hikey");
506
507 lokey = 0;
508
509 if(str_lokey != NULL){
510 retval = sscanf(str_lokey, "%lu", ¤t_lokey);
511
512 if(retval <= 0){
513 retval = ags_diatonic_scale_note_to_midi_key(str_lokey,
514 ¤t_lokey);
515
516 if(retval > 0){
517 lokey = current_lokey;
518 }
519 }else{
520 lokey = current_lokey;
521 }
522 }
523
524 key = lokey + i;
525
526 success = FALSE;
527
528 if(str_pitch_keycenter != NULL){
529 retval = sscanf(str_pitch_keycenter, "%lu", ¤t_key);
530
531 if(retval > 0){
532 if(current_key == key){
533 success = TRUE;
534 }
535 }else{
536 retval = ags_diatonic_scale_note_to_midi_key(str_pitch_keycenter,
537 ¤t_key);
538
539 if(retval > 0){
540 if(current_key == key){
541 success = TRUE;
542 }
543 }
544 }
545 }
546
547 if(str_key != NULL){
548 retval = sscanf(str_key, "%lu", ¤t_key);
549
550 if(retval > 0){
551 if(current_key == key){
552 success = TRUE;
553 }
554 }else{
555 retval = ags_diatonic_scale_note_to_midi_key(str_key,
556 ¤t_key);
557
558 if(retval > 0){
559 if(current_key == key){
560 success = TRUE;
561 }
562 }
563 }
564
565 if(success){
566 g_free(str_pitch_keycenter);
567 g_free(str_key);
568
569 g_free(str_hikey);
570 g_free(str_lokey);
571
572 break;
573 }
574 }
575
576 if(str_hikey != NULL && str_lokey != NULL){
577 success = FALSE;
578
579 retval = sscanf(str_hikey, "%lu", ¤t_hikey);
580
581 if(retval <= 0){
582 retval = ags_diatonic_scale_note_to_midi_key(str_hikey,
583 ¤t_hikey);
584
585 if(retval > 0){
586 if(current_key <= current_hikey){
587 success = TRUE;
588 }
589 }
590 }else{
591 if(current_key <= current_hikey){
592 success = TRUE;
593 }
594 }
595
596 retval = sscanf(str_lokey, "%lu", ¤t_lokey);
597
598 if(retval <= 0){
599 retval = ags_diatonic_scale_note_to_midi_key(str_lokey,
600 ¤t_lokey);
601
602 if(retval > 0){
603 if(current_key >= current_lokey){
604 success = TRUE;
605 }else{
606 success = FALSE;
607 }
608 }else{
609 success = FALSE;
610 }
611 }else{
612 if(current_key >= current_lokey){
613 success = TRUE;
614 }else{
615 success = FALSE;
616 }
617 }
618
619 if(success){
620 hikey = current_hikey;
621 lokey = current_lokey;
622
623 g_free(str_pitch_keycenter);
624 g_free(str_key);
625
626 g_free(str_hikey);
627 g_free(str_lokey);
628
629 break;
630 }
631 }
632
633 g_free(str_pitch_keycenter);
634 g_free(str_key);
635
636 g_free(str_hikey);
637 g_free(str_lokey);
638
639 /* region */
640 str_pitch_keycenter = ags_sfz_region_lookup_control(region,
641 "pitch_keycenter");
642
643 str_key = ags_sfz_region_lookup_control(region,
644 "key");
645
646 str_lokey = ags_sfz_region_lookup_control(region,
647 "lokey");
648
649 str_hikey = ags_sfz_region_lookup_control(region,
650 "hikey");
651
652 lokey = 0;
653
654 if(str_lokey != NULL){
655 retval = sscanf(str_lokey, "%lu", ¤t_lokey);
656
657 if(retval <= 0){
658 retval = ags_diatonic_scale_note_to_midi_key(str_lokey,
659 ¤t_lokey);
660
661 if(retval > 0){
662 lokey = current_lokey;
663 }
664 }else{
665 lokey = current_lokey;
666 }
667 }
668
669 key = lokey + i;
670
671 success = FALSE;
672
673 if(str_pitch_keycenter != NULL){
674 retval = sscanf(str_pitch_keycenter, "%lu", ¤t_key);
675
676 if(retval > 0){
677 if(current_key == key){
678 success = TRUE;
679 }
680 }else{
681 retval = ags_diatonic_scale_note_to_midi_key(str_pitch_keycenter,
682 ¤t_key);
683
684 if(retval > 0){
685 if(current_key == key){
686 success = TRUE;
687 }
688 }
689 }
690 }
691
692 if(str_key != NULL){
693 retval = sscanf(str_key, "%lu", ¤t_key);
694
695 if(retval > 0){
696 if(current_key == key){
697 success = TRUE;
698 }
699 }else{
700 retval = ags_diatonic_scale_note_to_midi_key(str_key,
701 ¤t_key);
702
703 if(retval > 0){
704 if(current_key == key){
705 success = TRUE;
706 }
707 }
708 }
709
710 if(success){
711 g_free(str_pitch_keycenter);
712 g_free(str_key);
713
714 g_free(str_hikey);
715 g_free(str_lokey);
716
717 break;
718 }
719 }
720
721 if(str_hikey != NULL && str_lokey != NULL){
722 gboolean success;
723
724 success = FALSE;
725
726 retval = sscanf(str_hikey, "%lu", ¤t_hikey);
727
728 if(retval <= 0){
729 retval = ags_diatonic_scale_note_to_midi_key(str_hikey,
730 ¤t_hikey);
731
732 if(retval > 0){
733 if(current_key <= current_hikey){
734 success = TRUE;
735 }
736 }
737 }else{
738 if(current_key <= current_hikey){
739 success = TRUE;
740 }
741 }
742
743 retval = sscanf(str_lokey, "%lu", ¤t_lokey);
744
745 if(retval <= 0){
746 retval = ags_diatonic_scale_note_to_midi_key(str_lokey,
747 ¤t_lokey);
748
749 if(retval > 0){
750 if(current_key >= current_lokey){
751 success = TRUE;
752 }else{
753 success = FALSE;
754 }
755 }else{
756 success = FALSE;
757 }
758 }else{
759 if(current_key >= current_lokey){
760 success = TRUE;
761 }else{
762 success = FALSE;
763 }
764 }
765
766 if(success){
767 hikey = current_hikey;
768 lokey = current_lokey;
769
770 g_free(str_pitch_keycenter);
771 g_free(str_key);
772
773 g_free(str_hikey);
774 g_free(str_lokey);
775
776 break;
777 }
778 }
779
780 g_free(str_pitch_keycenter);
781 g_free(str_key);
782
783 g_free(str_hikey);
784 g_free(str_lokey);
785
786 /* iterate */
787 list = list->next;
788 }
789
790 if(j == 0 &&
791 list != NULL){
792 audio_signal =
793 start_audio_signal = ags_sound_resource_read_audio_signal(AGS_SOUND_RESOURCE(list->data),
794 output_soundcard,
795 -1);
796 }
797
798 /* add audio signal as template to recycling */
799 audio_signal = g_list_nth(start_audio_signal,
800 j);
801
802 if(audio_signal != NULL){
803 AgsAudioSignal *current_audio_signal;
804
805 GList *start_stream, *stream;
806
807 gchar *str_key, *str_pitch_keycenter;
808 gchar *str_lokey;
809
810 guint samplerate;
811 guint buffer_size;
812 guint format;
813 guint loop_start, loop_end;
814 glong pitch_keycenter, current_pitch_keycenter;
815 guint x_offset;
816
817 /* key center */
818 g_object_get(list->data,
819 "group", &group,
820 "region", ®ion,
821 NULL);
822
823 key = lokey + i;
824 pitch_keycenter = 49;
825
826 /* group */
827 str_pitch_keycenter = ags_sfz_group_lookup_control(group,
828 "pitch_keycenter");
829
830 str_key = ags_sfz_group_lookup_control(group,
831 "key");
832
833 if(str_pitch_keycenter != NULL){
834 retval = sscanf(str_pitch_keycenter, "%lu", ¤t_pitch_keycenter);
835
836 if(retval > 0){
837 pitch_keycenter = current_pitch_keycenter;
838 }else{
839 retval = ags_diatonic_scale_note_to_midi_key(str_pitch_keycenter,
840 ¤t_key);
841
842 if(retval > 0){
843 pitch_keycenter = current_key;
844 }
845 }
846 }else if(str_key != NULL){
847 retval = sscanf(str_key, "%lu", ¤t_pitch_keycenter);
848
849 if(retval > 0){
850 pitch_keycenter = current_key;
851 }else{
852 retval = ags_diatonic_scale_note_to_midi_key(str_key,
853 ¤t_key);
854
855 if(retval > 0){
856 pitch_keycenter = current_key;
857 }
858 }
859 }
860
861 g_free(str_pitch_keycenter);
862 g_free(str_key);
863
864 /* region */
865 str_pitch_keycenter = ags_sfz_region_lookup_control(region,
866 "pitch_keycenter");
867
868 str_key = ags_sfz_region_lookup_control(region,
869 "key");
870
871 if(str_pitch_keycenter != NULL){
872 retval = sscanf(str_pitch_keycenter, "%lu", ¤t_pitch_keycenter);
873
874 if(retval > 0){
875 pitch_keycenter = current_pitch_keycenter;
876 }else{
877 retval = ags_diatonic_scale_note_to_midi_key(str_pitch_keycenter,
878 ¤t_key);
879
880 if(retval > 0){
881 pitch_keycenter = current_key;
882 }
883 }
884 }else if(str_key != NULL){
885 retval = sscanf(str_key, "%lu", ¤t_pitch_keycenter);
886
887 if(retval > 0){
888 pitch_keycenter = current_key;
889 }else{
890 retval = ags_diatonic_scale_note_to_midi_key(str_key,
891 ¤t_key);
892
893 if(retval > 0){
894 pitch_keycenter = current_key;
895 }
896 }
897 }
898
899 g_free(str_pitch_keycenter);
900 g_free(str_key);
901
902 /* loop start/end */
903 g_object_get(audio_signal->data,
904 "samplerate", &samplerate,
905 "buffer-size", &buffer_size,
906 "format", &format,
907 "loop-start", &loop_start,
908 "loop-end", &loop_end,
909 NULL);
910
911 /* create audio signal */
912 current_audio_signal = ags_audio_signal_new(output_soundcard,
913 (GObject *) first_recycling,
914 NULL);
915 current_audio_signal->flags |= AGS_AUDIO_SIGNAL_TEMPLATE;
916
917 g_object_set(current_audio_signal,
918 "loop-start", loop_start,
919 "loop-end", loop_end,
920 NULL);
921
922 ags_audio_signal_duplicate_stream(current_audio_signal,
923 audio_signal->data);
924
925 /* pitch */
926 stream =
927 start_stream = current_audio_signal->stream;
928
929 x_offset = 0;
930
931 key -= lokey;
932
933 while(stream != NULL){
934 switch(format){
935 case AGS_SOUNDCARD_SIGNED_8_BIT:
936 {
937 ags_filter_util_pitch_s8((gint8 *) stream->data,
938 buffer_size,
939 samplerate,
940 pitch_keycenter - 48.0,
941 ((gdouble) key - (gdouble) pitch_keycenter) * 100.0);
942 }
943 break;
944 case AGS_SOUNDCARD_SIGNED_16_BIT:
945 {
946 ags_filter_util_pitch_s16((gint16 *) stream->data,
947 buffer_size,
948 samplerate,
949 pitch_keycenter - 48.0,
950 ((gdouble) key - (gdouble) pitch_keycenter) * 100.0);
951 }
952 break;
953 case AGS_SOUNDCARD_SIGNED_24_BIT:
954 {
955 ags_filter_util_pitch_s24((gint32 *) stream->data,
956 buffer_size,
957 samplerate,
958 pitch_keycenter - 48.0,
959 ((gdouble) key - (gdouble) pitch_keycenter) * 100.0);
960 }
961 break;
962 case AGS_SOUNDCARD_SIGNED_32_BIT:
963 {
964 ags_filter_util_pitch_s32((gint32 *) stream->data,
965 buffer_size,
966 samplerate,
967 pitch_keycenter - 48.0,
968 ((gdouble) key - (gdouble) pitch_keycenter) * 100.0);
969 }
970 break;
971 case AGS_SOUNDCARD_SIGNED_64_BIT:
972 {
973 ags_filter_util_pitch_s64((gint64 *) stream->data,
974 buffer_size,
975 samplerate,
976 pitch_keycenter - 48.0,
977 ((gdouble) key - (gdouble) pitch_keycenter) * 100.0);
978 }
979 break;
980 case AGS_SOUNDCARD_FLOAT:
981 {
982 ags_filter_util_pitch_float((gfloat *) stream->data,
983 buffer_size,
984 samplerate,
985 pitch_keycenter - 48.0,
986 ((gdouble) key - (gdouble) pitch_keycenter) * 100.0);
987 }
988 break;
989 case AGS_SOUNDCARD_DOUBLE:
990 {
991 ags_filter_util_pitch_double((gdouble *) stream->data,
992 buffer_size,
993 samplerate,
994 pitch_keycenter - 48.0,
995 ((gdouble) key - (gdouble) pitch_keycenter) * 100.0);
996 }
997 break;
998 case AGS_SOUNDCARD_COMPLEX:
999 {
1000 ags_filter_util_pitch_complex((AgsComplex *) stream->data,
1001 buffer_size,
1002 samplerate,
1003 pitch_keycenter - 48.0,
1004 ((gdouble) key - (gdouble) pitch_keycenter) * 100.0);
1005 }
1006 break;
1007 }
1008
1009 /* iterate */
1010 x_offset += buffer_size;
1011
1012 stream = stream->next;
1013 }
1014
1015 /* add audio signal */
1016 ags_recycling_add_audio_signal(first_recycling,
1017 current_audio_signal);
1018 }else{
1019 g_message("SFZ audio signal not found");
1020 }
1021
1022 g_object_unref(first_recycling);
1023
1024 /* iterate */
1025 if(j + 1 < j_stop){
1026 j++;
1027 }else{
1028 g_list_free_full(start_audio_signal,
1029 g_object_unref);
1030
1031 audio_signal =
1032 start_audio_signal = NULL;
1033
1034 i++;
1035 j = 0;
1036
1037 list = list->next;
1038 }
1039
1040 next_input = ags_channel_next(input);
1041
1042 g_object_unref(input);
1043
1044 input = next_input;
1045 }
1046
1047 g_object_unref(output_soundcard);
1048
1049 g_list_free_full(start_list,
1050 g_object_unref);
1051 }
1052
1053 /**
1054 * ags_open_sfz_file_new:
1055 * @audio: the #AgsAudio
1056 * @sfz_file: the #AgsSFZFile or %NULL
1057 * @filename: the Soundfont2 file
1058 * @start_pad: the pad start
1059 *
1060 * Creates an #AgsOpenSFZFile.
1061 *
1062 * Returns: an new #AgsOpenSFZFile.
1063 *
1064 * Since: 3.4.0
1065 */
1066 AgsOpenSFZFile*
ags_open_sfz_file_new(AgsAudio * audio,AgsSFZFile * sfz_file,gchar * filename,guint start_pad)1067 ags_open_sfz_file_new(AgsAudio *audio,
1068 AgsSFZFile *sfz_file,
1069 gchar *filename,
1070 guint start_pad)
1071 {
1072 AgsOpenSFZFile *open_sfz_file;
1073
1074 open_sfz_file = (AgsOpenSFZFile *) g_object_new(AGS_TYPE_OPEN_SFZ_FILE,
1075 "audio", audio,
1076 "sfz-file", sfz_file,
1077 "filename", filename,
1078 "start-pad", start_pad,
1079 NULL);
1080
1081 return(open_sfz_file);
1082 }
1083