tests: fix audioresample formats
[platform/upstream/gstreamer.git] / tests / check / elements / audioresample.c
1 /* GStreamer
2  *
3  * unit test for audioresample, based on the audioresample unit test
4  *
5  * Copyright (C) <2005> Thomas Vander Stichele <thomas at apestaart dot org>
6  * Copyright (C) <2006> Tim-Philipp Müller <tim at centricular net>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 #include <unistd.h>
25
26 #include <gst/check/gstcheck.h>
27
28 #include <gst/audio/audio.h>
29
30 #include <gst/fft/gstfft.h>
31 #include <gst/fft/gstffts16.h>
32 #include <gst/fft/gstffts32.h>
33 #include <gst/fft/gstfftf32.h>
34 #include <gst/fft/gstfftf64.h>
35
36 /* For ease of programming we use globals to keep refs for our floating
37  * src and sink pads we create; otherwise we always have to do get_pad,
38  * get_peer, and then remove references in every test function */
39 static GstPad *mysrcpad, *mysinkpad;
40
41 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
42 #define FORMATS_F  "{ F32LE, F64LE }"
43 #define FORMATS_I  "{ S16LE, S32LE }"
44 #else
45 #define FORMATS_F  "{ F32BE, F64BE }"
46 #define FORMATS_I  "{ S16BE, S32BE }"
47 #endif
48
49 #define RESAMPLE_CAPS_FLOAT             \
50     "audio/x-raw, "                     \
51     "formats = (string) "FORMATS_F", "  \
52     "channels = (int) [ 1, MAX ], "     \
53     "rate = (int) [ 1,  MAX ]"
54
55 #define RESAMPLE_CAPS_INT               \
56     "audio/x-raw, "                     \
57     "formats = (string) "FORMATS_I", "  \
58     "channels = (int) [ 1, MAX ], "     \
59     "rate = (int) [ 1,  MAX ]"
60
61 #define RESAMPLE_CAPS_TEMPLATE_STRING   \
62     RESAMPLE_CAPS_FLOAT " ; " \
63     RESAMPLE_CAPS_INT
64
65 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
66     GST_PAD_SINK,
67     GST_PAD_ALWAYS,
68     GST_STATIC_CAPS (RESAMPLE_CAPS_TEMPLATE_STRING)
69     );
70 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
71     GST_PAD_SRC,
72     GST_PAD_ALWAYS,
73     GST_STATIC_CAPS (RESAMPLE_CAPS_TEMPLATE_STRING)
74     );
75
76 static GstElement *
77 setup_audioresample (int channels, int inrate, int outrate, int width,
78     gboolean fp)
79 {
80   GstElement *audioresample;
81   GstCaps *caps;
82   GstStructure *structure;
83
84   GST_DEBUG ("setup_audioresample");
85   audioresample = gst_check_setup_element ("audioresample");
86
87   if (fp)
88     caps = gst_caps_from_string (RESAMPLE_CAPS_FLOAT);
89   else
90     caps = gst_caps_from_string (RESAMPLE_CAPS_INT);
91   structure = gst_caps_get_structure (caps, 0);
92   gst_structure_set (structure, "channels", G_TYPE_INT, channels,
93       "rate", G_TYPE_INT, inrate, "width", G_TYPE_INT, width, NULL);
94   if (!fp)
95     gst_structure_set (structure, "depth", G_TYPE_INT, width, NULL);
96   fail_unless (gst_caps_is_fixed (caps));
97
98   fail_unless (gst_element_set_state (audioresample,
99           GST_STATE_PAUSED) == GST_STATE_CHANGE_SUCCESS,
100       "could not set to paused");
101
102   mysrcpad = gst_check_setup_src_pad (audioresample, &srctemplate);
103   gst_pad_set_caps (mysrcpad, caps);
104   gst_caps_unref (caps);
105
106   if (fp)
107     caps = gst_caps_from_string (RESAMPLE_CAPS_FLOAT);
108   else
109     caps = gst_caps_from_string (RESAMPLE_CAPS_INT);
110   structure = gst_caps_get_structure (caps, 0);
111   gst_structure_set (structure, "channels", G_TYPE_INT, channels,
112       "rate", G_TYPE_INT, outrate, "width", G_TYPE_INT, width, NULL);
113   if (!fp)
114     gst_structure_set (structure, "depth", G_TYPE_INT, width, NULL);
115   fail_unless (gst_caps_is_fixed (caps));
116
117   mysinkpad = gst_check_setup_sink_pad (audioresample, &sinktemplate);
118   /* this installs a getcaps func that will always return the caps we set
119    * later */
120   gst_pad_set_caps (mysinkpad, caps);
121   gst_pad_use_fixed_caps (mysinkpad);
122
123   gst_pad_set_active (mysinkpad, TRUE);
124   gst_pad_set_active (mysrcpad, TRUE);
125
126   gst_caps_unref (caps);
127
128   return audioresample;
129 }
130
131 static void
132 cleanup_audioresample (GstElement * audioresample)
133 {
134   GST_DEBUG ("cleanup_audioresample");
135
136   fail_unless (gst_element_set_state (audioresample,
137           GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to NULL");
138
139   gst_pad_set_active (mysrcpad, FALSE);
140   gst_pad_set_active (mysinkpad, FALSE);
141   gst_check_teardown_src_pad (audioresample);
142   gst_check_teardown_sink_pad (audioresample);
143   gst_check_teardown_element (audioresample);
144   gst_check_drop_buffers ();
145 }
146
147 static void
148 fail_unless_perfect_stream (void)
149 {
150   guint64 timestamp = 0L, duration = 0L;
151   guint64 offset = 0L, offset_end = 0L;
152
153   GList *l;
154   GstBuffer *buffer;
155
156   for (l = buffers; l; l = l->next) {
157     buffer = GST_BUFFER (l->data);
158     ASSERT_BUFFER_REFCOUNT (buffer, "buffer", 1);
159     GST_DEBUG ("buffer timestamp %" G_GUINT64_FORMAT ", duration %"
160         G_GUINT64_FORMAT " offset %" G_GUINT64_FORMAT " offset_end %"
161         G_GUINT64_FORMAT,
162         GST_BUFFER_TIMESTAMP (buffer),
163         GST_BUFFER_DURATION (buffer),
164         GST_BUFFER_OFFSET (buffer), GST_BUFFER_OFFSET_END (buffer));
165
166     fail_unless_equals_uint64 (timestamp, GST_BUFFER_TIMESTAMP (buffer));
167     fail_unless_equals_uint64 (offset, GST_BUFFER_OFFSET (buffer));
168     duration = GST_BUFFER_DURATION (buffer);
169     offset_end = GST_BUFFER_OFFSET_END (buffer);
170
171     timestamp += duration;
172     offset = offset_end;
173     gst_buffer_unref (buffer);
174   }
175   g_list_free (buffers);
176   buffers = NULL;
177 }
178
179 /* this tests that the output is a perfect stream if the input is */
180 static void
181 test_perfect_stream_instance (int inrate, int outrate, int samples,
182     int numbuffers)
183 {
184   GstElement *audioresample;
185   GstBuffer *inbuffer, *outbuffer;
186   GstCaps *caps;
187   guint64 offset = 0;
188   int i, j;
189   GstMapInfo map;
190   gint16 *p;
191
192   audioresample = setup_audioresample (2, inrate, outrate, 16, FALSE);
193   caps = gst_pad_get_current_caps (mysrcpad);
194   fail_unless (gst_caps_is_fixed (caps));
195
196   fail_unless (gst_element_set_state (audioresample,
197           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
198       "could not set to playing");
199
200   for (j = 1; j <= numbuffers; ++j) {
201
202     inbuffer = gst_buffer_new_and_alloc (samples * 4);
203     GST_BUFFER_DURATION (inbuffer) = GST_FRAMES_TO_CLOCK_TIME (samples, inrate);
204     GST_BUFFER_TIMESTAMP (inbuffer) = GST_BUFFER_DURATION (inbuffer) * (j - 1);
205     GST_BUFFER_OFFSET (inbuffer) = offset;
206     offset += samples;
207     GST_BUFFER_OFFSET_END (inbuffer) = offset;
208
209     gst_buffer_map (inbuffer, &map, GST_MAP_WRITE);
210     p = (gint16 *) map.data;
211
212     /* create a 16 bit signed ramp */
213     for (i = 0; i < samples; ++i) {
214       *p = -32767 + i * (65535 / samples);
215       ++p;
216       *p = -32767 + i * (65535 / samples);
217       ++p;
218     }
219     gst_buffer_unmap (inbuffer, &map);
220
221     /* pushing gives away my reference ... */
222     fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
223     /* ... but it ends up being collected on the global buffer list */
224     fail_unless_equals_int (g_list_length (buffers), j);
225   }
226
227   /* FIXME: we should make audioresample handle eos by flushing out the last
228    * samples, which will give us one more, small, buffer */
229   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
230   ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1);
231
232   fail_unless_perfect_stream ();
233
234   /* cleanup */
235   gst_caps_unref (caps);
236   cleanup_audioresample (audioresample);
237 }
238
239
240 /* make sure that outgoing buffers are contiguous in timestamp/duration and
241  * offset/offsetend
242  */
243 GST_START_TEST (test_perfect_stream)
244 {
245   /* integral scalings */
246   test_perfect_stream_instance (48000, 24000, 500, 20);
247   test_perfect_stream_instance (48000, 12000, 500, 20);
248   test_perfect_stream_instance (12000, 24000, 500, 20);
249   test_perfect_stream_instance (12000, 48000, 500, 20);
250
251   /* non-integral scalings */
252   test_perfect_stream_instance (44100, 8000, 500, 20);
253   test_perfect_stream_instance (8000, 44100, 500, 20);
254
255   /* wacky scalings */
256   test_perfect_stream_instance (12345, 54321, 500, 20);
257   test_perfect_stream_instance (101, 99, 500, 20);
258 }
259
260 GST_END_TEST;
261
262 /* this tests that the output is a correct discontinuous stream
263  * if the input is; ie input drops in time come out the same way */
264 static void
265 test_discont_stream_instance (int inrate, int outrate, int samples,
266     int numbuffers)
267 {
268   GstElement *audioresample;
269   GstBuffer *inbuffer, *outbuffer;
270   GstCaps *caps;
271   GstClockTime ints;
272
273   int i, j;
274   GstMapInfo map;
275   gint16 *p;
276
277   GST_DEBUG ("inrate:%d outrate:%d samples:%d numbuffers:%d",
278       inrate, outrate, samples, numbuffers);
279
280   audioresample = setup_audioresample (2, inrate, outrate, 16, FALSE);
281   caps = gst_pad_get_current_caps (mysrcpad);
282   fail_unless (gst_caps_is_fixed (caps));
283
284   fail_unless (gst_element_set_state (audioresample,
285           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
286       "could not set to playing");
287
288   for (j = 1; j <= numbuffers; ++j) {
289
290     inbuffer = gst_buffer_new_and_alloc (samples * 4);
291     GST_BUFFER_DURATION (inbuffer) = samples * GST_SECOND / inrate;
292     /* "drop" half the buffers */
293     ints = GST_BUFFER_DURATION (inbuffer) * 2 * (j - 1);
294     GST_BUFFER_TIMESTAMP (inbuffer) = ints;
295     GST_BUFFER_OFFSET (inbuffer) = (j - 1) * 2 * samples;
296     GST_BUFFER_OFFSET_END (inbuffer) = j * 2 * samples + samples;
297
298     gst_buffer_map (inbuffer, &map, GST_MAP_WRITE);
299     p = (gint16 *) map.data;
300     /* create a 16 bit signed ramp */
301     for (i = 0; i < samples; ++i) {
302       *p = -32767 + i * (65535 / samples);
303       ++p;
304       *p = -32767 + i * (65535 / samples);
305       ++p;
306     }
307     gst_buffer_unmap (inbuffer, &map);
308
309     GST_DEBUG ("Sending Buffer time:%" G_GUINT64_FORMAT " duration:%"
310         G_GINT64_FORMAT " discont:%d offset:%" G_GUINT64_FORMAT " offset_end:%"
311         G_GUINT64_FORMAT, GST_BUFFER_TIMESTAMP (inbuffer),
312         GST_BUFFER_DURATION (inbuffer), GST_BUFFER_IS_DISCONT (inbuffer),
313         GST_BUFFER_OFFSET (inbuffer), GST_BUFFER_OFFSET_END (inbuffer));
314     /* pushing gives away my reference ... */
315     fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
316
317     /* check if the timestamp of the pushed buffer matches the incoming one */
318     outbuffer = g_list_nth_data (buffers, g_list_length (buffers) - 1);
319     fail_if (outbuffer == NULL);
320     fail_unless_equals_uint64 (ints, GST_BUFFER_TIMESTAMP (outbuffer));
321     GST_DEBUG ("Got Buffer time:%" G_GUINT64_FORMAT " duration:%"
322         G_GINT64_FORMAT " discont:%d offset:%" G_GUINT64_FORMAT " offset_end:%"
323         G_GUINT64_FORMAT, GST_BUFFER_TIMESTAMP (outbuffer),
324         GST_BUFFER_DURATION (outbuffer), GST_BUFFER_IS_DISCONT (outbuffer),
325         GST_BUFFER_OFFSET (outbuffer), GST_BUFFER_OFFSET_END (outbuffer));
326     if (j > 1) {
327       fail_unless (GST_BUFFER_IS_DISCONT (outbuffer),
328           "expected discont for buffer #%d", j);
329     }
330   }
331
332   /* cleanup */
333   gst_caps_unref (caps);
334   cleanup_audioresample (audioresample);
335 }
336
337 GST_START_TEST (test_discont_stream)
338 {
339   /* integral scalings */
340   test_discont_stream_instance (48000, 24000, 5000, 20);
341   test_discont_stream_instance (48000, 12000, 5000, 20);
342   test_discont_stream_instance (12000, 24000, 5000, 20);
343   test_discont_stream_instance (12000, 48000, 5000, 20);
344
345   /* non-integral scalings */
346   test_discont_stream_instance (44100, 8000, 5000, 20);
347   test_discont_stream_instance (8000, 44100, 5000, 20);
348
349   /* wacky scalings */
350   test_discont_stream_instance (12345, 54321, 5000, 20);
351   test_discont_stream_instance (101, 99, 5000, 20);
352 }
353
354 GST_END_TEST;
355
356
357
358 GST_START_TEST (test_reuse)
359 {
360   GstElement *audioresample;
361   GstEvent *newseg;
362   GstBuffer *inbuffer;
363   GstCaps *caps;
364   GstSegment segment;
365
366   audioresample = setup_audioresample (1, 9343, 48000, 16, FALSE);
367   caps = gst_pad_get_current_caps (mysrcpad);
368   fail_unless (gst_caps_is_fixed (caps));
369
370   fail_unless (gst_element_set_state (audioresample,
371           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
372       "could not set to playing");
373
374   gst_segment_init (&segment, GST_FORMAT_TIME);
375   newseg = gst_event_new_segment (&segment);
376   fail_unless (gst_pad_push_event (mysrcpad, newseg) != FALSE);
377
378   inbuffer = gst_buffer_new_and_alloc (9343 * 4);
379   gst_buffer_memset (inbuffer, 0, 0, 9343 * 4);
380   GST_BUFFER_DURATION (inbuffer) = GST_SECOND;
381   GST_BUFFER_TIMESTAMP (inbuffer) = 0;
382   GST_BUFFER_OFFSET (inbuffer) = 0;
383
384   /* pushing gives away my reference ... */
385   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
386
387   /* ... but it ends up being collected on the global buffer list */
388   fail_unless_equals_int (g_list_length (buffers), 1);
389
390   /* now reset and try again ... */
391   fail_unless (gst_element_set_state (audioresample,
392           GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to NULL");
393
394   fail_unless (gst_element_set_state (audioresample,
395           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
396       "could not set to playing");
397
398   newseg = gst_event_new_segment (&segment);
399   fail_unless (gst_pad_push_event (mysrcpad, newseg) != FALSE);
400
401   inbuffer = gst_buffer_new_and_alloc (9343 * 4);
402   gst_buffer_memset (inbuffer, 0, 0, 9343 * 4);
403   GST_BUFFER_DURATION (inbuffer) = GST_SECOND;
404   GST_BUFFER_TIMESTAMP (inbuffer) = 0;
405   GST_BUFFER_OFFSET (inbuffer) = 0;
406
407   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
408
409   /* ... it also ends up being collected on the global buffer list. If we
410    * now have more than 2 buffers, then audioresample probably didn't clean
411    * up its internal buffer properly and tried to push the remaining samples
412    * when it got the second NEWSEGMENT event */
413   fail_unless_equals_int (g_list_length (buffers), 2);
414
415   cleanup_audioresample (audioresample);
416   gst_caps_unref (caps);
417 }
418
419 GST_END_TEST;
420
421 GST_START_TEST (test_shutdown)
422 {
423   GstElement *pipeline, *src, *cf1, *ar, *cf2, *sink;
424   GstCaps *caps;
425   guint i;
426
427   /* create pipeline, force audioresample to actually resample */
428   pipeline = gst_pipeline_new (NULL);
429
430   src = gst_check_setup_element ("audiotestsrc");
431   cf1 = gst_check_setup_element ("capsfilter");
432   ar = gst_check_setup_element ("audioresample");
433   cf2 = gst_check_setup_element ("capsfilter");
434   g_object_set (cf2, "name", "capsfilter2", NULL);
435   sink = gst_check_setup_element ("fakesink");
436
437   caps = gst_caps_new_simple ("audio/x-raw", "rate", G_TYPE_INT, 11025, NULL);
438   g_object_set (cf1, "caps", caps, NULL);
439   gst_caps_unref (caps);
440
441   caps = gst_caps_new_simple ("audio/x-raw", "rate", G_TYPE_INT, 48000, NULL);
442   g_object_set (cf2, "caps", caps, NULL);
443   gst_caps_unref (caps);
444
445   /* don't want to sync against the clock, the more throughput the better */
446   g_object_set (src, "is-live", FALSE, NULL);
447   g_object_set (sink, "sync", FALSE, NULL);
448
449   gst_bin_add_many (GST_BIN (pipeline), src, cf1, ar, cf2, sink, NULL);
450   fail_if (!gst_element_link_many (src, cf1, ar, cf2, sink, NULL));
451
452   /* now, wait until pipeline is running and then shut it down again; repeat */
453   for (i = 0; i < 20; ++i) {
454     gst_element_set_state (pipeline, GST_STATE_PAUSED);
455     gst_element_get_state (pipeline, NULL, NULL, -1);
456     gst_element_set_state (pipeline, GST_STATE_PLAYING);
457     g_usleep (100);
458     gst_element_set_state (pipeline, GST_STATE_NULL);
459   }
460
461   gst_object_unref (pipeline);
462 }
463
464 GST_END_TEST;
465
466 #if 0
467 static GstFlowReturn
468 live_switch_alloc_only_48000 (GstPad * pad, guint64 offset,
469     guint size, GstCaps * caps, GstBuffer ** buf)
470 {
471   GstStructure *structure;
472   gint rate;
473   gint channels;
474   GstCaps *desired;
475
476   structure = gst_caps_get_structure (caps, 0);
477   fail_unless (gst_structure_get_int (structure, "rate", &rate));
478   fail_unless (gst_structure_get_int (structure, "channels", &channels));
479
480   if (rate < 48000)
481     return GST_FLOW_NOT_NEGOTIATED;
482
483   desired = gst_caps_copy (caps);
484   gst_caps_set_simple (desired, "rate", G_TYPE_INT, 48000, NULL);
485
486   *buf = gst_buffer_new_and_alloc (channels * 48000);
487   gst_buffer_set_caps (*buf, desired);
488   gst_caps_unref (desired);
489
490   return GST_FLOW_OK;
491 }
492
493 static GstCaps *
494 live_switch_get_sink_caps (GstPad * pad)
495 {
496   GstCaps *result;
497
498   result = gst_caps_make_writable (gst_pad_get_current_caps (pad));
499
500   gst_caps_set_simple (result,
501       "rate", GST_TYPE_INT_RANGE, 48000, G_MAXINT, NULL);
502
503   return result;
504 }
505 #endif
506
507 static void
508 live_switch_push (int rate, GstCaps * caps)
509 {
510   GstBuffer *inbuffer;
511   GstCaps *desired;
512   GList *l;
513
514   desired = gst_caps_copy (caps);
515   gst_caps_set_simple (desired, "rate", G_TYPE_INT, rate, NULL);
516   gst_pad_set_caps (mysrcpad, desired);
517
518 #if 0
519   fail_unless (gst_pad_alloc_buffer_and_set_caps (mysrcpad,
520           GST_BUFFER_OFFSET_NONE, rate * 4, desired, &inbuffer) == GST_FLOW_OK);
521 #endif
522   inbuffer = gst_buffer_new_and_alloc (rate * 4);
523   gst_buffer_memset (inbuffer, 0, 0, rate * 4);
524
525   GST_BUFFER_DURATION (inbuffer) = GST_SECOND;
526   GST_BUFFER_TIMESTAMP (inbuffer) = 0;
527   GST_BUFFER_OFFSET (inbuffer) = 0;
528
529   /* pushing gives away my reference ... */
530   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
531
532   /* ... but it ends up being collected on the global buffer list */
533   fail_unless_equals_int (g_list_length (buffers), 1);
534
535   for (l = buffers; l; l = l->next) {
536     GstBuffer *buffer = GST_BUFFER (l->data);
537
538     gst_buffer_unref (buffer);
539   }
540
541   g_list_free (buffers);
542   buffers = NULL;
543
544   gst_caps_unref (desired);
545 }
546
547 GST_START_TEST (test_live_switch)
548 {
549   GstElement *audioresample;
550   GstEvent *newseg;
551   GstCaps *caps;
552   GstSegment segment;
553
554   audioresample = setup_audioresample (4, 48000, 48000, 16, FALSE);
555
556   /* Let the sinkpad act like something that can only handle things of
557    * rate 48000- and can only allocate buffers for that rate, but if someone
558    * tries to get a buffer with a rate higher then 48000 tries to renegotiate
559    * */
560   //gst_pad_set_bufferalloc_function (mysinkpad, live_switch_alloc_only_48000);
561   //gst_pad_set_getcaps_function (mysinkpad, live_switch_get_sink_caps);
562
563   gst_pad_use_fixed_caps (mysrcpad);
564
565   caps = gst_pad_get_current_caps (mysrcpad);
566   fail_unless (gst_caps_is_fixed (caps));
567
568   fail_unless (gst_element_set_state (audioresample,
569           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
570       "could not set to playing");
571
572   gst_segment_init (&segment, GST_FORMAT_TIME);
573   newseg = gst_event_new_segment (&segment);
574   fail_unless (gst_pad_push_event (mysrcpad, newseg) != FALSE);
575
576   /* downstream can provide the requested rate, a buffer alloc will be passed
577    * on */
578   live_switch_push (48000, caps);
579
580   /* Downstream can never accept this rate, buffer alloc isn't passed on */
581   live_switch_push (40000, caps);
582
583   /* Downstream can provide the requested rate but will re-negotiate */
584   live_switch_push (50000, caps);
585
586   cleanup_audioresample (audioresample);
587   gst_caps_unref (caps);
588 }
589
590 GST_END_TEST;
591
592 #ifndef GST_DISABLE_PARSE
593
594 static GMainLoop *loop;
595 static gint messages = 0;
596
597 static void
598 element_message_cb (GstBus * bus, GstMessage * message, gpointer user_data)
599 {
600   gchar *s;
601
602   s = gst_structure_to_string (gst_message_get_structure (message));
603   GST_DEBUG ("Received message: %s", s);
604   g_free (s);
605
606   messages++;
607 }
608
609 static void
610 eos_message_cb (GstBus * bus, GstMessage * message, gpointer user_data)
611 {
612   GST_DEBUG ("Received eos");
613   g_main_loop_quit (loop);
614 }
615
616 static void
617 test_pipeline (const gchar * format, gint inrate, gint outrate, gint quality)
618 {
619   GstElement *pipeline;
620   GstBus *bus;
621   GError *error = NULL;
622   gchar *pipe_str;
623
624   pipe_str =
625       g_strdup_printf
626       ("audiotestsrc num-buffers=10 ! audioconvert ! audio/x-raw,format=%s,rate=%d,channels=2 ! audioresample quality=%d ! audio/x-raw,format=%s,rate=%d ! identity check-imperfect-timestamp=TRUE ! fakesink",
627       format, inrate, quality, format, outrate);
628
629   pipeline = gst_parse_launch (pipe_str, &error);
630   fail_unless (pipeline != NULL, "Error parsing pipeline: %s",
631       error ? error->message : "(invalid error)");
632   g_free (pipe_str);
633
634   bus = gst_element_get_bus (pipeline);
635   fail_if (bus == NULL);
636   gst_bus_add_signal_watch (bus);
637   g_signal_connect (bus, "message::element", (GCallback) element_message_cb,
638       NULL);
639   g_signal_connect (bus, "message::eos", (GCallback) eos_message_cb, NULL);
640
641   gst_element_set_state (pipeline, GST_STATE_PLAYING);
642
643   /* run until we receive EOS */
644   loop = g_main_loop_new (NULL, FALSE);
645
646   g_main_loop_run (loop);
647
648   g_main_loop_unref (loop);
649   loop = NULL;
650
651   gst_element_set_state (pipeline, GST_STATE_NULL);
652
653   fail_if (messages > 0, "Received imperfect timestamp messages");
654   gst_object_unref (pipeline);
655 }
656
657 GST_START_TEST (test_pipelines)
658 {
659   gint quality;
660
661   /* Test qualities 0, 5 and 10 */
662   for (quality = 0; quality < 11; quality += 5) {
663     GST_DEBUG ("Checking with quality %d", quality);
664
665     test_pipeline ("S8", 44100, 48000, quality);
666     test_pipeline ("S8", 48000, 44100, quality);
667
668     test_pipeline (GST_AUDIO_NE (S16), 44100, 48000, quality);
669     test_pipeline (GST_AUDIO_NE (S16), 48000, 44100, quality);
670
671     test_pipeline (GST_AUDIO_NE (S24), 44100, 48000, quality);
672     test_pipeline (GST_AUDIO_NE (S24), 48000, 44100, quality);
673
674     test_pipeline (GST_AUDIO_NE (S32), 44100, 48000, quality);
675     test_pipeline (GST_AUDIO_NE (S32), 48000, 44100, quality);
676
677     test_pipeline (GST_AUDIO_NE (F32), 44100, 48000, quality);
678     test_pipeline (GST_AUDIO_NE (F32), 48000, 44100, quality);
679
680     test_pipeline (GST_AUDIO_NE (F64), 44100, 48000, quality);
681     test_pipeline (GST_AUDIO_NE (F64), 48000, 44100, quality);
682   }
683 }
684
685 GST_END_TEST;
686
687 GST_START_TEST (test_preference_passthrough)
688 {
689   GstStateChangeReturn ret;
690   GstElement *pipeline, *src;
691   GstStructure *s;
692   GstMessage *msg;
693   GstCaps *caps;
694   GstPad *pad;
695   GstBus *bus;
696   GError *error = NULL;
697   gint rate = 0;
698
699   pipeline = gst_parse_launch ("audiotestsrc num-buffers=1 name=src ! "
700       "audioresample ! audio/x-raw,format=" GST_AUDIO_NE (S16) ",channels=1,"
701       "rate=8000 ! fakesink can-activate-pull=false", &error);
702   fail_unless (pipeline != NULL, "Error parsing pipeline: %s",
703       error ? error->message : "(invalid error)");
704
705   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
706   fail_unless_equals_int (ret, GST_STATE_CHANGE_ASYNC);
707
708   /* run until we receive EOS */
709   bus = gst_element_get_bus (pipeline);
710   fail_if (bus == NULL);
711   msg = gst_bus_timed_pop_filtered (bus, -1, GST_MESSAGE_EOS);
712   gst_message_unref (msg);
713   gst_object_unref (bus);
714
715   src = gst_bin_get_by_name (GST_BIN (pipeline), "src");
716   fail_unless (src != NULL);
717   pad = gst_element_get_static_pad (src, "src");
718   fail_unless (pad != NULL);
719   caps = gst_pad_get_current_caps (pad);
720   GST_LOG ("current audiotestsrc caps: %" GST_PTR_FORMAT, caps);
721   fail_unless (caps != NULL);
722   s = gst_caps_get_structure (caps, 0);
723   fail_unless (gst_structure_get_int (s, "rate", &rate));
724   /* there's no need to resample, audiotestsrc supports any rate, so make
725    * sure audioresample provided upstream with the right caps to negotiate
726    * this correctly */
727   fail_unless_equals_int (rate, 8000);
728   gst_caps_unref (caps);
729   gst_object_unref (pad);
730   gst_object_unref (src);
731
732   gst_element_set_state (pipeline, GST_STATE_NULL);
733   gst_object_unref (pipeline);
734 }
735
736 GST_END_TEST;
737
738 #endif
739
740 static void
741 _message_cb (GstBus * bus, GstMessage * message, gpointer user_data)
742 {
743   GMainLoop *loop = user_data;
744
745   switch (GST_MESSAGE_TYPE (message)) {
746     case GST_MESSAGE_ERROR:
747     case GST_MESSAGE_WARNING:
748       g_assert_not_reached ();
749       break;
750     case GST_MESSAGE_EOS:
751       g_main_loop_quit (loop);
752       break;
753     default:
754       break;
755   }
756 }
757
758 typedef struct
759 {
760   guint64 latency;
761   GstClockTime in_ts;
762
763   GstClockTime next_out_ts;
764   guint64 next_out_off;
765
766   guint64 in_buffer_count, out_buffer_count;
767 } TimestampDriftCtx;
768
769 static void
770 fakesink_handoff_cb (GstElement * object, GstBuffer * buffer, GstPad * pad,
771     gpointer user_data)
772 {
773   TimestampDriftCtx *ctx = user_data;
774
775   ctx->out_buffer_count++;
776   if (ctx->latency == GST_CLOCK_TIME_NONE) {
777     ctx->latency = 1000 - gst_buffer_get_size (buffer) / 8;
778   }
779
780   /* Check if we have a perfectly timestamped stream */
781   if (ctx->next_out_ts != GST_CLOCK_TIME_NONE)
782     fail_unless (ctx->next_out_ts == GST_BUFFER_TIMESTAMP (buffer),
783         "expected timestamp %" GST_TIME_FORMAT " got timestamp %"
784         GST_TIME_FORMAT, GST_TIME_ARGS (ctx->next_out_ts),
785         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
786
787   /* Check if we have a perfectly offsetted stream */
788   fail_unless (GST_BUFFER_OFFSET_END (buffer) ==
789       GST_BUFFER_OFFSET (buffer) + gst_buffer_get_size (buffer) / 8,
790       "expected offset end %" G_GUINT64_FORMAT " got offset end %"
791       G_GUINT64_FORMAT,
792       GST_BUFFER_OFFSET (buffer) + gst_buffer_get_size (buffer) / 8,
793       GST_BUFFER_OFFSET_END (buffer));
794   if (ctx->next_out_off != GST_BUFFER_OFFSET_NONE) {
795     fail_unless (GST_BUFFER_OFFSET (buffer) == ctx->next_out_off,
796         "expected offset %" G_GUINT64_FORMAT " got offset %" G_GUINT64_FORMAT,
797         ctx->next_out_off, GST_BUFFER_OFFSET (buffer));
798   }
799
800   if (ctx->in_buffer_count != ctx->out_buffer_count) {
801     GST_INFO ("timestamp %" GST_TIME_FORMAT,
802         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
803   }
804
805   if (ctx->in_ts != GST_CLOCK_TIME_NONE && ctx->in_buffer_count > 1
806       && ctx->in_buffer_count == ctx->out_buffer_count) {
807     fail_unless (GST_BUFFER_TIMESTAMP (buffer) ==
808         ctx->in_ts - gst_util_uint64_scale_round (ctx->latency, GST_SECOND,
809             4096),
810         "expected output timestamp %" GST_TIME_FORMAT " (%" G_GUINT64_FORMAT
811         ") got output timestamp %" GST_TIME_FORMAT " (%" G_GUINT64_FORMAT ")",
812         GST_TIME_ARGS (ctx->in_ts - gst_util_uint64_scale_round (ctx->latency,
813                 GST_SECOND, 4096)),
814         ctx->in_ts - gst_util_uint64_scale_round (ctx->latency, GST_SECOND,
815             4096), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
816         GST_BUFFER_TIMESTAMP (buffer));
817   }
818
819   ctx->next_out_ts =
820       GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer);
821   ctx->next_out_off = GST_BUFFER_OFFSET_END (buffer);
822 }
823
824 static void
825 identity_handoff_cb (GstElement * object, GstBuffer * buffer,
826     gpointer user_data)
827 {
828   TimestampDriftCtx *ctx = user_data;
829
830   ctx->in_ts = GST_BUFFER_TIMESTAMP (buffer);
831   ctx->in_buffer_count++;
832 }
833
834 GST_START_TEST (test_timestamp_drift)
835 {
836   TimestampDriftCtx ctx =
837       { GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE,
838     GST_BUFFER_OFFSET_NONE, 0, 0
839   };
840   GstElement *pipeline;
841   GstElement *audiotestsrc, *capsfilter1, *identity, *audioresample,
842       *capsfilter2, *fakesink;
843   GstBus *bus;
844   GMainLoop *loop;
845   GstCaps *caps;
846
847   pipeline = gst_pipeline_new ("pipeline");
848   fail_unless (pipeline != NULL);
849
850   audiotestsrc = gst_element_factory_make ("audiotestsrc", "src");
851   fail_unless (audiotestsrc != NULL);
852   g_object_set (G_OBJECT (audiotestsrc), "num-buffers", 10000,
853       "samplesperbuffer", 4000, NULL);
854
855   capsfilter1 = gst_element_factory_make ("capsfilter", "capsfilter1");
856   fail_unless (capsfilter1 != NULL);
857   caps =
858       gst_caps_from_string
859       ("audio/x-raw, format=F64LE, channels=1, rate=16384");
860   g_object_set (G_OBJECT (capsfilter1), "caps", caps, NULL);
861   gst_caps_unref (caps);
862
863   identity = gst_element_factory_make ("identity", "identity");
864   fail_unless (identity != NULL);
865   g_object_set (G_OBJECT (identity), "sync", FALSE, "signal-handoffs", TRUE,
866       NULL);
867   g_signal_connect (identity, "handoff", (GCallback) identity_handoff_cb, &ctx);
868
869   audioresample = gst_element_factory_make ("audioresample", "resample");
870   fail_unless (audioresample != NULL);
871   capsfilter2 = gst_element_factory_make ("capsfilter", "capsfilter2");
872   fail_unless (capsfilter2 != NULL);
873   caps =
874       gst_caps_from_string ("audio/x-raw, format=F64LE, channels=1, rate=4096");
875   g_object_set (G_OBJECT (capsfilter2), "caps", caps, NULL);
876   gst_caps_unref (caps);
877
878   fakesink = gst_element_factory_make ("fakesink", "sink");
879   fail_unless (fakesink != NULL);
880   g_object_set (G_OBJECT (fakesink), "sync", FALSE, "async", FALSE,
881       "signal-handoffs", TRUE, NULL);
882   g_signal_connect (fakesink, "handoff", (GCallback) fakesink_handoff_cb, &ctx);
883
884
885   gst_bin_add_many (GST_BIN (pipeline), audiotestsrc, capsfilter1, identity,
886       audioresample, capsfilter2, fakesink, NULL);
887   fail_unless (gst_element_link_many (audiotestsrc, capsfilter1, identity,
888           audioresample, capsfilter2, fakesink, NULL));
889
890   loop = g_main_loop_new (NULL, FALSE);
891
892   bus = gst_element_get_bus (pipeline);
893   gst_bus_add_signal_watch (bus);
894   g_signal_connect (bus, "message", (GCallback) _message_cb, loop);
895
896   fail_unless (gst_element_set_state (pipeline,
897           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS);
898   g_main_loop_run (loop);
899
900   fail_unless (gst_element_set_state (pipeline,
901           GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS);
902   g_main_loop_unref (loop);
903   gst_object_unref (pipeline);
904
905 } GST_END_TEST;
906
907 #define FFT_HELPERS(type,ffttag,ffttag2,scale);                                                 \
908 static gdouble magnitude##ffttag (const GstFFT##ffttag##Complex *c)                             \
909 {                                                                                               \
910   gdouble mag = (gdouble) c->r * (gdouble) c->r;                                                \
911   mag += (gdouble) c->i * (gdouble) c->i;                                                       \
912   mag /= scale * scale;                                                                         \
913   mag = 10.0 * log10 (mag);                                                                     \
914   return mag;                                                                                   \
915 }                                                                                               \
916 static gdouble find_main_frequency_spot_##ffttag (const GstFFT##ffttag##Complex *v,             \
917                                                   int elements)                                 \
918 {                                                                                               \
919   int i;                                                                                        \
920   gdouble maxmag = -9999;                                                                       \
921   int maxidx = 0;                                                                               \
922   for (i=0; i<elements; ++i) {                                                                  \
923     gdouble mag = magnitude##ffttag (v+i);                                                      \
924     if (mag > maxmag) {                                                                         \
925       maxmag = mag;                                                                             \
926       maxidx = i;                                                                               \
927     }                                                                                           \
928   }                                                                                             \
929   return maxidx / (gdouble) elements;                                                           \
930 }                                                                                               \
931 static gboolean is_zero_except_##ffttag (const GstFFT##ffttag##Complex *v, int elements,        \
932                                 gdouble spot)                                                   \
933 {                                                                                               \
934   int i;                                                                                        \
935   for (i=0; i<elements; ++i) {                                                                  \
936     gdouble pos = i / (gdouble) elements;                                                       \
937     gdouble mag = magnitude##ffttag (v+i);                                                      \
938     if (fabs (pos - spot) > 0.01) {                                                             \
939       if (mag > -55.0) {                                                                        \
940         return FALSE;                                                                           \
941       }                                                                                         \
942     }                                                                                           \
943   }                                                                                             \
944   return TRUE;                                                                                  \
945 }                                                                                               \
946 static void compare_ffts_##ffttag (GstBuffer *inbuffer, GstBuffer *outbuffer)                   \
947 {                                                                                               \
948   GstMapInfo inmap, outmap;                                                                     \
949   int insamples, outsamples;                                                                    \
950   gdouble inspot, outspot;                                                                      \
951   GstFFT##ffttag *inctx, *outctx;                                                               \
952   GstFFT##ffttag##Complex *in, *out;                                                            \
953                                                                                                 \
954   gst_buffer_map (inbuffer, &inmap, GST_MAP_READ);                                              \
955   gst_buffer_map (outbuffer, &outmap, GST_MAP_READWRITE);                                       \
956                                                                                                 \
957   insamples = inmap.size / sizeof(type) & ~1;                                                   \
958   outsamples = outmap.size / sizeof(type) & ~1;                                                 \
959   inctx = gst_fft_##ffttag2##_new (insamples, FALSE);                                           \
960   outctx = gst_fft_##ffttag2##_new (outsamples, FALSE);                                         \
961   in = g_new (GstFFT##ffttag##Complex, insamples / 2 + 1);                                      \
962   out = g_new (GstFFT##ffttag##Complex, outsamples / 2 + 1);                                    \
963                                                                                                 \
964   gst_fft_##ffttag2##_window (inctx, (type*)inmap.data,                                         \
965       GST_FFT_WINDOW_HAMMING);                                                                  \
966   gst_fft_##ffttag2##_fft (inctx, (type*)inmap.data, in);                                       \
967   gst_fft_##ffttag2##_window (outctx, (type*)outmap.data,                                       \
968       GST_FFT_WINDOW_HAMMING);                                                                  \
969   gst_fft_##ffttag2##_fft (outctx, (type*)outmap.data, out);                                    \
970                                                                                                 \
971   inspot = find_main_frequency_spot_##ffttag (in, insamples / 2 + 1);                           \
972   outspot = find_main_frequency_spot_##ffttag (out, outsamples / 2 + 1);                        \
973   GST_LOG ("Spots are %.3f and %.3f", inspot, outspot);                                         \
974   fail_unless (fabs (outspot - inspot) < 0.05);                                                 \
975   fail_unless (is_zero_except_##ffttag (in, insamples / 2 + 1, inspot));                        \
976   fail_unless (is_zero_except_##ffttag (out, outsamples / 2 + 1, outspot));                     \
977                                                                                                 \
978   gst_buffer_unmap (inbuffer, &inmap);                                                          \
979   gst_buffer_unmap (outbuffer, &outmap);                                                        \
980                                                                                                 \
981   gst_fft_##ffttag2##_free (inctx);                                                             \
982   gst_fft_##ffttag2##_free (outctx);                                                            \
983   g_free (in);                                                                                  \
984   g_free (out);                                                                                 \
985 }
986 FFT_HELPERS (float, F32, f32, 2048.0f);
987 FFT_HELPERS (double, F64, f64, 2048.0);
988 FFT_HELPERS (gint16, S16, s16, 32767.0);
989 FFT_HELPERS (gint32, S32, s32, 2147483647.0);
990
991 #define FILL_BUFFER(type, desc, value);                         \
992   static void init_##type##_##desc (GstBuffer *buffer)          \
993   {                                                             \
994     GstMapInfo map;                                             \
995     type *ptr;                                                  \
996     int i, nsamples;                                            \
997     gst_buffer_map (buffer, &map, GST_MAP_WRITE);               \
998     ptr = (type *)map.data;                                     \
999     nsamples = map.size / sizeof (type);                        \
1000     for (i = 0; i < nsamples; ++i) {                            \
1001       *ptr++ = value;                                           \
1002     }                                                           \
1003   }
1004
1005 FILL_BUFFER (float, silence, 0.0f);
1006 FILL_BUFFER (double, silence, 0.0);
1007 FILL_BUFFER (gint16, silence, 0);
1008 FILL_BUFFER (gint32, silence, 0);
1009 FILL_BUFFER (float, sine, sinf (i * 0.01f));
1010 FILL_BUFFER (float, sine2, sinf (i * 1.8f));
1011 FILL_BUFFER (double, sine, sin (i * 0.01));
1012 FILL_BUFFER (double, sine2, sin (i * 1.8));
1013 FILL_BUFFER (gint16, sine, (gint16) (32767 * sinf (i * 0.01f)));
1014 FILL_BUFFER (gint16, sine2, (gint16) (32767 * sinf (i * 1.8f)));
1015 FILL_BUFFER (gint32, sine, (gint32) (2147483647 * sinf (i * 0.01f)));
1016 FILL_BUFFER (gint32, sine2, (gint32) (2147483647 * sinf (i * 1.8f)));
1017
1018 static void
1019 run_fft_pipeline (int inrate, int outrate, int quality, int width, gboolean fp,
1020     void (*init) (GstBuffer *), void (*compare_ffts) (GstBuffer *, GstBuffer *))
1021 {
1022   GstElement *audioresample;
1023   GstBuffer *inbuffer, *outbuffer;
1024   GstCaps *caps;
1025   const int nsamples = 2048;
1026
1027   audioresample = setup_audioresample (1, inrate, outrate, width, fp);
1028   fail_unless (audioresample != NULL);
1029   g_object_set (audioresample, "quality", quality, NULL);
1030   caps = gst_pad_get_current_caps (mysrcpad);
1031   fail_unless (gst_caps_is_fixed (caps));
1032
1033   fail_unless (gst_element_set_state (audioresample,
1034           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
1035       "could not set to playing");
1036
1037   inbuffer = gst_buffer_new_and_alloc (nsamples * width / 8);
1038   GST_BUFFER_DURATION (inbuffer) = GST_FRAMES_TO_CLOCK_TIME (nsamples, inrate);
1039   GST_BUFFER_TIMESTAMP (inbuffer) = 0;
1040   gst_pad_set_caps (mysrcpad, caps);
1041   gst_buffer_ref (inbuffer);
1042
1043   (*init) (inbuffer);
1044
1045   /* pushing gives away my reference ... */
1046   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
1047   /* ... but it ends up being collected on the global buffer list */
1048   fail_unless_equals_int (g_list_length (buffers), 1);
1049   /* retrieve out buffer */
1050   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
1051
1052   fail_unless (gst_element_set_state (audioresample,
1053           GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
1054
1055   (*compare_ffts) (inbuffer, outbuffer);
1056
1057   /* cleanup */
1058   gst_buffer_unref (inbuffer);
1059   gst_caps_unref (caps);
1060   cleanup_audioresample (audioresample);
1061 }
1062
1063 GST_START_TEST (test_fft)
1064 {
1065   int quality;
1066   size_t f0, f1;
1067   static const int frequencies[] =
1068       { 8000, 16000, 44100, 48000, 128000, 12345, 54321 };
1069
1070   /* audioresample uses a mixed float/double code path for floats with quality>8, make sure we test it */
1071   for (quality = 0; quality <= 10; quality += 5) {
1072     for (f0 = 0; f0 < G_N_ELEMENTS (frequencies); ++f0) {
1073       for (f1 = 0; f1 < G_N_ELEMENTS (frequencies); ++f1) {
1074         run_fft_pipeline (frequencies[f0], frequencies[f0], quality, 32, TRUE,
1075             &init_float_silence, &compare_ffts_F32);
1076         run_fft_pipeline (frequencies[f0], frequencies[f0], quality, 32, TRUE,
1077             &init_float_sine, &compare_ffts_F32);
1078         run_fft_pipeline (frequencies[f0], frequencies[f0], quality, 32, TRUE,
1079             &init_float_sine2, &compare_ffts_F32);
1080         run_fft_pipeline (frequencies[f0], frequencies[f0], quality, 64, TRUE,
1081             &init_double_silence, &compare_ffts_F64);
1082         run_fft_pipeline (frequencies[f0], frequencies[f0], quality, 64, TRUE,
1083             &init_double_sine, &compare_ffts_F64);
1084         run_fft_pipeline (frequencies[f0], frequencies[f0], quality, 64, TRUE,
1085             &init_double_sine2, &compare_ffts_F64);
1086         run_fft_pipeline (frequencies[f0], frequencies[f0], quality, 16, FALSE,
1087             &init_gint16_silence, &compare_ffts_S16);
1088         run_fft_pipeline (frequencies[f0], frequencies[f0], quality, 16, FALSE,
1089             &init_gint16_sine, &compare_ffts_S16);
1090         run_fft_pipeline (frequencies[f0], frequencies[f0], quality, 16, FALSE,
1091             &init_gint16_sine2, &compare_ffts_S16);
1092         run_fft_pipeline (frequencies[f0], frequencies[f0], quality, 32, FALSE,
1093             &init_gint32_silence, &compare_ffts_S32);
1094         run_fft_pipeline (frequencies[f0], frequencies[f0], quality, 32, FALSE,
1095             &init_gint32_sine, &compare_ffts_S32);
1096         run_fft_pipeline (frequencies[f0], frequencies[f0], quality, 32, FALSE,
1097             &init_gint32_sine2, &compare_ffts_S32);
1098       }
1099     }
1100   }
1101 }
1102
1103 GST_END_TEST;
1104
1105 static Suite *
1106 audioresample_suite (void)
1107 {
1108   Suite *s = suite_create ("audioresample");
1109   TCase *tc_chain = tcase_create ("general");
1110
1111   suite_add_tcase (s, tc_chain);
1112   tcase_add_test (tc_chain, test_perfect_stream);
1113   tcase_add_test (tc_chain, test_discont_stream);
1114   tcase_add_test (tc_chain, test_reuse);
1115   tcase_add_test (tc_chain, test_shutdown);
1116   tcase_add_test (tc_chain, test_live_switch);
1117   tcase_add_test (tc_chain, test_timestamp_drift);
1118   tcase_add_test (tc_chain, test_fft);
1119
1120 #ifndef GST_DISABLE_PARSE
1121   tcase_set_timeout (tc_chain, 360);
1122   tcase_add_test (tc_chain, test_pipelines);
1123   tcase_add_test (tc_chain, test_preference_passthrough);
1124 #endif
1125
1126   return s;
1127 }
1128
1129 GST_CHECK_MAIN (audioresample);