How to properly switch between multiple audio sources while playing

OPENSOURCE Manuel Huber manuel.huber at opensource.tttech.com
Thu Apr 4 13:04:27 UTC 2019


Hello,

I would like to switch between playing sine tones of specific duration
and playback files - both with low latency. There seem to be different
ways possible to potentially achieve this, and I already tried most of
them. However, I'm unsure which approach is cleanest and should be
followed in that case and would kindly ask for guidance...

I would of course be happy to report back how the final solution
looked like, which might be helpful for others.


There are multiple things important here:

- I would like to prevent that gstreamer has to spawns threads
  whenever a tone or file is played. I would rather like to keep the
  threads idle, which should be achieved if kept in PAUSED state as I
  understand it.

- Fast switching between playing files and tones. It doesn't have to
  be gap-less, but I think it would be good to avoid having to
  reassemble the pipeline every time. I'd rather have one pipeline and
  just replace / switch the current source.

To simplify the use-case, I tried to only switch between two sine
tones (just to get a basic understanding).

1. Using input-selector and valve

    audiotestsrc1 -> valve1 -+
                             +-> input-selector -> alsasink
    audiotestsrc2 -> valve2 -+

  I heard some click's and pop's when switching...

2. Dynamically changing the pipeline using probes:

    <source> -> [queue ->] alsasink

  The idea would be to replace the source using blocking probes similar to this:
  
  - https://gstreamer.freedesktop.org/documentation/application-development/advanced/pipeline-manipulation.html#changing-elements-in-a-pipeline

  I'm not sure whether it's possible to apply the same idea when
  replacing the source. Would this work:

  - block on source.src pad, install a new probe and send EOS
  - wait for EOS on alsasink.sink (or on the queue.src?)
  - in the callback for EOS remove the source, add a new source, set
    the state, ...

3. Using playbin directly

  I'm unsure whether it's possible to replace the source while playing
  or there is some other way to start playing sine tones mixed with
  actual files. Maybe also a combination with input-selector is
  possible?


A second problem is how to play the sine tone only for the requested
time. I see two approaches:

- audiotestsrc seems to be quite capable on the second look, as
  adjusting the parameters (lower buffer size, smaller blocks,
  live-source, etc) can lower the latency during starting and also
  allows to set the playback time (more or less) exactly to the
  requested duration.  The only problem I had with that approach is
  how to "rewind" and re-configure the element (or do I have to
  recreate the element and replace it (for example using option 2)
  every time a new tone will be played?

- appsrc gives me (more or less) full control over the playback, seems
  to work fine for me. However, if not necessary, I would of course
  prefer to stick with a standard source like audiotestsrc.


If anybody has suggestions regarding the topic, I would be happy to
hear about it ;)


Best regards,

Manuel


More information about the gstreamer-devel mailing list