Amateur radio contesting time-lapse map

Mapping geocoded  contest log data using node.js and openlayers.

The goal was to make something that looks like the Reverse Beacon Network map, only for contest log files. I use RBN for testing antennas now. That map display gives you a pretty good idea of your actual antenna pattern.

Code is written in node.js (javascript) and html.

Part 1: Read a Cabrillo log file containing QSO: records. Look up each callsign, get latitude and longitude, and rewrite the file as json data, tagged with geo coordinates. I originally tried getting the data from hamQTH but it was not current, so ended up using the qrz.com xml callsign lookup. For callsigns “not found” I used the qrz.com dxcc prefix lookup to get general coordinates for the country. There are still a few bad/missing data issues to resolve. Like European stations with coordinates at the South Pole.

Part 2: Tried various mapping frameworks – like leaflet, arcgis, and openlayers. Wanted to use a great-circle projection (azimuthal equidistant) like the big ARRL world map. And may still figure this out. But working with map projections and coordinate transforms is way worse than doing a Smith Chart.  I ended up hacking a flight tracking example from openlayers.org and basically replacing airplanes with QSO’s. That is why the lines are animated from source to destination.  Also added a layer for day/night, and QSO/time status display.

It probably makes sense to get rid of the flight animation and just display the entire path in sync with the QSO data – with color code for each band (K1KP) – and speed control on the time lapse, etc., So you can get a better sense of rate and propagation.

It would be cool to have a website where you could upload a log file and generate maps.

Note: this project is not yet available

Files

local files:

generating data:

internetsensors/cabrillomap

put the cabrillo data in testdata.cbr (use QSO: records only for now) should be sorted chronologically.

run:  node index.js

the output file will be: geocab.json (which is used as input to the mapping program)

mapping

internetsensors/oltest

main.js = node source with ol mapping and data processing

index.html = web page for map

geocab.json = geocoded cabrillo json test data

to run, type: npm start

Then open: http://localhost:5173/ in a browser

Additional work / current issues

Some of the qrz.com callsign data has bad geo coordinates. In particular some of the records show a latitude of -89 and longitute -179 – need to check for these numbers and replace with dxcc coordinates.

There should be an argument on the node program to pass in the datafile. Also the program should clean up any non QSO: records, like the file header info and any X-QSO recs.

Also need to clean up the async/await stuff – currently there are several methods for handling state transitions.

mapping ideas:

As mentioned above, its probably a good idea to make a version of the code without the flight animation, and have various controls to stop/start the data playback to look at individual qso’s do speed control, etc.,

azimuthal equidistant projection: there are some links to examples in leaflet, and arcgis to handle complex projections. In documents, look at:  “map links for projection stuff.txt”

leaflet test version:

in the internetsensors/cabrillomap folder there’s a test file: cbworld1.html that works using websockets when you run the index.js file to generate test data. It uses a leaflet map, but the lines don’t adapt to great circle polar paths.

arcgis

I believe the arcgis examples are in internetsensors/projected geometries

And: internetsensors/pe-gs-projection

The former is a a very nice world projection with some point markers. The latter is an example that shows how to switch out various projections in realtime.

MBTA API in Max

Sonification of Mass Ave buses, from Nubian to Harvard.

Updated for Max8 and Catalina

This patch requests data from MBTA API to get the current location of buses – using the Max js object. Latitude and Longitude data is mapped to oscillator pitch. Data is polled every 10 seconds, but it seems like the results might be more interesting to poll at a slower rate, because the updates don’t seem that frequent. And buses tend to stop a lot.

Original project link from 2014: https://reactivemusic.net/?p=17524

MBTA developer website: https://www.mbta.com/developers

This project uses version 3 of the API. There are quality issues with the realtime data. For example, there are bus stops not associated with the route. The direction_id and stop_sequence data from the buses is often wrong. Also, buses that are not in service are not removed from the vehicle list or indicated as such.

The patch uses a [multislider] object to graph the position of the buses along the route – but due to the data problems described above, the positions don’t always reflect the current latitude/longitude coordinates or the bus stop name.

download

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

folder: mbta

patches:

  • mbta.maxpat
  • mbta.js
  • poly-oscillator.maxpat
authentication

You will need  to replace the API key in the message object at the top of the patch with your own key. Or you can probably just remove it. The key distributed with the patch is fake. You can request your own developer API key from MBTA. It’s free.

instructions
  • Open mbta.maxpat
  • Open the Max console window so you can see what’s happening with the data
  • click on the yellow [getstops] message to get the current bus stop data
  • Toggle the metro (at the top of the patch) to start polling
  • Turn on the audio (click speaker icon) and turn up the gain

