Max8radio CubicSDR I/Q prototype

Another working prototype with Max and CubicSDR

Now working some better… The Max SDR patch is receiving an IQ audio stream at 96 KHz from CubicSDR and sending frequency data to rigctld daemon via a python script that recodes OSC to tcp data.

repository: https://github.com/tkzic/max8radio

Files:

max8sdr1.maxpat

py3rigctl2.py (python script)

Instructions:

Basically the same as instructions in the previous prototype here: https://reactivemusic.net/?p=19995

make sure to start the rigctl daemon before CubicSDR

 rigctld -m 1 4532 & 

And make sure there is some audio gain on CubicSDR

But… There is only one Max patch now and – after you start the rigcltd daemon, you need to run the python script in the max8radio folder like this:

python3 py3rigctl2.py

The most important thing is to start CubicSDR first before you run the Max patch. Make sure to get everything working correctly. Then start the Max SDR.

In CubicSDR make sure you only have one “modem” running – otherwise the IQ data stream will be a complete mess. Als0 make sure that the audio sample rate in CubicSDR is set to 96 KHz. It will revert to 48 KHz. everytime you load the program. You can use the ‘bookmarks’ from a previous CubicSDR session (lower left part of the screen) to load a previous session with the same parameters.

These are the necessary settings:

  • I/Q modem
  • Audio out: Existential Audio Inc. Blackhole 2 ch.
  • Audio sample rate: 96 KHz.
  • Rig Control Menu: enable rig and follow rig should be ‘checked’
  • Frequency should equal Center frequency and the V delta lock toggle should be on
  • Demodulator Gain level should be very low to prevent excess AGC (upper right corner)

