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/recall/ags_capture_wave_channel_run.h>
21
22 #include <ags/audio/ags_recycling.h>
23 #include <ags/audio/ags_recall_id.h>
24 #include <ags/audio/ags_recall_container.h>
25 #include <ags/audio/ags_audio_buffer_util.h>
26
27 #include <ags/audio/recall/ags_capture_wave_audio.h>
28 #include <ags/audio/recall/ags_capture_wave_audio_run.h>
29 #include <ags/audio/recall/ags_capture_wave_channel.h>
30
31 #include <ags/i18n.h>
32
33 void ags_capture_wave_channel_run_class_init(AgsCaptureWaveChannelRunClass *capture_wave_channel_run);
34 void ags_capture_wave_channel_run_seekable_interface_init(AgsSeekableInterface *seekable);
35 void ags_capture_wave_channel_run_init(AgsCaptureWaveChannelRun *capture_wave_channel_run);
36 void ags_capture_wave_channel_run_set_property(GObject *gobject,
37 guint prop_id,
38 const GValue *value,
39 GParamSpec *param_spec);
40 void ags_capture_wave_channel_run_get_property(GObject *gobject,
41 guint prop_id,
42 GValue *value,
43 GParamSpec *param_spec);
44 void ags_capture_wave_channel_run_dispose(GObject *gobject);
45 void ags_capture_wave_channel_run_finalize(GObject *gobject);
46
47 void ags_capture_wave_channel_run_seek(AgsSeekable *seekable,
48 gint64 offset,
49 guint whence);
50
51 void ags_capture_wave_channel_run_run_pre(AgsRecall *recall);
52
53 /**
54 * SECTION:ags_capture_wave_channel_run
55 * @short_description: capture wave
56 * @title: AgsCaptureWaveChannelRun
57 * @section_id:
58 * @include: ags/channel/recall/ags_capture_wave_channel_run.h
59 *
60 * The #AgsCaptureWaveChannelRun class capture wave.
61 */
62
63 enum{
64 PROP_0,
65 PROP_X_OFFSET,
66 };
67
68 static gpointer ags_capture_wave_channel_run_parent_class = NULL;
69
70 GType
ags_capture_wave_channel_run_get_type()71 ags_capture_wave_channel_run_get_type()
72 {
73 static volatile gsize g_define_type_id__volatile = 0;
74
75 if(g_once_init_enter (&g_define_type_id__volatile)){
76 GType ags_type_capture_wave_channel_run = 0;
77
78 static const GTypeInfo ags_capture_wave_channel_run_info = {
79 sizeof (AgsCaptureWaveChannelRunClass),
80 NULL, /* base_init */
81 NULL, /* base_finalize */
82 (GClassInitFunc) ags_capture_wave_channel_run_class_init,
83 NULL, /* class_finalize */
84 NULL, /* class_data */
85 sizeof (AgsCaptureWaveChannelRun),
86 0, /* n_preallocs */
87 (GInstanceInitFunc) ags_capture_wave_channel_run_init,
88 };
89
90 static const GInterfaceInfo ags_seekable_interface_info = {
91 (GInterfaceInitFunc) ags_capture_wave_channel_run_seekable_interface_init,
92 NULL, /* interface_finalize */
93 NULL, /* interface_data */
94 };
95
96 ags_type_capture_wave_channel_run = g_type_register_static(AGS_TYPE_RECALL_CHANNEL_RUN,
97 "AgsCaptureWaveChannelRun",
98 &ags_capture_wave_channel_run_info,
99 0);
100
101 g_type_add_interface_static(ags_type_capture_wave_channel_run,
102 AGS_TYPE_SEEKABLE,
103 &ags_seekable_interface_info);
104
105 g_once_init_leave(&g_define_type_id__volatile, ags_type_capture_wave_channel_run);
106 }
107
108 return g_define_type_id__volatile;
109 }
110
111 void
ags_capture_wave_channel_run_class_init(AgsCaptureWaveChannelRunClass * capture_wave_channel_run)112 ags_capture_wave_channel_run_class_init(AgsCaptureWaveChannelRunClass *capture_wave_channel_run)
113 {
114 GObjectClass *gobject;
115 AgsRecallClass *recall;
116
117 GParamSpec *param_spec;
118
119 ags_capture_wave_channel_run_parent_class = g_type_class_peek_parent(capture_wave_channel_run);
120
121 /* GObjectClass */
122 gobject = (GObjectClass *) capture_wave_channel_run;
123
124 gobject->set_property = ags_capture_wave_channel_run_set_property;
125 gobject->get_property = ags_capture_wave_channel_run_get_property;
126
127 gobject->dispose = ags_capture_wave_channel_run_dispose;
128 gobject->finalize = ags_capture_wave_channel_run_finalize;
129
130 /* properties */
131 /**
132 * AgsCaptureWaveChannelRun:x-offset:
133 *
134 * The x offset.
135 *
136 * Since: 3.0.0
137 */
138 param_spec = g_param_spec_uint64("x-offset",
139 i18n_pspec("x offset"),
140 i18n_pspec("The x offset in the wave"),
141 0,
142 G_MAXUINT64,
143 0,
144 G_PARAM_READABLE | G_PARAM_WRITABLE);
145 g_object_class_install_property(gobject,
146 PROP_X_OFFSET,
147 param_spec);
148
149 /* AgsRecallClass */
150 recall = (AgsRecallClass *) capture_wave_channel_run;
151
152 recall->run_pre = ags_capture_wave_channel_run_run_pre;
153 }
154
155 void
ags_capture_wave_channel_run_seekable_interface_init(AgsSeekableInterface * seekable)156 ags_capture_wave_channel_run_seekable_interface_init(AgsSeekableInterface *seekable)
157 {
158 seekable->seek = ags_capture_wave_channel_run_seek;
159 }
160
161 void
ags_capture_wave_channel_run_init(AgsCaptureWaveChannelRun * capture_wave_channel_run)162 ags_capture_wave_channel_run_init(AgsCaptureWaveChannelRun *capture_wave_channel_run)
163 {
164 ags_recall_set_ability_flags((AgsRecall *) capture_wave_channel_run, (AGS_SOUND_ABILITY_WAVE));
165
166 AGS_RECALL(capture_wave_channel_run)->name = "ags-capture-wave";
167 AGS_RECALL(capture_wave_channel_run)->version = AGS_RECALL_DEFAULT_VERSION;
168 AGS_RECALL(capture_wave_channel_run)->build_id = AGS_RECALL_DEFAULT_BUILD_ID;
169 AGS_RECALL(capture_wave_channel_run)->xml_type = "ags-capture-wave-channel-run";
170 AGS_RECALL(capture_wave_channel_run)->port = NULL;
171
172 capture_wave_channel_run->timestamp = ags_timestamp_new();
173 g_object_ref(capture_wave_channel_run->timestamp);
174
175 capture_wave_channel_run->timestamp->flags &= (~AGS_TIMESTAMP_UNIX);
176 capture_wave_channel_run->timestamp->flags |= AGS_TIMESTAMP_OFFSET;
177
178 capture_wave_channel_run->timestamp->timer.ags_offset.offset = 0;
179
180 capture_wave_channel_run->audio_signal = NULL;
181
182 capture_wave_channel_run->x_offset = 0;
183 }
184
185 void
ags_capture_wave_channel_run_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)186 ags_capture_wave_channel_run_set_property(GObject *gobject,
187 guint prop_id,
188 const GValue *value,
189 GParamSpec *param_spec)
190 {
191 AgsCaptureWaveChannelRun *capture_wave_channel_run;
192
193 GRecMutex *recall_mutex;
194
195 capture_wave_channel_run = AGS_CAPTURE_WAVE_CHANNEL_RUN(gobject);
196
197 /* get recall mutex */
198 recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(capture_wave_channel_run);
199
200 switch(prop_id){
201 case PROP_X_OFFSET:
202 {
203 guint64 x_offset;
204
205 x_offset = g_value_get_uint64(value);
206
207 g_rec_mutex_lock(recall_mutex);
208
209 capture_wave_channel_run->x_offset = x_offset;
210
211 g_rec_mutex_unlock(recall_mutex);
212 }
213 break;
214 default:
215 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
216 break;
217 };
218 }
219
220 void
ags_capture_wave_channel_run_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)221 ags_capture_wave_channel_run_get_property(GObject *gobject,
222 guint prop_id,
223 GValue *value,
224 GParamSpec *param_spec)
225 {
226 AgsCaptureWaveChannelRun *capture_wave_channel_run;
227
228 GRecMutex *recall_mutex;
229
230 capture_wave_channel_run = AGS_CAPTURE_WAVE_CHANNEL_RUN(gobject);
231
232 /* get recall mutex */
233 recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(capture_wave_channel_run);
234
235 switch(prop_id){
236 case PROP_X_OFFSET:
237 {
238 g_rec_mutex_lock(recall_mutex);
239
240 g_value_set_uint64(value, capture_wave_channel_run->x_offset);
241
242 g_rec_mutex_unlock(recall_mutex);
243 }
244 break;
245 default:
246 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
247 break;
248 };
249 }
250
251 void
ags_capture_wave_channel_run_dispose(GObject * gobject)252 ags_capture_wave_channel_run_dispose(GObject *gobject)
253 {
254 AgsCaptureWaveChannelRun *capture_wave_channel_run;
255
256 capture_wave_channel_run = AGS_CAPTURE_WAVE_CHANNEL_RUN(gobject);
257
258 /* call parent */
259 G_OBJECT_CLASS(ags_capture_wave_channel_run_parent_class)->dispose(gobject);
260 }
261
262 void
ags_capture_wave_channel_run_finalize(GObject * gobject)263 ags_capture_wave_channel_run_finalize(GObject *gobject)
264 {
265 AgsCaptureWaveChannelRun *capture_wave_channel_run;
266
267 capture_wave_channel_run = AGS_CAPTURE_WAVE_CHANNEL_RUN(gobject);
268
269 /* timestamp */
270 if(capture_wave_channel_run->timestamp != NULL){
271 g_object_unref(G_OBJECT(capture_wave_channel_run->timestamp));
272 }
273
274 /* call parent */
275 G_OBJECT_CLASS(ags_capture_wave_channel_run_parent_class)->finalize(gobject);
276 }
277
278 void
ags_capture_wave_channel_run_seek(AgsSeekable * seekable,gint64 offset,guint whence)279 ags_capture_wave_channel_run_seek(AgsSeekable *seekable,
280 gint64 offset,
281 guint whence)
282 {
283 AgsCaptureWaveChannelRun *capture_wave_channel_run;
284
285 GObject *soundcard;
286
287 gdouble absolute_delay;
288 guint buffer_size;
289 guint64 x_offset;
290
291 capture_wave_channel_run = AGS_CAPTURE_WAVE_CHANNEL_RUN(seekable);
292
293 g_object_get(capture_wave_channel_run,
294 "output-soundcard", &soundcard,
295 "buffer-size", &buffer_size,
296 NULL);
297
298 absolute_delay = ags_soundcard_get_absolute_delay(AGS_SOUNDCARD(soundcard));
299
300 switch(whence){
301 case AGS_SEEK_CUR:
302 {
303 g_object_get(capture_wave_channel_run,
304 "x-offset", &x_offset,
305 NULL);
306
307 if(x_offset + (offset * absolute_delay * buffer_size) < 0){
308 x_offset = 0;
309 }else{
310 x_offset = x_offset + (offset * absolute_delay * buffer_size);
311 }
312
313 g_object_set(capture_wave_channel_run,
314 "x-offset", x_offset,
315 NULL);
316 }
317 break;
318 case AGS_SEEK_END:
319 {
320 g_warning("seek from end not implemented");
321 }
322 break;
323 case AGS_SEEK_SET:
324 {
325 x_offset = offset * absolute_delay * buffer_size;
326
327 g_object_set(capture_wave_channel_run,
328 "x-offset", x_offset,
329 NULL);
330 }
331 break;
332 }
333
334 g_object_unref(soundcard);
335 }
336
337 void
ags_capture_wave_channel_run_run_pre(AgsRecall * recall)338 ags_capture_wave_channel_run_run_pre(AgsRecall *recall)
339 {
340 AgsAudio *audio;
341 AgsChannel *channel;
342 AgsChannel *start_input;
343 AgsChannel *input;
344 AgsPort *port;
345 AgsWave *wave;
346 AgsBuffer *buffer;
347
348 AgsCaptureWaveAudio *capture_wave_audio;
349 AgsCaptureWaveAudioRun *capture_wave_audio_run;
350 AgsCaptureWaveChannel *capture_wave_channel;
351 AgsCaptureWaveChannelRun *capture_wave_channel_run;
352
353 AgsTimestamp *timestamp;
354
355 GObject *output_soundcard, *input_soundcard;
356
357 GList *list_start, *list;
358
359 void *data, *file_data;
360
361 gint input_soundcard_channel;
362 guint line;
363 guint64 relative_offset;
364 guint note_offset;
365 gdouble delay;
366 guint delay_counter;
367 gboolean do_loop;
368 guint64 x_offset;
369 guint64 x_point_offset;
370 guint target_copy_mode, file_copy_mode;
371 guint audio_channels, target_audio_channels, file_audio_channels;
372 guint samplerate, target_samplerate, file_samplerate;
373 guint format, target_format, file_format;
374 guint buffer_size, target_buffer_size, file_buffer_size;
375 guint frame_count;
376 guint attack;
377 gboolean do_playback, do_replace, is_new_buffer;
378 gboolean do_record;
379 gboolean resample_target, resample_file;
380 gboolean create_wave;
381
382 GValue value = {0,};
383 GValue do_loop_value = {0,};
384 GValue x_offset_value = {0,};
385
386 void (*parent_class_run_pre)(AgsRecall *recall);
387
388 GRecMutex *audio_mutex;
389 GRecMutex *buffer_mutex;
390 GRecMutex *recall_mutex;
391
392 capture_wave_channel_run = AGS_CAPTURE_WAVE_CHANNEL_RUN(recall);
393
394 /* get parent class */
395 parent_class_run_pre = AGS_RECALL_CLASS(ags_capture_wave_channel_run_parent_class)->run_pre;
396
397 /* get mutex */
398 recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(recall);
399
400 /* get some fields */
401 g_object_get(capture_wave_channel_run,
402 "recall-audio", &capture_wave_audio,
403 "recall-audio-run", &capture_wave_audio_run,
404 "recall-channel", &capture_wave_channel,
405 NULL);
406
407 timestamp = capture_wave_channel_run->timestamp;
408
409 g_object_get(capture_wave_channel_run,
410 "source", &channel,
411 NULL);
412
413 g_object_get(channel,
414 "line", &line,
415 "input-soundcard-channel", &input_soundcard_channel,
416 NULL);
417
418 if(input_soundcard_channel == -1){
419 input_soundcard_channel = line;
420 }
421
422 /* get audio and mutex */
423 g_object_get(capture_wave_audio,
424 "audio", &audio,
425 NULL);
426
427 audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
428
429 g_object_get(audio,
430 "input", &start_input,
431 "buffer-size", &target_buffer_size,
432 NULL);
433
434 /* get soundcard */
435 input = ags_channel_nth(start_input,
436 line);
437
438 g_object_get(input,
439 "output-soundcard", &output_soundcard,
440 "input-soundcard", &input_soundcard,
441 NULL);
442
443 if(input_soundcard == NULL){
444 /* call parent */
445 parent_class_run_pre(recall);
446
447 /* unref */
448 g_object_unref(capture_wave_audio);
449
450 g_object_unref(capture_wave_audio_run);
451
452 g_object_unref(capture_wave_channel);
453
454 g_object_unref(channel);
455
456 g_object_unref(audio);
457
458 if(start_input != NULL){
459 g_object_unref(start_input);
460 }
461
462 if(input != NULL){
463 g_object_unref(input);
464 }
465
466 return;
467 }
468
469 data = ags_soundcard_get_prev_buffer(AGS_SOUNDCARD(input_soundcard));
470 ags_soundcard_get_presets(AGS_SOUNDCARD(input_soundcard),
471 &audio_channels,
472 &samplerate,
473 &buffer_size,
474 &format);
475
476 frame_count = buffer_size;
477
478 note_offset = ags_soundcard_get_note_offset(AGS_SOUNDCARD(output_soundcard));
479 delay = ags_soundcard_get_delay(AGS_SOUNDCARD(output_soundcard));
480
481 delay_counter = ags_soundcard_get_delay_counter(AGS_SOUNDCARD(output_soundcard));
482
483 x_offset = capture_wave_channel_run->x_offset;
484
485 relative_offset = AGS_WAVE_DEFAULT_BUFFER_LENGTH * samplerate;
486
487 /* read playback */
488 g_object_get(capture_wave_audio,
489 "playback", &port,
490 NULL);
491
492 g_value_init(&value,
493 G_TYPE_BOOLEAN);
494 ags_port_safe_read(port,
495 &value);
496
497 do_playback = g_value_get_boolean(&value);
498 g_value_unset(&value);
499
500 g_object_unref(port);
501
502 if(do_playback){
503 /* read replace */
504 g_object_get(capture_wave_audio,
505 "replace", &port,
506 NULL);
507
508 g_value_init(&value,
509 G_TYPE_BOOLEAN);
510 ags_port_safe_read(port,
511 &value);
512
513 do_replace = g_value_get_boolean(&value);
514 g_value_unset(&value);
515
516 g_object_unref(port);
517
518 /* get target presets */
519 g_rec_mutex_lock(audio_mutex);
520
521 target_audio_channels = audio->audio_channels;
522 target_samplerate = audio->samplerate;
523 target_buffer_size = audio->buffer_size;
524 target_format = audio->format;
525
526 list_start = g_list_copy(audio->wave);
527
528 g_rec_mutex_unlock(audio_mutex);
529
530 relative_offset = AGS_WAVE_DEFAULT_BUFFER_LENGTH * target_samplerate;
531
532 attack = (x_offset % relative_offset) % target_buffer_size;
533
534 frame_count = target_buffer_size - attack;
535
536 create_wave = FALSE;
537
538 if(x_offset + frame_count > relative_offset * floor(x_offset / relative_offset) + relative_offset){
539 frame_count = relative_offset * floor((x_offset + frame_count) / relative_offset) - x_offset;
540 create_wave = TRUE;
541 }else if(x_offset + frame_count == relative_offset * floor(x_offset / relative_offset) + relative_offset){
542 create_wave = TRUE;
543 }
544
545 /* check resample */
546 resample_target = FALSE;
547
548 if(target_samplerate != samplerate){
549 void *tmp_data;
550
551 tmp_data = ags_stream_alloc(target_buffer_size,
552 format);
553
554 ags_audio_buffer_util_resample_with_buffer(data, audio_channels,
555 ags_audio_buffer_util_format_from_soundcard(format), samplerate,
556 buffer_size,
557 target_samplerate,
558 target_buffer_size,
559 tmp_data);
560
561 data = tmp_data;
562
563 resample_target = TRUE;
564 }
565
566 target_copy_mode = ags_audio_buffer_util_get_copy_mode(ags_audio_buffer_util_format_from_soundcard(target_format),
567 ags_audio_buffer_util_format_from_soundcard(format));
568
569 ags_timestamp_set_ags_offset(timestamp,
570 relative_offset * floor(x_offset / relative_offset));
571
572 /* play */
573 list = ags_wave_find_near_timestamp(list_start, line,
574 timestamp);
575
576 if(list != NULL){
577 wave = list->data;
578 }else{
579 AgsTimestamp *current_timestamp;
580
581 wave = ags_wave_new((GObject *) audio,
582 line);
583
584 g_object_get(wave,
585 "timestamp", ¤t_timestamp,
586 NULL);
587 ags_timestamp_set_ags_offset(current_timestamp,
588 relative_offset * floor(x_offset / relative_offset));
589
590 ags_audio_add_wave(audio,
591 (GObject *) wave);
592
593 g_object_unref(current_timestamp);
594 }
595
596 x_point_offset = x_offset - attack;
597
598 buffer = ags_wave_find_point(wave,
599 x_point_offset,
600 FALSE);
601
602 is_new_buffer = FALSE;
603
604 if(buffer == NULL){
605 buffer = ags_buffer_new();
606 buffer->x = x_point_offset;
607
608 ags_wave_add_buffer(wave,
609 buffer,
610 FALSE);
611
612 is_new_buffer = TRUE;
613 }
614
615 /* get buffer mutex */
616 buffer_mutex = AGS_BUFFER_GET_OBJ_MUTEX(buffer);
617
618 if(!is_new_buffer &&
619 do_replace){
620 void *data;
621
622 data = NULL;
623
624 switch(target_format){
625 case AGS_SOUNDCARD_SIGNED_8_BIT:
626 {
627 data = ((gint8 *) buffer->data) + attack;
628 }
629 break;
630 case AGS_SOUNDCARD_SIGNED_16_BIT:
631 {
632 data = ((gint16 *) buffer->data) + attack;
633 }
634 break;
635 case AGS_SOUNDCARD_SIGNED_24_BIT:
636 {
637 data = ((gint32 *) buffer->data) + attack;
638 }
639 break;
640 case AGS_SOUNDCARD_SIGNED_32_BIT:
641 {
642 data = ((gint32 *) buffer->data) + attack;
643 }
644 break;
645 case AGS_SOUNDCARD_SIGNED_64_BIT:
646 {
647 data = ((gint64 *) buffer->data) + attack;
648 }
649 break;
650 }
651
652 g_rec_mutex_lock(buffer_mutex);
653
654 ags_audio_buffer_util_clear_buffer(data, 1,
655 target_buffer_size - attack, ags_audio_buffer_util_format_from_soundcard(target_format));
656
657 g_rec_mutex_unlock(buffer_mutex);
658 }
659
660 /* copy to buffer */
661 g_rec_mutex_lock(buffer_mutex);
662 ags_soundcard_lock_buffer(AGS_SOUNDCARD(input_soundcard), data);
663
664 ags_audio_buffer_util_copy_buffer_to_buffer(buffer->data, 1, attack,
665 data, audio_channels, input_soundcard_channel,
666 frame_count, target_copy_mode);
667
668 ags_soundcard_unlock_buffer(AGS_SOUNDCARD(input_soundcard), data);
669 g_rec_mutex_unlock(buffer_mutex);
670
671 g_list_free(list_start);
672
673 /* 2nd attempt */
674 g_rec_mutex_lock(audio_mutex);
675
676 list_start = g_list_copy(audio->wave);
677
678 g_rec_mutex_unlock(audio_mutex);
679
680 if(create_wave){
681 ags_timestamp_set_ags_offset(timestamp,
682 relative_offset * floor((x_offset + frame_count) / relative_offset));
683
684 /* play */
685 list = ags_wave_find_near_timestamp(list_start, line,
686 timestamp);
687
688 if(list != NULL){
689 wave = list->data;
690 }else{
691 AgsTimestamp *current_timestamp;
692
693 wave = ags_wave_new((GObject *) audio,
694 line);
695
696 g_object_get(wave,
697 "timestamp", ¤t_timestamp,
698 NULL);
699 ags_timestamp_set_ags_offset(current_timestamp,
700 relative_offset * floor((x_offset + frame_count) / relative_offset));
701
702 ags_audio_add_wave(audio,
703 (GObject *) wave);
704
705 g_object_unref(current_timestamp);
706 }
707 }
708
709 g_list_free(list_start);
710
711 if(attack != 0 ||
712 target_buffer_size != frame_count){
713 x_point_offset = x_offset + frame_count;
714 buffer = ags_wave_find_point(wave,
715 x_point_offset,
716 FALSE);
717
718 is_new_buffer = FALSE;
719
720 if(buffer == NULL){
721 buffer = ags_buffer_new();
722 buffer->x = x_point_offset;
723
724 ags_wave_add_buffer(wave,
725 buffer,
726 FALSE);
727
728 is_new_buffer = TRUE;
729 }
730
731 /* get buffer mutex */
732 buffer_mutex = AGS_BUFFER_GET_OBJ_MUTEX(buffer);
733
734 if(!is_new_buffer &&
735 do_replace){
736 g_rec_mutex_lock(buffer_mutex);
737
738 ags_audio_buffer_util_clear_buffer(buffer->data, 1,
739 target_buffer_size - frame_count, ags_audio_buffer_util_format_from_soundcard(target_format));
740
741 g_rec_mutex_unlock(buffer_mutex);
742 }
743
744 /* copy to buffer */
745 g_rec_mutex_lock(buffer_mutex);
746 ags_soundcard_lock_buffer(AGS_SOUNDCARD(input_soundcard), data);
747
748 ags_audio_buffer_util_copy_buffer_to_buffer(buffer->data, 1, 0,
749 data, audio_channels, (frame_count * audio_channels) + input_soundcard_channel,
750 target_buffer_size - frame_count, target_copy_mode);
751
752 ags_soundcard_unlock_buffer(AGS_SOUNDCARD(input_soundcard), data);
753 g_rec_mutex_unlock(buffer_mutex);
754 }
755
756 if(resample_target){
757 g_free(data);
758 }
759 }
760
761 /* read record */
762 g_object_get(capture_wave_audio,
763 "record", &port,
764 NULL);
765
766 g_value_init(&value,
767 G_TYPE_BOOLEAN);
768 ags_port_safe_read(port,
769 &value);
770
771 do_record = g_value_get_boolean(&value);
772 g_value_unset(&value);
773
774 g_object_unref(port);
775
776 if(do_record){
777 AgsAudioFile *audio_file;
778
779 g_rec_mutex_lock(&(capture_wave_audio->audio_file_mutex));
780
781 audio_file = capture_wave_audio->audio_file;
782
783 g_rec_mutex_unlock(&(capture_wave_audio->audio_file_mutex));
784
785 /* get presets */
786 g_object_get(audio_file,
787 "file-audio-channels", &file_audio_channels,
788 "samplerate", &file_samplerate,
789 "buffer-size", &file_buffer_size,
790 "format", &file_format,
791 NULL);
792
793 ags_audio_buffer_util_clear_buffer(capture_wave_audio_run->file_buffer, 1,
794 file_audio_channels * file_buffer_size, file_format);
795
796 if(file_samplerate != samplerate){
797 void *tmp_data;
798
799 tmp_data = ags_stream_alloc(file_buffer_size,
800 format);
801
802 ags_audio_buffer_util_resample_with_buffer(data, audio_channels,
803 ags_audio_buffer_util_format_from_soundcard(format), samplerate,
804 buffer_size,
805 file_samplerate,
806 file_buffer_size,
807 tmp_data);
808
809 data = tmp_data;
810
811 resample_file = TRUE;
812 }
813
814 file_copy_mode = ags_audio_buffer_util_get_copy_mode(ags_audio_buffer_util_format_from_soundcard(file_format),
815 ags_audio_buffer_util_format_from_soundcard(format));
816
817 //TODO:JK: implement me
818 #if 0
819 ags_soundcard_lock_buffer(AGS_SOUNDCARD(input_soundcard), data);
820
821 ags_audio_buffer_util_copy_buffer_to_buffer(file_data, file_audio_channels, line,
822 data, audio_channels, input_soundcard_channel,
823 file_buffer_size, file_copy_mode);
824
825 ags_soundcard_unlock_buffer(AGS_SOUNDCARD(input_soundcard), data);
826
827 if(resample_file){
828 g_free(data);
829 }
830
831 /* file */
832 g_rec_mutex_lock(&(capture_wave_audio->audio_file_mutex));
833
834 ags_audio_file_write(audio_file,
835 capture_wave_audio_run->file_buffer, file_buffer_size,
836 file_format);
837
838 g_rec_mutex_unlock(&(capture_wave_audio->audio_file_mutex));
839 #endif
840 }
841
842 /* check loop */
843 x_offset += target_buffer_size;
844
845 g_object_get(capture_wave_audio,
846 "wave-loop", &port,
847 NULL);
848
849 g_value_init(&do_loop_value,
850 G_TYPE_BOOLEAN);
851
852 ags_port_safe_read(port,
853 &do_loop_value);
854
855 do_loop = g_value_get_boolean(&do_loop_value);
856
857 g_value_unset(&do_loop_value);
858 g_object_unref(port);
859
860 if(do_loop){
861 guint64 loop_start, loop_end;
862
863 GValue loop_start_value = {0,};
864 GValue loop_end_value = {0,};
865
866 g_object_get(capture_wave_audio,
867 "wave-loop-end", &port,
868 NULL);
869
870 g_value_init(&loop_end_value,
871 G_TYPE_UINT64);
872
873 ags_port_safe_read(port,
874 &loop_end_value);
875
876 loop_end = g_value_get_uint64(&loop_end_value);
877
878 g_value_unset(&loop_end_value);
879 g_object_unref(port);
880
881 if(x_offset / buffer_size / delay >= loop_end){
882 g_object_get(capture_wave_audio,
883 "wave-loop-start", &port,
884 NULL);
885
886 g_value_init(&loop_start_value,
887 G_TYPE_UINT64);
888
889 ags_port_safe_read(port,
890 &loop_start_value);
891
892 loop_start = g_value_get_uint64(&loop_start_value);
893 g_value_unset(&loop_start_value);
894
895 g_object_unref(port);
896
897 x_offset = (relative_offset * floor((delay * buffer_size * loop_start) / relative_offset)) + ((guint64) (delay * buffer_size * loop_start) % relative_offset);
898 }
899 }
900
901 /* new x offset */
902 capture_wave_channel_run->x_offset = x_offset;
903
904 g_object_get(capture_wave_channel,
905 "x-offset", &port,
906 NULL);
907
908 g_value_init(&x_offset_value,
909 G_TYPE_UINT64);
910
911 g_value_set_uint64(&x_offset_value,
912 x_offset);
913
914 ags_port_safe_write(port,
915 &x_offset_value);
916
917 g_value_unset(&x_offset_value);
918 g_object_unref(port);
919
920 /* call parent */
921 parent_class_run_pre(recall);
922
923 /* unref */
924 g_object_unref(capture_wave_audio);
925
926 g_object_unref(capture_wave_audio_run);
927
928 g_object_unref(capture_wave_channel);
929
930 g_object_unref(channel);
931
932 g_object_unref(audio);
933
934 g_object_unref(output_soundcard);
935 g_object_unref(input_soundcard);
936
937 if(start_input != NULL){
938 g_object_unref(start_input);
939 }
940
941 if(input != NULL){
942 g_object_unref(input);
943 }
944 }
945
946 /**
947 * ags_capture_wave_channel_run_new:
948 * @source: the #AgsChannel
949 *
950 * Create a new instance of #AgsCaptureWaveChannelRun
951 *
952 * Returns: the new #AgsCaptureWaveChannelRun
953 *
954 * Since: 3.0.0
955 */
956 AgsCaptureWaveChannelRun*
ags_capture_wave_channel_run_new(AgsChannel * source)957 ags_capture_wave_channel_run_new(AgsChannel *source)
958 {
959 AgsCaptureWaveChannelRun *capture_wave_channel_run;
960
961 capture_wave_channel_run = (AgsCaptureWaveChannelRun *) g_object_new(AGS_TYPE_CAPTURE_WAVE_CHANNEL_RUN,
962 "source", source,
963 NULL);
964
965 return(capture_wave_channel_run);
966 }
967