Opulent Voice Protocol Development

Opulent Voice is an open source high bitrate digital voice (and chat, and data!) protocol developed by ORI. It’s designed as the native digital uplink protocol for ORI’s broadband microwave digital satellite transponder project. Opulent Voice (OPV) is good for both space and terrestrial use.

Locutus

The focus of most of the recent work has been on the minimum shift keying (MSK) modem, called Locutus. The target hardware for implementation is the PLUTO SDR from Analog Devices. See 

https://github.com/OpenResearchInstitute/pluto_msk for source code, documentation, and installation instructions.

The modem in an excellent “rough draft” state. There are positive results in over-the-air testing.

Interlocutor: The Human-Radio Interface

Interlocutor is the part of the design that takes input audio, text, and keyboard chat from the operator and processes this data into frames for the modem.

Current Interlocutor code can be found at

 https://github.com/OpenResearchInstitute/interlocutor

Interlocutor also handles received audio, text, and data. The target hardware for this part of the design is a Raspberry Pi version 4, with expectations that it will run on other Python-capable and/or Linux-based devices. 

What’s Happened Since Our May 2025 Updates?

What were the “Next Steps” from last month? We intended to take the functional Opulent Voice framing, which successfully delivered Opus packets, and insert COBS, RTP, UDP, and IP layers in order to gain a substantial increase in functionality. All of that has happened. The stream of Opulent Voice frames are much more functional and can be handled by a very large number of existing applications. The additional overhead was well worth the investment of complexity and latency. 

What Else is New?

We implemented configuration files. This is a YAML file that stores settings for the radio.

A configuration manager codebase was added to handle config file tasks.

We implemented audio hardware configuration files. This is a YAML file that stores settings for the audio hardware choices made by the operator.

We implemented an audio hardware manager. The audio hardware manager helps the operator test, list, and save audio hardware configurations. A microphone gain measurement and speaker test are included.

We wrote an automated test suite. It has four phases, with multiple tests per phase. As development proceeds, we can easily test if any code changes damage previously achieved functionality. If it’s in the test suite, then it needs to still be working regardless of anything we add to the codebase. This helps ensure a quality product moving forward.

Automated Test Suite Overview

Phase 1: Basic Operations

    run_test “help_display”

    run_test “version_info”

    run_test “no_callsign”

    run_test “invalid_callsign”


Phase 2: Command Line Options

    run_test “audio_help_options”

    run_test “list_audio_exits_clean”

    run_test “test_audio_exits_clean”

    run_test “setup_audio_handles_eof”


Phase 3: Network Configuration

    run_test “custom_ip”

    run_test “custom_port”

    run_test “invalid_ip_accepted”

    run_test “invalid_port”


Phase 4: Operating Modes

    run_test “chat_only_mode”

    run_test “verbose_mode”

    run_test “quiet_mode”


Phase 5: Configuration File Handling

    run_test “no_config_files”

    run_test “partial_config”

    run_test “corrupted_config”

    run_test “good_config_loaded”

    run_test “cli_overrides_config”

Next Steps?

If the Opus encoder does a good enough job of detecting when the speaker is silent, we can take advantage of those silence frames to send (fragments of) waiting control, text, or data packets. This would be useful mainly if we are also multiplexing multiple streams with an advance variant of COBS.

We have an ongoing discussion on how to deal with the potential problem of getting out-of-order frames, which may happen when we use Interlocutor with a remote computer network, or with a modem that is (significantly) remote.

An out-of-order Opulent Voice frame problem isn’t expected to occur over the radio link. Packets either get through or they don’t, but never out of order, because they are always transmitted in order and there’s no mechanism to retry transmitting them later. This assumes that the modem is located close to Interlocutor.

So the problem can only occur if we try to use this radio link protocol as a network (transport) protocol, which can introduce complications like out of order delivery. This happens when we’re communicating to another computer with Interlocutor software, over the Internet. Which, we expect people might want to do.

The obvious solution here is to use TCP, which is designed as a transport protocol. TCP can turn a channel that delivers packets unreliably and possibly out of order into a channel that never does either of those things. Bytes always arrive perfectly correct and perfectly in order, or else the link fails.

So where we are using just UDP to encapsulate our OPV frames on a short wire between the host and the modem, we would probably want to use TCP on a network link if we for some reason wanted to remote the modem over a network. 

Since we already have a configuration item for “computer” or “modem”, then we have a way to distinguish between the two modes. The difference between the two modes right now in the code is that selecting “computer” means a KEEPALIVE signal is sent as a control channel message. The KEEPALIVE is not sent when Interlocutor is configured as being connected to a “modem”. We could use TCP in computer and UDP in modem. Discussions on this will continue! 

Voice detection or VOX? Live voice-to-text transcripts? Smart QSO logging? 

Want to Help?

If you would like to help make these and the many other things that we do happen more quickly or better, then you are welcome at ORI!

Read over our code of conduct and developer and participant policies on our website at https://www.openresearch.institute/developer-and-participant-policies/, and then visit our getting started page at https://www.openresearch.institute/getting-started/

Leave a Reply

Your email address will not be published. Required fields are marked *