Blame tests/check/elements/rganalysis.c

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