Crackly audio through 3.5mm jack


96 posts   Page 2 of 4   1, 2, 3, 4
by dom » Fri Sep 14, 2012 7:24 am
millerpuckette wrote:That parasitic tone is the worst audio artifact in my opinion, but I think that
it will also be possible to further improve the audio by various (as yet unspecified)
bit-twiddling tricks -- I'll fool with this over the weekend if you seem interested (and
maybe regardless).

Sure, I'd love to hear suggestions for improvements.
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 5067
Joined: Wed Aug 17, 2011 7:41 pm
Location: Cambridge
by jackokring » Fri Sep 14, 2012 7:59 am
Using a accurate fast timer interrupt and doing a bit bang delta-sigma or MASH conversion. This requires more CPU as the PWM is no longer needed. Or if the PWM counter is read and rewritten, to alter the output wave, to not always be the same frequency (with various mark space). Maybe call it an advance-retard PWM. These methods require software to calculate the apparent voltage level, and alter it to better represent the interpolated over-sampled output required.

Here's some VHDL code for a DAC 16->1 bit which is not the best but shows the idea.

https://code.google.com/p/nibz/downloads/detail?name=dac.vhd&can=2&q=
Pi[NFA]=B256R0USB CL4SD8GB Raspbian Stock.
Pi[Work]=A+256 CL4SD8GB Raspbian Stock.
My favourite constant 1.65056745028
User avatar
Posts: 815
Joined: Tue Jul 31, 2012 8:27 am
Location: London, UK
by jackokring » Fri Sep 14, 2012 8:57 am
I put a IIR low pass filter i front of it in one design to interpolate and over sample. Simply add to an accumulator the difference between the accumulator and the incoming sample divided by 2. This makes a low pass, and extends the bit depth. The extra bit depth can be processed at 32 bits in the DAC by extending the precision of the DAC LSB to even more (less?) LSBs. Paying attention to signed arithmetic.
Pi[NFA]=B256R0USB CL4SD8GB Raspbian Stock.
Pi[Work]=A+256 CL4SD8GB Raspbian Stock.
My favourite constant 1.65056745028
User avatar
Posts: 815
Joined: Tue Jul 31, 2012 8:27 am
Location: London, UK
by bradvido » Fri Sep 14, 2012 1:54 pm
I am also having poor quality audio (tried various different builds) only through the 3.5 mm headphone jack. Making sure the Pi's volume is all the way up helps a little bith with the static/crackling, but it's still pretty poor quality.

I'll be eagerly awating a fix and willing to help test/debug.

Hopefully this is just driver related.
Posts: 11
Joined: Mon Sep 10, 2012 2:58 pm
by dom » Fri Sep 14, 2012 2:21 pm
millerpuckette wrote:OK... Please try my opus, http://crca.ucsd.edu/~msp/tmp/mmap-sinetest.c
-- it attempts to play a sinusoid for 10 seconds by flogging the PM control
registers. There are more detailed comments in the code, but in a nutshell, the
ALSA playback (in 2012-08-16-wheezy-raspbian) somehow modulates the output
so that you hear parasitic extra tones. Playing 440 Hz. there is a noticeable parasite
around F (MIDI 41, 87 Hz.) I think my sample code shows that the hardware is capable
of better. My guess about the parasitic tone is that there's a timing glitch every 512
samples but I haven't looked carefully for it yet.


