d59a96f3d8a363a6efd9b58d735af32b686d2685
[platform/upstream/gstreamer.git] / tests / check / elements / volume.c
1 /* GStreamer
2  *
3  * unit test for volume
4  *
5  * Copyright (C) <2005> Thomas Vander Stichele <thomas at apestaart dot org>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #include <unistd.h>
24
25 #include <gst/base/gstbasetransform.h>
26 #include <gst/check/gstcheck.h>
27 #include <gst/controller/gstcontroller.h>
28 #include <gst/interfaces/streamvolume.h>
29
30 /* For ease of programming we use globals to keep refs for our floating
31  * src and sink pads we create; otherwise we always have to do get_pad,
32  * get_peer, and then remove references in every test function */
33 static GstPad *mysrcpad, *mysinkpad;
34
35
36 #define VOLUME_CAPS_TEMPLATE_STRING     \
37     "audio/x-raw-int, "                 \
38     "channels = (int) [ 1, MAX ], "     \
39     "rate = (int) [ 1,  MAX ], "        \
40     "endianness = (int) BYTE_ORDER, "   \
41     "width = (int) { 8, 16, 24, 32 }, " \
42     "depth = (int) { 8, 16, 24, 32 }, " \
43     "signed = (bool) TRUE; "            \
44     "audio/x-raw-float, "               \
45     "channels = (int) [ 1, MAX ], "     \
46     "rate = (int) [ 1,  MAX ], "        \
47     "endianness = (int) BYTE_ORDER, "   \
48     "width = (int) { 32, 64 }"          \
49
50 #define VOLUME_CAPS_STRING_S8           \
51     "audio/x-raw-int, "                 \
52     "channels = (int) 1, "              \
53     "rate = (int) 44100, "              \
54     "endianness = (int) BYTE_ORDER, "   \
55     "width = (int) 8, "                 \
56     "depth = (int) 8, "                 \
57     "signed = (bool) TRUE"
58
59 #define VOLUME_CAPS_STRING_S16          \
60     "audio/x-raw-int, "                 \
61     "channels = (int) 1, "              \
62     "rate = (int) 44100, "              \
63     "endianness = (int) BYTE_ORDER, "   \
64     "width = (int) 16, "                \
65     "depth = (int) 16, "                \
66     "signed = (bool) TRUE"
67
68 #define VOLUME_CAPS_STRING_S24          \
69     "audio/x-raw-int, "                 \
70     "channels = (int) 1, "              \
71     "rate = (int) 44100, "              \
72     "endianness = (int) BYTE_ORDER, "   \
73     "width = (int) 24, "                \
74     "depth = (int) 24, "                \
75     "signed = (bool) TRUE"
76
77 #define VOLUME_CAPS_STRING_S32          \
78     "audio/x-raw-int, "                 \
79     "channels = (int) 1, "              \
80     "rate = (int) 44100, "              \
81     "endianness = (int) BYTE_ORDER, "   \
82     "width = (int) 32, "                \
83     "depth = (int) 32, "                \
84     "signed = (bool) TRUE"
85
86 #define VOLUME_CAPS_STRING_F32          \
87     "audio/x-raw-float, "               \
88     "channels = (int) 1, "              \
89     "rate = (int) 44100, "              \
90     "endianness = (int) BYTE_ORDER, "   \
91     "width = (int) 32"
92
93 #define VOLUME_CAPS_STRING_F64          \
94     "audio/x-raw-float, "               \
95     "channels = (int) 1, "              \
96     "rate = (int) 44100, "              \
97     "endianness = (int) BYTE_ORDER, "   \
98     "width = (int) 64"
99
100 #define VOLUME_WRONG_CAPS_STRING        \
101     "audio/x-raw-int, "                 \
102     "channels = (int) 1, "              \
103     "rate = (int) 44100, "              \
104     "endianness = (int) BYTE_ORDER, "   \
105     "width = (int) 16, "                \
106     "depth = (int) 16, "                \
107     "signed = (bool) FALSE"
108
109
110 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
111     GST_PAD_SINK,
112     GST_PAD_ALWAYS,
113     GST_STATIC_CAPS (VOLUME_CAPS_TEMPLATE_STRING)
114     );
115 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
116     GST_PAD_SRC,
117     GST_PAD_ALWAYS,
118     GST_STATIC_CAPS (VOLUME_CAPS_TEMPLATE_STRING)
119     );
120
121 static GstElement *
122 setup_volume (void)
123 {
124   GstElement *volume;
125
126   GST_DEBUG ("setup_volume");
127   volume = gst_check_setup_element ("volume");
128   mysrcpad = gst_check_setup_src_pad (volume, &srctemplate, NULL);
129   mysinkpad = gst_check_setup_sink_pad (volume, &sinktemplate, NULL);
130   gst_pad_set_active (mysrcpad, TRUE);
131   gst_pad_set_active (mysinkpad, TRUE);
132
133   return volume;
134 }
135
136 static void
137 cleanup_volume (GstElement * volume)
138 {
139   GST_DEBUG ("cleanup_volume");
140
141   g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL);
142   g_list_free (buffers);
143   buffers = NULL;
144
145   gst_pad_set_active (mysrcpad, FALSE);
146   gst_pad_set_active (mysinkpad, FALSE);
147   gst_check_teardown_src_pad (volume);
148   gst_check_teardown_sink_pad (volume);
149   gst_check_teardown_element (volume);
150 }
151
152 GST_START_TEST (test_get_set)
153 {
154   GstElement *volume = gst_element_factory_make ("volume", NULL);
155   gdouble val;
156
157   fail_unless (volume != NULL);
158   g_object_get (G_OBJECT (volume), "volume", &val, NULL);
159   fail_unless (val == 1.0);
160   fail_unless (val == gst_stream_volume_get_volume (GST_STREAM_VOLUME (volume),
161           GST_STREAM_VOLUME_FORMAT_LINEAR));
162
163   g_object_set (G_OBJECT (volume), "volume", 0.5, NULL);
164   g_object_get (G_OBJECT (volume), "volume", &val, NULL);
165   fail_unless (val == 0.5);
166   fail_unless (val == gst_stream_volume_get_volume (GST_STREAM_VOLUME (volume),
167           GST_STREAM_VOLUME_FORMAT_LINEAR));
168
169   gst_stream_volume_set_volume (GST_STREAM_VOLUME (volume),
170       GST_STREAM_VOLUME_FORMAT_LINEAR, 1.0);
171   g_object_get (G_OBJECT (volume), "volume", &val, NULL);
172   fail_unless (val == 1.0);
173   fail_unless (val == gst_stream_volume_get_volume (GST_STREAM_VOLUME (volume),
174           GST_STREAM_VOLUME_FORMAT_LINEAR));
175
176   gst_object_unref (volume);
177 }
178
179 GST_END_TEST;
180
181 GST_START_TEST (test_unity_s8)
182 {
183   GstElement *volume;
184   GstBuffer *inbuffer, *outbuffer;
185   GstCaps *caps;
186   gint8 in[2] = { 64, -16 };
187   gint8 *res;
188
189   volume = setup_volume ();
190   fail_unless (gst_element_set_state (volume,
191           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
192       "could not set to playing");
193
194   inbuffer = gst_buffer_new_and_alloc (2);
195   memcpy (GST_BUFFER_DATA (inbuffer), in, 2);
196   caps = gst_caps_from_string (VOLUME_CAPS_STRING_S8);
197   gst_buffer_set_caps (inbuffer, caps);
198   gst_caps_unref (caps);
199   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
200
201   /* pushing gives away my reference ... */
202   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
203   /* ... but it ends up being collected on the global buffer list */
204   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
205   fail_unless_equals_int (g_list_length (buffers), 1);
206   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
207   fail_unless (inbuffer == outbuffer);
208   res = (gint8 *) GST_BUFFER_DATA (outbuffer);
209   GST_INFO ("expected %+5d %+5d  real %+5d %+5d", in[0], in[1], res[0], res[1]);
210   fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 2) == 0);
211
212   /* cleanup */
213   cleanup_volume (volume);
214 }
215
216 GST_END_TEST;
217
218 GST_START_TEST (test_half_s8)
219 {
220   GstElement *volume;
221   GstBuffer *inbuffer;
222   GstBuffer *outbuffer;
223   GstCaps *caps;
224   gint8 in[2] = { 64, -16 };
225   gint8 out[2] = { 32, -8 };
226   gint8 *res;
227
228   volume = setup_volume ();
229   g_object_set (G_OBJECT (volume), "volume", 0.5, NULL);
230   fail_unless (gst_element_set_state (volume,
231           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
232       "could not set to playing");
233
234   inbuffer = gst_buffer_new_and_alloc (2);
235   memcpy (GST_BUFFER_DATA (inbuffer), in, 2);
236   fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 2) == 0);
237   caps = gst_caps_from_string (VOLUME_CAPS_STRING_S8);
238   gst_buffer_set_caps (inbuffer, caps);
239   gst_caps_unref (caps);
240   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
241   /* FIXME: reffing the inbuffer should make the transformation not be
242    * inplace
243    gst_buffer_ref (inbuffer);
244    */
245
246   /* pushing gives away my reference ... */
247   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
248   /* ... but it ends up being modified inplace and
249    * collected on the global buffer list */
250   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
251   fail_unless_equals_int (g_list_length (buffers), 1);
252   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
253   fail_unless (inbuffer == outbuffer);
254   res = (gint8 *) GST_BUFFER_DATA (outbuffer);
255   GST_INFO ("expected %+5d %+5d  real %+5d %+5d", out[0], out[1], res[0],
256       res[1]);
257   fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), out, 2) == 0);
258
259   /* cleanup */
260   cleanup_volume (volume);
261 }
262
263 GST_END_TEST;
264
265 GST_START_TEST (test_double_s8)
266 {
267   GstElement *volume;
268   GstBuffer *inbuffer;
269   GstBuffer *outbuffer;
270   GstCaps *caps;
271   gint8 in[2] = { 64, -16 };
272   gint8 out[2] = { 127, -32 };  /* notice the clamped sample */
273   gint8 *res;
274
275   volume = setup_volume ();
276   g_object_set (G_OBJECT (volume), "volume", 2.0, NULL);
277   fail_unless (gst_element_set_state (volume,
278           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
279       "could not set to playing");
280
281   inbuffer = gst_buffer_new_and_alloc (2);
282   memcpy (GST_BUFFER_DATA (inbuffer), in, 2);
283   fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 2) == 0);
284   caps = gst_caps_from_string (VOLUME_CAPS_STRING_S8);
285   gst_buffer_set_caps (inbuffer, caps);
286   gst_caps_unref (caps);
287   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
288   /* FIXME: reffing the inbuffer should make the transformation not be
289    * inplace
290    gst_buffer_ref (inbuffer);
291    */
292
293   /* pushing gives away my reference ... */
294   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
295   /* ... but it ends up being modified inplace and
296    * collected on the global buffer list */
297   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
298   fail_unless_equals_int (g_list_length (buffers), 1);
299   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
300   fail_unless (inbuffer == outbuffer);
301   res = (gint8 *) GST_BUFFER_DATA (outbuffer);
302   GST_INFO ("expected %+5d %+5d  real %+5d %+5d", out[0], out[1], res[0],
303       res[1]);
304   fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), out, 2) == 0);
305
306   /* cleanup */
307   cleanup_volume (volume);
308 }
309
310 GST_END_TEST;
311
312 GST_START_TEST (test_mute_s8)
313 {
314   GstElement *volume;
315   GstBuffer *inbuffer;
316   GstBuffer *outbuffer;
317   GstCaps *caps;
318   gint8 in[2] = { 64, -16 };
319   gint8 out[2] = { 0, 0 };
320   gint8 *res;
321
322   volume = setup_volume ();
323   g_object_set (G_OBJECT (volume), "mute", TRUE, NULL);
324   fail_unless (gst_element_set_state (volume,
325           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
326       "could not set to playing");
327
328   inbuffer = gst_buffer_new_and_alloc (2);
329   memcpy (GST_BUFFER_DATA (inbuffer), in, 2);
330   fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 2) == 0);
331   caps = gst_caps_from_string (VOLUME_CAPS_STRING_S8);
332   gst_buffer_set_caps (inbuffer, caps);
333   gst_caps_unref (caps);
334   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
335   /* FIXME: reffing the inbuffer should make the transformation not be
336    * inplace
337    gst_buffer_ref (inbuffer);
338    */
339
340   /* pushing gives away my reference ... */
341   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
342   /* ... but it ends up being modified inplace and
343    * collected on the global buffer list */
344   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
345   fail_unless_equals_int (g_list_length (buffers), 1);
346   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
347   fail_unless (inbuffer == outbuffer);
348   res = (gint8 *) GST_BUFFER_DATA (outbuffer);
349   GST_INFO ("expected %+5d %+5d  real %+5d %+5d", out[0], out[1], res[0],
350       res[1]);
351   fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), out, 2) == 0);
352
353   /* cleanup */
354   cleanup_volume (volume);
355 }
356
357 GST_END_TEST;
358
359 GST_START_TEST (test_unity_s16)
360 {
361   GstElement *volume;
362   GstBuffer *inbuffer, *outbuffer;
363   GstCaps *caps;
364   gint16 in[2] = { 16384, -256 };
365   gint16 *res;
366
367   volume = setup_volume ();
368   fail_unless (gst_element_set_state (volume,
369           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
370       "could not set to playing");
371
372   inbuffer = gst_buffer_new_and_alloc (4);
373   memcpy (GST_BUFFER_DATA (inbuffer), in, 4);
374   caps = gst_caps_from_string (VOLUME_CAPS_STRING_S16);
375   gst_buffer_set_caps (inbuffer, caps);
376   gst_caps_unref (caps);
377   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
378
379   /* pushing gives away my reference ... */
380   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
381   /* ... but it ends up being collected on the global buffer list */
382   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
383   fail_unless_equals_int (g_list_length (buffers), 1);
384   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
385   fail_unless (inbuffer == outbuffer);
386   res = (gint16 *) GST_BUFFER_DATA (outbuffer);
387   GST_INFO ("expected %+5d %+5d  real %+5d %+5d", in[0], in[1], res[0], res[1]);
388   fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 4) == 0);
389
390   /* cleanup */
391   cleanup_volume (volume);
392 }
393
394 GST_END_TEST;
395
396 GST_START_TEST (test_half_s16)
397 {
398   GstElement *volume;
399   GstBuffer *inbuffer;
400   GstBuffer *outbuffer;
401   GstCaps *caps;
402   gint16 in[2] = { 16384, -256 };
403   gint16 out[2] = { 8192, -128 };
404   gint16 *res;
405
406   volume = setup_volume ();
407   g_object_set (G_OBJECT (volume), "volume", 0.5, NULL);
408   fail_unless (gst_element_set_state (volume,
409           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
410       "could not set to playing");
411
412   inbuffer = gst_buffer_new_and_alloc (4);
413   memcpy (GST_BUFFER_DATA (inbuffer), in, 4);
414   fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 4) == 0);
415   caps = gst_caps_from_string (VOLUME_CAPS_STRING_S16);
416   gst_buffer_set_caps (inbuffer, caps);
417   gst_caps_unref (caps);
418   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
419   /* FIXME: reffing the inbuffer should make the transformation not be
420    * inplace
421    gst_buffer_ref (inbuffer);
422    */
423
424   /* pushing gives away my reference ... */
425   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
426   /* ... but it ends up being modified inplace and
427    * collected on the global buffer list */
428   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
429   fail_unless_equals_int (g_list_length (buffers), 1);
430   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
431   fail_unless (inbuffer == outbuffer);
432   res = (gint16 *) GST_BUFFER_DATA (outbuffer);
433   GST_INFO ("expected %+5d %+5d  real %+5d %+5d", out[0], out[1], res[0],
434       res[1]);
435   fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), out, 4) == 0);
436
437   /* cleanup */
438   cleanup_volume (volume);
439 }
440
441 GST_END_TEST;
442
443 GST_START_TEST (test_double_s16)
444 {
445   GstElement *volume;
446   GstBuffer *inbuffer;
447   GstBuffer *outbuffer;
448   GstCaps *caps;
449   gint16 in[2] = { 16384, -256 };
450   gint16 out[2] = { 32767, -512 };      /* notice the clamped sample */
451   gint16 *res;
452
453   volume = setup_volume ();
454   g_object_set (G_OBJECT (volume), "volume", 2.0, NULL);
455   fail_unless (gst_element_set_state (volume,
456           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
457       "could not set to playing");
458
459   inbuffer = gst_buffer_new_and_alloc (4);
460   memcpy (GST_BUFFER_DATA (inbuffer), in, 4);
461   fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 4) == 0);
462   caps = gst_caps_from_string (VOLUME_CAPS_STRING_S16);
463   gst_buffer_set_caps (inbuffer, caps);
464   gst_caps_unref (caps);
465   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
466   /* FIXME: reffing the inbuffer should make the transformation not be
467    * inplace
468    gst_buffer_ref (inbuffer);
469    */
470
471   /* pushing gives away my reference ... */
472   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
473   /* ... but it ends up being modified inplace and
474    * collected on the global buffer list */
475   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
476   fail_unless_equals_int (g_list_length (buffers), 1);
477   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
478   fail_unless (inbuffer == outbuffer);
479   res = (gint16 *) GST_BUFFER_DATA (outbuffer);
480   GST_INFO ("expected %+5d %+5d  real %+5d %+5d", out[0], out[1], res[0],
481       res[1]);
482   fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), out, 4) == 0);
483
484   /* cleanup */
485   cleanup_volume (volume);
486 }
487
488 GST_END_TEST;
489
490
491 GST_START_TEST (test_mute_s16)
492 {
493   GstElement *volume;
494   GstBuffer *inbuffer;
495   GstBuffer *outbuffer;
496   GstCaps *caps;
497   gint16 in[2] = { 16384, -256 };
498   gint16 out[2] = { 0, 0 };
499   gint16 *res;
500
501   volume = setup_volume ();
502   g_object_set (G_OBJECT (volume), "mute", TRUE, NULL);
503   fail_unless (gst_element_set_state (volume,
504           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
505       "could not set to playing");
506
507   inbuffer = gst_buffer_new_and_alloc (4);
508   memcpy (GST_BUFFER_DATA (inbuffer), in, 4);
509   fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 4) == 0);
510   caps = gst_caps_from_string (VOLUME_CAPS_STRING_S16);
511   gst_buffer_set_caps (inbuffer, caps);
512   gst_caps_unref (caps);
513   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
514   /* FIXME: reffing the inbuffer should make the transformation not be
515    * inplace
516    gst_buffer_ref (inbuffer);
517    */
518
519   /* pushing gives away my reference ... */
520   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
521   /* ... but it ends up being modified inplace and
522    * collected on the global buffer list */
523   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
524   fail_unless_equals_int (g_list_length (buffers), 1);
525   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
526   fail_unless (inbuffer == outbuffer);
527   res = (gint16 *) GST_BUFFER_DATA (outbuffer);
528   GST_INFO ("expected %+5d %+5d  real %+5d %+5d", out[0], out[1], res[0],
529       res[1]);
530   fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), out, 4) == 0);
531
532   /* cleanup */
533   cleanup_volume (volume);
534 }
535
536 GST_END_TEST;
537
538 #if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
539 #define get_unaligned_i24(_x) ( (((guint8*)_x)[0]) | ((((guint8*)_x)[1]) << 8) | ((((gint8*)_x)[2]) << 16) )
540 #define write_unaligned_u24(_x,samp) do { (((guint8*)_x)[0]) = samp & 0xFF; (((guint8*)_x)[1]) = (samp >> 8) & 0xFF; (((guint8*)_x)[2]) = (samp >> 16) & 0xFF; } while (0)
541 #else /* BIG ENDIAN */
542 #define get_unaligned_i24(_x) ( (((guint8*)_x)[2]) | ((((guint8*)_x)[1]) << 8) | ((((gint8*)_x)[0]) << 16) )
543 #define write_unaligned_u24(_x,samp) do { (((guint8*)_x)[0]) = (samp >> 16) & 0xFF; (((guint8*)_x)[1]) = (samp >> 8) & 0xFF; (((guint8*)_x)[2]) = samp & 0xFF; } while (0)
544 #endif
545
546 GST_START_TEST (test_unity_s24)
547 {
548   GstElement *volume;
549   GstBuffer *inbuffer, *outbuffer;
550   GstCaps *caps;
551   gint32 in_32[2] = { 4194304, -4096 };
552   guint8 in[6];
553   guint8 *res;
554   gint32 res_32[2];
555
556
557   write_unaligned_u24 (in, in_32[0]);
558   write_unaligned_u24 (in + 3, in_32[1]);
559
560   volume = setup_volume ();
561   fail_unless (gst_element_set_state (volume,
562           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
563       "could not set to playing");
564
565   inbuffer = gst_buffer_new_and_alloc (6);
566   memcpy (GST_BUFFER_DATA (inbuffer), in, 6);
567   caps = gst_caps_from_string (VOLUME_CAPS_STRING_S24);
568   gst_buffer_set_caps (inbuffer, caps);
569   gst_caps_unref (caps);
570   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
571
572   /* pushing gives away my reference ... */
573   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
574   /* ... but it ends up being collected on the global buffer list */
575   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
576   fail_unless_equals_int (g_list_length (buffers), 1);
577   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
578   fail_unless (inbuffer == outbuffer);
579   res = GST_BUFFER_DATA (outbuffer);
580
581   res_32[0] = get_unaligned_i24 (res);
582   res_32[1] = get_unaligned_i24 ((res + 3));
583
584   GST_INFO ("expected %+5d %+5d  real %+5d %+5d", in_32[0], in_32[1], res_32[0],
585       res_32[1]);
586   fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 6) == 0);
587
588   /* cleanup */
589   cleanup_volume (volume);
590 }
591
592 GST_END_TEST;
593
594 GST_START_TEST (test_half_s24)
595 {
596   GstElement *volume;
597   GstBuffer *inbuffer;
598   GstBuffer *outbuffer;
599   GstCaps *caps;
600   gint32 in_32[2] = { 4194304, -4096 };
601   guint8 in[6];
602   guint8 *res;
603   gint32 res_32[2];
604   gint32 out_32[2] = { 2097152, -2048 };
605
606   write_unaligned_u24 (in, in_32[0]);
607   write_unaligned_u24 (in + 3, in_32[1]);
608
609   volume = setup_volume ();
610   g_object_set (G_OBJECT (volume), "volume", 0.5, NULL);
611   fail_unless (gst_element_set_state (volume,
612           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
613       "could not set to playing");
614
615   inbuffer = gst_buffer_new_and_alloc (6);
616   memcpy (GST_BUFFER_DATA (inbuffer), in, 6);
617   fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 6) == 0);
618   caps = gst_caps_from_string (VOLUME_CAPS_STRING_S24);
619   gst_buffer_set_caps (inbuffer, caps);
620   gst_caps_unref (caps);
621   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
622   /* FIXME: reffing the inbuffer should make the transformation not be
623    * inplace
624    gst_buffer_ref (inbuffer);
625    */
626
627   /* pushing gives away my reference ... */
628   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
629   /* ... but it ends up being modified inplace and
630    * collected on the global buffer list */
631   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
632   fail_unless_equals_int (g_list_length (buffers), 1);
633   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
634   fail_unless (inbuffer == outbuffer);
635   res = GST_BUFFER_DATA (outbuffer);
636
637   res_32[0] = get_unaligned_i24 (res);
638   res_32[1] = get_unaligned_i24 ((res + 3));
639
640   GST_INFO ("expected %+5d %+5d  real %+5d %+5d", out_32[0], out_32[1],
641       res_32[0], res_32[1]);
642   fail_unless (memcmp (res_32, out_32, 8) == 0);
643
644   /* cleanup */
645   cleanup_volume (volume);
646 }
647
648 GST_END_TEST;
649
650 GST_START_TEST (test_double_s24)
651 {
652   GstElement *volume;
653   GstBuffer *inbuffer;
654   GstBuffer *outbuffer;
655   GstCaps *caps;
656   gint32 in_32[2] = { 4194304, -4096 };
657   guint8 in[6];
658   guint8 *res;
659   gint32 res_32[2];
660   gint32 out_32[2] = { 8388607, -8192 };        /* notice the clamped sample */
661
662   write_unaligned_u24 (in, in_32[0]);
663   write_unaligned_u24 (in + 3, in_32[1]);
664
665   volume = setup_volume ();
666   g_object_set (G_OBJECT (volume), "volume", 2.0, NULL);
667   fail_unless (gst_element_set_state (volume,
668           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
669       "could not set to playing");
670
671   inbuffer = gst_buffer_new_and_alloc (6);
672   memcpy (GST_BUFFER_DATA (inbuffer), in, 6);
673   fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 6) == 0);
674   caps = gst_caps_from_string (VOLUME_CAPS_STRING_S24);
675   gst_buffer_set_caps (inbuffer, caps);
676   gst_caps_unref (caps);
677   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
678   /* FIXME: reffing the inbuffer should make the transformation not be
679    * inplace
680    gst_buffer_ref (inbuffer);
681    */
682
683   /* pushing gives away my reference ... */
684   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
685   /* ... but it ends up being modified inplace and
686    * collected on the global buffer list */
687   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
688   fail_unless_equals_int (g_list_length (buffers), 1);
689   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
690   fail_unless (inbuffer == outbuffer);
691   res = GST_BUFFER_DATA (outbuffer);
692
693   res_32[0] = get_unaligned_i24 (res);
694   res_32[1] = get_unaligned_i24 ((res + 3));
695
696   GST_INFO ("expected %+5d %+5d  real %+5d %+5d", out_32[0], out_32[1],
697       res_32[0], res_32[1]);
698   fail_unless (memcmp (res_32, out_32, 8) == 0);
699
700   /* cleanup */
701   cleanup_volume (volume);
702 }
703
704 GST_END_TEST;
705
706
707 GST_START_TEST (test_mute_s24)
708 {
709   GstElement *volume;
710   GstBuffer *inbuffer;
711   GstBuffer *outbuffer;
712   GstCaps *caps;
713   gint32 in_32[2] = { 4194304, -4096 };
714   guint8 in[6];
715   guint8 *res;
716   gint32 res_32[2];
717   gint32 out_32[2] = { 0, 0 };  /* notice the clamped sample */
718
719   write_unaligned_u24 (in, in_32[0]);
720   write_unaligned_u24 (in + 3, in_32[1]);
721
722   volume = setup_volume ();
723   g_object_set (G_OBJECT (volume), "mute", TRUE, NULL);
724   fail_unless (gst_element_set_state (volume,
725           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
726       "could not set to playing");
727
728   inbuffer = gst_buffer_new_and_alloc (6);
729   memcpy (GST_BUFFER_DATA (inbuffer), in, 6);
730   fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 6) == 0);
731   caps = gst_caps_from_string (VOLUME_CAPS_STRING_S24);
732   gst_buffer_set_caps (inbuffer, caps);
733   gst_caps_unref (caps);
734   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
735   /* FIXME: reffing the inbuffer should make the transformation not be
736    * inplace
737    gst_buffer_ref (inbuffer);
738    */
739
740   /* pushing gives away my reference ... */
741   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
742   /* ... but it ends up being modified inplace and
743    * collected on the global buffer list */
744   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
745   fail_unless_equals_int (g_list_length (buffers), 1);
746   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
747   fail_unless (inbuffer == outbuffer);
748
749   res = GST_BUFFER_DATA (outbuffer);
750
751   res_32[0] = get_unaligned_i24 (res);
752   res_32[1] = get_unaligned_i24 ((res + 3));
753
754   GST_INFO ("expected %+5d %+5d  real %+5d %+5d", out_32[0], out_32[1],
755       res_32[0], res_32[1]);
756   fail_unless (memcmp (res_32, out_32, 8) == 0);
757
758   /* cleanup */
759   cleanup_volume (volume);
760 }
761
762 GST_END_TEST;
763
764 GST_START_TEST (test_unity_s32)
765 {
766   GstElement *volume;
767   GstBuffer *inbuffer, *outbuffer;
768   GstCaps *caps;
769   gint32 in[2] = { 1073741824, -65536 };
770   gint32 *res;
771
772   volume = setup_volume ();
773   fail_unless (gst_element_set_state (volume,
774           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
775       "could not set to playing");
776
777   inbuffer = gst_buffer_new_and_alloc (8);
778   memcpy (GST_BUFFER_DATA (inbuffer), in, 8);
779   caps = gst_caps_from_string (VOLUME_CAPS_STRING_S32);
780   gst_buffer_set_caps (inbuffer, caps);
781   gst_caps_unref (caps);
782   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
783
784   /* pushing gives away my reference ... */
785   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
786   /* ... but it ends up being collected on the global buffer list */
787   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
788   fail_unless_equals_int (g_list_length (buffers), 1);
789   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
790   fail_unless (inbuffer == outbuffer);
791   res = (gint32 *) GST_BUFFER_DATA (outbuffer);
792   GST_INFO ("expected %+5d %+5d  real %+5d %+5d", in[0], in[1], res[0], res[1]);
793   fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 8) == 0);
794
795   /* cleanup */
796   cleanup_volume (volume);
797 }
798
799 GST_END_TEST;
800
801 GST_START_TEST (test_half_s32)
802 {
803   GstElement *volume;
804   GstBuffer *inbuffer;
805   GstBuffer *outbuffer;
806   GstCaps *caps;
807   gint32 in[2] = { 1073741824, -65536 };
808   gint32 out[2] = { 536870912, -32768 };
809   gint32 *res;
810
811   volume = setup_volume ();
812   g_object_set (G_OBJECT (volume), "volume", 0.5, NULL);
813   fail_unless (gst_element_set_state (volume,
814           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
815       "could not set to playing");
816
817   inbuffer = gst_buffer_new_and_alloc (8);
818   memcpy (GST_BUFFER_DATA (inbuffer), in, 8);
819   fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 8) == 0);
820   caps = gst_caps_from_string (VOLUME_CAPS_STRING_S32);
821   gst_buffer_set_caps (inbuffer, caps);
822   gst_caps_unref (caps);
823   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
824   /* FIXME: reffing the inbuffer should make the transformation not be
825    * inplace
826    gst_buffer_ref (inbuffer);
827    */
828
829   /* pushing gives away my reference ... */
830   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
831   /* ... but it ends up being modified inplace and
832    * collected on the global buffer list */
833   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
834   fail_unless_equals_int (g_list_length (buffers), 1);
835   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
836   fail_unless (inbuffer == outbuffer);
837   res = (gint32 *) GST_BUFFER_DATA (outbuffer);
838   GST_INFO ("expected %+5d %+5d  real %+5d %+5d", out[0], out[1], res[0],
839       res[1]);
840   fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), out, 8) == 0);
841
842   /* cleanup */
843   cleanup_volume (volume);
844 }
845
846 GST_END_TEST;
847
848 GST_START_TEST (test_double_s32)
849 {
850   GstElement *volume;
851   GstBuffer *inbuffer;
852   GstBuffer *outbuffer;
853   GstCaps *caps;
854   gint32 in[2] = { 1073741824, -65536 };
855   gint32 out[2] = { 2147483647, -131072 };      /* notice the clamped sample */
856   gint32 *res;
857
858   volume = setup_volume ();
859   g_object_set (G_OBJECT (volume), "volume", 2.0, NULL);
860   fail_unless (gst_element_set_state (volume,
861           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
862       "could not set to playing");
863
864   inbuffer = gst_buffer_new_and_alloc (8);
865   memcpy (GST_BUFFER_DATA (inbuffer), in, 8);
866   fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 8) == 0);
867   caps = gst_caps_from_string (VOLUME_CAPS_STRING_S32);
868   gst_buffer_set_caps (inbuffer, caps);
869   gst_caps_unref (caps);
870   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
871   /* FIXME: reffing the inbuffer should make the transformation not be
872    * inplace
873    gst_buffer_ref (inbuffer);
874    */
875
876   /* pushing gives away my reference ... */
877   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
878   /* ... but it ends up being modified inplace and
879    * collected on the global buffer list */
880   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
881   fail_unless_equals_int (g_list_length (buffers), 1);
882   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
883   fail_unless (inbuffer == outbuffer);
884   res = (gint32 *) GST_BUFFER_DATA (outbuffer);
885   GST_INFO ("expected %+5d %+5d  real %+5d %+5d", out[0], out[1], res[0],
886       res[1]);
887   fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), out, 8) == 0);
888
889   /* cleanup */
890   cleanup_volume (volume);
891 }
892
893 GST_END_TEST;
894
895
896 GST_START_TEST (test_mute_s32)
897 {
898   GstElement *volume;
899   GstBuffer *inbuffer;
900   GstBuffer *outbuffer;
901   GstCaps *caps;
902   gint32 in[2] = { 1073741824, -65536 };
903   gint32 out[2] = { 0, 0 };
904   gint32 *res;
905
906   volume = setup_volume ();
907   g_object_set (G_OBJECT (volume), "mute", TRUE, NULL);
908   fail_unless (gst_element_set_state (volume,
909           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
910       "could not set to playing");
911
912   inbuffer = gst_buffer_new_and_alloc (8);
913   memcpy (GST_BUFFER_DATA (inbuffer), in, 8);
914   fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 8) == 0);
915   caps = gst_caps_from_string (VOLUME_CAPS_STRING_S32);
916   gst_buffer_set_caps (inbuffer, caps);
917   gst_caps_unref (caps);
918   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
919   /* FIXME: reffing the inbuffer should make the transformation not be
920    * inplace
921    gst_buffer_ref (inbuffer);
922    */
923
924   /* pushing gives away my reference ... */
925   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
926   /* ... but it ends up being modified inplace and
927    * collected on the global buffer list */
928   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
929   fail_unless_equals_int (g_list_length (buffers), 1);
930   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
931   fail_unless (inbuffer == outbuffer);
932   res = (gint32 *) GST_BUFFER_DATA (outbuffer);
933   GST_INFO ("expected %+5d %+5d  real %+5d %+5d", out[0], out[1], res[0],
934       res[1]);
935   fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), out, 8) == 0);
936
937   /* cleanup */
938   cleanup_volume (volume);
939 }
940
941 GST_END_TEST;
942
943 GST_START_TEST (test_unity_f32)
944 {
945   GstElement *volume;
946   GstBuffer *inbuffer, *outbuffer;
947   GstCaps *caps;
948   gfloat in[2] = { 0.75, -0.25 };
949   gfloat *res;
950
951   volume = setup_volume ();
952   fail_unless (gst_element_set_state (volume,
953           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
954       "could not set to playing");
955
956   inbuffer = gst_buffer_new_and_alloc (8);
957   memcpy (GST_BUFFER_DATA (inbuffer), in, 8);
958   caps = gst_caps_from_string (VOLUME_CAPS_STRING_F32);
959   gst_buffer_set_caps (inbuffer, caps);
960   gst_caps_unref (caps);
961   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
962
963   /* pushing gives away my reference ... */
964   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
965   /* ... but it ends up being collected on the global buffer list */
966   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
967   fail_unless_equals_int (g_list_length (buffers), 1);
968   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
969   fail_unless (inbuffer == outbuffer);
970   res = (gfloat *) GST_BUFFER_DATA (outbuffer);
971   GST_INFO ("expected %+1.4f %+1.4f  real %+1.4f %+1.4f", in[0], in[1], res[0],
972       res[1]);
973   fail_unless_equals_float (res[0], in[0]);
974   fail_unless_equals_float (res[1], in[1]);
975
976   /* cleanup */
977   cleanup_volume (volume);
978 }
979
980 GST_END_TEST;
981
982 GST_START_TEST (test_half_f32)
983 {
984   GstElement *volume;
985   GstBuffer *inbuffer;
986   GstBuffer *outbuffer;
987   GstCaps *caps;
988   gfloat in[2] = { 0.75, -0.25 };
989   gfloat out[2] = { 0.375, -0.125 };
990   gfloat *res;
991
992   volume = setup_volume ();
993   g_object_set (G_OBJECT (volume), "volume", 0.5, NULL);
994   fail_unless (gst_element_set_state (volume,
995           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
996       "could not set to playing");
997
998   inbuffer = gst_buffer_new_and_alloc (8);
999   memcpy (GST_BUFFER_DATA (inbuffer), in, 8);
1000   fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 8) == 0);
1001   caps = gst_caps_from_string (VOLUME_CAPS_STRING_F32);
1002   gst_buffer_set_caps (inbuffer, caps);
1003   gst_caps_unref (caps);
1004   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1005   /* FIXME: reffing the inbuffer should make the transformation not be
1006    * inplace
1007    gst_buffer_ref (inbuffer);
1008    */
1009
1010   /* pushing gives away my reference ... */
1011   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
1012   /* ... but it ends up being modified inplace and
1013    * collected on the global buffer list */
1014   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1015   fail_unless_equals_int (g_list_length (buffers), 1);
1016   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
1017   fail_unless (inbuffer == outbuffer);
1018   res = (gfloat *) GST_BUFFER_DATA (outbuffer);
1019   GST_INFO ("expected %+1.4f %+1.4f  real %+1.4f %+1.4f", out[0], out[1],
1020       res[0], res[1]);
1021   fail_unless_equals_float (res[0], out[0]);
1022   fail_unless_equals_float (res[1], out[1]);
1023
1024   /* cleanup */
1025   cleanup_volume (volume);
1026 }
1027
1028 GST_END_TEST;
1029
1030 GST_START_TEST (test_double_f32)
1031 {
1032   GstElement *volume;
1033   GstBuffer *inbuffer;
1034   GstBuffer *outbuffer;
1035   GstCaps *caps;
1036   gfloat in[2] = { 0.75, -0.25 };
1037   gfloat out[2] = { 1.5, -0.5 };        /* nothing is clamped */
1038   gfloat *res;
1039
1040   volume = setup_volume ();
1041   g_object_set (G_OBJECT (volume), "volume", 2.0, NULL);
1042   fail_unless (gst_element_set_state (volume,
1043           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
1044       "could not set to playing");
1045
1046   inbuffer = gst_buffer_new_and_alloc (8);
1047   memcpy (GST_BUFFER_DATA (inbuffer), in, 8);
1048   fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 8) == 0);
1049   caps = gst_caps_from_string (VOLUME_CAPS_STRING_F32);
1050   gst_buffer_set_caps (inbuffer, caps);
1051   gst_caps_unref (caps);
1052   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1053   /* FIXME: reffing the inbuffer should make the transformation not be
1054    * inplace
1055    gst_buffer_ref (inbuffer);
1056    */
1057
1058   /* pushing gives away my reference ... */
1059   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
1060   /* ... but it ends up being modified inplace and
1061    * collected on the global buffer list */
1062   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1063   fail_unless_equals_int (g_list_length (buffers), 1);
1064   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
1065   fail_unless (inbuffer == outbuffer);
1066   res = (gfloat *) GST_BUFFER_DATA (outbuffer);
1067   GST_INFO ("expected %+1.4f %+1.4f  real %+1.4f %+1.4f", out[0], out[1],
1068       res[0], res[1]);
1069   fail_unless_equals_float (res[0], out[0]);
1070   fail_unless_equals_float (res[1], out[1]);
1071
1072   /* cleanup */
1073   cleanup_volume (volume);
1074 }
1075
1076 GST_END_TEST;
1077
1078
1079 GST_START_TEST (test_mute_f32)
1080 {
1081   GstElement *volume;
1082   GstBuffer *inbuffer;
1083   GstBuffer *outbuffer;
1084   GstCaps *caps;
1085   gfloat in[2] = { 0.75, -0.25 };
1086   gfloat out[2] = { 0, 0 };
1087   gfloat *res;
1088
1089   volume = setup_volume ();
1090   g_object_set (G_OBJECT (volume), "mute", TRUE, NULL);
1091   fail_unless (gst_element_set_state (volume,
1092           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
1093       "could not set to playing");
1094
1095   inbuffer = gst_buffer_new_and_alloc (8);
1096   memcpy (GST_BUFFER_DATA (inbuffer), in, 8);
1097   fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 8) == 0);
1098   caps = gst_caps_from_string (VOLUME_CAPS_STRING_F32);
1099   gst_buffer_set_caps (inbuffer, caps);
1100   gst_caps_unref (caps);
1101   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1102   /* FIXME: reffing the inbuffer should make the transformation not be
1103    * inplace
1104    gst_buffer_ref (inbuffer);
1105    */
1106
1107   /* pushing gives away my reference ... */
1108   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
1109   /* ... but it ends up being modified inplace and
1110    * collected on the global buffer list */
1111   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1112   fail_unless_equals_int (g_list_length (buffers), 1);
1113   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
1114   fail_unless (inbuffer == outbuffer);
1115   res = (gfloat *) GST_BUFFER_DATA (outbuffer);
1116   GST_INFO ("expected %+1.4f %+1.4f  real %+1.4f %+1.4f", out[0], out[1],
1117       res[0], res[1]);
1118   fail_unless_equals_float (res[0], out[0]);
1119   fail_unless_equals_float (res[1], out[1]);
1120
1121   /* cleanup */
1122   cleanup_volume (volume);
1123 }
1124
1125 GST_END_TEST;
1126
1127 GST_START_TEST (test_unity_f64)
1128 {
1129   GstElement *volume;
1130   GstBuffer *inbuffer, *outbuffer;
1131   GstCaps *caps;
1132   gdouble in[2] = { 0.75, -0.25 };
1133   gdouble *res;
1134
1135   volume = setup_volume ();
1136   fail_unless (gst_element_set_state (volume,
1137           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
1138       "could not set to playing");
1139
1140   inbuffer = gst_buffer_new_and_alloc (16);
1141   memcpy (GST_BUFFER_DATA (inbuffer), in, 16);
1142   caps = gst_caps_from_string (VOLUME_CAPS_STRING_F64);
1143   gst_buffer_set_caps (inbuffer, caps);
1144   gst_caps_unref (caps);
1145   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1146
1147   /* pushing gives away my reference ... */
1148   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
1149   /* ... but it ends up being collected on the global buffer list */
1150   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1151   fail_unless_equals_int (g_list_length (buffers), 1);
1152   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
1153   fail_unless (inbuffer == outbuffer);
1154   res = (gdouble *) GST_BUFFER_DATA (outbuffer);
1155   GST_INFO ("expected %+1.4f %+1.4f  real %+1.4f %+1.4f", in[0], in[1], res[0],
1156       res[1]);
1157   fail_unless_equals_float (res[0], in[0]);
1158   fail_unless_equals_float (res[1], in[1]);
1159
1160   /* cleanup */
1161   cleanup_volume (volume);
1162 }
1163
1164 GST_END_TEST;
1165
1166 GST_START_TEST (test_half_f64)
1167 {
1168   GstElement *volume;
1169   GstBuffer *inbuffer;
1170   GstBuffer *outbuffer;
1171   GstCaps *caps;
1172   gdouble in[2] = { 0.75, -0.25 };
1173   gdouble out[2] = { 0.375, -0.125 };
1174   gdouble *res;
1175
1176   volume = setup_volume ();
1177   g_object_set (G_OBJECT (volume), "volume", 0.5, NULL);
1178   fail_unless (gst_element_set_state (volume,
1179           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
1180       "could not set to playing");
1181
1182   inbuffer = gst_buffer_new_and_alloc (16);
1183   memcpy (GST_BUFFER_DATA (inbuffer), in, 16);
1184   fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 16) == 0);
1185   caps = gst_caps_from_string (VOLUME_CAPS_STRING_F64);
1186   gst_buffer_set_caps (inbuffer, caps);
1187   gst_caps_unref (caps);
1188   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1189   /* FIXME: reffing the inbuffer should make the transformation not be
1190    * inplace
1191    gst_buffer_ref (inbuffer);
1192    */
1193
1194   /* pushing gives away my reference ... */
1195   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
1196   /* ... but it ends up being modified inplace and
1197    * collected on the global buffer list */
1198   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1199   fail_unless_equals_int (g_list_length (buffers), 1);
1200   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
1201   fail_unless (inbuffer == outbuffer);
1202   res = (gdouble *) GST_BUFFER_DATA (outbuffer);
1203   GST_INFO ("expected %+1.4f %+1.4f  real %+1.4f %+1.4f", out[0], out[1],
1204       res[0], res[1]);
1205   fail_unless_equals_float (res[0], out[0]);
1206   fail_unless_equals_float (res[1], out[1]);
1207
1208   /* cleanup */
1209   cleanup_volume (volume);
1210 }
1211
1212 GST_END_TEST;
1213
1214 GST_START_TEST (test_double_f64)
1215 {
1216   GstElement *volume;
1217   GstBuffer *inbuffer;
1218   GstBuffer *outbuffer;
1219   GstCaps *caps;
1220   gdouble in[2] = { 0.75, -0.25 };
1221   gdouble out[2] = { 1.5, -0.5 };       /* nothing is clamped */
1222   gdouble *res;
1223
1224   volume = setup_volume ();
1225   g_object_set (G_OBJECT (volume), "volume", 2.0, NULL);
1226   fail_unless (gst_element_set_state (volume,
1227           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
1228       "could not set to playing");
1229
1230   inbuffer = gst_buffer_new_and_alloc (16);
1231   memcpy (GST_BUFFER_DATA (inbuffer), in, 16);
1232   fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 16) == 0);
1233   caps = gst_caps_from_string (VOLUME_CAPS_STRING_F64);
1234   gst_buffer_set_caps (inbuffer, caps);
1235   gst_caps_unref (caps);
1236   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1237   /* FIXME: reffing the inbuffer should make the transformation not be
1238    * inplace
1239    gst_buffer_ref (inbuffer);
1240    */
1241
1242   /* pushing gives away my reference ... */
1243   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
1244   /* ... but it ends up being modified inplace and
1245    * collected on the global buffer list */
1246   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1247   fail_unless_equals_int (g_list_length (buffers), 1);
1248   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
1249   fail_unless (inbuffer == outbuffer);
1250   res = (gdouble *) GST_BUFFER_DATA (outbuffer);
1251   GST_INFO ("expected %+1.4f %+1.4f  real %+1.4f %+1.4f", out[0], out[1],
1252       res[0], res[1]);
1253   fail_unless_equals_float (res[0], out[0]);
1254   fail_unless_equals_float (res[1], out[1]);
1255
1256   /* cleanup */
1257   cleanup_volume (volume);
1258 }
1259
1260 GST_END_TEST;
1261
1262
1263 GST_START_TEST (test_mute_f64)
1264 {
1265   GstElement *volume;
1266   GstBuffer *inbuffer;
1267   GstBuffer *outbuffer;
1268   GstCaps *caps;
1269   gdouble in[2] = { 0.75, -0.25 };
1270   gdouble out[2] = { 0, 0 };
1271   gdouble *res;
1272
1273   volume = setup_volume ();
1274   g_object_set (G_OBJECT (volume), "mute", TRUE, NULL);
1275   fail_unless (gst_element_set_state (volume,
1276           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
1277       "could not set to playing");
1278
1279   inbuffer = gst_buffer_new_and_alloc (16);
1280   memcpy (GST_BUFFER_DATA (inbuffer), in, 16);
1281   fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 16) == 0);
1282   caps = gst_caps_from_string (VOLUME_CAPS_STRING_F64);
1283   gst_buffer_set_caps (inbuffer, caps);
1284   gst_caps_unref (caps);
1285   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1286   /* FIXME: reffing the inbuffer should make the transformation not be
1287    * inplace
1288    gst_buffer_ref (inbuffer);
1289    */
1290
1291   /* pushing gives away my reference ... */
1292   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
1293   /* ... but it ends up being modified inplace and
1294    * collected on the global buffer list */
1295   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1296   fail_unless_equals_int (g_list_length (buffers), 1);
1297   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
1298   fail_unless (inbuffer == outbuffer);
1299   res = (gdouble *) GST_BUFFER_DATA (outbuffer);
1300   GST_INFO ("expected %+1.4f %+1.4f  real %+1.4f %+1.4f", out[0], out[1],
1301       res[0], res[1]);
1302   fail_unless_equals_float (res[0], out[0]);
1303   fail_unless_equals_float (res[1], out[1]);
1304
1305   /* cleanup */
1306   cleanup_volume (volume);
1307 }
1308
1309 GST_END_TEST;
1310
1311 GST_START_TEST (test_wrong_caps)
1312 {
1313   GstElement *volume;
1314   GstBuffer *inbuffer;
1315   gint16 in[2] = { 16384, -256 };
1316   GstBus *bus;
1317   GstMessage *message;
1318   GstCaps *caps;
1319
1320   volume = setup_volume ();
1321   bus = gst_bus_new ();
1322
1323   fail_unless (gst_element_set_state (volume,
1324           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
1325       "could not set to playing");
1326
1327   inbuffer = gst_buffer_new_and_alloc (4);
1328   memcpy (GST_BUFFER_DATA (inbuffer), in, 4);
1329   caps = gst_caps_from_string (VOLUME_WRONG_CAPS_STRING);
1330   gst_buffer_set_caps (inbuffer, caps);
1331   gst_caps_unref (caps);
1332   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1333   gst_buffer_ref (inbuffer);
1334
1335   /* set a bus here so we avoid getting state change messages */
1336   gst_element_set_bus (volume, bus);
1337
1338   /* pushing gives an error because it can't negotiate with wrong caps */
1339   fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer),
1340       GST_FLOW_NOT_NEGOTIATED);
1341   /* ... and the buffer would have been lost if we didn't ref it ourselves */
1342   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1343   gst_buffer_unref (inbuffer);
1344   fail_unless_equals_int (g_list_length (buffers), 0);
1345
1346   /* volume_set_caps should not have been called since basetransform caught
1347    * the negotiation problem */
1348   fail_if ((message = gst_bus_pop (bus)) != NULL);
1349
1350   /* cleanup */
1351   gst_element_set_bus (volume, NULL);
1352   gst_object_unref (GST_OBJECT (bus));
1353   cleanup_volume (volume);
1354 }
1355
1356 GST_END_TEST;
1357
1358 GST_START_TEST (test_passthrough)
1359 {
1360   GstElement *volume;
1361   GstBuffer *inbuffer, *outbuffer;
1362   GstCaps *caps;
1363   gint16 in[2] = { 16384, -256 };
1364   gint16 *res;
1365
1366   volume = setup_volume ();
1367   g_object_set (G_OBJECT (volume), "volume", 1.0, NULL);
1368   fail_unless (gst_element_set_state (volume,
1369           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
1370       "could not set to playing");
1371
1372   inbuffer = gst_buffer_new_and_alloc (4);
1373   memcpy (GST_BUFFER_DATA (inbuffer), in, 4);
1374   caps = gst_caps_from_string (VOLUME_CAPS_STRING_S16);
1375   gst_buffer_set_caps (inbuffer, caps);
1376   gst_caps_unref (caps);
1377   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1378
1379   /* pushing gives away my reference ... */
1380   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
1381   /* ... but it ends up being collected on the global buffer list */
1382   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1383   fail_unless_equals_int (g_list_length (buffers), 1);
1384   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
1385   fail_unless (inbuffer == outbuffer);
1386   res = (gint16 *) GST_BUFFER_DATA (outbuffer);
1387   GST_INFO ("expected %+5d %+5d  real %+5d %+5d", in[0], in[1], res[0], res[1]);
1388   fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 4) == 0);
1389
1390   /* cleanup */
1391   cleanup_volume (volume);
1392 }
1393
1394 GST_END_TEST;
1395
1396 GST_START_TEST (test_controller_usability)
1397 {
1398   GstInterpolationControlSource *csource;
1399   GstController *c;
1400   GstElement *volume;
1401   GValue value = { 0, };
1402
1403   /* note: the volume element should init the controller library for us */
1404   volume = setup_volume ();
1405
1406   c = gst_controller_new (G_OBJECT (volume), "volume", NULL);
1407
1408   fail_unless (GST_IS_CONTROLLER (c));
1409
1410   /* this shouldn't crash, whether this mode is implemented or not */
1411   csource = gst_interpolation_control_source_new ();
1412   gst_interpolation_control_source_set_interpolation_mode (csource,
1413       GST_INTERPOLATE_CUBIC);
1414   gst_controller_set_control_source (c, "volume", GST_CONTROL_SOURCE (csource));
1415   g_object_unref (csource);
1416
1417   g_value_init (&value, G_TYPE_DOUBLE);
1418   g_value_set_double (&value, 0.0);
1419   gst_interpolation_control_source_set (csource, 0 * GST_SECOND, &value);
1420   g_value_set_double (&value, 1.0);
1421   gst_interpolation_control_source_set (csource, 5 * GST_SECOND, &value);
1422   g_value_set_double (&value, 0.0);
1423   gst_interpolation_control_source_set (csource, 10 * GST_SECOND, &value);
1424   g_value_unset (&value);
1425
1426   g_object_unref (c);
1427
1428   cleanup_volume (volume);
1429 }
1430
1431 GST_END_TEST;
1432
1433 GST_START_TEST (test_controller_processing)
1434 {
1435   GstInterpolationControlSource *csource;
1436   GstController *c;
1437   GstElement *volume;
1438   GstBuffer *inbuffer, *outbuffer;
1439   GstCaps *caps;
1440   gint16 in[2] = { 16384, -256 };
1441   gint16 *res;
1442
1443   volume = setup_volume ();
1444
1445   c = gst_controller_new (G_OBJECT (volume), "volume", NULL);
1446
1447   fail_unless (GST_IS_CONTROLLER (c));
1448
1449   csource = gst_interpolation_control_source_new ();
1450   gst_interpolation_control_source_set_interpolation_mode (csource,
1451       GST_INTERPOLATE_CUBIC);
1452   gst_controller_set_control_source (c, "volume", GST_CONTROL_SOURCE (csource));
1453   g_object_unref (csource);
1454
1455   fail_unless (gst_element_set_state (volume,
1456           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
1457       "could not set to playing");
1458
1459   inbuffer = gst_buffer_new_and_alloc (4);
1460   memcpy (GST_BUFFER_DATA (inbuffer), in, 4);
1461   caps = gst_caps_from_string (VOLUME_CAPS_STRING_S16);
1462   gst_buffer_set_caps (inbuffer, caps);
1463   GST_BUFFER_TIMESTAMP (inbuffer) = 0;
1464   gst_caps_unref (caps);
1465   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1466
1467   /* pushing gives away my reference ... */
1468   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
1469   /* ... but it ends up being collected on the global buffer list */
1470   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1471   fail_unless_equals_int (g_list_length (buffers), 1);
1472   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
1473   fail_unless (inbuffer == outbuffer);
1474   res = (gint16 *) GST_BUFFER_DATA (outbuffer);
1475   GST_INFO ("expected %+5d %+5d  real %+5d %+5d", in[0], in[1], res[0], res[1]);
1476   fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 4) == 0);
1477
1478   g_object_unref (c);
1479
1480   cleanup_volume (volume);
1481 }
1482
1483 GST_END_TEST;
1484
1485 static Suite *
1486 volume_suite (void)
1487 {
1488   Suite *s = suite_create ("volume");
1489   TCase *tc_chain = tcase_create ("general");
1490
1491   suite_add_tcase (s, tc_chain);
1492   tcase_add_test (tc_chain, test_get_set);
1493   tcase_add_test (tc_chain, test_unity_s8);
1494   tcase_add_test (tc_chain, test_half_s8);
1495   tcase_add_test (tc_chain, test_double_s8);
1496   tcase_add_test (tc_chain, test_mute_s8);
1497   tcase_add_test (tc_chain, test_unity_s16);
1498   tcase_add_test (tc_chain, test_half_s16);
1499   tcase_add_test (tc_chain, test_double_s16);
1500   tcase_add_test (tc_chain, test_mute_s16);
1501   tcase_add_test (tc_chain, test_unity_s24);
1502   tcase_add_test (tc_chain, test_half_s24);
1503   tcase_add_test (tc_chain, test_double_s24);
1504   tcase_add_test (tc_chain, test_mute_s24);
1505   tcase_add_test (tc_chain, test_unity_s32);
1506   tcase_add_test (tc_chain, test_half_s32);
1507   tcase_add_test (tc_chain, test_double_s32);
1508   tcase_add_test (tc_chain, test_mute_s32);
1509   tcase_add_test (tc_chain, test_unity_f32);
1510   tcase_add_test (tc_chain, test_half_f32);
1511   tcase_add_test (tc_chain, test_double_f32);
1512   tcase_add_test (tc_chain, test_mute_f32);
1513   tcase_add_test (tc_chain, test_unity_f64);
1514   tcase_add_test (tc_chain, test_half_f64);
1515   tcase_add_test (tc_chain, test_double_f64);
1516   tcase_add_test (tc_chain, test_mute_f64);
1517   tcase_add_test (tc_chain, test_wrong_caps);
1518   tcase_add_test (tc_chain, test_passthrough);
1519   tcase_add_test (tc_chain, test_controller_usability);
1520   tcase_add_test (tc_chain, test_controller_processing);
1521
1522   return s;
1523 }
1524
1525 GST_CHECK_MAIN (volume)