Go Back   Home > Forums > >
Home Forums Rules Articles diyAudio Store Blogs Gallery Wiki Register Donations FAQ Calendar Search Today's Posts Mark Forums Read

PC Based Computer music servers, crossovers, and equalization

A bash-script-based streaming audio system client controller for gstreamer
A bash-script-based streaming audio system client controller for gstreamer
Please consider donating to help us continue to serve you.

Ads on/off / Custom Title / More PMs / More album space / Advanced printing & mass image saving
Reply
 
Thread Tools Search this Thread
Old 6th February 2018, 10:50 PM   #71
CharlieLaub is offline CharlieLaub  United States
diyAudio Member
 
Join Date: Mar 2007
Location: Michigan
AND THE GSTREAMER RABBIT HOLE GETS DEEPER!!!

So, just when I thought I had everything working I did some multi-channel testing. By multichannel I mean more than 2 channels (2=stereo). That's when the wheels started to fall off...

I have been using my computer's onboard 7.1 (e.g. 8 output channels) audio to test gstreamer pipelines outside of GSASysCon. It turns out that with 2 channel stereo you get a "free pass" so to speak. Things just work as expected - perhaps stereo is a default case in gstreamer? When I increased the number of channels to 4, or 5, or 8 things would either break or would mixdown to stereo and those stereo channels were then duplicated into the other output channels. Hmmm... that's not right!

After a lot of Googling and reading of gstreamer source code and documentation, I started learning how channel-masks can be used to place channels correctly. Thanks to the skeleton of documentation available for gstreamer it has been a bit of a learning curve but now I seem to have at least gotten 8 channels working properly and am able to put the output into the desired channels. I need to take what I learned and update some of the code that I thought was already finished, so it is a bit of one-step-forward-two-steps-back.

At the same time I have been experimenting with LADSPA using my ACDf plugin and thankfully that is working as expected.

Looking Ahead...
I will continue to code, debug, and test everything related to the channel bitmasks. Up to 8 channels seems relatively well defined, however, I have an audio interface with 10 output channels and I wonder what channels 9 and 10 are supposed to be? Gstreamer defines 28 different channel types, so there are still lots of possibilties...

To allow for flexibility and future reconfiguration I will probably make it possible for users to provide channel masks. In this way different types of hardware can be accommodated. I can code up some internal defaults so the user does not need to provide the channel masks when their hardware obeys the "normal" channel assignments.

In any case, this is more or less a bump in the road and I am still confident that all of the new features will be implemented in the near future as time permits me to work on the code.
__________________
Visit my Audio Web Page <<--CLICK TO LEARN MORE-->> Get my LADSPA plugins
  Reply With Quote
Old 12th February 2018, 05:33 PM   #72
CharlieLaub is offline CharlieLaub  United States
diyAudio Member
 
Join Date: Mar 2007
Location: Michigan
UPDATE:

Still chipping away at the coding tasks here. I have been able to get more things figured out and working in bits a pieces by directly writing and running gstreamer code. I am doing lots of "planning" of how to implement them in the main program, which builds the gstreamer pipelines on demand. Lots to do yet, but still looking promising.
__________________
Visit my Audio Web Page <<--CLICK TO LEARN MORE-->> Get my LADSPA plugins
  Reply With Quote
Old 14th February 2018, 04:18 PM   #73
CharlieLaub is offline CharlieLaub  United States
diyAudio Member
 
Join Date: Mar 2007
Location: Michigan
It's alive! I'm doing some listening streaming to the localhost while I shake out the system.

I have been testing various clock management modes. Controlling the source of the clock for the system, from end to end, is one interesting new capability of the code. This should allow the user to deploy multiple DACs (e.g. two or more stereo DACs) and synchronize playback across them.

I still need to confirm that the LADSPA plugin handling is working as expected.
__________________
Visit my Audio Web Page <<--CLICK TO LEARN MORE-->> Get my LADSPA plugins
  Reply With Quote
Old 15th February 2018, 04:57 PM   #74
CharlieLaub is offline CharlieLaub  United States
diyAudio Member
 
