diff options
Diffstat (limited to 'tests/check/elements/rganalysis.c')
-rw-r--r-- | tests/check/elements/rganalysis.c | 1925 |
1 files changed, 0 insertions, 1925 deletions
diff --git a/tests/check/elements/rganalysis.c b/tests/check/elements/rganalysis.c deleted file mode 100644 index 0045cb94..00000000 --- a/tests/check/elements/rganalysis.c +++ /dev/null @@ -1,1925 +0,0 @@ -/* GStreamer ReplayGain analysis - * - * Copyright (C) 2006 Rene Stadler <mail@renestadler.de> - * - * rganalysis.c: Unit test for the rganalysis element - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301 USA - */ - -/* Some things to note about the RMS window length of the analysis algorithm and - * thus the implementation used in the element: Processing divides input data - * into 50ms windows at some point. Some details about this that normally do - * not matter: - * - * 1. At the end of a stream, the remainder of data that did not fill up the - * last 50ms window is simply discarded. - * - * 2. If the sample rate changes during a stream, the currently running window - * is discarded and the equal loudness filter gets reset as if a new stream - * started. - * - * 3. For the album gain, it is not entirely correct to think of obtaining it - * like "as if all the tracks are analyzed as one track". There isn't a - * separate window being tracked for album processing, so at stream (track) - * end, the remaining unfilled window does not contribute to the album gain - * either. - * - * 4. If a waveform with a result gain G is concatenated to itself and the - * result processed as a track, the gain can be different from G if and only - * if the duration of the original waveform is not an integer multiple of - * 50ms. If the original waveform gets processed as a single track and then - * the same data again as a subsequent track, the album result gain will - * always match G (this is implied by 3.). - * - * 5. A stream shorter than 50ms cannot be analyzed. At 8000 and 48000 Hz, - * this corresponds to 400 resp. 2400 frames. If a stream is shorter than - * 50ms, the element will not generate tags at EOS (only if an album - * finished, but only album tags are generated then). This is not an - * erroneous condition, the element should behave normally. - * - * The limitations outlined in 1.-4. do not apply to the peak values. Every - * single sample is accounted for when looking for the peak. Thus the album - * peak is guaranteed to be the maximum value of all track peaks. - * - * In normal day-to-day use, these little facts are unlikely to be relevant, but - * they have to be kept in mind for writing the tests here. - */ - -#include <gst/check/gstcheck.h> - -GList *buffers = NULL; - -/* For ease of programming we use globals to keep refs for our floating src and - * sink pads we create; otherwise we always have to do get_pad, get_peer, and - * then remove references in every test function */ -static GstPad *mysrcpad, *mysinkpad; - -/* Mapping from supported sample rates to the correct result gain for the - * following test waveform: 20 * 512 samples with a quarter-full amplitude of - * toggling sign, changing every 48 samples and starting with the positive - * value. - * - * Even if we would generate a wave describing a signal with the same frequency - * at each sampling rate, the results would vary (slightly). Hence the simple - * generation method, since we cannot use a constant value as expected result - * anyways. For all sample rates, changing the sign every 48 frames gives a - * sane frequency. Buffers containing data that forms such a waveform is - * created using the test_buffer_square_{float,int16}_{mono,stereo} functions - * below. - * - * The results have been checked against what the metaflac and wavegain programs - * generate for such a stream. If you want to verify these, be sure that the - * metaflac program does not produce incorrect results in your environment: I - * found a strange bug in the (defacto) reference code for the analysis that - * sometimes leads to incorrect RMS window lengths. */ - -struct rate_test -{ - guint sample_rate; - gdouble gain; -}; - -static const struct rate_test supported_rates[] = { - {8000, -0.91}, - {11025, -2.80}, - {12000, -3.13}, - {16000, -4.26}, - {22050, -5.64}, - {24000, -5.87}, - {32000, -6.03}, - {44100, -6.20}, - {48000, -6.14} -}; - -/* Lookup the correct gain adjustment result in above array. */ - -static gdouble -get_expected_gain (guint sample_rate) -{ - gint i; - - for (i = G_N_ELEMENTS (supported_rates); i--;) - if (supported_rates[i].sample_rate == sample_rate) - return supported_rates[i].gain; - g_return_val_if_reached (0.0); -} - -#define SILENCE_GAIN 64.82 - -#define REPLAY_GAIN_CAPS \ - "channels = (int) { 1, 2 }, " \ - "rate = (int) { 8000, 11025, 12000, 16000, 22050, " \ - "24000, 32000, 44100, 48000 }" - -#define RG_ANALYSIS_CAPS_TEMPLATE_STRING \ - "audio/x-raw-float, " \ - "width = (int) 32, " \ - "endianness = (int) BYTE_ORDER, " \ - REPLAY_GAIN_CAPS \ - "; " \ - "audio/x-raw-int, " \ - "width = (int) 16, " \ - "depth = (int) [ 1, 16 ], " \ - "signed = (boolean) true, " \ - "endianness = (int) BYTE_ORDER, " \ - REPLAY_GAIN_CAPS - -static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (RG_ANALYSIS_CAPS_TEMPLATE_STRING) - ); -static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (RG_ANALYSIS_CAPS_TEMPLATE_STRING) - ); - -GstElement * -setup_rganalysis () -{ - GstElement *analysis; - GstBus *bus; - - GST_DEBUG ("setup_rganalysis"); - analysis = gst_check_setup_element ("rganalysis"); - mysrcpad = gst_check_setup_src_pad (analysis, &srctemplate, NULL); - mysinkpad = gst_check_setup_sink_pad (analysis, &sinktemplate, NULL); - gst_pad_set_active (mysrcpad, TRUE); - gst_pad_set_active (mysinkpad, TRUE); - - bus = gst_bus_new (); - gst_element_set_bus (analysis, bus); - /* gst_element_set_bus does not steal a reference. */ - gst_object_unref (bus); - - return analysis; -} - -void -cleanup_rganalysis (GstElement * element) -{ - GST_DEBUG ("cleanup_rganalysis"); - - g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL); - g_list_free (buffers); - buffers = NULL; - - /* The bus owns references to the element: */ - gst_element_set_bus (element, NULL); - - gst_pad_set_active (mysrcpad, FALSE); - gst_pad_set_active (mysinkpad, FALSE); - gst_check_teardown_src_pad (element); - gst_check_teardown_sink_pad (element); - gst_check_teardown_element (element); -} - -static void -set_playing_state (GstElement * element) -{ - fail_unless (gst_element_set_state (element, - GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, - "Could not set state to PLAYING"); -} - -static void -send_eos_event (GstElement * element) -{ - GstBus *bus = gst_element_get_bus (element); - GstPad *pad = gst_element_get_static_pad (element, "sink"); - GstEvent *event = gst_event_new_eos (); - - fail_unless (gst_pad_send_event (pad, event), - "Cannot send EOS event: Not handled."); - - /* There is no sink element, so _we_ post the EOS message on the bus here. Of - * course we generate any EOS ourselves, but this allows us to poll for the - * EOS message in poll_eos if we expect the element to _not_ generate a TAG - * message. That's better than waiting for a timeout to lapse. */ - fail_unless (gst_bus_post (bus, gst_message_new_eos (NULL))); - - gst_object_unref (bus); - gst_object_unref (pad); -} - -static void -send_tag_event (GstElement * element, GstTagList * tag_list) -{ - GstPad *pad = gst_element_get_static_pad (element, "sink"); - GstEvent *event = gst_event_new_tag (tag_list); - - fail_unless (gst_pad_send_event (pad, event), - "Cannot send TAG event: Not handled."); - - gst_object_unref (pad); -} - -static void -poll_eos (GstElement * element) -{ - GstBus *bus = gst_element_get_bus (element); - GstMessage *message; - - message = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_TAG, GST_SECOND); - fail_unless (message != NULL, "Could not poll for EOS message: Timed out"); - fail_unless (message->type == GST_MESSAGE_EOS, - "Could not poll for eos message: got message of type %s instead", - gst_message_type_get_name (message->type)); - - gst_message_unref (message); - gst_object_unref (bus); -} - -/* This also polls for EOS since the TAG message comes right before the end of - * streams. */ - -static GstTagList * -poll_tags (GstElement * element) -{ - GstBus *bus = gst_element_get_bus (element); - GstTagList *tag_list; - GstMessage *message; - - message = gst_bus_poll (bus, GST_MESSAGE_TAG, GST_SECOND); - fail_unless (message != NULL, "Could not poll for TAG message: Timed out"); - - fail_unless (GST_MESSAGE_SRC (message) == GST_OBJECT (element)); - - gst_message_parse_tag (message, &tag_list); - gst_message_unref (message); - gst_object_unref (bus); - - poll_eos (element); - - return tag_list; -} - -#define MATCH_PEAK(p1, p2) ((p1 < p2 + 1e-6) && (p2 < p1 + 1e-6)) -#define MATCH_GAIN(g1, g2) ((g1 < g2 + 1e-13) && (g2 < g1 + 1e-13)) - -static void -fail_unless_track_gain (const GstTagList * tag_list, gdouble gain) -{ - gdouble result; - - fail_unless (gst_tag_list_get_double (tag_list, GST_TAG_TRACK_GAIN, &result), - "Tag list contains no track gain value"); - fail_unless (MATCH_GAIN (gain, result), - "Track gain %+.2f does not match, expected %+.2f", result, gain); -} - -static void -fail_unless_track_peak (const GstTagList * tag_list, gdouble peak) -{ - gdouble result; - - fail_unless (gst_tag_list_get_double (tag_list, GST_TAG_TRACK_PEAK, &result), - "Tag list contains no track peak value"); - fail_unless (MATCH_PEAK (peak, result), - "Track peak %f does not match, expected %f", result, peak); -} - -static void -fail_unless_album_gain (const GstTagList * tag_list, gdouble gain) -{ - gdouble result; - - fail_unless (gst_tag_list_get_double (tag_list, GST_TAG_ALBUM_GAIN, &result), - "Tag list contains no album gain value"); - fail_unless (MATCH_GAIN (result, gain), - "Album gain %+.2f does not match, expected %+.2f", result, gain); -} - -static void -fail_unless_album_peak (const GstTagList * tag_list, gdouble peak) -{ - gdouble result; - - fail_unless (gst_tag_list_get_double (tag_list, GST_TAG_ALBUM_PEAK, &result), - "Tag list contains no album peak value"); - fail_unless (MATCH_PEAK (peak, result), - "Album peak %f does not match, expected %f", result, peak); -} - -static void -fail_if_track_tags (const GstTagList * tag_list) -{ - gdouble result; - - fail_if (gst_tag_list_get_double (tag_list, GST_TAG_TRACK_GAIN, &result), - "Tag list contains track gain value (but should not)"); - fail_if (gst_tag_list_get_double (tag_list, GST_TAG_TRACK_PEAK, &result), - "Tag list contains track peak value (but should not)"); -} - -static void -fail_if_album_tags (const GstTagList * tag_list) -{ - gdouble result; - - fail_if (gst_tag_list_get_double (tag_list, GST_TAG_ALBUM_GAIN, &result), - "Tag list contains album gain value (but should not)"); - fail_if (gst_tag_list_get_double (tag_list, GST_TAG_ALBUM_PEAK, &result), - "Tag list contains album peak value (but should not)"); -} - -static void -fail_unless_num_tracks (GstElement * element, guint num_tracks) -{ - guint current; - - g_object_get (element, "num-tracks", ¤t, NULL); - fail_unless (current == num_tracks, - "num-tracks property has incorrect value %u, expected %u", - current, num_tracks); -} - -/* Functions that create buffers with constant sample values, for peak - * tests. */ - -static GstBuffer * -test_buffer_const_float_mono (gint sample_rate, gsize n_frames, gfloat value) -{ - GstBuffer *buf = gst_buffer_new_and_alloc (n_frames * sizeof (gfloat)); - gfloat *data = (gfloat *) GST_BUFFER_DATA (buf); - GstCaps *caps; - gint i; - - for (i = n_frames; i--;) - *data++ = value; - - caps = gst_caps_new_simple ("audio/x-raw-float", - "rate", G_TYPE_INT, sample_rate, "channels", G_TYPE_INT, 1, - "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32, NULL); - gst_buffer_set_caps (buf, caps); - gst_caps_unref (caps); - - ASSERT_BUFFER_REFCOUNT (buf, "buf", 1); - - return buf; -} - -static GstBuffer * -test_buffer_const_float_stereo (gint sample_rate, gsize n_frames, - gfloat value_l, gfloat value_r) -{ - GstBuffer *buf = gst_buffer_new_and_alloc (n_frames * sizeof (gfloat) * 2); - gfloat *data = (gfloat *) GST_BUFFER_DATA (buf); - GstCaps *caps; - gint i; - - for (i = n_frames; i--;) { - *data++ = value_l; - *data++ = value_r; - } - - caps = gst_caps_new_simple ("audio/x-raw-float", - "rate", G_TYPE_INT, sample_rate, "channels", G_TYPE_INT, 2, - "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32, NULL); - gst_buffer_set_caps (buf, caps); - gst_caps_unref (caps); - - ASSERT_BUFFER_REFCOUNT (buf, "buf", 1); - - return buf; -} - -static GstBuffer * -test_buffer_const_int16_mono (gint sample_rate, gint depth, gsize n_frames, - gint16 value) -{ - GstBuffer *buf = gst_buffer_new_and_alloc (n_frames * sizeof (gint16)); - gint16 *data = (gint16 *) GST_BUFFER_DATA (buf); - GstCaps *caps; - gint i; - - for (i = n_frames; i--;) - *data++ = value; - - caps = gst_caps_new_simple ("audio/x-raw-int", - "rate", G_TYPE_INT, sample_rate, "channels", G_TYPE_INT, 1, - "endianness", G_TYPE_INT, G_BYTE_ORDER, "signed", G_TYPE_BOOLEAN, TRUE, - "width", G_TYPE_INT, 16, "depth", G_TYPE_INT, depth, NULL); - gst_buffer_set_caps (buf, caps); - gst_caps_unref (caps); - - ASSERT_BUFFER_REFCOUNT (buf, "buf", 1); - - return buf; -} - -static GstBuffer * -test_buffer_const_int16_stereo (gint sample_rate, gint depth, gsize n_frames, - gint16 value_l, gint16 value_r) -{ - GstBuffer *buf = gst_buffer_new_and_alloc (n_frames * sizeof (gint16) * 2); - gint16 *data = (gint16 *) GST_BUFFER_DATA (buf); - GstCaps *caps; - gint i; - - for (i = n_frames; i--;) { - *data++ = value_l; - *data++ = value_r; - } - - caps = gst_caps_new_simple ("audio/x-raw-int", - "rate", G_TYPE_INT, sample_rate, "channels", G_TYPE_INT, 2, - "endianness", G_TYPE_INT, G_BYTE_ORDER, "signed", G_TYPE_BOOLEAN, TRUE, - "width", G_TYPE_INT, 16, "depth", G_TYPE_INT, depth, NULL); - gst_buffer_set_caps (buf, caps); - gst_caps_unref (caps); - - ASSERT_BUFFER_REFCOUNT (buf, "buf", 1); - - return buf; -} - -/* Functions that create data buffers containing square signal - * waveforms. */ - -static GstBuffer * -test_buffer_square_float_mono (gint * accumulator, gint sample_rate, - gsize n_frames, gfloat value) -{ - GstBuffer *buf = gst_buffer_new_and_alloc (n_frames * sizeof (gfloat)); - gfloat *data = (gfloat *) GST_BUFFER_DATA (buf); - GstCaps *caps; - gint i; - - for (i = n_frames; i--;) { - *accumulator += 1; - *accumulator %= 96; - - if (*accumulator < 48) - *data++ = value; - else - *data++ = -value; - } - - caps = gst_caps_new_simple ("audio/x-raw-float", - "rate", G_TYPE_INT, sample_rate, "channels", G_TYPE_INT, 1, - "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32, NULL); - gst_buffer_set_caps (buf, caps); - gst_caps_unref (caps); - - ASSERT_BUFFER_REFCOUNT (buf, "buf", 1); - - return buf; -} - -static GstBuffer * -test_buffer_square_float_stereo (gint * accumulator, gint sample_rate, - gsize n_frames, gfloat value_l, gfloat value_r) -{ - GstBuffer *buf = gst_buffer_new_and_alloc (n_frames * sizeof (gfloat) * 2); - gfloat *data = (gfloat *) GST_BUFFER_DATA (buf); - GstCaps *caps; - gint i; - - for (i = n_frames; i--;) { - *accumulator += 1; - *accumulator %= 96; - - if (*accumulator < 48) { - *data++ = value_l; - *data++ = value_r; - } else { - *data++ = -value_l; - *data++ = -value_r; - } - } - - caps = gst_caps_new_simple ("audio/x-raw-float", - "rate", G_TYPE_INT, sample_rate, "channels", G_TYPE_INT, 2, - "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32, NULL); - gst_buffer_set_caps (buf, caps); - gst_caps_unref (caps); - - ASSERT_BUFFER_REFCOUNT (buf, "buf", 1); - - return buf; -} - -static GstBuffer * -test_buffer_square_int16_mono (gint * accumulator, gint sample_rate, - gint depth, gsize n_frames, gint16 value) -{ - GstBuffer *buf = gst_buffer_new_and_alloc (n_frames * sizeof (gint16)); - gint16 *data = (gint16 *) GST_BUFFER_DATA (buf); - GstCaps *caps; - gint i; - - for (i = n_frames; i--;) { - *accumulator += 1; - *accumulator %= 96; - - if (*accumulator < 48) - *data++ = value; - else - *data++ = -MAX (value, -32767); - } - - caps = gst_caps_new_simple ("audio/x-raw-int", - "rate", G_TYPE_INT, sample_rate, "channels", G_TYPE_INT, 1, - "endianness", G_TYPE_INT, G_BYTE_ORDER, "signed", G_TYPE_BOOLEAN, TRUE, - "width", G_TYPE_INT, 16, "depth", G_TYPE_INT, depth, NULL); - gst_buffer_set_caps (buf, caps); - gst_caps_unref (caps); - - ASSERT_BUFFER_REFCOUNT (buf, "buf", 1); - - return buf; -} - -static GstBuffer * -test_buffer_square_int16_stereo (gint * accumulator, gint sample_rate, - gint depth, gsize n_frames, gint16 value_l, gint16 value_r) -{ - GstBuffer *buf = gst_buffer_new_and_alloc (n_frames * sizeof (gint16) * 2); - gint16 *data = (gint16 *) GST_BUFFER_DATA (buf); - GstCaps *caps; - gint i; - - for (i = n_frames; i--;) { - *accumulator += 1; - *accumulator %= 96; - - if (*accumulator < 48) { - *data++ = value_l; - *data++ = value_r; - } else { - *data++ = -MAX (value_l, -32767); - *data++ = -MAX (value_r, -32767); - } - } - - caps = gst_caps_new_simple ("audio/x-raw-int", - "rate", G_TYPE_INT, sample_rate, "channels", G_TYPE_INT, 2, - "endianness", G_TYPE_INT, G_BYTE_ORDER, "signed", G_TYPE_BOOLEAN, TRUE, - "width", G_TYPE_INT, 16, "depth", G_TYPE_INT, depth, NULL); - gst_buffer_set_caps (buf, caps); - gst_caps_unref (caps); - - ASSERT_BUFFER_REFCOUNT (buf, "buf", 1); - - return buf; -} - -static void -push_buffer (GstBuffer * buf) -{ - /* gst_pad_push steals a reference. */ - fail_unless (gst_pad_push (mysrcpad, buf) == GST_FLOW_OK); - ASSERT_BUFFER_REFCOUNT (buf, "buf", 1); -} - -/*** Start of the tests. ***/ - -/* This test looks redundant, but early versions of the element - * crashed when doing, well, nothing: */ - -GST_START_TEST (test_no_buffer) -{ - GstElement *element = setup_rganalysis (); - - set_playing_state (element); - send_eos_event (element); - poll_eos (element); - - cleanup_rganalysis (element); -} - -GST_END_TEST; - -GST_START_TEST (test_no_buffer_album_1) -{ - GstElement *element = setup_rganalysis (); - - set_playing_state (element); - - /* Single track: */ - send_eos_event (element); - poll_eos (element); - - /* First album: */ - g_object_set (element, "num-tracks", 3, NULL); - - send_eos_event (element); - poll_eos (element); - fail_unless_num_tracks (element, 2); - - send_eos_event (element); - poll_eos (element); - fail_unless_num_tracks (element, 1); - - send_eos_event (element); - poll_eos (element); - fail_unless_num_tracks (element, 0); - - /* Second album: */ - g_object_set (element, "num-tracks", 2, NULL); - - send_eos_event (element); - poll_eos (element); - fail_unless_num_tracks (element, 1); - - send_eos_event (element); - poll_eos (element); - fail_unless_num_tracks (element, 0); - - /* Single track: */ - send_eos_event (element); - poll_eos (element); - fail_unless_num_tracks (element, 0); - - cleanup_rganalysis (element); -} - -GST_END_TEST; - -GST_START_TEST (test_no_buffer_album_2) -{ - GstElement *element = setup_rganalysis (); - GstTagList *tag_list; - gint accumulator = 0; - gint i; - - g_object_set (element, "num-tracks", 3, NULL); - set_playing_state (element); - - /* No buffer for the first track. */ - - send_eos_event (element); - /* No tags should be posted, there was nothing to analyze: */ - poll_eos (element); - fail_unless_num_tracks (element, 2); - - /* A test waveform with known gain result as second track: */ - - for (i = 20; i--;) - push_buffer (test_buffer_square_float_mono (&accumulator, 44100, 512, - 0.25)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.25); - fail_unless_track_gain (tag_list, -6.20); - /* Album is not finished yet: */ - fail_if_album_tags (tag_list); - gst_tag_list_free (tag_list); - fail_unless_num_tracks (element, 1); - - /* No buffer for the last track. */ - - send_eos_event (element); - - tag_list = poll_tags (element); - fail_unless_album_peak (tag_list, 0.25); - fail_unless_album_gain (tag_list, -6.20); - /* No track tags should be posted, as there was no data for it: */ - fail_if_track_tags (tag_list); - gst_tag_list_free (tag_list); - fail_unless_num_tracks (element, 0); - - cleanup_rganalysis (element); -} - -GST_END_TEST; - -GST_START_TEST (test_empty_buffers) -{ - GstElement *element = setup_rganalysis (); - - set_playing_state (element); - - /* Single track: */ - push_buffer (test_buffer_const_float_stereo (44100, 0, 0.0, 0.0)); - send_eos_event (element); - poll_eos (element); - - /* First album: */ - g_object_set (element, "num-tracks", 2, NULL); - - push_buffer (test_buffer_const_float_stereo (44100, 0, 0.0, 0.0)); - send_eos_event (element); - poll_eos (element); - fail_unless_num_tracks (element, 1); - - push_buffer (test_buffer_const_float_stereo (44100, 0, 0.0, 0.0)); - send_eos_event (element); - poll_eos (element); - fail_unless_num_tracks (element, 0); - - /* Second album, with a single track: */ - g_object_set (element, "num-tracks", 1, NULL); - push_buffer (test_buffer_const_float_stereo (44100, 0, 0.0, 0.0)); - send_eos_event (element); - poll_eos (element); - fail_unless_num_tracks (element, 0); - - /* Single track: */ - push_buffer (test_buffer_const_float_stereo (44100, 0, 0.0, 0.0)); - send_eos_event (element); - poll_eos (element); - - cleanup_rganalysis (element); -} - -GST_END_TEST; - -GST_START_TEST (test_gap_buffers) -{ - GstElement *element = setup_rganalysis (); - GstTagList *tag_list; - GstBuffer *buf; - gint accumulator = 0; - gint i; - - set_playing_state (element); - - for (i = 0; i < 60; i++) { - if (i % 3 == 0) { - /* We are cheating here; the element cannot know that these GAP buffers - * actually contain non-silence so it must skip them. */ - buf = test_buffer_square_float_mono (&accumulator, 44100, 512, 0.25); - GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_GAP); - push_buffer (buf); - - /* Verify that the base class does not lift the GAP flag: */ - fail_if (g_list_length (buffers) == 0); - if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_GAP)) - fail_unless (GST_BUFFER_FLAG_IS_SET (buffers->data, - GST_BUFFER_FLAG_GAP)); - } else { - push_buffer (test_buffer_const_float_mono (44100, 512, 0.0)); - } - } - - send_eos_event (element); - tag_list = poll_tags (element); - /* We pushed faked GAP buffers with non-silence and non-GAP buffers with - * silence, so the correct result is that the analysis only got silence: */ - fail_unless_track_peak (tag_list, 0.0); - fail_unless_track_gain (tag_list, SILENCE_GAIN); - - gst_tag_list_free (tag_list); - - cleanup_rganalysis (element); -} - -GST_END_TEST; - -/* Tests for correctness of the peak values. */ - -/* Float peak test. For stereo, one channel has the constant value of -1.369, - * the other one 0.0. This tests many things: The result peak value should - * occur on any channel. The peak is of course the absolute amplitude, so 1.369 - * should be the result. This will also detect if the code uses the absolute - * value during the comparison. If it is buggy it will return 0.0 since 0.0 > - * -1.369. Furthermore, this makes sure that there is no problem with headroom - * (exceeding 0dBFS). In the wild you get float samples > 1.0 from stuff like - * vorbis. */ - -GST_START_TEST (test_peak_float) -{ - GstElement *element = setup_rganalysis (); - GstTagList *tag_list; - - set_playing_state (element); - push_buffer (test_buffer_const_float_stereo (8000, 512, -1.369, 0.0)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 1.369); - gst_tag_list_free (tag_list); - - /* Swapped channels. */ - push_buffer (test_buffer_const_float_stereo (8000, 512, 0.0, -1.369)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 1.369); - gst_tag_list_free (tag_list); - - /* Mono. */ - push_buffer (test_buffer_const_float_mono (8000, 512, -1.369)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 1.369); - gst_tag_list_free (tag_list); - - cleanup_rganalysis (element); -} - -GST_END_TEST; - -GST_START_TEST (test_peak_int16_16) -{ - GstElement *element = setup_rganalysis (); - GstTagList *tag_list; - - set_playing_state (element); - - /* Half amplitude. */ - push_buffer (test_buffer_const_int16_stereo (8000, 16, 512, 1 << 14, 0)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.5); - gst_tag_list_free (tag_list); - - /* Swapped channels. */ - push_buffer (test_buffer_const_int16_stereo (8000, 16, 512, 0, 1 << 14)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.5); - gst_tag_list_free (tag_list); - - /* Mono. */ - push_buffer (test_buffer_const_int16_mono (8000, 16, 512, 1 << 14)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.5); - gst_tag_list_free (tag_list); - - /* Half amplitude, negative variant. */ - push_buffer (test_buffer_const_int16_stereo (8000, 16, 512, -1 << 14, 0)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.5); - gst_tag_list_free (tag_list); - - /* Swapped channels. */ - push_buffer (test_buffer_const_int16_stereo (8000, 16, 512, 0, -1 << 14)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.5); - gst_tag_list_free (tag_list); - - /* Mono. */ - push_buffer (test_buffer_const_int16_mono (8000, 16, 512, -1 << 14)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.5); - gst_tag_list_free (tag_list); - - - /* Now check for correct normalization of the peak value: Sample - * values of this format range from -32768 to 32767. So for the - * highest positive amplitude we do not reach 1.0, only for - * -32768! */ - - push_buffer (test_buffer_const_int16_stereo (8000, 16, 512, 32767, 0)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 32767. / 32768.); - gst_tag_list_free (tag_list); - - /* Swapped channels. */ - push_buffer (test_buffer_const_int16_stereo (8000, 16, 512, 0, 32767)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 32767. / 32768.); - gst_tag_list_free (tag_list); - - /* Mono. */ - push_buffer (test_buffer_const_int16_mono (8000, 16, 512, 32767)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 32767. / 32768.); - gst_tag_list_free (tag_list); - - - /* Negative variant, reaching 1.0. */ - push_buffer (test_buffer_const_int16_stereo (8000, 16, 512, -32768, 0)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 1.0); - gst_tag_list_free (tag_list); - - /* Swapped channels. */ - push_buffer (test_buffer_const_int16_stereo (8000, 16, 512, 0, -32768)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 1.0); - gst_tag_list_free (tag_list); - - /* Mono. */ - push_buffer (test_buffer_const_int16_mono (8000, 16, 512, -32768)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 1.0); - gst_tag_list_free (tag_list); - - cleanup_rganalysis (element); -} - -GST_END_TEST; - -/* Same as the test before, but with 8 bits (packed into 16 bits). */ - -GST_START_TEST (test_peak_int16_8) -{ - GstElement *element = setup_rganalysis (); - GstTagList *tag_list; - - set_playing_state (element); - - /* Half amplitude. */ - push_buffer (test_buffer_const_int16_stereo (8000, 8, 512, 1 << 6, 0)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.5); - gst_tag_list_free (tag_list); - - /* Swapped channels. */ - push_buffer (test_buffer_const_int16_stereo (8000, 8, 512, 0, 1 << 6)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.5); - gst_tag_list_free (tag_list); - - /* Mono. */ - push_buffer (test_buffer_const_int16_mono (8000, 8, 512, 1 << 6)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.5); - gst_tag_list_free (tag_list); - - - /* Half amplitude, negative variant. */ - push_buffer (test_buffer_const_int16_stereo (8000, 8, 512, -1 << 6, 0)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.5); - gst_tag_list_free (tag_list); - - /* Swapped channels. */ - push_buffer (test_buffer_const_int16_stereo (8000, 8, 512, 0, -1 << 6)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.5); - gst_tag_list_free (tag_list); - - /* Mono. */ - push_buffer (test_buffer_const_int16_mono (8000, 8, 512, -1 << 6)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.5); - gst_tag_list_free (tag_list); - - - /* Almost full amplitude (maximum positive value). */ - push_buffer (test_buffer_const_int16_stereo (8000, 8, 512, (1 << 7) - 1, 0)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.9921875); - gst_tag_list_free (tag_list); - - /* Swapped channels. */ - push_buffer (test_buffer_const_int16_stereo (8000, 8, 512, 0, (1 << 7) - 1)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.9921875); - gst_tag_list_free (tag_list); - - /* Mono. */ - push_buffer (test_buffer_const_int16_mono (8000, 8, 512, (1 << 7) - 1)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.9921875); - gst_tag_list_free (tag_list); - - - /* Full amplitude (maximum negative value). */ - push_buffer (test_buffer_const_int16_stereo (8000, 8, 512, -1 << 7, 0)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 1.0); - gst_tag_list_free (tag_list); - - /* Swapped channels. */ - push_buffer (test_buffer_const_int16_stereo (8000, 8, 512, 0, -1 << 7)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 1.0); - gst_tag_list_free (tag_list); - - /* Mono. */ - push_buffer (test_buffer_const_int16_mono (8000, 8, 512, -1 << 7)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 1.0); - gst_tag_list_free (tag_list); - - cleanup_rganalysis (element); -} - -GST_END_TEST; - -GST_START_TEST (test_peak_album) -{ - GstElement *element = setup_rganalysis (); - GstTagList *tag_list; - - g_object_set (element, "num-tracks", 2, NULL); - set_playing_state (element); - - push_buffer (test_buffer_const_float_stereo (8000, 1024, 1.0, 0.0)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 1.0); - fail_if_album_tags (tag_list); - gst_tag_list_free (tag_list); - fail_unless_num_tracks (element, 1); - - push_buffer (test_buffer_const_float_stereo (8000, 1024, 0.0, 0.5)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.5); - fail_unless_album_peak (tag_list, 1.0); - gst_tag_list_free (tag_list); - fail_unless_num_tracks (element, 0); - - /* Try a second album: */ - g_object_set (element, "num-tracks", 3, NULL); - - push_buffer (test_buffer_const_float_stereo (8000, 1024, 0.4, 0.4)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.4); - fail_if_album_tags (tag_list); - gst_tag_list_free (tag_list); - fail_unless_num_tracks (element, 2); - - push_buffer (test_buffer_const_float_stereo (8000, 1024, 0.45, 0.45)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.45); - fail_if_album_tags (tag_list); - gst_tag_list_free (tag_list); - fail_unless_num_tracks (element, 1); - - push_buffer (test_buffer_const_float_stereo (8000, 1024, 0.2, 0.2)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.2); - fail_unless_album_peak (tag_list, 0.45); - gst_tag_list_free (tag_list); - fail_unless_num_tracks (element, 0); - - /* And now a single track, not in album mode (num-tracks is 0 - * now): */ - push_buffer (test_buffer_const_float_stereo (8000, 1024, 0.1, 0.1)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.1); - fail_if_album_tags (tag_list); - gst_tag_list_free (tag_list); - - cleanup_rganalysis (element); -} - -GST_END_TEST; - -/* Switching from track to album mode. */ - -GST_START_TEST (test_peak_track_album) -{ - GstElement *element = setup_rganalysis (); - GstTagList *tag_list; - - set_playing_state (element); - - push_buffer (test_buffer_const_float_mono (8000, 1024, 1.0)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 1.0); - fail_if_album_tags (tag_list); - gst_tag_list_free (tag_list); - - g_object_set (element, "num-tracks", 1, NULL); - push_buffer (test_buffer_const_float_mono (8000, 1024, 0.5)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.5); - fail_unless_album_peak (tag_list, 0.5); - gst_tag_list_free (tag_list); - fail_unless_num_tracks (element, 0); - - cleanup_rganalysis (element); -} - -GST_END_TEST; - -/* Disabling album processing before the end of the album. Probably a rare edge - * case and applications should not rely on this to work. They need to send the - * element to the READY state to clear up after an aborted album anyway since - * they might need to process another album afterwards. */ - -GST_START_TEST (test_peak_album_abort_to_track) -{ - GstElement *element = setup_rganalysis (); - GstTagList *tag_list; - - g_object_set (element, "num-tracks", 2, NULL); - set_playing_state (element); - - push_buffer (test_buffer_const_float_stereo (8000, 1024, 1.0, 0.0)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 1.0); - fail_if_album_tags (tag_list); - gst_tag_list_free (tag_list); - fail_unless_num_tracks (element, 1); - - g_object_set (element, "num-tracks", 0, NULL); - - push_buffer (test_buffer_const_float_stereo (8000, 1024, 0.0, 0.5)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.5); - fail_if_album_tags (tag_list); - gst_tag_list_free (tag_list); - - cleanup_rganalysis (element); -} - -GST_END_TEST; - -GST_START_TEST (test_gain_album) -{ - GstElement *element = setup_rganalysis (); - GstTagList *tag_list; - gint accumulator; - gint i; - - g_object_set (element, "num-tracks", 3, NULL); - set_playing_state (element); - - /* The three tracks are constructed such that if any of these is in fact - * ignored for the album gain, the album gain will differ. */ - - accumulator = 0; - for (i = 8; i--;) - push_buffer (test_buffer_square_float_stereo (&accumulator, 44100, 512, - 0.75, 0.75)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.75); - fail_unless_track_gain (tag_list, -15.70); - fail_if_album_tags (tag_list); - gst_tag_list_free (tag_list); - - accumulator = 0; - for (i = 12; i--;) - push_buffer (test_buffer_square_float_stereo (&accumulator, 44100, 512, - 0.5, 0.5)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.5); - fail_unless_track_gain (tag_list, -12.22); - fail_if_album_tags (tag_list); - gst_tag_list_free (tag_list); - - accumulator = 0; - for (i = 180; i--;) - push_buffer (test_buffer_square_float_stereo (&accumulator, 44100, 512, - 0.25, 0.25)); - send_eos_event (element); - - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.25); - fail_unless_track_gain (tag_list, -6.20); - fail_unless_album_peak (tag_list, 0.75); - /* Strangely, wavegain reports -12.17 for the album, but the fixed - * metaflac agrees to us. Could be a 32767 vs. 32768 issue. */ - fail_unless_album_gain (tag_list, -12.18); - gst_tag_list_free (tag_list); - - cleanup_rganalysis (element); -} - -GST_END_TEST; - -/* Checks ensuring that the "forced" property works as advertised. */ - -GST_START_TEST (test_forced) -{ - GstElement *element = setup_rganalysis (); - GstTagList *tag_list; - gint accumulator = 0; - gint i; - - g_object_set (element, "forced", FALSE, NULL); - set_playing_state (element); - - tag_list = gst_tag_list_new (); - /* Provided values are totally arbitrary. */ - gst_tag_list_add (tag_list, GST_TAG_MERGE_APPEND, - GST_TAG_TRACK_PEAK, 1.0, GST_TAG_TRACK_GAIN, 2.21, NULL); - send_tag_event (element, tag_list); - - for (i = 20; i--;) - push_buffer (test_buffer_const_float_stereo (44100, 512, 0.5, 0.5)); - send_eos_event (element); - /* This fails if a tag message is generated: */ - poll_eos (element); - - /* Now back to a track without tags. */ - - for (i = 20; i--;) - push_buffer (test_buffer_square_float_stereo (&accumulator, 44100, 512, - 0.25, 0.25)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.25); - fail_unless_track_gain (tag_list, get_expected_gain (44100)); - gst_tag_list_free (tag_list); - - cleanup_rganalysis (element); -} - -GST_END_TEST; - -/* Sending track gain and peak in separate tag lists. */ - -GST_START_TEST (test_forced_separate) -{ - GstElement *element = setup_rganalysis (); - GstTagList *tag_list; - gint accumulator = 0; - gint i; - - g_object_set (element, "forced", FALSE, NULL); - set_playing_state (element); - - tag_list = gst_tag_list_new (); - gst_tag_list_add (tag_list, GST_TAG_MERGE_APPEND, GST_TAG_TRACK_GAIN, 2.21, - NULL); - send_tag_event (element, tag_list); - - tag_list = gst_tag_list_new (); - gst_tag_list_add (tag_list, GST_TAG_MERGE_APPEND, GST_TAG_TRACK_PEAK, 1.0, - NULL); - send_tag_event (element, tag_list); - - for (i = 20; i--;) - push_buffer (test_buffer_square_float_stereo (&accumulator, 44100, 512, - 0.5, 0.5)); - send_eos_event (element); - /* This fails if a tag message is generated: */ - poll_eos (element); - - /* Now a track without tags. */ - - accumulator = 0; - for (i = 20; i--;) - push_buffer (test_buffer_square_float_stereo (&accumulator, 44100, 512, - 0.25, 0.25)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.25); - fail_unless_track_gain (tag_list, get_expected_gain (44100)); - fail_if_album_tags (tag_list); - gst_tag_list_free (tag_list); - - cleanup_rganalysis (element); -} - -GST_END_TEST; - -/* A TAG event is sent _after_ data has already been processed. In real - * pipelines, this could happen if there is more than one rganalysis element (by - * accident). While it would have analyzed all the data prior to receiving the - * event, I expect it to not post its results if not forced. This test is - * almost equivalent to test_forced. */ - -GST_START_TEST (test_forced_after_data) -{ - GstElement *element = setup_rganalysis (); - GstTagList *tag_list; - gint accumulator = 0; - gint i; - - g_object_set (element, "forced", FALSE, NULL); - set_playing_state (element); - - for (i = 20; i--;) - push_buffer (test_buffer_const_float_stereo (8000, 512, 0.5, 0.5)); - - tag_list = gst_tag_list_new (); - gst_tag_list_add (tag_list, GST_TAG_MERGE_APPEND, - GST_TAG_TRACK_PEAK, 1.0, GST_TAG_TRACK_GAIN, 2.21, NULL); - send_tag_event (element, tag_list); - - send_eos_event (element); - poll_eos (element); - - /* Now back to a normal track, this one has no tags: */ - for (i = 20; i--;) - push_buffer (test_buffer_square_float_stereo (&accumulator, 8000, 512, 0.25, - 0.25)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.25); - fail_unless_track_gain (tag_list, get_expected_gain (8000)); - gst_tag_list_free (tag_list); - - cleanup_rganalysis (element); -} - -GST_END_TEST; - -/* Like test_forced, but *analyze* an album afterwards. The two tests following - * this one check the *skipping* of albums. */ - -GST_START_TEST (test_forced_album) -{ - GstElement *element = setup_rganalysis (); - GstTagList *tag_list; - gint accumulator; - gint i; - - g_object_set (element, "forced", FALSE, NULL); - set_playing_state (element); - - tag_list = gst_tag_list_new (); - /* Provided values are totally arbitrary. */ - gst_tag_list_add (tag_list, GST_TAG_MERGE_APPEND, - GST_TAG_TRACK_PEAK, 1.0, GST_TAG_TRACK_GAIN, 2.21, NULL); - send_tag_event (element, tag_list); - - accumulator = 0; - for (i = 20; i--;) - push_buffer (test_buffer_square_float_stereo (&accumulator, 44100, 512, - 0.5, 0.5)); - send_eos_event (element); - /* This fails if a tag message is generated: */ - poll_eos (element); - - /* Now an album without tags. */ - g_object_set (element, "num-tracks", 2, NULL); - - accumulator = 0; - for (i = 20; i--;) - push_buffer (test_buffer_square_float_stereo (&accumulator, 44100, 512, - 0.25, 0.25)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.25); - fail_unless_track_gain (tag_list, get_expected_gain (44100)); - fail_if_album_tags (tag_list); - gst_tag_list_free (tag_list); - fail_unless_num_tracks (element, 1); - - accumulator = 0; - for (i = 20; i--;) - push_buffer (test_buffer_square_float_stereo (&accumulator, 44100, 512, - 0.25, 0.25)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.25); - fail_unless_track_gain (tag_list, get_expected_gain (44100)); - fail_unless_album_peak (tag_list, 0.25); - fail_unless_album_gain (tag_list, get_expected_gain (44100)); - gst_tag_list_free (tag_list); - fail_unless_num_tracks (element, 0); - - cleanup_rganalysis (element); -} - -GST_END_TEST; - -GST_START_TEST (test_forced_album_skip) -{ - GstElement *element = setup_rganalysis (); - GstTagList *tag_list; - gint accumulator = 0; - gint i; - - g_object_set (element, "forced", FALSE, "num-tracks", 2, NULL); - set_playing_state (element); - - tag_list = gst_tag_list_new (); - /* Provided values are totally arbitrary. */ - gst_tag_list_add (tag_list, GST_TAG_MERGE_APPEND, - GST_TAG_TRACK_PEAK, 0.75, GST_TAG_TRACK_GAIN, 2.21, - GST_TAG_ALBUM_PEAK, 0.80, GST_TAG_ALBUM_GAIN, -0.11, NULL); - send_tag_event (element, tag_list); - - for (i = 20; i--;) - push_buffer (test_buffer_square_float_stereo (&accumulator, 8000, 512, 0.25, - 0.25)); - send_eos_event (element); - poll_eos (element); - fail_unless_num_tracks (element, 1); - - /* This track has no tags, but needs to be skipped anyways since we - * are in album processing mode. */ - for (i = 20; i--;) - push_buffer (test_buffer_const_float_stereo (8000, 512, 0.0, 0.0)); - send_eos_event (element); - poll_eos (element); - fail_unless_num_tracks (element, 0); - - /* Normal track after the album. Of course not to be skipped. */ - accumulator = 0; - for (i = 20; i--;) - push_buffer (test_buffer_square_float_stereo (&accumulator, 8000, 512, 0.25, - 0.25)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.25); - fail_unless_track_gain (tag_list, get_expected_gain (8000)); - fail_if_album_tags (tag_list); - gst_tag_list_free (tag_list); - - cleanup_rganalysis (element); -} - -GST_END_TEST; - -GST_START_TEST (test_forced_album_no_skip) -{ - GstElement *element = setup_rganalysis (); - GstTagList *tag_list; - gint accumulator = 0; - gint i; - - g_object_set (element, "forced", FALSE, "num-tracks", 2, NULL); - set_playing_state (element); - - for (i = 20; i--;) - push_buffer (test_buffer_square_float_stereo (&accumulator, 8000, 512, 0.25, - 0.25)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.25); - fail_unless_track_gain (tag_list, get_expected_gain (8000)); - fail_if_album_tags (tag_list); - gst_tag_list_free (tag_list); - fail_unless_num_tracks (element, 1); - - /* The second track has indeed full tags, but although being not forced, this - * one has to be processed because album processing is on. */ - tag_list = gst_tag_list_new (); - /* Provided values are totally arbitrary. */ - gst_tag_list_add (tag_list, GST_TAG_MERGE_APPEND, - GST_TAG_TRACK_PEAK, 0.75, GST_TAG_TRACK_GAIN, 2.21, - GST_TAG_ALBUM_PEAK, 0.80, GST_TAG_ALBUM_GAIN, -0.11, NULL); - send_tag_event (element, tag_list); - for (i = 20; i--;) - push_buffer (test_buffer_const_float_stereo (8000, 512, 0.0, 0.0)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.0); - fail_unless_track_gain (tag_list, SILENCE_GAIN); - /* Second track was just silence so the album peak equals the first - * track's peak. */ - fail_unless_album_peak (tag_list, 0.25); - /* Statistical processing leads to the second track being - * ignored for the gain (because it is so short): */ - fail_unless_album_gain (tag_list, get_expected_gain (8000)); - gst_tag_list_free (tag_list); - fail_unless_num_tracks (element, 0); - - cleanup_rganalysis (element); -} - -GST_END_TEST; - -GST_START_TEST (test_forced_abort_album_no_skip) -{ - GstElement *element = setup_rganalysis (); - GstTagList *tag_list; - gint accumulator = 0; - gint i; - - g_object_set (element, "forced", FALSE, "num-tracks", 2, NULL); - set_playing_state (element); - - for (i = 20; i--;) - push_buffer (test_buffer_square_float_stereo (&accumulator, 8000, 512, 0.25, - 0.25)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.25); - fail_unless_track_gain (tag_list, get_expected_gain (8000)); - fail_if_album_tags (tag_list); - gst_tag_list_free (tag_list); - fail_unless_num_tracks (element, 1); - - /* Disabling album processing before end of album: */ - g_object_set (element, "num-tracks", 0, NULL); - - /* Processing a track that has to be skipped. */ - tag_list = gst_tag_list_new (); - /* Provided values are totally arbitrary. */ - gst_tag_list_add (tag_list, GST_TAG_MERGE_APPEND, - GST_TAG_TRACK_PEAK, 0.75, GST_TAG_TRACK_GAIN, 2.21, - GST_TAG_ALBUM_PEAK, 0.80, GST_TAG_ALBUM_GAIN, -0.11, NULL); - send_tag_event (element, tag_list); - for (i = 20; i--;) - push_buffer (test_buffer_const_float_stereo (8000, 512, 0.0, 0.0)); - send_eos_event (element); - poll_eos (element); - - cleanup_rganalysis (element); -} - -GST_END_TEST; - -GST_START_TEST (test_reference_level) -{ - GstElement *element = setup_rganalysis (); - GstTagList *tag_list; - gdouble ref_level; - gint accumulator = 0; - gint i; - - set_playing_state (element); - - for (i = 20; i--;) - push_buffer (test_buffer_square_float_stereo (&accumulator, 44100, 512, - 0.25, 0.25)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.25); - fail_unless_track_gain (tag_list, get_expected_gain (44100)); - fail_if_album_tags (tag_list); - fail_unless (gst_tag_list_get_double (tag_list, GST_TAG_REFERENCE_LEVEL, - &ref_level) && MATCH_GAIN (ref_level, 89.), - "Incorrect reference level tag"); - gst_tag_list_free (tag_list); - - g_object_set (element, "reference-level", 83., "num-tracks", 2, NULL); - - for (i = 20; i--;) - push_buffer (test_buffer_square_float_stereo (&accumulator, 44100, 512, - 0.25, 0.25)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.25); - fail_unless_track_gain (tag_list, get_expected_gain (44100) - 6.); - fail_if_album_tags (tag_list); - fail_unless (gst_tag_list_get_double (tag_list, GST_TAG_REFERENCE_LEVEL, - &ref_level) && MATCH_GAIN (ref_level, 83.), - "Incorrect reference level tag"); - gst_tag_list_free (tag_list); - - accumulator = 0; - for (i = 20; i--;) - push_buffer (test_buffer_square_float_stereo (&accumulator, 44100, 512, - 0.25, 0.25)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.25); - fail_unless_track_gain (tag_list, get_expected_gain (44100) - 6.); - fail_unless_album_peak (tag_list, 0.25); - /* We provided the same waveform twice, with a reset separating - * them. Therefore, the album gain matches the track gain. */ - fail_unless_album_gain (tag_list, get_expected_gain (44100) - 6.); - fail_unless (gst_tag_list_get_double (tag_list, GST_TAG_REFERENCE_LEVEL, - &ref_level) && MATCH_GAIN (ref_level, 83.), - "Incorrect reference level tag"); - gst_tag_list_free (tag_list); - - cleanup_rganalysis (element); -} - -GST_END_TEST; - -GST_START_TEST (test_all_formats) -{ - GstElement *element = setup_rganalysis (); - GstTagList *tag_list; - gint accumulator = 0; - gint i, j; - - set_playing_state (element); - for (i = G_N_ELEMENTS (supported_rates); i--;) { - accumulator = 0; - for (j = 0; j < 4; j++) - push_buffer (test_buffer_square_float_stereo (&accumulator, - supported_rates[i].sample_rate, 512, 0.25, 0.25)); - for (j = 0; j < 3; j++) - push_buffer (test_buffer_square_float_mono (&accumulator, - supported_rates[i].sample_rate, 512, 0.25)); - for (j = 0; j < 4; j++) - push_buffer (test_buffer_square_int16_stereo (&accumulator, - supported_rates[i].sample_rate, 16, 512, 1 << 13, 1 << 13)); - for (j = 0; j < 3; j++) - push_buffer (test_buffer_square_int16_mono (&accumulator, - supported_rates[i].sample_rate, 16, 512, 1 << 13)); - for (j = 0; j < 3; j++) - push_buffer (test_buffer_square_int16_stereo (&accumulator, - supported_rates[i].sample_rate, 8, 512, 1 << 5, 1 << 5)); - for (j = 0; j < 3; j++) - push_buffer (test_buffer_square_int16_mono (&accumulator, - supported_rates[i].sample_rate, 8, 512, 1 << 5)); - send_eos_event (element); - tag_list = poll_tags (element); - fail_unless_track_peak (tag_list, 0.25); - fail_unless_track_gain (tag_list, supported_rates[i].gain); - gst_tag_list_free (tag_list); - } - - cleanup_rganalysis (element); -} - -GST_END_TEST; - -/* Checks ensuring all advertised supported sample rates are really - * accepted, for integer and float, mono and stereo. This also - * verifies that the correct gain is computed for all formats (except - * odd bit depths). */ - -#define MAKE_GAIN_TEST_FLOAT_MONO(sample_rate) \ - GST_START_TEST (test_gain_float_mono_##sample_rate) \ -{ \ - GstElement *element = setup_rganalysis (); \ - GstTagList *tag_list; \ - gint accumulator = 0; \ - gint i; \ - \ - set_playing_state (element); \ - \ - for (i = 0; i < 20; i++) \ - push_buffer (test_buffer_square_float_mono (&accumulator, \ - sample_rate, 512, 0.25)); \ - send_eos_event (element); \ - tag_list = poll_tags (element); \ - fail_unless_track_peak (tag_list, 0.25); \ - fail_unless_track_gain (tag_list, \ - get_expected_gain (sample_rate)); \ - gst_tag_list_free (tag_list); \ - \ - cleanup_rganalysis (element); \ -} \ - \ -GST_END_TEST; - -#define MAKE_GAIN_TEST_FLOAT_STEREO(sample_rate) \ - GST_START_TEST (test_gain_float_stereo_##sample_rate) \ -{ \ - GstElement *element = setup_rganalysis (); \ - GstTagList *tag_list; \ - gint accumulator = 0; \ - gint i; \ - \ - set_playing_state (element); \ - \ - for (i = 0; i < 20; i++) \ - push_buffer (test_buffer_square_float_stereo (&accumulator, \ - sample_rate, 512, 0.25, 0.25)); \ - send_eos_event (element); \ - tag_list = poll_tags (element); \ - fail_unless_track_peak (tag_list, 0.25); \ - fail_unless_track_gain (tag_list, \ - get_expected_gain (sample_rate)); \ - gst_tag_list_free (tag_list); \ - \ - cleanup_rganalysis (element); \ -} \ - \ -GST_END_TEST; - -#define MAKE_GAIN_TEST_INT16_MONO(sample_rate, depth) \ - GST_START_TEST (test_gain_int16_##depth##_mono_##sample_rate) \ -{ \ - GstElement *element = setup_rganalysis (); \ - GstTagList *tag_list; \ - gint accumulator = 0; \ - gint i; \ - \ - set_playing_state (element); \ - \ - for (i = 0; i < 20; i++) \ - push_buffer (test_buffer_square_int16_mono (&accumulator, \ - sample_rate, depth, 512, 1 << (13 + depth - 16))); \ - \ - send_eos_event (element); \ - tag_list = poll_tags (element); \ - fail_unless_track_peak (tag_list, 0.25); \ - fail_unless_track_gain (tag_list, \ - get_expected_gain (sample_rate)); \ - gst_tag_list_free (tag_list); \ - \ - cleanup_rganalysis (element); \ -} \ - \ -GST_END_TEST; - -#define MAKE_GAIN_TEST_INT16_STEREO(sample_rate, depth) \ - GST_START_TEST (test_gain_int16_##depth##_stereo_##sample_rate) \ -{ \ - GstElement *element = setup_rganalysis (); \ - GstTagList *tag_list; \ - gint accumulator = 0; \ - gint i; \ - \ - set_playing_state (element); \ - \ - for (i = 0; i < 20; i++) \ - push_buffer (test_buffer_square_int16_stereo (&accumulator, \ - sample_rate, depth, 512, 1 << (13 + depth - 16), \ - 1 << (13 + depth - 16))); \ - send_eos_event (element); \ - tag_list = poll_tags (element); \ - fail_unless_track_peak (tag_list, 0.25); \ - fail_unless_track_gain (tag_list, \ - get_expected_gain (sample_rate)); \ - gst_tag_list_free (tag_list); \ - \ - cleanup_rganalysis (element); \ -} \ - \ -GST_END_TEST; - -MAKE_GAIN_TEST_FLOAT_MONO (8000); -MAKE_GAIN_TEST_FLOAT_MONO (11025); -MAKE_GAIN_TEST_FLOAT_MONO (12000); -MAKE_GAIN_TEST_FLOAT_MONO (16000); -MAKE_GAIN_TEST_FLOAT_MONO (22050); -MAKE_GAIN_TEST_FLOAT_MONO (24000); -MAKE_GAIN_TEST_FLOAT_MONO (32000); -MAKE_GAIN_TEST_FLOAT_MONO (44100); -MAKE_GAIN_TEST_FLOAT_MONO (48000); - -MAKE_GAIN_TEST_FLOAT_STEREO (8000); -MAKE_GAIN_TEST_FLOAT_STEREO (11025); -MAKE_GAIN_TEST_FLOAT_STEREO (12000); -MAKE_GAIN_TEST_FLOAT_STEREO (16000); -MAKE_GAIN_TEST_FLOAT_STEREO (22050); -MAKE_GAIN_TEST_FLOAT_STEREO (24000); -MAKE_GAIN_TEST_FLOAT_STEREO (32000); -MAKE_GAIN_TEST_FLOAT_STEREO (44100); -MAKE_GAIN_TEST_FLOAT_STEREO (48000); - -MAKE_GAIN_TEST_INT16_MONO (8000, 16); -MAKE_GAIN_TEST_INT16_MONO (11025, 16); -MAKE_GAIN_TEST_INT16_MONO (12000, 16); -MAKE_GAIN_TEST_INT16_MONO (16000, 16); -MAKE_GAIN_TEST_INT16_MONO (22050, 16); -MAKE_GAIN_TEST_INT16_MONO (24000, 16); -MAKE_GAIN_TEST_INT16_MONO (32000, 16); -MAKE_GAIN_TEST_INT16_MONO (44100, 16); -MAKE_GAIN_TEST_INT16_MONO (48000, 16); - -MAKE_GAIN_TEST_INT16_STEREO (8000, 16); -MAKE_GAIN_TEST_INT16_STEREO (11025, 16); -MAKE_GAIN_TEST_INT16_STEREO (12000, 16); -MAKE_GAIN_TEST_INT16_STEREO (16000, 16); -MAKE_GAIN_TEST_INT16_STEREO (22050, 16); -MAKE_GAIN_TEST_INT16_STEREO (24000, 16); -MAKE_GAIN_TEST_INT16_STEREO (32000, 16); -MAKE_GAIN_TEST_INT16_STEREO (44100, 16); -MAKE_GAIN_TEST_INT16_STEREO (48000, 16); - -MAKE_GAIN_TEST_INT16_MONO (8000, 8); -MAKE_GAIN_TEST_INT16_MONO (11025, 8); -MAKE_GAIN_TEST_INT16_MONO (12000, 8); -MAKE_GAIN_TEST_INT16_MONO (16000, 8); -MAKE_GAIN_TEST_INT16_MONO (22050, 8); -MAKE_GAIN_TEST_INT16_MONO (24000, 8); -MAKE_GAIN_TEST_INT16_MONO (32000, 8); -MAKE_GAIN_TEST_INT16_MONO (44100, 8); -MAKE_GAIN_TEST_INT16_MONO (48000, 8); - -MAKE_GAIN_TEST_INT16_STEREO (8000, 8); -MAKE_GAIN_TEST_INT16_STEREO (11025, 8); -MAKE_GAIN_TEST_INT16_STEREO (12000, 8); -MAKE_GAIN_TEST_INT16_STEREO (16000, 8); -MAKE_GAIN_TEST_INT16_STEREO (22050, 8); -MAKE_GAIN_TEST_INT16_STEREO (24000, 8); -MAKE_GAIN_TEST_INT16_STEREO (32000, 8); -MAKE_GAIN_TEST_INT16_STEREO (44100, 8); -MAKE_GAIN_TEST_INT16_STEREO (48000, 8); - -Suite * -rganalysis_suite (void) -{ - Suite *s = suite_create ("rganalysis"); - TCase *tc_chain = tcase_create ("general"); - - suite_add_tcase (s, tc_chain); - - tcase_add_test (tc_chain, test_no_buffer); - tcase_add_test (tc_chain, test_no_buffer_album_1); - tcase_add_test (tc_chain, test_no_buffer_album_2); - tcase_add_test (tc_chain, test_empty_buffers); - tcase_add_test (tc_chain, test_gap_buffers); - - tcase_add_test (tc_chain, test_peak_float); - tcase_add_test (tc_chain, test_peak_int16_16); - tcase_add_test (tc_chain, test_peak_int16_8); - - tcase_add_test (tc_chain, test_peak_album); - tcase_add_test (tc_chain, test_peak_track_album); - tcase_add_test (tc_chain, test_peak_album_abort_to_track); - - tcase_add_test (tc_chain, test_gain_album); - - tcase_add_test (tc_chain, test_forced); - tcase_add_test (tc_chain, test_forced_separate); - tcase_add_test (tc_chain, test_forced_after_data); - tcase_add_test (tc_chain, test_forced_album); - tcase_add_test (tc_chain, test_forced_album_skip); - tcase_add_test (tc_chain, test_forced_album_no_skip); - tcase_add_test (tc_chain, test_forced_abort_album_no_skip); - - tcase_add_test (tc_chain, test_reference_level); - - tcase_add_test (tc_chain, test_all_formats); - - tcase_add_test (tc_chain, test_gain_float_mono_8000); - tcase_add_test (tc_chain, test_gain_float_mono_11025); - tcase_add_test (tc_chain, test_gain_float_mono_12000); - tcase_add_test (tc_chain, test_gain_float_mono_16000); - tcase_add_test (tc_chain, test_gain_float_mono_22050); - tcase_add_test (tc_chain, test_gain_float_mono_24000); - tcase_add_test (tc_chain, test_gain_float_mono_32000); - tcase_add_test (tc_chain, test_gain_float_mono_44100); - tcase_add_test (tc_chain, test_gain_float_mono_48000); - - tcase_add_test (tc_chain, test_gain_float_stereo_8000); - tcase_add_test (tc_chain, test_gain_float_stereo_11025); - tcase_add_test (tc_chain, test_gain_float_stereo_12000); - tcase_add_test (tc_chain, test_gain_float_stereo_16000); - tcase_add_test (tc_chain, test_gain_float_stereo_22050); - tcase_add_test (tc_chain, test_gain_float_stereo_24000); - tcase_add_test (tc_chain, test_gain_float_stereo_32000); - tcase_add_test (tc_chain, test_gain_float_stereo_44100); - tcase_add_test (tc_chain, test_gain_float_stereo_48000); - - tcase_add_test (tc_chain, test_gain_int16_16_mono_8000); - tcase_add_test (tc_chain, test_gain_int16_16_mono_11025); - tcase_add_test (tc_chain, test_gain_int16_16_mono_12000); - tcase_add_test (tc_chain, test_gain_int16_16_mono_16000); - tcase_add_test (tc_chain, test_gain_int16_16_mono_22050); - tcase_add_test (tc_chain, test_gain_int16_16_mono_24000); - tcase_add_test (tc_chain, test_gain_int16_16_mono_32000); - tcase_add_test (tc_chain, test_gain_int16_16_mono_44100); - tcase_add_test (tc_chain, test_gain_int16_16_mono_48000); - - tcase_add_test (tc_chain, test_gain_int16_16_stereo_8000); - tcase_add_test (tc_chain, test_gain_int16_16_stereo_11025); - tcase_add_test (tc_chain, test_gain_int16_16_stereo_12000); - tcase_add_test (tc_chain, test_gain_int16_16_stereo_16000); - tcase_add_test (tc_chain, test_gain_int16_16_stereo_22050); - tcase_add_test (tc_chain, test_gain_int16_16_stereo_24000); - tcase_add_test (tc_chain, test_gain_int16_16_stereo_32000); - tcase_add_test (tc_chain, test_gain_int16_16_stereo_44100); - tcase_add_test (tc_chain, test_gain_int16_16_stereo_48000); - - tcase_add_test (tc_chain, test_gain_int16_8_mono_8000); - tcase_add_test (tc_chain, test_gain_int16_8_mono_11025); - tcase_add_test (tc_chain, test_gain_int16_8_mono_12000); - tcase_add_test (tc_chain, test_gain_int16_8_mono_16000); - tcase_add_test (tc_chain, test_gain_int16_8_mono_22050); - tcase_add_test (tc_chain, test_gain_int16_8_mono_24000); - tcase_add_test (tc_chain, test_gain_int16_8_mono_32000); - tcase_add_test (tc_chain, test_gain_int16_8_mono_44100); - tcase_add_test (tc_chain, test_gain_int16_8_mono_48000); - - tcase_add_test (tc_chain, test_gain_int16_8_stereo_8000); - tcase_add_test (tc_chain, test_gain_int16_8_stereo_11025); - tcase_add_test (tc_chain, test_gain_int16_8_stereo_12000); - tcase_add_test (tc_chain, test_gain_int16_8_stereo_16000); - tcase_add_test (tc_chain, test_gain_int16_8_stereo_22050); - tcase_add_test (tc_chain, test_gain_int16_8_stereo_24000); - tcase_add_test (tc_chain, test_gain_int16_8_stereo_32000); - tcase_add_test (tc_chain, test_gain_int16_8_stereo_44100); - tcase_add_test (tc_chain, test_gain_int16_8_stereo_48000); - - return s; -} - -int -main (int argc, char **argv) -{ - gint nf; - - Suite *s = rganalysis_suite (); - SRunner *sr = srunner_create (s); - - gst_check_init (&argc, &argv); - - srunner_run_all (sr, CK_ENV); - nf = srunner_ntests_failed (sr); - srunner_free (sr); - - return nf; -} |