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 gst_control_source_get_value_array()? 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?