LADSPA plugin programming for Linux audio crossovers

Now that I have some time again after completing work on some other audio projects I was able to do some more testing of the delay variation (call it jitter if you must) when streaming RTSP to two separate Raspberry Pi 2 "computers" running my LADSPA plugins under ecasound.

For this testing I wanted to eliminate the WiFi part of the streaming route. I brought both Pis up to my office where our router is located and plugged both in using their ethernet port (hardwired connection). The computer where I was doing the testing is also now the streaming server, and it is also connected using an ethernet cable to the same router. Since I was previously using WiFi in my garage, I was concerned that the WiFi signal strength was low (I sometimes get dropouts there when streaming audio). This test rules out that problem.

I set up as before and ran the group delay measurement several times in a row. I found that the maximum deviation (max minus min group delay) for a sample size of six measurements was 0.3 milliseconds.

This is MUCH less variation than the last test in the garage and would be within the limits for those who are concerned with the apparent stereo image shifting around significantly.

These test were run after the Pi had been powered up only about 5 minutes.

I will perform additional runs during the rest of the day to see whether the performance remains the same or not, and will report the results here.
 
UPDATE:

I monitored what was going on for about 30 minutes on and off, then I went shopping and came back again after about 2 hours had elapsed to see if things had settled down.

What I found was that the two Pis continuously and linearly drift out of sync by about 0.1 milliseconds per minute. The amount of drift seems to increase up to something like 20-30 milliseconds before it resets again. This is exactly what I observed and commented on in my last post, I just had not realized exactly what was going on at the time. It's still much better than when I was operating at the edge of my WiFi coverage.

A slow drift like this would not be noticiable, but it's not desirable either.

I'm now thinking of setting up one Pi as a NTP timeserver and the other as an NTP time client. This might keep them more tightly sync'd... it's worth a try.
 
More juicy details...

I have turned off the ecasound processing for now in case that is introducing some jitter. I have also tuned up my NTP settings, replacing the default servers with the correct ones for my part of the world and adjusting polling times, etc. Both Pi clients are using NTP as an ntp client (I have not set one up as a time server as I mentioned before).

I am currently getting some of the same behavior in that the time difference does still drift slightly by around 0.1 millisecond per minute, however, it seems that the time differences trend to small values of a couple of milliseconds (e.g. 4,3,2,1 msec) or less and the changes for the most part move the time difference towards zero, although there are some jumps up now and then as clocks are adjusted. I am not yet sure if this will become an asymptotic change, e.g. that the rate of change will slow down and both Pis will converge on the exact same time base with increasing stability. That is how is it supposed to work under NTP, and I have been rebooting a couple of times, so that indeed may turn out to be the case.

At least now, with ecasound off and a hardwired ethernet connection between server and clients it seems that the delay jitter is quite small and likely trending towards values of only a couple milliseconds or less.

I will let the Pis run for a few hours and then make some more measurements to see what is happening at that time. I'll report the results back here.
 
Last edited:
Latest testing and measurement results:

After what seemed to be some encouraging results yesterday (initially at least) that I posted about above, I have a more complete picture of the timing errors between Pis. I left my Pis running overnight, with NTP/ntpd running to supposedly sync the clocks to time servers. I was hoping that the NTP time corrections would improve things after several hours time. I read about NTP and it is basically like a software PLL. It has some overshoot in the response (e.g. controller gain is a little on the high side) which produces overshoot and oscillation in the error between local time and "real time" but it should eventually settle down and give errors on the order of a couple of milliseconds (based on some measurements I found on the web). Well that is how it is supposed to work in theory. What I am observing, and it may not just be due to NTP behavior, is time "jumps". I will describe that below.

What seems to be happening is that the measured delay between two Pis continuously drifts by about 0.1 milliseconds per minute. Periodically, say about every 10-20 minutes, there is a discontinuous "jump" in the delay by a few tens of milliseconds, e.g. 20-40msec. For instance, I observed first a drift from around 4msec down to 2msec. Then the offset jumps to -25msec and drifts again for while. Then the offset jumps to +35msec and drifts around for awhile. Then the offset jumps to 20msec and drifts, etc. Always (yesterday and today) the drift is the exact same 0.1msec per minute.

