Distorted playback of real-time audio on Linux

Hi,
I have switched my linux environment from Fedora 12 to Ubuntu
10.04. This gives me better network performance with the USRP2, even
when running Ubuntu 10.04 inside a VMware environment on Mac OS X 10.4.

However, real-time audio, e.g. an FM receiver application, when played
back in real-time gives me crackles and distortions. If the output is
sent to a wave file sink, and stored on the hard disk, it sounds fine.
So, FM demodulation is happening correctly and the signal reception is
very clear, as evidenced by the stored wave file.

However, when listening to it in real-time, it’s not the case.

Has anyone else encountered this problem before? I’ve run these tests
both natively by installing Ubuntu 10.04 on the iMac 27 i7 and
configuring the intel HDA audio module, and also on a VM image, but it
gives me the same results.

Elvis D.

On 12 August 2010 09:24, Elvis D. [email protected] wrote:

Has anyone else encountered this problem before? I’ve run these tests both
natively by installing Ubuntu 10.04 on the iMac 27 i7 and configuring the
intel HDA audio module, and also on a VM image, but it gives me the same
results.

Try to resample the audio to 44.1 kHz or 48 kHz using a
rational_resampler block. That might solve it.

Alex

Hi Alex,

On Aug 12, 2010, at 1:03 PM, Alexandru C. wrote:

Try to resample the audio to 44.1 kHz or 48 kHz using a
rational_resampler block. That might solve it.

Adding the Rational Resampler, with decimation = 2 and interpolation =
3, works in terms of resampling. The two separate wave files created
before and after resampling sound correct.

However, when I am listening to the audio in real-time, there are severe
audio crackles and distortions.

I also notice that there are a lot of audio over-runs in my console
output:

gr_fir_fff: using SSE
aUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaUaU

This behavior is the same, whether I run GNU Radio natively on my iMac
or inside a virtual machine using both Ubuntu 10.04 and 9.10.

What do you think the root cause is?

Best regards,

Elvis D.

Hi,
Would anyone happen to have an idea where I should start looking,
in order to debug the audio under-runs for the audio sink?

Best regards,

Elvis D.

Hi,
I was reading up on audio underruns, and basically its because
the application isn’t being able to generate enough data for the
sound-card, i.e. GNU Radio generating data slower than the card is
consuming the data.

Ubuntu Studio Upgrade from Ubuntu - Community Ubuntu Documentation

I upgraded the Ubuntu 10.04 64-bit with hard real-time extensions, to
improve the latency. However, I still get audio under-runs.

Best regards,

Elvis D.

On Thu, Aug 12, 2010 at 09:29:35PM +0400, Elvis D. wrote:

Hi,

Would anyone happen to have an idea where I should start looking,
in order to debug the audio under-runs for the audio sink?

Does the dial_tone.py example sound OK?

Eric

Hi,
Another data point, if I set the audio sink sample rate to 16kHz,
there are no under-runs, but that obviously will cause the sound to play
back at a lower pitch, but atleast there are no crackles and
distortions. In the console output window, there are no audio underruns.

When you set the audio sink sample rate to any value higher than 16kHz,
it starts to distort and crackle.

What can be inferred from all this?

Best regards,

Elvis

Hi Eric,
I came across an old thread,
http://www.ruby-forum.com/topic/107228

“There is a general issue related to the fact that when using
usrp_wfm_rcv and similar applications that there are in fact two clock
domains, and that they are guaranteed not to match. There’s an osc on
the USRP and an osc associated with the sound card. We made an API
change in the audio interfaces that can specify that it’s NOT OK to
block when accessing the audio interface. When used in a flow graph
that contained both an audio sink or source and a USRP sink or source,
this
would result in the USRP being the master clock, and would dodge the
“two clocks” problem. Although the parameter was added to all (most)
audio interfaces, I believe that it currently only works on the
portaudio interface. Please feel free to fix this for gr-audio-alsa,
gr-audio-oss and gr-audio-osx.”

This could potentially explain the issue I have, with distorted and
crackling audio. It might also explain the nearly un-reproduceable
random behaviour when it sometimes works giving clear audio output (so
far has happened only 4 times in 6 weeks, approx 16 hours a day).

How would one go about fixing this for gr-audio-alsa? Perhaps if you can
give me some high level tips and pointers, I could try to make the
changes.

Best regards,

Elvis D.

On 08/12/2010 04:47 PM, Elvis D. wrote:

would result in the USRP being the master clock, and would dodge the
“two clocks” problem. Although the parameter was added to all (most)
audio interfaces, I believe that it currently only works on the
portaudio interface. Please feel free to fix this for gr-audio-alsa,
gr-audio-oss and gr-audio-osx."

This could potentially explain the issue I have, with distorted and crackling audio. It might also explain the nearly un-reproduceable random behaviour when it sometimes works giving clear audio output (so far has happened only 4 times in 6 weeks, approx 16 hours a day).

How would one go about fixing this for gr-audio-alsa? Perhaps if you can give me some high level tips and pointers, I could try to make the changes.

Depending on how ALSA is configured, it may be able to do the final
resample internally. I’d look carefully at the sample rates at each of
the blocks and see what rate is being sent to ALSA. Drawing this out
should be helpful.

