Changing volume dynamically

Tony Houghton h at
Thu Nov 30 20:35:58 UTC 2017

I'm trying to write an app that plays soothing pulses of white/pink etc
noise. Each pulse's amplitude follows the profile of a sine wave from >=0
to <=1 and back, and each pulse has a randomised duration, and a randomised
delay before the next one. My naive approach was to change the volume
property on a volume element, using g_timeout_add with a period of 1/100
sec. It isn't working properly, pulses often stay silent for a while when
they should be growing louder, then suddenly jump; usually they seem to
follow the profile for the rest of the pulse, but sometimes it sounds
stepped. So I think what's going on is that the property change is failing
to sync across threads. I guess I need to use a GstControlSource, but I'm
not sure how I can get it to do what I want.

The first problem is that I don't want to change the volume alone, I also
want to change the stereo position (using audiopanorama) and the standard
deviation when using Gaussian white noise (controlled by audiotestsrc's
volume property, which is why I'm using a separate volume element). Volume
and SD can be derived from the same sine wave, but I want to pan one way
only, so that needs a wave of half the frequency. So I think I would be
better off using a source based on a sawtooth and deriving sines on the
fly. GstProxyControlBinding can't do this. Is it possible to just derive
from GstControlBinding and override gst_control_binding_sync_values to
remap from the sawtooth to the sine values?

The second problem is that I need a random space between each "tooth" in
the wave, and each tooth to have a random duration. I think I should ignore
GstLFOControlSource because I would need to attach a custom GstControlSource to
it anyway to change its properties with precise timing, and I could just as
easily generate sawtooth pulses in the latter. Is it as simple as
overriding gst_control_source_get_value() and
Or even making concrete instances of it and filling in their get_value and
get_value_array fields? But in the latter case I wouldn't be able to store
private data for generating the waveform so elegantly.

That leads to another question. I would use some sort of LIFO table to work
out the start and end timestamps of each pulse. When would it be safe to
discard old values from the table? Is it guaranteed that the timestamps
passed to gst_control_source_get_value*() always increase, or will I have
to wait until their time has passed according to some clock associated with
the pipeline?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the gstreamer-devel mailing list