It works!
You need to play something through ALSA first (I'm guessing to set up the PWM clock). This probably means the ALSA file you play should be the same samplerate.

What would be ideal is to be able to play the same samples though ALSA and then your direct program, side by side for comparison.
Can you get your program to suport some simple file format? i.e. wav or just raw sample? Something that can also be played through ALSA.
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 5067
Joined: Wed Aug 17, 2011 7:41 pm
Location: Cambridge
by millerpuckette » Fri Sep 14, 2012 4:12 pm
dom wrote:
It works!
You need to play something through ALSA first (I'm guessing to set up the PWM clock). This probably means the ALSA file you play should be the same samplerate.

What would be ideal is to be able to play the same samples though ALSA and then your direct program, side by side for comparison.
Can you get your program to suport some simple file format? i.e. wav or just raw sample? Something that can also be played through ALSA.


Sure - grab http://crca.ucsd.edu/~msp/tmp/mmap-sinetest2.c
- makes a 5 sec tone (I got tired of listening to all 10) and also writes it
out as a floating-point WAV file named "tone5sec.wav" that can be played
through ALSA via "aplay tone5sec.wav". Beware that ALSA has a volume
control (visible via alsamixer) - which should be set to unit gain (0 dB) so that
the two programs (mmap-sinetest2 and aplay) play at the same volume. The
ALSA gain control might conceivably be applied before conversion in which case
it would affect the fidelity in a big way.

cheers
Miller
Posts: 22
Joined: Tue Sep 11, 2012 4:25 am
by dom » Fri Sep 14, 2012 4:38 pm
millerpuckette wrote:Sure - grab http://crca.ucsd.edu/~msp/tmp/mmap-sinetest2.c
- makes a 5 sec tone (I got tired of listening to all 10) and also writes it
out as a floating-point WAV file named "tone5sec.wav" that can be played
through ALSA via "aplay tone5sec.wav". Beware that ALSA has a volume
control (visible via alsamixer) - which should be set to unit gain (0 dB) so that
the two programs (mmap-sinetest2 and aplay) play at the same volume. The
ALSA gain control might conceivably be applied before conversion in which case
it would affect the fidelity in a big way.


Even better would be if your program could read in a wav/raw file.
Then you could check for the difference in speech, or music, to see how noticable the improvement is in real world cases.
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 5067
Joined: Wed Aug 17, 2011 7:41 pm
Location: Cambridge
by millerpuckette » Fri Sep 14, 2012 6:47 pm
dom wrote:
millerpuckette wrote:Sure - grab http://crca.ucsd.edu/~msp/tmp/mmap-sinetest2.c
- makes a 5 sec tone (I got tired of listening to all 10) and also writes it
out as a floating-point WAV file named "tone5sec.wav" that can be played
through ALSA via "aplay tone5sec.wav". Beware that ALSA has a volume
control (visible via alsamixer) - which should be set to unit gain (0 dB) so that
the two programs (mmap-sinetest2 and aplay) play at the same volume. The
ALSA gain control might conceivably be applied before conversion in which case
it would affect the fidelity in a big way.


Even better would be if your program could read in a wav/raw file.
Then you could check for the difference in speech, or music, to see how noticable the improvement is in real world cases.


Yep, but that will make it a much less simple program (I\d have to
call in some libraries and qho-know-what) - I'm happy to do it if you
don't mind haveing to deal with a much bigger test program..

cheers
Miller
Posts: 22
Joined: Tue Sep 11, 2012 4:25 am
by dom » Fri Sep 14, 2012 8:53 pm
millerpuckette wrote:Yep, but that will make it a much less simple program (I\d have to
call in some libraries and qho-know-what) - I'm happy to do it if you
don't mind haveing to deal with a much bigger test program..

Just support a single raw format, e.g. 16-bit stereo.
Use sox to convert wav or whatever into your raw format.
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 5067
Joined: Wed Aug 17, 2011 7:41 pm
Location: Cambridge
by millerpuckette » Sat Sep 15, 2012 4:57 am
dom wrote:Just support a single raw format, e.g. 16-bit stereo.
Use sox to convert wav or whatever into your raw format.


OK... now http://crca.ucsd.edu/~msp/tmp/mmap-sinetest3.c -- if you
give it a file name as a command line arg it reads raw floating-point 32-bit samples
from the file, otherwise generates a tone and writes its own file. I fixed it to be
easier to change the frequenct etc of the tone it generates -- you can edit the
code or throw the compiler a flag like -DTEST_FREQUENCY=660 and run.

Next I'm thinking I should look at the output of aplay to see if I can diagnose it
more confidently.

Enjoy :)
Miller
Posts: 22
Joined: Tue Sep 11, 2012 4:25 am
by MattOwnby » Sat Sep 15, 2012 3:33 pm
millerpuckette wrote:it reads raw floating-point 32-bit samples
from the file


I'm curious why you chose 32-bit float samples instead of 16-bit signed ints. I assume this choice is influenced by your evident expertise in the realm of digital audio?
Posts: 58
Joined: Thu Aug 16, 2012 7:22 pm
by millerpuckette » Sat Sep 15, 2012 6:34 pm
MattOwnby wrote:
millerpuckette wrote:it reads raw floating-point 32-bit samples
from the file


I'm curious why you chose 32-bit float samples instead of 16-bit signed ints. I assume this choice is influenced by your evident expertise in the realm of digital audio?


Well, my back-of-the-envelope calculation suggests that the PWM interface is capable of
somewhere between 15 and 18 bits if accuracy once the kinks are worked out - so a 16-bit
test file won't have enough accuracy to see how well it's working in the end.

I can confirm that at 48kHz, 'aplay' is dropping 2 samples out of every 512; am working
on uploading suitable test program and output...

cheers
Miller
Posts: 22
Joined: Tue Sep 11, 2012 4:25 am
by millerpuckette » Sat Sep 15, 2012 6:56 pm
millerpuckette wrote:
MattOwnby wrote:I'm curious why you chose 32-bit float samples instead of 16-bit signed ints. I assume this choice is influenced by your evident expertise in the realm of digital audio?


[...]

I can confirm that at 48kHz, 'aplay' is dropping 2 samples out of every 512; am working
on uploading suitable test program and output...



Here is a test program and test output that shows clearly the samples dropping playing
files through aplay.

First off, the program
http://crca.ucsd.edu/~msp/tmp/mmap-sinetest4.c
now plays 48 kHz by default and can be used to generate the tone I used by compiling
as follows:

cc -DTEST_FREQUENCY=4800 -DTEST_AMPLITUDE=0.25 -DTEST_SRATE=48000 -o mmap-sinetest4 mmap-sinetest4.c -lm

This makes a tone of period 10 samples that's easy to psychoanalyze at the output. The
file it generated (and played) is here:

http://crca.ucsd.edu/~msp/tmp/test-4800Hz-48K.wav

and then I played it (using aplay) and made an analog recording of the output of
the Pi, which is here:

http://crca.ucsd.edu/~msp/tmp/recorded- ... Hz-48K.wav

Looking at this last file in audacity, there are two samples missing at or
around sample locations 172, 682, 1192, 1702, etc. -- i.e. every 510
recorded samples correspond to 512 samples in the test file I was playing.

I assume this is happening somewhere deeper in the processor than I can
look so am hoping you can figure it out from here :)

