1 /* GStreamer ReplayGain volume adjustment
2 *
3 * Copyright (C) 2007 Rene Stadler <mail@renestadler.de>
4 *
5 * rgvolume.c: Unit test for the rgvolume element
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * as published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 */
22
23 #include <gst/check/gstcheck.h>
24 #include <gst/audio/audio.h>
25
26 #include <math.h>
27
28 static GList *events = NULL;
29
30 /* For ease of programming we use globals to keep refs for our floating src and
31 * sink pads we create; otherwise we always have to do get_pad, get_peer, and
32 * then remove references in every test function */
33 static GstPad *mysrcpad, *mysinkpad;
34
35 #define RG_VOLUME_CAPS_TEMPLATE_STRING \
36 "audio/x-raw, " \
37 "format = (string) "GST_AUDIO_NE (F32) ", " \
38 "layout = (string) interleaved, " \
39 "channels = (int) [ 1, MAX ], " \
40 "rate = (int) [ 1, MAX ]"
41
42 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
43 GST_PAD_SINK,
44 GST_PAD_ALWAYS,
45 GST_STATIC_CAPS (RG_VOLUME_CAPS_TEMPLATE_STRING)
46 );
47 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
48 GST_PAD_SRC,
49 GST_PAD_ALWAYS,
50 GST_STATIC_CAPS (RG_VOLUME_CAPS_TEMPLATE_STRING)
51 );
52
53 static GstBuffer *test_buffer_new (gfloat value);
54
55 /* gstcheck sets up a chain function that appends buffers to a global list.
56 * This is our equivalent of that for event handling. */
57 static gboolean
event_func(GstPad * pad,GstObject * parent,GstEvent * event)58 event_func (GstPad * pad, GstObject * parent, GstEvent * event)
59 {
60 GST_DEBUG ("received event %p (%s)", event, GST_EVENT_TYPE_NAME (event));
61 events = g_list_append (events, event);
62
63 return TRUE;
64 }
65
66 static GstElement *
setup_rgvolume(void)67 setup_rgvolume (void)
68 {
69 GstElement *element;
70
71 GST_DEBUG ("setup_rgvolume");
72 element = gst_check_setup_element ("rgvolume");
73 mysrcpad = gst_check_setup_src_pad (element, &srctemplate);
74 mysinkpad = gst_check_setup_sink_pad (element, &sinktemplate);
75
76 /* Capture events, to test tag filtering behavior: */
77 gst_pad_set_event_function (mysinkpad, event_func);
78
79 gst_pad_set_active (mysrcpad, TRUE);
80 gst_pad_set_active (mysinkpad, TRUE);
81
82 return element;
83 }
84
85 static void
send_empty_buffer(void)86 send_empty_buffer (void)
87 {
88 GstBuffer *buf;
89
90 buf = test_buffer_new (0.0);
91 gst_buffer_resize (buf, 0, 0);
92 GST_BUFFER_DURATION (buf) = 0;
93 GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET (buf);
94 fail_unless (gst_pad_push (mysrcpad, buf) == GST_FLOW_OK);
95
96 fail_unless (g_list_length (buffers) == 1);
97 fail_unless (buffers->data == buf);
98 gst_mini_object_unref ((GstMiniObject *) buffers->data);
99 buffers = g_list_remove (buffers, buf);
100 }
101
102 static void
cleanup_rgvolume(GstElement * element)103 cleanup_rgvolume (GstElement * element)
104 {
105 GST_DEBUG ("cleanup_rgvolume");
106
107 g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL);
108 g_list_free (buffers);
109 buffers = NULL;
110
111 g_list_foreach (events, (GFunc) gst_mini_object_unref, NULL);
112 g_list_free (events);
113 events = NULL;
114
115 gst_pad_set_active (mysrcpad, FALSE);
116 gst_pad_set_active (mysinkpad, FALSE);
117 gst_check_teardown_src_pad (element);
118 gst_check_teardown_sink_pad (element);
119 gst_check_teardown_element (element);
120 }
121
122 static void
set_playing_state(GstElement * element)123 set_playing_state (GstElement * element)
124 {
125 fail_unless (gst_element_set_state (element,
126 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
127 "Could not set state to PLAYING");
128 }
129
130 static void
set_null_state(GstElement * element)131 set_null_state (GstElement * element)
132 {
133 fail_unless (gst_element_set_state (element,
134 GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS,
135 "Could not set state to NULL");
136 }
137
138 static void
send_flush_events(GstElement * element)139 send_flush_events (GstElement * element)
140 {
141 gboolean res;
142
143 res = gst_pad_push_event (mysrcpad, gst_event_new_flush_start ());
144 fail_unless (res, "flush-start even not handled");
145
146 res = gst_pad_push_event (mysrcpad, gst_event_new_flush_stop (TRUE));
147 fail_unless (res, "flush-stop event not handled");
148 }
149
150 static void
send_stream_start_event(GstElement * element)151 send_stream_start_event (GstElement * element)
152 {
153 gboolean res;
154
155 res = gst_pad_push_event (mysrcpad, gst_event_new_stream_start ("test"));
156 fail_unless (res, "STREAM_START event not handled");
157 }
158
159 static void
send_caps_event(GstElement * element)160 send_caps_event (GstElement * element)
161 {
162 GstCaps *caps;
163 gboolean res;
164
165 caps = gst_caps_from_string ("audio/x-raw, format = " GST_AUDIO_NE (F32) ", "
166 "layout = interleaved, rate = 8000, channels = 1");
167 res = gst_pad_push_event (mysrcpad, gst_event_new_caps (caps));
168 fail_unless (res, "CAPS event not handled");
169 gst_caps_unref (caps);
170 }
171
172 static void
send_segment_event(GstElement * element)173 send_segment_event (GstElement * element)
174 {
175 GstSegment segment;
176 gboolean res;
177
178 gst_segment_init (&segment, GST_FORMAT_TIME);
179 res = gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment));
180 fail_unless (res, "SEGMENT event not handled");
181 }
182
183 static void
send_eos_event(GstElement * element)184 send_eos_event (GstElement * element)
185 {
186 GstEvent *event = gst_event_new_eos ();
187
188 fail_unless (gst_pad_push_event (mysrcpad, event),
189 "Pushing EOS event failed");
190 }
191
192 static GstEvent *
send_tag_event(GstElement * element,GstEvent * event)193 send_tag_event (GstElement * element, GstEvent * event)
194 {
195 GList *l;
196 GstTagList *tag_list;
197 gdouble dummy;
198
199 g_return_val_if_fail (event->type == GST_EVENT_TAG, NULL);
200
201 fail_unless (gst_pad_push_event (mysrcpad, event),
202 "Pushing tag event failed");
203
204 event = NULL;
205
206 for (l = g_list_last (events); l; l = l->prev) {
207 if (GST_EVENT_TYPE (l->data) == GST_EVENT_TAG) {
208 event = l->data;
209 events = g_list_delete_link (events, l);
210 break;
211 }
212 }
213
214 /* Event got filtered out */
215 if (event == NULL)
216 return NULL;
217
218 fail_unless (event->type == GST_EVENT_TAG);
219 gst_event_parse_tag (event, &tag_list);
220
221 /* The element is supposed to filter out ReplayGain related tags. */
222 fail_if (gst_tag_list_get_double (tag_list, GST_TAG_TRACK_GAIN, &dummy),
223 "tag event still contains track gain tag");
224 fail_if (gst_tag_list_get_double (tag_list, GST_TAG_TRACK_PEAK, &dummy),
225 "tag event still contains track peak tag");
226 fail_if (gst_tag_list_get_double (tag_list, GST_TAG_ALBUM_GAIN, &dummy),
227 "tag event still contains album gain tag");
228 fail_if (gst_tag_list_get_double (tag_list, GST_TAG_ALBUM_PEAK, &dummy),
229 "tag event still contains album peak tag");
230
231 return event;
232 }
233
234 static GstBuffer *
test_buffer_new(gfloat value)235 test_buffer_new (gfloat value)
236 {
237 GstBuffer *buf;
238 GstMapInfo map;
239 gfloat *data;
240 gint i;
241
242 buf = gst_buffer_new_and_alloc (8 * sizeof (gfloat));
243 gst_buffer_map (buf, &map, GST_MAP_WRITE);
244 data = (gfloat *) map.data;
245 for (i = 0; i < 8; i++)
246 data[i] = value;
247 gst_buffer_unmap (buf, &map);
248
249
250 ASSERT_BUFFER_REFCOUNT (buf, "buf", 1);
251
252 return buf;
253 }
254
255 #define MATCH_GAIN(g1, g2) ((g1 < g2 + 1e-6) && (g2 < g1 + 1e-6))
256
257 static void
fail_unless_target_gain(GstElement * element,gdouble expected_gain)258 fail_unless_target_gain (GstElement * element, gdouble expected_gain)
259 {
260 gdouble prop_gain;
261
262 g_object_get (element, "target-gain", &prop_gain, NULL);
263
264 fail_unless (MATCH_GAIN (prop_gain, expected_gain),
265 "Target gain is %.2f dB, expected %.2f dB", prop_gain, expected_gain);
266 }
267
268 static void
fail_unless_result_gain(GstElement * element,gdouble expected_gain)269 fail_unless_result_gain (GstElement * element, gdouble expected_gain)
270 {
271 GstBuffer *input_buf, *output_buf;
272 gfloat *data;
273 gfloat input_sample, output_sample;
274 gdouble gain, prop_gain;
275 gboolean is_passthrough, expect_passthrough;
276 gint i;
277 GstMapInfo map;
278
279 fail_unless (g_list_length (buffers) == 0);
280
281 input_sample = 1.0;
282 input_buf = test_buffer_new (input_sample);
283
284 /* We keep an extra reference to detect passthrough mode. */
285 gst_buffer_ref (input_buf);
286 /* Pushing steals a reference. */
287 fail_unless (gst_pad_push (mysrcpad, input_buf) == GST_FLOW_OK);
288 gst_buffer_unref (input_buf);
289
290 /* The output buffer ends up on the global buffer list. */
291 fail_unless (g_list_length (buffers) == 1);
292 output_buf = buffers->data;
293 fail_if (output_buf == NULL);
294
295 buffers = g_list_remove (buffers, output_buf);
296 ASSERT_BUFFER_REFCOUNT (output_buf, "output_buf", 1);
297
298 fail_unless_equals_int (gst_buffer_get_size (output_buf),
299 8 * sizeof (gfloat));
300
301 gst_buffer_map (output_buf, &map, GST_MAP_READ);
302 data = (gfloat *) map.data;
303
304 output_sample = *data;
305 fail_if (output_sample == 0.0, "First output sample is zero");
306 for (i = 1; i < 8; i++) {
307 fail_unless (output_sample == data[i], "Output samples not uniform");
308 };
309 gst_buffer_unmap (output_buf, &map);
310
311 gain = 20. * log10 (output_sample / input_sample);
312 fail_unless (MATCH_GAIN (gain, expected_gain),
313 "Applied gain is %.2f dB, expected %.2f dB", gain, expected_gain);
314 g_object_get (element, "result-gain", &prop_gain, NULL);
315 fail_unless (MATCH_GAIN (prop_gain, expected_gain),
316 "Result gain is %.2f dB, expected %.2f dB", prop_gain, expected_gain);
317
318 is_passthrough = (output_buf == input_buf);
319 expect_passthrough = MATCH_GAIN (expected_gain, +0.00);
320 fail_unless (is_passthrough == expect_passthrough,
321 expect_passthrough
322 ? "Expected operation in passthrough mode"
323 : "Incorrect passthrough behaviour");
324
325 gst_buffer_unref (output_buf);
326 }
327
328 static void
fail_unless_gain(GstElement * element,gdouble expected_gain)329 fail_unless_gain (GstElement * element, gdouble expected_gain)
330 {
331 fail_unless_target_gain (element, expected_gain);
332 fail_unless_result_gain (element, expected_gain);
333 }
334
335 /* Start of tests. */
336
GST_START_TEST(test_no_buffer)337 GST_START_TEST (test_no_buffer)
338 {
339 GstElement *element = setup_rgvolume ();
340
341 set_playing_state (element);
342 set_null_state (element);
343 set_playing_state (element);
344 send_eos_event (element);
345
346 cleanup_rgvolume (element);
347 }
348
349 GST_END_TEST;
350
GST_START_TEST(test_events)351 GST_START_TEST (test_events)
352 {
353 GstElement *element = setup_rgvolume ();
354 GstEvent *event;
355 GstEvent *new_event;
356 GstTagList *tag_list;
357 gchar *artist;
358
359 set_playing_state (element);
360 send_stream_start_event (element);
361 send_caps_event (element);
362 send_segment_event (element);
363
364 send_empty_buffer ();
365
366 tag_list = gst_tag_list_new_empty ();
367 gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
368 GST_TAG_TRACK_GAIN, +4.95, GST_TAG_TRACK_PEAK, 0.59463,
369 GST_TAG_ALBUM_GAIN, -1.54, GST_TAG_ALBUM_PEAK, 0.693415,
370 GST_TAG_ARTIST, "Foobar", NULL);
371 event = gst_event_new_tag (tag_list);
372 new_event = send_tag_event (element, event);
373 gst_event_parse_tag (new_event, &tag_list);
374 fail_unless (gst_tag_list_get_string (tag_list, GST_TAG_ARTIST, &artist));
375 fail_unless (g_str_equal (artist, "Foobar"));
376 g_free (artist);
377 gst_event_unref (new_event);
378
379 /* Same as above, but with a non-writable event. */
380
381 tag_list = gst_tag_list_new_empty ();
382 gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
383 GST_TAG_TRACK_GAIN, +4.95, GST_TAG_TRACK_PEAK, 0.59463,
384 GST_TAG_ALBUM_GAIN, -1.54, GST_TAG_ALBUM_PEAK, 0.693415,
385 GST_TAG_ARTIST, "Foobar", NULL);
386 gst_tag_list_ref (tag_list);
387 event = gst_event_new_tag (tag_list);
388 new_event = send_tag_event (element, event);
389
390 /* Make sure our tags weren't modified in place while we still got a ref */
391 fail_unless_equals_int (5, gst_tag_list_n_tags (tag_list));
392 gst_tag_list_unref (tag_list);
393
394 gst_event_parse_tag (new_event, &tag_list);
395 fail_unless (gst_tag_list_get_string (tag_list, GST_TAG_ARTIST, &artist));
396 fail_unless (g_str_equal (artist, "Foobar"));
397 g_free (artist);
398 gst_event_unref (new_event);
399
400 cleanup_rgvolume (element);
401 }
402
403 GST_END_TEST;
404
GST_START_TEST(test_simple)405 GST_START_TEST (test_simple)
406 {
407 GstElement *element = setup_rgvolume ();
408 GstTagList *tag_list;
409
410 g_object_set (element, "album-mode", FALSE, "headroom", +0.00,
411 "pre-amp", -6.00, "fallback-gain", +1.23, NULL);
412 set_playing_state (element);
413 send_stream_start_event (element);
414 send_caps_event (element);
415 send_segment_event (element);
416
417 send_empty_buffer ();
418
419 tag_list = gst_tag_list_new_empty ();
420 gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
421 GST_TAG_TRACK_GAIN, -3.45, GST_TAG_TRACK_PEAK, 1.0,
422 GST_TAG_ALBUM_GAIN, +2.09, GST_TAG_ALBUM_PEAK, 1.0, NULL);
423 fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL);
424 fail_unless_gain (element, -9.45); /* pre-amp + track gain */
425 send_eos_event (element);
426
427 g_object_set (element, "album-mode", TRUE, NULL);
428
429 send_flush_events (element);
430 send_segment_event (element);
431
432 tag_list = gst_tag_list_new_empty ();
433 gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
434 GST_TAG_TRACK_GAIN, -3.45, GST_TAG_TRACK_PEAK, 1.0,
435 GST_TAG_ALBUM_GAIN, +2.09, GST_TAG_ALBUM_PEAK, 1.0, NULL);
436 fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL);
437 fail_unless_gain (element, -3.91); /* pre-amp + album gain */
438
439 /* Switching back to track mode in the middle of a stream: */
440 g_object_set (element, "album-mode", FALSE, NULL);
441 fail_unless_gain (element, -9.45); /* pre-amp + track gain */
442 send_eos_event (element);
443
444 cleanup_rgvolume (element);
445 }
446
447 GST_END_TEST;
448
449 /* If there are no gain tags at all, the fallback gain is used. */
450
GST_START_TEST(test_fallback_gain)451 GST_START_TEST (test_fallback_gain)
452 {
453 GstElement *element = setup_rgvolume ();
454 GstTagList *tag_list;
455
456 /* First some track where fallback does _not_ apply. */
457
458 g_object_set (element, "album-mode", FALSE, "headroom", 10.00,
459 "pre-amp", -6.00, "fallback-gain", -3.00, NULL);
460 set_playing_state (element);
461 send_stream_start_event (element);
462 send_caps_event (element);
463 send_segment_event (element);
464
465 send_empty_buffer ();
466
467 tag_list = gst_tag_list_new_empty ();
468 gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
469 GST_TAG_TRACK_GAIN, +3.5, GST_TAG_TRACK_PEAK, 1.0,
470 GST_TAG_ALBUM_GAIN, -0.5, GST_TAG_ALBUM_PEAK, 1.0, NULL);
471 fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL);
472 fail_unless_gain (element, -2.50); /* pre-amp + track gain */
473 send_eos_event (element);
474
475 /* Now a track completely missing tags. */
476 send_flush_events (element);
477 send_segment_event (element);
478
479 fail_unless_gain (element, -9.00); /* pre-amp + fallback-gain */
480
481 /* Changing the fallback gain in the middle of a stream, going to pass-through
482 * mode: */
483 g_object_set (element, "fallback-gain", +6.00, NULL);
484 fail_unless_gain (element, +0.00); /* pre-amp + fallback-gain */
485 send_eos_event (element);
486
487 /* Verify that result gain is set to +0.00 with pre-amp + fallback-gain >
488 * +0.00 and no headroom. */
489 send_flush_events (element);
490 send_segment_event (element);
491
492 g_object_set (element, "fallback-gain", +12.00, "headroom", +0.00, NULL);
493 fail_unless_target_gain (element, +6.00); /* pre-amp + fallback-gain */
494 fail_unless_result_gain (element, +0.00);
495 send_eos_event (element);
496
497 cleanup_rgvolume (element);
498 }
499
500 GST_END_TEST;
501
502 /* If album gain is to be preferred but not available, the track gain is to be
503 * taken instead. */
504
GST_START_TEST(test_fallback_track)505 GST_START_TEST (test_fallback_track)
506 {
507 GstElement *element = setup_rgvolume ();
508 GstTagList *tag_list;
509
510 g_object_set (element, "album-mode", TRUE, "headroom", +0.00,
511 "pre-amp", -6.00, "fallback-gain", +1.23, NULL);
512 set_playing_state (element);
513 send_stream_start_event (element);
514 send_caps_event (element);
515 send_segment_event (element);
516
517 send_empty_buffer ();
518
519 tag_list = gst_tag_list_new_empty ();
520 gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
521 GST_TAG_TRACK_GAIN, +2.11, GST_TAG_TRACK_PEAK, 1.0, NULL);
522 fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL);
523 fail_unless_gain (element, -3.89); /* pre-amp + track gain */
524
525 send_eos_event (element);
526
527 cleanup_rgvolume (element);
528 }
529
530 GST_END_TEST;
531
532 /* If track gain is to be preferred but not available, the album gain is to be
533 * taken instead. */
534
GST_START_TEST(test_fallback_album)535 GST_START_TEST (test_fallback_album)
536 {
537 GstElement *element = setup_rgvolume ();
538 GstTagList *tag_list;
539
540 g_object_set (element, "album-mode", FALSE, "headroom", +0.00,
541 "pre-amp", -6.00, "fallback-gain", +1.23, NULL);
542 set_playing_state (element);
543 send_stream_start_event (element);
544 send_caps_event (element);
545 send_segment_event (element);
546
547 send_empty_buffer ();
548
549 tag_list = gst_tag_list_new_empty ();
550 gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
551 GST_TAG_ALBUM_GAIN, +3.73, GST_TAG_ALBUM_PEAK, 1.0, NULL);
552 fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL);
553 fail_unless_gain (element, -2.27); /* pre-amp + album gain */
554
555 send_eos_event (element);
556
557 cleanup_rgvolume (element);
558 }
559
560 GST_END_TEST;
561
GST_START_TEST(test_headroom)562 GST_START_TEST (test_headroom)
563 {
564 GstElement *element = setup_rgvolume ();
565 GstTagList *tag_list;
566
567 g_object_set (element, "album-mode", FALSE, "headroom", +0.00,
568 "pre-amp", +0.00, "fallback-gain", +1.23, NULL);
569 set_playing_state (element);
570 send_stream_start_event (element);
571 send_caps_event (element);
572 send_segment_event (element);
573
574 send_empty_buffer ();
575
576 tag_list = gst_tag_list_new_empty ();
577 gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
578 GST_TAG_TRACK_GAIN, +3.50, GST_TAG_TRACK_PEAK, 1.0, NULL);
579 fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL);
580 fail_unless_target_gain (element, +3.50); /* pre-amp + track gain */
581 fail_unless_result_gain (element, +0.00);
582 send_eos_event (element);
583
584 send_flush_events (element);
585 send_segment_event (element);
586
587 g_object_set (element, "headroom", +2.00, NULL);
588 tag_list = gst_tag_list_new_empty ();
589 gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
590 GST_TAG_TRACK_GAIN, +9.18, GST_TAG_TRACK_PEAK, 0.687149, NULL);
591 fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL);
592 fail_unless_target_gain (element, +9.18); /* pre-amp + track gain */
593 /* Result is 20. * log10 (1. / peak) + headroom. */
594 fail_unless_result_gain (element, 5.2589816238303335);
595 send_eos_event (element);
596
597 send_flush_events (element);
598 send_segment_event (element);
599
600 g_object_set (element, "album-mode", TRUE, NULL);
601 tag_list = gst_tag_list_new_empty ();
602 gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
603 GST_TAG_ALBUM_GAIN, +5.50, GST_TAG_ALBUM_PEAK, 1.0, NULL);
604 fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL);
605 fail_unless_target_gain (element, +5.50); /* pre-amp + album gain */
606 fail_unless_result_gain (element, +2.00); /* headroom */
607 send_eos_event (element);
608
609 cleanup_rgvolume (element);
610 }
611
612 GST_END_TEST;
613
GST_START_TEST(test_reference_level)614 GST_START_TEST (test_reference_level)
615 {
616 GstElement *element = setup_rgvolume ();
617 GstTagList *tag_list;
618
619 g_object_set (element,
620 "album-mode", FALSE,
621 "headroom", +0.00, "pre-amp", +0.00, "fallback-gain", +1.23, NULL);
622 set_playing_state (element);
623
624 send_stream_start_event (element);
625 send_caps_event (element);
626 send_segment_event (element);
627
628 send_empty_buffer ();
629
630 tag_list = gst_tag_list_new_empty ();
631 gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
632 GST_TAG_TRACK_GAIN, 0.00, GST_TAG_TRACK_PEAK, 0.2,
633 GST_TAG_REFERENCE_LEVEL, 83., NULL);
634 fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL);
635 /* Because our authoritative reference is 89 dB, we bump it up by +6 dB. */
636 fail_unless_gain (element, +6.00); /* pre-amp + track gain */
637 send_eos_event (element);
638
639 g_object_set (element, "album-mode", TRUE, NULL);
640
641 /* Same as above, but with album gain. */
642 send_flush_events (element);
643 send_segment_event (element);
644
645 tag_list = gst_tag_list_new_empty ();
646 gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
647 GST_TAG_TRACK_GAIN, 1.23, GST_TAG_TRACK_PEAK, 0.1,
648 GST_TAG_ALBUM_GAIN, 0.00, GST_TAG_ALBUM_PEAK, 0.2,
649 GST_TAG_REFERENCE_LEVEL, 83., NULL);
650 fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL);
651 fail_unless_gain (element, +6.00); /* pre-amp + album gain */
652
653 cleanup_rgvolume (element);
654 }
655
656 GST_END_TEST;
657
658 static Suite *
rgvolume_suite(void)659 rgvolume_suite (void)
660 {
661 Suite *s = suite_create ("rgvolume");
662 TCase *tc_chain = tcase_create ("general");
663
664 suite_add_tcase (s, tc_chain);
665
666 tcase_add_test (tc_chain, test_no_buffer);
667 tcase_add_test (tc_chain, test_events);
668 tcase_add_test (tc_chain, test_simple);
669 tcase_add_test (tc_chain, test_fallback_gain);
670 tcase_add_test (tc_chain, test_fallback_track);
671 tcase_add_test (tc_chain, test_fallback_album);
672 tcase_add_test (tc_chain, test_headroom);
673 tcase_add_test (tc_chain, test_reference_level);
674
675 return s;
676 }
677
678 GST_CHECK_MAIN (rgvolume);
679