Walkthrough¶
Every output shape on this page was captured from a Quad Cortex running CorOS 4.0.1. Device identifiers, build hashes and owner-specific preset names are fictionalised for publication.
Preset names and identifiers are fictional
The preset names, serial number, MAC address, and firmware checksum shown here are invented stand-ins. A real serial identifies one person's hardware, and real preset names say what they play - neither belongs in public documentation. Everything structural is genuine.
Model names such as Brit 2203 and Rodent Drive are not invented: those come from Neural DSP's catalog and are identical on every unit.
Talk to the device¶
device_type QC
custom_name Neural DSP Quad Cortex
serial_number QA00AB123
coros_version 4.0.1
app_firmware d14e
bootloader_firmware d119
zencoder_app d111
zencoder_bootloader d10d
wireless_fw_checksum 0123456789abcdef0123456789abcdef
linux_kernel Linux buildroot 4.0.0-ADI-1.3.0 #1 PREEMPT ... armv7l (none)
uboot U-Boot 2015.01 ADI-1.3.0 (Sep 30 2021 - 01:01:44)
mac_address 02:00:5e:10:00:01
The direct fallback for device version needs no full handshake, which makes it the right first command. If a held session is already running, the command correctly uses its cached identity instead of opening a second HID connection.
Two field names are the vendor's, and both are wrong
coros_version is carried in a schema field Neural DSP named zenos_git_hash, and it holds 4.0.1 rather than a hash. wireless_fw_checksum is carried in one they named zenwireless_fw_version, and it holds a 32-character checksum rather than a version. We verified by decoding raw field numbers off the wire; the fields are not swapped, each simply holds something its name does not describe. We rename them in output and record the originals. See the protocol.
Check everything works¶
connect handshake:
resetting comms buffers ...
reading and announcing versions ...
requesting model catalog ...
announcing connection ...
subscribing to device state ...
settling ...
done (3.8s)
active_scene ... ok
read_current_preset ... ok
list_presets ... ok (11 occupied)
active_scene: 0
current_preset: Plexi Sunrise
preset_count: 11
1A Plexi Sunrise
1B Tweed Porchlight
...
With no daemon, probe performs a subscribed handshake and exercises the core scene/current-preset/preset-list reads. With a held session, it exercises those reads through the existing owner and does not disconnect it.
If the handshake seems to hang
A healthy handshake is consistently a few seconds. A large or variable delay is a client-side fault until a wire trace proves otherwise; the two known causes were the RX loop starving its own writer and an unpaced request burst queueing work against the catalog transfer.
cortex waits for the catalog before subscribing, then waits for the non-heartbeat push burst to settle. Progress is printed at each step. If it pauses for tens of seconds, trace our client with s/usb-trace rather than treating that as normal device behaviour.
Browse presets¶
1A Plexi Sunrise
1B Tweed Porchlight
1C Cathedral Clean
1D Northern Chime
1E Velvet Hammer
1F Slapback Diner
1G Winter Rotary
1H Desert Two-Lane
2A Glasshouse Lead
2C Bramble Fuzz
2E Low Tide
Slots are named as the unit labels them: bank 1-32 then letter A-H. Empty slots are hidden; --include-empty shows the full 256-slot map, which is how to find a free one.
The factory library is just another setlist:
cortex setlist list shows occupied folders by default. Use --show-empty to include every folder the device reports, which can be several hundred.
Explore the model catalog¶
This is the fun one. The catalog comes from the device, so it reflects installed block types rather than a hard-coded factory table. Its Neural Capture entries are block types, not individual captures; capture inventory comes from separate File listings.
models: 533
with_attribution: 318
categories: 31
13 Bass Amplifier
111 Guitar Amplifier
36 Guitar Overdrive
26 Reverb
...
Search by name or by the gear it evokes:
9 Brit Blues Guitar Overdrive [Based on Marshall® BluesBreaker®]
11 Brit Governor Guitar Overdrive [Based on Marshall® Guv'nor®]
1001 Brit 2203 Guitar Amplifier [Based on Marshall® JCM800®]
1038 Brit TM45 Normal Guitar Amplifier [Based on Marshall® JTM 45® - Normal Channel]
1041 Brit 900 Clean Guitar Amplifier [Based on Marshall® JCM900® 4100 - Clean]
That attribution is Neural DSP's own
The Based on ... text is not ours. The device's catalog carries a tm field holding Neural DSP's own carefully-worded attribution, on 318 of 533 models. We reproduce it verbatim and never paraphrase it - it concerns other companies' trademarks and their wording is both more accurate and more appropriate than anything we would write.
Look at one model in full:
id: 1001
name: Brit 2203
category: Guitar Amplifier
attribution: Based on Marshall® JCM800®
parameters: 7
0 GAIN float 0..10
1 BASS float 0..10
2 MID float 0..10
3 TREBLE float 0..10
4 MASTER float 0..10
5 PRESENCE float 0..10
6 OUTPUT float -60..12 dB
Those indices are what the wire uses. You rarely need them - set-param takes names - but this is where to look when you do.
Work offline
cortex catalog --dump ~/qc-catalog.bin # once, with the device
cortex catalog --from-file ~/qc-catalog.bin --search vox
Saves the 47 KB payload so you can browse without tying up the unit or paying a handshake.
Look at a preset¶
slot: 1A
name: Plexi Sunrise
chains: 4
row 0 (screen row 1):
col 0: Opto Comp (M) (Compressor)
col 1: Rodent Drive (Guitar Overdrive) [Based on ProCo® Rat®]
col 2: Studio Capture (Neural Capture)
col 3: Graphic-9 (Equalizer)
col 4: Adaptive Gate (Utility)
row 1 (screen row 2):
row 2 (screen row 3):
col 1: Slapback Delay (M) (Delay)
col 2: Tape Delay (ST) (Delay)
col 3: Tremolo (Modulation)
col 6: Spring Reverb Engine (ST) (Reverb)
row 3 (screen row 4):
col 1: Legendary 87 (M) (Compressor) [Based on Universal Audio® 1176®]
col 2: Parametric-8 (Equalizer)
col 5: Room (Reverb)
preset show --slot recalls the slot
There is no side-effect-free way to read a stored preset: the device only emits one when it recalls it. So this changes what is loaded and what you hear, and discards any unsaved edit.
To inspect what is loaded right now without disturbing it, use cortex grid show.
Scene labels, colours, copy and swap are working-copy edits. On the unit they live in Gig View: enter SCENE mode, swipe up from the bottom, select a scene, then use EDIT SCENE, COPY SCENE or SWAP SCENE. The CLI exposes the same operations directly:
cortex scene label --index 0 --label "Focused"
cortex scene color --index 0 --color '#22AA66'
cortex scene copy --from 0 --to 4
cortex scene swap --first 1 --second 3
cortex grid show
Indices are zero-based: 0 is A and 7 is H. Copy and swap move the scene label and colour with its parameter and bypass state. None of these changes persist until the working grid is saved.
Edit the grid¶
If you intend to save the result, start a held session and prepare the destination before editing. Preparation recalls and backs up the target, so doing it afterwards would discard the grid you meant to save:
cortex session start
SAVE_TOKEN=$(cortex preset prepare-save --slot 31A --format json | jq -r '.token')
Rows are given as the unit labels them, 1-4.
cortex block set --row 2 --column 0 --model 1
cortex block param --row 2 --column 0 --param GAIN --value 0.9
cortex grid show --params
row 1 (screen row 2):
col 0: Myth Drive (Guitar Overdrive) [Based on Klon® Centaur®]
0 GAIN 0.9
1 TREBLE 0.5
2 LEVEL 0.5
Parameters are addressed by name, resolved through the catalog by reading which model is actually in that cell. Get the name wrong and it tells you the real ones:
You can also give a value in the parameter's own units:
Edits remain a working copy until committed
Every grid edit lives on the working grid until you save or recall another preset. A recall discards the edits. To keep them, explicitly commit the destination token you reviewed before editing:
block set verifies. A block that does not fit the preset's DSP budget is accepted on the wire and simply is not there afterwards, with no error of any kind. So cortex uses the device's echo as a fast path and reads the grid back when no echo arrives; it reports BlockRefused only when the grid confirms that the block is absent.
Machine-readable output¶
Ordinary result-producing device commands support --format json:
cortex preset list --format json | jq -r '.[] | "\(.slot) \(.name)"'
cortex catalog --model 1001 --format json | jq '.parameters[] | select(.read_only | not)'
Progress and warnings always go to stderr, so stdout stays clean for piping even though the handshake prints six progress lines.
When something is wrong¶
With no held daemon, that traces the direct probe. To trace commands routed through a held session, stop the background daemon and run CORTEX_TRACE=1 cortex session start --foreground in a separate terminal. Traces contain device data; sanitise them before sharing and never commit raw captures.