QA401 Headless & Linux Support

There are two recurring requests for the QA401 platform: First, people ask if they can easily control the hardware from a language like Python, Matlab or LabView instead of DotNet C# or C++ (both of which can easily automate QA401 measurements). The second is if there's a way to run without a GUI because the UI isn't required in a factory setting.

The answer to the first question is "yes" but it requires a fair bit of savvy because it requires you to write a bridge DLL OR enter the world of COM. Neither are very much fun. That's why we currently recommend a managed language like C# or C++ for controlling the hardware--it's very easy to do.

But to address both of these, and to pick up a cross-platform solution in the process, we're sharing an early look at a headless application for the QA401 hardware called the QA401H (H = headless). The application lives in a console--there's no UI except for text that is largely useful just to developers. The application is written in DotNet Core, which means it will run on Windows, MacOS and Linux platforms. In the examples below, we'll show the application running on Ubuntu 18.04 LTS.

The interface to the QA401H console is via REST. REST isn't a language. Instead, it's a methodology for interacting with other machines using common web protocols. As a result, it's well supported by most all languages and platforms. For the developer, it means it's very easy to start communicating and controlling the QA401 hardware. And as we'll show below, it can be extremely fast for making basic audio measurements. 

DotNet Core is an open-source subset of DotNet. The DotNet Core framework runs on Windows, MacOS and Linux. Applications written to run on DotNet core are highly portable for the most part. In some cases, the DotNet Core application will rely on lower level libraries that rely on services provided by the underlying OS. In the case of QA401H, the app relies on a cross-platform USB solution called LibUSB. LibUSB in turn relies on WinUSB to deliver USB functionality on Windows, and on Linux it relies on kernel and file-level calls to deliver functionality. 

The purpose of this post is to solicit feedback regarding the direction. Like it? No? Send your thoughts to our support alias or leave a comment below.

Getting Setup on Ubuntu 18.04 LTS

For the screenshots below, the environment was an Oracle VirtualBox running Ubuntu 18.04 LTS as guest on a Win10 host. Other distros may requires different steps. If you want to try the QA401H app on a VM and if you have PCAP, Wireshark, USBlyzer or any other USB sniffing applications on your machine, you will likely have trouble getting the VM to properly capture the QA401 USB hardware. There are solutions on-line to change the registry on the host OS. But it's probably easiest to just uninstall the USB-sniffing apps on the host OS and re-install later.

Step 1

Install the DotNet Runtime. This needs to be downloaded from Microsoft for your particular flavor of Linux. Link is HERE.

Step 2

Install LibUSB. This may already be present on your distro. But if not, you can use the command below. If it is already present, running it again doesn't hurt anything. 

sudo apt-get install libusb-1.0-0

QA401H relies on System.Drawing, which requires native libraries that may not be present on your Linux install. Those can be installed with. 
sudo apt install libc6-dev 
sudo apt install libgdiplus

Step 3

Make the hardware device known to the OS. I'll offer a huge "thanks!" to JamesO and SimonM for their help here. This was a tough nut to crack for a Windows guy.

sudo sh -c 'echo "SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"16c0\", ATTRS{idProduct}==\"4e27\", MODE==\"0666\"" > /etc/udev/rules.d/51-qa401.rules'

cat /etc/udev/rules.d/51-qa401.rules

sudo udevadm control --reload-rules

Step 4

Plug in (or re-plug) the QA401. Right now, the QA401 requires a re-plug before the QA401H application is launched. Every time. That will hopefully be fixed in the future. 

Step 5

Verify the QA401 is shown in the list of connected devices using the 'lsusb' command. 

Step 6

Download the QA401H zip from Github. It is located HERE. Unzip it into the directory of your choice.

Step 7

Open a terminal in the directory that hosts the application unzipped above, navigate into the 'publish' folder and type

dotnet qa401h.dll

This will launch the QA401H application. The QA401H application will configure the FPGA inside the QA401 hardware. During this time, you won't see any activity from the app. It will just appear to sit there for 30 to 60 seconds.

After the pause, the hardware should be fully configured and the application should get to the idle state. The QA401 should have the LINK and ATTEN LED active at this point. 

Step 8

Note in the above screen, the application offers a web address. If you browse to that address, you'll see the QA401 REST API and some simple examples. Remember, this is early and the API isn't fully fleshed-out yet. But browsing this doc this will give you a feel for where things are headed.

Step 10

With the QA401H app up and running, we can now get ready to make a simple THD measurement. Put the QA401 hardware into loopback mode by connecting the output to the input. That is, connect the L+ OUTPUT to the L+ INPUT. And short the L- INPUT with a shorting block. 

Step 11

For the commands below, you can build them into your measurement app or for prototyping you can use an application such as cURL to issue a series of HTTP commands from another terminal window. The -d "" in cURL specifies a body and sets the body length to be zero. The -X lets us specify the HTTP verb and the URI/URL. 

The first command we send will disable the QA401 attenuator. We do this by stating we want the max input level to be +6 dBV. The other legal value is +26 dBV (which engages the attenuator).