Philip

On Fri, Aug 13, 2010 at 03:47:12AM +0400, Elvis D. wrote:

would result in the USRP being the master clock, and would dodge the
“two clocks” problem. Although the parameter was added to all (most)
audio interfaces, I believe that it currently only works on the
portaudio interface. Please feel free to fix this for gr-audio-alsa,
gr-audio-oss and gr-audio-osx."

This could potentially explain the issue I have, with distorted and
crackling audio. It might also explain the nearly un-reproduceable
random behaviour when it sometimes works giving clear audio output
(so far has happened only 4 times in 6 weeks, approx 16 hours a
day).

How would one go about fixing this for gr-audio-alsa? Perhaps if you
can give me some high level tips and pointers, I could try to make
the changes.

Thanks for being willing to take a look at this!

First off, you’d need to read the docs on ALSA and understand the
interfaces that are available to work with.

I think that fixing it in audio_alsa_sink should be enough. Once the
sink is working you could go after the source if you like.
Given the interfaces exported by ALSA, you’d need to figure out how to
honor the condition “ok_to_block == False”.

There are two cases.

(1) audio clock is slower than usrp clock
(2) audio clock is faster than usrp clock

In (1) you’ll want to avoid an ever growing queue of samples by
somehow giving the driver samples when it wants them, but dropping the
excess samples (hopefull in a way that nobody notices) every now and
then.

In (2) you’ll need to insert an extra sample every now and then to keep
the audio from underruning.

It’s been a long while since I looked at the ALSA docs, but there
may be some kind of callback that you can arrange for the ALSA code
to call when it needs (or provides) samples. Right now we just
naively block when reading or writing.

You may want to look at audio_portaudio_sink. It’s got at least
partial support for this feature, although the interface to the driver
will be different than ALSA.

Eric

Hi Eric,
Before I dive into it, I just have a quick question.

Why is it that others are not encountering the same issue? The same
example code was run on a Mac Pro dual quad machine belonging to another
member of this forum, and he didn’t face the issue of crackling and
distorted audio with the audio sink.

Anyway, I guess from a logical stand-point if the wave file sink writes
to the file correctly, then the data is coming in correctly, and its
only the real-time rendering of the audio using the alsa audio sink
that’s not working correctly.

Still, I wonder what the difference could be, it working consistently
for others, but not for me.

Best regards,

Elvis D.

I guess, its perhaps an older version of GNU Radio, the one before the
audio API changed.

Best regards,

Elvis

On 13 August 2010 01:02, Elvis D. [email protected] wrote:

Hi,
Another data point, if I set the audio sink sample rate to 16kHz, there are no under-runs, but that obviously will cause the sound to play back at a lower pitch, but atleast there are no crackles and distortions. In the console output window, there are no audio underruns.

When you set the audio sink sample rate to any value higher than 16kHz, it starts to distort and crackle.

What can be inferred from all this?

Maybe it is a driver issue. I suppose your iMac is the latest
generation (late 2009?) but the distributed alsa drivers are usually
older.
You can check how the hardware is detected in the hardware tab of the
audio settings or “lspci | grep Audio” and see how it fits with what’s
actually in the computer.
You can also try to install linux-backports-modules-alsa and see if
that provides better driver.

ALex

Hi Alex,

On Aug 13, 2010, at 12:39 PM, Alexandru C. wrote:

Maybe it is a driver issue. I suppose your iMac is the latest
generation (late 2009?) but the distributed alsa drivers are usually
older.

Yes, my iMac 27" is a late 2009 model.

$ sudo dmidecode -s system-product-name

iMac11,1

You can check how the hardware is detected in the hardware tab of the
audio settings or “lspci | grep Audio” and see how it fits with what’s
actually in the computer.

The following commands show the various hardware and codec installed on
the iMac. I’m running it natively on the iMac 27 at the moment.

Install required packages to enable audio.

$ sudo apt-get install linux-backports-modules-alsa-lucid-generic
gnome-alsamixer

Find the Sound card model

cat /proc/asound/card0/codec#0 | grep Codec

Codec: Cirrus Logic CS4206

List all the audio PCI devices connected to the system

$ sudo lspci | grep Audio

00:1b.0 Audio device: Intel Corporation 5 Series/3400 Series Chipset
High Definition Audio (rev 06)
01:00.1 Audio device: ATI Technologies Inc HD48x0 audio

Modify the alsa-base.conf file.

$ sudo gedit /etc/modprobe.d/alsa-base.conf

options snd-hda-intel power_save=10 power_save_controller=N model=imac27

For the Cirrus Logic CS4206/4207 chipset, the snd-hda-intel driver
options parameter for the model is imac27

Do you think the two are matched?

Best regards,

Elvis D.

On Fri, Aug 13, 2010 at 09:59:20PM +0400, Elvis D. wrote:

Hi Eric,
Before I dive into it, I just have a quick question.

Why is it that others are not encountering the same issue? The same
example code was run on a Mac Pro dual quad machine belonging to
another member of this forum, and he didn’t face the issue of
crackling and distorted audio with the audio sink.