Miller
Posts: 22
Joined: Tue Sep 11, 2012 4:25 am
by toxibunny » Sat Sep 15, 2012 7:02 pm
I love reading threads like these. Smart people who know what they're talking about...
note: I may or may not know what I'm talking about...
Posts: 1383
Joined: Thu Aug 18, 2011 9:21 pm
by dom » Sun Sep 16, 2012 9:58 am
millerpuckette wrote:I assume this is happening somewhere deeper in the processor than I can
look so am hoping you can figure it out from here :)

Thanks for the analysis. I'll see if I can find any missing samples through the GPU path.

I'd be interested to hear if you can get more effective bits coming out through additional processing.
I initially implemented a sigma-delta scheme to try to do this, that a colleague had modelled in matlab, but never got it sounding better than the non-sigma-delta version.
Not sure if there was a flaw in the algorithm, or the slew on the GPIO pins stopped the sigma-delta from working.
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 5067
Joined: Wed Aug 17, 2011 7:41 pm
Location: Cambridge
by PeterO » Sun Sep 16, 2012 12:04 pm
Interesting. I've observed something similar when playing a square wave, there is an audible "variation" which seemed to equate to the block size I was using to write the data to the alsa device.
I'll investigate further and see if it equated to this problem. However I seem to remember it was only audible (and visible on a 'scope) when using the stereo outoput, via hdmi it was OK.
PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),Aeromodelling,1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson
User avatar
Posts: 3303
Joined: Sun Jul 22, 2012 4:14 pm
by dom » Sun Sep 16, 2012 1:44 pm
This bug seems related: We play audio 0.4% fast, which ties up quite closely with 2 out of 512 samples being lost:
viewtopic.php?f=38&t=17127&p=174655#p174655

