1 /* GSequencer - Advanced GTK Sequencer
2 * Copyright (C) 2005-2019 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_analyse_channel_run.h>
21
22 #include <ags/audio/ags_audio.h>
23 #include <ags/audio/ags_recycling.h>
24 #include <ags/audio/ags_recall_id.h>
25 #include <ags/audio/ags_audio_buffer_util.h>
26
27 #include <ags/audio/recall/ags_analyse_channel.h>
28 #include <ags/audio/recall/ags_analyse_recycling.h>
29
30 void ags_analyse_channel_run_class_init(AgsAnalyseChannelRunClass *analyse_channel_run);
31 void ags_analyse_channel_run_init(AgsAnalyseChannelRun *analyse_channel_run);
32 void ags_analyse_channel_run_finalize(GObject *gobject);
33
34 void ags_analyse_channel_run_run_pre(AgsRecall *recall);
35
36 /**
37 * SECTION:ags_analyse_channel_run
38 * @short_description: analyse channel
39 * @title: AgsAnalyseChannelRun
40 * @section_id:
41 * @include: ags/audio/recall/ags_analyse_channel_run.h
42 *
43 * The #AgsAnalyseChannelRun class analyses the channel.
44 */
45
46 static gpointer ags_analyse_channel_run_parent_class = NULL;
47
48 GType
ags_analyse_channel_run_get_type()49 ags_analyse_channel_run_get_type()
50 {
51 static volatile gsize g_define_type_id__volatile = 0;
52
53 if(g_once_init_enter (&g_define_type_id__volatile)){
54 GType ags_type_analyse_channel_run = 0;
55
56 static const GTypeInfo ags_analyse_channel_run_info = {
57 sizeof (AgsAnalyseChannelRunClass),
58 NULL, /* base_init */
59 NULL, /* base_finalize */
60 (GClassInitFunc) ags_analyse_channel_run_class_init,
61 NULL, /* class_finalize */
62 NULL, /* class_data */
63 sizeof (AgsAnalyseChannelRun),
64 0, /* n_preallocs */
65 (GInstanceInitFunc) ags_analyse_channel_run_init,
66 };
67
68 ags_type_analyse_channel_run = g_type_register_static(AGS_TYPE_RECALL_CHANNEL_RUN,
69 "AgsAnalyseChannelRun",
70 &ags_analyse_channel_run_info,
71 0);
72
73 g_once_init_leave(&g_define_type_id__volatile, ags_type_analyse_channel_run);
74 }
75
76 return g_define_type_id__volatile;
77 }
78
79 void
ags_analyse_channel_run_class_init(AgsAnalyseChannelRunClass * analyse_channel_run)80 ags_analyse_channel_run_class_init(AgsAnalyseChannelRunClass *analyse_channel_run)
81 {
82 GObjectClass *gobject;
83 AgsRecallClass *recall;
84
85 ags_analyse_channel_run_parent_class = g_type_class_peek_parent(analyse_channel_run);
86
87 /* GObjectClass */
88 gobject = (GObjectClass *) analyse_channel_run;
89
90 gobject->finalize = ags_analyse_channel_run_finalize;
91
92 /* AgsRecallClass */
93 recall = (AgsRecallClass *) analyse_channel_run;
94
95 recall->run_pre = ags_analyse_channel_run_run_pre;
96 }
97
98 void
ags_analyse_channel_run_init(AgsAnalyseChannelRun * analyse_channel_run)99 ags_analyse_channel_run_init(AgsAnalyseChannelRun *analyse_channel_run)
100 {
101 ags_recall_set_ability_flags((AgsRecall *) analyse_channel_run, (AGS_SOUND_ABILITY_PLAYBACK |
102 AGS_SOUND_ABILITY_SEQUENCER |
103 AGS_SOUND_ABILITY_NOTATION |
104 AGS_SOUND_ABILITY_WAVE |
105 AGS_SOUND_ABILITY_MIDI));
106
107 AGS_RECALL(analyse_channel_run)->name = "ags-analyse";
108 AGS_RECALL(analyse_channel_run)->version = AGS_RECALL_DEFAULT_VERSION;
109 AGS_RECALL(analyse_channel_run)->build_id = AGS_RECALL_DEFAULT_BUILD_ID;
110 AGS_RECALL(analyse_channel_run)->xml_type = "ags-analyse-channel-run";
111 AGS_RECALL(analyse_channel_run)->port = NULL;
112
113 AGS_RECALL(analyse_channel_run)->child_type = AGS_TYPE_ANALYSE_RECYCLING;
114 }
115
116 void
ags_analyse_channel_run_finalize(GObject * gobject)117 ags_analyse_channel_run_finalize(GObject *gobject)
118 {
119 /* call parent */
120 G_OBJECT_CLASS(ags_analyse_channel_run_parent_class)->finalize(gobject);
121 }
122
123 void
ags_analyse_channel_run_run_pre(AgsRecall * recall)124 ags_analyse_channel_run_run_pre(AgsRecall *recall)
125 {
126 AgsPort *buffer_computed;
127
128 AgsAnalyseChannel *analyse_channel;
129 AgsAnalyseChannelRun *analyse_channel_run;
130
131 guint cache_buffer_size;
132 guint cache_format;
133 gboolean current_buffer_computed;
134
135 GValue value = {0,};
136
137 void (*parent_class_run_pre)(AgsRecall *recall);
138
139 GRecMutex *recall_mutex;
140 GRecMutex *buffer_mutex;
141
142 analyse_channel_run = AGS_ANALYSE_CHANNEL_RUN(recall);
143
144 g_object_get(recall,
145 "recall-channel", &analyse_channel,
146 NULL);
147
148 /* get parent class */
149 parent_class_run_pre = AGS_RECALL_CLASS(ags_analyse_channel_run_parent_class)->run_pre;
150
151 /* get mutex and buffer mutex */
152 recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(recall);
153 buffer_mutex = AGS_ANALYSE_CHANNEL_GET_BUFFER_MUTEX(analyse_channel);
154
155 /* call parent */
156 parent_class_run_pre(recall);
157
158 /* get some fields */
159 g_object_get(analyse_channel,
160 "buffer-computed", &buffer_computed,
161 "cache-buffer-size", &cache_buffer_size,
162 "cache-format", &cache_format,
163 NULL);
164
165 /* calculate of previous run */
166 g_value_init(&value,
167 G_TYPE_BOOLEAN);
168
169 ags_port_safe_read(analyse_channel->buffer_computed,
170 &value);
171
172 current_buffer_computed = g_value_get_boolean(&value);
173
174 if(!current_buffer_computed){
175 /* set buffer-computed port to TRUE */
176 g_value_reset(&value);
177 g_value_set_boolean(&value,
178 TRUE);
179
180 ags_port_safe_write(buffer_computed,
181 &value);
182 }
183
184 g_value_unset(&value);
185
186 /* lock free - buffer-computed reset by cyclic-task AgsResetAnalyse */
187 if(!current_buffer_computed){
188 /* retrieve analyse */
189 ags_analyse_channel_retrieve_frequency_and_magnitude(analyse_channel);
190
191 /* clear buffer */
192 g_rec_mutex_lock(buffer_mutex);
193
194 ags_audio_buffer_util_clear_buffer(analyse_channel->in, 1,
195 cache_buffer_size, cache_format);
196
197 g_rec_mutex_unlock(buffer_mutex);
198 }
199
200 g_object_unref(analyse_channel);
201 }
202
203 /**
204 * ags_analyse_channel_run_new:
205 * @source: the source #AgsChannel
206 *
207 * Create a new instance of #AgsAnalyseChannelRun
208 *
209 * Returns: the new #AgsAnalyseChannelRun
210 *
211 * Since: 3.0.0
212 */
213 AgsAnalyseChannelRun*
ags_analyse_channel_run_new(AgsChannel * source)214 ags_analyse_channel_run_new(AgsChannel *source)
215 {
216 AgsAnalyseChannelRun *analyse_channel_run;
217
218 analyse_channel_run = (AgsAnalyseChannelRun *) g_object_new(AGS_TYPE_ANALYSE_CHANNEL_RUN,
219 "source", source,
220 NULL);
221
222 return(analyse_channel_run);
223 }
224