check: Use GST_CHECK_MAIN () macro everywhere
[platform/upstream/gst-plugins-good.git] / tests / check / elements / rgvolume.c
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
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 *
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
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
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
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
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
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
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
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
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
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 *
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 *
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
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
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
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
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
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   event = gst_event_new_tag (tag_list);
387   new_event = send_tag_event (element, event);
388   gst_event_parse_tag (new_event, &tag_list);
389   fail_unless (gst_tag_list_get_string (tag_list, GST_TAG_ARTIST, &artist));
390   fail_unless (g_str_equal (artist, "Foobar"));
391   g_free (artist);
392   gst_event_unref (new_event);
393
394   cleanup_rgvolume (element);
395 }
396
397 GST_END_TEST;
398
399 GST_START_TEST (test_simple)
400 {
401   GstElement *element = setup_rgvolume ();
402   GstTagList *tag_list;
403
404   g_object_set (element, "album-mode", FALSE, "headroom", +0.00,
405       "pre-amp", -6.00, "fallback-gain", +1.23, NULL);
406   set_playing_state (element);
407   send_stream_start_event (element);
408   send_caps_event (element);
409   send_segment_event (element);
410
411   send_empty_buffer ();
412
413   tag_list = gst_tag_list_new_empty ();
414   gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
415       GST_TAG_TRACK_GAIN, -3.45, GST_TAG_TRACK_PEAK, 1.0,
416       GST_TAG_ALBUM_GAIN, +2.09, GST_TAG_ALBUM_PEAK, 1.0, NULL);
417   fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL);
418   fail_unless_gain (element, -9.45);    /* pre-amp + track gain */
419   send_eos_event (element);
420
421   g_object_set (element, "album-mode", TRUE, NULL);
422
423   send_flush_events (element);
424   send_segment_event (element);
425
426   tag_list = gst_tag_list_new_empty ();
427   gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
428       GST_TAG_TRACK_GAIN, -3.45, GST_TAG_TRACK_PEAK, 1.0,
429       GST_TAG_ALBUM_GAIN, +2.09, GST_TAG_ALBUM_PEAK, 1.0, NULL);
430   fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL);
431   fail_unless_gain (element, -3.91);    /* pre-amp + album gain */
432
433   /* Switching back to track mode in the middle of a stream: */
434   g_object_set (element, "album-mode", FALSE, NULL);
435   fail_unless_gain (element, -9.45);    /* pre-amp + track gain */
436   send_eos_event (element);
437
438   cleanup_rgvolume (element);
439 }
440
441 GST_END_TEST;
442
443 /* If there are no gain tags at all, the fallback gain is used. */
444
445 GST_START_TEST (test_fallback_gain)
446 {
447   GstElement *element = setup_rgvolume ();
448   GstTagList *tag_list;
449
450   /* First some track where fallback does _not_ apply. */
451
452   g_object_set (element, "album-mode", FALSE, "headroom", 10.00,
453       "pre-amp", -6.00, "fallback-gain", -3.00, NULL);
454   set_playing_state (element);
455   send_stream_start_event (element);
456   send_caps_event (element);
457   send_segment_event (element);
458
459   send_empty_buffer ();
460
461   tag_list = gst_tag_list_new_empty ();
462   gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
463       GST_TAG_TRACK_GAIN, +3.5, GST_TAG_TRACK_PEAK, 1.0,
464       GST_TAG_ALBUM_GAIN, -0.5, GST_TAG_ALBUM_PEAK, 1.0, NULL);
465   fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL);
466   fail_unless_gain (element, -2.50);    /* pre-amp + track gain */
467   send_eos_event (element);
468
469   /* Now a track completely missing tags. */
470   send_flush_events (element);
471   send_segment_event (element);
472
473   fail_unless_gain (element, -9.00);    /* pre-amp + fallback-gain */
474
475   /* Changing the fallback gain in the middle of a stream, going to pass-through
476    * mode: */
477   g_object_set (element, "fallback-gain", +6.00, NULL);
478   fail_unless_gain (element, +0.00);    /* pre-amp + fallback-gain */
479   send_eos_event (element);
480
481   /* Verify that result gain is set to +0.00 with pre-amp + fallback-gain >
482    * +0.00 and no headroom. */
483   send_flush_events (element);
484   send_segment_event (element);
485
486   g_object_set (element, "fallback-gain", +12.00, "headroom", +0.00, NULL);
487   fail_unless_target_gain (element, +6.00);     /* pre-amp + fallback-gain */
488   fail_unless_result_gain (element, +0.00);
489   send_eos_event (element);
490
491   cleanup_rgvolume (element);
492 }
493
494 GST_END_TEST;
495
496 /* If album gain is to be preferred but not available, the track gain is to be
497  * taken instead. */
498
499 GST_START_TEST (test_fallback_track)
500 {
501   GstElement *element = setup_rgvolume ();
502   GstTagList *tag_list;
503
504   g_object_set (element, "album-mode", TRUE, "headroom", +0.00,
505       "pre-amp", -6.00, "fallback-gain", +1.23, NULL);
506   set_playing_state (element);
507   send_stream_start_event (element);
508   send_caps_event (element);
509   send_segment_event (element);
510
511   send_empty_buffer ();
512
513   tag_list = gst_tag_list_new_empty ();
514   gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
515       GST_TAG_TRACK_GAIN, +2.11, GST_TAG_TRACK_PEAK, 1.0, NULL);
516   fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL);
517   fail_unless_gain (element, -3.89);    /* pre-amp + track gain */
518
519   send_eos_event (element);
520
521   cleanup_rgvolume (element);
522 }
523
524 GST_END_TEST;
525
526 /* If track gain is to be preferred but not available, the album gain is to be
527  * taken instead. */
528
529 GST_START_TEST (test_fallback_album)
530 {
531   GstElement *element = setup_rgvolume ();
532   GstTagList *tag_list;
533
534   g_object_set (element, "album-mode", FALSE, "headroom", +0.00,
535       "pre-amp", -6.00, "fallback-gain", +1.23, NULL);
536   set_playing_state (element);
537   send_stream_start_event (element);
538   send_caps_event (element);
539   send_segment_event (element);
540
541   send_empty_buffer ();
542
543   tag_list = gst_tag_list_new_empty ();
544   gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
545       GST_TAG_ALBUM_GAIN, +3.73, GST_TAG_ALBUM_PEAK, 1.0, NULL);
546   fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL);
547   fail_unless_gain (element, -2.27);    /* pre-amp + album gain */
548
549   send_eos_event (element);
550
551   cleanup_rgvolume (element);
552 }
553
554 GST_END_TEST;
555
556 GST_START_TEST (test_headroom)
557 {
558   GstElement *element = setup_rgvolume ();
559   GstTagList *tag_list;
560
561   g_object_set (element, "album-mode", FALSE, "headroom", +0.00,
562       "pre-amp", +0.00, "fallback-gain", +1.23, NULL);
563   set_playing_state (element);
564   send_stream_start_event (element);
565   send_caps_event (element);
566   send_segment_event (element);
567
568   send_empty_buffer ();
569
570   tag_list = gst_tag_list_new_empty ();
571   gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
572       GST_TAG_TRACK_GAIN, +3.50, GST_TAG_TRACK_PEAK, 1.0, NULL);
573   fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL);
574   fail_unless_target_gain (element, +3.50);     /* pre-amp + track gain */
575   fail_unless_result_gain (element, +0.00);
576   send_eos_event (element);
577
578   send_flush_events (element);
579   send_segment_event (element);
580
581   g_object_set (element, "headroom", +2.00, NULL);
582   tag_list = gst_tag_list_new_empty ();
583   gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
584       GST_TAG_TRACK_GAIN, +9.18, GST_TAG_TRACK_PEAK, 0.687149, NULL);
585   fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL);
586   fail_unless_target_gain (element, +9.18);     /* pre-amp + track gain */
587   /* Result is 20. * log10 (1. / peak) + headroom. */
588   fail_unless_result_gain (element, 5.2589816238303335);
589   send_eos_event (element);
590
591   send_flush_events (element);
592   send_segment_event (element);
593
594   g_object_set (element, "album-mode", TRUE, NULL);
595   tag_list = gst_tag_list_new_empty ();
596   gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
597       GST_TAG_ALBUM_GAIN, +5.50, GST_TAG_ALBUM_PEAK, 1.0, NULL);
598   fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL);
599   fail_unless_target_gain (element, +5.50);     /* pre-amp + album gain */
600   fail_unless_result_gain (element, +2.00);     /* headroom */
601   send_eos_event (element);
602
603   cleanup_rgvolume (element);
604 }
605
606 GST_END_TEST;
607
608 GST_START_TEST (test_reference_level)
609 {
610   GstElement *element = setup_rgvolume ();
611   GstTagList *tag_list;
612
613   g_object_set (element,
614       "album-mode", FALSE,
615       "headroom", +0.00, "pre-amp", +0.00, "fallback-gain", +1.23, NULL);
616   set_playing_state (element);
617
618   send_stream_start_event (element);
619   send_caps_event (element);
620   send_segment_event (element);
621
622   send_empty_buffer ();
623
624   tag_list = gst_tag_list_new_empty ();
625   gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
626       GST_TAG_TRACK_GAIN, 0.00, GST_TAG_TRACK_PEAK, 0.2,
627       GST_TAG_REFERENCE_LEVEL, 83., NULL);
628   fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL);
629   /* Because our authorative reference is 89 dB, we bump it up by +6 dB. */
630   fail_unless_gain (element, +6.00);    /* pre-amp + track gain */
631   send_eos_event (element);
632
633   g_object_set (element, "album-mode", TRUE, NULL);
634
635   /* Same as above, but with album gain. */
636   send_flush_events (element);
637   send_segment_event (element);
638
639   tag_list = gst_tag_list_new_empty ();
640   gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
641       GST_TAG_TRACK_GAIN, 1.23, GST_TAG_TRACK_PEAK, 0.1,
642       GST_TAG_ALBUM_GAIN, 0.00, GST_TAG_ALBUM_PEAK, 0.2,
643       GST_TAG_REFERENCE_LEVEL, 83., NULL);
644   fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL);
645   fail_unless_gain (element, +6.00);    /* pre-amp + album gain */
646
647   cleanup_rgvolume (element);
648 }
649
650 GST_END_TEST;
651
652 static Suite *
653 rgvolume_suite (void)
654 {
655   Suite *s = suite_create ("rgvolume");
656   TCase *tc_chain = tcase_create ("general");
657
658   suite_add_tcase (s, tc_chain);
659
660   tcase_add_test (tc_chain, test_no_buffer);
661   tcase_add_test (tc_chain, test_events);
662   tcase_add_test (tc_chain, test_simple);
663   tcase_add_test (tc_chain, test_fallback_gain);
664   tcase_add_test (tc_chain, test_fallback_track);
665   tcase_add_test (tc_chain, test_fallback_album);
666   tcase_add_test (tc_chain, test_headroom);
667   tcase_add_test (tc_chain, test_reference_level);
668
669   return s;
670 }
671
672 GST_CHECK_MAIN (rgvolume);