Ultrasound and audiotestsrc

Christian Leichsenring cleichsenring at techfak.uni-bielefeld.de
Tue Sep 1 12:58:06 PDT 2015


On 08/28/2015 05:40 PM, Nicolas Dufresne wrote:
> Seems fairly simple patch to propose. In case you don't know yet, you
> can create the patch and commit to your local git repository. And the
> submit the patch (in git format-patch form) through bugs.gnome.org.

"fairly simple patch" Well, I believe you really jinxed it ;) I ran into
a nasty problem that I can't see an elegant solution for right now. See
below.

> From property stand point, we should maybe increase the limits to
> something that make sense (property range are static). And then post an
> error if the frequency cannot be represented at the selected rate.

Actually, what I ended up doing is to dynamically use a minimal sample
rate that's four times the freq property (I tried using twice the freq
but ... see below). So if a downstream element or caps filter forces a
sample rate that is too low, caps negotiation should simply fail. One
could argue that this limitation is unnecessary for noise wave forms
that don't use freq at all but since this won't come into effect until
people set freq despite not using it or if the sample rate is below 1760
Hz (4 * the freq default), I don't think this would be a problem in
practice. Maybe a nicer error message would be good but since I'm not
sure about the intricacies of caps negotiations, I'm not sure where such
a message would be placed best.

*Anyway*, the main issue is that the Nyquist frequency is a great thing
in theory but audiotestsrc will currently output digital silence when
trying to produce a frequency that is exactly the Nyquist frequency
(which is actually forbidden by the Nyquist-Shannon sampling theorem but
could in principle work with common assumptions) and a slowly pulsing
target frequency f for a sampling rate of 2f+1. And since my original
code lead the caps negotiations to end up at the Nyquist frequency each
time the sample rate is not specified and the generated frequency is too
high, this was not just a weird corner case.

What happens is that the first sample is sin(0) = 0, the second sample
sin(π) = 0, the third sin(0) = 0 and so on. Now what would work here is
to use cos instead of sin (or any other method to phase shift the
signal). However, this will generate a signal that starts with maximum
amplitude instead of a zero crossing for all frequency/sample rate
combinations, which could lead to an audible artefact.

So there's no easy way out here. I could force the caps to use a sample
rate that's sufficiently higher than twice the Nyquist frequency (four
times the Nyquist frequency to be exact; just a minimally larger
sampling rate will not do as pointed out above) but that requires quite
unusual sampling rates for moderately high target frequencies.

A practical workaround to generate a sine at the Nyquist frequency is to
use a square wave instead. This will do exactly what one would expect
but of course it's not a solution either. It also requires one to allow
exactly 2f instead of 2f+1 (let alone 4f of course) because for 2f+1 the
square wave generator actually produces quite nasty artefacts. So given
all these weird aliasing artefacts, I decided to go with the 4f
solution, even though I'm not too happy about it.

I also decided not to upload my patch to the bug tracker right away but
get some second opinions here first. I attached the code so feel free to
have a look. BTW, I also changed the maximum number of channels because
it's quite impractical to have this restriction, especially given that
the audioconvert module doesn't allow upmixing to more than 8 channels.

Any feedback is much appreciated,

	Christian

-------------- next part --------------
A non-text attachment was scrubbed...
Name: ultrasound.patch
Type: text/x-patch
Size: 2607 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/gstreamer-devel/attachments/20150901/bea21c24/attachment.bin>


More information about the gstreamer-devel mailing list