curl -d "" -X PUT http://localhost:9401/Settings/Input/Max/6

After issuing this command, you should hear a relay click inside the QA401, and the front-panel ATTEN LED should extinguish.

Below, you can see the cURL command issued in a terminal on the right. This is a simple HTTP PUT. On the left, you can see the QA401H application processing the command.

Next, let's set the FFT size to 32768

curl -d "" -X PUT http://localhost:9401/Settings/BufferSize/32768

Next, let's enable Audio Generator #1, set the frequency to 1000 Hz and set the amplitude to -1 dBV

curl -d "" -X PUT http://localhost:9401/Settings/AudioGen/1/1/1000/-1

The above statements set up the QA401 hardware. We could also have specified filters, sample frequency and other parameters (although this early eval code doesn't have everything implemented yet).

Now that we have the hardware setup as we want, we can kick off an acquisition using

curl -d "" -X POST http://localhost:9401/Acquisition

The command above will return after the acquisition is done, which should take about 1 second given the settings we applied. And once the POST has returned, we can ask the QA401 to compute the THD of the acquisition, out to 20 KHz and assuming a 1 KHz fundamental.

curl -d "" -X GET http://localhost:9401/ThdDb/1000/20000

At this point, take a look at the QA401H response to the POST command issued above and highlighted below. You can see the elapsed time was 0.95 seconds, during this time the frame of audio was emitted and captured. For those not familiar with the QA401 hardware, it generally operates on packets or bursts of audio. The manual included with the QA401 install for Windows has a good explanation of the process. 

The next two commands are the same command: A THD computation performed on the acquired data and shown in the picture below. The first instance took about 20 mS, but the subsequent call took about 680 microseconds. This is the JIT (just-in-time) aspects of the JIT compiler at work. The first time code runs it runs slowly as the compiler optimizes the IL bytecode down to machine instructions. But after the first run, it's very fast. 

The second point to make here is that large data sets aren't being pulled across for each calculation. The data you've acquired remains in the QA401H application (unless you request to pull it across). So basic calculations such as THD, RMS, amplitudes at various frequencies will be exceedingly fast to make. The QA401 REST API outlined in the localhost:9401 web page goes into the return types in much more detail. 

Finally, let's switch back to the browser and request a plot of the frequency domain data we've acquired for the left channel. This is done via an HTTP GET.


The ability to generate graphs won't be a primary use case of the QA401H application. Instead, it's provided primarily as a way for developers to sanity check what they are seeing during development. 


This is preview code, still very rough around the edges. But it hopefully makes it clear how easily you can "drive" an audio analyzer in a factory setting to make lightening-fast measurements of your products using common web protocols support by just about any language or environment out there today. In the future, this should make it easy to connect a very high quality audio analyzer to applications written in language ranging from Python to Matlab. 

This is still several months away from a product release. But we'd love to hear if you like the direction or not. 

Thanks, Matt

Like what you just read? Join our mailing list at the bottom of the page.


  • The REST api looks useful, I suspect we could automate our testing with that. We did look at the QA40x a while ago, but decided at the time not to pursue it, as it required some windows tools we were not familiar with, such as “Visual Studio” … but the REST API looks easy to use and platform agnostic, I’m sure we’ll be able to work with that through Perl or whatever. Thanks.

  • @Matt, thank you very much for the quick, honest response. I take it as excellent news and we will definitely be keeping an eye on your products (especially the QA401 series). Your willingness to listen to customers and offer cross platform support in the future are major factors in gaining and keeping our loyalty.
    Keep up the good work and best of luck!

  • @phs, we need a bit more time to evolve the software to get cross platform. There’s a chunk of the QA401 application that relies on dotnet remoting, and that’s not supported in Mono. We’ve not done the work yet, but we’ll move the QA401 application to REST at some point, dump the remoting API (or make it optional), and the QA401 and QA401H will then share the same API. And our belief is that once dotnet remoting is removed from the QA401 app that it will run under Mono. And at that point, we’ll be able to truly be cross platform on the GUI too. No idea on the timelines on any of this, but the early work has started. It will likely roll out together with a new GUI too.

  • While I applaud your attempt to bring some functionality to the Linux platform, we’ll be looking at other options until you fully support Linux. Any products that can not be completely independent from Microsoft are simply not considered here, or at many other organizations, for a myriad of obvious reasons. Managers have to start realizing that Microsoft lock-in, privacy and honesty issues, etc. are no longer acceptable risks. Please quit assuming your precious customers are willing to submit to Microsoft, just to use their products!

  • @Hans, I think SCPI made a lot of sense when there was a focus on standardizing communications over a specific bus. And yes, there was some benefit in making it easy to move between equipment from various vendors. But at the end of the day, looking up the command to see how you change a voltage is the trivial/easy problem. The harder problem is exposing all of this to developers. REST is where the world is headed or, more accurately, has already headed. You could ask “why not make scpi run atop REST” and while I guess you could, the hard part of GPIB and SCPI has never been looking up the relevant command. To me, it’s better to preserve REST best practices.


Leave a comment

Please note, comments must be approved before they are published