Actually if you have loaded everything ok in a previous session, try this:

  • get the rigctld daemon running from the command
  • load CubicSDR
  • First thing: click ‘enable rig’ under rig control (this will probably load some crazy frequency like 145 Mhz
  • Then in the bookmarks (lower left) double click on your previous session, under ‘recents’ for example: 7007MHzI/Q – this should restore almost all the settings.
  • Then change the audio sample rate to 96 KHz if needed.
  • If the input to Max seems wrong, try clicking the S  (over near the top right)  to solo the modems. There may be more than one going.

Max settings

  • Set audio input to Blackhole 2ch @ 96 KHz. (to match output from CubicSDR
  • Click the ‘flip IQ’ toggle – for some reason CubicSDR sends out the I/Q signal flipped
  • The arrow key tuning and all other tuning methods should work now

Notes

One of the problems with CubicSDR is sometimes you’ll accidentally change something and all the settings go crazy.

note: I tried a new version of CubicSDR (2.6) from the sdrplay website. It would not detect any connected devices or audio drivers.

Once you get it working, the audio quality inside Max is excellent – using the Airspy HF+

Python3 tcp client for Max

Using OSC from [udpsend]

I needed a better way to send radio frequency data from Max to a rigcltd daemon (via tcp). This is the method of tuning SDR devices hosted by CubicSDR.

From the max8radio folder run:

py3rigctl2.py

The input is OSC frequency data, on port 8001, in the form: /F 7001000

(This would be for 7.001 MHz)

An OSC server in the python program listens for these messages and then reformats and sends them to a running rigctld daemon running in the background on port 4532

rigctld -m 1 4532 &

The frequency message going to rigctld would be in the format: F+ 7001000

 

Python3 tcp client and server

Substitute for command line netcat (nc)

Running nc from the Max [shell] object was not only slow, but also caused audio clicks in CubicSDR. So here’s a link to python code using sockets to build a tcp client and server.  from this link: https://stackoverflow.com/questions/34653875/python-how-to-send-data-over-tcp

import socket

host = socket.gethostname()
port = 12345                   # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.sendall(b'Hello, world')
data = s.recv(1024)
s.close()
print('Received', repr(data))

Python2 is not Python3

Less than subtle differences

The default python on Mac Catalina is 2.7.16.

But python 2 is officially deprecated. So to use a current version of python and pip in Mac OS you need to specify python3 and pip3.

Most of the python2 and python3 examples I found were not compatible. For example, the print command.

IQ file and stream converters for SDR

Notes on streaming IQ data

Looking for an alternative to CubicSDR that would provide soapySDR library support, and backend frequency control without at GUI


links:

audacity: http://play.fallows.ca/wp/radio/software-defined-radio/recording-smartsdr-iq-data-audacity/

convert rtlsdr to sdr-sharp: https://github.com/Marcin648/iqToSharp

demod (demodulate IQ streams)  https://github.com/cubehub/demod

rust-airspy  (get stream from airspy)  https://github.com/cubehub/rust-airspy

andres vahter blog: https://andres.svbtle.com/pipe-sdr-iq-data-through-fm-demodulator-for-fsk9600-ax25-reception

rtl_tcp -a 192.168.2.106

rtl_fm can also output raw signed 16 bit IQ data. – as in this example from vahter’s blog: rtl_fm -f 437.505M -M raw –s 1024000r 22050 | doppler -tle “ESTCUBE 1” cubesat.txt | demod -M fm -deviation 3.5k | multimon-ng -t raw -a FSK9600 /dev/stdin

liquid-dsp c sdr dsp lib : https://github.com/jgaeddert/liquid-dsp

sv3exp – interesting experiment with piping iq data in linux command line:  https://sv3exp.blogspot.com/2019/09/decoding-ft8-in-with-any-sdr-like-usrp.html

ha7ilm csdr (command line sdr processor)  https://github.com/ha7ilm/csdr

**sdrplay rtl_tcp fork  https://github.com/SDRplay/RSPTCPServer

cloud-sdr internet streaming:  http://www.cloud-sdr.com/streaming-iq-over-internet-listen-remotely-to-airport-radio/ cloud-sdr also looks to be out of business.

 

interesting post about requests for command line cubicsdr and related : https://github.com/cjcliffe/CubicSDR/issues/654

rx tools (an update of some of the rtl stuff using soapysdr  https://github.com/rxseger/rx_tools

rx_tools, in theory, is a good prospect, but the code is several years out of date, gives errors on devices, is unsupported – just doesn’t work yet.

There are many good examples of IQ streaming with rtl_fm and rtl_tcp, but of course they only suppport rtlsdr.

Prospects

pothos sdr : flowgraph https://github.com/pothosware/PothosCore/wiki

**luaradio – similar to gnu-radio and looks like will run with macports:  https://github.com/vsergeev/luaradio This is a flowgraph language like Gnu-radio. But its lightweight. If the device support is ok, then it looks like there are flowgraph modules that would allow tcp data in/out as well as audio. This is primarily a linux app – but if you ran it on r-pi it could make a good front end for a lot of devices. Also it may run in Mac OS with some audio tweaks. ie., portaudio and pulseaudio.

**sdrGlut this app runs on mac os and streams iq https://github.com/righthalfplane/SdrGlut – I was not able to find a method of external frequency control. It may be added in future releases as this app is in active current development.  Also it runs sdrplay rspdx.

**gnu-radio: Well supported and active development. Not sure about device support for common hobbyist radios like sdrplay, airspyhf, etc.,  gnu-radio: http://play.fallows.ca/wp/radio/software-defined-radio/gnuradio-ssb-receiver/

**worst-case scenario. Actually build something with soapy-sdr, hamlib, and csdr.

docs

**PLSDR – some nice theory here: https://arachnoid.com/PLSDR/

**IQ data for dummies: http://whiteboard.ping.se/SDR/IQ

 

Max8radio project

New version of software define radio for Max/MSP  (in progress)

github repository: https://github.com/tkzic/max8radio

Notes

goals and strategy

The new approach will be to remove most of the device handling code from Max. Instead providing device interfaces from existing device libraries, like soapy-sdr, hamlib, gnu-radio, etc., The Max portion of the project will read IQ files, perform DSP, and other magic.

The first platform will be Max8 in Mac OS Catalina

projects

Max + CubicSDR + hamlib

See working prototype below. This setup uses CubicSDR as a device driver to send IQ data into Max’s input audio stream. CubicSDR supports many devices via soapySDR. It supports networked rig control via Hamlib.

Advantages of this system: It works now. It runs in Windows. It runs over the a local network. The software is managed and distributed by somebody else.

Disadvantages: Its not an elegant solution – ie., not self contained within Max. It requires installation and setup of CubicSDr. The software is managed and distributed by somebody else – so it could stop working at any time.

rx_tools + hamlib

rx_tools is an update of some of the rtl tools, like rtl_fm. It includes soapySDR device support. If hamlib is added to rx_tools, then you could do the same networked frequency control, and IQ streaming as CubicSDR – using rigctld. Without the overhead of running CubicSDR. The downside it that it’s yet another program to maintain and distribute.

Next step: look at source code for rx_tools and estimate scope of hamlib intergration.

openwebrx and websdr API

openwebrx  https://www.openwebrx.de/

Websdr  http://websdr.org/

These sites provide access to SDR devices connected to web servers. Although they don’t stream IQ data, it would be interesting to build a Max front end to the APIS.

background information

See previous posts:

External programs required

  • hamlib (macports)
  • cubicSDR (see link above)
  • netcat (nc) (built into Mac OS terminal)

notes on rigctld commands

Best results using one letter commands with single quotes:

echo 'F 7023000' | nc -w 1 localhost 4532

Prepend ‘+’ for more feedback, like this:

% echo '+F 7023000' | nc -w 1 localhost 4532
set_freq: 7023000
RPRT 0

Latest prototypes

Links to latest working projects (from newest to oldest)

 

First Max test project

This is an update of the test done with CubicSDR and RTLSDR as described here: https://reactivemusic.net/?p=19802

CubicSDR is great but eventually the goal is to pare down the interface between the SDR device and Max. Something like a command line IQ filter would be ideal:  https://github.com/xmikos/simplesoapy

Hardware and system setup

This test uses an Airspy Discovery HF+, but any device supported in CubicSDR should work – that’s the point of this exercise.

Using BlackHole from Existential Audio https://existential.audio/blackhole/

as an alternative to Soundflower to route the IQ (audio stream) data from CubicSDR to Max. You could also use a cable to connect output of one audio device to input of another, etc.,

Signal path:

Antenna -> Airspy -> CubicSDR -> rigctld -> Max

CubicSDR settings

  • Plug in Airspy device before launching CubicSDR, so it will be discovered on the setup screen
  • On the main display, click just to the right of the mode buttons to bring up a drop down menu of audio devices
  • select I/Q mode
  • select the audio device, or “BlackHole 2ch”, that you will use to route audio to Max
  • click on any of the frequency digits, press space, and enter in the same frequency as the Center Frequency (e.g., 7000000)
  • click the ‘V’ to the left of the frequency digits, to select ‘delta lock mode’. This causes the frequency and center frequency to sync.
  • Be careful not to click anywhere in the waterfall window – or this will mess up the sync
  • Under Rig Control menu:
    • Select “Hamlib NET rigctl” as the model
    • Enter localhost:4532 as the control port
    • Select 57600 as the serial rate
    • Make sure that “follow rig” and “floating center” are checked
    • After you get the rigctld daemon started, come back here and ‘Check’ ‘enable rig’. If it doesn’t stay checked, then there is a problem with the connection.
  • Under the Audio sample rate menu, select the correct sample rate for your audio device (e.g. 96k)

Notes: It seems there is some kind of AGC hardwired into CubicSDR.  https://github.com/cjcliffe/CubicSDR/issues/826

TCP and rigctld settings

  • Open a terminal window
  • type: rigctld -m 1 4532 &
  • This starts the server running in the background using the HAMLIB test dummy rig
  • to set frequency to 7.010 MHz, type:

    echo ‘F 7010000’ | nc -w 1 localhost 4532

  • This should change the center frequency and frequency in CubicSDR

Max settings

For this test, you can use any of the MaxSDR tutorials available  at https://github.com/tkzic/max8radio

We’ll be using maxsdr7a.maxpat

ignore the max-console messages about missing externals.

The key is to choose the default audio input device and set it to be the same as what is coming out of CubicSDR.  ie., “BlackHole 2ch”

  • Set the audio input device to match CubicSDR, as described above. Also match the sample rate (e.g., 96k)
  • Set the audio output device to your internal soundcard/speakers
  • Start audio and recall preset 1 or some normal settings for SSB
  • It should be receiving I/Q data now from Cubic SDR
  • Note: may need to flip the I/Q input due to anomaly in CubicSDR.
  • Now load another Max patch to do the frequency control: rigctld1.maxpat

This patch sends frequency data to the rigctld daemon via the [shell] object. You can change the frequency using the number box.

That’s about it for now.

Updating Max/MSP internet sensor projects

Notes for updating from Max6 to Max8 in Mac OS Catalina

In general, 32 bit code will not work

Link to internetsensors project: https://reactivemusic.net/?p=5859

Github: https://github.com/tkzic/internet-sensors

1. mxj object

Need to update, but the Oracle link leads to a dead end message. Go to the Oracle download link https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html but instead of pressing the green download button, <ctrl> click and save the link as described in the instructions from intrepidOlivia in this link https://gist.github.com/wavezhang/ba8425f24a968ec9b2a8619d7c2d86a6

2. aka.objects

I have used aka.shell, and aka.speech – among others. These objects no longer work. Replace with Jeremy Bernstein’s shell object: https://github.com/jeremybernstein/shell/releases/tag/1.0b2

NOTE: There’s a problem with [shell] – it rejects input that is converted to a symbol using [tosymbol].

This can be fixed by using from symbol – or just eliminating [tosymbol] – it make affect the stderr-stdout redirection token, ie., “>” and other special characters but for now [shell] does not accept symbol input

aka.speech can be replaced using the “say” command in the shell.  more details to follow about voice parameters.

‘say’ has similar params to aka.speech, eg., voice name and rate. There are voices for specific languages. This feature could be used, for example, to match the language from a Tweet to an appropriate voice

3. Twitter streaming API

I revised the php code for the Twitter streaming project, to use the coordinates of a corner of the city polygon bounding box. That seems to be more reliable than the geo coordinates which are absent from most Tweets.

There is a new API in the works – but its difficult to decipher the Twitter API docs because they have so many products and the documentation is obtuse.

Also it would be interesting to extract the “language” field and use it to select which voice to use in the speech synthesizer. Or even have an english translation option.

4. Echonest API

Echonest was absorbed into Spotify. The API is gone. But the Spotify API does have some of the feature detection and analysis code. But it doesn’t allow you to submit your own audio clips. There are also some efforts to preserve some of the Echonest stuff like the blog by Paul Lamere, and the remix code. Here are a few links I found to get started.

Spotify API (features) https://developer.spotify.com/console/get-audio-features-track/?id=06AKEBrKUckW0KREUWRnvT

Echonest blog:  https://blog.echonest.com/

Amen – algorithmic remix project:  https://github.com/algorithmic-music-exploration/amen

5. Google speech to text

Several issues:

  • Replacing [aka.shell] with [shell] – instead of using [tosymbol], this workaround seems to help

  • Now have rewritten all of the recording code, and shell interactions with Google.
  • Still need to work on voice options for the ‘say’ command (text to speech)
  • pandorabots API problems turned out that the URL needed to be https instead of http

6. twitter curl project

Looks like xively.com is gone. Maybe purchased by google? Anyway – this project is toast

7. Twitter via Ruby

Got this working again.

8. Bird calls from xeno-canto.com

This patch has been completely re-written. The old API was obsolete. This version uses [dict] and [maxurl] to format and execute the initial query. Then it uses [jit.uldl] to download the mp3 file with the bird-call audio.  Interesting that [maxurl] would not download the file using the “download” URL. It only worked with a URL containing the actual file name.

9. ping

Needed to reinstall ruby gems using xcrun (see above)

seems to be a problem with mashape:

Could not resolve host: igor-zachetly-ping-uin.p.mashape.com (Patron::HostResolutionError)

[mashape was acquired by rapidapi.com – so will need to refactor the code in the ruby server.]

 

Test

Returning after a long long time

For many years this website lived on an Amazon cloud server. Around 2016 the attacks began. Malware and viruses swarmed the site and used it to send bizarre emails. Then the people at Amazon threatened to shut it down if I didn’t do something. I added recommended security features. The attacks continued. Eventually I closed the site to all outside IP addresses. Until today. I found a new hosting platform.