195 gobject_class->get_property = gst_audio_test_src_get_property; |
184 gobject_class->get_property = gst_audio_test_src_get_property; |
196 |
185 |
197 g_object_class_install_property (gobject_class, PROP_SAMPLES_PER_BUFFER, |
186 g_object_class_install_property (gobject_class, PROP_SAMPLES_PER_BUFFER, |
198 g_param_spec_int ("samplesperbuffer", "Samples per buffer", |
187 g_param_spec_int ("samplesperbuffer", "Samples per buffer", |
199 "Number of samples in each outgoing buffer", |
188 "Number of samples in each outgoing buffer", |
200 1, G_MAXINT, DEFAULT_SAMPLES_PER_BUFFER, |
189 1, G_MAXINT, 1024, G_PARAM_READWRITE)); |
201 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
190 g_object_class_install_property (gobject_class, PROP_WAVE, g_param_spec_enum ("wave", "Waveform", "Oscillator waveform", GST_TYPE_AUDIO_TEST_SRC_WAVE, /* enum type */ |
202 g_object_class_install_property (gobject_class, PROP_WAVE, |
191 GST_AUDIO_TEST_SRC_WAVE_SINE, /* default value */ |
203 g_param_spec_enum ("wave", "Waveform", "Oscillator waveform", |
192 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); |
204 GST_TYPE_AUDIO_TEST_SRC_WAVE, GST_AUDIO_TEST_SRC_WAVE_SINE, |
|
205 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); |
|
206 g_object_class_install_property (gobject_class, PROP_FREQ, |
193 g_object_class_install_property (gobject_class, PROP_FREQ, |
207 g_param_spec_double ("freq", "Frequency", "Frequency of test signal", |
194 g_param_spec_double ("freq", "Frequency", "Frequency of test signal", |
208 0.0, 20000.0, DEFAULT_FREQ, |
195 0.0, 20000.0, 440.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); |
209 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); |
|
210 g_object_class_install_property (gobject_class, PROP_VOLUME, |
196 g_object_class_install_property (gobject_class, PROP_VOLUME, |
211 g_param_spec_double ("volume", "Volume", "Volume of test signal", 0.0, |
197 g_param_spec_double ("volume", "Volume", "Volume of test signal", |
212 1.0, DEFAULT_VOLUME, |
198 0.0, 1.0, 0.8, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); |
213 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); |
|
214 g_object_class_install_property (gobject_class, PROP_IS_LIVE, |
199 g_object_class_install_property (gobject_class, PROP_IS_LIVE, |
215 g_param_spec_boolean ("is-live", "Is Live", |
200 g_param_spec_boolean ("is-live", "Is Live", |
216 "Whether to act as a live source", DEFAULT_IS_LIVE, |
201 "Whether to act as a live source", FALSE, G_PARAM_READWRITE)); |
217 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
|
218 g_object_class_install_property (G_OBJECT_CLASS (klass), |
202 g_object_class_install_property (G_OBJECT_CLASS (klass), |
219 PROP_TIMESTAMP_OFFSET, g_param_spec_int64 ("timestamp-offset", |
203 PROP_TIMESTAMP_OFFSET, |
220 "Timestamp offset", |
204 g_param_spec_int64 ("timestamp-offset", "Timestamp offset", |
221 "An offset added to timestamps set on buffers (in ns)", G_MININT64, |
205 "An offset added to timestamps set on buffers (in ns)", G_MININT64, |
222 G_MAXINT64, DEFAULT_TIMESTAMP_OFFSET, |
206 G_MAXINT64, 0, G_PARAM_READWRITE)); |
223 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
|
224 g_object_class_install_property (gobject_class, PROP_CAN_ACTIVATE_PUSH, |
|
225 g_param_spec_boolean ("can-activate-push", "Can activate push", |
|
226 "Can activate in push mode", DEFAULT_CAN_ACTIVATE_PUSH, |
|
227 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
|
228 g_object_class_install_property (gobject_class, PROP_CAN_ACTIVATE_PULL, |
|
229 g_param_spec_boolean ("can-activate-pull", "Can activate pull", |
|
230 "Can activate in pull mode", DEFAULT_CAN_ACTIVATE_PULL, |
|
231 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
|
232 |
207 |
233 gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_audio_test_src_setcaps); |
208 gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_audio_test_src_setcaps); |
234 gstbasesrc_class->is_seekable = |
209 gstbasesrc_class->is_seekable = |
235 GST_DEBUG_FUNCPTR (gst_audio_test_src_is_seekable); |
210 GST_DEBUG_FUNCPTR (gst_audio_test_src_is_seekable); |
236 gstbasesrc_class->check_get_range = |
|
237 GST_DEBUG_FUNCPTR (gst_audio_test_src_check_get_range); |
|
238 gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (gst_audio_test_src_do_seek); |
211 gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (gst_audio_test_src_do_seek); |
239 gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_audio_test_src_query); |
212 gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_audio_test_src_query); |
240 gstbasesrc_class->get_times = |
213 gstbasesrc_class->get_times = |
241 GST_DEBUG_FUNCPTR (gst_audio_test_src_get_times); |
214 GST_DEBUG_FUNCPTR (gst_audio_test_src_get_times); |
242 gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_audio_test_src_start); |
|
243 gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_audio_test_src_stop); |
|
244 gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_audio_test_src_create); |
215 gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_audio_test_src_create); |
245 } |
216 } |
246 |
217 |
247 static void |
218 static void |
248 gst_audio_test_src_init (GstAudioTestSrc * src, GstAudioTestSrcClass * g_class) |
219 gst_audio_test_src_init (GstAudioTestSrc * src, GstAudioTestSrcClass * g_class) |
251 |
222 |
252 gst_pad_set_fixatecaps_function (pad, gst_audio_test_src_src_fixate); |
223 gst_pad_set_fixatecaps_function (pad, gst_audio_test_src_src_fixate); |
253 |
224 |
254 src->samplerate = 44100; |
225 src->samplerate = 44100; |
255 src->format = GST_AUDIO_TEST_SRC_FORMAT_NONE; |
226 src->format = GST_AUDIO_TEST_SRC_FORMAT_NONE; |
256 |
227 src->volume = 0.8; |
257 src->volume = DEFAULT_VOLUME; |
228 src->freq = 440.0; |
258 src->freq = DEFAULT_FREQ; |
|
259 |
229 |
260 /* we operate in time */ |
230 /* we operate in time */ |
261 gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME); |
231 gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME); |
262 gst_base_src_set_live (GST_BASE_SRC (src), DEFAULT_IS_LIVE); |
232 gst_base_src_set_live (GST_BASE_SRC (src), FALSE); |
263 |
233 |
264 src->samples_per_buffer = DEFAULT_SAMPLES_PER_BUFFER; |
234 src->samples_per_buffer = 1024; |
265 src->generate_samples_per_buffer = src->samples_per_buffer; |
235 src->generate_samples_per_buffer = src->samples_per_buffer; |
266 src->timestamp_offset = DEFAULT_TIMESTAMP_OFFSET; |
236 src->timestamp_offset = G_GINT64_CONSTANT (0); |
267 src->can_activate_pull = DEFAULT_CAN_ACTIVATE_PULL; |
237 |
268 |
238 src->wave = GST_AUDIO_TEST_SRC_WAVE_SINE; |
269 src->wave = DEFAULT_WAVE; |
|
270 gst_base_src_set_blocksize (GST_BASE_SRC (src), -1); |
|
271 } |
239 } |
272 |
240 |
273 static void |
241 static void |
274 gst_audio_test_src_src_fixate (GstPad * pad, GstCaps * caps) |
242 gst_audio_test_src_src_fixate (GstPad * pad, GstCaps * caps) |
275 { |
243 { |
276 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (GST_PAD_PARENT (pad)); |
244 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (GST_PAD_PARENT (pad)); |
277 const gchar *name; |
245 const gchar *name; |
278 GstStructure *structure; |
246 GstStructure *structure; |
279 |
247 |
280 structure = gst_caps_get_structure (caps, 0); |
248 structure = gst_caps_get_structure (caps, 0); |
281 |
|
282 GST_DEBUG_OBJECT (src, "fixating samplerate to %d", src->samplerate); |
|
283 |
249 |
284 gst_structure_fixate_field_nearest_int (structure, "rate", src->samplerate); |
250 gst_structure_fixate_field_nearest_int (structure, "rate", src->samplerate); |
285 |
251 |
286 name = gst_structure_get_name (structure); |
252 name = gst_structure_get_name (structure); |
287 if (strcmp (name, "audio/x-raw-int") == 0) |
253 if (strcmp (name, "audio/x-raw-int") == 0) |
288 gst_structure_fixate_field_nearest_int (structure, "width", 32); |
254 gst_structure_fixate_field_nearest_int (structure, "width", 32); |
289 else if (strcmp (name, "audio/x-raw-float") == 0) |
255 else if (strcmp (name, "audio/x-raw-float") == 0) |
290 gst_structure_fixate_field_nearest_int (structure, "width", 64); |
256 gst_structure_fixate_field_nearest_int (structure, "width", 64); |
291 |
|
292 /* fixate to mono unless downstream requires stereo, for backwards compat */ |
|
293 gst_structure_fixate_field_nearest_int (structure, "channels", 1); |
|
294 } |
257 } |
295 |
258 |
296 static gboolean |
259 static gboolean |
297 gst_audio_test_src_setcaps (GstBaseSrc * basesrc, GstCaps * caps) |
260 gst_audio_test_src_setcaps (GstBaseSrc * basesrc, GstCaps * caps) |
298 { |
261 { |
413 |
351 |
414 #define DEFINE_SINE(type,scale) \ |
352 #define DEFINE_SINE(type,scale) \ |
415 static void \ |
353 static void \ |
416 gst_audio_test_src_create_sine_##type (GstAudioTestSrc * src, g##type * samples) \ |
354 gst_audio_test_src_create_sine_##type (GstAudioTestSrc * src, g##type * samples) \ |
417 { \ |
355 { \ |
418 gint i, c; \ |
356 gint i; \ |
419 gdouble step, amp; \ |
357 gdouble step, amp; \ |
420 \ |
358 \ |
421 step = M_PI_M2 * src->freq / src->samplerate; \ |
359 step = M_PI_M2 * src->freq / src->samplerate; \ |
422 amp = src->volume * scale; \ |
360 amp = src->volume * scale; \ |
423 \ |
361 \ |
424 i = 0; \ |
362 for (i = 0; i < src->generate_samples_per_buffer; i++) { \ |
425 while (i < (src->generate_samples_per_buffer * src->channels)) { \ |
|
426 src->accumulator += step; \ |
363 src->accumulator += step; \ |
427 if (src->accumulator >= M_PI_M2) \ |
364 if (src->accumulator >= M_PI_M2) \ |
428 src->accumulator -= M_PI_M2; \ |
365 src->accumulator -= M_PI_M2; \ |
429 \ |
366 \ |
430 for (c = 0; c < src->channels; ++c) { \ |
367 samples[i] = (g##type) (sin (src->accumulator) * amp); \ |
431 samples[i++] = (g##type) (sin (src->accumulator) * amp); \ |
|
432 } \ |
|
433 } \ |
368 } \ |
434 } |
369 } |
435 |
370 |
436 DEFINE_SINE (int16, 32767.0); |
371 DEFINE_SINE (int16, 32767.0); |
437 DEFINE_SINE (int32, 2147483647.0); |
372 DEFINE_SINE (int32, 2147483647.0); |
438 DEFINE_SINE (float, 1.0); |
373 DEFINE_SINE (float, 1.0); |
439 DEFINE_SINE (double, 1.0); |
374 DEFINE_SINE (double, 1.0); |
440 |
375 |
441 static const ProcessFunc sine_funcs[] = { |
376 static ProcessFunc sine_funcs[] = { |
442 (ProcessFunc) gst_audio_test_src_create_sine_int16, |
377 (ProcessFunc) gst_audio_test_src_create_sine_int16, |
443 (ProcessFunc) gst_audio_test_src_create_sine_int32, |
378 (ProcessFunc) gst_audio_test_src_create_sine_int32, |
444 (ProcessFunc) gst_audio_test_src_create_sine_float, |
379 (ProcessFunc) gst_audio_test_src_create_sine_float, |
445 (ProcessFunc) gst_audio_test_src_create_sine_double |
380 (ProcessFunc) gst_audio_test_src_create_sine_double |
446 }; |
381 }; |
447 |
382 |
448 #define DEFINE_SQUARE(type,scale) \ |
383 #define DEFINE_SQUARE(type,scale) \ |
449 static void \ |
384 static void \ |
450 gst_audio_test_src_create_square_##type (GstAudioTestSrc * src, g##type * samples) \ |
385 gst_audio_test_src_create_square_##type (GstAudioTestSrc * src, g##type * samples) \ |
451 { \ |
386 { \ |
452 gint i, c; \ |
387 gint i; \ |
453 gdouble step, amp; \ |
388 gdouble step, amp; \ |
454 \ |
389 \ |
455 step = M_PI_M2 * src->freq / src->samplerate; \ |
390 step = M_PI_M2 * src->freq / src->samplerate; \ |
456 amp = src->volume * scale; \ |
391 amp = src->volume * scale; \ |
457 \ |
392 \ |
458 i = 0; \ |
393 for (i = 0; i < src->generate_samples_per_buffer; i++) { \ |
459 while (i < (src->generate_samples_per_buffer * src->channels)) { \ |
|
460 src->accumulator += step; \ |
394 src->accumulator += step; \ |
461 if (src->accumulator >= M_PI_M2) \ |
395 if (src->accumulator >= M_PI_M2) \ |
462 src->accumulator -= M_PI_M2; \ |
396 src->accumulator -= M_PI_M2; \ |
463 \ |
397 \ |
464 for (c = 0; c < src->channels; ++c) { \ |
398 samples[i] = (g##type) ((src->accumulator < M_PI) ? amp : -amp); \ |
465 samples[i++] = (g##type) ((src->accumulator < M_PI) ? amp : -amp); \ |
|
466 } \ |
|
467 } \ |
399 } \ |
468 } |
400 } |
469 |
401 |
470 DEFINE_SQUARE (int16, 32767.0); |
402 DEFINE_SQUARE (int16, 32767.0); |
471 DEFINE_SQUARE (int32, 2147483647.0); |
403 DEFINE_SQUARE (int32, 2147483647.0); |
472 DEFINE_SQUARE (float, 1.0); |
404 DEFINE_SQUARE (float, 1.0); |
473 DEFINE_SQUARE (double, 1.0); |
405 DEFINE_SQUARE (double, 1.0); |
474 |
406 |
475 static const ProcessFunc square_funcs[] = { |
407 static ProcessFunc square_funcs[] = { |
476 (ProcessFunc) gst_audio_test_src_create_square_int16, |
408 (ProcessFunc) gst_audio_test_src_create_square_int16, |
477 (ProcessFunc) gst_audio_test_src_create_square_int32, |
409 (ProcessFunc) gst_audio_test_src_create_square_int32, |
478 (ProcessFunc) gst_audio_test_src_create_square_float, |
410 (ProcessFunc) gst_audio_test_src_create_square_float, |
479 (ProcessFunc) gst_audio_test_src_create_square_double |
411 (ProcessFunc) gst_audio_test_src_create_square_double |
480 }; |
412 }; |
481 |
413 |
482 #define DEFINE_SAW(type,scale) \ |
414 #define DEFINE_SAW(type,scale) \ |
483 static void \ |
415 static void \ |
484 gst_audio_test_src_create_saw_##type (GstAudioTestSrc * src, g##type * samples) \ |
416 gst_audio_test_src_create_saw_##type (GstAudioTestSrc * src, g##type * samples) \ |
485 { \ |
417 { \ |
486 gint i, c; \ |
418 gint i; \ |
487 gdouble step, amp; \ |
419 gdouble step, amp; \ |
488 \ |
420 \ |
489 step = M_PI_M2 * src->freq / src->samplerate; \ |
421 step = M_PI_M2 * src->freq / src->samplerate; \ |
490 amp = (src->volume * scale) / M_PI; \ |
422 amp = (src->volume * scale) / M_PI; \ |
491 \ |
423 \ |
492 i = 0; \ |
424 for (i = 0; i < src->generate_samples_per_buffer; i++) { \ |
493 while (i < (src->generate_samples_per_buffer * src->channels)) { \ |
|
494 src->accumulator += step; \ |
425 src->accumulator += step; \ |
495 if (src->accumulator >= M_PI_M2) \ |
426 if (src->accumulator >= M_PI_M2) \ |
496 src->accumulator -= M_PI_M2; \ |
427 src->accumulator -= M_PI_M2; \ |
497 \ |
428 \ |
498 if (src->accumulator < M_PI) { \ |
429 if (src->accumulator < M_PI) { \ |
499 for (c = 0; c < src->channels; ++c) \ |
430 samples[i] = (g##type) (src->accumulator * amp); \ |
500 samples[i++] = (g##type) (src->accumulator * amp); \ |
|
501 } else { \ |
431 } else { \ |
502 for (c = 0; c < src->channels; ++c) \ |
432 samples[i] = (g##type) ((M_PI_M2 - src->accumulator) * -amp); \ |
503 samples[i++] = (g##type) ((M_PI_M2 - src->accumulator) * -amp); \ |
|
504 } \ |
433 } \ |
505 } \ |
434 } \ |
506 } |
435 } |
507 |
436 |
508 DEFINE_SAW (int16, 32767.0); |
437 DEFINE_SAW (int16, 32767.0); |
509 DEFINE_SAW (int32, 2147483647.0); |
438 DEFINE_SAW (int32, 2147483647.0); |
510 DEFINE_SAW (float, 1.0); |
439 DEFINE_SAW (float, 1.0); |
511 DEFINE_SAW (double, 1.0); |
440 DEFINE_SAW (double, 1.0); |
512 |
441 |
513 static const ProcessFunc saw_funcs[] = { |
442 static ProcessFunc saw_funcs[] = { |
514 (ProcessFunc) gst_audio_test_src_create_saw_int16, |
443 (ProcessFunc) gst_audio_test_src_create_saw_int16, |
515 (ProcessFunc) gst_audio_test_src_create_saw_int32, |
444 (ProcessFunc) gst_audio_test_src_create_saw_int32, |
516 (ProcessFunc) gst_audio_test_src_create_saw_float, |
445 (ProcessFunc) gst_audio_test_src_create_saw_float, |
517 (ProcessFunc) gst_audio_test_src_create_saw_double |
446 (ProcessFunc) gst_audio_test_src_create_saw_double |
518 }; |
447 }; |
519 |
448 |
520 #define DEFINE_TRIANGLE(type,scale) \ |
449 #define DEFINE_TRIANGLE(type,scale) \ |
521 static void \ |
450 static void \ |
522 gst_audio_test_src_create_triangle_##type (GstAudioTestSrc * src, g##type * samples) \ |
451 gst_audio_test_src_create_triangle_##type (GstAudioTestSrc * src, g##type * samples) \ |
523 { \ |
452 { \ |
524 gint i, c; \ |
453 gint i; \ |
525 gdouble step, amp; \ |
454 gdouble step, amp; \ |
526 \ |
455 \ |
527 step = M_PI_M2 * src->freq / src->samplerate; \ |
456 step = M_PI_M2 * src->freq / src->samplerate; \ |
528 amp = (src->volume * scale) / M_PI_2; \ |
457 amp = (src->volume * scale) / M_PI_2; \ |
529 \ |
458 \ |
530 i = 0; \ |
459 for (i = 0; i < src->generate_samples_per_buffer; i++) { \ |
531 while (i < (src->generate_samples_per_buffer * src->channels)) { \ |
|
532 src->accumulator += step; \ |
460 src->accumulator += step; \ |
533 if (src->accumulator >= M_PI_M2) \ |
461 if (src->accumulator >= M_PI_M2) \ |
534 src->accumulator -= M_PI_M2; \ |
462 src->accumulator -= M_PI_M2; \ |
535 \ |
463 \ |
536 if (src->accumulator < (M_PI * 0.5)) { \ |
464 if (src->accumulator < (M_PI * 0.5)) { \ |
537 for (c = 0; c < src->channels; ++c) \ |
465 samples[i] = (g##type) (src->accumulator * amp); \ |
538 samples[i++] = (g##type) (src->accumulator * amp); \ |
|
539 } else if (src->accumulator < (M_PI * 1.5)) { \ |
466 } else if (src->accumulator < (M_PI * 1.5)) { \ |
540 for (c = 0; c < src->channels; ++c) \ |
467 samples[i] = (g##type) ((src->accumulator - M_PI) * -amp); \ |
541 samples[i++] = (g##type) ((src->accumulator - M_PI) * -amp); \ |
|
542 } else { \ |
468 } else { \ |
543 for (c = 0; c < src->channels; ++c) \ |
469 samples[i] = (g##type) ((M_PI_M2 - src->accumulator) * -amp); \ |
544 samples[i++] = (g##type) ((M_PI_M2 - src->accumulator) * -amp); \ |
|
545 } \ |
470 } \ |
546 } \ |
471 } \ |
547 } |
472 } |
548 |
473 |
549 DEFINE_TRIANGLE (int16, 32767.0); |
474 DEFINE_TRIANGLE (int16, 32767.0); |
550 DEFINE_TRIANGLE (int32, 2147483647.0); |
475 DEFINE_TRIANGLE (int32, 2147483647.0); |
551 DEFINE_TRIANGLE (float, 1.0); |
476 DEFINE_TRIANGLE (float, 1.0); |
552 DEFINE_TRIANGLE (double, 1.0); |
477 DEFINE_TRIANGLE (double, 1.0); |
553 |
478 |
554 static const ProcessFunc triangle_funcs[] = { |
479 static ProcessFunc triangle_funcs[] = { |
555 (ProcessFunc) gst_audio_test_src_create_triangle_int16, |
480 (ProcessFunc) gst_audio_test_src_create_triangle_int16, |
556 (ProcessFunc) gst_audio_test_src_create_triangle_int32, |
481 (ProcessFunc) gst_audio_test_src_create_triangle_int32, |
557 (ProcessFunc) gst_audio_test_src_create_triangle_float, |
482 (ProcessFunc) gst_audio_test_src_create_triangle_float, |
558 (ProcessFunc) gst_audio_test_src_create_triangle_double |
483 (ProcessFunc) gst_audio_test_src_create_triangle_double |
559 }; |
484 }; |
560 |
485 |
561 #define DEFINE_SILENCE(type) \ |
486 #define DEFINE_SILENCE(type) \ |
562 static void \ |
487 static void \ |
563 gst_audio_test_src_create_silence_##type (GstAudioTestSrc * src, g##type * samples) \ |
488 gst_audio_test_src_create_silence_##type (GstAudioTestSrc * src, g##type * samples) \ |
564 { \ |
489 { \ |
565 memset (samples, 0, src->generate_samples_per_buffer * sizeof (g##type) * src->channels); \ |
490 memset (samples, 0, src->generate_samples_per_buffer * sizeof (g##type)); \ |
566 } |
491 } |
567 |
492 |
568 DEFINE_SILENCE (int16); |
493 DEFINE_SILENCE (int16); |
569 DEFINE_SILENCE (int32); |
494 DEFINE_SILENCE (int32); |
570 DEFINE_SILENCE (float); |
495 DEFINE_SILENCE (float); |
571 DEFINE_SILENCE (double); |
496 DEFINE_SILENCE (double); |
572 |
497 |
573 static const ProcessFunc silence_funcs[] = { |
498 static ProcessFunc silence_funcs[] = { |
574 (ProcessFunc) gst_audio_test_src_create_silence_int16, |
499 (ProcessFunc) gst_audio_test_src_create_silence_int16, |
575 (ProcessFunc) gst_audio_test_src_create_silence_int32, |
500 (ProcessFunc) gst_audio_test_src_create_silence_int32, |
576 (ProcessFunc) gst_audio_test_src_create_silence_float, |
501 (ProcessFunc) gst_audio_test_src_create_silence_float, |
577 (ProcessFunc) gst_audio_test_src_create_silence_double |
502 (ProcessFunc) gst_audio_test_src_create_silence_double |
578 }; |
503 }; |
579 |
504 |
580 #define DEFINE_WHITE_NOISE(type,scale) \ |
505 #define DEFINE_WHITE_NOISE(type,scale) \ |
581 static void \ |
506 static void \ |
582 gst_audio_test_src_create_white_noise_##type (GstAudioTestSrc * src, g##type * samples) \ |
507 gst_audio_test_src_create_white_noise_##type (GstAudioTestSrc * src, g##type * samples) \ |
583 { \ |
508 { \ |
584 gint i, c; \ |
509 gint i; \ |
585 gdouble amp = (src->volume * scale); \ |
510 gdouble amp = (src->volume * scale); \ |
586 \ |
511 \ |
587 i = 0; \ |
512 for (i = 0; i < src->generate_samples_per_buffer; i++) { \ |
588 while (i < (src->generate_samples_per_buffer * src->channels)) { \ |
513 samples[i] = (g##type) (amp * g_random_double_range (-1.0, 1.0)); \ |
589 for (c = 0; c < src->channels; ++c) \ |
|
590 samples[i++] = (g##type) (amp * g_random_double_range (-1.0, 1.0)); \ |
|
591 } \ |
514 } \ |
592 } |
515 } |
593 |
516 |
594 DEFINE_WHITE_NOISE (int16, 32767.0); |
517 DEFINE_WHITE_NOISE (int16, 32767.0); |
595 DEFINE_WHITE_NOISE (int32, 2147483647.0); |
518 DEFINE_WHITE_NOISE (int32, 2147483647.0); |
596 DEFINE_WHITE_NOISE (float, 1.0); |
519 DEFINE_WHITE_NOISE (float, 1.0); |
597 DEFINE_WHITE_NOISE (double, 1.0); |
520 DEFINE_WHITE_NOISE (double, 1.0); |
598 |
521 |
599 static const ProcessFunc white_noise_funcs[] = { |
522 static ProcessFunc white_noise_funcs[] = { |
600 (ProcessFunc) gst_audio_test_src_create_white_noise_int16, |
523 (ProcessFunc) gst_audio_test_src_create_white_noise_int16, |
601 (ProcessFunc) gst_audio_test_src_create_white_noise_int32, |
524 (ProcessFunc) gst_audio_test_src_create_white_noise_int32, |
602 (ProcessFunc) gst_audio_test_src_create_white_noise_float, |
525 (ProcessFunc) gst_audio_test_src_create_white_noise_float, |
603 (ProcessFunc) gst_audio_test_src_create_white_noise_double |
526 (ProcessFunc) gst_audio_test_src_create_white_noise_double |
604 }; |
527 }; |
714 |
635 |
715 #define DEFINE_SINE_TABLE(type,scale) \ |
636 #define DEFINE_SINE_TABLE(type,scale) \ |
716 static void \ |
637 static void \ |
717 gst_audio_test_src_create_sine_table_##type (GstAudioTestSrc * src, g##type * samples) \ |
638 gst_audio_test_src_create_sine_table_##type (GstAudioTestSrc * src, g##type * samples) \ |
718 { \ |
639 { \ |
719 gint i, c; \ |
640 gint i; \ |
720 gdouble step, scl; \ |
641 gdouble step, scl; \ |
721 \ |
642 \ |
722 step = M_PI_M2 * src->freq / src->samplerate; \ |
643 step = M_PI_M2 * src->freq / src->samplerate; \ |
723 scl = 1024.0 / M_PI_M2; \ |
644 scl = 1024.0 / M_PI_M2; \ |
724 \ |
645 \ |
725 i = 0; \ |
646 for (i = 0; i < src->generate_samples_per_buffer; i++) { \ |
726 while (i < (src->generate_samples_per_buffer * src->channels)) { \ |
|
727 src->accumulator += step; \ |
647 src->accumulator += step; \ |
728 if (src->accumulator >= M_PI_M2) \ |
648 if (src->accumulator >= M_PI_M2) \ |
729 src->accumulator -= M_PI_M2; \ |
649 src->accumulator -= M_PI_M2; \ |
730 \ |
650 \ |
731 for (c = 0; c < src->channels; ++c) \ |
651 samples[i] = (g##type) scale * src->wave_table[(gint) (src->accumulator * scl)]; \ |
732 samples[i++] = (g##type) scale * src->wave_table[(gint) (src->accumulator * scl)]; \ |
|
733 } \ |
652 } \ |
734 } |
653 } |
735 |
654 |
736 DEFINE_SINE_TABLE (int16, 32767.0); |
655 DEFINE_SINE_TABLE (int16, 32767.0); |
737 DEFINE_SINE_TABLE (int32, 2147483647.0); |
656 DEFINE_SINE_TABLE (int32, 2147483647.0); |
738 DEFINE_SINE_TABLE (float, 1.0); |
657 DEFINE_SINE_TABLE (float, 1.0); |
739 DEFINE_SINE_TABLE (double, 1.0); |
658 DEFINE_SINE_TABLE (double, 1.0); |
740 |
659 |
741 static const ProcessFunc sine_table_funcs[] = { |
660 static ProcessFunc sine_table_funcs[] = { |
742 (ProcessFunc) gst_audio_test_src_create_sine_table_int16, |
661 (ProcessFunc) gst_audio_test_src_create_sine_table_int16, |
743 (ProcessFunc) gst_audio_test_src_create_sine_table_int32, |
662 (ProcessFunc) gst_audio_test_src_create_sine_table_int32, |
744 (ProcessFunc) gst_audio_test_src_create_sine_table_float, |
663 (ProcessFunc) gst_audio_test_src_create_sine_table_float, |
745 (ProcessFunc) gst_audio_test_src_create_sine_table_double |
664 (ProcessFunc) gst_audio_test_src_create_sine_table_double |
746 }; |
665 }; |
747 |
666 |
748 #define DEFINE_TICKS(type,scale) \ |
|
749 static void \ |
|
750 gst_audio_test_src_create_tick_##type (GstAudioTestSrc * src, g##type * samples) \ |
|
751 { \ |
|
752 gint i, c; \ |
|
753 gdouble step, scl; \ |
|
754 \ |
|
755 step = M_PI_M2 * src->freq / src->samplerate; \ |
|
756 scl = 1024.0 / M_PI_M2; \ |
|
757 \ |
|
758 for (i = 0; i < src->generate_samples_per_buffer; i++) { \ |
|
759 src->accumulator += step; \ |
|
760 if (src->accumulator >= M_PI_M2) \ |
|
761 src->accumulator -= M_PI_M2; \ |
|
762 \ |
|
763 if ((src->next_sample + i)%src->samplerate < 1600) { \ |
|
764 for (c = 0; c < src->channels; ++c) \ |
|
765 samples[(i * src->channels) + c] = (g##type) scale * src->wave_table[(gint) (src->accumulator * scl)]; \ |
|
766 } else { \ |
|
767 for (c = 0; c < src->channels; ++c) \ |
|
768 samples[(i * src->channels) + c] = 0; \ |
|
769 } \ |
|
770 } \ |
|
771 } |
|
772 |
|
773 DEFINE_TICKS (int16, 32767.0); |
|
774 DEFINE_TICKS (int32, 2147483647.0); |
|
775 DEFINE_TICKS (float, 1.0); |
|
776 DEFINE_TICKS (double, 1.0); |
|
777 |
|
778 static const ProcessFunc tick_funcs[] = { |
|
779 (ProcessFunc) gst_audio_test_src_create_tick_int16, |
|
780 (ProcessFunc) gst_audio_test_src_create_tick_int32, |
|
781 (ProcessFunc) gst_audio_test_src_create_tick_float, |
|
782 (ProcessFunc) gst_audio_test_src_create_tick_double |
|
783 }; |
|
784 |
|
785 /* Gaussian white noise using Box-Muller algorithm. unit variance |
|
786 * normally-distributed random numbers are generated in pairs as the real |
|
787 * and imaginary parts of a compex random variable with |
|
788 * uniformly-distributed argument and \chi^{2}-distributed modulus. |
|
789 */ |
|
790 |
|
791 #define DEFINE_GAUSSIAN_WHITE_NOISE(type,scale) \ |
|
792 static void \ |
|
793 gst_audio_test_src_create_gaussian_white_noise_##type (GstAudioTestSrc * src, g##type * samples) \ |
|
794 { \ |
|
795 gint i, c; \ |
|
796 gdouble amp = (src->volume * scale); \ |
|
797 \ |
|
798 for (i = 0; i < src->generate_samples_per_buffer * src->channels; ) { \ |
|
799 for (c = 0; c < src->channels; ++c) { \ |
|
800 gdouble mag = sqrt (-2 * log (1.0 - g_random_double ())); \ |
|
801 gdouble phs = g_random_double_range (0.0, M_PI_M2); \ |
|
802 \ |
|
803 samples[i++] = (g##type) (amp * mag * cos (phs)); \ |
|
804 if (++c >= src->channels) \ |
|
805 break; \ |
|
806 samples[i++] = (g##type) (amp * mag * sin (phs)); \ |
|
807 } \ |
|
808 } \ |
|
809 } |
|
810 |
|
811 DEFINE_GAUSSIAN_WHITE_NOISE (int16, 32767.0); |
|
812 DEFINE_GAUSSIAN_WHITE_NOISE (int32, 2147483647.0); |
|
813 DEFINE_GAUSSIAN_WHITE_NOISE (float, 1.0); |
|
814 DEFINE_GAUSSIAN_WHITE_NOISE (double, 1.0); |
|
815 |
|
816 static const ProcessFunc gaussian_white_noise_funcs[] = { |
|
817 (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_int16, |
|
818 (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_int32, |
|
819 (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_float, |
|
820 (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_double |
|
821 }; |
|
822 |
|
823 /* |
667 /* |
824 * gst_audio_test_src_change_wave: |
668 * gst_audio_test_src_change_wave: |
825 * Assign function pointer of wave genrator. |
669 * Assign function pointer of wave genrator. |
826 */ |
670 */ |
827 static void |
671 static void |
971 { |
783 { |
972 /* we're seekable... */ |
784 /* we're seekable... */ |
973 return TRUE; |
785 return TRUE; |
974 } |
786 } |
975 |
787 |
976 static gboolean |
|
977 gst_audio_test_src_check_get_range (GstBaseSrc * basesrc) |
|
978 { |
|
979 GstAudioTestSrc *src; |
|
980 |
|
981 src = GST_AUDIO_TEST_SRC (basesrc); |
|
982 |
|
983 /* if we can operate in pull mode */ |
|
984 return src->can_activate_pull; |
|
985 } |
|
986 |
|
987 static GstFlowReturn |
788 static GstFlowReturn |
988 gst_audio_test_src_create (GstBaseSrc * basesrc, guint64 offset, |
789 gst_audio_test_src_create (GstBaseSrc * basesrc, guint64 offset, |
989 guint length, GstBuffer ** buffer) |
790 guint length, GstBuffer ** buffer) |
990 { |
791 { |
991 GstFlowReturn res; |
792 GstFlowReturn res; |
992 GstAudioTestSrc *src; |
793 GstAudioTestSrc *src; |
993 GstBuffer *buf; |
794 GstBuffer *buf; |
994 GstClockTime next_time; |
795 GstClockTime next_time; |
995 gint64 next_sample, next_byte; |
796 gint64 n_samples; |
996 guint bytes, samples; |
797 gint sample_size; |
997 GstElementClass *eclass; |
|
998 |
798 |
999 src = GST_AUDIO_TEST_SRC (basesrc); |
799 src = GST_AUDIO_TEST_SRC (basesrc); |
|
800 |
|
801 if (src->eos_reached) |
|
802 return GST_FLOW_UNEXPECTED; |
1000 |
803 |
1001 /* example for tagging generated data */ |
804 /* example for tagging generated data */ |
1002 if (!src->tags_pushed) { |
805 if (!src->tags_pushed) { |
1003 GstTagList *taglist; |
806 GstTagList *taglist; |
|
807 GstEvent *event; |
1004 |
808 |
1005 taglist = gst_tag_list_new (); |
809 taglist = gst_tag_list_new (); |
1006 |
810 |
1007 gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, |
811 gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, |
1008 GST_TAG_DESCRIPTION, "audiotest wave", NULL); |
812 GST_TAG_DESCRIPTION, "audiotest wave", NULL); |
1009 |
813 |
1010 eclass = GST_ELEMENT_CLASS (parent_class); |
814 event = gst_event_new_tag (taglist); |
1011 if (eclass->send_event) |
815 gst_pad_push_event (basesrc->srcpad, event); |
1012 eclass->send_event (GST_ELEMENT_CAST (basesrc), |
|
1013 gst_event_new_tag (taglist)); |
|
1014 src->tags_pushed = TRUE; |
816 src->tags_pushed = TRUE; |
1015 } |
|
1016 |
|
1017 if (src->eos_reached) |
|
1018 return GST_FLOW_UNEXPECTED; |
|
1019 |
|
1020 /* if no length was given, use our default length in samples otherwise convert |
|
1021 * the length in bytes to samples. */ |
|
1022 if (length == -1) |
|
1023 samples = src->samples_per_buffer; |
|
1024 else |
|
1025 samples = length / (src->sample_size * src->channels); |
|
1026 |
|
1027 /* if no offset was given, use our next logical byte */ |
|
1028 if (offset == -1) |
|
1029 offset = src->next_byte; |
|
1030 |
|
1031 /* now see if we are at the byteoffset we think we are */ |
|
1032 if (offset != src->next_byte) { |
|
1033 GST_DEBUG_OBJECT (src, "seek to new offset %" G_GUINT64_FORMAT, offset); |
|
1034 /* we have a discont in the expected sample offset, do a 'seek' */ |
|
1035 src->next_sample = offset / (src->sample_size * src->channels); |
|
1036 src->next_time = |
|
1037 gst_util_uint64_scale_int (src->next_sample, GST_SECOND, |
|
1038 src->samplerate); |
|
1039 src->next_byte = offset; |
|
1040 } |
817 } |
1041 |
818 |
1042 /* check for eos */ |
819 /* check for eos */ |
1043 if (src->check_seek_stop && |
820 if (src->check_seek_stop && |
1044 (src->sample_stop > src->next_sample) && |
821 (src->n_samples_stop > src->n_samples) && |
1045 (src->sample_stop < src->next_sample + samples) |
822 (src->n_samples_stop < src->n_samples + src->samples_per_buffer) |
1046 ) { |
823 ) { |
1047 /* calculate only partial buffer */ |
824 /* calculate only partial buffer */ |
1048 src->generate_samples_per_buffer = src->sample_stop - src->next_sample; |
825 src->generate_samples_per_buffer = src->n_samples_stop - src->n_samples; |
1049 next_sample = src->sample_stop; |
826 n_samples = src->n_samples_stop; |
1050 src->eos_reached = TRUE; |
827 src->eos_reached = TRUE; |
1051 } else { |
828 } else { |
1052 /* calculate full buffer */ |
829 /* calculate full buffer */ |
1053 src->generate_samples_per_buffer = samples; |
830 src->generate_samples_per_buffer = src->samples_per_buffer; |
1054 next_sample = src->next_sample + samples; |
831 n_samples = src->n_samples + src->samples_per_buffer; |
1055 } |
832 } |
1056 |
833 next_time = gst_util_uint64_scale (n_samples, GST_SECOND, |
1057 bytes = src->generate_samples_per_buffer * src->sample_size * src->channels; |
834 (guint64) src->samplerate); |
1058 |
835 |
1059 if ((res = gst_pad_alloc_buffer (basesrc->srcpad, src->next_sample, |
836 /* allocate a new buffer suitable for this pad */ |
1060 bytes, GST_PAD_CAPS (basesrc->srcpad), &buf)) != GST_FLOW_OK) { |
837 switch (src->format) { |
|
838 case GST_AUDIO_TEST_SRC_FORMAT_S16: |
|
839 sample_size = sizeof (gint16); |
|
840 break; |
|
841 case GST_AUDIO_TEST_SRC_FORMAT_S32: |
|
842 sample_size = sizeof (gint32); |
|
843 break; |
|
844 case GST_AUDIO_TEST_SRC_FORMAT_F32: |
|
845 sample_size = sizeof (gfloat); |
|
846 break; |
|
847 case GST_AUDIO_TEST_SRC_FORMAT_F64: |
|
848 sample_size = sizeof (gdouble); |
|
849 break; |
|
850 default: |
|
851 sample_size = -1; |
|
852 GST_ELEMENT_ERROR (src, CORE, NEGOTIATION, (NULL), |
|
853 ("format wasn't negotiated before get function")); |
|
854 return GST_FLOW_NOT_NEGOTIATED; |
|
855 break; |
|
856 } |
|
857 |
|
858 if ((res = gst_pad_alloc_buffer (basesrc->srcpad, src->n_samples, |
|
859 src->generate_samples_per_buffer * sample_size, |
|
860 GST_PAD_CAPS (basesrc->srcpad), &buf)) != GST_FLOW_OK) { |
1061 return res; |
861 return res; |
1062 } |
862 } |
1063 |
863 |
1064 next_byte = src->next_byte + bytes; |
864 GST_BUFFER_TIMESTAMP (buf) = src->timestamp_offset + src->running_time; |
1065 next_time = gst_util_uint64_scale_int (next_sample, GST_SECOND, |
865 GST_BUFFER_OFFSET_END (buf) = n_samples; |
1066 src->samplerate); |
866 GST_BUFFER_DURATION (buf) = next_time - src->running_time; |
1067 |
867 |
1068 GST_LOG_OBJECT (src, "samplerate %d", src->samplerate); |
868 gst_object_sync_values (G_OBJECT (src), src->running_time); |
1069 GST_LOG_OBJECT (src, "next_sample %" G_GINT64_FORMAT ", ts %" GST_TIME_FORMAT, |
869 |
1070 next_sample, GST_TIME_ARGS (next_time)); |
870 src->running_time = next_time; |
1071 |
871 src->n_samples = n_samples; |
1072 GST_BUFFER_TIMESTAMP (buf) = src->timestamp_offset + src->next_time; |
|
1073 GST_BUFFER_OFFSET (buf) = src->next_sample; |
|
1074 GST_BUFFER_OFFSET_END (buf) = next_sample; |
|
1075 GST_BUFFER_DURATION (buf) = next_time - src->next_time; |
|
1076 |
|
1077 gst_object_sync_values (G_OBJECT (src), src->next_time); |
|
1078 |
|
1079 src->next_time = next_time; |
|
1080 src->next_sample = next_sample; |
|
1081 src->next_byte = next_byte; |
|
1082 |
872 |
1083 GST_LOG_OBJECT (src, "generating %u samples at ts %" GST_TIME_FORMAT, |
873 GST_LOG_OBJECT (src, "generating %u samples at ts %" GST_TIME_FORMAT, |
1084 src->generate_samples_per_buffer, |
874 length, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); |
1085 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); |
|
1086 |
875 |
1087 src->process (src, GST_BUFFER_DATA (buf)); |
876 src->process (src, GST_BUFFER_DATA (buf)); |
1088 |
877 |
1089 if (G_UNLIKELY ((src->wave == GST_AUDIO_TEST_SRC_WAVE_SILENCE) |
878 if (G_UNLIKELY ((src->wave == GST_AUDIO_TEST_SRC_WAVE_SILENCE) |
1090 || (src->volume == 0.0))) { |
879 || (src->volume == 0.0))) { |