Join Date: Mar 2007
Location: Michigan
Yesterday I tested out a system under Gstreamer 1.4 (a rather old version!) using my ACDf LADSPA plugin to create a simple crossover system between a small monitor speaker and mono subwoofer. Once I had it figured out it all went pretty well. I created a stream, of left, right, and summed left and right channels. Using the mixing equation formalism, this is "0 1 0+1". These three channels are then streamed to the client, where I do the DSP filtering. The output is split between two stereo DACs. Everything stays nicely synchronized without glitches. I am still using NTP to synchronize all the computers on my LAN, so I can use GstSystemClock on each machine.

On the client I came up with a formalism to describe how the input should connect to LADSPA plugins and to output channels. I do this via:
ROUTE=A,B,C,D
where
A=index of an input channel
B=index of an output channel
C=index of a DAC or sink
D=channel mask
Each ROUTE describes how to connect a single channel, like in a patchbay. As an example, in my system I have three input channel (channels 0,1 and 2) and each DAC has two output channels, e.g. DAC0_channel0, DAC0_channel1, DAC1_channel0, and DAC1_channel1. So the route descriptions are:
ROUTE=0,0,0,0 -->routes input ch 0 to DAC 0, ch 0
ROUTE=1,1,0,1 -->routes input ch 1 to DAC 0, ch 1
ROUTE=2,0,1,0 -->routes input ch 2 to DAC 1, ch 0
ROUTE=2,1,1,1 -->routes input ch 2 to DAC 1, ch 1

I won't get into the channel masks here.

Now let's say we want to apply some LADSPA filters to these routes. All you need to do is add some gstreamer LADSPA elements after each ROUTE statement and the filters will automatically be inlined into the pipeline for that route. To make things readable, you can declare each element on a separate line and they will all be joined with gstreamer's exclamation point mark behind the scenes.

Gstreamer automatically collects all the existing LADSPA plugins that have been installed on the operating system and transforms them into the Gstreamer version, giving them a compound name. For instance, my plugin is called ACDf. Under gstreamer the name is "ladspa-acdf-so-acdf". So, for example if I want a 100Hz second order Butterworth high pass filter on the route for input channel 0 to output channel 0 on DAC 0 I write:
ROUTE=0,0,0,0
ladspa-acdf-so-acdf type=22 fp=100 qp=0.707
ROUTE=...


A 4th order Linkwitz-Riley filter - this is just two identical Butterworth filters in series. To use a 100Hz LR4 the description becomes:
ROUTE=0,0,0,0
ladspa-acdf-so-acdf type=22 fp=100 qp=0.707
ladspa-acdf-so-acdf type=22 fp=100 qp=0.707
ROUTE=...

You can add as many LADSPA filters as you would like, since they are computationally very lightweight.

Since this seems to be working well so far I am thinking about how I can improve the crossover functionality and flexibility.
__________________
Visit my Audio Web Page <<--CLICK TO LEARN MORE-->> Get my LADSPA plugins
  Reply With Quote
Old 16th February 2018, 01:31 AM   #75
CharlieLaub is offline CharlieLaub  United States
diyAudio Member
 
Join Date: Mar 2007
Location: Michigan
I have been thinking about how to expand on my "ROUTE" nomenclature. What I would really like to do is include filters that could then feed multiple downstream channels. This is often done in loudspeaker crossovers, e.g. the "PRE" block in the following diagram:
.
Click the image to open in full size.
There is a single channel entering at "IN". It passes thru two filters within PRE and then is split (or teed) into two new channels WOOFER and TWEETER where a couple of other filters are applied.

Under my existing code the ROUTEs can only specify an input channel as their source, so any filters in the "PRE" block would need to be duplicated in all ROUTEs that use that channel as input. It's workable, but a bit cumbersome.

Instead I could borrow an idea from ecasound: the loop. In ecasound's LOOP device you can output to it, and then use it as input for as many channels as you would like. In gstreamer this would be a TEE element. I could implement the very same thing as shown in the figure above, like this:
Code:
TEE=0,A
  pre filter 1
  pre filter 2
