Fox Red Labs / Builds / Audio
Audio and video codecs on a LaunchPad
Pick a codec, build it for the board, flash it and compare every frame with a Mac build. LC3, Opus, MP3 and Plaits run on the MSPM33 C321A, and H.264 on it and the AM13E230.
HardNo wiring
Parts and steps
Which version
You need
- LP-MSPM33C321A LaunchPad development kit runs the codec and times it with its cycle counter
Build the Mac reference.TERMINAL
Build the strict and fast-math references with a per-frame CRC for each frame.
cd ports/lc3 host/build.shYou should see: The Mac references are built under
ports/lc3/results/host.Build the board image.TERMINAL
Build at -O2 with the float unit on and strict arithmetic. Nothing is flashed.
target-m33/build.sh O2 hard strictYou should see: The script ends with
built .../lc3.outand a size line.Flash the board and compare.TERMINAL
Flash the image, wait for the finished flag, read the results back over the probe and compare every checksum with the Mac reference. It prints cycles, the share of real time and the stack use. It plays no sound and drives no pin.
Replace <probe serial> and <path of lc3.out> before you run this.
cd ../.. PROBE=<probe serial> python3 ports/lc3/run_board.py <path of lc3.out>You should see: The CRCs match and the printed shares are about 12, 16 and 24 percent for encoding at 16, 24 and 48 kHz.
You need
- LP-MSPM33C321A LaunchPad development kit runs the codec and times it with its cycle counter
Build the Mac references.TERMINAL
Build the stock and the 32-bit-macro references with a CRC for each frame.
cd ports/opus INT64=0 host/build.shYou should see: The references are built under
ports/opus/results/host.Build the fixed-point image.TERMINAL
Build at -Os. Nothing is flashed.
target-m33/build.sh fixed OsYou should see: The script ends with
built .../opus.outand a size line.Flash the board and compare.TERMINAL
Flash the image, wait for the finished flag, read the results back over the probe and compare every checksum with the Mac reference. It prints cycles and the share of real time for each configuration. It plays no sound and drives no pin.
Replace <probe serial> and <path of opus.out> before you run this.
cd ../.. PROBE=<probe serial> python3 ports/opus/run_board.py <path of opus.out> fixed --ref fixed32You should see: Every packet and decoded block CRC matches the 32-bit-macro reference.
You need
- LP-MSPM33C321A LaunchPad development kit runs the codec and times it with its cycle counter
- LP-MSPM0G3519 LaunchPad development kit the Cortex-M0+ run, with no float unit
Check the Mac side.TERMINAL
Build the references, decode both clips and compare them with the SSE build and ffmpeg.
cd ports/minimp3 tests/check_host.shYou should see: The check ends with the clips matching.
Build the Cortex-M33 image.TERMINAL
Build at -O2 with the hardware float unit. Nothing is flashed.
target-m33/build.sh O2 hardYou should see: The script ends with
built .../mp3.out; flash is 153.4 kB.Flash the board and compare.TERMINAL
Flash the image, wait for the finished flag, read the results back over the probe and compare every checksum with the Mac reference. The stereo clip reads 0.151 and the mono clip 0.109 times real time. It plays no sound and drives no pin.
Replace <probe serial> and <path of mp3.out> before you run this.
cd ../.. PROBE=<probe serial> python3 ports/minimp3/run_board.py <path of mp3.out>You should see: Every frame checksum matches, 194 of 194 per clip.
Run it on the Cortex-M0+.TERMINAL
Build the soft-float image with
arm-none-eabi-gcc, then flash the MSPM0 G3519, wait and compare. It takes about 2 minutes.Replace <gnu arm bin>, <dir> and <probe serial> before you run this.
PATH=<gnu arm bin>:$PATH OUT=<dir> ports/minimp3/target-g3519/build.sh -O2 PROBE=<probe serial> python3 ports/minimp3/run_board_g3519.py <dir>/mp3.elfYou should see: The stereo clip reads 9.84 and the mono clip 7.38 times real time, with every frame checksum equal.
You need
- LP-MSPM33C321A LaunchPad development kit runs the codec and times it with its cycle counter
Build the Mac reference.TERMINAL
Build the reference and write its per-block CRCs.
cd ports/plaits host/build.sh /tmp/plaits-host && /tmp/plaits-host/ref v > /tmp/plaits-host/ref.txtYou should see:
/tmp/plaits-host/ref.txtlists a CRC for each block.Build the board image.TERMINAL
Build at -O2 with the float unit on. Nothing is flashed.
target-m33/build.sh O2 hardYou should see: The script ends with
built .../plaits.out; flash is 202.2 kB.Flash the board and compare.TERMINAL
Flash the image, wait for the finished flag, read the results back over the probe and compare every checksum with the Mac reference. It prints the cycles per block for each engine. It plays no sound and drives no pin.
Replace <probe serial> and <path of plaits.out> before you run this.
cd ../.. PROBE=<probe serial> python3 ports/plaits/run_board.py <path of plaits.out> --ref /tmp/plaits-host/ref.txtYou should see: 24 of 24 engines match the Mac, 23 of them under 37 percent of real time in every block.
You need
- LP-MSPM33C321A LaunchPad development kit runs the codec and times it with its cycle counter
- LP-AM13E230 LaunchPad development kit the second board
Run the Mac reference.TERMINAL
Build the decoder and the harness for the Mac and decode every test stream. It prints one
H264Rline per stream and pass.portability/h264/build_host.shYou should see: One
H264Rline per stream, each with its frame checksums.Build the board image.TERMINAL
Build the 176 by 144 set at -Os for the MSPM33 C321A;
s240adds a 240 by 240 stream. The AM13E230 hasam13e230/tools/build_h264.sh.mspm33c321a/tools/build_h264.sh s176 OsYou should see: The script ends with
built .../h264.outand a size listing.Flash it and read the records.TERMINAL
Flash the
.outwith DSLite as the board'sAGENTS.mdshows. The program leaves one record per stream in RAM (h264_rec). The results were read back over the probe, andportability/h264/parse_rec.pyturns the dump into the sameH264Rlines as step 1.You should see: The board's lines carry the same frame checksums as the Mac's and a cycle count per frame.
Or hand it to a coding assistant
Paste this in a terminal. It hands off to an AI assistant.
git clone --depth 1 --filter=blob:none https://github.com/Fox-Red-Labs/fox-red-labs.git && cd fox-red-labs
./start.sh mspm33c321a codecs --assistant claudegit clone --depth 1 --filter=blob:none https://github.com/Fox-Red-Labs/fox-red-labs.git && cd fox-red-labs
py start.py mspm33c321a codecs --assistant claudeIt runs the steps above and reports what it saw.
Not Claude Code? Copy this prompt instead.
Or hand it to a coding assistant
Paste this in a terminal. It hands off to an AI assistant.
git clone --depth 1 --filter=blob:none https://github.com/Fox-Red-Labs/fox-red-labs.git && cd fox-red-labs
./start.sh mspm33c321a codecs --assistant claudegit clone --depth 1 --filter=blob:none https://github.com/Fox-Red-Labs/fox-red-labs.git && cd fox-red-labs
py start.py mspm33c321a codecs --assistant claudeIt runs the steps above and reports what it saw.
Not Claude Code? Copy this prompt instead.
Or hand it to a coding assistant
Paste this in a terminal. It hands off to an AI assistant, which says when to plug in each of the two boards.
git clone --depth 1 --filter=blob:none https://github.com/Fox-Red-Labs/fox-red-labs.git && cd fox-red-labs
./start.sh mspm33c321a codecs --assistant claudegit clone --depth 1 --filter=blob:none https://github.com/Fox-Red-Labs/fox-red-labs.git && cd fox-red-labs
py start.py mspm33c321a codecs --assistant claudeIt runs the steps above and reports what it saw.
Not Claude Code? Copy this prompt instead.
Or hand it to a coding assistant
Paste this in a terminal. It hands off to an AI assistant.
git clone --depth 1 --filter=blob:none https://github.com/Fox-Red-Labs/fox-red-labs.git && cd fox-red-labs
./start.sh mspm33c321a codecs --assistant claudegit clone --depth 1 --filter=blob:none https://github.com/Fox-Red-Labs/fox-red-labs.git && cd fox-red-labs
py start.py mspm33c321a codecs --assistant claudeIt runs the steps above and reports what it saw.
Not Claude Code? Copy this prompt instead.
Or hand it to a coding assistant
Paste this in a terminal. It hands off to an AI assistant, which says when to plug in each of the two boards.
git clone --depth 1 --filter=blob:none https://github.com/Fox-Red-Labs/fox-red-labs.git && cd fox-red-labs
./start.sh mspm33c321a codecs --assistant claudegit clone --depth 1 --filter=blob:none https://github.com/Fox-Red-Labs/fox-red-labs.git && cd fox-red-labs
py start.py mspm33c321a codecs --assistant claudeIt runs the steps above and reports what it saw.
Not Claude Code? Copy this prompt instead.
If something goes wrong
| The compiler is missing | Install the Xcode command line tools and run it again. |
| It cannot find the SysConfig output | Set G to the gen160 folder from the prerequisites. |
| The probe is not found | Pass the serial of your probe that xdsdfu -e lists. |
Every fix for this board: the FAQ.
| The compiler is missing | Install the Xcode command line tools and run it again. |
| It cannot find the SysConfig output | Set G to the gen160 folder from the prerequisites. |
| The probe is not found | Pass the serial of your probe that xdsdfu -e lists. |
Every fix for this board: the FAQ.
ffmpeg is missing | Install it; it is needed only to remake the clips. |
| It cannot find the SysConfig output | Set G to the gen160 folder from the prerequisites. |
| The probe is not found | Pass the serial of your probe that xdsdfu -e lists. |
| The results read zero | An OpenOCD connect reset the board; read it with DSLite instead. |
Every fix for this board: the FAQ.
clang++ is missing | Install the Xcode command line tools. |
| It cannot find the SysConfig output | Set G to the gen160 folder from the prerequisites. |
| The probe is not found | Pass the serial of your probe that xdsdfu -e lists. |
Every fix for this board: the FAQ.
fetch_src.sh cannot clone the decoder | Check the network and run it again. |
| The SDK is not found | Install it as mac-setup/README.md says and run it again. |
| A line shows a nonzero status or concealed frames | The stream is not baseline or did not fit; use a stream from portability/h264/streams. |
Every fix for this board: the FAQ.
What to build next
Every build. The code for all of them is in the GitHub repository.
Evidence and limitsLC3, Opus, MP3 and Plaits run bit-exact on an MSPM33 C321A, and H.264 video decodes on it and on an AM13E230. Ran on 3 boards. Results, sources, timing and limits.
LC3 (LE Audio) on the LP-MSPM33C321A
Expected result: The board encodes and decodes LC3 frames with every checksum equal to the Mac's.
What this shows
- LE Audio's codec runs in real time on a Cortex-M33 at 160 MHz with room left: the heaviest encode is 24.2 percent of a 10 ms frame.
- The output is bit-exact against the Mac build in all three configurations, and the 7.5, 5 and 2.5 ms frames, packet-loss concealment and two channels also match in 9 of 9 runs.
What this does not establish, and limits
What this does not establish
- Codec only: a generated test signal, no Bluetooth link and no sound output.
- A Cortex-M0+ at 80 MHz is modelled in an emulator, not run: it needs about 329 percent of real time for the 16 kHz encode.
Limits to keep in mind
- Build size is 157.8 kB of flash with every feature and 83.2 kB with LC3 only at -Os.
- A fast-math build makes different encoder bytes from the strict build; both are valid LC3 but not byte-identical.
Sources
Versions, sizes and timing
| Encode, 16 / 24 / 48 kHz | 198k / 249k / 388k cycles a frame | |
|---|---|---|
| Decode, 16 / 24 / 48 kHz | 73k / 114k / 168k cycles a frame |
Evidence
- liblc3 v1.1.3 encodes 16, 24 and 48 kHz mono 10 ms frames in 12.4, 15.6 and 24.2 percent of real time and decodes them in 4.6, 7.1 and 10.5 percent at 160 MHz. The CRC-32 of every encoded frame and decoded block equals the Mac build in all three configurations.
- With the float unit off the same core needs 120 to 262 percent of real time to encode. README notes
Other boards
- MSPM0G3507, MSPM0L1306, CC2340R5, F2800137
- MSPM0G3519, AM13E230ran another way
What the status words mean
Works ran here and did what it shouldCould work some of it ran; real porting effort is left; hover for whatNot for this chip the chip or its vendor software cannot; hover for why
Opus voice and music on the LP-MSPM33C321A
Expected result: The board encodes and decodes Opus voice and music frames with every checksum equal to the Mac's.
What this shows
- CELT at 48 kHz encodes in 29 to 54 percent and decodes in 17 to 22 percent of real time at 160 MHz; SILK decodes in 5 percent.
- The fixed-point build is bit-exact against the Mac in 12 of 12 runs.
What this does not establish, and limits
What this does not establish
- Mono, constant bit rate, a generated signal; no radio and no sound output.
- The SILK encoder keeps up only at complexity 0 (56 percent); at complexity 5 it needs 2.5 times the core.
Limits to keep in mind
- Flash is 331.4 kB at -O2 and 164.7 kB at -Os.
- A Mac build with its default 64-bit multiply macros differs from CELT complexity 5 and up.
Sources
Versions, sizes and timing
| CELT 48 kHz 10 ms, complexity 5 | 858k cycles to encode, 358,367 to decode | README notes |
|---|---|---|
| SILK 16 kHz 20 ms, complexity 0 | 1.79M cycles to encode, 155,615 to decode | README notes |
Evidence
- libopus 1.5.2 fixed-point builds encode and decode SILK 16 kHz and CELT 48 and 16 kHz frames; packets and decoded samples equal a Mac build with the same multiply macros in 12 of 12 runs at three optimization levels.
- The floating-point image runs but its decoded samples equal the Mac in 2 of 12 runs, and it is slower in all 12. README notes
Other boards
- MSPM0G3507, MSPM0L1306, CC2340R5, F2800137
- MSPM0G3519, AM13E230ran another way
What the status words mean
Works ran here and did what it shouldCould work some of it ran; real porting effort is left; hover for whatNot for this chip the chip or its vendor software cannot; hover for why
MP3 decoding (minimp3) on two LaunchPad kits
Expected result: Both boards decode the clip with every frame checksum equal to the Mac's; the M33 keeps up in real time and the M0+ does not.
What this shows
- A Cortex-M33 at 160 MHz decodes stereo MP3 in 15 percent of real time with the hardware float unit.
- The Cortex-M0+ at 80 MHz, with no float unit, needs about 787 MHz to keep up with stereo.
What this does not establish, and limits
What this does not establish
- Decode only: no audio is played.
- minimp3 has no fixed-point path, so there is no fixed-point row.
Limits to keep in mind
- The M0+ image is 150.3 kB of flash and 34.1 kB of static RAM plus a 32 kB stack.
- The M0+ timer is SysTick plus an overflow count; a bare SysTick read would understate each frame.
Sources
Versions, sizes and timing
| LP-MSPM33C321A | 0.151 (stereo) and 0.109 (mono) times real time | |
|---|---|---|
| LP-MSPM0G3519 | 9.84 (stereo) and 7.38 (mono) times real time |
Evidence
- minimp3 decodes a 5.07 s 128 kbps stereo clip in 0.151 times its length on the MSPM33 C321A; all 194 frame checksums equal the Mac's scalar build and the maximum sample error is 0.
- On the MSPM0 G3519 at 80 MHz the same clip takes 9.84 times its length, again with every checksum equal.
Other boards
- MSPM0G3507, MSPM0L1306, CC2340R5, F2800137
- AM13E230ran another way
What the status words mean
Works ran here and did what it shouldCould work some of it ran; real porting effort is left; hover for whatNot for this chip the chip or its vendor software cannot; hover for why
Plaits synthesis (24 engines) on the LP-MSPM33C321A
Expected result: All 24 engines render with every block checksum equal to the Mac's.
What this shows
- A full synthesizer voice costs about a quarter of the core: 23 of 24 engines stay under 37 percent of real time in every block.
- The output is bit-exact against the Mac in all 24 engines.
What this does not establish, and limits
What this does not establish
- Synthesis only: the sound goes to a RAM buffer, with no DAC, MIDI or listening test. The Audio BoosterPack page plays a tone and a tune through a DAC.
- The speech engine has three blocks over real time, where the harmonics jump.
Limits to keep in mind
- One voice and one fixed note sequence.
- Flash is 202.2 kB at -O2. Switching to six of the engines costs one slow block, so switch while the output is muted.
Sources
Versions, sizes and timing
| Block cost | 4.3k cycles (chiptune) to 13.8k (modal) of a 40k-cycle block | README notes |
|---|
Evidence
- Mutable Instruments' Plaits code renders 24 engines in 12-sample blocks at 48 kHz; the CRC-32 of every block equals the Mac build for all 24 engines. A block costs 10.7 to 34.5 percent of real time, median 26.2.
- With the float unit off the same core needs 149 to 1,140 percent of real time. README notes
Other boards
- MSPM0G3507, MSPM0L1306, CC2340R5, F2800137
- MSPM0G3519, AM13E230ran another way
What the status words mean
Works ran here and did what it shouldCould work some of it ran; real porting effort is left; hover for whatNot for this chip the chip or its vendor software cannot; hover for why
H.264 video decoding on two LaunchPad kits
Expected result: Each board decodes the streams with every frame checksum equal to the Mac's.
What this shows
- Small H.264 baseline video decodes in software on both boards: 176 by 144 at 57.4 frames a second on the MSPM33 C321A and at 86.1 on the AM13E230.
- The decoded frames equal the Mac's.
What this does not establish, and limits
What this does not establish
- Decode only: no display, and the numbers are test-pattern streams.
- Streams of 240 by 240 and up do not fit the AM13E230's RAM, and 320 by 240 and up do not fit the MSPM33 C321A's.
Limits to keep in mind
- Baseline profile only. The decoder is a software decoder with no video block.
Sources
Versions, sizes and timing
| LP-MSPM33C321A | 176 by 144 at 57.4 frames a second (-Os), 240 by 240 at 33.3; 110.9 kB of RAM for the first | the data (CSV) |
|---|---|---|
| LP-AM13E230 | 176 by 144 at 86.1, 160 by 112 at 109.9, 128 by 96 at 149.8 frames a second | the data (CSV) |
Evidence
- h264bsd decodes a 176 by 144 baseline stream at 57.4 frames a second on the MSPM33 C321A (240 by 240 at 33.3) with the YUV and RGB CRCs equal to the Mac's. the data (CSV)
- On the AM13E230 the 176 by 144 stream runs at 86.1 frames a second, 160 by 112 at 109.9 and 128 by 96 at 149.8. the data (CSV)
Other boards
- MSPM0G3507, MSPM0L1306, CC2340R5, F2800137
- MSPM0G3519ran another way
What the status words mean
Works ran here and did what it shouldCould work some of it ran; real porting effort is left; hover for whatNot for this chip the chip or its vendor software cannot; hover for why
Result grid
Works ran here and did what it shouldShould work it builds; only naming, packaging or build glue is in the way; hover for whichCould work some of it ran; real porting effort is left; hover for whatNot for this chip the chip or its vendor software cannot; hover for why
Source files
- Measured results (data file) (AM13E230): the raw numbers
Get the code and tell us how it wentThe clone command, the board folder with its AGENTS.md, reports from others, and the three report forms.
Get the code
Clone the repository and open the board's folder below. AGENTS.md is a plain text file of notes for AI coding assistants, and llms.txt at the root indexes the site for one.
git clone https://github.com/Fox-Red-Labs/fox-red-labs.git
- LP-MSPM33C321A: folder
mspm33c321a/.- README: the board's lab notebook (what was run, in order)
- Notes for an AI coding assistant working in this repository: notes for an AI assistant; copy it into your own project if you use one
- FAQ: errors and fixes
The other 2 board folders
- LP-MSPM0G3519: folder
mspm0g3519/.- README: the board's lab notebook (what was run, in order)
- Notes for an AI coding assistant working in this repository: notes for an AI assistant; copy it into your own project if you use one
- FAQ: errors and fixes
- LP-AM13E230: folder
am13e230/.- README: the board's lab notebook (what was run, in order)
- Notes for an AI coding assistant working in this repository: notes for an AI assistant; copy it into your own project if you use one
- FAQ: errors and fixes
- LP-MSPM0G3519: folder
Code is BSD-3-Clause, writing is CC BY 4.0; third-party folders keep their own licenses.
Built it? Tell us
Built this, or got stuck? Report it on GitHub with a few short answers. Your report shows here in your words, marked as yours. A failure that repeats on the bench gets its fix here.