5 * Copyright (C) <2005> Thomas Vander Stichele <thomas at apestaart dot org>
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.
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.
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.
25 #include <gst/base/gstbasetransform.h>
26 #include <gst/check/gstcheck.h>
27 #include <gst/audio/streamvolume.h>
28 #include <gst/controller/gstinterpolationcontrolsource.h>
29 #include <gst/controller/gstcontrolbindingdirect.h>
31 /* For ease of programming we use globals to keep refs for our floating
32 * src and sink pads we create; otherwise we always have to do get_pad,
33 * get_peer, and then remove references in every test function */
34 static GstPad *mysrcpad, *mysinkpad;
36 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
37 #define FORMATS1 "{ S8, S16LE, S24LE, S32LE, F32LE, F64LE }"
39 #define FORMATS3 "S16LE"
40 #define FORMATS4 "S24LE"
41 #define FORMATS5 "S32LE"
42 #define FORMATS6 "F32LE"
43 #define FORMATS7 "F64LE"
44 #define FORMATS8 "U16LE"
46 #define FORMATS1 "{ S8, S16BE, S24BE, S32BE, F32BE, F64BE }"
48 #define FORMATS3 "S16BE"
49 #define FORMATS4 "S24BE"
50 #define FORMATS5 "S32BE"
51 #define FORMATS6 "F32BE"
52 #define FORMATS7 "F64BE"
53 #define FORMATS8 "U16BE"
56 #define VOLUME_CAPS_TEMPLATE_STRING \
58 "format = (string) "FORMATS1", " \
59 "channels = (int) [ 1, MAX ], " \
60 "rate = (int) [ 1, MAX ]"
62 #define VOLUME_CAPS_STRING_S8 \
64 "formats = (string) "FORMATS2", " \
65 "channels = (int) 1, " \
68 #define VOLUME_CAPS_STRING_S16 \
70 "formats = (string) "FORMATS3", " \
71 "channels = (int) 1, " \
74 #define VOLUME_CAPS_STRING_S24 \
76 "formats = (string) "FORMATS4", " \
77 "channels = (int) 1, " \
80 #define VOLUME_CAPS_STRING_S32 \
82 "formats = (string) "FORMATS5", " \
83 "channels = (int) 1, " \
86 #define VOLUME_CAPS_STRING_F32 \
88 "formats = (string) "FORMATS6", " \
89 "channels = (int) 1, " \
92 #define VOLUME_CAPS_STRING_F64 \
94 "formats = (string) "FORMATS7", " \
95 "channels = (int) 1, " \
98 #define VOLUME_WRONG_CAPS_STRING \
100 "formats = (string) "FORMATS8", " \
101 "channels = (int) 1, " \
105 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
108 GST_STATIC_CAPS (VOLUME_CAPS_TEMPLATE_STRING)
110 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
113 GST_STATIC_CAPS (VOLUME_CAPS_TEMPLATE_STRING)
121 GST_DEBUG ("setup_volume");
122 volume = gst_check_setup_element ("volume");
123 mysrcpad = gst_check_setup_src_pad (volume, &srctemplate);
124 mysinkpad = gst_check_setup_sink_pad (volume, &sinktemplate);
125 gst_pad_set_active (mysrcpad, TRUE);
126 gst_pad_set_active (mysinkpad, TRUE);
132 cleanup_volume (GstElement * volume)
134 GST_DEBUG ("cleanup_volume");
136 g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL);
137 g_list_free (buffers);
140 gst_pad_set_active (mysrcpad, FALSE);
141 gst_pad_set_active (mysinkpad, FALSE);
142 gst_check_teardown_src_pad (volume);
143 gst_check_teardown_sink_pad (volume);
144 gst_check_teardown_element (volume);
147 GST_START_TEST (test_get_set)
149 GstElement *volume = gst_element_factory_make ("volume", NULL);
152 fail_unless (volume != NULL);
153 g_object_get (G_OBJECT (volume), "volume", &val, NULL);
154 fail_unless (val == 1.0);
155 fail_unless (val == gst_stream_volume_get_volume (GST_STREAM_VOLUME (volume),
156 GST_STREAM_VOLUME_FORMAT_LINEAR));
158 g_object_set (G_OBJECT (volume), "volume", 0.5, NULL);
159 g_object_get (G_OBJECT (volume), "volume", &val, NULL);
160 fail_unless (val == 0.5);
161 fail_unless (val == gst_stream_volume_get_volume (GST_STREAM_VOLUME (volume),
162 GST_STREAM_VOLUME_FORMAT_LINEAR));
164 gst_stream_volume_set_volume (GST_STREAM_VOLUME (volume),
165 GST_STREAM_VOLUME_FORMAT_LINEAR, 1.0);
166 g_object_get (G_OBJECT (volume), "volume", &val, NULL);
167 fail_unless (val == 1.0);
168 fail_unless (val == gst_stream_volume_get_volume (GST_STREAM_VOLUME (volume),
169 GST_STREAM_VOLUME_FORMAT_LINEAR));
171 gst_object_unref (volume);
176 GST_START_TEST (test_unity_s8)
179 GstBuffer *inbuffer, *outbuffer;
181 gint8 in[2] = { 64, -16 };
184 volume = setup_volume ();
185 fail_unless (gst_element_set_state (volume,
186 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
187 "could not set to playing");
189 inbuffer = gst_buffer_new_and_alloc (2);
190 gst_buffer_fill (inbuffer, 0, in, 2);
191 caps = gst_caps_from_string (VOLUME_CAPS_STRING_S8);
192 gst_pad_set_caps (mysrcpad, caps);
193 gst_caps_unref (caps);
194 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
196 /* pushing gives away my reference ... */
197 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
198 /* ... but it ends up being collected on the global buffer list */
199 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
200 fail_unless_equals_int (g_list_length (buffers), 1);
201 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
202 fail_unless (inbuffer == outbuffer);
203 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
204 GST_INFO ("expected %+5d %+5d real %+5d %+5d", in[0], in[1], map.data[0],
206 fail_unless (memcmp (map.data, in, 2) == 0);
207 gst_buffer_unmap (outbuffer, &map);
210 cleanup_volume (volume);
215 GST_START_TEST (test_half_s8)
219 GstBuffer *outbuffer;
221 gint8 in[2] = { 64, -16 };
222 gint8 out[2] = { 32, -8 };
225 volume = setup_volume ();
226 g_object_set (G_OBJECT (volume), "volume", 0.5, NULL);
227 fail_unless (gst_element_set_state (volume,
228 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
229 "could not set to playing");
231 inbuffer = gst_buffer_new_and_alloc (2);
232 gst_buffer_fill (inbuffer, 0, in, 2);
233 caps = gst_caps_from_string (VOLUME_CAPS_STRING_S8);
234 gst_pad_set_caps (mysrcpad, caps);
235 gst_caps_unref (caps);
236 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
237 /* FIXME: reffing the inbuffer should make the transformation not be
239 gst_buffer_ref (inbuffer);
242 /* pushing gives away my reference ... */
243 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
244 /* ... but it ends up being modified inplace and
245 * collected on the global buffer list */
246 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
247 fail_unless_equals_int (g_list_length (buffers), 1);
248 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
249 fail_unless (inbuffer == outbuffer);
250 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
251 GST_INFO ("expected %+5d %+5d real %+5d %+5d", out[0], out[1], map.data[0],
253 fail_unless (memcmp (map.data, out, 2) == 0);
254 gst_buffer_unmap (outbuffer, &map);
257 cleanup_volume (volume);
262 GST_START_TEST (test_double_s8)
266 GstBuffer *outbuffer;
268 gint8 in[2] = { 64, -16 };
269 gint8 out[2] = { 127, -32 }; /* notice the clamped sample */
272 volume = setup_volume ();
273 g_object_set (G_OBJECT (volume), "volume", 2.0, NULL);
274 fail_unless (gst_element_set_state (volume,
275 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
276 "could not set to playing");
278 inbuffer = gst_buffer_new_and_alloc (2);
279 gst_buffer_fill (inbuffer, 0, in, 2);
280 caps = gst_caps_from_string (VOLUME_CAPS_STRING_S8);
281 gst_pad_set_caps (mysrcpad, caps);
282 gst_caps_unref (caps);
283 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
284 /* FIXME: reffing the inbuffer should make the transformation not be
286 gst_buffer_ref (inbuffer);
289 /* pushing gives away my reference ... */
290 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
291 /* ... but it ends up being modified inplace and
292 * collected on the global buffer list */
293 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
294 fail_unless_equals_int (g_list_length (buffers), 1);
295 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
296 fail_unless (inbuffer == outbuffer);
297 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
298 GST_INFO ("expected %+5d %+5d real %+5d %+5d", out[0], out[1], map.data[0],
300 fail_unless (memcmp (map.data, out, 2) == 0);
301 gst_buffer_unmap (outbuffer, &map);
304 cleanup_volume (volume);
309 GST_START_TEST (test_ten_s8)
313 GstBuffer *outbuffer;
315 gint8 in[2] = { 64, -10 };
316 gint8 out[2] = { 127, -100 }; /* notice the clamped sample */
319 volume = setup_volume ();
320 g_object_set (G_OBJECT (volume), "volume", 10.0, NULL);
321 fail_unless (gst_element_set_state (volume,
322 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
323 "could not set to playing");
325 inbuffer = gst_buffer_new_and_alloc (2);
326 gst_buffer_fill (inbuffer, 0, in, 2);
327 fail_unless (gst_buffer_memcmp (inbuffer, 0, in, 2) == 0);
328 caps = gst_caps_from_string (VOLUME_CAPS_STRING_S8);
329 gst_pad_set_caps (mysrcpad, caps);
330 gst_caps_unref (caps);
331 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
332 /* FIXME: reffing the inbuffer should make the transformation not be
334 gst_buffer_ref (inbuffer);
337 /* pushing gives away my reference ... */
338 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
339 /* ... but it ends up being modified inplace and
340 * collected on the global buffer list */
341 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
342 fail_unless_equals_int (g_list_length (buffers), 1);
343 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
344 fail_unless (inbuffer == outbuffer);
345 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
346 GST_INFO ("expected %+5d %+5d real %+5d %+5d", out[0], out[1], map.data[0],
348 fail_unless (memcmp (map.data, out, 2) == 0);
349 gst_buffer_unmap (outbuffer, &map);
352 cleanup_volume (volume);
357 GST_START_TEST (test_mute_s8)
361 GstBuffer *outbuffer;
363 gint8 in[2] = { 64, -16 };
364 gint8 out[2] = { 0, 0 };
367 volume = setup_volume ();
368 g_object_set (G_OBJECT (volume), "mute", TRUE, NULL);
369 fail_unless (gst_element_set_state (volume,
370 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
371 "could not set to playing");
373 inbuffer = gst_buffer_new_and_alloc (2);
374 gst_buffer_fill (inbuffer, 0, in, 2);
375 caps = gst_caps_from_string (VOLUME_CAPS_STRING_S8);
376 gst_pad_set_caps (mysrcpad, caps);
377 gst_caps_unref (caps);
378 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
379 /* FIXME: reffing the inbuffer should make the transformation not be
381 gst_buffer_ref (inbuffer);
384 /* pushing gives away my reference ... */
385 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
386 /* ... but it ends up being modified inplace and
387 * collected on the global buffer list */
388 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
389 fail_unless_equals_int (g_list_length (buffers), 1);
390 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
391 fail_unless (inbuffer == outbuffer);
392 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
393 GST_INFO ("expected %+5d %+5d real %+5d %+5d", out[0], out[1], map.data[0],
395 fail_unless (memcmp (map.data, out, 2) == 0);
396 gst_buffer_unmap (outbuffer, &map);
399 cleanup_volume (volume);
404 GST_START_TEST (test_unity_s16)
407 GstBuffer *inbuffer, *outbuffer;
409 gint16 in[2] = { 16384, -256 };
412 volume = setup_volume ();
413 fail_unless (gst_element_set_state (volume,
414 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
415 "could not set to playing");
417 inbuffer = gst_buffer_new_and_alloc (4);
418 gst_buffer_fill (inbuffer, 0, in, 4);
419 caps = gst_caps_from_string (VOLUME_CAPS_STRING_S16);
420 gst_pad_set_caps (mysrcpad, caps);
421 gst_caps_unref (caps);
422 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
424 /* pushing gives away my reference ... */
425 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
426 /* ... but it ends up being collected on the global buffer list */
427 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
428 fail_unless_equals_int (g_list_length (buffers), 1);
429 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
430 fail_unless (inbuffer == outbuffer);
431 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
432 GST_INFO ("expected %+5d %+5d real %+5d %+5d", in[0], in[1], map.data[0],
434 fail_unless (memcmp (map.data, in, 4) == 0);
435 gst_buffer_unmap (outbuffer, &map);
438 cleanup_volume (volume);
443 GST_START_TEST (test_half_s16)
447 GstBuffer *outbuffer;
449 gint16 in[2] = { 16384, -256 };
450 gint16 out[2] = { 8192, -128 };
453 volume = setup_volume ();
454 g_object_set (G_OBJECT (volume), "volume", 0.5, NULL);
455 fail_unless (gst_element_set_state (volume,
456 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
457 "could not set to playing");
459 inbuffer = gst_buffer_new_and_alloc (4);
460 gst_buffer_fill (inbuffer, 0, in, 4);
461 caps = gst_caps_from_string (VOLUME_CAPS_STRING_S16);
462 gst_pad_set_caps (mysrcpad, caps);
463 gst_caps_unref (caps);
464 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
465 /* FIXME: reffing the inbuffer should make the transformation not be
467 gst_buffer_ref (inbuffer);
470 /* pushing gives away my reference ... */
471 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
472 /* ... but it ends up being modified inplace and
473 * collected on the global buffer list */
474 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
475 fail_unless_equals_int (g_list_length (buffers), 1);
476 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
477 fail_unless (inbuffer == outbuffer);
478 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
479 GST_INFO ("expected %+5d %+5d real %+5d %+5d", out[0], out[1], map.data[0],
481 fail_unless (memcmp (map.data, out, 4) == 0);
482 gst_buffer_unmap (outbuffer, &map);
485 cleanup_volume (volume);
490 GST_START_TEST (test_double_s16)
494 GstBuffer *outbuffer;
496 gint16 in[2] = { 16384, -256 };
497 gint16 out[2] = { 32767, -512 }; /* notice the clamped sample */
500 volume = setup_volume ();
501 g_object_set (G_OBJECT (volume), "volume", 2.0, NULL);
502 fail_unless (gst_element_set_state (volume,
503 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
504 "could not set to playing");
506 inbuffer = gst_buffer_new_and_alloc (4);
507 gst_buffer_fill (inbuffer, 0, in, 4);
508 caps = gst_caps_from_string (VOLUME_CAPS_STRING_S16);
509 gst_pad_set_caps (mysrcpad, caps);
510 gst_caps_unref (caps);
511 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
512 /* FIXME: reffing the inbuffer should make the transformation not be
514 gst_buffer_ref (inbuffer);
517 /* pushing gives away my reference ... */
518 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
519 /* ... but it ends up being modified inplace and
520 * collected on the global buffer list */
521 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
522 fail_unless_equals_int (g_list_length (buffers), 1);
523 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
524 fail_unless (inbuffer == outbuffer);
525 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
526 GST_INFO ("expected %+5d %+5d real %+5d %+5d", out[0], out[1], map.data[0],
528 fail_unless (memcmp (map.data, out, 4) == 0);
529 gst_buffer_unmap (outbuffer, &map);
532 cleanup_volume (volume);
537 GST_START_TEST (test_ten_s16)
541 GstBuffer *outbuffer;
543 gint16 in[2] = { 16384, -10 };
544 gint16 out[2] = { 32767, -100 }; /* notice the clamped sample */
547 volume = setup_volume ();
548 g_object_set (G_OBJECT (volume), "volume", 10.0, NULL);
549 fail_unless (gst_element_set_state (volume,
550 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
551 "could not set to playing");
553 inbuffer = gst_buffer_new_and_alloc (4);
554 gst_buffer_fill (inbuffer, 0, in, 4);
555 fail_unless (gst_buffer_memcmp (inbuffer, 0, in, 4) == 0);
556 caps = gst_caps_from_string (VOLUME_CAPS_STRING_S16);
557 gst_pad_set_caps (mysrcpad, caps);
558 gst_caps_unref (caps);
559 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
560 /* FIXME: reffing the inbuffer should make the transformation not be
562 gst_buffer_ref (inbuffer);
565 /* pushing gives away my reference ... */
566 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
567 /* ... but it ends up being modified inplace and
568 * collected on the global buffer list */
569 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
570 fail_unless_equals_int (g_list_length (buffers), 1);
571 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
572 fail_unless (inbuffer == outbuffer);
573 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
574 GST_INFO ("expected %+5d %+5d real %+5d %+5d", out[0], out[1], map.data[0],
576 fail_unless (memcmp (map.data, out, 4) == 0);
577 gst_buffer_unmap (outbuffer, &map);
580 cleanup_volume (volume);
586 GST_START_TEST (test_mute_s16)
590 GstBuffer *outbuffer;
592 gint16 in[2] = { 16384, -256 };
593 gint16 out[2] = { 0, 0 };
596 volume = setup_volume ();
597 g_object_set (G_OBJECT (volume), "mute", TRUE, NULL);
598 fail_unless (gst_element_set_state (volume,
599 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
600 "could not set to playing");
602 inbuffer = gst_buffer_new_and_alloc (4);
603 gst_buffer_fill (inbuffer, 0, in, 4);
604 caps = gst_caps_from_string (VOLUME_CAPS_STRING_S16);
605 gst_pad_set_caps (mysrcpad, caps);
606 gst_caps_unref (caps);
607 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
608 /* FIXME: reffing the inbuffer should make the transformation not be
610 gst_buffer_ref (inbuffer);
613 /* pushing gives away my reference ... */
614 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
615 /* ... but it ends up being modified inplace and
616 * collected on the global buffer list */
617 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
618 fail_unless_equals_int (g_list_length (buffers), 1);
619 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
620 fail_unless (inbuffer == outbuffer);
621 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
622 GST_INFO ("expected %+5d %+5d real %+5d %+5d", out[0], out[1], map.data[0],
624 fail_unless (memcmp (map.data, out, 4) == 0);
625 gst_buffer_unmap (outbuffer, &map);
628 cleanup_volume (volume);
633 #if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
634 #define get_unaligned_i24(_x) ( (((guint8*)_x)[0]) | ((((guint8*)_x)[1]) << 8) | ((((gint8*)_x)[2]) << 16) )
635 #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)
636 #else /* BIG ENDIAN */
637 #define get_unaligned_i24(_x) ( (((guint8*)_x)[2]) | ((((guint8*)_x)[1]) << 8) | ((((gint8*)_x)[0]) << 16) )
638 #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)
641 GST_START_TEST (test_unity_s24)
644 GstBuffer *inbuffer, *outbuffer;
646 gint32 in_32[2] = { 4194304, -4096 };
651 write_unaligned_u24 (in, in_32[0]);
652 write_unaligned_u24 (in + 3, in_32[1]);
654 volume = setup_volume ();
655 fail_unless (gst_element_set_state (volume,
656 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
657 "could not set to playing");
659 inbuffer = gst_buffer_new_and_alloc (6);
660 gst_buffer_fill (inbuffer, 0, in, 6);
661 caps = gst_caps_from_string (VOLUME_CAPS_STRING_S24);
662 gst_pad_set_caps (mysrcpad, caps);
663 gst_caps_unref (caps);
664 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
666 /* pushing gives away my reference ... */
667 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
668 /* ... but it ends up being collected on the global buffer list */
669 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
670 fail_unless_equals_int (g_list_length (buffers), 1);
671 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
672 fail_unless (inbuffer == outbuffer);
673 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
675 res_32[0] = get_unaligned_i24 (map.data);
676 res_32[1] = get_unaligned_i24 ((map.data + 3));
678 GST_INFO ("expected %+5d %+5d real %+5d %+5d", in_32[0], in_32[1], res_32[0],
680 fail_unless (memcmp (map.data, in, 6) == 0);
681 gst_buffer_unmap (outbuffer, &map);
684 cleanup_volume (volume);
689 GST_START_TEST (test_half_s24)
693 GstBuffer *outbuffer;
695 gint32 in_32[2] = { 4194304, -4096 };
699 gint32 out_32[2] = { 2097152, -2048 };
701 write_unaligned_u24 (in, in_32[0]);
702 write_unaligned_u24 (in + 3, in_32[1]);
704 volume = setup_volume ();
705 g_object_set (G_OBJECT (volume), "volume", 0.5, NULL);
706 fail_unless (gst_element_set_state (volume,
707 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
708 "could not set to playing");
710 inbuffer = gst_buffer_new_and_alloc (6);
711 gst_buffer_fill (inbuffer, 0, in, 6);
712 caps = gst_caps_from_string (VOLUME_CAPS_STRING_S24);
713 gst_pad_set_caps (mysrcpad, caps);
714 gst_caps_unref (caps);
715 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
716 /* FIXME: reffing the inbuffer should make the transformation not be
718 gst_buffer_ref (inbuffer);
721 /* pushing gives away my reference ... */
722 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
723 /* ... but it ends up being modified inplace and
724 * collected on the global buffer list */
725 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
726 fail_unless_equals_int (g_list_length (buffers), 1);
727 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
728 fail_unless (inbuffer == outbuffer);
729 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
731 res_32[0] = get_unaligned_i24 (map.data);
732 res_32[1] = get_unaligned_i24 ((map.data + 3));
734 GST_INFO ("expected %+5d %+5d real %+5d %+5d", out_32[0], out_32[1],
735 res_32[0], res_32[1]);
736 fail_unless (memcmp (res_32, out_32, 8) == 0);
737 gst_buffer_unmap (outbuffer, &map);
740 cleanup_volume (volume);
745 GST_START_TEST (test_double_s24)
749 GstBuffer *outbuffer;
751 gint32 in_32[2] = { 4194304, -4096 };
755 gint32 out_32[2] = { 8388607, -8192 }; /* notice the clamped sample */
757 write_unaligned_u24 (in, in_32[0]);
758 write_unaligned_u24 (in + 3, in_32[1]);
760 volume = setup_volume ();
761 g_object_set (G_OBJECT (volume), "volume", 2.0, NULL);
762 fail_unless (gst_element_set_state (volume,
763 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
764 "could not set to playing");
766 inbuffer = gst_buffer_new_and_alloc (6);
767 gst_buffer_fill (inbuffer, 0, in, 6);
768 caps = gst_caps_from_string (VOLUME_CAPS_STRING_S24);
769 gst_pad_set_caps (mysrcpad, caps);
770 gst_caps_unref (caps);
771 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
772 /* FIXME: reffing the inbuffer should make the transformation not be
774 gst_buffer_ref (inbuffer);
777 /* pushing gives away my reference ... */
778 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
779 /* ... but it ends up being modified inplace and
780 * collected on the global buffer list */
781 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
782 fail_unless_equals_int (g_list_length (buffers), 1);
783 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
784 fail_unless (inbuffer == outbuffer);
785 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
787 res_32[0] = get_unaligned_i24 (map.data);
788 res_32[1] = get_unaligned_i24 ((map.data + 3));
790 GST_INFO ("expected %+5d %+5d real %+5d %+5d", out_32[0], out_32[1],
791 res_32[0], res_32[1]);
792 fail_unless (memcmp (res_32, out_32, 8) == 0);
793 gst_buffer_unmap (outbuffer, &map);
796 cleanup_volume (volume);
801 GST_START_TEST (test_ten_s24)
805 GstBuffer *outbuffer;
807 gint32 in_32[2] = { 4194304, -10 };
811 gint32 out_32[2] = { 8388607, -100 }; /* notice the clamped sample */
813 write_unaligned_u24 (in, in_32[0]);
814 write_unaligned_u24 (in + 3, in_32[1]);
816 volume = setup_volume ();
817 g_object_set (G_OBJECT (volume), "volume", 10.0, NULL);
818 fail_unless (gst_element_set_state (volume,
819 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
820 "could not set to playing");
822 inbuffer = gst_buffer_new_and_alloc (6);
823 gst_buffer_fill (inbuffer, 0, in, 6);
824 fail_unless (gst_buffer_memcmp (inbuffer, 0, in, 6) == 0);
825 caps = gst_caps_from_string (VOLUME_CAPS_STRING_S24);
826 gst_pad_set_caps (mysrcpad, caps);
827 gst_caps_unref (caps);
828 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
829 /* FIXME: reffing the inbuffer should make the transformation not be
831 gst_buffer_ref (inbuffer);
834 /* pushing gives away my reference ... */
835 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
836 /* ... but it ends up being modified inplace and
837 * collected on the global buffer list */
838 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
839 fail_unless_equals_int (g_list_length (buffers), 1);
840 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
841 fail_unless (inbuffer == outbuffer);
842 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
844 res_32[0] = get_unaligned_i24 (map.data);
845 res_32[1] = get_unaligned_i24 ((map.data + 3));
847 GST_INFO ("expected %+5d %+5d real %+5d %+5d", out_32[0], out_32[1],
848 res_32[0], res_32[1]);
849 fail_unless (memcmp (res_32, out_32, 8) == 0);
850 gst_buffer_unmap (outbuffer, &map);
853 cleanup_volume (volume);
858 GST_START_TEST (test_mute_s24)
862 GstBuffer *outbuffer;
864 gint32 in_32[2] = { 4194304, -4096 };
868 gint32 out_32[2] = { 0, 0 }; /* notice the clamped sample */
870 write_unaligned_u24 (in, in_32[0]);
871 write_unaligned_u24 (in + 3, in_32[1]);
873 volume = setup_volume ();
874 g_object_set (G_OBJECT (volume), "mute", TRUE, NULL);
875 fail_unless (gst_element_set_state (volume,
876 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
877 "could not set to playing");
879 inbuffer = gst_buffer_new_and_alloc (6);
880 gst_buffer_fill (inbuffer, 0, in, 6);
881 caps = gst_caps_from_string (VOLUME_CAPS_STRING_S24);
882 gst_pad_set_caps (mysrcpad, caps);
883 gst_caps_unref (caps);
884 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
885 /* FIXME: reffing the inbuffer should make the transformation not be
887 gst_buffer_ref (inbuffer);
890 /* pushing gives away my reference ... */
891 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
892 /* ... but it ends up being modified inplace and
893 * collected on the global buffer list */
894 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
895 fail_unless_equals_int (g_list_length (buffers), 1);
896 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
897 fail_unless (inbuffer == outbuffer);
899 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
901 res_32[0] = get_unaligned_i24 (map.data);
902 res_32[1] = get_unaligned_i24 ((map.data + 3));
904 GST_INFO ("expected %+5d %+5d real %+5d %+5d", out_32[0], out_32[1],
905 res_32[0], res_32[1]);
906 fail_unless (memcmp (res_32, out_32, 8) == 0);
907 gst_buffer_unmap (outbuffer, &map);
910 cleanup_volume (volume);
915 GST_START_TEST (test_unity_s32)
918 GstBuffer *inbuffer, *outbuffer;
920 gint32 in[2] = { 1073741824, -65536 };
923 volume = setup_volume ();
924 fail_unless (gst_element_set_state (volume,
925 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
926 "could not set to playing");
928 inbuffer = gst_buffer_new_and_alloc (8);
929 gst_buffer_fill (inbuffer, 0, in, 8);
930 caps = gst_caps_from_string (VOLUME_CAPS_STRING_S32);
931 gst_pad_set_caps (mysrcpad, caps);
932 gst_caps_unref (caps);
933 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
935 /* pushing gives away my reference ... */
936 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
937 /* ... but it ends up being collected on the global buffer list */
938 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
939 fail_unless_equals_int (g_list_length (buffers), 1);
940 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
941 fail_unless (inbuffer == outbuffer);
942 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
943 GST_INFO ("expected %+5d %+5d real %+5d %+5d", in[0], in[1], map.data[0],
945 fail_unless (memcmp (map.data, in, 8) == 0);
946 gst_buffer_unmap (outbuffer, &map);
949 cleanup_volume (volume);
954 GST_START_TEST (test_half_s32)
958 GstBuffer *outbuffer;
960 gint32 in[2] = { 1073741824, -65536 };
961 gint32 out[2] = { 536870912, -32768 };
964 volume = setup_volume ();
965 g_object_set (G_OBJECT (volume), "volume", 0.5, NULL);
966 fail_unless (gst_element_set_state (volume,
967 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
968 "could not set to playing");
970 inbuffer = gst_buffer_new_and_alloc (8);
971 gst_buffer_fill (inbuffer, 0, in, 8);
972 caps = gst_caps_from_string (VOLUME_CAPS_STRING_S32);
973 gst_pad_set_caps (mysrcpad, caps);
974 gst_caps_unref (caps);
975 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
976 /* FIXME: reffing the inbuffer should make the transformation not be
978 gst_buffer_ref (inbuffer);
981 /* pushing gives away my reference ... */
982 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
983 /* ... but it ends up being modified inplace and
984 * collected on the global buffer list */
985 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
986 fail_unless_equals_int (g_list_length (buffers), 1);
987 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
988 fail_unless (inbuffer == outbuffer);
989 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
990 GST_INFO ("expected %+5d %+5d real %+5d %+5d", out[0], out[1], map.data[0],
992 fail_unless (memcmp (map.data, out, 8) == 0);
993 gst_buffer_unmap (outbuffer, &map);
996 cleanup_volume (volume);
1001 GST_START_TEST (test_double_s32)
1004 GstBuffer *inbuffer;
1005 GstBuffer *outbuffer;
1007 gint32 in[2] = { 1073741824, -65536 };
1008 gint32 out[2] = { 2147483647, -131072 }; /* notice the clamped sample */
1011 volume = setup_volume ();
1012 g_object_set (G_OBJECT (volume), "volume", 2.0, NULL);
1013 fail_unless (gst_element_set_state (volume,
1014 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
1015 "could not set to playing");
1017 inbuffer = gst_buffer_new_and_alloc (8);
1018 gst_buffer_fill (inbuffer, 0, in, 8);
1019 caps = gst_caps_from_string (VOLUME_CAPS_STRING_S32);
1020 gst_pad_set_caps (mysrcpad, caps);
1021 gst_caps_unref (caps);
1022 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1023 /* FIXME: reffing the inbuffer should make the transformation not be
1025 gst_buffer_ref (inbuffer);
1028 /* pushing gives away my reference ... */
1029 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
1030 /* ... but it ends up being modified inplace and
1031 * collected on the global buffer list */
1032 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1033 fail_unless_equals_int (g_list_length (buffers), 1);
1034 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
1035 fail_unless (inbuffer == outbuffer);
1036 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
1037 GST_INFO ("expected %+5d %+5d real %+5d %+5d", out[0], out[1], map.data[0],
1039 fail_unless (memcmp (map.data, out, 8) == 0);
1040 gst_buffer_unmap (outbuffer, &map);
1043 cleanup_volume (volume);
1048 GST_START_TEST (test_ten_s32)
1051 GstBuffer *inbuffer;
1052 GstBuffer *outbuffer;
1054 gint32 in[2] = { 1073741824, -10 };
1055 gint32 out[2] = { 2147483647, -100 }; /* notice the clamped sample */
1058 volume = setup_volume ();
1059 g_object_set (G_OBJECT (volume), "volume", 10.0, NULL);
1060 fail_unless (gst_element_set_state (volume,
1061 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
1062 "could not set to playing");
1064 inbuffer = gst_buffer_new_and_alloc (8);
1065 gst_buffer_fill (inbuffer, 0, in, 8);
1066 fail_unless (gst_buffer_memcmp (inbuffer, 0, in, 8) == 0);
1067 caps = gst_caps_from_string (VOLUME_CAPS_STRING_S32);
1068 gst_pad_set_caps (mysrcpad, caps);
1069 gst_caps_unref (caps);
1070 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1071 /* FIXME: reffing the inbuffer should make the transformation not be
1073 gst_buffer_ref (inbuffer);
1076 /* pushing gives away my reference ... */
1077 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
1078 /* ... but it ends up being modified inplace and
1079 * collected on the global buffer list */
1080 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1081 fail_unless_equals_int (g_list_length (buffers), 1);
1082 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
1083 fail_unless (inbuffer == outbuffer);
1084 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
1085 GST_INFO ("expected %+5d %+5d real %+5d %+5d", out[0], out[1], map.data[0],
1087 fail_unless (memcmp (map.data, out, 8) == 0);
1088 gst_buffer_unmap (outbuffer, &map);
1091 cleanup_volume (volume);
1096 GST_START_TEST (test_mute_s32)
1099 GstBuffer *inbuffer;
1100 GstBuffer *outbuffer;
1102 gint32 in[2] = { 1073741824, -65536 };
1103 gint32 out[2] = { 0, 0 };
1106 volume = setup_volume ();
1107 g_object_set (G_OBJECT (volume), "mute", TRUE, NULL);
1108 fail_unless (gst_element_set_state (volume,
1109 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
1110 "could not set to playing");
1112 inbuffer = gst_buffer_new_and_alloc (8);
1113 gst_buffer_fill (inbuffer, 0, in, 8);
1114 caps = gst_caps_from_string (VOLUME_CAPS_STRING_S32);
1115 gst_pad_set_caps (mysrcpad, caps);
1116 gst_caps_unref (caps);
1117 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1118 /* FIXME: reffing the inbuffer should make the transformation not be
1120 gst_buffer_ref (inbuffer);
1123 /* pushing gives away my reference ... */
1124 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
1125 /* ... but it ends up being modified inplace and
1126 * collected on the global buffer list */
1127 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1128 fail_unless_equals_int (g_list_length (buffers), 1);
1129 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
1130 fail_unless (inbuffer == outbuffer);
1131 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
1132 GST_INFO ("expected %+5d %+5d real %+5d %+5d", out[0], out[1], map.data[0],
1134 fail_unless (memcmp (map.data, out, 8) == 0);
1135 gst_buffer_unmap (outbuffer, &map);
1138 cleanup_volume (volume);
1143 GST_START_TEST (test_unity_f32)
1146 GstBuffer *inbuffer, *outbuffer;
1148 gfloat in[2] = { 0.75, -0.25 };
1151 volume = setup_volume ();
1152 fail_unless (gst_element_set_state (volume,
1153 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
1154 "could not set to playing");
1156 inbuffer = gst_buffer_new_and_alloc (8);
1157 gst_buffer_fill (inbuffer, 0, in, 8);
1158 caps = gst_caps_from_string (VOLUME_CAPS_STRING_F32);
1159 gst_pad_set_caps (mysrcpad, caps);
1160 gst_caps_unref (caps);
1161 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1163 /* pushing gives away my reference ... */
1164 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
1165 /* ... but it ends up being collected on the global buffer list */
1166 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1167 fail_unless_equals_int (g_list_length (buffers), 1);
1168 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
1169 fail_unless (inbuffer == outbuffer);
1170 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
1171 GST_INFO ("expected %+1.4f %+1.4f real %+1.4f %+1.4f", in[0], in[1],
1172 map.data[0], map.data[1]);
1173 fail_unless_equals_float (map.data[0], in[0]);
1174 fail_unless_equals_float (map.data[1], in[1]);
1177 cleanup_volume (volume);
1182 GST_START_TEST (test_half_f32)
1185 GstBuffer *inbuffer;
1186 GstBuffer *outbuffer;
1188 gfloat in[2] = { 0.75, -0.25 };
1189 gfloat out[2] = { 0.375, -0.125 };
1192 volume = setup_volume ();
1193 g_object_set (G_OBJECT (volume), "volume", 0.5, NULL);
1194 fail_unless (gst_element_set_state (volume,
1195 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
1196 "could not set to playing");
1198 inbuffer = gst_buffer_new_and_alloc (8);
1199 gst_buffer_fill (inbuffer, 0, in, 8);
1200 caps = gst_caps_from_string (VOLUME_CAPS_STRING_F32);
1201 gst_pad_set_caps (mysrcpad, caps);
1202 gst_caps_unref (caps);
1203 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1204 /* FIXME: reffing the inbuffer should make the transformation not be
1206 gst_buffer_ref (inbuffer);
1209 /* pushing gives away my reference ... */
1210 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
1211 /* ... but it ends up being modified inplace and
1212 * collected on the global buffer list */
1213 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1214 fail_unless_equals_int (g_list_length (buffers), 1);
1215 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
1216 fail_unless (inbuffer == outbuffer);
1217 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
1218 GST_INFO ("expected %+1.4f %+1.4f real %+1.4f %+1.4f", out[0], out[1],
1219 map.data[0], map.data[1]);
1220 fail_unless_equals_float (map.data[0], out[0]);
1221 fail_unless_equals_float (map.data[1], out[1]);
1222 gst_buffer_unmap (outbuffer, &map);
1225 cleanup_volume (volume);
1230 GST_START_TEST (test_double_f32)
1233 GstBuffer *inbuffer;
1234 GstBuffer *outbuffer;
1236 gfloat in[2] = { 0.75, -0.25 };
1237 gfloat out[2] = { 1.5, -0.5 }; /* nothing is clamped */
1240 volume = setup_volume ();
1241 g_object_set (G_OBJECT (volume), "volume", 2.0, NULL);
1242 fail_unless (gst_element_set_state (volume,
1243 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
1244 "could not set to playing");
1246 inbuffer = gst_buffer_new_and_alloc (8);
1247 gst_buffer_fill (inbuffer, 0, in, 8);
1248 caps = gst_caps_from_string (VOLUME_CAPS_STRING_F32);
1249 gst_pad_set_caps (mysrcpad, caps);
1250 gst_caps_unref (caps);
1251 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1252 /* FIXME: reffing the inbuffer should make the transformation not be
1254 gst_buffer_ref (inbuffer);
1257 /* pushing gives away my reference ... */
1258 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
1259 /* ... but it ends up being modified inplace and
1260 * collected on the global buffer list */
1261 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1262 fail_unless_equals_int (g_list_length (buffers), 1);
1263 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
1264 fail_unless (inbuffer == outbuffer);
1265 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
1266 GST_INFO ("expected %+1.4f %+1.4f real %+1.4f %+1.4f", out[0], out[1],
1267 map.data[0], map.data[1]);
1268 fail_unless_equals_float (map.data[0], out[0]);
1269 fail_unless_equals_float (map.data[1], out[1]);
1270 gst_buffer_unmap (outbuffer, &map);
1273 cleanup_volume (volume);
1278 GST_START_TEST (test_ten_f32)
1281 GstBuffer *inbuffer;
1282 GstBuffer *outbuffer;
1284 gfloat in[2] = { 0.75, -0.25 };
1285 gfloat out[2] = { 7.5, -2.5 }; /* nothing is clamped */
1288 volume = setup_volume ();
1289 g_object_set (G_OBJECT (volume), "volume", 10.0, NULL);
1290 fail_unless (gst_element_set_state (volume,
1291 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
1292 "could not set to playing");
1294 inbuffer = gst_buffer_new_and_alloc (8);
1295 gst_buffer_fill (inbuffer, 0, in, 8);
1296 fail_unless (gst_buffer_memcmp (inbuffer, 0, in, 8) == 0);
1297 caps = gst_caps_from_string (VOLUME_CAPS_STRING_F32);
1298 gst_pad_set_caps (mysrcpad, caps);
1299 gst_caps_unref (caps);
1300 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1301 /* FIXME: reffing the inbuffer should make the transformation not be
1303 gst_buffer_ref (inbuffer);
1306 /* pushing gives away my reference ... */
1307 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
1308 /* ... but it ends up being modified inplace and
1309 * collected on the global buffer list */
1310 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1311 fail_unless_equals_int (g_list_length (buffers), 1);
1312 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
1313 fail_unless (inbuffer == outbuffer);
1314 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
1315 GST_INFO ("expected %+1.4f %+1.4f real %+1.4f %+1.4f", out[0], out[1],
1316 map.data[0], map.data[1]);
1317 fail_unless_equals_float (map.data[0], out[0]);
1318 fail_unless_equals_float (map.data[1], out[1]);
1319 gst_buffer_unmap (outbuffer, &map);
1322 cleanup_volume (volume);
1328 GST_START_TEST (test_mute_f32)
1331 GstBuffer *inbuffer;
1332 GstBuffer *outbuffer;
1334 gfloat in[2] = { 0.75, -0.25 };
1335 gfloat out[2] = { 0, 0 };
1338 volume = setup_volume ();
1339 g_object_set (G_OBJECT (volume), "mute", TRUE, NULL);
1340 fail_unless (gst_element_set_state (volume,
1341 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
1342 "could not set to playing");
1344 inbuffer = gst_buffer_new_and_alloc (8);
1345 gst_buffer_fill (inbuffer, 0, in, 8);
1346 caps = gst_caps_from_string (VOLUME_CAPS_STRING_F32);
1347 gst_pad_set_caps (mysrcpad, caps);
1348 gst_caps_unref (caps);
1349 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1350 /* FIXME: reffing the inbuffer should make the transformation not be
1352 gst_buffer_ref (inbuffer);
1355 /* pushing gives away my reference ... */
1356 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
1357 /* ... but it ends up being modified inplace and
1358 * collected on the global buffer list */
1359 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1360 fail_unless_equals_int (g_list_length (buffers), 1);
1361 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
1362 fail_unless (inbuffer == outbuffer);
1363 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
1364 GST_INFO ("expected %+1.4f %+1.4f real %+1.4f %+1.4f", out[0], out[1],
1365 map.data[0], map.data[1]);
1366 fail_unless_equals_float (map.data[0], out[0]);
1367 fail_unless_equals_float (map.data[1], out[1]);
1368 gst_buffer_unmap (outbuffer, &map);
1371 cleanup_volume (volume);
1376 GST_START_TEST (test_unity_f64)
1379 GstBuffer *inbuffer, *outbuffer;
1381 gdouble in[2] = { 0.75, -0.25 };
1384 volume = setup_volume ();
1385 fail_unless (gst_element_set_state (volume,
1386 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
1387 "could not set to playing");
1389 inbuffer = gst_buffer_new_and_alloc (16);
1390 gst_buffer_fill (inbuffer, 0, in, 16);
1391 caps = gst_caps_from_string (VOLUME_CAPS_STRING_F64);
1392 gst_pad_set_caps (mysrcpad, caps);
1393 gst_caps_unref (caps);
1394 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1396 /* pushing gives away my reference ... */
1397 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
1398 /* ... but it ends up being collected on the global buffer list */
1399 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1400 fail_unless_equals_int (g_list_length (buffers), 1);
1401 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
1402 fail_unless (inbuffer == outbuffer);
1403 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
1404 GST_INFO ("expected %+1.4f %+1.4f real %+1.4f %+1.4f", in[0], in[1],
1405 map.data[0], map.data[1]);
1406 fail_unless_equals_float (map.data[0], in[0]);
1407 fail_unless_equals_float (map.data[1], in[1]);
1410 cleanup_volume (volume);
1415 GST_START_TEST (test_half_f64)
1418 GstBuffer *inbuffer;
1419 GstBuffer *outbuffer;
1421 gdouble in[2] = { 0.75, -0.25 };
1422 gdouble out[2] = { 0.375, -0.125 };
1425 volume = setup_volume ();
1426 g_object_set (G_OBJECT (volume), "volume", 0.5, NULL);
1427 fail_unless (gst_element_set_state (volume,
1428 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
1429 "could not set to playing");
1431 inbuffer = gst_buffer_new_and_alloc (16);
1432 gst_buffer_fill (inbuffer, 0, in, 16);
1433 caps = gst_caps_from_string (VOLUME_CAPS_STRING_F64);
1434 gst_pad_set_caps (mysrcpad, caps);
1435 gst_caps_unref (caps);
1436 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1437 /* FIXME: reffing the inbuffer should make the transformation not be
1439 gst_buffer_ref (inbuffer);
1442 /* pushing gives away my reference ... */
1443 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
1444 /* ... but it ends up being modified inplace and
1445 * collected on the global buffer list */
1446 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1447 fail_unless_equals_int (g_list_length (buffers), 1);
1448 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
1449 fail_unless (inbuffer == outbuffer);
1450 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
1451 GST_INFO ("expected %+1.4f %+1.4f real %+1.4f %+1.4f", out[0], out[1],
1452 map.data[0], map.data[1]);
1453 fail_unless_equals_float (map.data[0], out[0]);
1454 fail_unless_equals_float (map.data[1], out[1]);
1455 gst_buffer_unmap (outbuffer, &map);
1458 cleanup_volume (volume);
1463 GST_START_TEST (test_double_f64)
1466 GstBuffer *inbuffer;
1467 GstBuffer *outbuffer;
1469 gdouble in[2] = { 0.75, -0.25 };
1470 gdouble out[2] = { 1.5, -0.5 }; /* nothing is clamped */
1473 volume = setup_volume ();
1474 g_object_set (G_OBJECT (volume), "volume", 2.0, NULL);
1475 fail_unless (gst_element_set_state (volume,
1476 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
1477 "could not set to playing");
1479 inbuffer = gst_buffer_new_and_alloc (16);
1480 gst_buffer_fill (inbuffer, 0, in, 16);
1481 caps = gst_caps_from_string (VOLUME_CAPS_STRING_F64);
1482 gst_pad_set_caps (mysrcpad, caps);
1483 gst_caps_unref (caps);
1484 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1485 /* FIXME: reffing the inbuffer should make the transformation not be
1487 gst_buffer_ref (inbuffer);
1490 /* pushing gives away my reference ... */
1491 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
1492 /* ... but it ends up being modified inplace and
1493 * collected on the global buffer list */
1494 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1495 fail_unless_equals_int (g_list_length (buffers), 1);
1496 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
1497 fail_unless (inbuffer == outbuffer);
1498 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
1499 GST_INFO ("expected %+1.4f %+1.4f real %+1.4f %+1.4f", out[0], out[1],
1500 map.data[0], map.data[1]);
1501 fail_unless_equals_float (map.data[0], out[0]);
1502 fail_unless_equals_float (map.data[1], out[1]);
1503 gst_buffer_unmap (outbuffer, &map);
1506 cleanup_volume (volume);
1511 GST_START_TEST (test_ten_f64)
1514 GstBuffer *inbuffer;
1515 GstBuffer *outbuffer;
1517 gdouble in[2] = { 0.75, -0.25 };
1518 gdouble out[2] = { 7.5, -2.5 }; /* nothing is clamped */
1521 volume = setup_volume ();
1522 g_object_set (G_OBJECT (volume), "volume", 10.0, NULL);
1523 fail_unless (gst_element_set_state (volume,
1524 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
1525 "could not set to playing");
1527 inbuffer = gst_buffer_new_and_alloc (16);
1528 gst_buffer_fill (inbuffer, 0, in, 16);
1529 fail_unless (gst_buffer_memcmp (inbuffer, 0, in, 16) == 0);
1530 caps = gst_caps_from_string (VOLUME_CAPS_STRING_F64);
1531 gst_pad_set_caps (mysrcpad, caps);
1532 gst_caps_unref (caps);
1533 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1534 /* FIXME: reffing the inbuffer should make the transformation not be
1536 gst_buffer_ref (inbuffer);
1539 /* pushing gives away my reference ... */
1540 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
1541 /* ... but it ends up being modified inplace and
1542 * collected on the global buffer list */
1543 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1544 fail_unless_equals_int (g_list_length (buffers), 1);
1545 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
1546 fail_unless (inbuffer == outbuffer);
1547 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
1548 GST_INFO ("expected %+1.4f %+1.4f real %+1.4f %+1.4f", out[0], out[1],
1549 map.data[0], map.data[1]);
1550 fail_unless_equals_float (map.data[0], out[0]);
1551 fail_unless_equals_float (map.data[1], out[1]);
1552 gst_buffer_unmap (outbuffer, &map);
1555 cleanup_volume (volume);
1561 GST_START_TEST (test_mute_f64)
1564 GstBuffer *inbuffer;
1565 GstBuffer *outbuffer;
1567 gdouble in[2] = { 0.75, -0.25 };
1568 gdouble out[2] = { 0, 0 };
1571 volume = setup_volume ();
1572 g_object_set (G_OBJECT (volume), "mute", TRUE, NULL);
1573 fail_unless (gst_element_set_state (volume,
1574 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
1575 "could not set to playing");
1577 inbuffer = gst_buffer_new_and_alloc (16);
1578 gst_buffer_fill (inbuffer, 0, in, 16);
1579 caps = gst_caps_from_string (VOLUME_CAPS_STRING_F64);
1580 gst_pad_set_caps (mysrcpad, caps);
1581 gst_caps_unref (caps);
1582 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1583 /* FIXME: reffing the inbuffer should make the transformation not be
1585 gst_buffer_ref (inbuffer);
1588 /* pushing gives away my reference ... */
1589 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
1590 /* ... but it ends up being modified inplace and
1591 * collected on the global buffer list */
1592 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1593 fail_unless_equals_int (g_list_length (buffers), 1);
1594 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
1595 fail_unless (inbuffer == outbuffer);
1596 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
1597 GST_INFO ("expected %+1.4f %+1.4f real %+1.4f %+1.4f", out[0], out[1],
1598 map.data[0], map.data[1]);
1599 fail_unless_equals_float (map.data[0], out[0]);
1600 fail_unless_equals_float (map.data[1], out[1]);
1601 gst_buffer_unmap (outbuffer, &map);
1604 cleanup_volume (volume);
1609 GST_START_TEST (test_wrong_caps)
1612 GstBuffer *inbuffer;
1613 gint16 in[2] = { 16384, -256 };
1615 GstMessage *message;
1618 volume = setup_volume ();
1619 bus = gst_bus_new ();
1621 fail_unless (gst_element_set_state (volume,
1622 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
1623 "could not set to playing");
1625 inbuffer = gst_buffer_new_and_alloc (4);
1626 gst_buffer_fill (inbuffer, 0, in, 4);
1627 caps = gst_caps_from_string (VOLUME_WRONG_CAPS_STRING);
1628 gst_pad_set_caps (mysrcpad, caps);
1629 gst_caps_unref (caps);
1630 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1631 gst_buffer_ref (inbuffer);
1633 /* set a bus here so we avoid getting state change messages */
1634 gst_element_set_bus (volume, bus);
1636 /* pushing gives an error because it can't negotiate with wrong caps */
1637 fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer),
1638 GST_FLOW_NOT_NEGOTIATED);
1639 /* ... and the buffer would have been lost if we didn't ref it ourselves */
1640 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1641 gst_buffer_unref (inbuffer);
1642 fail_unless_equals_int (g_list_length (buffers), 0);
1644 /* volume_set_caps should not have been called since basetransform caught
1645 * the negotiation problem */
1646 fail_if ((message = gst_bus_pop (bus)) != NULL);
1649 gst_element_set_bus (volume, NULL);
1650 gst_object_unref (GST_OBJECT (bus));
1651 cleanup_volume (volume);
1656 GST_START_TEST (test_passthrough)
1659 GstBuffer *inbuffer, *outbuffer;
1661 gint16 in[2] = { 16384, -256 };
1664 volume = setup_volume ();
1665 g_object_set (G_OBJECT (volume), "volume", 1.0, NULL);
1666 fail_unless (gst_element_set_state (volume,
1667 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
1668 "could not set to playing");
1670 inbuffer = gst_buffer_new_and_alloc (4);
1671 gst_buffer_fill (inbuffer, 0, in, 4);
1672 caps = gst_caps_from_string (VOLUME_CAPS_STRING_S16);
1673 gst_pad_set_caps (mysrcpad, caps);
1674 gst_caps_unref (caps);
1675 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1677 /* pushing gives away my reference ... */
1678 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
1679 /* ... but it ends up being collected on the global buffer list */
1680 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1681 fail_unless_equals_int (g_list_length (buffers), 1);
1682 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
1683 fail_unless (inbuffer == outbuffer);
1684 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
1685 GST_INFO ("expected %+5d %+5d real %+5d %+5d", in[0], in[1], map.data[0],
1687 fail_unless (memcmp (map.data, in, 4) == 0);
1688 gst_buffer_unmap (outbuffer, &map);
1691 cleanup_volume (volume);
1696 GST_START_TEST (test_controller_usability)
1698 GstInterpolationControlSource *csource;
1699 GstTimedValueControlSource *cs;
1702 volume = setup_volume ();
1704 /* this shouldn't crash, whether this mode is implemented or not */
1705 csource = gst_interpolation_control_source_new ();
1706 g_object_set (csource, "mode", GST_INTERPOLATION_MODE_CUBIC, NULL);
1707 gst_object_add_control_binding (GST_OBJECT_CAST (volume),
1708 gst_direct_control_binding_new (GST_OBJECT_CAST (volume), "volume",
1709 GST_CONTROL_SOURCE (csource)));
1711 cs = (GstTimedValueControlSource *) csource;
1712 gst_timed_value_control_source_set (cs, 0 * GST_SECOND, 0.0);
1713 gst_timed_value_control_source_set (cs, 5 * GST_SECOND, 1.0);
1714 gst_timed_value_control_source_set (cs, 10 * GST_SECOND, 0.0);
1716 gst_object_unref (csource);
1718 cleanup_volume (volume);
1723 GST_START_TEST (test_controller_processing)
1725 GstInterpolationControlSource *csource;
1727 GstBuffer *inbuffer, *outbuffer;
1729 gint16 in[2] = { 16384, -256 };
1732 volume = setup_volume ();
1734 csource = gst_interpolation_control_source_new ();
1735 g_object_set (csource, "mode", GST_INTERPOLATION_MODE_CUBIC, NULL);
1736 gst_object_add_control_binding (GST_OBJECT_CAST (volume),
1737 gst_direct_control_binding_new (GST_OBJECT_CAST (volume), "volume",
1738 GST_CONTROL_SOURCE (csource)));
1740 fail_unless (gst_element_set_state (volume,
1741 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
1742 "could not set to playing");
1744 inbuffer = gst_buffer_new_and_alloc (4);
1745 gst_buffer_fill (inbuffer, 0, in, 4);
1746 caps = gst_caps_from_string (VOLUME_CAPS_STRING_S16);
1747 gst_pad_set_caps (mysrcpad, caps);
1748 GST_BUFFER_TIMESTAMP (inbuffer) = 0;
1749 gst_caps_unref (caps);
1750 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1752 /* pushing gives away my reference ... */
1753 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
1754 /* ... but it ends up being collected on the global buffer list */
1755 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
1756 fail_unless_equals_int (g_list_length (buffers), 1);
1757 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
1758 fail_unless (inbuffer == outbuffer);
1759 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
1760 GST_INFO ("expected %+5d %+5d real %+5d %+5d", in[0], in[1], map.data[0],
1762 fail_unless (memcmp (map.data, in, 4) == 0);
1763 gst_buffer_unmap (outbuffer, &map);
1765 gst_object_unref (csource);
1766 cleanup_volume (volume);
1774 Suite *s = suite_create ("volume");
1775 TCase *tc_chain = tcase_create ("general");
1777 suite_add_tcase (s, tc_chain);
1778 tcase_add_test (tc_chain, test_get_set);
1779 tcase_add_test (tc_chain, test_unity_s8);
1780 tcase_add_test (tc_chain, test_half_s8);
1781 tcase_add_test (tc_chain, test_double_s8);
1782 tcase_add_test (tc_chain, test_ten_s8);
1783 tcase_add_test (tc_chain, test_mute_s8);
1784 tcase_add_test (tc_chain, test_unity_s16);
1785 tcase_add_test (tc_chain, test_half_s16);
1786 tcase_add_test (tc_chain, test_double_s16);
1787 tcase_add_test (tc_chain, test_ten_s16);
1788 tcase_add_test (tc_chain, test_mute_s16);
1789 tcase_add_test (tc_chain, test_unity_s24);
1790 tcase_add_test (tc_chain, test_half_s24);
1791 tcase_add_test (tc_chain, test_double_s24);
1792 tcase_add_test (tc_chain, test_ten_s24);
1793 tcase_add_test (tc_chain, test_mute_s24);
1794 tcase_add_test (tc_chain, test_unity_s32);
1795 tcase_add_test (tc_chain, test_half_s32);
1796 tcase_add_test (tc_chain, test_double_s32);
1797 tcase_add_test (tc_chain, test_ten_s32);
1798 tcase_add_test (tc_chain, test_mute_s32);
1799 tcase_add_test (tc_chain, test_unity_f32);
1800 tcase_add_test (tc_chain, test_half_f32);
1801 tcase_add_test (tc_chain, test_double_f32);
1802 tcase_add_test (tc_chain, test_ten_f32);
1803 tcase_add_test (tc_chain, test_mute_f32);
1804 tcase_add_test (tc_chain, test_unity_f64);
1805 tcase_add_test (tc_chain, test_half_f64);
1806 tcase_add_test (tc_chain, test_double_f64);
1807 tcase_add_test (tc_chain, test_ten_f64);
1808 tcase_add_test (tc_chain, test_mute_f64);
1809 tcase_add_test (tc_chain, test_wrong_caps);
1810 tcase_add_test (tc_chain, test_passthrough);
1811 tcase_add_test (tc_chain, test_controller_usability);
1812 tcase_add_test (tc_chain, test_controller_processing);
1817 GST_CHECK_MAIN (volume)