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/audio/ags_sfz_synth_generator.h>
21 
22 #include <ags/audio/ags_diatonic_scale.h>
23 #include <ags/audio/ags_audio_signal.h>
24 #include <ags/audio/ags_audio_buffer_util.h>
25 #include <ags/audio/ags_generic_pitch_util.h>
26 #include <ags/audio/ags_sfz_synth_util.h>
27 
28 #include <ags/audio/file/ags_audio_container.h>
29 #include <ags/audio/file/ags_audio_container_manager.h>
30 #include <ags/audio/file/ags_sfz_sample.h>
31 
32 #include <math.h>
33 
34 #include <ags/i18n.h>
35 
36 void ags_sfz_synth_generator_class_init(AgsSFZSynthGeneratorClass *sfz_synth_generator);
37 void ags_sfz_synth_generator_init(AgsSFZSynthGenerator *sfz_synth_generator);
38 void ags_sfz_synth_generator_set_property(GObject *gobject,
39 					  guint prop_id,
40 					  const GValue *value,
41 					  GParamSpec *param_spec);
42 void ags_sfz_synth_generator_get_property(GObject *gobject,
43 					  guint prop_id,
44 					  GValue *value,
45 					  GParamSpec *param_spec);
46 void ags_sfz_synth_generator_finalize(GObject *gobject);
47 
48 /**
49  * SECTION:ags_sfz_synth_generator
50  * @short_description: generate wave-form
51  * @title: AgsSFZSynthGenerator
52  * @section_id:
53  * @include: ags/file/ags_sfz_synth_generator.h
54  *
55  * The #AgsSFZSynthGenerator generates wave-forms with oscillators.
56  */
57 
58 enum{
59   PROP_0,
60   PROP_FILENAME,
61   PROP_SAMPLERATE,
62   PROP_BUFFER_SIZE,
63   PROP_FORMAT,
64   PROP_PITCH_TYPE,
65   PROP_DELAY,
66   PROP_ATTACK,
67   PROP_FRAME_COUNT,
68   PROP_LOOP_START,
69   PROP_LOOP_END,
70   PROP_VOLUME,
71   PROP_BASE_KEY,
72   PROP_TUNING,
73   PROP_TIMESTAMP,
74 };
75 
76 static gpointer ags_sfz_synth_generator_parent_class = NULL;
77 
78 
79 GType
ags_sfz_synth_generator_get_type()80 ags_sfz_synth_generator_get_type()
81 {
82   static volatile gsize g_define_type_id__volatile = 0;
83 
84   if(g_once_init_enter (&g_define_type_id__volatile)){
85     GType ags_type_sfz_synth_generator = 0;
86 
87     static const GTypeInfo ags_sfz_synth_generator_info = {
88       sizeof (AgsSFZSynthGeneratorClass),
89       NULL, /* base_init */
90       NULL, /* base_finalize */
91       (GClassInitFunc) ags_sfz_synth_generator_class_init,
92       NULL, /* class_finalize */
93       NULL, /* class_data */
94       sizeof (AgsSFZSynthGenerator),
95       0,    /* n_preallocs */
96       (GInstanceInitFunc) ags_sfz_synth_generator_init,
97     };
98 
99     ags_type_sfz_synth_generator = g_type_register_static(AGS_TYPE_FUNCTION,
100 							  "AgsSFZSynthGenerator",
101 							  &ags_sfz_synth_generator_info,
102 							  0);
103 
104     g_once_init_leave(&g_define_type_id__volatile, ags_type_sfz_synth_generator);
105   }
106 
107   return g_define_type_id__volatile;
108 }
109 
110 void
ags_sfz_synth_generator_class_init(AgsSFZSynthGeneratorClass * sfz_synth_generator)111 ags_sfz_synth_generator_class_init(AgsSFZSynthGeneratorClass *sfz_synth_generator)
112 {
113   GObjectClass *gobject;
114   GParamSpec *param_spec;
115 
116   ags_sfz_synth_generator_parent_class = g_type_class_peek_parent(sfz_synth_generator);
117 
118   /* GObjectClass */
119   gobject = (GObjectClass *) sfz_synth_generator;
120 
121   gobject->set_property = ags_sfz_synth_generator_set_property;
122   gobject->get_property = ags_sfz_synth_generator_get_property;
123 
124   gobject->finalize = ags_sfz_synth_generator_finalize;
125 
126   /* properties */
127   /**
128    * AgsSFZSynthGenerator:filename:
129    *
130    * The assigned filename.
131    *
132    * Since: 3.4.0
133    */
134   param_spec = g_param_spec_string("filename",
135 				   i18n_pspec("filename of audio container"),
136 				   i18n_pspec("The filename of audio container"),
137 				   NULL,
138 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
139   g_object_class_install_property(gobject,
140 				  PROP_FILENAME,
141 				  param_spec);
142 
143   /**
144    * AgsSFZSynthGenerator:samplerate:
145    *
146    * The samplerate to be used.
147    *
148    * Since: 3.4.0
149    */
150   param_spec = g_param_spec_uint("samplerate",
151 				 i18n_pspec("using samplerate"),
152 				 i18n_pspec("The samplerate to be used"),
153 				 0,
154 				 G_MAXUINT32,
155 				 AGS_SFZ_SYNTH_GENERATOR_DEFAULT_SAMPLERATE,
156 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
157   g_object_class_install_property(gobject,
158 				  PROP_SAMPLERATE,
159 				  param_spec);
160 
161   /**
162    * AgsSFZSynthGenerator:buffer-size:
163    *
164    * The buffer size to be used.
165    *
166    * Since: 3.4.0
167    */
168   param_spec = g_param_spec_uint("buffer-size",
169 				 i18n_pspec("using buffer size"),
170 				 i18n_pspec("The buffer size to be used"),
171 				 0,
172 				 G_MAXUINT32,
173 				 AGS_SFZ_SYNTH_GENERATOR_DEFAULT_BUFFER_SIZE,
174 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
175   g_object_class_install_property(gobject,
176 				  PROP_BUFFER_SIZE,
177 				  param_spec);
178 
179   /**
180    * AgsSFZSynthGenerator:format:
181    *
182    * The format to be used.
183    *
184    * Since: 3.4.0
185    */
186   param_spec = g_param_spec_uint("format",
187 				 i18n_pspec("using format"),
188 				 i18n_pspec("The format to be used"),
189 				 0,
190 				 G_MAXUINT32,
191 				 AGS_SFZ_SYNTH_GENERATOR_DEFAULT_FORMAT,
192 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
193   g_object_class_install_property(gobject,
194 				  PROP_FORMAT,
195 				  param_spec);
196 
197   /**
198    * AgsSFZSynthGenerator:pitch-type:
199    *
200    * The pitch type to be used.
201    *
202    * Since: 3.9.0
203    */
204   param_spec = g_param_spec_uint("pitch-type",
205 				 i18n_pspec("using pitch type"),
206 				 i18n_pspec("The pitch type to be used"),
207 				 0,
208 				 G_MAXUINT32,
209 				 AGS_FLUID_4TH_ORDER_INTERPOLATE,
210 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
211   g_object_class_install_property(gobject,
212 				  PROP_PITCH_TYPE,
213 				  param_spec);
214 
215   /**
216    * AgsSFZSynthGenerator:frame-count:
217    *
218    * The frame count to be used.
219    *
220    * Since: 3.4.0
221    */
222   param_spec = g_param_spec_uint("frame-count",
223 				 i18n_pspec("apply frame count"),
224 				 i18n_pspec("To apply frame count"),
225 				 0,
226 				 G_MAXUINT32,
227 				 0,
228 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
229   g_object_class_install_property(gobject,
230 				  PROP_FRAME_COUNT,
231 				  param_spec);
232 
233   /**
234    * AgsSFZSynthGenerator:loop-start:
235    *
236    * The loop start to be used.
237    *
238    * Since: 3.4.0
239    */
240   param_spec = g_param_spec_uint("loop-start",
241 				 i18n_pspec("loop start"),
242 				 i18n_pspec("The loop start"),
243 				 0,
244 				 G_MAXUINT32,
245 				 0,
246 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
247   g_object_class_install_property(gobject,
248 				  PROP_LOOP_START,
249 				  param_spec);
250 
251   /**
252    * AgsSFZSynthGenerator:loop-end:
253    *
254    * The loop end to be used.
255    *
256    * Since: 3.4.0
257    */
258   param_spec = g_param_spec_uint("loop-end",
259 				 i18n_pspec("loop end"),
260 				 i18n_pspec("To loop end"),
261 				 0,
262 				 G_MAXUINT32,
263 				 0,
264 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
265   g_object_class_install_property(gobject,
266 				  PROP_LOOP_END,
267 				  param_spec);
268 
269 
270   /**
271    * AgsSFZSynthGenerator:delay:
272    *
273    * The delay to be used.
274    *
275    * Since: 3.4.11
276    */
277   param_spec = g_param_spec_double("delay",
278 				   i18n_pspec("using delay"),
279 				   i18n_pspec("The delay to be used"),
280 				   0.0,
281 				   65535.0,
282 				   0.0,
283 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
284   g_object_class_install_property(gobject,
285 				  PROP_DELAY,
286 				  param_spec);
287 
288   /**
289    * AgsSFZSynthGenerator:attack:
290    *
291    * The attack to be used.
292    *
293    * Since: 3.4.11
294    */
295   param_spec = g_param_spec_uint("attack",
296 				 i18n_pspec("apply attack"),
297 				 i18n_pspec("To apply attack"),
298 				 0,
299 				 G_MAXUINT32,
300 				 0,
301 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
302   g_object_class_install_property(gobject,
303 				  PROP_ATTACK,
304 				  param_spec);
305 
306   /**
307    * AgsSFZSynthGenerator:volume:
308    *
309    * The volume to be used.
310    *
311    * Since: 3.4.11
312    */
313   param_spec = g_param_spec_double("volume",
314 				   i18n_pspec("using volume"),
315 				   i18n_pspec("The volume to be used"),
316 				   0.0,
317 				   2.0,
318 				   AGS_SFZ_SYNTH_GENERATOR_DEFAULT_VOLUME,
319 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
320   g_object_class_install_property(gobject,
321 				  PROP_VOLUME,
322 				  param_spec);
323 
324   /**
325    * AgsSFZSynthGenerator:tuning:
326    *
327    * The tuning to be used.
328    *
329    * Since: 3.4.0
330    */
331   param_spec = g_param_spec_double("tuning",
332 				   i18n_pspec("using tuning"),
333 				   i18n_pspec("The tuning to be used"),
334 				   0.0,
335 				   1200.0,
336 				   AGS_SFZ_SYNTH_GENERATOR_DEFAULT_TUNING,
337 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
338   g_object_class_install_property(gobject,
339 				  PROP_TUNING,
340 				  param_spec);
341 
342   /**
343    * AgsSFZSynthGenerator:base_key:
344    *
345    * The base_key to be used.
346    *
347    * Since: 3.4.0
348    */
349   param_spec = g_param_spec_double("base_key",
350 				   i18n_pspec("using base_key"),
351 				   i18n_pspec("The base_key to be used"),
352 				   -65535.0,
353 				   65535.0,
354 				   AGS_SFZ_SYNTH_GENERATOR_DEFAULT_BASE_KEY,
355 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
356   g_object_class_install_property(gobject,
357 				  PROP_BASE_KEY,
358 				  param_spec);
359 }
360 
361 void
ags_sfz_synth_generator_init(AgsSFZSynthGenerator * sfz_synth_generator)362 ags_sfz_synth_generator_init(AgsSFZSynthGenerator *sfz_synth_generator)
363 {
364   AgsConfig *config;
365 
366   sfz_synth_generator->flags = 0;
367 
368   /* sfz synth generator mutex */
369   g_rec_mutex_init(&(sfz_synth_generator->obj_mutex));
370 
371   /* config */
372   config = ags_config_get_instance();
373 
374   sfz_synth_generator->filename = NULL;
375 
376   /* presets */
377   sfz_synth_generator->samplerate = ags_soundcard_helper_config_get_samplerate(config);
378   sfz_synth_generator->buffer_size = ags_soundcard_helper_config_get_buffer_size(config);
379   sfz_synth_generator->format = ags_soundcard_helper_config_get_format(config);
380 
381   sfz_synth_generator->pitch_type = AGS_FLUID_4TH_ORDER_INTERPOLATE;
382 
383   /* more base init */
384   sfz_synth_generator->frame_count = 0;
385   sfz_synth_generator->loop_start = 0;
386   sfz_synth_generator->loop_end = 0;
387 
388   sfz_synth_generator->delay = 0.0;
389   sfz_synth_generator->attack = 0;
390 
391   sfz_synth_generator->volume = AGS_SFZ_SYNTH_GENERATOR_DEFAULT_VOLUME;
392 
393   sfz_synth_generator->base_key = AGS_SFZ_SYNTH_GENERATOR_DEFAULT_BASE_KEY;
394   sfz_synth_generator->tuning = AGS_SFZ_SYNTH_GENERATOR_DEFAULT_TUNING;
395 
396   sfz_synth_generator->sfz = (AgsSFZ *) g_new0(AgsSFZ,
397 					       1);
398 
399   sfz_synth_generator->sfz->generic_pitch = (gpointer) g_new0(AgsGenericPitch,
400 							      1);
401 
402   /* timestamp */
403   sfz_synth_generator->timestamp = NULL;
404 }
405 
406 
407 void
ags_sfz_synth_generator_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)408 ags_sfz_synth_generator_set_property(GObject *gobject,
409 				     guint prop_id,
410 				     const GValue *value,
411 				     GParamSpec *param_spec)
412 {
413   AgsSFZSynthGenerator *sfz_synth_generator;
414 
415   GRecMutex *sfz_synth_generator_mutex;
416 
417   sfz_synth_generator = AGS_SFZ_SYNTH_GENERATOR(gobject);
418 
419   /* get sfz synth generator mutex */
420   sfz_synth_generator_mutex = AGS_SFZ_SYNTH_GENERATOR_GET_OBJ_MUTEX(sfz_synth_generator);
421 
422   switch(prop_id){
423   case PROP_FILENAME:
424   {
425     gchar *filename;
426 
427     filename = (gchar *) g_value_get_string(value);
428 
429     g_rec_mutex_lock(sfz_synth_generator_mutex);
430 
431     if(sfz_synth_generator->filename == filename){
432       g_rec_mutex_unlock(sfz_synth_generator_mutex);
433 
434       return;
435     }
436 
437     if(sfz_synth_generator->filename != NULL){
438       g_free(sfz_synth_generator->filename);
439     }
440 
441     sfz_synth_generator->filename = g_strdup(filename);
442 
443     g_rec_mutex_unlock(sfz_synth_generator_mutex);
444   }
445   break;
446   case PROP_SAMPLERATE:
447   {
448     guint samplerate;
449 
450     samplerate = g_value_get_uint(value);
451 
452     ags_sfz_synth_generator_set_samplerate(sfz_synth_generator,
453 					   samplerate);
454   }
455   break;
456   case PROP_BUFFER_SIZE:
457   {
458     guint buffer_size;
459 
460     buffer_size = g_value_get_uint(value);
461 
462     ags_sfz_synth_generator_set_buffer_size(sfz_synth_generator,
463 					    buffer_size);
464   }
465   break;
466   case PROP_FORMAT:
467   {
468     guint format;
469 
470     format = g_value_get_uint(value);
471 
472     ags_sfz_synth_generator_set_format(sfz_synth_generator,
473 				       format);
474   }
475   break;
476   case PROP_PITCH_TYPE:
477   {
478     guint pitch_type;
479 
480     pitch_type = g_value_get_uint(value);
481 
482     ags_sfz_synth_generator_set_pitch_type(sfz_synth_generator,
483 					   pitch_type);
484   }
485   break;
486   case PROP_DELAY:
487   {
488     g_rec_mutex_lock(sfz_synth_generator_mutex);
489 
490     sfz_synth_generator->delay = g_value_get_double(value);
491 
492     g_rec_mutex_unlock(sfz_synth_generator_mutex);
493   }
494   break;
495   case PROP_ATTACK:
496   {
497     g_rec_mutex_lock(sfz_synth_generator_mutex);
498 
499     sfz_synth_generator->attack = g_value_get_uint(value);
500 
501     g_rec_mutex_unlock(sfz_synth_generator_mutex);
502   }
503   break;
504   case PROP_FRAME_COUNT:
505   {
506     g_rec_mutex_lock(sfz_synth_generator_mutex);
507 
508     sfz_synth_generator->frame_count = g_value_get_uint(value);
509 
510     g_rec_mutex_unlock(sfz_synth_generator_mutex);
511   }
512   break;
513   case PROP_LOOP_START:
514   {
515     g_rec_mutex_lock(sfz_synth_generator_mutex);
516 
517     sfz_synth_generator->loop_start = g_value_get_uint(value);
518 
519     g_rec_mutex_unlock(sfz_synth_generator_mutex);
520   }
521   break;
522   case PROP_LOOP_END:
523   {
524     g_rec_mutex_lock(sfz_synth_generator_mutex);
525 
526     sfz_synth_generator->loop_end = g_value_get_uint(value);
527 
528     g_rec_mutex_unlock(sfz_synth_generator_mutex);
529   }
530   break;
531   case PROP_VOLUME:
532   {
533     g_rec_mutex_lock(sfz_synth_generator_mutex);
534 
535     sfz_synth_generator->volume = g_value_get_double(value);
536 
537     g_rec_mutex_unlock(sfz_synth_generator_mutex);
538   }
539   break;
540   case PROP_BASE_KEY:
541   {
542     g_rec_mutex_lock(sfz_synth_generator_mutex);
543 
544     sfz_synth_generator->base_key = g_value_get_double(value);
545 
546     g_rec_mutex_unlock(sfz_synth_generator_mutex);
547   }
548   break;
549   case PROP_TUNING:
550   {
551     g_rec_mutex_lock(sfz_synth_generator_mutex);
552 
553     sfz_synth_generator->tuning = g_value_get_double(value);
554 
555     g_rec_mutex_unlock(sfz_synth_generator_mutex);
556   }
557   break;
558   case PROP_TIMESTAMP:
559   {
560     AgsTimestamp *timestamp;
561 
562     timestamp = (AgsTimestamp *) g_value_get_object(value);
563 
564     g_rec_mutex_lock(sfz_synth_generator_mutex);
565 
566     if(sfz_synth_generator->timestamp == (GObject *) timestamp){
567       g_rec_mutex_unlock(sfz_synth_generator_mutex);
568 
569       return;
570     }
571 
572     if(sfz_synth_generator->timestamp != NULL){
573       g_object_unref(sfz_synth_generator->timestamp);
574     }
575 
576     if(timestamp != NULL){
577       g_object_ref(timestamp);
578     }
579 
580     sfz_synth_generator->timestamp = (GObject *) timestamp;
581 
582     g_rec_mutex_unlock(sfz_synth_generator_mutex);
583   }
584   break;
585   default:
586     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
587     break;
588   }
589 }
590 
591 void
ags_sfz_synth_generator_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)592 ags_sfz_synth_generator_get_property(GObject *gobject,
593 				     guint prop_id,
594 				     GValue *value,
595 				     GParamSpec *param_spec)
596 {
597   AgsSFZSynthGenerator *sfz_synth_generator;
598 
599   GRecMutex *sfz_synth_generator_mutex;
600 
601   sfz_synth_generator = AGS_SFZ_SYNTH_GENERATOR(gobject);
602 
603   /* get sfz synth generator mutex */
604   sfz_synth_generator_mutex = AGS_SFZ_SYNTH_GENERATOR_GET_OBJ_MUTEX(sfz_synth_generator);
605 
606   switch(prop_id){
607   case PROP_FILENAME:
608   {
609     g_rec_mutex_lock(sfz_synth_generator_mutex);
610 
611     g_value_set_string(value, sfz_synth_generator->filename);
612 
613     g_rec_mutex_unlock(sfz_synth_generator_mutex);
614   }
615   break;
616   case PROP_SAMPLERATE:
617   {
618     g_rec_mutex_lock(sfz_synth_generator_mutex);
619 
620     g_value_set_uint(value, sfz_synth_generator->samplerate);
621 
622     g_rec_mutex_unlock(sfz_synth_generator_mutex);
623   }
624   break;
625   case PROP_BUFFER_SIZE:
626   {
627     g_rec_mutex_lock(sfz_synth_generator_mutex);
628 
629     g_value_set_uint(value, sfz_synth_generator->buffer_size);
630 
631     g_rec_mutex_unlock(sfz_synth_generator_mutex);
632   }
633   break;
634   case PROP_FORMAT:
635   {
636     g_rec_mutex_lock(sfz_synth_generator_mutex);
637 
638     g_value_set_uint(value, sfz_synth_generator->format);
639 
640     g_rec_mutex_unlock(sfz_synth_generator_mutex);
641   }
642   break;
643   case PROP_PITCH_TYPE:
644   {
645     g_rec_mutex_lock(sfz_synth_generator_mutex);
646 
647     g_value_set_uint(value, sfz_synth_generator->pitch_type);
648 
649     g_rec_mutex_unlock(sfz_synth_generator_mutex);
650   }
651   break;
652   case PROP_DELAY:
653   {
654     g_rec_mutex_lock(sfz_synth_generator_mutex);
655 
656     g_value_set_double(value, sfz_synth_generator->delay);
657 
658     g_rec_mutex_unlock(sfz_synth_generator_mutex);
659   }
660   break;
661   case PROP_ATTACK:
662   {
663     g_rec_mutex_lock(sfz_synth_generator_mutex);
664 
665     g_value_set_uint(value, sfz_synth_generator->attack);
666 
667     g_rec_mutex_unlock(sfz_synth_generator_mutex);
668   }
669   break;
670   case PROP_FRAME_COUNT:
671   {
672     g_rec_mutex_lock(sfz_synth_generator_mutex);
673 
674     g_value_set_uint(value, sfz_synth_generator->frame_count);
675 
676     g_rec_mutex_unlock(sfz_synth_generator_mutex);
677   }
678   break;
679   case PROP_LOOP_START:
680   {
681     g_rec_mutex_lock(sfz_synth_generator_mutex);
682 
683     g_value_set_uint(value, sfz_synth_generator->loop_start);
684 
685     g_rec_mutex_unlock(sfz_synth_generator_mutex);
686   }
687   break;
688   case PROP_LOOP_END:
689   {
690     g_rec_mutex_lock(sfz_synth_generator_mutex);
691 
692     g_value_set_uint(value, sfz_synth_generator->loop_end);
693 
694     g_rec_mutex_unlock(sfz_synth_generator_mutex);
695   }
696   break;
697   case PROP_VOLUME:
698   {
699     g_rec_mutex_lock(sfz_synth_generator_mutex);
700 
701     g_value_set_double(value, sfz_synth_generator->volume);
702 
703     g_rec_mutex_unlock(sfz_synth_generator_mutex);
704   }
705   break;
706   case PROP_BASE_KEY:
707   {
708     g_rec_mutex_lock(sfz_synth_generator_mutex);
709 
710     g_value_set_double(value, sfz_synth_generator->base_key);
711 
712     g_rec_mutex_unlock(sfz_synth_generator_mutex);
713   }
714   break;
715   case PROP_TUNING:
716   {
717     g_rec_mutex_lock(sfz_synth_generator_mutex);
718 
719     g_value_set_double(value, sfz_synth_generator->tuning);
720 
721     g_rec_mutex_unlock(sfz_synth_generator_mutex);
722   }
723   break;
724   case PROP_TIMESTAMP:
725   {
726     g_rec_mutex_lock(sfz_synth_generator_mutex);
727 
728     g_value_set_object(value, sfz_synth_generator->timestamp);
729 
730     g_rec_mutex_unlock(sfz_synth_generator_mutex);
731   }
732   break;
733   default:
734     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
735     break;
736   }
737 }
738 
739 void
ags_sfz_synth_generator_finalize(GObject * gobject)740 ags_sfz_synth_generator_finalize(GObject *gobject)
741 {
742   AgsSFZSynthGenerator *sfz_synth_generator;
743 
744   sfz_synth_generator = AGS_SFZ_SYNTH_GENERATOR(gobject);
745 
746   if(sfz_synth_generator->timestamp != NULL){
747     g_object_unref(sfz_synth_generator->timestamp);
748   }
749 
750   /* finalize */
751   G_OBJECT_CLASS(ags_sfz_synth_generator_parent_class)->finalize(gobject);
752 }
753 
754 /**
755  * ags_sfz_synth_generator_get_obj_mutex:
756  * @sfz_synth_generator: the #AgsSFZSynthGenerator
757  *
758  * Get object mutex.
759  *
760  * Returns: the #GRecMutex to lock @sfz_synth_generator
761  *
762  * Since: 3.4.0
763  */
764 GRecMutex*
ags_sfz_synth_generator_get_obj_mutex(AgsSFZSynthGenerator * sfz_synth_generator)765 ags_sfz_synth_generator_get_obj_mutex(AgsSFZSynthGenerator *sfz_synth_generator)
766 {
767   if(!AGS_IS_SFZ_SYNTH_GENERATOR(sfz_synth_generator)){
768     return(NULL);
769   }
770 
771   return(AGS_SFZ_SYNTH_GENERATOR_GET_OBJ_MUTEX(sfz_synth_generator));
772 }
773 
774 /**
775  * ags_sfz_synth_generator_get_filename:
776  * @sfz_synth_generator: the #AgsSFZSynthGenerator
777  *
778  * Gets filename.
779  *
780  * Returns: the filename
781  *
782  * Since: 3.4.0
783  */
784 gchar*
ags_sfz_synth_generator_get_filename(AgsSFZSynthGenerator * sfz_synth_generator)785 ags_sfz_synth_generator_get_filename(AgsSFZSynthGenerator *sfz_synth_generator)
786 {
787   gchar *filename;
788 
789   if(!AGS_IS_SFZ_SYNTH_GENERATOR(sfz_synth_generator)){
790     return(NULL);
791   }
792 
793   g_object_get(sfz_synth_generator,
794 	       "filename", &filename,
795 	       NULL);
796 
797   return(filename);
798 }
799 
800 /**
801  * ags_sfz_synth_generator_set_filename:
802  * @sfz_synth_generator: the #AgsSFZSynthGenerator
803  * @filename: the filename
804  *
805  * Set filename.
806  *
807  * Since: 3.4.0
808  */
809 void
ags_sfz_synth_generator_set_filename(AgsSFZSynthGenerator * sfz_synth_generator,gchar * filename)810 ags_sfz_synth_generator_set_filename(AgsSFZSynthGenerator *sfz_synth_generator, gchar *filename)
811 {
812   if(!AGS_IS_SFZ_SYNTH_GENERATOR(sfz_synth_generator)){
813     return;
814   }
815 
816   g_object_set(sfz_synth_generator,
817 	       "filename", filename,
818 	       NULL);
819 }
820 
821 /**
822  * ags_sfz_synth_generator_get_samplerate:
823  * @sfz_synth_generator: the #AgsSFZSynthGenerator
824  *
825  * Gets samplerate.
826  *
827  * Returns: the samplerate
828  *
829  * Since: 3.4.0
830  */
831 guint
ags_sfz_synth_generator_get_samplerate(AgsSFZSynthGenerator * sfz_synth_generator)832 ags_sfz_synth_generator_get_samplerate(AgsSFZSynthGenerator *sfz_synth_generator)
833 {
834   guint samplerate;
835 
836   if(!AGS_IS_SFZ_SYNTH_GENERATOR(sfz_synth_generator)){
837     return(0);
838   }
839 
840   g_object_get(sfz_synth_generator,
841 	       "samplerate", &samplerate,
842 	       NULL);
843 
844   return(samplerate);
845 }
846 
847 /**
848  * ags_sfz_synth_generator_set_samplerate:
849  * @sfz_synth_generator: the #AgsSFZSynthGenerator
850  * @samplerate: the samplerate
851  *
852  * Set samplerate.
853  *
854  * Since: 3.4.0
855  */
856 void
ags_sfz_synth_generator_set_samplerate(AgsSFZSynthGenerator * sfz_synth_generator,guint samplerate)857 ags_sfz_synth_generator_set_samplerate(AgsSFZSynthGenerator *sfz_synth_generator, guint samplerate)
858 {
859   guint old_samplerate;
860   guint i;
861 
862   GRecMutex *sfz_synth_generator_mutex;
863 
864   if(!AGS_IS_SFZ_SYNTH_GENERATOR(sfz_synth_generator)){
865     return;
866   }
867 
868   /* get sfz synth generator mutex */
869   sfz_synth_generator_mutex = AGS_SFZ_SYNTH_GENERATOR_GET_OBJ_MUTEX(sfz_synth_generator);
870 
871   g_rec_mutex_lock(sfz_synth_generator_mutex);
872 
873   old_samplerate = sfz_synth_generator->samplerate;
874 
875   if(old_samplerate == samplerate){
876     g_rec_mutex_unlock(sfz_synth_generator_mutex);
877 
878     return;
879   }
880 
881   sfz_synth_generator->samplerate = samplerate;
882 
883   sfz_synth_generator->frame_count = samplerate * (sfz_synth_generator->frame_count / old_samplerate);
884 
885   sfz_synth_generator->loop_start = samplerate * (sfz_synth_generator->loop_start / old_samplerate);
886   sfz_synth_generator->loop_end = samplerate * (sfz_synth_generator->loop_end / old_samplerate);
887 
888   g_rec_mutex_unlock(sfz_synth_generator_mutex);
889 }
890 
891 /**
892  * ags_sfz_synth_generator_get_buffer_size:
893  * @sfz_synth_generator: the #AgsSFZSynthGenerator
894  *
895  * Gets buffer size.
896  *
897  * Returns: the buffer size
898  *
899  * Since: 3.4.0
900  */
901 guint
ags_sfz_synth_generator_get_buffer_size(AgsSFZSynthGenerator * sfz_synth_generator)902 ags_sfz_synth_generator_get_buffer_size(AgsSFZSynthGenerator *sfz_synth_generator)
903 {
904   guint buffer_size;
905 
906   if(!AGS_IS_SFZ_SYNTH_GENERATOR(sfz_synth_generator)){
907     return(0);
908   }
909 
910   g_object_get(sfz_synth_generator,
911 	       "buffer-size", &buffer_size,
912 	       NULL);
913 
914   return(buffer_size);
915 }
916 
917 /**
918  * ags_sfz_synth_generator_set_buffer_size:
919  * @sfz_synth_generator: the #AgsSFZSynthGenerator
920  * @buffer_size: the buffer size
921  *
922  * Set buffer size.
923  *
924  * Since: 3.4.0
925  */
926 void
ags_sfz_synth_generator_set_buffer_size(AgsSFZSynthGenerator * sfz_synth_generator,guint buffer_size)927 ags_sfz_synth_generator_set_buffer_size(AgsSFZSynthGenerator *sfz_synth_generator, guint buffer_size)
928 {
929   GRecMutex *sfz_synth_generator_mutex;
930 
931   if(!AGS_IS_SFZ_SYNTH_GENERATOR(sfz_synth_generator)){
932     return;
933   }
934 
935   /* get sfz synth generator mutex */
936   sfz_synth_generator_mutex = AGS_SFZ_SYNTH_GENERATOR_GET_OBJ_MUTEX(sfz_synth_generator);
937 
938   g_rec_mutex_lock(sfz_synth_generator_mutex);
939 
940   sfz_synth_generator->buffer_size = buffer_size;
941 
942   g_rec_mutex_unlock(sfz_synth_generator_mutex);
943 }
944 
945 /**
946  * ags_sfz_synth_generator_get_format:
947  * @sfz_synth_generator: the #AgsSFZSynthGenerator
948  *
949  * Gets format.
950  *
951  * Returns: the format
952  *
953  * Since: 3.4.0
954  */
955 guint
ags_sfz_synth_generator_get_format(AgsSFZSynthGenerator * sfz_synth_generator)956 ags_sfz_synth_generator_get_format(AgsSFZSynthGenerator *sfz_synth_generator)
957 {
958   guint format;
959 
960   if(!AGS_IS_SFZ_SYNTH_GENERATOR(sfz_synth_generator)){
961     return(0);
962   }
963 
964   g_object_get(sfz_synth_generator,
965 	       "format", &format,
966 	       NULL);
967 
968   return(format);
969 }
970 
971 /**
972  * ags_sfz_synth_generator_set_format:
973  * @sfz_synth_generator: the #AgsSFZSynthGenerator
974  * @format: the format
975  *
976  * Set format.
977  *
978  * Since: 3.4.0
979  */
980 void
ags_sfz_synth_generator_set_format(AgsSFZSynthGenerator * sfz_synth_generator,guint format)981 ags_sfz_synth_generator_set_format(AgsSFZSynthGenerator *sfz_synth_generator, guint format)
982 {
983   GRecMutex *sfz_synth_generator_mutex;
984 
985   if(!AGS_IS_SFZ_SYNTH_GENERATOR(sfz_synth_generator)){
986     return;
987   }
988 
989   /* get sfz synth generator mutex */
990   sfz_synth_generator_mutex = AGS_SFZ_SYNTH_GENERATOR_GET_OBJ_MUTEX(sfz_synth_generator);
991 
992   g_rec_mutex_lock(sfz_synth_generator_mutex);
993 
994   sfz_synth_generator->format = format;
995 
996   g_rec_mutex_unlock(sfz_synth_generator_mutex);
997 }
998 
999 /**
1000  * ags_sfz_synth_generator_get_pitch_type:
1001  * @sfz_synth_generator: the #AgsSFZSynthGenerator
1002  *
1003  * Gets pitch type.
1004  *
1005  * Returns: the pitch type
1006  *
1007  * Since: 3.9.0
1008  */
1009 guint
ags_sfz_synth_generator_get_pitch_type(AgsSFZSynthGenerator * sfz_synth_generator)1010 ags_sfz_synth_generator_get_pitch_type(AgsSFZSynthGenerator *sfz_synth_generator)
1011 {
1012   guint pitch_type;
1013 
1014   if(!AGS_IS_SFZ_SYNTH_GENERATOR(sfz_synth_generator)){
1015     return(0);
1016   }
1017 
1018   g_object_get(sfz_synth_generator,
1019 	       "pitch-type", &pitch_type,
1020 	       NULL);
1021 
1022   return(pitch_type);
1023 }
1024 
1025 /**
1026  * ags_sfz_synth_generator_set_pitch_type:
1027  * @sfz_synth_generator: the #AgsSFZSynthGenerator
1028  * @pitch_type: the pitch type
1029  *
1030  * Set pitch type.
1031  *
1032  * Since: 3.9.0
1033  */
1034 void
ags_sfz_synth_generator_set_pitch_type(AgsSFZSynthGenerator * sfz_synth_generator,guint pitch_type)1035 ags_sfz_synth_generator_set_pitch_type(AgsSFZSynthGenerator *sfz_synth_generator, guint pitch_type)
1036 {
1037   GRecMutex *sfz_synth_generator_mutex;
1038 
1039   if(!AGS_IS_SFZ_SYNTH_GENERATOR(sfz_synth_generator)){
1040     return;
1041   }
1042 
1043   /* get sfz synth generator mutex */
1044   sfz_synth_generator_mutex = AGS_SFZ_SYNTH_GENERATOR_GET_OBJ_MUTEX(sfz_synth_generator);
1045 
1046   g_rec_mutex_lock(sfz_synth_generator_mutex);
1047 
1048   sfz_synth_generator->pitch_type = pitch_type;
1049 
1050   g_rec_mutex_unlock(sfz_synth_generator_mutex);
1051 }
1052 
1053 /**
1054  * ags_sfz_synth_generator_get_delay:
1055  * @sfz_synth_generator: the #AgsSFZSynthGenerator
1056  *
1057  * Gets delay.
1058  *
1059  * Returns: the delay
1060  *
1061  * Since: 3.4.0
1062  */
1063 gdouble
ags_sfz_synth_generator_get_delay(AgsSFZSynthGenerator * sfz_synth_generator)1064 ags_sfz_synth_generator_get_delay(AgsSFZSynthGenerator *sfz_synth_generator)
1065 {
1066   gdouble delay;
1067 
1068   if(!AGS_IS_SFZ_SYNTH_GENERATOR(sfz_synth_generator)){
1069     return(0.0);
1070   }
1071 
1072   g_object_get(sfz_synth_generator,
1073 	       "delay", &delay,
1074 	       NULL);
1075 
1076   return(delay);
1077 }
1078 
1079 /**
1080  * ags_sfz_synth_generator_set_delay:
1081  * @sfz_synth_generator: the #AgsSFZSynthGenerator
1082  * @delay: the delay
1083  *
1084  * Sets delay.
1085  *
1086  * Since: 3.4.0
1087  */
1088 void
ags_sfz_synth_generator_set_delay(AgsSFZSynthGenerator * sfz_synth_generator,gdouble delay)1089 ags_sfz_synth_generator_set_delay(AgsSFZSynthGenerator *sfz_synth_generator, gdouble delay)
1090 {
1091   if(!AGS_IS_SFZ_SYNTH_GENERATOR(sfz_synth_generator)){
1092     return;
1093   }
1094 
1095   g_object_set(sfz_synth_generator,
1096 	       "delay", delay,
1097 	       NULL);
1098 }
1099 
1100 /**
1101  * ags_sfz_synth_generator_get_frame_count:
1102  * @sfz_synth_generator: the #AgsSFZSynthGenerator
1103  *
1104  * Gets frame count.
1105  *
1106  * Returns: the frame count
1107  *
1108  * Since: 3.4.0
1109  */
1110 guint
ags_sfz_synth_generator_get_frame_count(AgsSFZSynthGenerator * sfz_synth_generator)1111 ags_sfz_synth_generator_get_frame_count(AgsSFZSynthGenerator *sfz_synth_generator)
1112 {
1113   guint frame_count;
1114 
1115   if(!AGS_IS_SFZ_SYNTH_GENERATOR(sfz_synth_generator)){
1116     return(0);
1117   }
1118 
1119   g_object_get(sfz_synth_generator,
1120 	       "frame-count", &frame_count,
1121 	       NULL);
1122 
1123   return(frame_count);
1124 }
1125 
1126 /**
1127  * ags_sfz_synth_generator_set_frame_count:
1128  * @sfz_synth_generator: the #AgsSFZSynthGenerator
1129  * @frame_count: the frame count
1130  *
1131  * Sets frame count.
1132  *
1133  * Since: 3.4.0
1134  */
1135 void
ags_sfz_synth_generator_set_frame_count(AgsSFZSynthGenerator * sfz_synth_generator,guint frame_count)1136 ags_sfz_synth_generator_set_frame_count(AgsSFZSynthGenerator *sfz_synth_generator, guint frame_count)
1137 {
1138   if(!AGS_IS_SFZ_SYNTH_GENERATOR(sfz_synth_generator)){
1139     return;
1140   }
1141 
1142   g_object_set(sfz_synth_generator,
1143 	       "frame-count", frame_count,
1144 	       NULL);
1145 }
1146 
1147 /**
1148  * ags_sfz_synth_generator_get_loop_start:
1149  * @sfz_synth_generator: the #AgsSFZSynthGenerator
1150  *
1151  * Gets loop start.
1152  *
1153  * Returns: the loop start
1154  *
1155  * Since: 3.4.0
1156  */
1157 guint
ags_sfz_synth_generator_get_loop_start(AgsSFZSynthGenerator * sfz_synth_generator)1158 ags_sfz_synth_generator_get_loop_start(AgsSFZSynthGenerator *sfz_synth_generator)
1159 {
1160   guint loop_start;
1161 
1162   if(!AGS_IS_SFZ_SYNTH_GENERATOR(sfz_synth_generator)){
1163     return(0);
1164   }
1165 
1166   g_object_get(sfz_synth_generator,
1167 	       "loop-start", &loop_start,
1168 	       NULL);
1169 
1170   return(loop_start);
1171 }
1172 
1173 /**
1174  * ags_sfz_synth_generator_set_loop_start:
1175  * @sfz_synth_generator: the #AgsSFZSynthGenerator
1176  * @loop_start: the loop start
1177  *
1178  * Sets loop start.
1179  *
1180  * Since: 3.4.0
1181  */
1182 void
ags_sfz_synth_generator_set_loop_start(AgsSFZSynthGenerator * sfz_synth_generator,guint loop_start)1183 ags_sfz_synth_generator_set_loop_start(AgsSFZSynthGenerator *sfz_synth_generator, guint loop_start)
1184 {
1185   if(!AGS_IS_SFZ_SYNTH_GENERATOR(sfz_synth_generator)){
1186     return;
1187   }
1188 
1189   g_object_set(sfz_synth_generator,
1190 	       "loop-start", loop_start,
1191 	       NULL);
1192 }
1193 
1194 /**
1195  * ags_sfz_synth_generator_get_loop_end:
1196  * @sfz_synth_generator: the #AgsSFZSynthGenerator
1197  *
1198  * Gets loop end.
1199  *
1200  * Returns: the loop end
1201  *
1202  * Since: 3.4.0
1203  */
1204 guint
ags_sfz_synth_generator_get_loop_end(AgsSFZSynthGenerator * sfz_synth_generator)1205 ags_sfz_synth_generator_get_loop_end(AgsSFZSynthGenerator *sfz_synth_generator)
1206 {
1207   guint loop_end;
1208 
1209   if(!AGS_IS_SFZ_SYNTH_GENERATOR(sfz_synth_generator)){
1210     return(0);
1211   }
1212 
1213   g_object_get(sfz_synth_generator,
1214 	       "loop-end", &loop_end,
1215 	       NULL);
1216 
1217   return(loop_end);
1218 }
1219 
1220 /**
1221  * ags_sfz_synth_generator_set_loop_end:
1222  * @sfz_synth_generator: the #AgsSFZSynthGenerator
1223  * @loop_end: the loop end
1224  *
1225  * Sets loop end.
1226  *
1227  * Since: 3.4.0
1228  */
1229 void
ags_sfz_synth_generator_set_loop_end(AgsSFZSynthGenerator * sfz_synth_generator,guint loop_end)1230 ags_sfz_synth_generator_set_loop_end(AgsSFZSynthGenerator *sfz_synth_generator, guint loop_end)
1231 {
1232   if(!AGS_IS_SFZ_SYNTH_GENERATOR(sfz_synth_generator)){
1233     return;
1234   }
1235 
1236   g_object_set(sfz_synth_generator,
1237 	       "loop-end", loop_end,
1238 	       NULL);
1239 }
1240 
1241 /**
1242  * ags_sfz_synth_generator_get_base_key:
1243  * @sfz_synth_generator: the #AgsSFZSynthGenerator
1244  *
1245  * Gets base key.
1246  *
1247  * Returns: the base key
1248  *
1249  * Since: 3.4.0
1250  */
1251 gdouble
ags_sfz_synth_generator_get_base_key(AgsSFZSynthGenerator * sfz_synth_generator)1252 ags_sfz_synth_generator_get_base_key(AgsSFZSynthGenerator *sfz_synth_generator)
1253 {
1254   gdouble base_key;
1255 
1256   if(!AGS_IS_SFZ_SYNTH_GENERATOR(sfz_synth_generator)){
1257     return(0.0);
1258   }
1259 
1260   g_object_get(sfz_synth_generator,
1261 	       "base_key", &base_key,
1262 	       NULL);
1263 
1264   return(base_key);
1265 }
1266 
1267 /**
1268  * ags_sfz_synth_generator_set_base_key:
1269  * @sfz_synth_generator: the #AgsSFZSynthGenerator
1270  * @base_key: the base key
1271  *
1272  * Sets base key.
1273  *
1274  * Since: 3.4.0
1275  */
1276 void
ags_sfz_synth_generator_set_base_key(AgsSFZSynthGenerator * sfz_synth_generator,gdouble base_key)1277 ags_sfz_synth_generator_set_base_key(AgsSFZSynthGenerator *sfz_synth_generator, gdouble base_key)
1278 {
1279   if(!AGS_IS_SFZ_SYNTH_GENERATOR(sfz_synth_generator)){
1280     return;
1281   }
1282 
1283   g_object_set(sfz_synth_generator,
1284 	       "base-key", base_key,
1285 	       NULL);
1286 }
1287 
1288 /**
1289  * ags_sfz_synth_generator_get_tuning:
1290  * @sfz_synth_generator: the #AgsSFZSynthGenerator
1291  *
1292  * Gets tuning.
1293  *
1294  * Returns: the tuning
1295  *
1296  * Since: 3.4.0
1297  */
1298 gdouble
ags_sfz_synth_generator_get_tuning(AgsSFZSynthGenerator * sfz_synth_generator)1299 ags_sfz_synth_generator_get_tuning(AgsSFZSynthGenerator *sfz_synth_generator)
1300 {
1301   gdouble tuning;
1302 
1303   if(!AGS_IS_SFZ_SYNTH_GENERATOR(sfz_synth_generator)){
1304     return(0.0);
1305   }
1306 
1307   g_object_get(sfz_synth_generator,
1308 	       "tuning", &tuning,
1309 	       NULL);
1310 
1311   return(tuning);
1312 }
1313 
1314 /**
1315  * ags_sfz_synth_generator_set_tuning:
1316  * @sfz_synth_generator: the #AgsSFZSynthGenerator
1317  * @tuning: the tuning
1318  *
1319  * Sets tuning.
1320  *
1321  * Since: 3.4.0
1322  */
1323 void
ags_sfz_synth_generator_set_tuning(AgsSFZSynthGenerator * sfz_synth_generator,gdouble tuning)1324 ags_sfz_synth_generator_set_tuning(AgsSFZSynthGenerator *sfz_synth_generator, gdouble tuning)
1325 {
1326   if(!AGS_IS_SFZ_SYNTH_GENERATOR(sfz_synth_generator)){
1327     return;
1328   }
1329 
1330   g_object_set(sfz_synth_generator,
1331 	       "tuning", tuning,
1332 	       NULL);
1333 }
1334 
1335 /**
1336  * ags_sfz_synth_generator_get_timestamp:
1337  * @sfz_synth_generator: the #AgsSFZSynthGenerator
1338  *
1339  * Get timestamp.
1340  *
1341  * Returns: (transfer full): the #AgsTimestamp
1342  *
1343  * Since: 3.4.0
1344  */
1345 AgsTimestamp*
ags_sfz_synth_generator_get_timestamp(AgsSFZSynthGenerator * sfz_synth_generator)1346 ags_sfz_synth_generator_get_timestamp(AgsSFZSynthGenerator *sfz_synth_generator)
1347 {
1348   AgsTimestamp *timestamp;
1349 
1350   if(!AGS_IS_SFZ_SYNTH_GENERATOR(sfz_synth_generator)){
1351     return(NULL);
1352   }
1353 
1354   g_object_get(sfz_synth_generator,
1355 	       "timestamp", &timestamp,
1356 	       NULL);
1357 
1358   return(timestamp);
1359 }
1360 
1361 /**
1362  * ags_sfz_synth_generator_set_timestamp:
1363  * @sfz_synth_generator: the #AgsSFZSynthGenerator
1364  * @timestamp: the #AgsTimestamp
1365  *
1366  * Set timestamp.
1367  *
1368  * Since: 3.4.0
1369  */
1370 void
ags_sfz_synth_generator_set_timestamp(AgsSFZSynthGenerator * sfz_synth_generator,AgsTimestamp * timestamp)1371 ags_sfz_synth_generator_set_timestamp(AgsSFZSynthGenerator *sfz_synth_generator, AgsTimestamp *timestamp)
1372 {
1373   if(!AGS_IS_SFZ_SYNTH_GENERATOR(sfz_synth_generator)){
1374     return;
1375   }
1376 
1377   g_object_set(sfz_synth_generator,
1378 	       "timestamp", timestamp,
1379 	       NULL);
1380 }
1381 
1382 /**
1383  * ags_sfz_synth_generator_compute:
1384  * @sfz_synth_generator: the #AgsSFZSynthGenerator
1385  * @audio_signal: the #AgsAudioSignal
1386  * @note: the note to compute
1387  *
1388  * Compute instrument for @note.
1389  *
1390  * Since: 3.4.0
1391  */
1392 void
ags_sfz_synth_generator_compute(AgsSFZSynthGenerator * sfz_synth_generator,GObject * audio_signal,gdouble note)1393 ags_sfz_synth_generator_compute(AgsSFZSynthGenerator *sfz_synth_generator,
1394 				GObject *audio_signal,
1395 				gdouble note)
1396 {
1397   AgsAudioContainerManager *audio_container_manager;
1398   AgsAudioContainer *audio_container;
1399   AgsSFZSample *sfz_sample;
1400 
1401   GObject *output_soundcard;
1402 
1403   GList *start_list, *list;
1404   GList *stream_start, *stream;
1405 
1406   void *buffer;
1407 
1408   gchar *filename;
1409 
1410   gint midi_key;
1411   glong lower, upper;
1412   gdouble delay;
1413   guint attack;
1414   guint frame_count;
1415   guint length;
1416   guint buffer_size;
1417   guint current_frame_count, requested_frame_count;
1418   gdouble samplerate;
1419   guint format;
1420   gdouble volume;
1421   guint audio_buffer_util_format;
1422   guint loop_mode;
1423   gint loop_start, loop_end;
1424   guint copy_mode;
1425   guint i;
1426 
1427   GRecMutex *sfz_synth_generator_mutex;
1428   GRecMutex *stream_mutex;
1429   GRecMutex *audio_container_manager_mutex;
1430 
1431   if(!AGS_IS_SFZ_SYNTH_GENERATOR(sfz_synth_generator) ||
1432      !AGS_IS_AUDIO_SIGNAL(audio_signal)){
1433     return;
1434   }
1435 
1436   /* get sfz synth generator mutex */
1437   sfz_synth_generator_mutex = AGS_SFZ_SYNTH_GENERATOR_GET_OBJ_MUTEX(sfz_synth_generator);
1438 
1439   /* get stream mutex */
1440   stream_mutex = AGS_AUDIO_SIGNAL_GET_STREAM_MUTEX(audio_signal);
1441 
1442   sfz_sample = NULL;
1443 
1444   output_soundcard = NULL;
1445 
1446   g_object_get(audio_signal,
1447 	       "output-soundcard", &output_soundcard,
1448 	       NULL);
1449 
1450   filename = NULL;
1451 
1452   g_object_get(sfz_synth_generator,
1453 	       "filename", &filename,
1454 	       NULL);
1455 
1456   audio_container_manager = ags_audio_container_manager_get_instance();
1457 
1458   /* get audio container manager mutex */
1459   audio_container_manager_mutex = AGS_AUDIO_CONTAINER_MANAGER_GET_OBJ_MUTEX(audio_container_manager);
1460 
1461   g_rec_mutex_lock(audio_container_manager_mutex);
1462 
1463   audio_container = ags_audio_container_manager_find_audio_container(audio_container_manager,
1464 								     filename);
1465 
1466   if(audio_container == NULL){
1467     audio_container = ags_audio_container_new(filename,
1468 					      NULL,
1469 					      NULL,
1470 					      NULL,
1471 					      output_soundcard,
1472 					      -1);
1473     ags_audio_container_open(audio_container);
1474 
1475     ags_audio_container_manager_add_audio_container(audio_container_manager,
1476 						    audio_container);
1477   }
1478 
1479   g_rec_mutex_unlock(audio_container_manager_mutex);
1480 
1481   list =
1482     start_list = ags_audio_container_find_sound_resource(audio_container,
1483 							 NULL,
1484 							 NULL,
1485 							 NULL);
1486 
1487   sfz_sample = NULL;
1488 
1489   if(list != NULL){
1490     sfz_sample = list->data;
1491   }
1492 
1493   midi_key = (gint) floor(note) + 69;
1494 
1495 //  g_message("--> %d", midi_key);
1496 
1497   upper = -1;
1498   lower = -1;
1499 
1500   while(list != NULL){
1501     gchar *str;
1502 
1503     glong hikey, lokey;
1504     glong value;
1505     glong current_diff, diff;
1506     int retval;
1507 
1508     hikey = ags_sfz_sample_get_hikey(list->data);
1509     lokey = ags_sfz_sample_get_lokey(list->data);
1510 
1511     if(lokey <= midi_key &&
1512        hikey >= midi_key){
1513       sfz_sample = list->data;
1514 
1515       break;
1516     }
1517 
1518     diff = lower - midi_key;
1519     current_diff = lokey - midi_key;
1520 
1521     if(diff < 0){
1522       diff *= -1;
1523     }
1524 
1525     if(current_diff < 0){
1526       current_diff *= -1;
1527     }
1528 
1529     if(lower == -1 ||
1530        current_diff < diff){
1531       sfz_sample = list->data;
1532 
1533       lower = lokey;
1534       upper = hikey;
1535     }
1536 
1537     diff = upper - midi_key;
1538     current_diff = hikey - midi_key;
1539 
1540     if(diff < 0){
1541       diff *= -1;
1542     }
1543 
1544     if(current_diff < 0){
1545       current_diff *= -1;
1546     }
1547 
1548     if(upper == -1 ||
1549        current_diff < diff){
1550       sfz_sample = list->data;
1551 
1552       lower = lokey;
1553       upper = hikey;
1554     }
1555 
1556     list = list->next;
1557   }
1558 
1559   g_list_free_full(start_list,
1560 		   (GDestroyNotify) g_object_unref);
1561 
1562   delay = 0.0;
1563   attack = 0;
1564 
1565   frame_count = 0;
1566 
1567   volume = 1.0;
1568 
1569   g_object_get(sfz_synth_generator,
1570 	       "delay", &delay,
1571 	       "attack", &attack,
1572 	       "frame-count", &frame_count,
1573 	       "volume", &volume,
1574 	       NULL);
1575 
1576   if(sfz_sample != NULL){
1577     guint loop_start, loop_end;
1578 
1579     loop_start = 0;
1580     loop_end = 0;
1581 
1582     ags_sound_resource_info(AGS_SOUND_RESOURCE(sfz_sample),
1583 			    NULL,
1584 			    &loop_start, &loop_end);
1585 
1586     g_object_set(audio_signal,
1587 		 "loop-start", loop_start,
1588 		 "loop-end", loop_end,
1589 		 NULL);
1590   }
1591 
1592   buffer_size = AGS_SFZ_SYNTH_GENERATOR_DEFAULT_BUFFER_SIZE;
1593   samplerate = AGS_SFZ_SYNTH_GENERATOR_DEFAULT_SAMPLERATE;
1594   format = AGS_SFZ_SYNTH_GENERATOR_DEFAULT_FORMAT;
1595 
1596   length = 0;
1597 
1598   g_object_get(audio_signal,
1599 	       "buffer-size", &buffer_size,
1600 	       "format", &format,
1601 	       "samplerate", &samplerate,
1602 	       "length", &length,
1603 	       NULL);
1604 
1605   current_frame_count = length * buffer_size;
1606   requested_frame_count = (guint) ceil(((floor(delay) * buffer_size + attack) + frame_count) / buffer_size) * buffer_size;
1607 
1608   if(current_frame_count < requested_frame_count){
1609     ags_audio_signal_stream_resize((AgsAudioSignal *) audio_signal,
1610 				   ceil(requested_frame_count / buffer_size));
1611   }
1612 
1613   ags_audio_signal_clear(audio_signal);
1614 
1615   /*  */
1616   g_rec_mutex_lock(stream_mutex);
1617 
1618   stream =
1619     stream_start = g_list_nth(AGS_AUDIO_SIGNAL(audio_signal)->stream,
1620 			      (guint) floor(delay));
1621 
1622   g_rec_mutex_unlock(stream_mutex);
1623 
1624   loop_mode = AGS_SFZ_SYNTH_UTIL_LOOP_NONE;
1625 
1626   loop_start = 0;
1627   loop_end = 0;
1628 
1629   audio_buffer_util_format = ags_audio_buffer_util_format_from_soundcard(format);
1630 
1631   buffer = ags_stream_alloc(frame_count,
1632 			    format);
1633 
1634   if(sfz_sample != NULL){
1635     ags_sound_resource_seek(AGS_SOUND_RESOURCE(sfz_sample),
1636 			    0, G_SEEK_SET);
1637   }
1638 
1639 #if 0
1640   {
1641     gint current_midi_key;
1642 
1643     current_midi_key = ags_sfz_sample_get_pitch_keycenter(sfz_sample);
1644 
1645     g_message("SFZ, note %f, midi_key %d", note, current_midi_key);
1646   }
1647 #endif
1648 
1649 #if 0
1650   ags_sfz_synth_util_copy(buffer,
1651 			  frame_count,
1652 			  sfz_sample,
1653 			  (gdouble) note,
1654 			  volume,
1655 			  samplerate, audio_buffer_util_format,
1656 			  0, frame_count,
1657 			  AGS_SFZ_SYNTH_UTIL_LOOP_NONE,
1658 			  0, 0);
1659 #else
1660   g_rec_mutex_lock(sfz_synth_generator_mutex);
1661 
1662   sfz_synth_generator->sfz->note = note;
1663 
1664   sfz_synth_generator->sfz->volume = volume;
1665 
1666   sfz_synth_generator->sfz->samplerate = samplerate;
1667 
1668   sfz_synth_generator->sfz->offset = 0;
1669   sfz_synth_generator->sfz->n_frames = frame_count;
1670 
1671   sfz_synth_generator->sfz->loop_mode = AGS_SFZ_SYNTH_UTIL_LOOP_NONE;
1672 
1673   sfz_synth_generator->sfz->loop_start = 0;
1674   sfz_synth_generator->sfz->loop_end = 0;
1675 
1676   AGS_GENERIC_PITCH(sfz_synth_generator->sfz->generic_pitch)->pitch_type = sfz_synth_generator->pitch_type;
1677 
1678   ags_sfz_util_copy(sfz_synth_generator->sfz,
1679 		    buffer,
1680 		    frame_count,
1681 		    sfz_sample,
1682 		    audio_buffer_util_format);
1683 
1684   g_rec_mutex_unlock(sfz_synth_generator_mutex);
1685 #endif
1686 
1687   copy_mode = ags_audio_buffer_util_get_copy_mode(audio_buffer_util_format,
1688 						  audio_buffer_util_format);
1689 
1690 
1691   g_rec_mutex_lock(stream_mutex);
1692 
1693   for(i = 0; i < frame_count && stream != NULL;){
1694     guint copy_count;
1695 
1696     copy_count = buffer_size;
1697 
1698     if(i + copy_count > frame_count){
1699       copy_count = frame_count - i;
1700     }
1701 
1702     ags_audio_buffer_util_copy_buffer_to_buffer(stream->data, 1, 0,
1703 						buffer, 1, i,
1704 						copy_count, copy_mode);
1705     i += copy_count;
1706 
1707     stream = stream->next;
1708   }
1709 
1710   g_rec_mutex_unlock(stream_mutex);
1711 
1712   if(output_soundcard != NULL){
1713     g_object_unref(output_soundcard);
1714   }
1715 
1716   g_free(filename);
1717 
1718   ags_stream_free(buffer);
1719 }
1720 
1721 /**
1722  * ags_sfz_synth_generator_new:
1723  *
1724  * Creates an #AgsSFZSynthGenerator
1725  *
1726  * Returns: a new #AgsSFZSynthGenerator
1727  *
1728  * Since: 3.4.0
1729  */
1730 AgsSFZSynthGenerator*
ags_sfz_synth_generator_new()1731 ags_sfz_synth_generator_new()
1732 {
1733   AgsSFZSynthGenerator *sfz_synth_generator;
1734 
1735   sfz_synth_generator = (AgsSFZSynthGenerator *) g_object_new(AGS_TYPE_SFZ_SYNTH_GENERATOR,
1736 							      NULL);
1737 
1738   return(sfz_synth_generator);
1739 }
1740