There has been the problem with the “two clocks” since the code was
written. The symptoms and how bad they are depend on how far the
clocks are apart, and which one’s fast wrt to the other.

Anyway, I guess from a logical stand-point if the wave file sink
writes to the file correctly, then the data is coming in correctly,
and its only the real-time rendering of the audio using the alsa
audio sink that’s not working correctly.

Perhaps. You’re on a VM right?

As I mentioned above, I believe the problem is the “two clock problem”.

Still, I wonder what the difference could be, it working
consistently for others, but not for me.

Hi Eric,

On Aug 13, 2010, at 8:38 PM, Eric B. wrote:

Given the interfaces exported by ALSA, you’d need to figure out how to
honor the condition “ok_to_block == False”.

Could you please tell me the intent behind the ok_to_block flag?

By blocking, do you mean a synchronous call, which will block and render
the subsystem un-responsive, until, it completes?

In this scenario, should the two subsystems be running asynchronously,
with a buffer in between, so that the two can run at different clock
rates? e.g. USRP2 running at a particular clock rate, and the
alsa_audio_sink running at a different clock rate?

Or is the whole GNU Radio flow-graph a synchronous system, i.e. it
completes execution and evaluation of the entire flow graph, every clock
cycle, reading data from the environment, processing the inputs, and
computing the output, for every clock cycle?

Best regards,

Elvis D.

On Wed, Aug 18, 2010 at 18:35, Eric B. [email protected] wrote:

The relative rates may be mismatched by less than 0.1%. Even at that
level, on the average you’d need to be adding or dropping 1 sample
every 1000 to match the rates between the two clock domains.

I’ve had (cheap) sound cards that required 2500 ppm resampling to
match a frequency reference. That’s 1 sample slip every 400!

Johnathan

Hi Eric,

On Aug 19, 2010, at 5:35 AM, Eric B. wrote:

Elvis, do you understand the high level source of the problem?
That is, that there are two hardware devices whose clocks are not
synchronized?

Yes, I do now, and that one possible solution is to rate match or buffer
the sample data to the audio sink. I was looking at the PortAudio sink,
didn’t realize it was cross-platform portable; so I’ll enable
gr-audio-portaudio, and disable gr-audio-oss and gr-audio-alsa (if it’s
okay to do so), and see if the problem still manifests itself.

The issue manifests itself on both a VM and with GR running natively on
my hardware (late 2009 iMac 27" i7).

Best regards,

Elvis D.

On Aug 19, 2010, at 1:31 AM, Elvis D. wrote:

The issue manifests itself on both a VM and with GR running natively
on my hardware (late 2009 iMac 27" i7).

My US$0.02 worth: TTBOMK&M, on the Mac OS X side you can input and
output about any sample rate & CoreAudio will handle the sample rate
conversion for you to / from what the hardware requires / provides.
If you have audio issues on the native side, those issues are probably
not with the audio source or sink. That said, I’ve also never worked
on an i7 & from my reading there are subtle differences in execution
between it and the Core2 series. While I doubt the processor is the
issue, you never know. Good luck with your continued debugging. - MLD

On Sat, Aug 14, 2010 at 03:16:38AM +0400, Elvis D. wrote:

Hi Eric,

On Aug 13, 2010, at 8:38 PM, Eric B. wrote:

Given the interfaces exported by ALSA, you’d need to figure out how to
honor the condition “ok_to_block == False”.

Could you please tell me the intent behind the ok_to_block flag?

The name could be improved, but when “ok_to_block == False”, the
interpretation should be that the GR interface to the audio subsystem
should attempt to rate match the data being consumed or produced by
the GR flow graph to the rate that the audio subsystem wants it.

By blocking, do you mean a synchronous call, which will block and
render the subsystem un-responsive, until, it completes?

Yes. You should think of “ok_to_block == True” means that the audio
device is effectively setting the absolute (real-time) sample rate of
the graph. This only makes sense when there is no other source or
sink that is also attempting to set the absolute (real-time) sample
rate. Thus the problem shows up with flow graphs that contain either
a USRP source and a audio sink or an audio source and a USRP sink.
(It doesn’t have to be a USRP — any other i/o device that’s tied to
a sample rate clock will show the problem.)

Note also that depending on which clock is faster rate matching requires
either dropping or adding samples on average.

In this scenario, should the two subsystems be running
asynchronously, with a buffer in between, so that the two can run at
different clock rates? e.g. USRP2 running at a particular clock
rate, and the alsa_audio_sink running at a different clock rate?

Yes.

The relative rates may be mismatched by less than 0.1%. Even at that
level, on the average you’d need to be adding or dropping 1 sample
every 1000 to match the rates between the two clock domains.

Or is the whole GNU Radio flow-graph a synchronous system, i.e. it
completes execution and evaluation of the entire flow graph, every
clock cycle, reading data from the environment, processing the
inputs, and computing the output, for every clock cycle?

No, it doesn’t work that way. It buffers a certain amount of data
between blocks before running them.

Elvis, do you understand the high level source of the problem?
That is, that there are two hardware devices whose clocks are not
synchronized?

Eric