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_peak_audio_signal.h>
21 
22 #include <ags/audio/recall/ags_peak_channel.h>
23 #include <ags/audio/recall/ags_peak_channel_run.h>
24 #include <ags/audio/recall/ags_peak_recycling.h>
25 
26 #include <ags/i18n.h>
27 
28 void ags_peak_audio_signal_class_init(AgsPeakAudioSignalClass *peak_audio_signal);
29 void ags_peak_audio_signal_init(AgsPeakAudioSignal *peak_audio_signal);
30 void ags_peak_audio_signal_set_property(GObject *gobject,
31 					guint prop_id,
32 					const GValue *value,
33 					GParamSpec *param_spec);
34 void ags_peak_audio_signal_get_property(GObject *gobject,
35 					guint prop_id,
36 					GValue *value,
37 					GParamSpec *param_spec);
38 void ags_peak_audio_signal_finalize(GObject *gobject);
39 
40 void ags_peak_audio_signal_run_inter(AgsRecall *recall);
41 AgsRecall* ags_peak_audio_signal_duplicate(AgsRecall *recall,
42 					   AgsRecallID *recall_id,
43 					   guint *n_params, GParameter *parameter);
44 
45 /**
46  * SECTION:ags_peak_audio_signal
47  * @short_description: peaks audio signal
48  * @title: AgsPeakAudioSignal
49  * @section_id:
50  * @include: ags/audio/recall/ags_peak_audio_signal.h
51  *
52  * The #AgsPeakAudioSignal class peaks the audio signal.
53  */
54 
55 enum{
56   PROP_0,
57   PROP_PEAK,
58 };
59 
60 static gpointer ags_peak_audio_signal_parent_class = NULL;
61 
62 GType
ags_peak_audio_signal_get_type()63 ags_peak_audio_signal_get_type()
64 {
65   static volatile gsize g_define_type_id__volatile = 0;
66 
67   if(g_once_init_enter (&g_define_type_id__volatile)){
68     GType ags_type_peak_audio_signal = 0;
69 
70     static const GTypeInfo ags_peak_audio_signal_info = {
71       sizeof (AgsPeakAudioSignalClass),
72       NULL, /* base_init */
73       NULL, /* base_finalize */
74       (GClassInitFunc) ags_peak_audio_signal_class_init,
75       NULL, /* class_finalize */
76       NULL, /* class_data */
77       sizeof (AgsPeakAudioSignal),
78       0,    /* n_preallocs */
79       (GInstanceInitFunc) ags_peak_audio_signal_init,
80     };
81 
82     ags_type_peak_audio_signal = g_type_register_static(AGS_TYPE_RECALL_AUDIO_SIGNAL,
83 							"AgsPeakAudioSignal",
84 							&ags_peak_audio_signal_info,
85 							0);
86 
87     g_once_init_leave(&g_define_type_id__volatile, ags_type_peak_audio_signal);
88   }
89 
90   return g_define_type_id__volatile;
91 }
92 
93 void
ags_peak_audio_signal_class_init(AgsPeakAudioSignalClass * peak_audio_signal)94 ags_peak_audio_signal_class_init(AgsPeakAudioSignalClass *peak_audio_signal)
95 {
96   GObjectClass *gobject;
97   AgsRecallClass *recall;
98 
99   GParamSpec *param_spec;
100 
101   ags_peak_audio_signal_parent_class = g_type_class_peek_parent(peak_audio_signal);
102 
103   /* GObjectClass */
104   gobject = (GObjectClass *) peak_audio_signal;
105 
106   gobject->set_property = ags_peak_audio_signal_set_property;
107   gobject->get_property = ags_peak_audio_signal_get_property;
108 
109   gobject->finalize = ags_peak_audio_signal_finalize;
110 
111   /* properties */
112   /**
113    * AgsPeakAudioSignal:peak:
114    *
115    * The peak.
116    *
117    * Since: 3.0.0
118    */
119   param_spec = g_param_spec_double("peak",
120 				   i18n_pspec("resulting peak"),
121 				   i18n_pspec("The peak resulted"),
122 				   0.0,
123 				   1.0,
124 				   0.0,
125 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
126   g_object_class_install_property(gobject,
127 				  PROP_PEAK,
128 				  param_spec);
129 
130   /* AgsRecallClass */
131   recall = (AgsRecallClass *) peak_audio_signal;
132 
133   recall->run_inter = ags_peak_audio_signal_run_inter;
134 }
135 
136 void
ags_peak_audio_signal_init(AgsPeakAudioSignal * peak_audio_signal)137 ags_peak_audio_signal_init(AgsPeakAudioSignal *peak_audio_signal)
138 {
139   AGS_RECALL(peak_audio_signal)->child_type = G_TYPE_NONE;
140 
141   peak_audio_signal->peak = 0.0;
142 }
143 
144 void
ags_peak_audio_signal_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)145 ags_peak_audio_signal_set_property(GObject *gobject,
146 				   guint prop_id,
147 				   const GValue *value,
148 				   GParamSpec *param_spec)
149 {
150   AgsPeakAudioSignal *peak_audio_signal;
151 
152   GRecMutex *recall_mutex;
153 
154   peak_audio_signal = AGS_PEAK_AUDIO_SIGNAL(gobject);
155 
156   /* get recall mutex */
157   recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(peak_audio_signal);
158 
159   switch(prop_id){
160   case PROP_PEAK:
161     {
162       gdouble peak;
163 
164       peak = g_value_get_double(value);
165 
166       g_rec_mutex_lock(recall_mutex);
167 
168       peak_audio_signal->peak = peak;
169 
170       g_rec_mutex_unlock(recall_mutex);
171     }
172     break;
173   default:
174     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
175     break;
176   }
177 }
178 
179 void
ags_peak_audio_signal_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)180 ags_peak_audio_signal_get_property(GObject *gobject,
181 				   guint prop_id,
182 				   GValue *value,
183 				   GParamSpec *param_spec)
184 {
185   AgsPeakAudioSignal *peak_audio_signal;
186 
187   GRecMutex *recall_mutex;
188 
189   peak_audio_signal = AGS_PEAK_AUDIO_SIGNAL(gobject);
190 
191   /* get recall mutex */
192   recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(peak_audio_signal);
193 
194   switch(prop_id){
195   case PROP_PEAK:
196     {
197       g_rec_mutex_lock(recall_mutex);
198 
199       g_value_set_double(value, peak_audio_signal->peak);
200 
201       g_rec_mutex_unlock(recall_mutex);
202     }
203     break;
204   default:
205     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
206     break;
207   }
208 }
209 
210 void
ags_peak_audio_signal_finalize(GObject * gobject)211 ags_peak_audio_signal_finalize(GObject *gobject)
212 {
213   /* call parent */
214   G_OBJECT_CLASS(ags_peak_audio_signal_parent_class)->finalize(gobject);
215 }
216 
217 void
ags_peak_audio_signal_run_inter(AgsRecall * recall)218 ags_peak_audio_signal_run_inter(AgsRecall *recall)
219 {
220   AgsAudioSignal *source;
221   AgsPeakChannel *peak_channel;
222   AgsPeakChannelRun *peak_channel_run;
223   AgsPeakRecycling *peak_recycling;
224   AgsPeakAudioSignal *peak_audio_signal;
225 
226   guint samplerate;
227   guint buffer_size;
228   guint format;
229 
230   void (*parent_class_run_inter)(AgsRecall *recall);
231 
232   peak_audio_signal = (AgsPeakAudioSignal *) recall;
233 
234   /* get parent class */
235   parent_class_run_inter = AGS_RECALL_CLASS(ags_peak_audio_signal_parent_class)->run_inter;
236 
237   /* call parent */
238   parent_class_run_inter(recall);
239 
240   /* get some fields */
241   g_object_get(peak_audio_signal,
242 	       "source", &source,
243 	       NULL);
244 
245   if(source->stream_current != NULL){
246     g_object_get(peak_audio_signal,
247 		 "parent", &peak_recycling,
248 		 NULL);
249 
250     g_object_get(peak_recycling,
251 		 "parent", &peak_channel_run,
252 		 NULL);
253 
254     g_object_get(peak_channel_run,
255 		 "recall-channel", &peak_channel,
256 		 NULL);
257 
258     g_object_get(source,
259 		 "samplerate", &samplerate,
260 		 "buffer-size", &buffer_size,
261 		 "format", &format,
262 		 NULL);
263 
264     ags_peak_channel_buffer_add(peak_channel,
265 				source->stream_current->data,
266 				samplerate,
267 				buffer_size,
268 				format);
269 
270     g_object_unref(peak_recycling);
271 
272     g_object_unref(peak_channel_run);
273     g_object_unref(peak_channel);
274   }else{
275     ags_recall_done(recall);
276   }
277 
278   g_object_unref(source);
279 }
280 
281 /**
282  * ags_peak_audio_signal_new:
283  * @source: the #AgsAudioSignal
284  *
285  * Create a new instance of #AgsPeakAudioSignal
286  *
287  * Returns: the new #AgsPeakAudioSignal
288  *
289  * Since: 3.0.0
290  */
291 AgsPeakAudioSignal*
ags_peak_audio_signal_new(AgsAudioSignal * source)292 ags_peak_audio_signal_new(AgsAudioSignal *source)
293 {
294   AgsPeakAudioSignal *peak_audio_signal;
295 
296   peak_audio_signal = (AgsPeakAudioSignal *) g_object_new(AGS_TYPE_PEAK_AUDIO_SIGNAL,
297 							  "source", source,
298 							  NULL);
299 
300   return(peak_audio_signal);
301 }
302