Note: there will be more buses running during rush hours in Boston.  Try experimenting with the polling rate and ramp length in the poly-oscillator patch. Also, you can experiment with the pitch range.

Spotify segment analysis player in Max

Echo Nest API audio analysis data is now provided by Spotify. This project is part of the internet-sensors project: https://reactivemusic.net/?p=5859

There is an older version here using the discontinued Echo Nest API: https://reactivemusic.net/?p=6296

Note:  Last tested 2024/01/21

The original analyzer document by Tristan Jehan can be found here (for the time being):  https://web.archive.org/web/20160528174915/http://developer.echonest.com/docs/v4/_static/AnalyzeDocumentation.pdf

This implementation uses node.js for Max instead of Ruby to access the API. You will need set up a developer account with Spotify and request API credentials. See below.

Other than that, the synthesis code in Max has not changed.  Some of the following background information and video is from the original version. ..

What if you used that data to reconstruct music by driving a sequencer in Max? The analysis is a series of time based quanta called segments. Each segment provides information about timing, timbre, and pitch – roughly corresponding to rhythm, harmony, and melody.

spotify-synth1.maxpat

download

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

folder: spotify2

files

main Max patch
  • spotify-synth1.maxpat
abstractions and other files
  • polyvoice-sine.maxpat
  • polyvoice2.maxpat
node.js code
  • spot1.js
node folders and infrastructure
  • /node_modules
  • package-lock.json
  • package.json
dependencies:
  • You will need to install node.js
  • the node package manager will do the rest – see below.

Note: Your best bet is to just download the repository, leave everything in place, and run it from the existing folder

authentication

You will need to sign up for a developer account at Spotify and get an API key. https://developer.spotify.com/documentation/general/guides/authorization-guide/

Edit spot1.js replacing the cliendID and clientSecret with your spotify credentials

node for max install instructions (first time only)

  •  Open the Max patch: spotify-synth1.maxpat
  •  Scroll the patch over to the far right side until you see this green panel:

  • Click the [script npm init] message – this initializes the node infrastructure in the current folder
  • Then click each of the 2 script npm install messages –  this installs the necessary libraries

Instructions

  •  Open the Max patch: spotify-synth1.maxpat
  •  Click the green [script start] message
  • Click the Speaker icon to start audio
  • Click the first dot in the preset object to set the mixer settings to something reasonable
  • open the Max Console window so you can see the Spotify API data
  • From the 2 menus at the top of the screen select an Artist and Title that match, for example: Albert Ayler and “Witches and Devils”
  • Click the [analyze] button – the console window should fill with interest data about your selection.
  • Click [play]
  • Note: if you hear a lot of clicks and pops, reduce the audio sample rate to 44.1 KHz.
Alternative search method:

Enter an Artist and Song title for analysis, in the text boxes. Then press the buttons for title and artist. Then press the /analyze button. If it works you will get prompts from the terminal window, the Max window, and you should see the time in seconds in upper right corner of the patch.

troubleshooting

If there are problems with the analysis, its most likely due to one of the following:

  • artist or title spelled incorrectly
  • song is not available
  • song is too long
  • API is busy
Mixer controls

The Mixer channels from Left to right are:

  • bass
  • synth (left)
  • synth (right)
  • random octave synth
  • timbre synth
  • master volume
  • gain trim
  • HPF cutoff frequency
You can also adjust the reverb decay time and the playback rate. Normal playback rate is 1.

programming notes

Best results happen with slow abstract material, like the Miles (Wayne Shorter) piece above. The bass is not really happening. Lines all sound pretty much the same. I’m thinking it might be possible to derive a bass line from the pitch data by doing a chordal analysis of the analysis.

Here are screenshots of the Max sub-patches (the main screen is in the video above)

Timbre (percussion synth) – plays filtered noise:

Random octave synth:

Here’s a Coltrane piece, using roughly the same configuration but with sine oscillators for everything:

There are issues with clicks on the envelopes and the patch is kind of a mess but it plays!

Several modules respond to the API data:

  • tone synthesiszer (pitch data)
  • harmonic (random octave) synthesizer (pitch data)
  • filtered noise (timbre data)
  • bass synthesizer (key and mode data)
  • envelope generator (loudness data)

Since the key/mode data is global for the track, bass notes are probable guesses. This method doesn’t work for material with strong root motion or a variety of harmonic content. It’s essentially the same approach I use when asked to play bass at an open mic night.

additional notes

