1 /* GSequencer - Advanced GTK Sequencer
2 * Copyright (C) 2005-2020 Joël Krähemann
3 *
4 * This file is part of GSequencer.
5 *
6 * GSequencer is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * GSequencer is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GSequencer. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <ags/audio/ags_fifoout.h>
21
22 #include <ags/audio/ags_sound_provider.h>
23 #include <ags/audio/ags_audio_buffer_util.h>
24
25 #include <ags/audio/task/ags_tic_device.h>
26 #include <ags/audio/task/ags_clear_buffer.h>
27 #include <ags/audio/task/ags_switch_buffer_flag.h>
28
29 #include <sys/stat.h>
30 #include <sys/types.h>
31
32 #ifndef AGS_W32API
33 #include <fcntl.h>
34 #include <sys/ioctl.h>
35 #endif
36
37 #include <errno.h>
38
39 #include <string.h>
40 #include <math.h>
41
42 #include <time.h>
43 #include <signal.h>
44 #include <strings.h>
45 #include <unistd.h>
46
47 #include <ags/config.h>
48 #include <ags/i18n.h>
49
50 void ags_fifoout_class_init(AgsFifooutClass *fifoout);
51 void ags_fifoout_connectable_interface_init(AgsConnectableInterface *connectable);
52 void ags_fifoout_soundcard_interface_init(AgsSoundcardInterface *soundcard);
53 void ags_fifoout_init(AgsFifoout *fifoout);
54 void ags_fifoout_set_property(GObject *gobject,
55 guint prop_id,
56 const GValue *value,
57 GParamSpec *param_spec);
58 void ags_fifoout_get_property(GObject *gobject,
59 guint prop_id,
60 GValue *value,
61 GParamSpec *param_spec);
62 void ags_fifoout_dispose(GObject *gobject);
63 void ags_fifoout_finalize(GObject *gobject);
64
65 AgsUUID* ags_fifoout_get_uuid(AgsConnectable *connectable);
66 gboolean ags_fifoout_has_resource(AgsConnectable *connectable);
67 gboolean ags_fifoout_is_ready(AgsConnectable *connectable);
68 void ags_fifoout_add_to_registry(AgsConnectable *connectable);
69 void ags_fifoout_remove_from_registry(AgsConnectable *connectable);
70 xmlNode* ags_fifoout_list_resource(AgsConnectable *connectable);
71 xmlNode* ags_fifoout_xml_compose(AgsConnectable *connectable);
72 void ags_fifoout_xml_parse(AgsConnectable *connectable,
73 xmlNode *node);
74 gboolean ags_fifoout_is_connected(AgsConnectable *connectable);
75 void ags_fifoout_connect(AgsConnectable *connectable);
76 void ags_fifoout_disconnect(AgsConnectable *connectable);
77
78 void ags_fifoout_set_device(AgsSoundcard *soundcard,
79 gchar *device);
80 gchar* ags_fifoout_get_device(AgsSoundcard *soundcard);
81
82 void ags_fifoout_set_presets(AgsSoundcard *soundcard,
83 guint channels,
84 guint rate,
85 guint buffer_size,
86 guint format);
87 void ags_fifoout_get_presets(AgsSoundcard *soundcard,
88 guint *channels,
89 guint *rate,
90 guint *buffer_size,
91 guint *format);
92
93 void ags_fifoout_list_cards(AgsSoundcard *soundcard,
94 GList **card_id, GList **card_name);
95 void ags_fifoout_pcm_info(AgsSoundcard *soundcard, gchar *card_id,
96 guint *channels_min, guint *channels_max,
97 guint *rate_min, guint *rate_max,
98 guint *buffer_size_min, guint *buffer_size_max,
99 GError **error);
100
101 gboolean ags_fifoout_is_available(AgsSoundcard *soundcard);
102
103 gboolean ags_fifoout_is_starting(AgsSoundcard *soundcard);
104 gboolean ags_fifoout_is_playing(AgsSoundcard *soundcard);
105
106 gchar* ags_fifoout_get_uptime(AgsSoundcard *soundcard);
107
108 void ags_fifoout_fifo_init(AgsSoundcard *soundcard,
109 GError **error);
110 void ags_fifoout_fifo_play(AgsSoundcard *soundcard,
111 GError **error);
112 void ags_fifoout_fifo_free(AgsSoundcard *soundcard);
113
114 void ags_fifoout_tic(AgsSoundcard *soundcard);
115 void ags_fifoout_offset_changed(AgsSoundcard *soundcard,
116 guint note_offset);
117
118 void ags_fifoout_set_bpm(AgsSoundcard *soundcard,
119 gdouble bpm);
120 gdouble ags_fifoout_get_bpm(AgsSoundcard *soundcard);
121
122 void ags_fifoout_set_delay_factor(AgsSoundcard *soundcard,
123 gdouble delay_factor);
124 gdouble ags_fifoout_get_delay_factor(AgsSoundcard *soundcard);
125
126 gdouble ags_fifoout_get_absolute_delay(AgsSoundcard *soundcard);
127
128 gdouble ags_fifoout_get_delay(AgsSoundcard *soundcard);
129 guint ags_fifoout_get_attack(AgsSoundcard *soundcard);
130
131 void* ags_fifoout_get_buffer(AgsSoundcard *soundcard);
132 void* ags_fifoout_get_next_buffer(AgsSoundcard *soundcard);
133
134 guint ags_fifoout_get_delay_counter(AgsSoundcard *soundcard);
135
136 void ags_fifoout_set_note_offset(AgsSoundcard *soundcard,
137 guint note_offset);
138 guint ags_fifoout_get_note_offset(AgsSoundcard *soundcard);
139
140 void ags_fifoout_set_note_offset_absolute(AgsSoundcard *soundcard,
141 guint note_offset);
142 guint ags_fifoout_get_note_offset_absolute(AgsSoundcard *soundcard);
143
144 void ags_fifoout_set_loop(AgsSoundcard *soundcard,
145 guint loop_left, guint loop_right,
146 gboolean do_loop);
147 void ags_fifoout_get_loop(AgsSoundcard *soundcard,
148 guint *loop_left, guint *loop_right,
149 gboolean *do_loop);
150
151 guint ags_fifoout_get_loop_offset(AgsSoundcard *soundcard);
152
153 /**
154 * SECTION:ags_fifoout
155 * @short_description: Output to pipe
156 * @title: AgsFifoout
157 * @section_id:
158 * @include: ags/audio/ags_fifoout.h
159 *
160 * #AgsFifoout represents a pipe and supports output.
161 */
162
163 enum{
164 PROP_0,
165 PROP_DEVICE,
166 PROP_DSP_CHANNELS,
167 PROP_PCM_CHANNELS,
168 PROP_FORMAT,
169 PROP_BUFFER_SIZE,
170 PROP_SAMPLERATE,
171 PROP_BUFFER,
172 PROP_BPM,
173 PROP_DELAY_FACTOR,
174 PROP_ATTACK,
175 };
176
177 static gpointer ags_fifoout_parent_class = NULL;
178
179 GType
ags_fifoout_get_type(void)180 ags_fifoout_get_type (void)
181 {
182 static volatile gsize g_define_type_id__volatile = 0;
183
184 if(g_once_init_enter (&g_define_type_id__volatile)){
185 GType ags_type_fifoout = 0;
186
187 static const GTypeInfo ags_fifoout_info = {
188 sizeof(AgsFifooutClass),
189 NULL, /* base_init */
190 NULL, /* base_finalize */
191 (GClassInitFunc) ags_fifoout_class_init,
192 NULL, /* class_finalize */
193 NULL, /* class_data */
194 sizeof(AgsFifoout),
195 0, /* n_preallocs */
196 (GInstanceInitFunc) ags_fifoout_init,
197 };
198
199 static const GInterfaceInfo ags_connectable_interface_info = {
200 (GInterfaceInitFunc) ags_fifoout_connectable_interface_init,
201 NULL, /* interface_finalize */
202 NULL, /* interface_data */
203 };
204
205 static const GInterfaceInfo ags_soundcard_interface_info = {
206 (GInterfaceInitFunc) ags_fifoout_soundcard_interface_init,
207 NULL, /* interface_finalize */
208 NULL, /* interface_data */
209 };
210
211 ags_type_fifoout = g_type_register_static(G_TYPE_OBJECT,
212 "AgsFifoout",
213 &ags_fifoout_info,
214 0);
215
216 g_type_add_interface_static(ags_type_fifoout,
217 AGS_TYPE_CONNECTABLE,
218 &ags_connectable_interface_info);
219
220 g_type_add_interface_static(ags_type_fifoout,
221 AGS_TYPE_SOUNDCARD,
222 &ags_soundcard_interface_info);
223
224 g_once_init_leave(&g_define_type_id__volatile, ags_type_fifoout);
225 }
226
227 return g_define_type_id__volatile;
228 }
229
230 GType
ags_fifoout_flags_get_type()231 ags_fifoout_flags_get_type()
232 {
233 static volatile gsize g_flags_type_id__volatile;
234
235 if(g_once_init_enter (&g_flags_type_id__volatile)){
236 static const GFlagsValue values[] = {
237 { AGS_FIFOOUT_ADDED_TO_REGISTRY, "AGS_FIFOOUT_ADDED_TO_REGISTRY", "fifoout-added-to-registry" },
238 { AGS_FIFOOUT_CONNECTED, "AGS_FIFOOUT_CONNECTED", "fifoout-connected" },
239 { AGS_FIFOOUT_BUFFER0, "AGS_FIFOOUT_BUFFER0", "fifoout-buffer0" },
240 { AGS_FIFOOUT_BUFFER1, "AGS_FIFOOUT_BUFFER1", "fifoout-buffer1" },
241 { AGS_FIFOOUT_BUFFER2, "AGS_FIFOOUT_BUFFER2", "fifoout-buffer2" },
242 { AGS_FIFOOUT_BUFFER3, "AGS_FIFOOUT_BUFFER3", "fifoout-buffer3" },
243 { AGS_FIFOOUT_ATTACK_FIRST, "AGS_FIFOOUT_ATTACK_FIRST", "fifoout-attack-first" },
244 { AGS_FIFOOUT_PLAY, "AGS_FIFOOUT_PLAY", "fifoout-play" },
245 { AGS_FIFOOUT_SHUTDOWN, "AGS_FIFOOUT_SHUTDOWN", "fifoout-shutdown" },
246 { AGS_FIFOOUT_START_PLAY, "AGS_FIFOOUT_START_PLAY", "fifoout-start-play" },
247 { AGS_FIFOOUT_NONBLOCKING, "AGS_FIFOOUT_NONBLOCKING", "fifoout-nonblocking" },
248 { AGS_FIFOOUT_INITIALIZED, "AGS_FIFOOUT_INITIALIZED", "fifoout-initialized" },
249 { 0, NULL, NULL }
250 };
251
252 GType g_flags_type_id = g_flags_register_static(g_intern_static_string("AgsFifooutFlags"), values);
253
254 g_once_init_leave (&g_flags_type_id__volatile, g_flags_type_id);
255 }
256
257 return g_flags_type_id__volatile;
258 }
259
260 void
ags_fifoout_class_init(AgsFifooutClass * fifoout)261 ags_fifoout_class_init(AgsFifooutClass *fifoout)
262 {
263 GObjectClass *gobject;
264
265 GParamSpec *param_spec;
266
267 ags_fifoout_parent_class = g_type_class_peek_parent(fifoout);
268
269 /* GObjectClass */
270 gobject = (GObjectClass *) fifoout;
271
272 gobject->set_property = ags_fifoout_set_property;
273 gobject->get_property = ags_fifoout_get_property;
274
275 gobject->dispose = ags_fifoout_dispose;
276 gobject->finalize = ags_fifoout_finalize;
277
278 /* properties */
279 /**
280 * AgsFifoout:device:
281 *
282 * The fifo soundcard indentifier
283 *
284 * Since: 3.0.0
285 */
286 param_spec = g_param_spec_string("device",
287 i18n_pspec("the device identifier"),
288 i18n_pspec("The device to perform output to"),
289 AGS_FIFOOUT_DEFAULT_DEVICE,
290 G_PARAM_READABLE | G_PARAM_WRITABLE);
291 g_object_class_install_property(gobject,
292 PROP_DEVICE,
293 param_spec);
294
295 /**
296 * AgsFifoout:dsp-channels:
297 *
298 * The dsp channel count
299 *
300 * Since: 3.0.0
301 */
302 param_spec = g_param_spec_uint("dsp-channels",
303 i18n_pspec("count of DSP channels"),
304 i18n_pspec("The count of DSP channels to use"),
305 AGS_SOUNDCARD_MIN_DSP_CHANNELS,
306 AGS_SOUNDCARD_MAX_DSP_CHANNELS,
307 AGS_SOUNDCARD_DEFAULT_DSP_CHANNELS,
308 G_PARAM_READABLE | G_PARAM_WRITABLE);
309 g_object_class_install_property(gobject,
310 PROP_DSP_CHANNELS,
311 param_spec);
312
313 /**
314 * AgsFifoout:pcm-channels:
315 *
316 * The pcm channel count
317 *
318 * Since: 3.0.0
319 */
320 param_spec = g_param_spec_uint("pcm-channels",
321 i18n_pspec("count of PCM channels"),
322 i18n_pspec("The count of PCM channels to use"),
323 AGS_SOUNDCARD_MIN_PCM_CHANNELS,
324 AGS_SOUNDCARD_MAX_PCM_CHANNELS,
325 AGS_SOUNDCARD_DEFAULT_PCM_CHANNELS,
326 G_PARAM_READABLE | G_PARAM_WRITABLE);
327 g_object_class_install_property(gobject,
328 PROP_PCM_CHANNELS,
329 param_spec);
330
331 /**
332 * AgsFifoout:format:
333 *
334 * The precision of the buffer
335 *
336 * Since: 3.0.0
337 */
338 param_spec = g_param_spec_uint("format",
339 i18n_pspec("precision of buffer"),
340 i18n_pspec("The precision to use for a frame"),
341 0,
342 G_MAXUINT32,
343 AGS_SOUNDCARD_DEFAULT_FORMAT,
344 G_PARAM_READABLE | G_PARAM_WRITABLE);
345 g_object_class_install_property(gobject,
346 PROP_FORMAT,
347 param_spec);
348
349 /**
350 * AgsFifoout:buffer-size:
351 *
352 * The buffer size
353 *
354 * Since: 3.0.0
355 */
356 param_spec = g_param_spec_uint("buffer-size",
357 i18n_pspec("frame count of a buffer"),
358 i18n_pspec("The count of frames a buffer contains"),
359 AGS_SOUNDCARD_MIN_BUFFER_SIZE,
360 AGS_SOUNDCARD_MAX_BUFFER_SIZE,
361 AGS_SOUNDCARD_DEFAULT_BUFFER_SIZE,
362 G_PARAM_READABLE | G_PARAM_WRITABLE);
363 g_object_class_install_property(gobject,
364 PROP_BUFFER_SIZE,
365 param_spec);
366
367 /**
368 * AgsFifoout:samplerate:
369 *
370 * The samplerate
371 *
372 * Since: 3.0.0
373 */
374 param_spec = g_param_spec_uint("samplerate",
375 i18n_pspec("frames per second"),
376 i18n_pspec("The frames count played during a second"),
377 AGS_SOUNDCARD_MIN_SAMPLERATE,
378 AGS_SOUNDCARD_MAX_SAMPLERATE,
379 AGS_SOUNDCARD_DEFAULT_SAMPLERATE,
380 G_PARAM_READABLE | G_PARAM_WRITABLE);
381 g_object_class_install_property(gobject,
382 PROP_SAMPLERATE,
383 param_spec);
384
385 /**
386 * AgsFifoout:buffer:
387 *
388 * The buffer
389 *
390 * Since: 3.0.0
391 */
392 param_spec = g_param_spec_pointer("buffer",
393 i18n_pspec("the buffer"),
394 i18n_pspec("The buffer to play"),
395 G_PARAM_READABLE);
396 g_object_class_install_property(gobject,
397 PROP_BUFFER,
398 param_spec);
399
400 /**
401 * AgsFifoout:bpm:
402 *
403 * Beats per minute
404 *
405 * Since: 3.0.0
406 */
407 param_spec = g_param_spec_double("bpm",
408 i18n_pspec("beats per minute"),
409 i18n_pspec("Beats per minute to use"),
410 1.0,
411 240.0,
412 AGS_SOUNDCARD_DEFAULT_BPM,
413 G_PARAM_READABLE | G_PARAM_WRITABLE);
414 g_object_class_install_property(gobject,
415 PROP_BPM,
416 param_spec);
417
418 /**
419 * AgsFifoout:delay-factor:
420 *
421 * tact
422 *
423 * Since: 3.0.0
424 */
425 param_spec = g_param_spec_double("delay-factor",
426 i18n_pspec("delay factor"),
427 i18n_pspec("The delay factor"),
428 0.0,
429 16.0,
430 1.0,
431 G_PARAM_READABLE | G_PARAM_WRITABLE);
432 g_object_class_install_property(gobject,
433 PROP_DELAY_FACTOR,
434 param_spec);
435
436 /**
437 * AgsFifoout:attack:
438 *
439 * Attack of the buffer
440 *
441 * Since: 3.0.0
442 */
443 param_spec = g_param_spec_pointer("attack",
444 i18n_pspec("attack of buffer"),
445 i18n_pspec("The attack to use for the buffer"),
446 G_PARAM_READABLE);
447 g_object_class_install_property(gobject,
448 PROP_ATTACK,
449 param_spec);
450
451 /* AgsFifooutClass */
452 }
453
454 GQuark
ags_fifoout_error_quark()455 ags_fifoout_error_quark()
456 {
457 return(g_quark_from_static_string("ags-fifoout-error-quark"));
458 }
459
460 void
ags_fifoout_connectable_interface_init(AgsConnectableInterface * connectable)461 ags_fifoout_connectable_interface_init(AgsConnectableInterface *connectable)
462 {
463 connectable->get_uuid = ags_fifoout_get_uuid;
464 connectable->has_resource = ags_fifoout_has_resource;
465
466 connectable->is_ready = ags_fifoout_is_ready;
467 connectable->add_to_registry = ags_fifoout_add_to_registry;
468 connectable->remove_from_registry = ags_fifoout_remove_from_registry;
469
470 connectable->list_resource = ags_fifoout_list_resource;
471 connectable->xml_compose = ags_fifoout_xml_compose;
472 connectable->xml_parse = ags_fifoout_xml_parse;
473
474 connectable->is_connected = ags_fifoout_is_connected;
475 connectable->connect = ags_fifoout_connect;
476 connectable->disconnect = ags_fifoout_disconnect;
477
478 connectable->connect_connection = NULL;
479 connectable->disconnect_connection = NULL;
480 }
481
482 void
ags_fifoout_soundcard_interface_init(AgsSoundcardInterface * soundcard)483 ags_fifoout_soundcard_interface_init(AgsSoundcardInterface *soundcard)
484 {
485 soundcard->set_device = ags_fifoout_set_device;
486 soundcard->get_device = ags_fifoout_get_device;
487
488 soundcard->set_presets = ags_fifoout_set_presets;
489 soundcard->get_presets = ags_fifoout_get_presets;
490
491 soundcard->list_cards = ags_fifoout_list_cards;
492 soundcard->pcm_info = ags_fifoout_pcm_info;
493 soundcard->get_capability = NULL;
494
495 soundcard->is_available = ags_fifoout_is_available;
496
497 soundcard->is_starting = ags_fifoout_is_starting;
498 soundcard->is_playing = ags_fifoout_is_playing;
499 soundcard->is_recording = NULL;
500
501 soundcard->get_uptime = ags_fifoout_get_uptime;
502
503 soundcard->play_init = ags_fifoout_fifo_init;
504 soundcard->play = ags_fifoout_fifo_play;
505
506 soundcard->record_init = NULL;
507 soundcard->record = NULL;
508
509 soundcard->stop = ags_fifoout_fifo_free;
510
511 soundcard->tic = ags_fifoout_tic;
512 soundcard->offset_changed = ags_fifoout_offset_changed;
513
514 soundcard->set_bpm = ags_fifoout_set_bpm;
515 soundcard->get_bpm = ags_fifoout_get_bpm;
516
517 soundcard->set_delay_factor = ags_fifoout_set_delay_factor;
518 soundcard->get_delay_factor = ags_fifoout_get_delay_factor;
519
520 soundcard->get_absolute_delay = ags_fifoout_get_absolute_delay;
521
522 soundcard->get_delay = ags_fifoout_get_delay;
523 soundcard->get_attack = ags_fifoout_get_attack;
524
525 soundcard->get_buffer = ags_fifoout_get_buffer;
526 soundcard->get_next_buffer = ags_fifoout_get_next_buffer;
527
528 soundcard->get_delay_counter = ags_fifoout_get_delay_counter;
529
530 soundcard->set_note_offset = ags_fifoout_set_note_offset;
531 soundcard->get_note_offset = ags_fifoout_get_note_offset;
532
533 soundcard->set_note_offset_absolute = ags_fifoout_set_note_offset_absolute;
534 soundcard->get_note_offset_absolute = ags_fifoout_get_note_offset_absolute;
535
536 soundcard->set_loop = ags_fifoout_set_loop;
537 soundcard->get_loop = ags_fifoout_get_loop;
538
539 soundcard->get_loop_offset = ags_fifoout_get_loop_offset;
540 }
541
542 void
ags_fifoout_init(AgsFifoout * fifoout)543 ags_fifoout_init(AgsFifoout *fifoout)
544 {
545 AgsConfig *config;
546
547 gchar *str;
548 gchar *segmentation;
549
550 guint denumerator, numerator;
551
552 fifoout->flags = 0;
553
554 /* insert fifoout mutex */
555 g_rec_mutex_init(&(fifoout->obj_mutex));
556
557 /* uuid */
558 fifoout->uuid = ags_uuid_alloc();
559 ags_uuid_generate(fifoout->uuid);
560
561 /* flags */
562 config = ags_config_get_instance();
563
564 /* presets */
565 fifoout->dsp_channels = ags_soundcard_helper_config_get_dsp_channels(config);
566 fifoout->pcm_channels = ags_soundcard_helper_config_get_pcm_channels(config);
567
568 fifoout->samplerate = ags_soundcard_helper_config_get_samplerate(config);
569 fifoout->buffer_size = ags_soundcard_helper_config_get_buffer_size(config);
570 fifoout->format = ags_soundcard_helper_config_get_format(config);
571
572 /* */
573 fifoout->device = AGS_FIFOOUT_DEFAULT_DEVICE;
574 fifoout->fifo_fd = -1;
575
576 /* buffer */
577 fifoout->buffer = (void **) malloc(4 * sizeof(void*));
578
579 fifoout->buffer[0] = NULL;
580 fifoout->buffer[1] = NULL;
581 fifoout->buffer[2] = NULL;
582 fifoout->buffer[3] = NULL;
583
584 g_atomic_int_set(&(fifoout->available),
585 FALSE);
586
587 fifoout->ring_buffer_size = AGS_FIFOOUT_DEFAULT_RING_BUFFER_SIZE;
588 fifoout->nth_ring_buffer = 0;
589
590 fifoout->ring_buffer = NULL;
591
592 ags_fifoout_realloc_buffer(fifoout);
593
594 /* bpm */
595 fifoout->bpm = AGS_SOUNDCARD_DEFAULT_BPM;
596
597 /* delay factor */
598 fifoout->delay_factor = AGS_SOUNDCARD_DEFAULT_DELAY_FACTOR;
599
600 /* segmentation */
601 segmentation = ags_config_get_value(config,
602 AGS_CONFIG_GENERIC,
603 "segmentation");
604
605 if(segmentation != NULL){
606 sscanf(segmentation, "%d/%d",
607 &denumerator,
608 &numerator);
609
610 fifoout->delay_factor = 1.0 / numerator * (numerator / denumerator);
611
612 g_free(segmentation);
613 }
614
615 /* delay and attack */
616 fifoout->delay = (gdouble *) malloc((int) 2 * AGS_SOUNDCARD_DEFAULT_PERIOD *
617 sizeof(gdouble));
618
619 fifoout->attack = (guint *) malloc((int) 2 * AGS_SOUNDCARD_DEFAULT_PERIOD *
620 sizeof(guint));
621
622 ags_fifoout_adjust_delay_and_attack(fifoout);
623
624 /* counters */
625 fifoout->tact_counter = 0.0;
626 fifoout->delay_counter = 0;
627 fifoout->tic_counter = 0;
628
629 fifoout->note_offset = 0;
630 fifoout->note_offset_absolute = 0;
631
632 fifoout->loop_left = AGS_SOUNDCARD_DEFAULT_LOOP_LEFT;
633 fifoout->loop_right = AGS_SOUNDCARD_DEFAULT_LOOP_RIGHT;
634
635 fifoout->do_loop = FALSE;
636
637 fifoout->loop_offset = 0;
638 }
639
640 void
ags_fifoout_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)641 ags_fifoout_set_property(GObject *gobject,
642 guint prop_id,
643 const GValue *value,
644 GParamSpec *param_spec)
645 {
646 AgsFifoout *fifoout;
647
648 GRecMutex *fifoout_mutex;
649
650 fifoout = AGS_FIFOOUT(gobject);
651
652 /* get fifoout mutex */
653 fifoout_mutex = AGS_FIFOOUT_GET_OBJ_MUTEX(fifoout);
654
655 switch(prop_id){
656 case PROP_DEVICE:
657 {
658 char *device;
659
660 device = (char *) g_value_get_string(value);
661
662 g_rec_mutex_lock(fifoout_mutex);
663
664 fifoout->device = g_strdup(device);
665
666 g_rec_mutex_unlock(fifoout_mutex);
667 }
668 break;
669 case PROP_DSP_CHANNELS:
670 {
671 guint dsp_channels;
672
673 dsp_channels = g_value_get_uint(value);
674
675 g_rec_mutex_lock(fifoout_mutex);
676
677 if(dsp_channels == fifoout->dsp_channels){
678 g_rec_mutex_unlock(fifoout_mutex);
679
680 return;
681 }
682
683 fifoout->dsp_channels = dsp_channels;
684
685 g_rec_mutex_unlock(fifoout_mutex);
686 }
687 break;
688 case PROP_PCM_CHANNELS:
689 {
690 guint pcm_channels;
691
692 pcm_channels = g_value_get_uint(value);
693
694 g_rec_mutex_lock(fifoout_mutex);
695
696 if(pcm_channels == fifoout->pcm_channels){
697 g_rec_mutex_unlock(fifoout_mutex);
698
699 return;
700 }
701
702 fifoout->pcm_channels = pcm_channels;
703
704 g_rec_mutex_unlock(fifoout_mutex);
705
706 ags_fifoout_realloc_buffer(fifoout);
707 }
708 break;
709 case PROP_FORMAT:
710 {
711 guint format;
712
713 format = g_value_get_uint(value);
714
715 g_rec_mutex_lock(fifoout_mutex);
716
717 if(format == fifoout->format){
718 g_rec_mutex_unlock(fifoout_mutex);
719
720 return;
721 }
722
723 fifoout->format = format;
724
725 g_rec_mutex_unlock(fifoout_mutex);
726
727 ags_fifoout_realloc_buffer(fifoout);
728 }
729 break;
730 case PROP_BUFFER_SIZE:
731 {
732 guint buffer_size;
733
734 buffer_size = g_value_get_uint(value);
735
736 g_rec_mutex_lock(fifoout_mutex);
737
738 if(buffer_size == fifoout->buffer_size){
739 g_rec_mutex_unlock(fifoout_mutex);
740
741 return;
742 }
743
744 fifoout->buffer_size = buffer_size;
745
746 g_rec_mutex_unlock(fifoout_mutex);
747
748 ags_fifoout_realloc_buffer(fifoout);
749 ags_fifoout_adjust_delay_and_attack(fifoout);
750 }
751 break;
752 case PROP_SAMPLERATE:
753 {
754 guint samplerate;
755
756 samplerate = g_value_get_uint(value);
757
758 g_rec_mutex_lock(fifoout_mutex);
759
760 if(samplerate == fifoout->samplerate){
761 g_rec_mutex_unlock(fifoout_mutex);
762
763 return;
764 }
765
766 fifoout->samplerate = samplerate;
767
768 g_rec_mutex_unlock(fifoout_mutex);
769
770 ags_fifoout_adjust_delay_and_attack(fifoout);
771 }
772 break;
773 case PROP_BUFFER:
774 {
775 //TODO:JK: implement me
776 }
777 break;
778 case PROP_BPM:
779 {
780 gdouble bpm;
781
782 bpm = g_value_get_double(value);
783
784 g_rec_mutex_lock(fifoout_mutex);
785
786 if(bpm == fifoout->bpm){
787 g_rec_mutex_unlock(fifoout_mutex);
788
789 return;
790 }
791
792 fifoout->bpm = bpm;
793
794 g_rec_mutex_unlock(fifoout_mutex);
795
796 ags_fifoout_adjust_delay_and_attack(fifoout);
797 }
798 break;
799 case PROP_DELAY_FACTOR:
800 {
801 gdouble delay_factor;
802
803 delay_factor = g_value_get_double(value);
804
805 g_rec_mutex_lock(fifoout_mutex);
806
807 if(delay_factor == fifoout->delay_factor){
808 g_rec_mutex_unlock(fifoout_mutex);
809
810 return;
811 }
812
813 fifoout->delay_factor = delay_factor;
814
815 g_rec_mutex_unlock(fifoout_mutex);
816
817 ags_fifoout_adjust_delay_and_attack(fifoout);
818 }
819 break;
820 default:
821 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
822 break;
823 }
824 }
825
826 void
ags_fifoout_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)827 ags_fifoout_get_property(GObject *gobject,
828 guint prop_id,
829 GValue *value,
830 GParamSpec *param_spec)
831 {
832 AgsFifoout *fifoout;
833
834 GRecMutex *fifoout_mutex;
835
836 fifoout = AGS_FIFOOUT(gobject);
837
838 /* get fifoout mutex */
839 fifoout_mutex = AGS_FIFOOUT_GET_OBJ_MUTEX(fifoout);
840
841 switch(prop_id){
842 case PROP_DEVICE:
843 {
844 g_rec_mutex_lock(fifoout_mutex);
845
846 g_value_set_string(value, fifoout->device);
847
848 g_rec_mutex_unlock(fifoout_mutex);
849 }
850 break;
851 case PROP_DSP_CHANNELS:
852 {
853 g_rec_mutex_lock(fifoout_mutex);
854
855 g_value_set_uint(value, fifoout->dsp_channels);
856
857 g_rec_mutex_unlock(fifoout_mutex);
858 }
859 break;
860 case PROP_PCM_CHANNELS:
861 {
862 g_rec_mutex_lock(fifoout_mutex);
863
864 g_value_set_uint(value, fifoout->pcm_channels);
865
866 g_rec_mutex_unlock(fifoout_mutex);
867 }
868 break;
869 case PROP_FORMAT:
870 {
871 g_rec_mutex_lock(fifoout_mutex);
872
873 g_value_set_uint(value, fifoout->format);
874
875 g_rec_mutex_unlock(fifoout_mutex);
876 }
877 break;
878 case PROP_BUFFER_SIZE:
879 {
880 g_rec_mutex_lock(fifoout_mutex);
881
882 g_value_set_uint(value, fifoout->buffer_size);
883
884 g_rec_mutex_unlock(fifoout_mutex);
885 }
886 break;
887 case PROP_SAMPLERATE:
888 {
889 g_rec_mutex_lock(fifoout_mutex);
890
891 g_value_set_uint(value, fifoout->samplerate);
892
893 g_rec_mutex_unlock(fifoout_mutex);
894 }
895 break;
896 case PROP_BUFFER:
897 {
898 g_rec_mutex_lock(fifoout_mutex);
899
900 g_value_set_pointer(value, fifoout->buffer);
901
902 g_rec_mutex_unlock(fifoout_mutex);
903 }
904 break;
905 case PROP_BPM:
906 {
907 g_rec_mutex_lock(fifoout_mutex);
908
909 g_value_set_double(value, fifoout->bpm);
910
911 g_rec_mutex_unlock(fifoout_mutex);
912 }
913 break;
914 case PROP_DELAY_FACTOR:
915 {
916 g_rec_mutex_lock(fifoout_mutex);
917
918 g_value_set_double(value, fifoout->delay_factor);
919
920 g_rec_mutex_unlock(fifoout_mutex);
921 }
922 break;
923 case PROP_ATTACK:
924 {
925 g_rec_mutex_lock(fifoout_mutex);
926
927 g_value_set_pointer(value, fifoout->attack);
928
929 g_rec_mutex_unlock(fifoout_mutex);
930 }
931 break;
932 default:
933 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
934 break;
935 }
936 }
937
938 void
ags_fifoout_dispose(GObject * gobject)939 ags_fifoout_dispose(GObject *gobject)
940 {
941 AgsFifoout *fifoout;
942
943 fifoout = AGS_FIFOOUT(gobject);
944
945 /* call parent */
946 G_OBJECT_CLASS(ags_fifoout_parent_class)->dispose(gobject);
947 }
948
949 void
ags_fifoout_finalize(GObject * gobject)950 ags_fifoout_finalize(GObject *gobject)
951 {
952 AgsFifoout *fifoout;
953
954 fifoout = AGS_FIFOOUT(gobject);
955
956 /* free output buffer */
957 free(fifoout->buffer[0]);
958 free(fifoout->buffer[1]);
959 free(fifoout->buffer[2]);
960 free(fifoout->buffer[3]);
961
962 /* free buffer array */
963 free(fifoout->buffer);
964
965 /* free AgsAttack */
966 free(fifoout->attack);
967
968 /* call parent */
969 G_OBJECT_CLASS(ags_fifoout_parent_class)->finalize(gobject);
970 }
971
972 AgsUUID*
ags_fifoout_get_uuid(AgsConnectable * connectable)973 ags_fifoout_get_uuid(AgsConnectable *connectable)
974 {
975 AgsFifoout *fifoout;
976
977 AgsUUID *ptr;
978
979 GRecMutex *fifoout_mutex;
980
981 fifoout = AGS_FIFOOUT(connectable);
982
983 /* get fifoout signal mutex */
984 fifoout_mutex = AGS_FIFOOUT_GET_OBJ_MUTEX(fifoout);
985
986 /* get UUID */
987 g_rec_mutex_lock(fifoout_mutex);
988
989 ptr = fifoout->uuid;
990
991 g_rec_mutex_unlock(fifoout_mutex);
992
993 return(ptr);
994 }
995
996 gboolean
ags_fifoout_has_resource(AgsConnectable * connectable)997 ags_fifoout_has_resource(AgsConnectable *connectable)
998 {
999 return(FALSE);
1000 }
1001
1002 gboolean
ags_fifoout_is_ready(AgsConnectable * connectable)1003 ags_fifoout_is_ready(AgsConnectable *connectable)
1004 {
1005 AgsFifoout *fifoout;
1006
1007 gboolean is_ready;
1008
1009 fifoout = AGS_FIFOOUT(connectable);
1010
1011 /* check is added */
1012 is_ready = ags_fifoout_test_flags(fifoout, AGS_FIFOOUT_ADDED_TO_REGISTRY);
1013
1014 return(is_ready);
1015 }
1016
1017 void
ags_fifoout_add_to_registry(AgsConnectable * connectable)1018 ags_fifoout_add_to_registry(AgsConnectable *connectable)
1019 {
1020 AgsFifoout *fifoout;
1021
1022 if(ags_connectable_is_ready(connectable)){
1023 return;
1024 }
1025
1026 fifoout = AGS_FIFOOUT(connectable);
1027
1028 ags_fifoout_set_flags(fifoout, AGS_FIFOOUT_ADDED_TO_REGISTRY);
1029 }
1030
1031 void
ags_fifoout_remove_from_registry(AgsConnectable * connectable)1032 ags_fifoout_remove_from_registry(AgsConnectable *connectable)
1033 {
1034 AgsFifoout *fifoout;
1035
1036 if(!ags_connectable_is_ready(connectable)){
1037 return;
1038 }
1039
1040 fifoout = AGS_FIFOOUT(connectable);
1041
1042 ags_fifoout_unset_flags(fifoout, AGS_FIFOOUT_ADDED_TO_REGISTRY);
1043 }
1044
1045 xmlNode*
ags_fifoout_list_resource(AgsConnectable * connectable)1046 ags_fifoout_list_resource(AgsConnectable *connectable)
1047 {
1048 xmlNode *node;
1049
1050 node = NULL;
1051
1052 //TODO:JK: implement me
1053
1054 return(node);
1055 }
1056
1057 xmlNode*
ags_fifoout_xml_compose(AgsConnectable * connectable)1058 ags_fifoout_xml_compose(AgsConnectable *connectable)
1059 {
1060 xmlNode *node;
1061
1062 node = NULL;
1063
1064 //TODO:JK: implement me
1065
1066 return(node);
1067 }
1068
1069 void
ags_fifoout_xml_parse(AgsConnectable * connectable,xmlNode * node)1070 ags_fifoout_xml_parse(AgsConnectable *connectable,
1071 xmlNode *node)
1072 {
1073 //TODO:JK: implement me
1074 }
1075
1076 gboolean
ags_fifoout_is_connected(AgsConnectable * connectable)1077 ags_fifoout_is_connected(AgsConnectable *connectable)
1078 {
1079 AgsFifoout *fifoout;
1080
1081 gboolean is_connected;
1082
1083 fifoout = AGS_FIFOOUT(connectable);
1084
1085 /* check is connected */
1086 is_connected = ags_fifoout_test_flags(fifoout, AGS_FIFOOUT_CONNECTED);
1087
1088 return(is_connected);
1089 }
1090
1091 void
ags_fifoout_connect(AgsConnectable * connectable)1092 ags_fifoout_connect(AgsConnectable *connectable)
1093 {
1094 AgsFifoout *fifoout;
1095
1096 if(ags_connectable_is_connected(connectable)){
1097 return;
1098 }
1099
1100 fifoout = AGS_FIFOOUT(connectable);
1101
1102 ags_fifoout_set_flags(fifoout, AGS_FIFOOUT_CONNECTED);
1103 }
1104
1105 void
ags_fifoout_disconnect(AgsConnectable * connectable)1106 ags_fifoout_disconnect(AgsConnectable *connectable)
1107 {
1108
1109 AgsFifoout *fifoout;
1110
1111 if(!ags_connectable_is_connected(connectable)){
1112 return;
1113 }
1114
1115 fifoout = AGS_FIFOOUT(connectable);
1116
1117 ags_fifoout_unset_flags(fifoout, AGS_FIFOOUT_CONNECTED);
1118 }
1119
1120 /**
1121 * ags_fifoout_test_flags:
1122 * @fifoout: the #AgsFifoout
1123 * @flags: the flags
1124 *
1125 * Test @flags to be set on @fifoout.
1126 *
1127 * Returns: %TRUE if flags are set, else %FALSE
1128 *
1129 * Since: 3.0.0
1130 */
1131 gboolean
ags_fifoout_test_flags(AgsFifoout * fifoout,guint flags)1132 ags_fifoout_test_flags(AgsFifoout *fifoout, guint flags)
1133 {
1134 gboolean retval;
1135
1136 GRecMutex *fifoout_mutex;
1137
1138 if(!AGS_IS_FIFOOUT(fifoout)){
1139 return(FALSE);
1140 }
1141
1142 /* get fifoout mutex */
1143 fifoout_mutex = AGS_FIFOOUT_GET_OBJ_MUTEX(fifoout);
1144
1145 /* test */
1146 g_rec_mutex_lock(fifoout_mutex);
1147
1148 retval = (flags & (fifoout->flags)) ? TRUE: FALSE;
1149
1150 g_rec_mutex_unlock(fifoout_mutex);
1151
1152 return(retval);
1153 }
1154
1155 /**
1156 * ags_fifoout_set_flags:
1157 * @fifoout: the #AgsFifoout
1158 * @flags: see #AgsFifooutFlags-enum
1159 *
1160 * Enable a feature of @fifoout.
1161 *
1162 * Since: 3.0.0
1163 */
1164 void
ags_fifoout_set_flags(AgsFifoout * fifoout,guint flags)1165 ags_fifoout_set_flags(AgsFifoout *fifoout, guint flags)
1166 {
1167 GRecMutex *fifoout_mutex;
1168
1169 if(!AGS_IS_FIFOOUT(fifoout)){
1170 return;
1171 }
1172
1173 /* get fifoout mutex */
1174 fifoout_mutex = AGS_FIFOOUT_GET_OBJ_MUTEX(fifoout);
1175
1176 //TODO:JK: add more?
1177
1178 /* set flags */
1179 g_rec_mutex_lock(fifoout_mutex);
1180
1181 fifoout->flags |= flags;
1182
1183 g_rec_mutex_unlock(fifoout_mutex);
1184 }
1185
1186 /**
1187 * ags_fifoout_unset_flags:
1188 * @fifoout: the #AgsFifoout
1189 * @flags: see #AgsFifooutFlags-enum
1190 *
1191 * Disable a feature of @fifoout.
1192 *
1193 * Since: 3.0.0
1194 */
1195 void
ags_fifoout_unset_flags(AgsFifoout * fifoout,guint flags)1196 ags_fifoout_unset_flags(AgsFifoout *fifoout, guint flags)
1197 {
1198 GRecMutex *fifoout_mutex;
1199
1200 if(!AGS_IS_FIFOOUT(fifoout)){
1201 return;
1202 }
1203
1204 /* get fifoout mutex */
1205 fifoout_mutex = AGS_FIFOOUT_GET_OBJ_MUTEX(fifoout);
1206
1207 //TODO:JK: add more?
1208
1209 /* unset flags */
1210 g_rec_mutex_lock(fifoout_mutex);
1211
1212 fifoout->flags &= (~flags);
1213
1214 g_rec_mutex_unlock(fifoout_mutex);
1215 }
1216
1217
1218 void
ags_fifoout_set_device(AgsSoundcard * soundcard,gchar * device)1219 ags_fifoout_set_device(AgsSoundcard *soundcard,
1220 gchar *device)
1221 {
1222 AgsFifoout *fifoout;
1223
1224 GRecMutex *fifoout_mutex;
1225
1226 fifoout = AGS_FIFOOUT(soundcard);
1227
1228 /* get fifoout mutex */
1229 fifoout_mutex = AGS_FIFOOUT_GET_OBJ_MUTEX(fifoout);
1230
1231 /* set device */
1232 g_rec_mutex_lock(fifoout_mutex);
1233
1234 fifoout->device = g_strdup(device);
1235
1236 g_rec_mutex_unlock(fifoout_mutex);
1237 }
1238
1239 gchar*
ags_fifoout_get_device(AgsSoundcard * soundcard)1240 ags_fifoout_get_device(AgsSoundcard *soundcard)
1241 {
1242 AgsFifoout *fifoout;
1243
1244 gchar *device;
1245
1246 GRecMutex *fifoout_mutex;
1247
1248 fifoout = AGS_FIFOOUT(soundcard);
1249
1250 /* get fifoout mutex */
1251 fifoout_mutex = AGS_FIFOOUT_GET_OBJ_MUTEX(fifoout);
1252
1253 /* get device */
1254 g_rec_mutex_lock(fifoout_mutex);
1255
1256 device = fifoout->device;
1257
1258 g_rec_mutex_unlock(fifoout_mutex);
1259
1260 return(device);
1261 }
1262
1263 void
ags_fifoout_set_presets(AgsSoundcard * soundcard,guint channels,guint rate,guint buffer_size,guint format)1264 ags_fifoout_set_presets(AgsSoundcard *soundcard,
1265 guint channels,
1266 guint rate,
1267 guint buffer_size,
1268 guint format)
1269 {
1270 AgsFifoout *fifoout;
1271
1272 fifoout = AGS_FIFOOUT(soundcard);
1273
1274 g_object_set(fifoout,
1275 "pcm-channels", channels,
1276 "samplerate", rate,
1277 "buffer-size", buffer_size,
1278 "format", format,
1279 NULL);
1280 }
1281
1282 void
ags_fifoout_get_presets(AgsSoundcard * soundcard,guint * channels,guint * rate,guint * buffer_size,guint * format)1283 ags_fifoout_get_presets(AgsSoundcard *soundcard,
1284 guint *channels,
1285 guint *rate,
1286 guint *buffer_size,
1287 guint *format)
1288 {
1289 AgsFifoout *fifoout;
1290
1291 GRecMutex *fifoout_mutex;
1292
1293 fifoout = AGS_FIFOOUT(soundcard);
1294
1295
1296 /* get fifoout mutex */
1297 fifoout_mutex = AGS_FIFOOUT_GET_OBJ_MUTEX(fifoout);
1298
1299 /* get presets */
1300 g_rec_mutex_lock(fifoout_mutex);
1301
1302 if(channels != NULL){
1303 *channels = fifoout->pcm_channels;
1304 }
1305
1306 if(rate != NULL){
1307 *rate = fifoout->samplerate;
1308 }
1309
1310 if(buffer_size != NULL){
1311 *buffer_size = fifoout->buffer_size;
1312 }
1313
1314 if(format != NULL){
1315 *format = fifoout->format;
1316 }
1317
1318 g_rec_mutex_unlock(fifoout_mutex);
1319 }
1320
1321 void
ags_fifoout_list_cards(AgsSoundcard * soundcard,GList ** card_id,GList ** card_name)1322 ags_fifoout_list_cards(AgsSoundcard *soundcard,
1323 GList **card_id, GList **card_name)
1324 {
1325 AgsFifoout *fifoout;
1326
1327 fifoout = AGS_FIFOOUT(soundcard);
1328
1329 if(card_id != NULL){
1330 *card_id = NULL;
1331 }
1332
1333 if(card_name != NULL){
1334 *card_name = NULL;
1335 }
1336
1337 //TODO:JK: implement me
1338
1339 if(card_id != NULL){
1340 *card_id = g_list_reverse(*card_id);
1341 }
1342
1343 if(card_name != NULL){
1344 *card_name = g_list_reverse(*card_name);
1345 }
1346 }
1347
1348 void
ags_fifoout_pcm_info(AgsSoundcard * soundcard,char * card_id,guint * channels_min,guint * channels_max,guint * rate_min,guint * rate_max,guint * buffer_size_min,guint * buffer_size_max,GError ** error)1349 ags_fifoout_pcm_info(AgsSoundcard *soundcard,
1350 char *card_id,
1351 guint *channels_min, guint *channels_max,
1352 guint *rate_min, guint *rate_max,
1353 guint *buffer_size_min, guint *buffer_size_max,
1354 GError **error)
1355 {
1356 AgsFifoout *fifoout;
1357
1358 fifoout = AGS_FIFOOUT(soundcard);
1359
1360 //TODO:JK: implement me
1361 }
1362
1363 gboolean
ags_fifoout_is_available(AgsSoundcard * soundcard)1364 ags_fifoout_is_available(AgsSoundcard *soundcard)
1365 {
1366 AgsFifoout *fifoout;
1367
1368 //TODO:JK: implement me
1369
1370 return(TRUE);
1371 }
1372
1373 gboolean
ags_fifoout_is_starting(AgsSoundcard * soundcard)1374 ags_fifoout_is_starting(AgsSoundcard *soundcard)
1375 {
1376 AgsFifoout *fifoout;
1377
1378 gboolean is_starting;
1379
1380 GRecMutex *fifoout_mutex;
1381
1382 fifoout = AGS_FIFOOUT(soundcard);
1383
1384 /* get fifoout mutex */
1385 fifoout_mutex = AGS_FIFOOUT_GET_OBJ_MUTEX(fifoout);
1386
1387 /* check is starting */
1388 g_rec_mutex_lock(fifoout_mutex);
1389
1390 is_starting = ((AGS_FIFOOUT_START_PLAY & (fifoout->flags)) != 0) ? TRUE: FALSE;
1391
1392 g_rec_mutex_unlock(fifoout_mutex);
1393
1394 return(is_starting);
1395 }
1396
1397 gboolean
ags_fifoout_is_playing(AgsSoundcard * soundcard)1398 ags_fifoout_is_playing(AgsSoundcard *soundcard)
1399 {
1400 AgsFifoout *fifoout;
1401
1402 gboolean is_playing;
1403
1404 GRecMutex *fifoout_mutex;
1405
1406 fifoout = AGS_FIFOOUT(soundcard);
1407
1408 /* get fifoout mutex */
1409 fifoout_mutex = AGS_FIFOOUT_GET_OBJ_MUTEX(fifoout);
1410
1411 /* check is starting */
1412 g_rec_mutex_lock(fifoout_mutex);
1413
1414 is_playing = ((AGS_FIFOOUT_PLAY & (fifoout->flags)) != 0) ? TRUE: FALSE;
1415
1416 g_rec_mutex_unlock(fifoout_mutex);
1417
1418 return(is_playing);
1419 }
1420
1421 gchar*
ags_fifoout_get_uptime(AgsSoundcard * soundcard)1422 ags_fifoout_get_uptime(AgsSoundcard *soundcard)
1423 {
1424 gchar *uptime;
1425
1426 if(ags_soundcard_is_playing(soundcard)){
1427 guint samplerate;
1428 guint buffer_size;
1429
1430 guint note_offset;
1431 gdouble bpm;
1432 gdouble delay_factor;
1433
1434 gdouble delay;
1435
1436 ags_soundcard_get_presets(soundcard,
1437 NULL,
1438 &samplerate,
1439 &buffer_size,
1440 NULL);
1441
1442 note_offset = ags_soundcard_get_note_offset(soundcard);
1443
1444 bpm = ags_soundcard_get_bpm(soundcard);
1445 delay_factor = ags_soundcard_get_delay_factor(soundcard);
1446
1447 /* calculate delays */
1448 delay = ((gdouble) samplerate / (gdouble) buffer_size) * (gdouble)(60.0 / bpm) * delay_factor;
1449
1450 uptime = ags_time_get_uptime_from_offset(note_offset,
1451 bpm,
1452 delay,
1453 delay_factor);
1454 }else{
1455 uptime = g_strdup(AGS_TIME_ZERO);
1456 }
1457
1458 return(uptime);
1459 }
1460
1461 void
ags_fifoout_fifo_init(AgsSoundcard * soundcard,GError ** error)1462 ags_fifoout_fifo_init(AgsSoundcard *soundcard,
1463 GError **error)
1464 {
1465 //TODO:JK: implement me
1466 }
1467
1468 void
ags_fifoout_fifo_play(AgsSoundcard * soundcard,GError ** error)1469 ags_fifoout_fifo_play(AgsSoundcard *soundcard,
1470 GError **error)
1471 {
1472 //TODO:JK: implement me
1473 }
1474
1475 void
ags_fifoout_fifo_free(AgsSoundcard * soundcard)1476 ags_fifoout_fifo_free(AgsSoundcard *soundcard)
1477 {
1478 //TODO:JK: implement me
1479 }
1480
1481 void
ags_fifoout_tic(AgsSoundcard * soundcard)1482 ags_fifoout_tic(AgsSoundcard *soundcard)
1483 {
1484 AgsFifoout *fifoout;
1485
1486 gdouble delay;
1487 gdouble delay_counter;
1488 guint note_offset_absolute;
1489 guint note_offset;
1490 guint loop_left, loop_right;
1491 gboolean do_loop;
1492
1493 GRecMutex *fifoout_mutex;
1494
1495 fifoout = AGS_FIFOOUT(soundcard);
1496
1497 /* get fifoout mutex */
1498 fifoout_mutex = AGS_FIFOOUT_GET_OBJ_MUTEX(fifoout);
1499
1500 /* determine if attack should be switched */
1501 g_rec_mutex_lock(fifoout_mutex);
1502
1503 delay = fifoout->delay[fifoout->tic_counter];
1504 delay_counter = fifoout->delay_counter;
1505
1506 note_offset = fifoout->note_offset;
1507 note_offset_absolute = fifoout->note_offset_absolute;
1508
1509 loop_left = fifoout->loop_left;
1510 loop_right = fifoout->loop_right;
1511
1512 do_loop = fifoout->do_loop;
1513
1514 g_rec_mutex_unlock(fifoout_mutex);
1515
1516 if((guint) delay_counter + 1 >= (guint) delay){
1517 if(do_loop &&
1518 note_offset + 1 == loop_right){
1519 ags_soundcard_set_note_offset(soundcard,
1520 loop_left);
1521 }else{
1522 ags_soundcard_set_note_offset(soundcard,
1523 note_offset + 1);
1524 }
1525
1526 ags_soundcard_set_note_offset_absolute(soundcard,
1527 note_offset_absolute + 1);
1528
1529 /* delay */
1530 ags_soundcard_offset_changed(soundcard,
1531 note_offset);
1532
1533 /* reset - delay counter */
1534 g_rec_mutex_lock(fifoout_mutex);
1535
1536 fifoout->delay_counter = 0.0;
1537 fifoout->tact_counter += 1.0;
1538
1539 g_rec_mutex_unlock(fifoout_mutex);
1540 }else{
1541 g_rec_mutex_lock(fifoout_mutex);
1542
1543 fifoout->delay_counter += 1.0;
1544
1545 g_rec_mutex_unlock(fifoout_mutex);
1546 }
1547 }
1548
1549 void
ags_fifoout_offset_changed(AgsSoundcard * soundcard,guint note_offset)1550 ags_fifoout_offset_changed(AgsSoundcard *soundcard,
1551 guint note_offset)
1552 {
1553 AgsFifoout *fifoout;
1554
1555 GRecMutex *fifoout_mutex;
1556
1557 fifoout = AGS_FIFOOUT(soundcard);
1558
1559 /* get fifoout mutex */
1560 fifoout_mutex = AGS_FIFOOUT_GET_OBJ_MUTEX(fifoout);
1561
1562 /* offset changed */
1563 g_rec_mutex_lock(fifoout_mutex);
1564
1565 fifoout->tic_counter += 1;
1566
1567 if(fifoout->tic_counter == AGS_SOUNDCARD_DEFAULT_PERIOD){
1568 /* reset - tic counter i.e. modified delay index within period */
1569 fifoout->tic_counter = 0;
1570 }
1571
1572 g_rec_mutex_unlock(fifoout_mutex);
1573 }
1574
1575 void
ags_fifoout_set_bpm(AgsSoundcard * soundcard,gdouble bpm)1576 ags_fifoout_set_bpm(AgsSoundcard *soundcard,
1577 gdouble bpm)
1578 {
1579 AgsFifoout *fifoout;
1580
1581 GRecMutex *fifoout_mutex;
1582
1583 fifoout = AGS_FIFOOUT(soundcard);
1584
1585 /* get fifoout mutex */
1586 fifoout_mutex = AGS_FIFOOUT_GET_OBJ_MUTEX(fifoout);
1587
1588 /* set bpm */
1589 g_rec_mutex_lock(fifoout_mutex);
1590
1591 fifoout->bpm = bpm;
1592
1593 g_rec_mutex_unlock(fifoout_mutex);
1594
1595 ags_fifoout_adjust_delay_and_attack(fifoout);
1596 }
1597
1598 gdouble
ags_fifoout_get_bpm(AgsSoundcard * soundcard)1599 ags_fifoout_get_bpm(AgsSoundcard *soundcard)
1600 {
1601 AgsFifoout *fifoout;
1602
1603 gdouble bpm;
1604
1605 GRecMutex *fifoout_mutex;
1606
1607 fifoout = AGS_FIFOOUT(soundcard);
1608
1609 /* get fifoout mutex */
1610 fifoout_mutex = AGS_FIFOOUT_GET_OBJ_MUTEX(fifoout);
1611
1612 /* get bpm */
1613 g_rec_mutex_lock(fifoout_mutex);
1614
1615 bpm = fifoout->bpm;
1616
1617 g_rec_mutex_unlock(fifoout_mutex);
1618
1619 return(bpm);
1620 }
1621
1622 void
ags_fifoout_set_delay_factor(AgsSoundcard * soundcard,gdouble delay_factor)1623 ags_fifoout_set_delay_factor(AgsSoundcard *soundcard,
1624 gdouble delay_factor)
1625 {
1626 AgsFifoout *fifoout;
1627
1628 GRecMutex *fifoout_mutex;
1629
1630 fifoout = AGS_FIFOOUT(soundcard);
1631
1632 /* get fifoout mutex */
1633 fifoout_mutex = AGS_FIFOOUT_GET_OBJ_MUTEX(fifoout);
1634
1635 /* set delay factor */
1636 g_rec_mutex_lock(fifoout_mutex);
1637
1638 fifoout->delay_factor = delay_factor;
1639
1640 g_rec_mutex_unlock(fifoout_mutex);
1641
1642 ags_fifoout_adjust_delay_and_attack(fifoout);
1643 }
1644
1645 gdouble
ags_fifoout_get_delay_factor(AgsSoundcard * soundcard)1646 ags_fifoout_get_delay_factor(AgsSoundcard *soundcard)
1647 {
1648 AgsFifoout *fifoout;
1649
1650 gdouble delay_factor;
1651
1652 GRecMutex *fifoout_mutex;
1653
1654 fifoout = AGS_FIFOOUT(soundcard);
1655
1656 /* get fifoout mutex */
1657 fifoout_mutex = AGS_FIFOOUT_GET_OBJ_MUTEX(fifoout);
1658
1659 /* get delay factor */
1660 g_rec_mutex_lock(fifoout_mutex);
1661
1662 delay_factor = fifoout->delay_factor;
1663
1664 g_rec_mutex_unlock(fifoout_mutex);
1665
1666 return(delay_factor);
1667 }
1668
1669 gdouble
ags_fifoout_get_delay(AgsSoundcard * soundcard)1670 ags_fifoout_get_delay(AgsSoundcard *soundcard)
1671 {
1672 AgsFifoout *fifoout;
1673
1674 guint index;
1675 gdouble delay;
1676
1677 GRecMutex *fifoout_mutex;
1678
1679 fifoout = AGS_FIFOOUT(soundcard);
1680
1681 /* get fifoout mutex */
1682 fifoout_mutex = AGS_FIFOOUT_GET_OBJ_MUTEX(fifoout);
1683
1684 /* get delay */
1685 g_rec_mutex_lock(fifoout_mutex);
1686
1687 index = fifoout->tic_counter;
1688
1689 delay = fifoout->delay[index];
1690
1691 g_rec_mutex_unlock(fifoout_mutex);
1692
1693 return(delay);
1694 }
1695
1696 gdouble
ags_fifoout_get_absolute_delay(AgsSoundcard * soundcard)1697 ags_fifoout_get_absolute_delay(AgsSoundcard *soundcard)
1698 {
1699 AgsFifoout *fifoout;
1700
1701 gdouble absolute_delay;
1702
1703 GRecMutex *fifoout_mutex;
1704
1705 fifoout = AGS_FIFOOUT(soundcard);
1706
1707 /* get fifoout mutex */
1708 fifoout_mutex = AGS_FIFOOUT_GET_OBJ_MUTEX(fifoout);
1709
1710 /* get absolute delay */
1711 g_rec_mutex_lock(fifoout_mutex);
1712
1713 absolute_delay = (60.0 * (((gdouble) fifoout->samplerate / (gdouble) fifoout->buffer_size) / (gdouble) fifoout->bpm) * ((1.0 / 16.0) * (1.0 / (gdouble) fifoout->delay_factor)));
1714
1715 g_rec_mutex_unlock(fifoout_mutex);
1716
1717 return(absolute_delay);
1718 }
1719
1720 guint
ags_fifoout_get_attack(AgsSoundcard * soundcard)1721 ags_fifoout_get_attack(AgsSoundcard *soundcard)
1722 {
1723 AgsFifoout *fifoout;
1724
1725 guint index;
1726 guint attack;
1727
1728 GRecMutex *fifoout_mutex;
1729
1730 fifoout = AGS_FIFOOUT(soundcard);
1731
1732 /* get fifoout mutex */
1733 fifoout_mutex = AGS_FIFOOUT_GET_OBJ_MUTEX(fifoout);
1734
1735 /* get attack */
1736 g_rec_mutex_lock(fifoout_mutex);
1737
1738 index = fifoout->tic_counter;
1739
1740 attack = fifoout->attack[index];
1741
1742 g_rec_mutex_unlock(fifoout_mutex);
1743
1744 return(attack);
1745 }
1746
1747 void*
ags_fifoout_get_buffer(AgsSoundcard * soundcard)1748 ags_fifoout_get_buffer(AgsSoundcard *soundcard)
1749 {
1750 AgsFifoout *fifoout;
1751
1752 void *buffer;
1753
1754 fifoout = AGS_FIFOOUT(soundcard);
1755
1756 if(ags_fifoout_test_flags(fifoout, AGS_FIFOOUT_BUFFER0)){
1757 buffer = fifoout->buffer[0];
1758 }else if(ags_fifoout_test_flags(fifoout, AGS_FIFOOUT_BUFFER1)){
1759 buffer = fifoout->buffer[1];
1760 }else if(ags_fifoout_test_flags(fifoout, AGS_FIFOOUT_BUFFER2)){
1761 buffer = fifoout->buffer[2];
1762 }else if(ags_fifoout_test_flags(fifoout, AGS_FIFOOUT_BUFFER3)){
1763 buffer = fifoout->buffer[3];
1764 }else{
1765 buffer = NULL;
1766 }
1767
1768 return(buffer);
1769 }
1770
1771 void*
ags_fifoout_get_next_buffer(AgsSoundcard * soundcard)1772 ags_fifoout_get_next_buffer(AgsSoundcard *soundcard)
1773 {
1774 AgsFifoout *fifoout;
1775
1776 void *buffer;
1777
1778 fifoout = AGS_FIFOOUT(soundcard);
1779
1780 // g_message("next - 0x%0x", ((AGS_FIFOOUT_BUFFER0 |
1781 // AGS_FIFOOUT_BUFFER1 |
1782 // AGS_FIFOOUT_BUFFER2 |
1783 // AGS_FIFOOUT_BUFFER3) & (fifoout->flags)));
1784
1785 if(ags_fifoout_test_flags(fifoout, AGS_FIFOOUT_BUFFER0)){
1786 buffer = fifoout->buffer[1];
1787 }else if(ags_fifoout_test_flags(fifoout, AGS_FIFOOUT_BUFFER1)){
1788 buffer = fifoout->buffer[2];
1789 }else if(ags_fifoout_test_flags(fifoout, AGS_FIFOOUT_BUFFER2)){
1790 buffer = fifoout->buffer[3];
1791 }else if(ags_fifoout_test_flags(fifoout, AGS_FIFOOUT_BUFFER3)){
1792 buffer = fifoout->buffer[0];
1793 }else{
1794 buffer = NULL;
1795 }
1796
1797 return(buffer);
1798 }
1799
1800 void*
ags_fifoout_get_prev_buffer(AgsSoundcard * soundcard)1801 ags_fifoout_get_prev_buffer(AgsSoundcard *soundcard)
1802 {
1803 AgsFifoout *fifoout;
1804
1805 void *buffer;
1806
1807 fifoout = AGS_FIFOOUT(soundcard);
1808
1809 if(ags_fifoout_test_flags(fifoout, AGS_FIFOOUT_BUFFER0)){
1810 buffer = fifoout->buffer[3];
1811 }else if(ags_fifoout_test_flags(fifoout, AGS_FIFOOUT_BUFFER1)){
1812 buffer = fifoout->buffer[0];
1813 }else if(ags_fifoout_test_flags(fifoout, AGS_FIFOOUT_BUFFER2)){
1814 buffer = fifoout->buffer[1];
1815 }else if(ags_fifoout_test_flags(fifoout, AGS_FIFOOUT_BUFFER3)){
1816 buffer = fifoout->buffer[2];
1817 }else{
1818 buffer = NULL;
1819 }
1820
1821 return(buffer);
1822 }
1823
1824 guint
ags_fifoout_get_delay_counter(AgsSoundcard * soundcard)1825 ags_fifoout_get_delay_counter(AgsSoundcard *soundcard)
1826 {
1827 AgsFifoout *fifoout;
1828
1829 guint delay_counter;
1830
1831 GRecMutex *fifoout_mutex;
1832
1833 fifoout = AGS_FIFOOUT(soundcard);
1834
1835 /* get fifoout mutex */
1836 fifoout_mutex = AGS_FIFOOUT_GET_OBJ_MUTEX(fifoout);
1837
1838 /* delay counter */
1839 g_rec_mutex_lock(fifoout_mutex);
1840
1841 delay_counter = fifoout->delay_counter;
1842
1843 g_rec_mutex_unlock(fifoout_mutex);
1844
1845 return(delay_counter);
1846 }
1847
1848 void
ags_fifoout_set_note_offset(AgsSoundcard * soundcard,guint note_offset)1849 ags_fifoout_set_note_offset(AgsSoundcard *soundcard,
1850 guint note_offset)
1851 {
1852 AgsFifoout *fifoout;
1853
1854 GRecMutex *fifoout_mutex;
1855
1856 fifoout = AGS_FIFOOUT(soundcard);
1857
1858 /* get fifoout mutex */
1859 fifoout_mutex = AGS_FIFOOUT_GET_OBJ_MUTEX(fifoout);
1860
1861 /* set note offset */
1862 g_rec_mutex_lock(fifoout_mutex);
1863
1864 fifoout->note_offset = note_offset;
1865
1866 g_rec_mutex_unlock(fifoout_mutex);
1867 }
1868
1869 guint
ags_fifoout_get_note_offset(AgsSoundcard * soundcard)1870 ags_fifoout_get_note_offset(AgsSoundcard *soundcard)
1871 {
1872 AgsFifoout *fifoout;
1873
1874 guint note_offset;
1875
1876 GRecMutex *fifoout_mutex;
1877
1878 fifoout = AGS_FIFOOUT(soundcard);
1879
1880 /* get fifoout mutex */
1881 fifoout_mutex = AGS_FIFOOUT_GET_OBJ_MUTEX(fifoout);
1882
1883 /* set note offset */
1884 g_rec_mutex_lock(fifoout_mutex);
1885
1886 note_offset = fifoout->note_offset;
1887
1888 g_rec_mutex_unlock(fifoout_mutex);
1889
1890 return(note_offset);
1891 }
1892
1893 void
ags_fifoout_set_note_offset_absolute(AgsSoundcard * soundcard,guint note_offset_absolute)1894 ags_fifoout_set_note_offset_absolute(AgsSoundcard *soundcard,
1895 guint note_offset_absolute)
1896 {
1897 AgsFifoout *fifoout;
1898
1899 GRecMutex *fifoout_mutex;
1900
1901 fifoout = AGS_FIFOOUT(soundcard);
1902
1903 /* get fifoout mutex */
1904 fifoout_mutex = AGS_FIFOOUT_GET_OBJ_MUTEX(fifoout);
1905
1906 /* set note offset */
1907 g_rec_mutex_lock(fifoout_mutex);
1908
1909 fifoout->note_offset_absolute = note_offset_absolute;
1910
1911 g_rec_mutex_unlock(fifoout_mutex);
1912 }
1913
1914 guint
ags_fifoout_get_note_offset_absolute(AgsSoundcard * soundcard)1915 ags_fifoout_get_note_offset_absolute(AgsSoundcard *soundcard)
1916 {
1917 AgsFifoout *fifoout;
1918
1919 guint note_offset_absolute;
1920
1921 GRecMutex *fifoout_mutex;
1922
1923 fifoout = AGS_FIFOOUT(soundcard);
1924
1925 /* get fifoout mutex */
1926 fifoout_mutex = AGS_FIFOOUT_GET_OBJ_MUTEX(fifoout);
1927
1928 /* set note offset */
1929 g_rec_mutex_lock(fifoout_mutex);
1930
1931 note_offset_absolute = fifoout->note_offset_absolute;
1932
1933 g_rec_mutex_unlock(fifoout_mutex);
1934
1935 return(note_offset_absolute);
1936 }
1937
1938 void
ags_fifoout_set_loop(AgsSoundcard * soundcard,guint loop_left,guint loop_right,gboolean do_loop)1939 ags_fifoout_set_loop(AgsSoundcard *soundcard,
1940 guint loop_left, guint loop_right,
1941 gboolean do_loop)
1942 {
1943 AgsFifoout *fifoout;
1944
1945 GRecMutex *fifoout_mutex;
1946
1947 fifoout = AGS_FIFOOUT(soundcard);
1948
1949 /* get fifoout mutex */
1950 fifoout_mutex = AGS_FIFOOUT_GET_OBJ_MUTEX(fifoout);
1951
1952 /* set loop */
1953 g_rec_mutex_lock(fifoout_mutex);
1954
1955 fifoout->loop_left = loop_left;
1956 fifoout->loop_right = loop_right;
1957 fifoout->do_loop = do_loop;
1958
1959 if(do_loop){
1960 fifoout->loop_offset = fifoout->note_offset;
1961 }
1962
1963 g_rec_mutex_unlock(fifoout_mutex);
1964 }
1965
1966 void
ags_fifoout_get_loop(AgsSoundcard * soundcard,guint * loop_left,guint * loop_right,gboolean * do_loop)1967 ags_fifoout_get_loop(AgsSoundcard *soundcard,
1968 guint *loop_left, guint *loop_right,
1969 gboolean *do_loop)
1970 {
1971 AgsFifoout *fifoout;
1972
1973 GRecMutex *fifoout_mutex;
1974
1975 fifoout = AGS_FIFOOUT(soundcard);
1976
1977 /* get fifoout mutex */
1978 fifoout_mutex = AGS_FIFOOUT_GET_OBJ_MUTEX(fifoout);
1979
1980 /* get loop */
1981 g_rec_mutex_lock(fifoout_mutex);
1982
1983 if(loop_left != NULL){
1984 *loop_left = fifoout->loop_left;
1985 }
1986
1987 if(loop_right != NULL){
1988 *loop_right = fifoout->loop_right;
1989 }
1990
1991 if(do_loop != NULL){
1992 *do_loop = fifoout->do_loop;
1993 }
1994
1995 g_rec_mutex_unlock(fifoout_mutex);
1996 }
1997
1998 guint
ags_fifoout_get_loop_offset(AgsSoundcard * soundcard)1999 ags_fifoout_get_loop_offset(AgsSoundcard *soundcard)
2000 {
2001 AgsFifoout *fifoout;
2002
2003 guint loop_offset;
2004
2005 GRecMutex *fifoout_mutex;
2006
2007 fifoout = AGS_FIFOOUT(soundcard);
2008
2009 /* get fifoout mutex */
2010 fifoout_mutex = AGS_FIFOOUT_GET_OBJ_MUTEX(fifoout);
2011
2012 /* get loop offset */
2013 g_rec_mutex_lock(fifoout_mutex);
2014
2015 loop_offset = fifoout->loop_offset;
2016
2017 g_rec_mutex_unlock(fifoout_mutex);
2018
2019 return(loop_offset);
2020 }
2021
2022 /**
2023 * ags_fifoout_switch_buffer_flag:
2024 * @fifoout: the #AgsFifoout
2025 *
2026 * The buffer flag indicates the currently played buffer.
2027 *
2028 * Since: 3.0.0
2029 */
2030 void
ags_fifoout_switch_buffer_flag(AgsFifoout * fifoout)2031 ags_fifoout_switch_buffer_flag(AgsFifoout *fifoout)
2032 {
2033 GRecMutex *fifoout_mutex;
2034
2035 if(!AGS_IS_FIFOOUT(fifoout)){
2036 return;
2037 }
2038
2039 /* get fifoout mutex */
2040 fifoout_mutex = AGS_FIFOOUT_GET_OBJ_MUTEX(fifoout);
2041
2042 /* switch buffer flag */
2043 g_rec_mutex_lock(fifoout_mutex);
2044
2045 if((AGS_FIFOOUT_BUFFER0 & (fifoout->flags)) != 0){
2046 fifoout->flags &= (~AGS_FIFOOUT_BUFFER0);
2047 fifoout->flags |= AGS_FIFOOUT_BUFFER1;
2048 }else if((AGS_FIFOOUT_BUFFER1 & (fifoout->flags)) != 0){
2049 fifoout->flags &= (~AGS_FIFOOUT_BUFFER1);
2050 fifoout->flags |= AGS_FIFOOUT_BUFFER2;
2051 }else if((AGS_FIFOOUT_BUFFER2 & (fifoout->flags)) != 0){
2052 fifoout->flags &= (~AGS_FIFOOUT_BUFFER2);
2053 fifoout->flags |= AGS_FIFOOUT_BUFFER3;
2054 }else if((AGS_FIFOOUT_BUFFER3 & (fifoout->flags)) != 0){
2055 fifoout->flags &= (~AGS_FIFOOUT_BUFFER3);
2056 fifoout->flags |= AGS_FIFOOUT_BUFFER0;
2057 }
2058
2059 g_rec_mutex_unlock(fifoout_mutex);
2060 }
2061
2062 /**
2063 * ags_fifoout_adjust_delay_and_attack:
2064 * @fifoout: the #AgsFifoout
2065 *
2066 * Calculate delay and attack and reset it.
2067 *
2068 * Since: 3.0.0
2069 */
2070 void
ags_fifoout_adjust_delay_and_attack(AgsFifoout * fifoout)2071 ags_fifoout_adjust_delay_and_attack(AgsFifoout *fifoout)
2072 {
2073 gdouble delay;
2074 guint default_tact_frames;
2075 guint default_period;
2076 guint i;
2077
2078 GRecMutex *fifoout_mutex;
2079
2080 if(!AGS_IS_FIFOOUT(fifoout)){
2081 return;
2082 }
2083
2084 /* get fifoout mutex */
2085 fifoout_mutex = AGS_FIFOOUT_GET_OBJ_MUTEX(fifoout);
2086
2087 /* get some initial values */
2088 delay = (60.0 * (((gdouble) fifoout->samplerate / (gdouble) fifoout->buffer_size) / (gdouble) fifoout->bpm) * ((1.0 / 16.0) * (1.0 / (gdouble) fifoout->delay_factor)));
2089
2090 #ifdef AGS_DEBUG
2091 g_message("delay : %f", delay);
2092 #endif
2093
2094 g_rec_mutex_lock(fifoout_mutex);
2095
2096 default_tact_frames = (guint) (delay * fifoout->buffer_size);
2097 default_period = (1.0 / AGS_SOUNDCARD_DEFAULT_PERIOD) * (default_tact_frames);
2098
2099 fifoout->attack[0] = 0;
2100 fifoout->delay[0] = delay;
2101
2102 for(i = 1; i < (int) 2.0 * AGS_SOUNDCARD_DEFAULT_PERIOD; i++){
2103 fifoout->attack[i] = (guint) ((i * default_tact_frames + fifoout->attack[i - 1]) / (AGS_SOUNDCARD_DEFAULT_PERIOD / (delay * i))) % (guint) (fifoout->buffer_size);
2104
2105 #ifdef AGS_DEBUG
2106 g_message("%d", fifoout->attack[i]);
2107 #endif
2108 }
2109
2110 for(i = 1; i < (int) 2.0 * AGS_SOUNDCARD_DEFAULT_PERIOD; i++){
2111 fifoout->delay[i] = ((gdouble) (default_tact_frames + fifoout->attack[i])) / (gdouble) fifoout->buffer_size;
2112
2113 #ifdef AGS_DEBUG
2114 g_message("%f", fifoout->delay[i]);
2115 #endif
2116 }
2117
2118 g_rec_mutex_unlock(fifoout_mutex);
2119 }
2120
2121 /**
2122 * ags_fifoout_realloc_buffer:
2123 * @fifoout: the #AgsFifoout
2124 *
2125 * Reallocate the internal audio buffer.
2126 *
2127 * Since: 3.0.0
2128 */
2129 void
ags_fifoout_realloc_buffer(AgsFifoout * fifoout)2130 ags_fifoout_realloc_buffer(AgsFifoout *fifoout)
2131 {
2132 guint pcm_channels;
2133 guint buffer_size;
2134 guint word_size;
2135
2136 GRecMutex *fifoout_mutex;
2137
2138 if(!AGS_IS_FIFOOUT(fifoout)){
2139 return;
2140 }
2141
2142 /* get fifoout mutex */
2143 fifoout_mutex = AGS_FIFOOUT_GET_OBJ_MUTEX(fifoout);
2144
2145 /* get word size */
2146 g_rec_mutex_lock(fifoout_mutex);
2147
2148 pcm_channels = fifoout->pcm_channels;
2149 buffer_size = fifoout->buffer_size;
2150
2151 switch(fifoout->format){
2152 case AGS_SOUNDCARD_SIGNED_8_BIT:
2153 {
2154 word_size = sizeof(gint8);
2155 }
2156 break;
2157 case AGS_SOUNDCARD_SIGNED_16_BIT:
2158 {
2159 word_size = sizeof(gint16);
2160 }
2161 break;
2162 case AGS_SOUNDCARD_SIGNED_24_BIT:
2163 {
2164 word_size = sizeof(gint32);
2165 }
2166 break;
2167 case AGS_SOUNDCARD_SIGNED_32_BIT:
2168 {
2169 word_size = sizeof(gint32);
2170 }
2171 break;
2172 case AGS_SOUNDCARD_SIGNED_64_BIT:
2173 {
2174 word_size = sizeof(gint64);
2175 }
2176 break;
2177 default:
2178 g_warning("ags_fifoout_realloc_buffer(): unsupported word size");
2179 return;
2180 }
2181
2182 g_rec_mutex_unlock(fifoout_mutex);
2183
2184 //NOTE:JK: there is no lock applicable to buffer
2185
2186 /* AGS_FIFOOUT_BUFFER_0 */
2187 if(fifoout->buffer[0] != NULL){
2188 free(fifoout->buffer[0]);
2189 }
2190
2191 fifoout->buffer[0] = (void *) malloc(pcm_channels * buffer_size * word_size);
2192
2193 /* AGS_FIFOOUT_BUFFER_1 */
2194 if(fifoout->buffer[1] != NULL){
2195 free(fifoout->buffer[1]);
2196 }
2197
2198 fifoout->buffer[1] = (void *) malloc(pcm_channels * buffer_size * word_size);
2199
2200 /* AGS_FIFOOUT_BUFFER_2 */
2201 if(fifoout->buffer[2] != NULL){
2202 free(fifoout->buffer[2]);
2203 }
2204
2205 fifoout->buffer[2] = (void *) malloc(pcm_channels * buffer_size * word_size);
2206
2207 /* AGS_FIFOOUT_BUFFER_3 */
2208 if(fifoout->buffer[3] != NULL){
2209 free(fifoout->buffer[3]);
2210 }
2211
2212 fifoout->buffer[3] = (void *) malloc(pcm_channels * buffer_size * word_size);
2213 }
2214
2215 /**
2216 * ags_fifoout_new:
2217 *
2218 * Creates a new instance of #AgsFifoout.
2219 *
2220 * Returns: the new #AgsFifoout
2221 *
2222 * Since: 3.0.0
2223 */
2224 AgsFifoout*
ags_fifoout_new()2225 ags_fifoout_new()
2226 {
2227 AgsFifoout *fifoout;
2228
2229 fifoout = (AgsFifoout *) g_object_new(AGS_TYPE_FIFOOUT,
2230 NULL);
2231
2232 return(fifoout);
2233 }
2234