ROUTE=A,0,0,0
  woofer filter 1
  woofer filter 2
ROUTE=A,1,0,1
  tweeter filter 1
  tweeter filter 2
  tweeter filter 3
ROUTE=END
Let's step through the instructions, above.
TEE=0,A says to use input channel 0 as the source for a tee called "A". So here we are sending input channel 0 to "A". The next two lines describe filters that we want to apply to the audio produced by A.
ROUTE=A,0,0,0 says to take audio from "A" and send it to channel 0 of DAC 0. The next two lines are the filters for this route, for the woofer.
ROUTE=A,1,0,1 says to take audio from "A" and send it to channel 1 of DAC 0. The next three lines are the filters for this route, for the tweeter.
ROUTE=END says that the declaration for this route is completed.

This would essentially duplicate the functionality of ecasound's LOOP, and would allow for a branching structure like what is shown in the figure. It's often used in loudspeaker crossover work, where the PRE filters are system-wide, and the woofer and tweeter filters are specific to that driver. PRE filters are often EQ, and it is useful to apply them globally.
__________________
Visit my Audio Web Page <<--CLICK TO LEARN MORE-->> Get my LADSPA plugins
  Reply With Quote
Old 20th February 2018, 12:20 AM   #76
CharlieLaub is offline CharlieLaub  United States
diyAudio Member
 
Join Date: Mar 2007
Location: Michigan
UPDATE:

I have implemented a new ROUTE formalism that allows the user to tee an audio channel whenever that is desired on the client side. This will provide more flexibility for LADSPA crossover signal routing, as I illustrated with the figure in the last post.

With that in place, I started to do more testing of multichannel streaming. Then I encountered some strange problems that I can't seem to solve. Streaming up to 2-channels of audio is no problem. But when I attempt to stream 3 channels (I also tried 4) things don't work on the client side. After lots of testing, it seems that has something to do either with the RTP depayloading or receiving the UDP stream on the client side, and channel assignments.

I can't find any kind of documentation about this online, and multiple posts to the gstreamer-devel forum have gone unanswered. So at this point after trying to figure a way past this problem for a few days, I am about ready to throw in the towel on multchannel streaming. This would be a bit of a disappointment, since I thought I would be able to stream e.g. 5.1/7.1 audio, or mixed-down/up-mixed audio to clients. Until I can figure out a solution, 2 channels will be the limit. There is still a possibility that I will come to understand a solution that will support multichannel streaming, but at this point I am more or less done wasting time on it.

For my own uses (and quite possibly for most other people too) this doesn't represent any kind of setback. I only listen to stereo sources, and my primary goals were to be able to implement a DSP crossover using LADSPA under gstreamer, and get better control of the clocking used on both the sender and receiver sides. All of that seems to be working pretty well.

The only functionality that I need to modify is to move the "mixing" capability from the server side to the client side. Currently all you can do on the client side is "split" (e.g. tee) the input. But if you wanted to stream a stereo source and support a system of left speaker, right speaker, and mono subwoofer you need to be able to downmix the input to mono for the sub.
__________________
Visit my Audio Web Page <<--CLICK TO LEARN MORE-->> Get my LADSPA plugins
  Reply With Quote
Old 26th February 2018, 03:11 AM   #77
CharlieLaub is offline CharlieLaub  United States
diyAudio Member
 
Join Date: Mar 2007
Location: Michigan
yet another UPDATE:

I have been doing more testing on different platforms and OSes. I have at my disposal R-Pi 2 and 3 as well as a couple of BayTrail J1900 Linux boxes. These run different versions of Gstreamer. It seems that after some checking, some problems are due to the Gstreamer versions that I am running and the fact that I am runnging the command line version of Gstreamer, which is not really the best for complicated applications. I SHOULD be able to do everything I need with it, but perhaps the command line launcher does not receive as much vetting as the code-based API stuff... at least that is my guess.

I have had the best success overall on my J1900 Linux boxes. These are running Ubuntu 16.04, which comes with Gstreamer 1.8.3, and Ubuntu 17.04, which comes with Gstreamer 1.10.4. I can run multiple USB DACs, implement LADSPA plugins, etc.

I have a Pi2 system that was running an old version of Raspbian that was not working until I upgraded it to Raspbian Stretch. Now it works mostly. Sometimes it's not running properly when I attempt to use multiple DACs, however, supposedly it also has Gstreamer version 1.10.4. Could be a problem with USB, or the build on the ARM. I just don't know.

Today I tried a couple other boards: Tinker Board running Tinker OS 2.0.4, and a Pi 3 running Ubuntu Mate. I could not get either of these to work properly, but I was not all that patient when trying.

Gstreamer 1.12.4 is currently available via Ubuntu 17.10, however I have not tried it yet since I am waiting for 18.04 to be released in May before upgrading my systems, which will come with Gstreamer 1.14.x. With each new version comes some bugfixes and eventually everything should work as advertised.

Currently I don't think that I will release the new code that includes the LADSPA DSP crossover functionality until I have had more time to test it with various hardware and software and I see things are working more reliably, or at least it is clear on what systems I could expect success... kind of frustrating, but unless I want to re-write everything in C++ or Python this is the nature of the beast.

I will post new info here when I have it. In the meantime I will keep testing. I am hoping to try out some new hardware platforms in the next couple of months, so there are lots of testing possibilities ahead.
__________________
Visit my Audio Web Page <<--CLICK TO LEARN MORE-->> Get my LADSPA plugins
  Reply With Quote
Old 28th February 2018, 04:03 PM   #78
CharlieLaub is offline CharlieLaub  United States
diyAudio Member
 
Join Date: Mar 2007
Location: Michigan
UPDATE: most problems have now been fixed!

By chance I discovered a complete set of detailed gstreamer docs online. As a result I was able to implement some addition buffering and latency options for a few key pipeline elements. This seems to have eliminated a couple of strange and not-very-reproducible problems that were occasionally causing audio glitches. Why complete and detailed documentation is not available on the gstreamer site itself is a bit perplexing...

The good news is that I seem to have most everything working as I had envisioned. I tested out the input mixing, multiple channel streaming (well, at least more than 2 channels!), the LADSPA DSP plugins, etc. on multiple hardware platforms including the TinkerBoard and a Pi3 running Rapbian Stretch. These generally are running Gstramer version 1.10.4 or later. I will continue to do more testing and listening but so far it's looking very positive.

With that in the rear mirror I can move ahead with some ideas that would improve the flexibility of the program. Currently mixing is only done on the server side, and the LADSPA DSP crossover filtering is only done on the client side. It would be beneficial if all capabilities were available on both the server and client. Maybe you want to apply the DSP filtering on the server and then just stream the audio right to the client's DAC? Or perhaps you want to implement a DSP crossover on the "server" (where the audio source is located) without any streaming. I will figure out how to implement this during the next few days.

Check back here for additional updates and progress reports.
__________________
Visit my Audio Web Page <<--CLICK TO LEARN MORE-->> Get my LADSPA plugins
  Reply With Quote
Old 3rd March 2018, 11:33 PM   #79
hopkins is offline hopkins  France
diyAudio Member
 
Join Date: Feb 2012
Location: Paris
Hi, I have been testing using MPD in a "client/server" mode, and found this japanese site that documents a simple method using ncat: Home * papalius/symphonic-mpd Wiki * GitHub

In MPD you define one output per "client", with the following syntax:

audio_output {
type "pipe"
name "PIPE"
format "44100:16:2"
always_on "yes"
command "ncat 192.168.x.x 4444"
}

(not sure the format option does anything)

Then on the client side I run this command (not sure all is necessary either):

/usr/bin/ncat -kl 4444 -e "/usr/bin/aplay -M -t raw -Dplug:default -f cd"

It works. I imagine you could create a command to run ecasound, for example.

What are the advantages of the solution you are developing ?

Last edited by hopkins; 3rd March 2018 at 11:46 PM.
  Reply With Quote
Old 4th March 2018, 05:03 PM   #80
CharlieLaub is offline CharlieLaub  United States
diyAudio Member
 
Join Date: Mar 2007
Location: Michigan
Quote:
Originally Posted by hopkins View Post
Hi, I have been testing using MPD in a "client/server" mode, and found this japanese site that documents a simple method using ncat: Home * papalius/symphonic-mpd Wiki * GitHub

In MPD you define one output per "client", with the following syntax:

audio_output {
type "pipe"
name "PIPE"
format "44100:16:2"
always_on "yes"
command "ncat 192.168.x.x 4444"
}

(not sure the format option does anything)

Then on the client side I run this command (not sure all is necessary either):

/usr/bin/ncat -kl 4444 -e "/usr/bin/aplay -M -t raw -Dplug:default -f cd"

It works. I imagine you could create a command to run ecasound, for example.

What are the advantages of the solution you are developing ?
Well, if your goal is to stream audio to one client, then there are MANY ways to do that. Netcatting the stream is one of the more primitive ones. And yes, you probably could pipe/loop the audio to ecasound on the client. This is exactly what I have done in the past with my own code.

One of the goals of my project is to achieve accomplish tight synchronicity of all playback sinks, across all clients. Some programs claim to "tightly" sync playback, but this they mean they can at best get around 1msec synchronicity, and often its worse. One application I have in mind is when there is a separate client in left and right loudspeaker of a stereo pair. In this case 1msec timing differences are clearly audible and at least 10x better synchronization is necessary.

Since Gstreamer includes mechanisms for clock control that are not available in most other platforms it makes sense to use it. Gstreamer is freely available, is continually being updated and developed, and comes preinstalled with many flavors of Linux (e.g. Debian, Ubuntu, Raspbian, etc). At the same time I am folding in the DSP processing aspect that I used to achieve through ecasound. Then means that Gstreamer will be in control of the timing from source to sink, something that is not possible with netcat, or when passing the audio off to ecasound.

My code includes a system of configuration and playback control files, including the DSP filtering capabilities. There is also a simple interface to turn systems on and off, and systems can include multiple local and streaming clients. It can be run in interactive mode, or in a one-shot mode that would permit it to be called from script files or as the backend of another control system (e.g. with a pretty GUI). This makes it very versatile and powerful. I have multiple DIY loudspeaker systems in my home and this allows me to switch them on and off using any interface that can connect to the main computer via ssh. I use an Android tablet that I can take around with me. It runs the control interface as well as an MPD control client with which I can adjust volume and playback source, but any mobile playback interface to any player software would work equally as well. I can also adjust the DSP filtering via the same SSH connection, so that I can tune the system from my listening position.

I basically cooked up all the features that I need as a DIY loudspeaker builder and built the system around Gstreamer. It's perfect for my needs and, thanks to the easy-to-use control interface, for others in my household who want to fire up some music. Simple to use, yet extremely capable.
__________________
Visit my Audio Web Page <<--CLICK TO LEARN MORE-->> Get my LADSPA plugins
  Reply With Quote

Reply


A bash-script-based streaming audio system client controller for gstreamerHide this!Advertise here!
Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
New BeagleBone based Audio System dogrocket Vendor's Bazaar 3 1st April 2016 04:02 AM
XMOS audio streaming controller GB interest heartwinter Group Buys 12 13th July 2015 04:30 PM
USB streaming controller arjunm009 Digital Line Level 2 12th May 2015 04:38 AM
First audio project, Wall controller for room audio system, looking for guidance, Chrisdvip Construction Tips 2 10th June 2013 05:47 AM
Audio System Controller happyboy Analog Line Level 9 12th September 2012 09:12 AM


New To Site? Need Help?

All times are GMT. The time now is 11:58 PM.


Search Engine Optimisation provided by DragonByte SEO (Pro) - vBulletin Mods & Addons Copyright © 2018 DragonByte Technologies Ltd.
Resources saved on this page: MySQL 15.00%
vBulletin Optimisation provided by vB Optimise (Pro) - vBulletin Mods & Addons Copyright © 2018 DragonByte Technologies Ltd.
Copyright ©1999-2018 diyAudio
Wiki