Now that this project is running again. I plan to write additional synthesizers that follow more of the spirit of the data. For example, distinguishing strong pitches from noise.

Also would like to make use of  the [section] data as well as the rhythmic analysis. There is an amazing amount of potential here.

Generic SDR realtime IQ converter

With CubicSDR, HAMLIB, and Max

update: 1/25/2021 – Using this general setup with Airspy, CubicSDR, rigctld, and netcat (nc) to send IQ data into the basicSDR3.maxpat patch


CubicSDR uses the SoapySDR library as generic tool for extracting realtime IQ data streams from common SDR devices. It also provides TCP external frequency control using HAMLIB.

http://cubicsdr.com/

Although its not the main purpose of CubicSDR, the IQ streaming capability will connect SDR devices to Max, Pd, and other DSP platforms, to build experimental radios. All without building external objects or hardware device drivers.  The convenience of using CubicSDR for this purpose far outweighs the overhead.

A prototype with Max and rtl_sdr

How to use CubicSDR as a front-end for SDR experiments in Max.

The signal path for this test is:

  1. antenna
  2. NooElec HAM IT UP upconverter
  3. rtl-sdr dongle
  4. CubicSDR
  5. Soundflower (or a “loop-backed” external audio device)
  6. Max

Running in the other direction, the frequency control path is:

  1. netcat running in Mac OS X terminal (or a Max patch that sends TCP)
  2. rigctld (hamlib TCP server)
  3. CubicSDR
  4. rtl-sdr dongle

There’s a lot of stuff going on here, so the choice to use hardware audio routing instead of Soundflower and netcat instead of TCP in Max, is an effort toward simplicity.

CubicSDR settings:

  • Plug in the rtl-sdr 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 Soundflower, that you will use to route audio to Max
  • If using an upconverter, set the ‘frequency offset’ in the settings menu (e.g. -125000000)
  • 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
    • ‘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)

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/maxradio but I chose to use the main program, currently maxsdr7a.maxpat. The key is to choose the default audio input device and set it to be the same as what is coming out of CubicSDR.  I used a stereo patch cord to connect the line output of my Apollo Twin interface to the input jacks – but you can also use Soundflower.

  • 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
  • You may need to toggle the flip IQ button
  • Start audio and recall preset 1 or some normal settings for SSB
  • It should be receiving I/Q data now from Cubic SDR

Links:

Installing Hamlib: https://reactivemusic.net/?p=19402

Installing CubicSDR: https://github.com/cjcliffe/CubicSDR/releases

Supported SDR devices: https://reactivemusic.net/?p=19746

Notes:

I had some success using the Max TCP external described at the Installing Hamlib link above, but temporarily abandoned it due to some latency and dropouts.

Local version of this patch is: tcpClient-small2.maxpat

Next steps:

  • hardware (i.e., MIDI controller) control of frequency – and refinement of Max TCP patch. Can likely re-use the patch from the remote radio project.
  • Convert to PD : TCP/IP code is builtin
  • Consider forking CubicSDR and adding direct MIDI/OSC control of UI.

Black on white with Max 7

Making Max 7 look like 6.

What’s this about?

The UI in Max 7 reverses foreground and background from previous versions of Max (and Pd).  Additionally,  a secondary toolbar menu frames the patcher and all sub-patchers. For example, here is a simple Max 6 patch and its Max 7 equivalent.

Max 6:

Max 7:

Regardless of which look you find more appealing, the new UI is problematic in several ways.

  • Light text on dark background can be difficult (blurry)  for people with vision impairment – given the same font size and screen brightness.
  • Patches created in previous versions of Max lose their original design.
  • Larger objects and toolbar frames consume more screen space.
  • If you like to sketch ideas with pencil – an empty white patcher screen is like paper.

Max 7 doesn’t include a black-on-white style, but you can make your own. And lose the toolbar. Here is a new and improved version of the patch:

Making a new style

The process is arcane. But it took less than a half hour to get results. Then I wasted time endlessly tweaking.

The secret recipe came from a 2014 Cycling 74 forum post by Phiol, with assistance from Ben Bracken. Everything you need to know is explained in Phiol’s first 2 posts in the thread. https://cycling74.com/forums/topic/custom-color-scheme-layout-setup-walkthrough/#.V6oHMZMrIcg

