1 /* GSequencer - Advanced GTK Sequencer
2 * Copyright (C) 2005-2021 Joël Krähemann
3 *
4 * This file is part of GSequencer.
5 *
6 * GSequencer is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * GSequencer is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GSequencer. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <ags/X/machine/ags_pitch_sampler.h>
21 #include <ags/X/machine/ags_pitch_sampler_callbacks.h>
22
23 #include <ags/X/ags_ui_provider.h>
24 #include <ags/X/ags_window.h>
25 #include <ags/X/ags_navigation.h>
26
27 #include <math.h>
28
29 #include <ags/i18n.h>
30
31 void ags_pitch_sampler_class_init(AgsPitchSamplerClass *pitch_sampler);
32 void ags_pitch_sampler_connectable_interface_init(AgsConnectableInterface *connectable);
33 void ags_pitch_sampler_init(AgsPitchSampler *pitch_sampler);
34 void ags_pitch_sampler_finalize(GObject *gobject);
35
36 void ags_pitch_sampler_connect(AgsConnectable *connectable);
37 void ags_pitch_sampler_disconnect(AgsConnectable *connectable);
38
39 void ags_pitch_sampler_resize_audio_channels(AgsMachine *machine,
40 guint audio_channels, guint audio_channels_old,
41 gpointer data);
42 void ags_pitch_sampler_resize_pads(AgsMachine *machine, GType type,
43 guint pads, guint pads_old,
44 gpointer data);
45
46 void ags_pitch_sampler_map_recall(AgsMachine *machine);
47 void ags_pitch_sampler_output_map_recall(AgsPitchSampler *pitch_sampler,
48 guint audio_channel_start,
49 guint output_pad_start);
50 void ags_pitch_sampler_input_map_recall(AgsPitchSampler *pitch_sampler,
51 guint audio_channel_start,
52 guint input_pad_start);
53
54 /**
55 * SECTION:ags_pitch_sampler
56 * @short_description: pitch_sampler notation
57 * @title: AgsPitchSampler
58 * @section_id:
59 * @include: ags/X/machine/ags_pitch_sampler.h
60 *
61 * The #AgsPitchSampler is a composite widget to act as soundfont2 notation player.
62 */
63
64 static gpointer ags_pitch_sampler_parent_class = NULL;
65 static AgsConnectableInterface *ags_pitch_sampler_parent_connectable_interface;
66
67 GHashTable *ags_pitch_sampler_sfz_loader_completed = NULL;
68
69 GType
ags_pitch_sampler_get_type(void)70 ags_pitch_sampler_get_type(void)
71 {
72 static volatile gsize g_define_type_id__volatile = 0;
73
74 if(g_once_init_enter (&g_define_type_id__volatile)){
75 GType ags_type_pitch_sampler = 0;
76
77 static const GTypeInfo ags_pitch_sampler_info = {
78 sizeof(AgsPitchSamplerClass),
79 NULL, /* base_init */
80 NULL, /* base_finalize */
81 (GClassInitFunc) ags_pitch_sampler_class_init,
82 NULL, /* class_finalize */
83 NULL, /* class_data */
84 sizeof(AgsPitchSampler),
85 0, /* n_preallocs */
86 (GInstanceInitFunc) ags_pitch_sampler_init,
87 };
88
89 static const GInterfaceInfo ags_connectable_interface_info = {
90 (GInterfaceInitFunc) ags_pitch_sampler_connectable_interface_init,
91 NULL, /* interface_finalize */
92 NULL, /* interface_data */
93 };
94
95 ags_type_pitch_sampler = g_type_register_static(AGS_TYPE_MACHINE,
96 "AgsPitchSampler", &ags_pitch_sampler_info,
97 0);
98
99 g_type_add_interface_static(ags_type_pitch_sampler,
100 AGS_TYPE_CONNECTABLE,
101 &ags_connectable_interface_info);
102
103 g_once_init_leave(&g_define_type_id__volatile, ags_type_pitch_sampler);
104 }
105
106 return g_define_type_id__volatile;
107 }
108
109 void
ags_pitch_sampler_class_init(AgsPitchSamplerClass * pitch_sampler)110 ags_pitch_sampler_class_init(AgsPitchSamplerClass *pitch_sampler)
111 {
112 GObjectClass *gobject;
113 AgsMachineClass *machine;
114
115 ags_pitch_sampler_parent_class = g_type_class_peek_parent(pitch_sampler);
116
117 /* GObjectClass */
118 gobject = (GObjectClass *) pitch_sampler;
119
120 gobject->finalize = ags_pitch_sampler_finalize;
121
122 /* AgsMachineClass */
123 machine = (AgsMachineClass *) pitch_sampler;
124
125 machine->map_recall = ags_pitch_sampler_map_recall;
126 }
127
128 void
ags_pitch_sampler_connectable_interface_init(AgsConnectableInterface * connectable)129 ags_pitch_sampler_connectable_interface_init(AgsConnectableInterface *connectable)
130 {
131 ags_pitch_sampler_parent_connectable_interface = g_type_interface_peek_parent(connectable);
132
133 connectable->connect = ags_pitch_sampler_connect;
134 connectable->disconnect = ags_pitch_sampler_disconnect;
135 }
136
137 void
ags_pitch_sampler_init(AgsPitchSampler * pitch_sampler)138 ags_pitch_sampler_init(AgsPitchSampler *pitch_sampler)
139 {
140 GtkExpander *expander;
141 GtkBox *vbox;
142 AgsPitchSamplerFile *file;
143 GtkBox *hbox;
144 GtkBox *control_vbox;
145 GtkBox *filename_hbox;
146 GtkBox *synth_generator_vbox;
147 GtkBox *pitch_hbox;
148 GtkBox *base_note_hbox;
149 GtkBox *key_count_hbox;
150 GtkBox *aliase_hbox;
151 GtkGrid *lfo_grid;
152 GtkBox *volume_hbox;
153 GtkFrame *frame;
154 GtkLabel *label;
155
156 GtkAdjustment *adjustment;
157
158 AgsAudio *audio;
159 AgsSFZSynthGenerator *sfz_synth_generator;
160
161 AgsApplicationContext *application_context;
162
163 gdouble gui_scale_factor;
164 gdouble page, step;
165
166 application_context = ags_application_context_get_instance();
167
168 /* scale factor */
169 gui_scale_factor = ags_ui_provider_get_gui_scale_factor(AGS_UI_PROVIDER(application_context));
170
171 g_signal_connect_after((GObject *) pitch_sampler, "parent_set",
172 G_CALLBACK(ags_pitch_sampler_parent_set_callback), (gpointer) pitch_sampler);
173
174 audio = AGS_MACHINE(pitch_sampler)->audio;
175 ags_audio_set_flags(audio, (AGS_AUDIO_SYNC |
176 AGS_AUDIO_ASYNC |
177 AGS_AUDIO_OUTPUT_HAS_RECYCLING |
178 AGS_AUDIO_INPUT_HAS_RECYCLING |
179 AGS_AUDIO_INPUT_HAS_FILE));
180 ags_audio_set_ability_flags(audio, (AGS_SOUND_ABILITY_PLAYBACK |
181 AGS_SOUND_ABILITY_NOTATION));
182 ags_audio_set_behaviour_flags(audio, (AGS_SOUND_BEHAVIOUR_REVERSE_MAPPING |
183 AGS_SOUND_BEHAVIOUR_DEFAULTS_TO_INPUT));
184
185 g_object_set(audio,
186 "min-audio-channels", 1,
187 "min-output-pads", 1,
188 "min-input-pads", 1,
189 "max-input-pads", 128,
190 "audio-start-mapping", 0,
191 "audio-end-mapping", 128,
192 "midi-start-mapping", 0,
193 "midi-end-mapping", 128,
194 NULL);
195
196 sfz_synth_generator = ags_sfz_synth_generator_new();
197
198 ags_audio_add_sfz_synth_generator(audio,
199 (GObject *) sfz_synth_generator);
200
201 AGS_MACHINE(pitch_sampler)->flags |= (AGS_MACHINE_IS_SYNTHESIZER |
202 AGS_MACHINE_REVERSE_NOTATION);
203 AGS_MACHINE(pitch_sampler)->file_input_flags |= AGS_MACHINE_ACCEPT_SFZ;
204
205 AGS_MACHINE(pitch_sampler)->input_pad_type = G_TYPE_NONE;
206 AGS_MACHINE(pitch_sampler)->input_line_type = G_TYPE_NONE;
207 AGS_MACHINE(pitch_sampler)->output_pad_type = G_TYPE_NONE;
208 AGS_MACHINE(pitch_sampler)->output_line_type = G_TYPE_NONE;
209
210 /* context menu */
211 ags_machine_popup_add_connection_options((AgsMachine *) pitch_sampler,
212 (AGS_MACHINE_POPUP_MIDI_DIALOG));
213
214 /* audio resize */
215 g_signal_connect_after(G_OBJECT(pitch_sampler), "resize-audio-channels",
216 G_CALLBACK(ags_pitch_sampler_resize_audio_channels), NULL);
217
218 g_signal_connect_after(G_OBJECT(pitch_sampler), "resize-pads",
219 G_CALLBACK(ags_pitch_sampler_resize_pads), NULL);
220
221 /* flags */
222 pitch_sampler->flags = 0;
223
224 /* mapped IO */
225 pitch_sampler->mapped_input_pad = 0;
226 pitch_sampler->mapped_output_pad = 0;
227
228 pitch_sampler->playback_play_container = ags_recall_container_new();
229 pitch_sampler->playback_recall_container = ags_recall_container_new();
230
231 pitch_sampler->notation_play_container = ags_recall_container_new();
232 pitch_sampler->notation_recall_container = ags_recall_container_new();
233
234 pitch_sampler->lfo_play_container = ags_recall_container_new();
235 pitch_sampler->lfo_recall_container = ags_recall_container_new();
236
237 pitch_sampler->two_pass_aliase_play_container = ags_recall_container_new();
238 pitch_sampler->two_pass_aliase_recall_container = ags_recall_container_new();
239
240 pitch_sampler->volume_play_container = ags_recall_container_new();
241 pitch_sampler->volume_recall_container = ags_recall_container_new();
242
243 pitch_sampler->envelope_play_container = ags_recall_container_new();
244 pitch_sampler->envelope_recall_container = ags_recall_container_new();
245
246 pitch_sampler->buffer_play_container = ags_recall_container_new();
247 pitch_sampler->buffer_recall_container = ags_recall_container_new();
248
249 /* context menu */
250 ags_machine_popup_add_edit_options((AgsMachine *) pitch_sampler,
251 (AGS_MACHINE_POPUP_ENVELOPE));
252
253 /* name and xml type */
254 pitch_sampler->name = NULL;
255 pitch_sampler->xml_type = "ags-pitch-sampler";
256
257 /* audio container */
258 pitch_sampler->audio_container = NULL;
259
260 /* create widgets */
261 vbox = (GtkBox *) gtk_box_new(GTK_ORIENTATION_VERTICAL,
262 0);
263 gtk_container_add((GtkContainer *) (gtk_bin_get_child((GtkBin *) pitch_sampler)),
264 (GtkWidget *) vbox);
265
266 /* hbox */
267 hbox = (GtkBox *) gtk_box_new(GTK_ORIENTATION_HORIZONTAL,
268 0);
269 gtk_box_pack_start(vbox,
270 (GtkWidget *) hbox,
271 FALSE, FALSE,
272 0);
273
274 /* file */
275 expander = gtk_expander_new(i18n("file"));
276 gtk_box_pack_start(hbox,
277 (GtkWidget *) expander,
278 FALSE, FALSE,
279 0);
280
281 pitch_sampler->file = (GtkBox *) gtk_box_new(GTK_ORIENTATION_VERTICAL,
282 0);
283 gtk_container_add((GtkContainer *) expander,
284 (GtkWidget *) pitch_sampler->file);
285
286 /* add 1 sample */
287 file = ags_pitch_sampler_file_new();
288 ags_pitch_sampler_add_file(pitch_sampler,
289 file);
290
291 /* control */
292 control_vbox = (GtkBox *) gtk_box_new(GTK_ORIENTATION_VERTICAL,
293 0);
294 gtk_box_pack_start(hbox,
295 (GtkWidget *) control_vbox,
296 FALSE, FALSE,
297 0);
298
299 /* filename */
300 filename_hbox = (GtkBox *) gtk_box_new(GTK_ORIENTATION_HORIZONTAL,
301 0);
302 gtk_box_pack_start(control_vbox,
303 (GtkWidget *) filename_hbox,
304 FALSE, FALSE,
305 0);
306
307 pitch_sampler->filename = (GtkEntry *) gtk_entry_new();
308 gtk_box_pack_start(filename_hbox,
309 (GtkWidget *) pitch_sampler->filename,
310 FALSE, FALSE,
311 0);
312
313 pitch_sampler->open = (GtkButton *) gtk_button_new_from_icon_name("document-open",
314 GTK_ICON_SIZE_BUTTON);
315 gtk_box_pack_start(filename_hbox,
316 (GtkWidget *) pitch_sampler->open,
317 FALSE, FALSE,
318 0);
319
320 pitch_sampler->sfz_loader = NULL;
321
322 pitch_sampler->position = -1;
323
324 pitch_sampler->loading = (GtkLabel *) gtk_label_new(i18n("loading ... "));
325 gtk_box_pack_start(filename_hbox,
326 (GtkWidget *) pitch_sampler->loading,
327 FALSE, FALSE,
328 0);
329 gtk_widget_set_no_show_all((GtkWidget *) pitch_sampler->loading,
330 TRUE);
331 gtk_widget_hide((GtkWidget *) pitch_sampler->loading);
332
333
334 /* synth generator */
335 frame = (GtkFrame *) gtk_frame_new(i18n("synth generator"));
336 gtk_box_pack_start(hbox,
337 (GtkWidget *) frame,
338 FALSE, FALSE,
339 0);
340
341 synth_generator_vbox = (GtkBox *) gtk_box_new(GTK_ORIENTATION_VERTICAL,
342 0);
343 gtk_container_add((GtkContainer *) frame,
344 (GtkWidget *) synth_generator_vbox);
345
346 pitch_sampler->enable_synth_generator = (GtkCheckButton *) gtk_check_button_new_with_label(i18n("enabled"));
347 gtk_box_pack_start(synth_generator_vbox,
348 (GtkWidget *) pitch_sampler->enable_synth_generator,
349 FALSE, FALSE,
350 0);
351
352 /* pitch function */
353 pitch_hbox = (GtkBox *) gtk_box_new(GTK_ORIENTATION_HORIZONTAL,
354 0);
355 gtk_box_pack_start(synth_generator_vbox,
356 (GtkWidget *) pitch_hbox,
357 FALSE, FALSE,
358 0);
359
360 label = (GtkLabel *) gtk_label_new(i18n("pitch"));
361 gtk_box_pack_start(pitch_hbox,
362 (GtkWidget *) label,
363 FALSE, FALSE,
364 0);
365
366 pitch_sampler->pitch_function = (GtkComboBox *) gtk_combo_box_text_new();
367
368 gtk_combo_box_text_append_text((GtkComboBoxText *) pitch_sampler->pitch_function,
369 "ags-fast-pitch");
370
371 gtk_combo_box_text_append_text((GtkComboBoxText *) pitch_sampler->pitch_function,
372 "ags-hq-pitch");
373
374 gtk_combo_box_text_append_text((GtkComboBoxText *) pitch_sampler->pitch_function,
375 "fluid-no-interpolate");
376
377 gtk_combo_box_text_append_text((GtkComboBoxText *) pitch_sampler->pitch_function,
378 "fluid-linear-interpolate");
379
380 gtk_combo_box_text_append_text((GtkComboBoxText *) pitch_sampler->pitch_function,
381 "fluid-4th-order-interpolate");
382
383 gtk_combo_box_text_append_text((GtkComboBoxText *) pitch_sampler->pitch_function,
384 "fluid-7th-order-interpolate");
385
386 gtk_combo_box_set_active(pitch_sampler->pitch_function,
387 4);
388
389 gtk_box_pack_start(pitch_hbox,
390 (GtkWidget *) pitch_sampler->pitch_function,
391 FALSE, FALSE,
392 0);
393
394 /* base note */
395 base_note_hbox = (GtkBox *) gtk_box_new(GTK_ORIENTATION_HORIZONTAL,
396 0);
397 gtk_box_pack_start(synth_generator_vbox,
398 (GtkWidget *) base_note_hbox,
399 FALSE, FALSE,
400 0);
401
402 label = (GtkLabel *) gtk_label_new(i18n("lower"));
403 gtk_box_pack_start(base_note_hbox,
404 (GtkWidget *) label,
405 FALSE, FALSE,
406 0);
407
408 pitch_sampler->lower = (GtkSpinButton *) gtk_spin_button_new_with_range(-70.0,
409 70.0,
410 1.0);
411 gtk_spin_button_set_digits(pitch_sampler->lower,
412 2);
413 gtk_spin_button_set_value(pitch_sampler->lower,
414 -48.0);
415 gtk_box_pack_start(base_note_hbox,
416 (GtkWidget *) pitch_sampler->lower,
417 FALSE, FALSE,
418 0);
419
420 /* key count */
421 key_count_hbox = (GtkBox *) gtk_box_new(GTK_ORIENTATION_HORIZONTAL,
422 0);
423 gtk_box_pack_start(synth_generator_vbox,
424 (GtkWidget *) key_count_hbox,
425 FALSE, FALSE,
426 0);
427
428 label = (GtkLabel *) gtk_label_new(i18n("key count"));
429 gtk_box_pack_start(key_count_hbox,
430 (GtkWidget *) label,
431 FALSE, FALSE,
432 0);
433
434 pitch_sampler->key_count = (GtkSpinButton *) gtk_spin_button_new_with_range(0.0,
435 128.0,
436 1.0);
437 gtk_spin_button_set_value(pitch_sampler->key_count,
438 78.0);
439 gtk_box_pack_start((GtkBox *) key_count_hbox,
440 (GtkWidget *) pitch_sampler->key_count,
441 FALSE, FALSE,
442 0);
443
444 pitch_sampler->update = (GtkButton *) gtk_button_new_with_label(i18n("update"));
445 gtk_widget_set_valign((GtkWidget *) pitch_sampler->update,
446 GTK_ALIGN_END);
447 gtk_box_pack_start(hbox,
448 (GtkWidget *) pitch_sampler->update,
449 FALSE, FALSE,
450 0);
451
452 /* other controls */
453 /* aliase */
454 frame = (GtkFrame *) gtk_frame_new(i18n("aliase"));
455
456 gtk_widget_set_valign((GtkWidget *) frame,
457 GTK_ALIGN_FILL);
458 gtk_widget_set_halign((GtkWidget *) frame,
459 GTK_ALIGN_FILL);
460
461 gtk_box_pack_start(hbox,
462 (GtkWidget *) frame,
463 FALSE, FALSE,
464 0);
465
466 aliase_hbox = (GtkBox *) gtk_box_new(GTK_ORIENTATION_HORIZONTAL,
467 0);
468 gtk_container_add((GtkContainer *) frame,
469 (GtkWidget *) aliase_hbox);
470
471 pitch_sampler->enable_aliase = (GtkCheckButton *) gtk_check_button_new_with_label(i18n("enabled"));
472 gtk_box_pack_start(aliase_hbox,
473 (GtkWidget *) pitch_sampler->enable_aliase,
474 FALSE, FALSE,
475 0);
476
477 step = 2.0 * M_PI / 100.0;
478 page = 2.0 * M_PI / AGS_DIAL_DEFAULT_PRECISION;
479
480 /* aliase a */
481 pitch_sampler->aliase_a_amount = (AgsDial *) ags_dial_new();
482
483 adjustment = ags_dial_get_adjustment(pitch_sampler->aliase_a_amount);
484
485 gtk_adjustment_set_step_increment(adjustment,
486 step);
487 gtk_adjustment_set_page_increment(adjustment,
488 page);
489
490 gtk_adjustment_set_lower(adjustment,
491 0.0);
492 gtk_adjustment_set_upper(adjustment,
493 2.0 * M_PI);
494
495 gtk_box_pack_start(aliase_hbox,
496 (GtkWidget *) pitch_sampler->aliase_a_amount,
497 FALSE, FALSE,
498 0);
499
500 pitch_sampler->aliase_a_phase = (AgsDial *) ags_dial_new();
501
502 adjustment = ags_dial_get_adjustment(pitch_sampler->aliase_a_phase);
503
504 gtk_adjustment_set_step_increment(adjustment,
505 step);
506 gtk_adjustment_set_page_increment(adjustment,
507 page);
508
509 gtk_adjustment_set_lower(adjustment,
510 0.0);
511 gtk_adjustment_set_upper(adjustment,
512 2.0 * M_PI);
513
514 gtk_box_pack_start(aliase_hbox,
515 (GtkWidget *) pitch_sampler->aliase_a_phase,
516 FALSE, FALSE,
517 0);
518
519 /* aliase b */
520 pitch_sampler->aliase_b_amount = (AgsDial *) ags_dial_new();
521
522 adjustment = ags_dial_get_adjustment(pitch_sampler->aliase_b_amount);
523
524 gtk_adjustment_set_step_increment(adjustment,
525 step);
526 gtk_adjustment_set_page_increment(adjustment,
527 page);
528
529 gtk_adjustment_set_lower(adjustment,
530 0.0);
531 gtk_adjustment_set_upper(adjustment,
532 2.0 * M_PI);
533
534 gtk_box_pack_start(aliase_hbox,
535 (GtkWidget *) pitch_sampler->aliase_b_amount,
536 FALSE, FALSE,
537 0);
538
539 pitch_sampler->aliase_b_phase = (AgsDial *) ags_dial_new();
540
541 adjustment = ags_dial_get_adjustment(pitch_sampler->aliase_b_phase);
542
543 gtk_adjustment_set_step_increment(adjustment,
544 step);
545 gtk_adjustment_set_page_increment(adjustment,
546 page);
547
548 gtk_adjustment_set_lower(adjustment,
549 0.0);
550 gtk_adjustment_set_upper(adjustment,
551 2.0 * M_PI);
552
553 gtk_box_pack_start(aliase_hbox,
554 (GtkWidget *) pitch_sampler->aliase_b_phase,
555 FALSE, FALSE,
556 0);
557
558 /* volume */
559 frame = (GtkFrame *) gtk_frame_new(i18n("volume"));
560
561 gtk_widget_set_valign((GtkWidget *) frame,
562 GTK_ALIGN_FILL);
563 gtk_widget_set_halign((GtkWidget *) frame,
564 GTK_ALIGN_FILL);
565
566 gtk_box_pack_start(hbox,
567 (GtkWidget *) frame,
568 FALSE, FALSE,
569 0);
570
571 volume_hbox = (GtkBox *) gtk_box_new(GTK_ORIENTATION_HORIZONTAL,
572 0);
573 gtk_container_add((GtkContainer *) frame,
574 (GtkWidget *) volume_hbox);
575
576 pitch_sampler->volume = (GtkScale *) gtk_scale_new_with_range(GTK_ORIENTATION_VERTICAL,
577 0.0,
578 2.0,
579 0.025);
580
581 gtk_widget_set_size_request(pitch_sampler->volume,
582 gui_scale_factor * 16, gui_scale_factor * 100);
583
584 gtk_box_pack_start(volume_hbox,
585 (GtkWidget *) pitch_sampler->volume,
586 FALSE, FALSE,
587 0);
588
589 gtk_scale_set_digits(pitch_sampler->volume,
590 3);
591
592 gtk_range_set_increments(GTK_RANGE(pitch_sampler->volume),
593 0.025, 0.1);
594 gtk_range_set_value(GTK_RANGE(pitch_sampler->volume),
595 1.0);
596 gtk_range_set_inverted(GTK_RANGE(pitch_sampler->volume),
597 TRUE);
598
599 /* LFO grid */
600 lfo_grid = (GtkGrid *) gtk_grid_new();
601 gtk_box_pack_start(hbox,
602 (GtkWidget *) lfo_grid,
603 FALSE, FALSE,
604 0);
605
606 pitch_sampler->enable_lfo = gtk_check_button_new_with_label(i18n("enable LFO"));
607
608 gtk_widget_set_valign((GtkWidget *) pitch_sampler->enable_lfo,
609 GTK_ALIGN_FILL);
610 gtk_widget_set_halign((GtkWidget *) pitch_sampler->enable_lfo,
611 GTK_ALIGN_FILL);
612
613 gtk_grid_attach(lfo_grid,
614 (GtkWidget *) pitch_sampler->enable_lfo,
615 0, 0,
616 1, 1);
617
618 label = gtk_label_new(i18n("LFO freq"));
619
620 gtk_widget_set_valign((GtkWidget *) label,
621 GTK_ALIGN_FILL);
622 gtk_widget_set_halign((GtkWidget *) label,
623 GTK_ALIGN_FILL);
624
625 gtk_grid_attach(lfo_grid,
626 (GtkWidget *) label,
627 1, 0,
628 1, 1);
629
630 pitch_sampler->lfo_freq = (GtkSpinButton *) gtk_spin_button_new_with_range(AGS_PITCH_SAMPLER_LFO_FREQ_MIN,
631 AGS_PITCH_SAMPLER_LFO_FREQ_MAX,
632 0.001);
633 gtk_spin_button_set_digits(pitch_sampler->lfo_freq,
634 3);
635 gtk_spin_button_set_value(pitch_sampler->lfo_freq, AGS_PITCH_SAMPLER_DEFAULT_LFO_FREQ);
636
637 gtk_widget_set_valign((GtkWidget *) pitch_sampler->lfo_freq,
638 GTK_ALIGN_FILL);
639 gtk_widget_set_halign((GtkWidget *) pitch_sampler->lfo_freq,
640 GTK_ALIGN_FILL);
641
642 gtk_grid_attach(lfo_grid,
643 (GtkWidget *) pitch_sampler->lfo_freq,
644 2, 0,
645 1, 1);
646
647 label = gtk_label_new(i18n("LFO phase"));
648
649 gtk_widget_set_valign((GtkWidget *) label,
650 GTK_ALIGN_FILL);
651 gtk_widget_set_halign((GtkWidget *) label,
652 GTK_ALIGN_FILL);
653
654 gtk_grid_attach(lfo_grid,
655 (GtkWidget *) label,
656 1, 1,
657 1, 1);
658
659 pitch_sampler->lfo_phase = (GtkSpinButton *) gtk_spin_button_new_with_range(0.0,
660 G_MAXDOUBLE,
661 1.0);
662 gtk_spin_button_set_value(pitch_sampler->lfo_phase, 0.0);
663
664 gtk_widget_set_valign((GtkWidget *) pitch_sampler->lfo_phase,
665 GTK_ALIGN_FILL);
666 gtk_widget_set_halign((GtkWidget *) pitch_sampler->lfo_phase,
667 GTK_ALIGN_FILL);
668
669 gtk_grid_attach(lfo_grid,
670 (GtkWidget *) pitch_sampler->lfo_phase,
671 2, 1,
672 1, 1);
673
674 label = gtk_label_new(i18n("LFO depth"));
675
676 gtk_widget_set_valign((GtkWidget *) label,
677 GTK_ALIGN_FILL);
678 gtk_widget_set_halign((GtkWidget *) label,
679 GTK_ALIGN_FILL);
680
681 gtk_grid_attach(lfo_grid,
682 (GtkWidget *) label,
683 1, 2,
684 1, 1);
685
686 pitch_sampler->lfo_depth = (GtkSpinButton *) gtk_spin_button_new_with_range(-1200.0,
687 1200.0,
688 1.0);
689 gtk_spin_button_set_digits(pitch_sampler->lfo_depth,
690 3);
691 gtk_spin_button_set_value(pitch_sampler->lfo_depth, 0.0);
692
693 gtk_widget_set_valign((GtkWidget *) pitch_sampler->lfo_depth,
694 GTK_ALIGN_FILL);
695 gtk_widget_set_halign((GtkWidget *) pitch_sampler->lfo_depth,
696 GTK_ALIGN_FILL);
697
698 gtk_grid_attach(lfo_grid,
699 (GtkWidget *) pitch_sampler->lfo_depth,
700 2, 2,
701 1, 1);
702
703 label = gtk_label_new(i18n("LFO tuning"));
704
705 gtk_widget_set_valign((GtkWidget *) label,
706 GTK_ALIGN_FILL);
707 gtk_widget_set_halign((GtkWidget *) label,
708 GTK_ALIGN_FILL);
709
710 gtk_grid_attach(lfo_grid,
711 (GtkWidget *) label,
712 1, 3,
713 1, 1);
714
715 pitch_sampler->lfo_tuning = (GtkSpinButton *) gtk_spin_button_new_with_range(-1200.0,
716 1200.0,
717 1.0);
718 gtk_spin_button_set_digits(pitch_sampler->lfo_tuning,
719 2);
720 gtk_spin_button_set_value(pitch_sampler->lfo_tuning, 1.0);
721
722 gtk_widget_set_valign((GtkWidget *) pitch_sampler->lfo_tuning,
723 GTK_ALIGN_FILL);
724 gtk_widget_set_halign((GtkWidget *) pitch_sampler->lfo_tuning,
725 GTK_ALIGN_FILL);
726
727 gtk_grid_attach(lfo_grid,
728 (GtkWidget *) pitch_sampler->lfo_tuning,
729 2, 3,
730 1, 1);
731
732 /* dialog */
733 pitch_sampler->open_dialog = NULL;
734
735 /* SFZ loader */
736 if(ags_pitch_sampler_sfz_loader_completed == NULL){
737 ags_pitch_sampler_sfz_loader_completed = g_hash_table_new_full(g_direct_hash, g_direct_equal,
738 NULL,
739 NULL);
740 }
741
742 g_hash_table_insert(ags_pitch_sampler_sfz_loader_completed,
743 pitch_sampler, ags_pitch_sampler_sfz_loader_completed_timeout);
744 g_timeout_add(1000 / 4, (GSourceFunc) ags_pitch_sampler_sfz_loader_completed_timeout, (gpointer) pitch_sampler);
745 }
746
747 void
ags_pitch_sampler_finalize(GObject * gobject)748 ags_pitch_sampler_finalize(GObject *gobject)
749 {
750 g_hash_table_remove(ags_pitch_sampler_sfz_loader_completed,
751 gobject);
752
753 /* call parent */
754 G_OBJECT_CLASS(ags_pitch_sampler_parent_class)->finalize(gobject);
755 }
756
757 void
ags_pitch_sampler_connect(AgsConnectable * connectable)758 ags_pitch_sampler_connect(AgsConnectable *connectable)
759 {
760 AgsPitchSampler *pitch_sampler;
761
762 GList *start_list, *list;
763
764 if((AGS_MACHINE_CONNECTED & (AGS_MACHINE(connectable)->flags)) != 0){
765 return;
766 }
767
768 ags_pitch_sampler_parent_connectable_interface->connect(connectable);
769
770 pitch_sampler = AGS_PITCH_SAMPLER(connectable);
771
772 list =
773 start_list = gtk_container_get_children((GtkContainer *) pitch_sampler->file);
774
775 while(list != NULL){
776 GList *child_start;
777
778 child_start = gtk_container_get_children(GTK_CONTAINER(list->data));
779
780 ags_connectable_connect(AGS_CONNECTABLE(child_start->next->data));
781
782 list = list->next;
783 }
784
785 g_list_free(start_list);
786
787 /* filename */
788 g_signal_connect(pitch_sampler->open, "clicked",
789 G_CALLBACK(ags_pitch_sampler_open_callback), pitch_sampler);
790
791 /* update */
792 g_signal_connect(pitch_sampler->update, "clicked",
793 G_CALLBACK(ags_pitch_sampler_update_callback), pitch_sampler);
794
795 /* LFO */
796 g_signal_connect_after((GObject *) pitch_sampler->enable_lfo, "toggled",
797 G_CALLBACK(ags_pitch_sampler_enable_lfo_callback), pitch_sampler);
798
799 g_signal_connect_after((GObject *) pitch_sampler->lfo_freq, "value-changed",
800 G_CALLBACK(ags_pitch_sampler_lfo_freq_callback), (gpointer) pitch_sampler);
801
802 g_signal_connect_after((GObject *) pitch_sampler->lfo_phase, "value-changed",
803 G_CALLBACK(ags_pitch_sampler_lfo_phase_callback), (gpointer) pitch_sampler);
804
805 g_signal_connect_after((GObject *) pitch_sampler->lfo_depth, "value-changed",
806 G_CALLBACK(ags_pitch_sampler_lfo_depth_callback), (gpointer) pitch_sampler);
807
808 g_signal_connect_after((GObject *) pitch_sampler->lfo_tuning, "value-changed",
809 G_CALLBACK(ags_pitch_sampler_lfo_tuning_callback), (gpointer) pitch_sampler);
810
811 g_signal_connect((GObject *) pitch_sampler->enable_aliase, "clicked",
812 G_CALLBACK(ags_pitch_sampler_enable_aliase_callback), (gpointer) pitch_sampler);
813
814 g_signal_connect((GObject *) pitch_sampler->aliase_a_amount, "value-changed",
815 G_CALLBACK(ags_pitch_sampler_aliase_a_amount_callback), (gpointer) pitch_sampler);
816
817 g_signal_connect((GObject *) pitch_sampler->aliase_a_phase, "value-changed",
818 G_CALLBACK(ags_pitch_sampler_aliase_a_phase_callback), (gpointer) pitch_sampler);
819
820 g_signal_connect((GObject *) pitch_sampler->aliase_b_amount, "value-changed",
821 G_CALLBACK(ags_pitch_sampler_aliase_b_amount_callback), (gpointer) pitch_sampler);
822
823 g_signal_connect((GObject *) pitch_sampler->aliase_b_phase, "value-changed",
824 G_CALLBACK(ags_pitch_sampler_aliase_b_phase_callback), (gpointer) pitch_sampler);
825
826 g_signal_connect((GObject *) pitch_sampler->volume, "value-changed",
827 G_CALLBACK(ags_pitch_sampler_volume_callback), (gpointer) pitch_sampler);
828 }
829
830 void
ags_pitch_sampler_disconnect(AgsConnectable * connectable)831 ags_pitch_sampler_disconnect(AgsConnectable *connectable)
832 {
833 AgsPitchSampler *pitch_sampler;
834
835 GList *start_list, *list;
836
837 if((AGS_MACHINE_CONNECTED & (AGS_MACHINE(connectable)->flags)) == 0){
838 return;
839 }
840
841 ags_pitch_sampler_parent_connectable_interface->disconnect(connectable);
842
843 pitch_sampler = AGS_PITCH_SAMPLER(connectable);
844
845 list =
846 start_list = gtk_container_get_children((GtkContainer *) pitch_sampler->file);
847
848 while(list != NULL){
849 GList *child_start;
850
851 child_start = gtk_container_get_children(GTK_CONTAINER(list->data));
852
853 ags_connectable_disconnect(AGS_CONNECTABLE(child_start->next->data));
854
855 g_list_free(child_start);
856
857 list = list->next;
858 }
859
860 g_list_free(start_list);
861
862 /* filename */
863 g_object_disconnect(pitch_sampler->open,
864 "any_signal::clicked",
865 G_CALLBACK(ags_pitch_sampler_open_callback),
866 pitch_sampler,
867 NULL);
868
869 /* update */
870 g_object_disconnect(pitch_sampler->update,
871 "any_signal::clicked",
872 G_CALLBACK(ags_pitch_sampler_update_callback),
873 pitch_sampler,
874 NULL);
875
876 /* LFO */
877 g_object_disconnect((GObject *) pitch_sampler->enable_lfo,
878 "any_signal::toggled",
879 G_CALLBACK(ags_pitch_sampler_enable_lfo_callback),
880 pitch_sampler,
881 NULL);
882
883 g_object_disconnect((GObject *) pitch_sampler->lfo_freq,
884 "any_signal::value-changed",
885 G_CALLBACK(ags_pitch_sampler_lfo_freq_callback),
886 (gpointer) pitch_sampler,
887 NULL);
888
889 g_object_disconnect((GObject *) pitch_sampler->lfo_phase,
890 "any_signal::value-changed",
891 G_CALLBACK(ags_pitch_sampler_lfo_phase_callback),
892 (gpointer) pitch_sampler,
893 NULL);
894
895 g_object_disconnect((GObject *) pitch_sampler->lfo_depth,
896 "any_signal::value-changed",
897 G_CALLBACK(ags_pitch_sampler_lfo_depth_callback),
898 (gpointer) pitch_sampler,
899 NULL);
900
901 g_object_disconnect((GObject *) pitch_sampler->lfo_tuning,
902 "any_signal::value-changed",
903 G_CALLBACK(ags_pitch_sampler_lfo_tuning_callback),
904 (gpointer) pitch_sampler,
905 NULL);
906
907 /* aliase */
908 g_object_disconnect((GObject *) pitch_sampler->enable_aliase,
909 "any_signal::clicked",
910 G_CALLBACK(ags_pitch_sampler_enable_aliase_callback),
911 (gpointer) pitch_sampler,
912 NULL);
913
914 g_object_disconnect((GObject *) pitch_sampler->aliase_a_amount,
915 "any_signal::value-changed",
916 G_CALLBACK(ags_pitch_sampler_aliase_a_amount_callback),
917 (gpointer) pitch_sampler,
918 NULL);
919
920 g_object_disconnect((GObject *) pitch_sampler->aliase_a_phase,
921 "any_signal::value-changed",
922 G_CALLBACK(ags_pitch_sampler_aliase_a_phase_callback),
923 (gpointer) pitch_sampler,
924 NULL);
925
926 g_object_disconnect((GObject *) pitch_sampler->aliase_b_amount,
927 "any_signal::value-changed",
928 G_CALLBACK(ags_pitch_sampler_aliase_b_amount_callback),
929 (gpointer) pitch_sampler,
930 NULL);
931
932 g_object_disconnect((GObject *) pitch_sampler->aliase_b_phase,
933 "any_signal::value-changed",
934 G_CALLBACK(ags_pitch_sampler_aliase_b_phase_callback),
935 (gpointer) pitch_sampler,
936 NULL);
937
938 /* volume */
939 g_object_disconnect((GObject *) pitch_sampler->volume,
940 "any_signal::value-changed",
941 G_CALLBACK(ags_pitch_sampler_volume_callback),
942 (gpointer) pitch_sampler,
943 NULL);
944 }
945
946 void
ags_pitch_sampler_resize_audio_channels(AgsMachine * machine,guint audio_channels,guint audio_channels_old,gpointer data)947 ags_pitch_sampler_resize_audio_channels(AgsMachine *machine,
948 guint audio_channels, guint audio_channels_old,
949 gpointer data)
950 {
951 AgsPitchSampler *pitch_sampler;
952
953 pitch_sampler = (AgsPitchSampler *) machine;
954
955 /* */
956 if(audio_channels > audio_channels_old){
957 /* recall */
958 if((AGS_MACHINE_MAPPED_RECALL & (machine->flags)) != 0){
959 ags_pitch_sampler_input_map_recall(pitch_sampler,
960 audio_channels_old,
961 0);
962
963 ags_pitch_sampler_output_map_recall(pitch_sampler,
964 audio_channels_old,
965 0);
966 }
967 }
968 }
969
970 void
ags_pitch_sampler_resize_pads(AgsMachine * machine,GType channel_type,guint pads,guint pads_old,gpointer data)971 ags_pitch_sampler_resize_pads(AgsMachine *machine, GType channel_type,
972 guint pads, guint pads_old,
973 gpointer data)
974 {
975 AgsPitchSampler *pitch_sampler;
976
977 gboolean grow;
978
979 pitch_sampler = (AgsPitchSampler *) machine;
980
981 /* check grow */
982 if(pads_old < pads){
983 grow = TRUE;
984 }else{
985 grow = FALSE;
986 }
987
988 if(g_type_is_a(channel_type, AGS_TYPE_INPUT)){
989 if(grow){
990 /* depending on destination */
991 ags_pitch_sampler_input_map_recall(pitch_sampler,
992 0,
993 pads_old);
994 }else{
995 pitch_sampler->mapped_input_pad = pads;
996 }
997 }else if(g_type_is_a(channel_type, AGS_TYPE_OUTPUT)){
998 if(grow){
999 /* depending on destination */
1000 ags_pitch_sampler_output_map_recall(pitch_sampler,
1001 0,
1002 pads_old);
1003 }else{
1004 pitch_sampler->mapped_output_pad = pads;
1005 }
1006 }else{
1007 g_critical("unknown channel type");
1008 }
1009 }
1010
1011 void
ags_pitch_sampler_map_recall(AgsMachine * machine)1012 ags_pitch_sampler_map_recall(AgsMachine *machine)
1013 {
1014 AgsNavigation *navigation;
1015 AgsPitchSampler *pitch_sampler;
1016
1017 AgsAudio *audio;
1018
1019 AgsApplicationContext *application_context;
1020
1021 GList *start_recall, *recall;
1022
1023 gint position;
1024
1025 if((AGS_MACHINE_MAPPED_RECALL & (machine->flags)) != 0 ||
1026 (AGS_MACHINE_PREMAPPED_RECALL & (machine->flags)) != 0){
1027 return;
1028 }
1029
1030 application_context = ags_application_context_get_instance();
1031
1032 navigation = (AgsNavigation *) ags_ui_provider_get_navigation(AGS_UI_PROVIDER(application_context));
1033
1034 pitch_sampler = AGS_PITCH_SAMPLER(machine);
1035
1036 audio = machine->audio;
1037
1038 position = 0;
1039
1040 /* ags-fx-playback */
1041 start_recall = ags_fx_factory_create(audio,
1042 pitch_sampler->playback_play_container, pitch_sampler->playback_recall_container,
1043 "ags-fx-playback",
1044 NULL,
1045 NULL,
1046 0, 0,
1047 0, 0,
1048 position,
1049 (AGS_FX_FACTORY_ADD | AGS_FX_FACTORY_INPUT),
1050 0);
1051
1052 g_list_free_full(start_recall,
1053 (GDestroyNotify) g_object_unref);
1054
1055 /* ags-fx-notation */
1056 start_recall = ags_fx_factory_create(audio,
1057 pitch_sampler->notation_play_container, pitch_sampler->notation_recall_container,
1058 "ags-fx-notation",
1059 NULL,
1060 NULL,
1061 0, 0,
1062 0, 0,
1063 position,
1064 (AGS_FX_FACTORY_ADD | AGS_FX_FACTORY_INPUT),
1065 0);
1066
1067 g_list_free_full(start_recall,
1068 (GDestroyNotify) g_object_unref);
1069
1070 /* ags-fx-lfo */
1071 start_recall = ags_fx_factory_create(audio,
1072 pitch_sampler->lfo_play_container, pitch_sampler->lfo_recall_container,
1073 "ags-fx-lfo",
1074 NULL,
1075 NULL,
1076 0, 0,
1077 0, 0,
1078 position,
1079 (AGS_FX_FACTORY_ADD | AGS_FX_FACTORY_INPUT),
1080 0);
1081
1082 g_list_free_full(start_recall,
1083 (GDestroyNotify) g_object_unref);
1084
1085 /* ags-fx-two-pass-aliase */
1086 start_recall = ags_fx_factory_create(audio,
1087 pitch_sampler->two_pass_aliase_play_container, pitch_sampler->two_pass_aliase_recall_container,
1088 "ags-fx-two-pass-aliase",
1089 NULL,
1090 NULL,
1091 0, 0,
1092 0, 0,
1093 position,
1094 (AGS_FX_FACTORY_ADD | AGS_FX_FACTORY_INPUT),
1095 0);
1096
1097 g_list_free_full(start_recall,
1098 (GDestroyNotify) g_object_unref);
1099
1100 /* ags-fx-volume */
1101 start_recall = ags_fx_factory_create(audio,
1102 pitch_sampler->volume_play_container, pitch_sampler->volume_recall_container,
1103 "ags-fx-volume",
1104 NULL,
1105 NULL,
1106 0, 0,
1107 0, 0,
1108 position,
1109 (AGS_FX_FACTORY_ADD | AGS_FX_FACTORY_INPUT),
1110 0);
1111
1112 g_list_free_full(start_recall,
1113 (GDestroyNotify) g_object_unref);
1114
1115 /* ags-fx-envelope */
1116 start_recall = ags_fx_factory_create(audio,
1117 pitch_sampler->envelope_play_container, pitch_sampler->envelope_recall_container,
1118 "ags-fx-envelope",
1119 NULL,
1120 NULL,
1121 0, 0,
1122 0, 0,
1123 position,
1124 (AGS_FX_FACTORY_ADD | AGS_FX_FACTORY_INPUT),
1125 0);
1126
1127 g_list_free_full(start_recall,
1128 (GDestroyNotify) g_object_unref);
1129
1130 /* ags-fx-buffer */
1131 start_recall = ags_fx_factory_create(audio,
1132 pitch_sampler->buffer_play_container, pitch_sampler->buffer_recall_container,
1133 "ags-fx-buffer",
1134 NULL,
1135 NULL,
1136 0, 0,
1137 0, 0,
1138 position,
1139 (AGS_FX_FACTORY_ADD | AGS_FX_FACTORY_INPUT),
1140 0);
1141
1142 g_list_free_full(start_recall,
1143 (GDestroyNotify) g_object_unref);
1144
1145 /* depending on destination */
1146 ags_pitch_sampler_input_map_recall(pitch_sampler,
1147 0,
1148 0);
1149
1150 /* depending on destination */
1151 ags_pitch_sampler_output_map_recall(pitch_sampler,
1152 0,
1153 0);
1154
1155 /* call parent */
1156 AGS_MACHINE_CLASS(ags_pitch_sampler_parent_class)->map_recall(machine);
1157 }
1158
1159 void
ags_pitch_sampler_input_map_recall(AgsPitchSampler * pitch_sampler,guint audio_channel_start,guint input_pad_start)1160 ags_pitch_sampler_input_map_recall(AgsPitchSampler *pitch_sampler,
1161 guint audio_channel_start,
1162 guint input_pad_start)
1163 {
1164 AgsAudio *audio;
1165
1166 GList *start_recall;
1167
1168 gint position;
1169 guint input_pads;
1170 guint audio_channels;
1171
1172 if(pitch_sampler->mapped_input_pad > input_pad_start){
1173 return;
1174 }
1175
1176 audio = AGS_MACHINE(pitch_sampler)->audio;
1177
1178 position = 0;
1179
1180 input_pads = 0;
1181 audio_channels = 0;
1182
1183 /* get some fields */
1184 g_object_get(audio,
1185 "input-pads", &input_pads,
1186 "audio-channels", &audio_channels,
1187 NULL);
1188
1189 /* ags-fx-playback */
1190 start_recall = ags_fx_factory_create(audio,
1191 pitch_sampler->playback_play_container, pitch_sampler->playback_recall_container,
1192 "ags-fx-playback",
1193 NULL,
1194 NULL,
1195 audio_channel_start, audio_channels,
1196 input_pad_start, input_pads,
1197 position,
1198 (AGS_FX_FACTORY_REMAP | AGS_FX_FACTORY_INPUT), 0);
1199
1200 g_list_free_full(start_recall,
1201 (GDestroyNotify) g_object_unref);
1202
1203 /* ags-fx-notation */
1204 start_recall = ags_fx_factory_create(audio,
1205 pitch_sampler->notation_play_container, pitch_sampler->notation_recall_container,
1206 "ags-fx-notation",
1207 NULL,
1208 NULL,
1209 audio_channel_start, audio_channels,
1210 input_pad_start, input_pads,
1211 position,
1212 (AGS_FX_FACTORY_REMAP | AGS_FX_FACTORY_INPUT), 0);
1213
1214 g_list_free_full(start_recall,
1215 (GDestroyNotify) g_object_unref);
1216
1217 /* ags-fx-lfo */
1218 start_recall = ags_fx_factory_create(audio,
1219 pitch_sampler->lfo_play_container, pitch_sampler->lfo_recall_container,
1220 "ags-fx-lfo",
1221 NULL,
1222 NULL,
1223 audio_channel_start, audio_channels,
1224 input_pad_start, input_pads,
1225 position,
1226 (AGS_FX_FACTORY_REMAP | AGS_FX_FACTORY_INPUT), 0);
1227
1228 g_list_free_full(start_recall,
1229 (GDestroyNotify) g_object_unref);
1230
1231 /* ags-fx-two-pass-aliase */
1232 start_recall = ags_fx_factory_create(audio,
1233 pitch_sampler->two_pass_aliase_play_container, pitch_sampler->two_pass_aliase_recall_container,
1234 "ags-fx-two-pass-aliase",
1235 NULL,
1236 NULL,
1237 audio_channel_start, audio_channels,
1238 input_pad_start, input_pads,
1239 position,
1240 (AGS_FX_FACTORY_REMAP | AGS_FX_FACTORY_INPUT), 0);
1241
1242 g_list_free_full(start_recall,
1243 (GDestroyNotify) g_object_unref);
1244
1245 /* ags-fx-volume */
1246 start_recall = ags_fx_factory_create(audio,
1247 pitch_sampler->volume_play_container, pitch_sampler->volume_recall_container,
1248 "ags-fx-volume",
1249 NULL,
1250 NULL,
1251 audio_channel_start, audio_channels,
1252 input_pad_start, input_pads,
1253 position,
1254 (AGS_FX_FACTORY_REMAP | AGS_FX_FACTORY_INPUT), 0);
1255
1256 g_list_free_full(start_recall,
1257 (GDestroyNotify) g_object_unref);
1258
1259 /* ags-fx-envelope */
1260 start_recall = ags_fx_factory_create(audio,
1261 pitch_sampler->envelope_play_container, pitch_sampler->envelope_recall_container,
1262 "ags-fx-envelope",
1263 NULL,
1264 NULL,
1265 audio_channel_start, audio_channels,
1266 input_pad_start, input_pads,
1267 position,
1268 (AGS_FX_FACTORY_REMAP | AGS_FX_FACTORY_INPUT), 0);
1269
1270 g_list_free_full(start_recall,
1271 (GDestroyNotify) g_object_unref);
1272
1273 /* ags-fx-buffer */
1274 start_recall = ags_fx_factory_create(audio,
1275 pitch_sampler->buffer_play_container, pitch_sampler->buffer_recall_container,
1276 "ags-fx-buffer",
1277 NULL,
1278 NULL,
1279 audio_channel_start, audio_channels,
1280 input_pad_start, input_pads,
1281 position,
1282 (AGS_FX_FACTORY_REMAP | AGS_FX_FACTORY_INPUT), 0);
1283
1284 g_list_free_full(start_recall,
1285 (GDestroyNotify) g_object_unref);
1286
1287 pitch_sampler->mapped_input_pad = input_pads;
1288 }
1289
1290 void
ags_pitch_sampler_output_map_recall(AgsPitchSampler * pitch_sampler,guint audio_channel_start,guint output_pad_start)1291 ags_pitch_sampler_output_map_recall(AgsPitchSampler *pitch_sampler,
1292 guint audio_channel_start,
1293 guint output_pad_start)
1294 {
1295 AgsAudio *audio;
1296
1297 guint output_pads;
1298
1299 if(pitch_sampler->mapped_output_pad > output_pad_start){
1300 return;
1301 }
1302
1303 audio = AGS_MACHINE(pitch_sampler)->audio;
1304
1305 /* get some fields */
1306 g_object_get(audio,
1307 "output-pads", &output_pads,
1308 NULL);
1309
1310 pitch_sampler->mapped_output_pad = output_pads;
1311 }
1312
1313 /**
1314 * ags_pitch_sampler_add_file:
1315 * @pitch_sampler: the #AgsPitchSampler
1316 * @file: the #AgsPitchSamplerFile
1317 *
1318 * Add @file to @pitch_sampler.
1319 *
1320 * Since: 3.0.0
1321 */
1322 void
ags_pitch_sampler_add_file(AgsPitchSampler * pitch_sampler,AgsPitchSamplerFile * file)1323 ags_pitch_sampler_add_file(AgsPitchSampler *pitch_sampler,
1324 AgsPitchSamplerFile *file)
1325 {
1326 GtkBox *hbox;
1327 GtkCheckButton *check_button;
1328
1329 hbox = (GtkBox *) gtk_box_new(GTK_ORIENTATION_HORIZONTAL,
1330 0);
1331
1332 check_button = (GtkCheckButton *) gtk_check_button_new();
1333 gtk_box_pack_start(hbox,
1334 (GtkWidget *) check_button,
1335 FALSE,
1336 FALSE,
1337 0);
1338
1339 gtk_box_pack_start(hbox,
1340 (GtkWidget *) file,
1341 FALSE,
1342 FALSE,
1343 0);
1344
1345 gtk_box_pack_start(pitch_sampler->file,
1346 (GtkWidget *) hbox,
1347 FALSE,
1348 FALSE,
1349 0);
1350 gtk_widget_show_all((GtkWidget *) hbox);
1351 }
1352
1353 /**
1354 * ags_pitch_sampler_remove_file:
1355 * @pitch_sampler: the #AgsPitchSampler
1356 * @nth: the nth #AgsPitchSamplerFile
1357 *
1358 * Remove nth file.
1359 *
1360 * Since: 3.0.0
1361 */
1362 void
ags_pitch_sampler_remove_file(AgsPitchSampler * pitch_sampler,guint nth)1363 ags_pitch_sampler_remove_file(AgsPitchSampler *pitch_sampler,
1364 guint nth)
1365 {
1366 GList *list, *list_start;
1367
1368 list_start = gtk_container_get_children(GTK_CONTAINER(pitch_sampler->file));
1369
1370 list = g_list_nth(list_start,
1371 nth);
1372
1373 if(list != NULL){
1374 gtk_widget_destroy(list->data);
1375 }
1376
1377 g_list_free(list_start);
1378 }
1379
1380 /**
1381 * ags_pitch_sampler_open_filename:
1382 * @pitch_sampler: the #AgsPitchSampler
1383 * @filename: the filename
1384 *
1385 * Open @filename.
1386 *
1387 * Since: 3.0.0
1388 */
1389 void
ags_pitch_sampler_open_filename(AgsPitchSampler * pitch_sampler,gchar * filename)1390 ags_pitch_sampler_open_filename(AgsPitchSampler *pitch_sampler,
1391 gchar *filename)
1392 {
1393 AgsSFZLoader *sfz_loader;
1394
1395 if(!AGS_IS_PITCH_SAMPLER(pitch_sampler) ||
1396 filename == NULL){
1397 return;
1398 }
1399
1400 pitch_sampler->sfz_loader =
1401 sfz_loader = ags_sfz_loader_new(AGS_MACHINE(pitch_sampler)->audio,
1402 filename,
1403 TRUE);
1404
1405 ags_sfz_loader_start(sfz_loader);
1406 }
1407
1408 /**
1409 * ags_pitch_sampler_update:
1410 * @pitch_sampler: the #AgsPitchSampler
1411 *
1412 * Update @pitch_sampler.
1413 *
1414 * Since: 3.0.0
1415 */
1416 void
ags_pitch_sampler_update(AgsPitchSampler * pitch_sampler)1417 ags_pitch_sampler_update(AgsPitchSampler *pitch_sampler)
1418 {
1419 AgsAudio *audio;
1420 AgsChannel *start_input;
1421
1422 AgsAudioContainer *audio_container;
1423
1424 AgsResizeAudio *resize_audio;
1425 AgsApplySFZSynth *apply_sfz_synth;
1426 AgsOpenSFZFile *open_sfz_file;
1427
1428 AgsApplicationContext *application_context;
1429
1430 gchar *str;
1431
1432 gdouble lower;
1433 gdouble key_count;
1434 guint audio_channels;
1435 guint output_pads;
1436 guint pitch_type;
1437
1438 if(!AGS_IS_PITCH_SAMPLER(pitch_sampler)){
1439 return;
1440 }
1441
1442 application_context = ags_application_context_get_instance();
1443
1444 audio_container = pitch_sampler->audio_container;
1445
1446 if(audio_container == NULL){
1447 return;
1448 }
1449
1450 audio = AGS_MACHINE(pitch_sampler)->audio;
1451
1452 start_input = NULL;
1453
1454 g_object_get(audio,
1455 "input", &start_input,
1456 NULL);
1457
1458 /* */
1459 lower = gtk_spin_button_get_value(pitch_sampler->lower);
1460 key_count = gtk_spin_button_get_value(pitch_sampler->key_count);
1461
1462 audio_channels = AGS_MACHINE(pitch_sampler)->audio_channels;
1463
1464 output_pads = AGS_MACHINE(pitch_sampler)->output_pads;
1465
1466 /* pitch type */
1467 pitch_type = AGS_FLUID_4TH_ORDER_INTERPOLATE;
1468
1469 str = gtk_combo_box_text_get_active_text(pitch_sampler->pitch_function);
1470
1471 if(!g_ascii_strncasecmp(str,
1472 "ags-fast-pitch",
1473 16)){
1474 pitch_type = AGS_FAST_PITCH;
1475 }else if(!g_ascii_strncasecmp(str,
1476 "ags-hq-pitch",
1477 14)){
1478 pitch_type = AGS_HQ_PITCH;
1479 }else if(!g_ascii_strncasecmp(str,
1480 "fluid-no-interpolate",
1481 21)){
1482 pitch_type = AGS_FLUID_NO_INTERPOLATE;
1483 }else if(!g_ascii_strncasecmp(str,
1484 "fluid-linear-interpolate",
1485 26)){
1486 pitch_type = AGS_FLUID_LINEAR_INTERPOLATE;
1487 }else if(!g_ascii_strncasecmp(str,
1488 "fluid-4th-order-interpolate",
1489 29)){
1490 pitch_type = AGS_FLUID_4TH_ORDER_INTERPOLATE;
1491 }else if(!g_ascii_strncasecmp(str,
1492 "fluid-7th-order-interpolate",
1493 29)){
1494 pitch_type = AGS_FLUID_7TH_ORDER_INTERPOLATE;
1495 }
1496
1497 /* open sfz file */
1498 if(gtk_toggle_button_get_active((GtkToggleButton *) pitch_sampler->enable_synth_generator)){
1499 GList *start_sfz_synth_generator;
1500 GList *start_sound_resource;
1501
1502 guint requested_frame_count;
1503
1504 resize_audio = ags_resize_audio_new(audio,
1505 output_pads,
1506 key_count,
1507 audio_channels);
1508
1509 /* append task */
1510 ags_ui_provider_schedule_task(AGS_UI_PROVIDER(application_context),
1511 (AgsTask *) resize_audio);
1512
1513 start_sfz_synth_generator = NULL;
1514
1515 g_object_get(audio,
1516 "sfz-synth-generator", &start_sfz_synth_generator,
1517 NULL);
1518
1519 requested_frame_count = 0;
1520
1521 start_sound_resource = ags_audio_container_find_sound_resource(audio_container,
1522 NULL,
1523 NULL,
1524 NULL);
1525
1526 if(start_sound_resource != NULL){
1527 ags_sound_resource_info(AGS_SOUND_RESOURCE(start_sound_resource->data),
1528 &requested_frame_count,
1529 NULL, NULL);
1530 }
1531
1532 if(start_sfz_synth_generator != NULL){
1533 g_object_set(start_sfz_synth_generator->data,
1534 "filename", audio_container->filename,
1535 "frame-count", requested_frame_count,
1536 "pitch-type", pitch_type,
1537 NULL);
1538
1539 apply_sfz_synth = ags_apply_sfz_synth_new(start_sfz_synth_generator->data,
1540 start_input,
1541 lower, (guint) key_count);
1542
1543 g_object_set(apply_sfz_synth,
1544 "requested-frame-count", requested_frame_count,
1545 NULL);
1546
1547 /* append task */
1548 ags_ui_provider_schedule_task(AGS_UI_PROVIDER(application_context),
1549 (AgsTask *) apply_sfz_synth);
1550 }
1551
1552 g_list_free_full(start_sound_resource,
1553 (GDestroyNotify) g_object_unref);
1554
1555 g_list_free_full(start_sfz_synth_generator,
1556 (GDestroyNotify) g_object_unref);
1557 }else{
1558 open_sfz_file = ags_open_sfz_file_new(audio,
1559 AGS_SFZ_FILE(audio_container->sound_container),
1560 NULL,
1561 0);
1562
1563 /* append task */
1564 ags_ui_provider_schedule_task(AGS_UI_PROVIDER(application_context),
1565 (AgsTask *) open_sfz_file);
1566 }
1567 }
1568
1569 /**
1570 * ags_pitch_sampler_sfz_loader_completed_timeout:
1571 * @pitch_sampler: the #AgsPitchSampler
1572 *
1573 * Queue draw widget
1574 *
1575 * Returns: %TRUE if proceed poll completed, otherwise %FALSE
1576 *
1577 * Since: 3.0.0
1578 */
1579 gboolean
ags_pitch_sampler_sfz_loader_completed_timeout(AgsPitchSampler * pitch_sampler)1580 ags_pitch_sampler_sfz_loader_completed_timeout(AgsPitchSampler *pitch_sampler)
1581 {
1582 if(g_hash_table_lookup(ags_pitch_sampler_sfz_loader_completed,
1583 pitch_sampler) != NULL){
1584 if(pitch_sampler->sfz_loader != NULL){
1585 if(ags_sfz_loader_test_flags(pitch_sampler->sfz_loader, AGS_SFZ_LOADER_HAS_COMPLETED)){
1586 AgsPitchSamplerFile *file;
1587
1588 GList *start_list, *list;
1589
1590 /* file */
1591 list =
1592 start_list = gtk_container_get_children(GTK_CONTAINER(pitch_sampler->file));
1593
1594 while(list != NULL){
1595 gtk_widget_destroy(list->data);
1596
1597 list = list->next;
1598 }
1599
1600 g_list_free(start_list);
1601
1602 /* reassign audio container */
1603 pitch_sampler->audio_container = pitch_sampler->sfz_loader->audio_container;
1604 pitch_sampler->sfz_loader->audio_container = NULL;
1605
1606 g_object_get(pitch_sampler->audio_container->sound_container,
1607 "sample", &start_list,
1608 NULL);
1609
1610 list = start_list;
1611
1612 while(list != NULL){
1613 AgsSFZGroup *group;
1614 AgsSFZRegion *region;
1615
1616 gchar *filename;
1617 gchar *str_key, *str_pitch_keycenter;
1618 gchar *str;
1619
1620 glong current_key;
1621 glong pitch_keycenter, current_pitch_keycenter;
1622 guint loop_start, loop_end;
1623 int retval;
1624
1625 file = ags_pitch_sampler_file_new();
1626 ags_pitch_sampler_add_file(pitch_sampler,
1627 file);
1628 ags_connectable_connect(AGS_CONNECTABLE(file));
1629
1630 /* pitch keycenter */
1631 g_object_get(list->data,
1632 "group", &group,
1633 "region", ®ion,
1634 "filename", &filename,
1635 NULL);
1636
1637 pitch_keycenter = 49;
1638
1639 /* group */
1640 str_pitch_keycenter = ags_sfz_group_lookup_control(group,
1641 "pitch_keycenter");
1642
1643 str_key = ags_sfz_group_lookup_control(group,
1644 "key");
1645
1646 if(str_pitch_keycenter != NULL){
1647 retval = sscanf(str_pitch_keycenter, "%lu", ¤t_pitch_keycenter);
1648
1649 if(retval > 0){
1650 pitch_keycenter = current_pitch_keycenter;
1651 }else{
1652 retval = ags_diatonic_scale_note_to_midi_key(str_pitch_keycenter,
1653 ¤t_key);
1654
1655 if(retval > 0){
1656 pitch_keycenter = current_key;
1657 }
1658 }
1659 }else if(str_key != NULL){
1660 retval = sscanf(str_key, "%lu", ¤t_pitch_keycenter);
1661
1662 if(retval > 0){
1663 pitch_keycenter = current_pitch_keycenter;
1664 }else{
1665 retval = ags_diatonic_scale_note_to_midi_key(str_key,
1666 ¤t_key);
1667
1668 if(retval > 0){
1669 pitch_keycenter = current_key;
1670 }
1671 }
1672 }
1673
1674 /* region */
1675 str_pitch_keycenter = ags_sfz_region_lookup_control(region,
1676 "pitch_keycenter");
1677
1678 str_key = ags_sfz_region_lookup_control(region,
1679 "key");
1680
1681 if(str_pitch_keycenter != NULL){
1682 retval = sscanf(str_pitch_keycenter, "%lu", ¤t_pitch_keycenter);
1683
1684 if(retval > 0){
1685 pitch_keycenter = current_pitch_keycenter;
1686 }else{
1687 retval = ags_diatonic_scale_note_to_midi_key(str_pitch_keycenter,
1688 ¤t_key);
1689
1690 if(retval > 0){
1691 pitch_keycenter = current_key;
1692 }
1693 }
1694 }else if(str_key != NULL){
1695 retval = sscanf(str_key, "%lu", ¤t_pitch_keycenter);
1696
1697 if(retval > 0){
1698 pitch_keycenter = current_pitch_keycenter;
1699 }else{
1700 retval = ags_diatonic_scale_note_to_midi_key(str_key,
1701 ¤t_key);
1702
1703 if(retval > 0){
1704 pitch_keycenter = current_key;
1705 }
1706 }
1707 }
1708
1709 /* set filename */
1710 gtk_entry_set_text(file->filename,
1711 filename);
1712 g_free(filename);
1713
1714 /* set pitch keycenter */
1715 str = g_strdup_printf("%f",
1716 27.5 * exp2((gdouble) pitch_keycenter / 12.0));
1717 gtk_label_set_text(file->freq,
1718 str);
1719
1720 g_free(str);
1721
1722 str = g_strdup_printf("%ld",
1723 pitch_keycenter);
1724 gtk_label_set_text(file->base_key,
1725 str);
1726
1727 g_free(str);
1728
1729 /* set loop start/end */
1730 g_object_get(list->data,
1731 "loop-start", &loop_start,
1732 "loop-end", &loop_end,
1733 NULL);
1734
1735 str = g_strdup_printf("%d",
1736 loop_start);
1737 gtk_label_set_text(file->loop_start,
1738 str);
1739
1740 g_free(str);
1741
1742 str = g_strdup_printf("%d",
1743 loop_end);
1744 gtk_label_set_text(file->loop_end,
1745 str);
1746
1747 g_free(str);
1748
1749 /* iterate */
1750 list = list->next;
1751 }
1752
1753 g_list_free_full(start_list,
1754 g_object_unref);
1755
1756 /* cleanup */
1757 g_object_run_dispose((GObject *) pitch_sampler->sfz_loader);
1758 g_object_unref(pitch_sampler->sfz_loader);
1759
1760 pitch_sampler->sfz_loader = NULL;
1761
1762 pitch_sampler->position = -1;
1763 gtk_widget_hide((GtkWidget *) pitch_sampler->loading);
1764
1765 }else{
1766 if(pitch_sampler->position == -1){
1767 pitch_sampler->position = 0;
1768
1769 gtk_widget_show((GtkWidget *) pitch_sampler->loading);
1770 }
1771
1772 switch(pitch_sampler->position){
1773 case 0:
1774 {
1775 pitch_sampler->position = 1;
1776
1777 gtk_label_set_label(pitch_sampler->loading,
1778 "loading ... ");
1779 }
1780 break;
1781 case 1:
1782 {
1783 pitch_sampler->position = 2;
1784
1785 gtk_label_set_label(pitch_sampler->loading,
1786 "loading ... ");
1787 }
1788 break;
1789 case 2:
1790 {
1791 pitch_sampler->position = 0;
1792
1793 gtk_label_set_label(pitch_sampler->loading,
1794 "loading ...");
1795 }
1796 break;
1797 }
1798 }
1799 }
1800
1801 return(TRUE);
1802 }else{
1803 return(FALSE);
1804 }
1805 }
1806
1807 /**
1808 * ags_pitch_sampler_new:
1809 * @soundcard: the assigned soundcard.
1810 *
1811 * Create a new instance of #AgsPitchSampler
1812 *
1813 * Returns: the new #AgsPitchSampler
1814 *
1815 * Since: 3.0.0
1816 */
1817 AgsPitchSampler*
ags_pitch_sampler_new(GObject * output_soundcard)1818 ags_pitch_sampler_new(GObject *output_soundcard)
1819 {
1820 AgsPitchSampler *pitch_sampler;
1821
1822 pitch_sampler = (AgsPitchSampler *) g_object_new(AGS_TYPE_PITCH_SAMPLER,
1823 NULL);
1824
1825 if(output_soundcard != NULL){
1826 g_object_set(AGS_MACHINE(pitch_sampler)->audio,
1827 "output-soundcard", output_soundcard,
1828 NULL);
1829 }
1830
1831 return(pitch_sampler);
1832 }
1833