The other bug report is quite useful as it provides a test program that can identify the loss of samples through timing.

I've had a look and followed a block of samples through alsa, through audioplus and they get all the way to the dma to pwm perpheral intact.
Been through the PWM and DMA specs to see what could cause it, and found the DMAC register in PWM peripheral. It is set to trigger DREQ when the threshold is 7 somethings (not a great spec...)
So I've been playing with that threshold, and it seems lowering it to 3 makes the 0.4% speed loss disappear. Increasing it can make us lose many more samples (e.g. 50%).

My guess is that when the threshold is too high, the DMA can overfill the PWM fifo, and so lose samples. 2 out of 512 seems a surprisingly low and consistent number. I'll see if any hardware people can explain it Monday.

The important thing is, does the adjustment improve things. To my unmusical ears, then yes, I think it sounds better. And the 0.4% speed difference has gone.
I'd be interested if you can test the updated firmware (available through rpi-update) and comment on the change.
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 5067
Joined: Wed Aug 17, 2011 7:41 pm
Location: Cambridge
by PeterO » Sun Sep 16, 2012 2:38 pm
rpi-update just updated to 3.2.27+ #151 dated Fri Sep 14 17:00:51
Where is this "latest" version then ?
PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),Aeromodelling,1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson
User avatar
Posts: 3303
Joined: Sun Jul 22, 2012 4:14 pm
by dom » Sun Sep 16, 2012 2:58 pm
PeterO wrote:rpi-update just updated to 3.2.27+ #151 dated Fri Sep 14 17:00:51
Where is this "latest" version then ?

The kernel is unchanged. Try
Code: Select all
/opt/vc/bin/vcgencmd version

to identify the GPU firmware version.
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 5067
Joined: Wed Aug 17, 2011 7:41 pm
Location: Cambridge
by MattOwnby » Sun Sep 16, 2012 3:05 pm
dom wrote:The important thing is, does the adjustment improve things. To my unmusical ears, then yes, I think it sounds better. And the 0.4% speed difference has gone.
I'd be interested if you can test the updated firmware (available through rpi-update) and comment on the change.


Excellent work!! I will test this as soon as I can. Unfortunately, I will not have physical access to my Raspberry Pi again for about 7 days (!!) so I cannot test until then. Hopefully some other people in the forum can test sooner than that because I am very curious to see the results.
Posts: 58
Joined: Thu Aug 16, 2012 7:22 pm
by PeterO » Sun Sep 16, 2012 3:06 pm
Ah, I hadn't realised the firmware could change without update to the kernel release number.
Anyway it seems I have version 337302

Ok, just tried it and it sounds to have made an improvement :D but I'll need to check waeforms on my 'scope and look at the waveform to be 100% sure. ('scope is connected to another project at the moment so that will have to wait a while).
PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),Aeromodelling,1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson
User avatar
Posts: 3303
Joined: Sun Jul 22, 2012 4:14 pm
by millerpuckette » Sun Sep 16, 2012 5:34 pm
dom wrote:This bug seems related: We play audio 0.4% fast, which ties up quite closely with 2 out of 512 samples being lost:
viewtopic.php?f=38&t=17127&p=174655#p174655

The other bug report is quite useful as it provides a test program that can identify the loss of samples through timing.