I encourage you to read both posts and follow the steps precisely. There are no shortcuts. I will paraphrase Phiol’s method here:

  1. In a default patcher, make a bunch of objects and then in the Format Palette (object inspector) change them to whatever colors you want
  2. Select all the objects in the patcher
  3. In the Format palette, make a new style – this style will be for multiple objects
  4. Select the patcher to activate it in the Format palette
  5. In the Style menu (located in the patcher inspector window), select the style you just made, applying it to the patcher level
  6. Delete all of the objects in the patcher
  7. Save a new template (in dropdown file menu “create template”) and make it your default.

And then the bad news:

Step 1. is important.
  • You must start from a blank “Default Patcher Template” and choose “Default Max7”
  • You cannot copy/paste objects that you had already done your custom colors. You will have to start from scratch. one by one.
  • In the inspector window, make sure the “Appearance style” has nothing selected in it’s umenu

Then do all the steps mentioned in the previous thread.

The Glitch/bug:

-Gradients objects do not work.
For example, [message and umenu] would not keep my custom colors.

Workaround: Once you have started a new patch, reselect your “custom_style” in patch inspector window or the ‘format’ sub menu. That is, click the style that should already be selected/checked – and now it should work.

So yes, for now, as we start a new patch we will we have to make it a habit to always select our “custom_style” in patcher inspector window or the format sub-menu.

patcher inspector window

format submenu

(click the paintbucket icon on the top toolbar)

 

Copy style to library

Also, when you open older Max6 patches and/or the help patch and want to apply your new custom style template, make sure that in the “Format” dropdown menu you have selected the “copy style to library”.

Loading Max 6 patches

Once you’ve done this, you will be able to apply you’re custom style to older/help patchers and resave them with your custom look. To do so, you open Inpector’s Appearance again, and select your “custom_style” that will be in the Library style.

Walking through the process of step one

If you are totally confused at this point, so was I.

Starting with step one above,  make a patch with common objects, that looks something like this:

Select each object individually, then with inspector, change the background color to white, or a lighter shade, and the text color to black.

You may need to experiment. Try with a small number of objects at first – because you will probably need to do the whole process several times. As noted above, you have start from the begining  each time by hand. You can’t modify a style after you save it.

Then, you should be able to follow the rest of the steps from Phiol’s post.

The objects used for this style are:

  • umenu*
  • button
  • dial
  • toggle
  • generic object
  • textedit
  • slider
  • message*

*these objects use gradients

Making a white patcher background

  • open a blank patcher
  • ctrl click on the background and select “Inspector Window”.
  • Change the unlocked and locked background colors to white.
  • Then, from the File menu, select ‘create template’ and give it the same name as the template you selected in step 7 above (and make sure to check ‘default for new patchers’)

Getting rid of the tool bar frame

The procedure is basically the same as setting the white background.

  • In a blankpatcher, open the inspector window and uncheck ‘show toolbar on open’.
  •  Then, from the File menu, select ‘create template’ and give it the same name as the template you selected in step 7 above (and make sure to check ‘default for new patchers’)

Note: you can toggle the toolbar anytime with <cmd>8

 If subpatchers  still have the default look

If you create a subpatch and it reverts back to the default style then…

  • In a blank patcher, open the inspector window and set the subpatcher template to your new tempate created in step 7 above.
  •  Then, from the File menu, select ‘create template’ and give it the same name as the template you selected in step 7 above (and make sure to check ‘default for new patchers’)

More about styles and templates in Max 7

Check out the Cycling 74 vignettes about styles and templates to get a better understanding of what’s going on here:

https://docs.cycling74.com/max7/vignettes/styles

https://docs.cycling74.com/max7/vignettes/templates

SDR Panadpter, logger, and skimmer

With a TenTec Eagle transceiver, Managed by N4PY software.

n4py-diagram

http://www.n4py.com/

N4PY acts as router, distributing CAT commands to other applications.

The applications are connected using virtual serial port bridge pairs. For each of the applications, N4PY emulates a K3 transceiver on one side of the bridge.

  • Panadapter: NAP3
  • Logger: N1MM
  • CW Skimmer

The CW keyer is a K1EL Winkeyer USB controlled solely by the N1MM logger.

The routing of IQ signals from LP-PAN2 SDR is done through a MOTU 828 mk3 interface, simply to be able to split the signal so that both NAP3 and CW Skimmer can use it.

CW Skimmer gets the IQ signal directly from the MOTU. NAP3 doesn’t not recognize multiple ports on soundcards. So one end of the split from the MOTU is sent through another audio interface (Focusrite 2I2). NAP3 uses the 2I2 as an input device.

LP-PAN frequency adjustments

Notes on configuration for correct zero-beating.

When setting the Eagle BW or PBT, the IF will shift in frequency, so the numbers below assume a centered PBT and a BW of 700.