If we focus on NTP for a minute, it doesn't seem to be working as advertised. The action of the ntpd is designed to ferret out the clock rate and then adjust for that. Adjustments can be made through several kernel processes, and can be both discrete jumps or slight adjustments to the rate factor for the clock. But the Pi uses a "fake" clock done in software. This might not be amenable to the types of adjustments that NTP is designed to make. So perhaps a hardware clock might be better after all - I have two DS3231 based modules on order. After I have installed and configured them in software I will do this testing again. In any case, even though the value in the ntp.drift file is changing, I don't see evidence of that kind of correction to the clocks. All I see are discrete jumps. Perhaps it's the fake clock, or perhaps the rate adjustment is not included as part of Raspbian. I can only guess at this point.

What else could be at play here? Well we are using RTSP and some other software to process the stream along the way. It could be that those introduce some timing jitter. Unfortunately I don't know of a way to directly compare the time on two systems with microsecond resolution or I would just do that to see how the time is drifting. Instead all I can do is send an audio pulse through the system(s) and then compare the arrival time. What is happening along the way is a bit of a black box.

I will keep working on this. If timing can't be at least a little better controlled between two Pis then a dual streaming setup is not really going to be up to a high-fidelity type of implementation.
 
Aha, I finally have a way to see what is happening with the time on each Pi individually without having to do any audio measurements. I can collect statistics using NTP's built in logging capabilities and then plot the data to see what is going on. Explanation about NTP statistics and example plots (comparing Radio and GPS based references) can be found on this page:
Troubleshooting

This will help me figure out whether the Pis software clock plus NTP is to blame for the timing errors I am seeing or, if not, whether RTSP might be to blame.
 
Last edited:
Thanks for sharing the progress - enjoying the read.

When looking around, I also came accross Radclock, which claims "similar or usually better performance than ntpd and ptpd under many different conditions
- much higher robustness against network congestion, change of routes, server errors, disconnections". They have some research papers on the documentation page: SyncLab.org.

Here's some of their thoughs on the raspberry: SyncLab.org

An alternative more simple test protocol showing similar findings as you: How accurately can the Raspberry Pi keep time? Remi Bergsma's blog
 
This is an interesting figure from the links above:

http://remibergsma.files.wordpress.com/2013/05/timedrift_difference_raspberrypi_1_and_2.png?w=580

It shows about 0.07 ms drift per minute (0.2s in 50 hours) which gets pretty close to 0.1ms/min measured by Charlie. IMO this is precision of the Pi's internal oscillator which times everything in Pi.

I wish we could get more from those finnish research guys who implemented the time-synchronization for RTSP down to single microsecs.
 
Awesome project