I've had a look and followed a block of samples through alsa, through audioplus and they get all the way to the dma to pwm perpheral intact.
Been through the PWM and DMA specs to see what could cause it, and found the DMAC register in PWM peripheral. It is set to trigger DREQ when the threshold is 7 somethings (not a great spec...)
So I've been playing with that threshold, and it seems lowering it to 3 makes the 0.4% speed loss disappear. Increasing it can make us lose many more samples (e.g. 50%).

My guess is that when the threshold is too high, the DMA can overfill the PWM fifo, and so lose samples. 2 out of 512 seems a surprisingly low and consistent number. I'll see if any hardware people can explain it Monday.

The important thing is, does the adjustment improve things. To my unmusical ears, then yes, I think it sounds better. And the 0.4% speed difference has gone.
I'd be interested if you can test the updated firmware (available through rpi-update) and comment on the change.


SUCCESS!!! I installed the firmware update this morning and the problem is fixed over here.
I had to figure out rpi-update so for others reading this thread here's a blow-by-blow account:

To check firmware version:
# /opt/vc/bin/vcgencmd version
Aug 25 2012 01:12:00
Copyright (c) 2012 Broadcom
version 333349 (release)

To get rpi-update tool, get tool by Hexxeh on https://github.com/Hexxeh/rpi-update
(very easy-to-follow instructions) - then:

# rpi-update
(takes 5 minutes and asks for a reboot. I rebot and verify:)
# /opt/vc/bin/vcgencmd version
Sep 16 2012 14:37:55
Copyright (c) 2012 Broadcom
version 337302 (release)

And thereafter Pd, aplay, etc give much much cleaner audio.

More technically: I see also that the PWM status register (which was
riding at 0x634 before) now is at 0x630, i.e. there's no longer a write
error bit set (although the two "GAP" bits 0x30 are constantly getting
set even when I don't hear any audio errors; I don't know if this is worth
worrying about or not.)

