"Fossies" - the Fresh Open Source Software Archive 
Member "gst-plugins-good-1.20.3/gst/audiofx/audioinvert.c" (15 Jun 2022, 7837 Bytes) of package /linux/misc/gst-plugins-good-1.20.3.tar.xz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "audioinvert.c" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
1.18.6_vs_1.20.0.
1 /*
2 * GStreamer
3 * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
4 * Copyright (C) 2006 Stefan Kost <ensonic@users.sf.net>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library 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 GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22 /**
23 * SECTION:element-audioinvert
24 * @title: audioinvert
25 *
26 * Swaps upper and lower half of audio samples. Mixing an inverted sample on top of
27 * the original with a slight delay can produce effects that sound like resonance.
28 * Creating a stereo sample from a mono source, with one channel inverted produces wide-stereo sounds.
29 *
30 * ## Example launch line
31 * |[
32 * gst-launch-1.0 audiotestsrc wave=saw ! audioinvert degree=0.4 ! alsasink
33 * gst-launch-1.0 filesrc location="melo1.ogg" ! oggdemux ! vorbisdec ! audioconvert ! audioinvert degree=0.4 ! alsasink
34 * gst-launch-1.0 audiotestsrc wave=saw ! audioconvert ! audioinvert degree=0.4 ! audioconvert ! alsasink
35 * ]|
36 *
37 */
38
39 #ifdef HAVE_CONFIG_H
40 #include "config.h"
41 #endif
42
43 #include <gst/gst.h>
44 #include <gst/base/gstbasetransform.h>
45 #include <gst/audio/audio.h>
46 #include <gst/audio/gstaudiofilter.h>
47
48 #include "audioinvert.h"
49
50 #define GST_CAT_DEFAULT gst_audio_invert_debug
51 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
52
53 /* Filter signals and args */
54 enum
55 {
56 /* FILL ME */
57 LAST_SIGNAL
58 };
59
60 enum
61 {
62 PROP_0,
63 PROP_DEGREE
64 };
65
66 #define ALLOWED_CAPS \
67 "audio/x-raw," \
68 " format=(string) {"GST_AUDIO_NE(S16)","GST_AUDIO_NE(F32)"}," \
69 " rate=(int)[1,MAX]," \
70 " channels=(int)[1,MAX]," \
71 " layout=(string) {interleaved, non-interleaved}"
72
73 G_DEFINE_TYPE (GstAudioInvert, gst_audio_invert, GST_TYPE_AUDIO_FILTER);
74 GST_ELEMENT_REGISTER_DEFINE (audioinvert, "audioinvert",
75 GST_RANK_NONE, GST_TYPE_AUDIO_INVERT);
76
77 static void gst_audio_invert_set_property (GObject * object, guint prop_id,
78 const GValue * value, GParamSpec * pspec);
79 static void gst_audio_invert_get_property (GObject * object, guint prop_id,
80 GValue * value, GParamSpec * pspec);
81
82 static gboolean gst_audio_invert_setup (GstAudioFilter * filter,
83 const GstAudioInfo * info);
84 static GstFlowReturn gst_audio_invert_transform_ip (GstBaseTransform * base,
85 GstBuffer * buf);
86
87 static void gst_audio_invert_transform_int (GstAudioInvert * filter,
88 gint16 * data, guint num_samples);
89 static void gst_audio_invert_transform_float (GstAudioInvert * filter,
90 gfloat * data, guint num_samples);
91
92 /* GObject vmethod implementations */
93
94 static void
95 gst_audio_invert_class_init (GstAudioInvertClass * klass)
96 {
97 GObjectClass *gobject_class;
98 GstElementClass *gstelement_class;
99 GstCaps *caps;
100
101 GST_DEBUG_CATEGORY_INIT (gst_audio_invert_debug, "audioinvert", 0,
102 "audioinvert element");
103
104 gobject_class = (GObjectClass *) klass;
105 gstelement_class = (GstElementClass *) klass;
106
107 gobject_class->set_property = gst_audio_invert_set_property;
108 gobject_class->get_property = gst_audio_invert_get_property;
109
110 g_object_class_install_property (gobject_class, PROP_DEGREE,
111 g_param_spec_float ("degree", "Degree",
112 "Degree of inversion", 0.0, 1.0,
113 0.0,
114 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
115
116 gst_element_class_set_static_metadata (gstelement_class, "Audio inversion",
117 "Filter/Effect/Audio",
118 "Swaps upper and lower half of audio samples",
119 "Sebastian Dröge <slomo@circular-chaos.org>");
120
121 caps = gst_caps_from_string (ALLOWED_CAPS);
122 gst_audio_filter_class_add_pad_templates (GST_AUDIO_FILTER_CLASS (klass),
123 caps);
124 gst_caps_unref (caps);
125
126 GST_BASE_TRANSFORM_CLASS (klass)->transform_ip =
127 GST_DEBUG_FUNCPTR (gst_audio_invert_transform_ip);
128 GST_BASE_TRANSFORM_CLASS (klass)->transform_ip_on_passthrough = FALSE;
129
130 GST_AUDIO_FILTER_CLASS (klass)->setup =
131 GST_DEBUG_FUNCPTR (gst_audio_invert_setup);
132 }
133
134 static void
135 gst_audio_invert_init (GstAudioInvert * filter)
136 {
137 filter->degree = 0.0;
138 gst_base_transform_set_in_place (GST_BASE_TRANSFORM (filter), TRUE);
139 gst_base_transform_set_gap_aware (GST_BASE_TRANSFORM (filter), TRUE);
140 }
141
142 static void
143 gst_audio_invert_set_property (GObject * object, guint prop_id,
144 const GValue * value, GParamSpec * pspec)
145 {
146 GstAudioInvert *filter = GST_AUDIO_INVERT (object);
147
148 switch (prop_id) {
149 case PROP_DEGREE:
150 filter->degree = g_value_get_float (value);
151 gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (filter),
152 filter->degree == 0.0);
153 break;
154 default:
155 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
156 break;
157 }
158 }
159
160 static void
161 gst_audio_invert_get_property (GObject * object, guint prop_id,
162 GValue * value, GParamSpec * pspec)
163 {
164 GstAudioInvert *filter = GST_AUDIO_INVERT (object);
165
166 switch (prop_id) {
167 case PROP_DEGREE:
168 g_value_set_float (value, filter->degree);
169 break;
170 default:
171 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
172 break;
173 }
174 }
175
176 /* GstAudioFilter vmethod implementations */
177
178 static gboolean
179 gst_audio_invert_setup (GstAudioFilter * base, const GstAudioInfo * info)
180 {
181 GstAudioInvert *filter = GST_AUDIO_INVERT (base);
182 gboolean ret = TRUE;
183
184 switch (GST_AUDIO_INFO_FORMAT (info)) {
185 case GST_AUDIO_FORMAT_S16:
186 filter->process = (GstAudioInvertProcessFunc)
187 gst_audio_invert_transform_int;
188 break;
189 case GST_AUDIO_FORMAT_F32:
190 filter->process = (GstAudioInvertProcessFunc)
191 gst_audio_invert_transform_float;
192 break;
193 default:
194 ret = FALSE;
195 break;
196 }
197 return ret;
198 }
199
200 static void
201 gst_audio_invert_transform_int (GstAudioInvert * filter,
202 gint16 * data, guint num_samples)
203 {
204 gint i;
205 gfloat dry = 1.0 - filter->degree;
206 glong val;
207
208 for (i = 0; i < num_samples; i++) {
209 val = (*data) * dry + (-1 - (*data)) * filter->degree;
210 *data++ = (gint16) CLAMP (val, G_MININT16, G_MAXINT16);
211 }
212 }
213
214 static void
215 gst_audio_invert_transform_float (GstAudioInvert * filter,
216 gfloat * data, guint num_samples)
217 {
218 gint i;
219 gfloat dry = 1.0 - filter->degree;
220 glong val;
221
222 for (i = 0; i < num_samples; i++) {
223 val = (*data) * dry - (*data) * filter->degree;
224 *data++ = val;
225 }
226 }
227
228 /* GstBaseTransform vmethod implementations */
229 static GstFlowReturn
230 gst_audio_invert_transform_ip (GstBaseTransform * base, GstBuffer * buf)
231 {
232 GstAudioInvert *filter = GST_AUDIO_INVERT (base);
233 guint num_samples;
234 GstClockTime timestamp, stream_time;
235 GstMapInfo map;
236
237 timestamp = GST_BUFFER_TIMESTAMP (buf);
238 stream_time =
239 gst_segment_to_stream_time (&base->segment, GST_FORMAT_TIME, timestamp);
240
241 GST_DEBUG_OBJECT (filter, "sync to %" GST_TIME_FORMAT,
242 GST_TIME_ARGS (timestamp));
243
244 if (GST_CLOCK_TIME_IS_VALID (stream_time))
245 gst_object_sync_values (GST_OBJECT (filter), stream_time);
246
247 if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_GAP)))
248 return GST_FLOW_OK;
249
250 gst_buffer_map (buf, &map, GST_MAP_READWRITE);
251 num_samples = map.size / GST_AUDIO_FILTER_BPS (filter);
252
253 filter->process (filter, map.data, num_samples);
254
255 gst_buffer_unmap (buf, &map);
256
257 return GST_FLOW_OK;
258 }