I think this is a great and very promising project. I want to help. I have two cheap Ebay 5.1 USB sound cards on order ($8.99 ea including shipping - can't get much cheaper than that!). I'm getting a couple of Pi2 as well.

I probably won't be much help with crossover guts, that's over my head for now at least. I think I can contribute on the higher level Linux stuff, maybe building and optimizing OS images for testing.

@CharlieLaub, would you mind if I collated information from this thread and elsewhere into a wiki page here? Or do you have a documentation site already?
 
I think this is a great and very promising project. I want to help. I have two cheap Ebay 5.1 USB sound cards on order ($8.99 ea including shipping - can't get much cheaper than that!). I'm getting a couple of Pi2 as well.

I probably won't be much help with crossover guts, that's over my head for now at least. I think I can contribute on the higher level Linux stuff, maybe building and optimizing OS images for testing.

@CharlieLaub, would you mind if I collated information from this thread and elsewhere into a wiki page here? Or do you have a documentation site already?

Sam - if you want to build a WIKI about this, here or elsewhere, please be my guest. That would be a great resource.

I'm not sure what you have in mind when you talk about OS images and higher level Linux "stuff". Can you expand on that? I am currently using only standard stable release OS and software, all freeware.
 
UPDATE on client synchronization:

I replaced the Pis with a pair of identical small form factor computers that I am testing out. These are running Ubuntu 15.04. I configured them as NTP clients, sync'd up with some local Stratum 1 time servers, and let them sync up for several hours. I have also enabled the W32Time NTP service on my Windows machine that streams RTSP to the two playback clients. All three systems are connected using hardware (ethernet cable).

I was hoping that I would get better client-to-client synchronization with this setup. After monitoring the delay once per minute (manually!) over a time period of several hours I found that:
  • The initial sync was always relatively good, around 4-5 msec, often trending towards zero.
  • The playback delay between computers constantly drifted by about 0.4 msec per minute. This was independent of when the measurement was taken.
  • The drift would continue for quite some time, linearly changing the playback delay, and then a relatively large "jump" or shift in delay would occur. This typically came in the form of the "ahead" client changing to the "behind" client but the delay magnitude remaining about the same
  • The typical long term delay is on the order of 15-25 milliseconds, sometimes less.
The behavior described above is similar to what I observed with the Raspberry Pis, except that the long term delay could be up to 50 milliseconds and the jumps occurred more frequently.

I will do some more testing today using the mini computers. I hope to do some listening tests in the near future and will post my subjective evaluation about the effect of the delay on the sound as a follow up.
 
UPDATE on client synchronization:

I replaced the Pis with a pair of identical small form factor computers that I am testing out. These are running Ubuntu 15.04. I configured them as NTP clients, sync'd up with some local Stratum 1 time servers, and let them sync up for several hours. I have also enabled the W32Time NTP service on my Windows machine that streams RTSP to the two playback clients. All three systems are connected using hardware (ethernet cable).

I was hoping that I would get better client-to-client synchronization with this setup. After monitoring the delay once per minute (manually!) over a time period of several hours I found that:
  • The initial sync was always relatively good, around 4-5 msec, often trending towards zero.
  • The playback delay between computers constantly drifted by about 0.4 msec per minute. This was independent of when the measurement was taken.
  • The drift would continue for quite some time, linearly changing the playback delay, and then a relatively large "jump" or shift in delay would occur. This typically came in the form of the "ahead" client changing to the "behind" client but the delay magnitude remaining about the same
  • The typical long term delay is on the order of 15-25 milliseconds, sometimes less.
The behavior described above is similar to what I observed with the Raspberry Pis, except that the long term delay could be up to 50 milliseconds and the jumps occurred more frequently.

I will do some more testing today using the mini computers. I hope to do some listening tests in the near future and will post my subjective evaluation about the effect of the delay on the sound as a follow up.

raspberry share the same bad bus for all its external communication, and it could be the same with other micro PC.
Linux share its kernel for all tasks and priorities.
It is a mega soup!

Good improvement could be code optimisation, and dedicated kernel, that mean without linux (bare)

Other way could be a dedicated DSP processor.
the new STM32F7 looks very interesting as well for people who can set up a professionnal development environment and produce in C language, DSP algorithms (<100 people in the world).
 
Hi Charlie,

Does the configuration with 2 small form factor clients use wifi or LAN?

Is there any hardware time stamping, sort of like precision time protocol?

Regards,

Rob

Everything was connected to the LAN using ethernet cable.

I am running NTP that supposedly syncs time to within a couple of milliseconds on all three machines. This is about as good as it gets unless you establish a time base via GPS signal or something, and then you can get accuracy into the microseconds. That would be overkill here.

The RTSP protocol sends a timestamp along with the packets so that playback can be synchronized. This actually works pretty well. I have tried using RTP and UDP streaming and the result is pretty bad actually.

Since I can not see inside the software to know exactly what it is doing (lack of documentation, etc) I could only guess why there is a drift at this point.

It's certainly possible to write code to do all of this with better synchronization - I have found some descriptions of projects on the web that were based on NTP synchronized server and clients and pushing data using a small HTTP server. I would love to start up a project like this with some Silicon Valley people (anyone listening?). This has potential commercial applications, too. I think it's a doable project, and it would be fun if a small group of programmers cum audio geeks got together and built it. I would be a good idea to talk to some industry people to make sure that the wheel was not being reinvented...

For now my hope (and assumption at this point) is that the current level of synchronization would be fine for "normal" music listening, but not critical audiophile level stuff. For that I would just stick to one machine to supply the audio channels to both speakers - that is the plan for the system that I will be bringing to Burning Amp in OCT, for example, using one of the small computers I mentioned (has onboard 7.1 audio). But I will bring another system that uses two Pis, one for each speaker, just to demo and talk about with folks who stop by.
 
Last edited:
I've moved on to doing some listening tests, with the occasional check of delay now and then. What I have found that even when the delay is over 20 msec between left and right channels, I don't really notice it even in headphones on music signals. This is likely why I didn't notice the delay in my early trials either. It seems that I will be able to pull off a 2-Pi wireless streaming loudspeaker after all. I plan to demo that setup at Burning Amp with some speakers or another and an outboard amp. Hopefully all will go well on the host's wireless... come on by and find out.
 
Ah, funny footnote here...

I am now not so confident in the precision of my delay measurements. I just noticed that when the impulse is just about at 0msec when comparing right to left channel, when I then reverse and compare left to right channel the delay is 12 msec. I cant' tell if this means that there is a 12 msec offset, or 6 msec on each side, but I now no longer trust the numbers I was getting before. On the bright side it likely means that the actual delay that I mentioned in earlier posts are likely lower than I was reporting at the time.

I will try to look for another way to reliably measure the delay between channels...

In the meantime, I'm continuing the listening tests and the sound is great. No real notable "delay" in the audio, etc.

On a brighter measurement note, I did manage to measure the distortion of these little mini computers with built in ALC892 audio and it's pretty low, around 0.02%, which is about the resolution of my measurement system so it could be even lower. The measurement was taken by streaming audio as MP3 quality level 0 at 48kHz to the computer and measuring the distortion in the analog audio out signal. Nice.
 
Last edited:
LOL. A couple of questions/comments:

1. Were you able to hear audible delays with the RP2's as clients?

2. Could you summarize the division of processing functions between server and client?

3. TI has developed a series of wifi chips, the WL18x series, which are designed to work with the Beaglebone processor. This solution set appears to include a PTP, open source code, and a cape for prototyping. The cape doesn't appear to be in stock anywhere, but the schematic, BOM, and board layout are available. Very intriguing. This is probably a lot of work to get this working on multiple BBB's, and a ton to adapt to RP2. Anyway, while all of this is really interesting, I can't help but wonder if a couple of Squeezeboxes and brutefir might be a faster/cheaper way to get there.

Regards,

Rob
 
LOL. A couple of questions/comments:

1. Were you able to hear audible delays with the RP2's as clients?
Have not tested yet. I just finished installing DS1307 RTCs on both Pis and have restarted. I will wait several (12+) hours to let NTP settle down again. Then I will test the delay again using the Pis (likely tomorrow) and do some listening tests.

2. Could you summarize the division of processing functions between server and client?
Lets see...
SERVER:
On the server there are four key processes:
1. player - queue up and play tunes. Output is connected to #2:
2. "loopback". In Linux I would use an ALSA loopback device. Under windows I am using "VB-Cable", available here:
VB-Audio Virtual Apps
3. FFmpeg - Input comes from #2. I use this to repackage the audio stream using mp3lame and stream it to a localhost port as rtp or udp
4. Streaming server - this re-streams the output from FFmpeg on my local network using RTSP multicast.

CLIENT:
On the (linux, e.g. R-Pi) client I do the following:
1. player receives the RTSP stream. Output is to an ALSA loopback device
2. ecasound is used to process the audio stream into channels and apply filters, e.g. function as a software DSP crossover. Output from ecasound is directed, via ALSA, to DAC (built in sound on some platforms, or one or more USB DACs on R-Pi)
All of the client stuff can be done with a headless setup using scripts that start up the player on boot up and wait for a stream to arrive.

3. TI has developed a series of wifi chips, the WL18x series, which are designed to work with the Beaglebone processor. This solution set appears to include a PTP, open source code, and a cape for prototyping. The cape doesn't appear to be in stock anywhere, but the schematic, BOM, and board layout are available. Very intriguing. This is probably a lot of work to get this working on multiple BBB's, and a ton to adapt to RP2. Anyway, while all of this is really interesting, I can't help but wonder if a couple of Squeezeboxes and brutefir might be a faster/cheaper way to get there.

Regards,

Rob

I saw that TI cape on the web. I does sound very interesting, but as far as I know it's only available as a design, not an assembled and tested board. It's also moving towards more dedicated and specific hardware, and it will cost something. With my current approach you can use whatever hardware you want and all software (that I am using at least) is open source freeware.

There are lots of different ways that this kind of approach could be replicated. I am certainly not saying that this is the only way, or even the best way. I am just posting my experiences. People have suggested using JRiver, bruteFIR, BBB with the crossover done all in ALSA, etc. and all of those are valid approaches, too.

I see the Pi as a low-power, inexpensive yet capable platform for embedded crossovers that can also provide functionality that is not available in hardware DSP units (streaming client, using GPIO pins to control external equipment like power amplifiers). As hardware evolves (small computing units and inexpensive DACs) I can move on/up in terms of performance using exactly the same approach as I do now, and that kind of flexibility is very attractive to me.
 
Since installing the RTC hardware and software, and then restarting NTP, it's been about 9 hours. I retested the delay between one Pi and the other and initially measured 5.35 msec comparing left against right and 7.35 msec comparing right against left. It's the same as before, low. That 12 msec difference still separates the two...

Moved on to some listening with headphones and the sound is great. I don't perceive delay or other artifacts. Streaming is working perfectly.

Adding the RTC may have improved the performance but its too soon to tell for sure. Both Pis should converge on the same timebase within a millisecond or two, as long as I leave them running and connected to the internet for NTP.
 
IMO we should analyze what the time synchronization actually synchronizes. Even if the time is synchronized to picosecs, it will not help if it is not used for synchronizing the frames being played but some moment in the player, far away from the actual playback time.

Alsa-lib offers snd_pcm_delay call which should provide the time (in frames) how long it will take for a frame now sent to the alsa-lib device to actually reach the analog output. Some drivers report correctly, some don't.

Now the RTSP playback app must take this information into account, to be able to work correctly. VLC alsa output plugin reads this information, the upper layers seem to use it (from what I could learn from opengrokked vlc source tree). There seem to be some debug messages in the corresponding code path, perhaps enabling them in vlc should five us more information VLC secrets: Logging and how it helps with bad files

Nevertheless, if the important snd_pcm_delay information is used properly in VLC, it is still a question what relevance it has in the aloop setup. IMO the actual delay is way different and pretty unpredictable since it involves another proccess (one process writes into aloop, another reads from it), the LADSPA filtering of the initial sound frames in ecasound can (and very likely is) be interrupted by another process (introducing thus further random delay). Thus IMO the delay of the first sound frame reaching the soundcard (which is what should be fed back to the overall synchronization) is totally unpredictable and much larger than what is reported by snd_pcm_delay (for the actual playback chain which is trivial) to the upper layers in vlc.

I do not know if the alsa ladspa plugin reports its part of the delay correctly. If it does, perhaps the single process chain as used by Francolargo reports a correct snd_pcm_delay value and the synchronization could work as envisioned by the RTSP scheme designers. Maybe 🙂
 
Last edited: