• Welcome to ASR. There are many reviews of audio hardware and expert members to help answer your questions. Click here to have your audio equipment measured for free!

Sharing my Linux-based Software DSP app for IIR DSP, Loudspeaker Crossovers

charlielaub

Senior Member
Joined
Jan 5, 2023
Messages
362
Likes
514
Location
Bayern DE
I have decided to share my DIY software DSP app "GStreamer Streaming-Audio System Controller" (GSASysCon) with the greater community. It's something I have been using and slowly modifying and enhancing for the last 10 years or so, and it's very stable and reliable. Features include multiple-playback endpoints, synchronous playback, and streaming to remote clients (e.g. other computers on your LAN). A recent addition are "shortcut" names for a wide variety of loudspeaker filters. There are several help documents available that describe all the features and functionality of the app, as well as a setup guide to get you started.

The app automatically builds and launches GStreamer pipelines using GStreamer's command-line interface based on the user configuration. IIR filtering is provided by my ACDf LADSPA filters, which are included with the package. Configuration of routing and DSP is via text-based files. There is also a text-based user interface for controlling playback and basic volume control. It can also be called in a non-interactive mode.

The primary online thread can be found at DIY audio, however, I often log in here and you are welcome to PM me with questions or issues, or simply post in this thread.

Link:
 
Last edited:
This project has been moved to GitHub:
The latest release is 3.15.0:
GSASysCon-3.15.0 GitHub release page

Under Linux you can use wget to download the file into the current directory instead of having to use a browser. Choose one of the following:
To download the ZIP compressed file:
wget https://github.com/charlielaub/GSASysCon/archive/refs/tags/3.15.0.zip
To download the GZIP+TAR compressed file:
wget https://github.com/charlielaub/GSASysCon/archive/refs/tags/3.15.0.tar.gz

Unpack the archive, open the SetupGuide.txt file in the directory /system_control/docs, and then follow the instructions.

To unpack the compressed files: for the zipped archive use the unzip command. For the tar.gz'd file, first gunzip the gz archive and then run tar -xvf on the resulting tar file.
 
Bumping this back up to the first page...

This is a capable and easy to use IIR DSP software for loudspeaker crossovers. I hope you will try it.
 
Chiming to say this looks fabulous. I suspect a lot of readers don't realise what is embodied here.

I use GStreamer a lot in my day job, and had been musing that exactly this approach would be an excellent way forward for a lot of uses. The idea of building up an active loudspeaker with say a Rasberry Pi acting as both streaming endpoint and crossover DSP engine, all managed within a GStreamer pipeline should make a lot of people really enthusiastic.

Maybe one can point out that RTP encapsulated audio is exactly what AES67 uses. So this solution is potentially of wider interest.

AES67 doesn't define the discovery protocol, but in a domestic setting you don't always need one. GStreamer provides a simple RTSP receiver, so if needed one could in principle slot that in on an end point. RTSP service is also possible with GStreamer, albeit with more work. So a very sophisticated home streaming environment is possible.

Heck, add PTP to the system and you have essentially full AES67. Although I do note that latency might remain a potential issue. But for replay use, it won't be.
 
Last edited:
@Francis Vaughan Thanks for your comment. I use GSASysCon on a daily basis to stream to endpoints in my home and, there, do any DSP needed. I have incorporated the RTP+RTCP method using rtpbin that is for example described here:
All the port assignments and logins are handled automatically in the background.

This works quite well to synchronize various playback pipelines. When both the TX and RX communication is good and there is a distributed clock (I use chrony and NTP, but PTP is possible) you can synchronize all the endpoints pretty tightly. Using NTP to distribute a clock, I can get sync down to 100 microseconds or less, confirmed with measurements, over WiFi.
 
Chiming to say this looks fabulous. I suspect a lot of readers don't realise what is embodied here.

I use GStreamer a lot in my day job, and had been musing that exactly this approach would be an excellent way forward for a lot of uses. The idea of building up an active loudspeaker with say a Rasberry Pi acting as both streaming endpoint and crossover DSP engine, all managed within a GStreamer pipeline should make a lot of people really enthusiastic.

Maybe one can point out that RTP encapsulated audio is exactly what AES67 uses. So this solution is potentially of wider interest.

AES67 doesn't define the discovery protocol, but in a domestic setting you don't always need one. GStreamer provides a simple RTSP receiver, so if needed one could in principle slot that in on an end point. RTSP service is also possible with GStreamer, albeit with more work. So a very sophisticated home streaming environment is possible.

Heck, add PTP to the system and you have essentially full AES67. Although I do note that latency might remain a potential issue. But for replay use, it won't be.
Yes what you're thinking about is 100% possible with Gstreamer. I use it all the time for AES67 I/O, it also helps cut out the need for virtual AES67 'devices' like virtual soundcards or whatever. It's PTP implementation is good, and works on Windows now (previously I was building it to get gst-ptp-helper, but I think it's in releases now?). It's worth a look if you know what you're doing. There's some references floating around to get you started, you should be able to work out how to deal with the clocking and stuff ^_^
 
Bumping this thread back up to the top of the pile...
Is there something I need to install to run gunzip? I've been using linux for a couple of years and have never heard of it. I'm getting the following error when I invoke it

j@mx-j:~
$ gunzip GSASysCon-3.15.2.tar.gz
gzip: GSASysCon-3.15.2.tar.gz: No such file or directory

I'm using MXLinux (debian based) if that makes a difference
 
Is there something I need to install to run gunzip? I've been using linux for a couple of years and have never heard of it. I'm getting the following error when I invoke it

j@mx-j:~
$ gunzip GSASysCon-3.15.2.tar.gz
gzip: GSASysCon-3.15.2.tar.gz: No such file or directory

I'm using MXLinux (debian based) if that makes a difference
No - gunzip is running fine. The problem is that there is no file named GSASysCon-3.15.2.tar.gz in your current directory. You need to include the path to that file, either as an absolute or relative path.
 
Is there something I need to install to run gunzip? I've been using linux for a couple of years and have never heard of it. I'm getting the following error when I invoke it

j@mx-j:~
$ gunzip GSASysCon-3.15.2.tar.gz
gzip: GSASysCon-3.15.2.tar.gz: No such file or directory

I'm using MXLinux (debian based) if that makes a difference
Sorry that I did not reply earlier about the problem with gunzip. Whenever I push out a new version the version number and therefore the filename changes. I tried to say in the instructions to use whatever is the current filename but will review that and try to clarify it for the next release.
 
A new release of GSASysCon, version 3.16, has just been made available.

The release is available for download from my GitHub repository here:
https://github.com/charlielaub/GSASysCon/releases/tag/3.16

This release is primarily to fix a couple of bugs that I found, that occurred when the user had multiple INSERT FROM FILE or DEFINE VARIABLE statements. The first statement would work but subsequent ones did not. This is a relatively important bug, since the user might typically include both of these in the system configuration file:
Code:
INSERT_FROM_FILE Common_Loudspeaker_Crossover_Filters.txt
INSERT_FROM_FILE Equalization_Filters.txt

I also updated some other code, some documentation, and added my recent writeup about interfacing with Pipewire.

There is one new feature. The user can now make the Gstreamer code explicitly state the sample rate of the stream as it is being sent to the sink. During testing, I found this was necessary to get Pipewire to use the correct rate instead of a default one. When using a pipewire-pulse sink, the format and rate can be specified like this:
Code:
   SINK_FORMAT = S32LE
   SINK_RATE = 96000
   CLIENT_SINK = pulsesink device=XXXXX
Pipewire is now supplied with many LinuxOSes and it is more flexible and convenient to get application audio via this system rather than the old way, via an ALSA loopback.

If you encounter any problems or want to make a bug report, please contact me so that I can fix/update the code as necessary. Thanks!
 
Since I had my fingers poking around under the hood of GSASysCon I decided to rework user scripting, how it is declared in the system configuration, and to expand its potential uses. Here is a little post about that...

User scripting is a very helpful part of GSASysCon. It lets the user call code or commands that are external to GSASysCon. Let's say you wanted to integrate GSASysCon for its DSP into a powered speaker and as part of that you want to perform some action like turn on or off the amplifier modules depending on when the system fired up. This is done with the user command and scripting feature. Anything you can run from the bash command line, you can integrate into GSASysCon. So you could (for example) call a routine to switch a GPIO pin from low to high, that you would normally do from the command line, but instead it is integrated into the process of launching or terminating the playback system. When the system includes a remote client (e.g. for a distributed audio application), you can run code that is stored on the local machine on the client via the magic of SSH and something called a HereDoc. See for details:
https://www.geeksforgeeks.org/linux-unix/how-to-use-heredoc-in-shell-scripting/
https://linuxize.com/post/bash-heredoc/#using-heredoc-with-ssh

I happen to have a need for this exact functionality in my latest system. It uses Pipewire as the source for audio that is used/consumed by the Gstreamer pipeline. The audio is taken from a custom null_sink that I create in PW. However, the behavior is such, that when there is not audio playing the null sink goes into a kind of hibernation. In hibernation it doesn't do anything and disappears from PW after a while, or it might stick around but does not produce any samples (e.g. zeroes). So when Gstreamer tries to use the hibernating null sink to feed its pipeline the pipeline stalls and unfortunately never wakes up, e.g. later when I start playing audio in my application. The Gstreamer process appears when you list it with ps but it doesn't actually seem to run. The solution I cam up with is, just before launching the Gstream pipeline with GSASysCon, to send zeroes to Pipewire from a dummy process that I run in a terminal window, for example "aplay -D Pipewire -c2 -r 96000 -f S32LE /dev/zero" or something similar. This wakes up the null sink and it starts producing zeroes as output. Then when I launch the Gstreamer pipeline for my playback system the null sink remains active even after I kill the dummy source. So, all I need to do is use the user command and scripting feature of GSASysCon to automatically launch the command to produce zeroes for the null sink just before the system launch and everything will happen as desired and audio data will flow. It's a good way to address this quirk (or desired behavior perhaps) of Pipewire's null sink.

When you think about it, there are several different possibilities for running commands and script. You have to know:
1. Where does the script reside?
a. on the LOCAL machine?
b. REMOTE (client side)?

2. Where does the script execute?
a. LOCALLY
b. REMOTELY (on the client)

3. When does the script execute?
a. before_launch
b. after_launch
c. before_terminate
d. after_terminate

To cover all of these possibilities, I came up with a new syntax to describe them in the system configuration file. You start with the directive:
EXTERNAL_COMMAND
and then you provide "key=value" pairs for several configurational variables:
RESIDES
RUN_WHEN
RUN_WHERE
COMMAND

The complete directive would look something like this:
EXTERNAL_COMMAND RESIDES=local RUN_WHERE=local RUN_WHEN=before_launch COMMAND=my_user_commands.sh
The order of appearance of the key-value pairs does not matter as long as RUN_WHEN and COMMAND are present (they are required parameters).

A couple of parameters have default values:
RESIDES = local
RUN_WHERE = local
RUN_WHEN= no default value!
COMMAND = no default value!

This now covers all the potential use cases for calling command and scripts from with in GSASysCon. I have mostly coded these up and will do some testing. The expanded scripting functionality will be available in the next release.
 
ANNOUNCING MY FIRST VIDEO ABOUT GSASysCon !

I decided to shoot a video of GSASysCon in action so that others can see how it works. The system is run from a Ubuntu desktop, and streams OS audio to a remote client, where IIR DSP is performed and then 10 channels at 96kHz/32bit are rendered via my audio interface. This functions both like a DANTE system and as a DSP crossover for the loudspeakers. I go over some details in the video, which you should be able to view here on my new YouTube channel:
https://youtu.be/ZghXUpxAwmU


Splash.png
 
I made another video, this time showing how I use GSASysCon to give "preamp functionality" to my computer. By preamp I mean input switching, volume control, and output switching functions. Of course you can also implement DSP, and it does streaming, so GSASysCon is a bit more versatile compared to an analog preamp!

The video is shot on the computer I use it to run my whole-home audio playback system.

Link to YT:
 
Back
Top Bottom