The sidetone pitch is 523 Hz.

Settings may also depend on which roofing filters are installed in the Eagle.

NAP3 settings

Set the global offset to -8200. Leave everything else at 0.

CW Skimmer settings
  • CW pitch: 523
  • Audio IF: -7520
  • Sample rate: 96 kHz
  • Hardware: SoftRock-IF

This post is about ham radio.

SQLite database for remote radio in Max

under construction…

Max/MSP features a full implementation of SQLite using the js (javascript) object. Here we describe a database to track radio frequencies. Frequencies are stored by time, type, and mode. The frequencies can be retrieved in various ways, like with a scanner radio.

Tables can be created and maintained outside of Max using the command line (sqlite3) or database apps like SQLiteStudio.

Max patches:

(not yet available on github:

  • freqdb4.maxpat (database UI)
  • swBase3.js (SQLite code)
  • lp_radio2.maxpate (Launchpad)

DB structure:

The database is called newtestDB1

tables:

You can see the table schema in the screenshots. The tables were created using command line sqlite3 and SQLiteStudio.

freq table:

One record for each stored frequency. This table retains its state from each previous use, but new records can be added using the Max patch, or the Launchpad.

Screen Shot 2016-04-05 at 11.00.31 PM

xtime: Timestamp in UTC.

frequency: Hz.
mode:

  • usb: 0
  • lsb 1
  • cw 2
  • am 3
  • fm 4

filter: bandpass filter setting in Hz. (default is 6000)

typecodes:

0 : unknown
1 : AM/SW broadcast
2 : clock
3 : digital mode
4 : local broadcast
5 : mostly noise

zone: cq zone number

rating: 0-5 (0 = unrated)

confidence: 0-5 (0 = unknown)

tags: (general text notes)

preset table:

The preset table contains one record for each 8×8 launchpad button, for each of 3 screens.

  • screen 0: fixed presets (red) (static and persistent)
  • screen 1: time presets (green) (rebuilt with each time query)
  • screen 2: user presets (yellow) (persistent but can be modified using the Launchpad)

Data from each of theses screens is also displayed in jit.cellblock objects in the Max patch. All of the fields correspond to the fields in the freq table – except for screen, row, and col which are locators for the launchpad.

Screen Shot 2016-04-05 at 11.11.08 PM

Using the database

Launchpad presets

There are three screens of presets color coded using the Launchpad mixer button (upper right). Press it to cycle through the 3 screens.

0 fixed presets (red)

The fixed presets are static. But can be changed using SQLiteStudio. They contain commonly used radio frequencies, like the SW, Ham, and CB bands. And clock stations.

To select a preset, press its button on the Launchpad.

Currently assigned presets:

Screen Shot 2016-04-05 at 11.39.12 PM

1 Time Presets (green)

Time presets are frequencies with Timestamps that match a selected range. For example, every frequency within one hour of the current time. These can be selected with a query in the Max patch, or using default values from the Launchpad. The query will randomly match up to 64 records. If the query returns less than 64 records, you will get all matching records, but in random order.

From the Max patch:

Match hours plus/minus current time (0-12).

Type the number of hours in the number box and press the button under the delay object. This reloads the presets.

Screen Shot 2016-04-05 at 11.36.35 PM

You can view the results in the jit.cellblock:

Screen Shot 2016-04-05 at 11.39.07 PM

 

Match a specific time range:

Enter the start/end times and press the button.

Screen Shot 2016-04-05 at 11.40.51 PM

 

Selecting from launchpad

trk button: re-runs query using last set number of hours plus/minus current time. Default is one.

solo button: select one random preset using current hour range, and play it?

 

User Presets (yellow)

The user presets work like the pushbuttons on a car radio. Press to select. Hold to save the currently tuned radio frequency.

The learn button (upper left) gives feedback. If you press a pad for which no frequency has been assigned, the learn button will flash red. When you save a new preset, the learn button flashes green to indicated that the saving is done. If you press a pad for a preset that has already been saved, there will be no flash, but the radio frequency will change.

Adding new frequency records

You can add records using the Max patch or the Launchpad, or from SQLiteStudio.

Adding records from Max:

Tunning the radio fills in all of the fields except for typecode. Tune the radio. Then press one of the typecode buttons. Then press the big green button. You have added a new record.

Screen Shot 2016-04-05 at 11.55.57 PM

 

Adding records with Launchpad:

Press the Arm button (lower right) to add a record for the currently tuned frequency, using an ‘unknown typecode’

Adding records from SQLiteStudio

Just do it.