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