Also, I saw in an earlier thread that the PWM was only able to run up to
2048 times the sample rate; but looking at the registers I see the PWM
only running at 1024 oversampling (PWM0_RANGE and PWM1_RANGE
are at 0x400 = 1024). (Of course, at sample rates higher than
(100 mHz)/2048 = 48829 this would have to go back down. It would be cool
to be able to play at rates around 1 or 2 mHz for those of us interested in
synthesizing radio in the AM band -- oops I didn't say that did I -- hope the FCC
isn't listening). Anyhow, changing this to 2048 would immediately improve the
signal/noise ratio by 6 dB which will be a very audible improvement.

Beyond that, (and regardless of whether it turns out to be possible to get that
extra bit), I'll start experimenting with improving the PWM algorithm - I now think
my earlier estimate of getting 15-18 bits of SNR was wildly overoptimistic but
still think I can get an extra bit or 3.

thanks for all and stay tuned...
Miller
Posts: 22
Joined: Tue Sep 11, 2012 4:25 am
by MattOwnby » Sun Sep 16, 2012 5:35 pm
While I won't have physical access to my Pi for 7 days, I do have remote access.

I was able to re-run my test program at 48khz and the numbers are much closer now:

Code: Select all
Total elapsed time: 7794.190000
Total frames processed: 374133760
Effective audio frequency: 48001.621721


This is more in line with what I would expect to see: not exactly 48000 but close enough for every day use.
Posts: 58
Joined: Thu Aug 16, 2012 7:22 pm
by dom » Sun Sep 16, 2012 6:17 pm
Firstly, thanks to millerpuckette and MattOwnby for the high quality bug reporting that gave me the pointers needed to find this.

millerpuckette wrote:And thereafter Pd, aplay, etc give much much cleaner audio.

Excellent.

millerpuckette wrote:More technically: I see also that the PWM status register (which was
riding at 0x634 before) now is at 0x630, i.e. there's no longer a write
error bit set (although the two "GAP" bits 0x30 are constantly getting
set even when I don't hear any audio errors; I don't know if this is worth
worrying about or not.)

Yes, I saw the same when debugging. I'm guessing the GAP bit is set when I switch from "ramping" in non-DMA mode, to enabling the dma,
and doesn't happen when we are up and running. I guess you can try clearing the bit (write 1 to it) whilst audio is playing and see if it reappears.

millerpuckette wrote:Also, I saw in an earlier thread that the PWM was only able to run up to
2048 times the sample rate; but looking at the registers I see the PWM
only running at 1024 oversampling (PWM0_RANGE and PWM1_RANGE
are at 0x400 = 1024). (Of course, at sample rates higher than
(100 mHz)/2048 = 48829 this would have to go back down. It would be cool
to be able to play at rates around 1 or 2 mHz for those of us interested in
synthesizing radio in the AM band -- oops I didn't say that did I -- hope the FCC
isn't listening). Anyhow, changing this to 2048 would immediately improve the
signal/noise ratio by 6 dB which will be a very audible improvement.


Yes, I'm aware that there is a factor of two/one bit that is missing. You can run:
Code: Select all
/opt/vc/bin/vcgencmd measure_clock pwm
frequency(25)=98304000

which is right. But if I set PWM_RANGE to 0x800 as I predicted I could, the audio comes out at half speed.
Can you run with 0x800?

millerpuckette wrote:Beyond that, (and regardless of whether it turns out to be possible to get that
extra bit), I'll start experimenting with improving the PWM algorithm - I now think
my earlier estimate of getting 15-18 bits of SNR was wildly overoptimistic but
still think I can get an extra bit or 3.

Please do.

MattOwnby wrote:I was able to re-run my test program at 48khz and the numbers are much closer now:
Code: Select all
Total elapsed time: 7794.190000
Total frames processed: 374133760
Effective audio frequency: 48001.621721

This is more in line with what I would expect to see: not exactly 48000 but close enough for every day use.

Excellent.
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 5067
Joined: Wed Aug 17, 2011 7:41 pm
Location: Cambridge
by millerpuckette » Sun Sep 16, 2012 6:49 pm
dom wrote:
millerpuckette wrote:More technically: I see also that the PWM status register (which was
riding at 0x634 before) now is at 0x630, i.e. there's no longer a write
error bit set (although the two "GAP" bits 0x30 are constantly getting
set even when I don't hear any audio errors; I don't know if this is worth
worrying about or not.)

Yes, I saw the same when debugging. I'm guessing the GAP bit is set when I switch from "ramping" in non-DMA mode, to enabling the dma,
and doesn't happen when we are up and running. I guess you can try clearing the bit (write 1 to it) whilst audio is playing and see if it reappears.


I try clearing the bits; they quickly (< 1/10 sec?) get set again. Using my little cmd/status
peek/poke util (I'll upload if you'd like it :)

# ./register-poker
command 2525, status 630
# ./register-poker 1 34 && ./register-poker
command 2525, status 630 (before poking)
command 2525, status 600 (immediately after)
command 2525, status 630 (next run of register-poker ~ 1/10 sec later I presume)
dom wrote:
millerpuckette wrote: [...] Anyhow, changing this to 2048 would immediately improve the
signal/noise ratio by 6 dB which will be a very audible improvement.


Yes, I'm aware that there is a factor of two/one bit that is missing. You can run:
Code: Select all
/opt/vc/bin/vcgencmd measure_clock pwm
frequency(25)=98304000

which is right. But if I set PWM_RANGE to 0x800 as I predicted I could, the audio comes out at half speed.
Can you run with 0x800?


Yeah I get the same 98304000. I also tried 0x800 and got 1/2 speed. Something's
fishy here.

I wonder if it has anything to do with the REPEATFF bits being set? The manual
said to leave them unset when in WM mode - I'll try a few permutations and report
back.

cheers
M
Posts: 22
Joined: Tue Sep 11, 2012 4:25 am