docs: rewrite README to characterize rspektrum accurately
Replaces the stale Unity-port README (wrong controls, premake build, missing features). Documents the mLink/mLnL focus, real keybindings, make-based build, headless --render mode, and the Xvfb GUI-driving primer. Consolidates the old SPECTROGRAM_README.md into README.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,161 +1,194 @@
|
||||
# Raylib-Quickstart
|
||||
A simple cross platform template for setting up a project with the bleeding edge raylib code.
|
||||
Works with C or C++.
|
||||
# rspektrum
|
||||
|
||||
# Basic Setup
|
||||
Download this repository to get started.
|
||||
An interactive spectrogram viewer for inspecting **mLink** radio captures (and
|
||||
any other audio). It computes an STFT of a WAV file, draws it as a zoomable,
|
||||
pannable spectrogram, and can overlay **mLnL annotations** — labelled regions
|
||||
(TX frames, assertion outcomes, impairment fires, …) carried *inside* the WAV
|
||||
file itself. You can box a time/frequency region, hear it back through a
|
||||
bandpass filter, and export either the picture (PNG) or the isolated audio
|
||||
(WAV). It runs as a native desktop app (C + raylib), as a headless CLI renderer,
|
||||
and as a WebAssembly build in the browser.
|
||||
|
||||
You can download the zip file of the repository from the Green Code button on github. This is the simplest way to get the template to start from.
|
||||
Once you have downloaded the template, rename it to your project name.
|
||||
## What it's for
|
||||
|
||||
or
|
||||
The primary use case is reviewing captures from the mLink stack: a WAV recording
|
||||
of an over-the-air signal, with an embedded `mLnL` chunk describing what the
|
||||
modem/daemon believed it was transmitting at each instant. rspektrum renders
|
||||
those annotations on top of the measured spectrogram so you can see, frame by
|
||||
frame, what was *intended* versus what actually hit the air. See
|
||||
[`mlnl_chunk_spec.md`](mlnl_chunk_spec.md) for the annotation format. It also
|
||||
works as a general-purpose spectrogram tool for plain WAVs with no annotations.
|
||||
|
||||
Clone the repository with git, from the url
|
||||
```
|
||||
https://github.com/raylib-extras/raylib-quickstart.git
|
||||
## Features
|
||||
|
||||
- **STFT spectrogram** with selectable colormaps, adjustable dB floor / dynamic
|
||||
range, and absolute (dBFS) or relative amplitude scaling.
|
||||
- **mLnL annotation overlay** — labelled boxes drawn from the WAV's embedded
|
||||
annotation chunk; hover a box (or its region on the waveform scope) for a
|
||||
tooltip with per-frame detail (sequence, channel, rate, scheduling offset…).
|
||||
- **Zoom & pan** the time/frequency view (mouse wheel + Alt/middle-drag).
|
||||
- **Region selection**: box a time **and** frequency range with the mouse.
|
||||
- **Filtered playback**: play just the selected region, band-limited to the
|
||||
selected frequency box (FFT bandpass — "what you hear is what you'd export").
|
||||
- **Waveform scope** (toggle) showing the time-domain signal under the spectrum.
|
||||
- **Marker / ruler tool** and a **spectrum slice (PSD)** readout.
|
||||
- **Export**: save the view as a **PNG**, or the selected region as a **WAV**.
|
||||
- **Headless render mode**: produce an annotated PNG from the command line with
|
||||
no window (see below).
|
||||
- **Broad input support**: WAV directly (8/16-bit PCM, 32-bit float; stereo
|
||||
downmixed to mono); other formats transparently transcoded via `ffmpeg` if it
|
||||
is on `PATH`. Drag-and-drop loading.
|
||||
- **Cross-platform**: Linux/desktop, Windows, and a WebAssembly build.
|
||||
|
||||
## Building
|
||||
|
||||
The build is driven by a checked-in Makefile (premake5 is **not** required to
|
||||
build — only to regenerate the makefiles):
|
||||
|
||||
```bash
|
||||
make -f rspektrum.make config=debug_x64 # -> bin/Debug/rspektrum
|
||||
make -f rspektrum.make config=release_x64 # -> bin/Release/rspektrum
|
||||
```
|
||||
|
||||
If you are using a command line git client you can use the command below to download and rename the template in one step
|
||||
```
|
||||
git clone https://github.com/raylib-extras/raylib-quickstart.git [name-for-your-project-here]
|
||||
The web build:
|
||||
|
||||
```bash
|
||||
./build_web.sh # emscripten; emits the WebAssembly bundle
|
||||
```
|
||||
|
||||
# Naming projects
|
||||
* Replace the placeholder with your desired project name when running the git clone command above.
|
||||
* __Do not name your game project 'raylib', it will conflict with the raylib library.__
|
||||
* If you have used custom game name with __git clone__, there is no need to rename it again.
|
||||
> Note: the release build enables `-O2`, which turns on extra warnings
|
||||
> (`-Wformat-truncation`) that the debug build doesn't — build release before
|
||||
> declaring a change clean.
|
||||
|
||||
## Running (GUI)
|
||||
|
||||
## Supported Platforms
|
||||
Quickstart supports the main 3 desktop platforms:
|
||||
* Windows
|
||||
* Linux
|
||||
* MacOS
|
||||
|
||||
# VSCode Users (all platforms)
|
||||
*Note* You must have a compiler toolchain installed in addition to vscode.
|
||||
|
||||
1. Download the quickstart
|
||||
2. Rename the folder to your game name
|
||||
3. Open the folder in VSCode
|
||||
4. Run the build task ( CTRL+SHIFT+B or F5 )
|
||||
5. You are good to go
|
||||
|
||||
# Windows Users
|
||||
There are two compiler toolchains available for windows, MinGW-W64 (a free compiler using GCC), and Microsoft Visual Studio
|
||||
## Using MinGW-W64
|
||||
* Rename the folder to your game name
|
||||
* Double click the `build-MinGW-W64.bat` file
|
||||
* CD into the folder in your terminal
|
||||
* if you are using the W64devkit and have not added it to your system path environment variable, you must use the W64devkit.exe terminal, not CMD.exe
|
||||
* If you want to use cmd.exe or any other terminal, please make sure that gcc/mingw-W64 is in your path environment variable.
|
||||
* run `make`
|
||||
* You are good to go
|
||||
|
||||
### Note on MinGW-64 versions
|
||||
Make sure you have a modern version of MinGW-W64 (not mingw).
|
||||
The best place to get it is from the W64devkit from
|
||||
https://github.com/skeeto/w64devkit/releases
|
||||
|
||||
or the version installed with the raylib installer
|
||||
|
||||
#### If you have installed raylib from the installer
|
||||
Make sure you have added the path
|
||||
|
||||
`C:\raylib\w64devkit\bin`
|
||||
|
||||
To your path environment variable so that the compiler that came with raylib can be found.
|
||||
|
||||
DO NOT INSTALL ANOTHER MinGW-W64 from another source such as msys2, you don't need it.
|
||||
|
||||
## Microsoft Visual Studio
|
||||
* Rename the folder to your game name
|
||||
* Run `build-VisualStudio2022.bat`
|
||||
* double click the `.sln` file that is generated
|
||||
* develop your game
|
||||
* you are good to go
|
||||
|
||||
# Linux Users
|
||||
* Rename the folder to your game name
|
||||
* CD into the build folder
|
||||
* run `./premake5 gmake`
|
||||
* CD back to the root
|
||||
* run `make`
|
||||
* you are good to go
|
||||
|
||||
# MacOS Users
|
||||
* Rename the folder to your game name
|
||||
* CD into the build folder
|
||||
* run `./premake5.osx gmake`
|
||||
* CD back to the root
|
||||
* run `make`
|
||||
* you are good to go
|
||||
|
||||
# Output files
|
||||
The built code will be in the bin dir
|
||||
|
||||
# Working directories and the resources folder
|
||||
The example uses a utility function from `path_utils.h` that will find the resources dir and set it as the current working directory. This is very useful when starting out. If you wish to manage your own working directory you can simply remove the call to the function and the header.
|
||||
|
||||
# Changing to C++
|
||||
Simply rename `src/main.c` to `src/main.cpp` and re-run the steps above and do a clean build.
|
||||
|
||||
# Using your own code
|
||||
Simply remove `src/main.c` and replace it with your code, and re-run the steps above and do a clean build.
|
||||
|
||||
# Building for other OpenGL targets
|
||||
If you need to build for a different OpenGL version than the default (OpenGL 3.3) you can specify an OpenGL version in your premake command line. Just modify the bat file or add the following to your command line
|
||||
|
||||
## For OpenGL 1.1
|
||||
`--graphics=opengl11`
|
||||
|
||||
## For OpenGL 2.1
|
||||
`--graphics=opengl21`
|
||||
|
||||
## For OpenGL 4.3
|
||||
`--graphics=opengl43`
|
||||
|
||||
## For OpenGLES 2.0
|
||||
`--graphics=opengles2`
|
||||
|
||||
## For OpenGLES 3.0
|
||||
`--graphics=opengles3`
|
||||
|
||||
## For Software Rendering
|
||||
`--graphics=software`
|
||||
|
||||
*Note*
|
||||
Sofware rendering does not work with glfw, use Win32 or SDL platforms
|
||||
`--backend=win32`
|
||||
|
||||
# Adding External Libraries
|
||||
|
||||
Quickstart is intentionally minimal — it only includes what is required to compile and run a basic raylib project.
|
||||
If you want to use extra libraries, you can add them to the `build/premake5.lua` file yourself using the links function.
|
||||
|
||||
You can find the documentation for the links function here https://premake.github.io/docs/links/
|
||||
|
||||
### Example: adding the required libraries for tinyfiledialogs on Windows
|
||||
tinyfiledialogs requires extra Windows system libraries.
|
||||
The premake file uses filters to define options that are platform specific
|
||||
https://premake.github.io/docs/Filters/
|
||||
|
||||
Using the windows filter adds these libraries only to the windows build.
|
||||
```
|
||||
filter "system:windows"
|
||||
links {
|
||||
"Comdlg32",
|
||||
"User32",
|
||||
"Ole32",
|
||||
"Shell32"
|
||||
}
|
||||
```bash
|
||||
./bin/Debug/rspektrum [input.wav]
|
||||
```
|
||||
|
||||
### Cross-platform reminder
|
||||
If you add a library, make sure to add its required dependencies for all platforms you plan to support (Windows, Linux, MacOS).
|
||||
Different libraries will have different dependencies on different platforms.
|
||||
Load a file by passing it on the command line, dragging a `.wav` onto the window,
|
||||
or pressing **O** for the file browser.
|
||||
|
||||
### Controls
|
||||
|
||||
# License
|
||||
Raylib-Quickstart by Jeffery Myers is marked with CC0 1.0. To view a copy of this license, visit https://creativecommons.org/publicdomain/zero/1.0/
|
||||
| Input | Action |
|
||||
|-------|--------|
|
||||
| **O** | Open file browser |
|
||||
| **Mouse wheel** | Zoom time/frequency |
|
||||
| **Alt+drag** / **middle-drag** | Pan the view |
|
||||
| **LMB drag** | Select a time + frequency region |
|
||||
| **Space** | Play / stop the selected region |
|
||||
| **Hover an annotation** | Tooltip with that frame's mLnL detail |
|
||||
| **P** | Show / hide the waveform scope |
|
||||
| **M** | Marker / ruler tool |
|
||||
| **S** | Spectrum slice (PSD) |
|
||||
| **E** | Export PNG |
|
||||
| **W** | Export selection as WAV |
|
||||
| **Home** | Reset view (fit all) |
|
||||
| **End** | Zoom to start |
|
||||
| **F11** | Toggle fullscreen |
|
||||
| **F1** | About / help |
|
||||
| **Esc** | Clear selection / close dialog |
|
||||
|
||||
Most controls are also available as buttons in the left sidebar (colormap,
|
||||
floor, dynamic range, annotation opacity, grid, etc.).
|
||||
|
||||
## Headless rendering (CLI)
|
||||
|
||||
rspektrum can render an annotated spectrogram to a PNG without opening a window —
|
||||
useful for batch capture and for agents reviewing test output:
|
||||
|
||||
```bash
|
||||
./bin/Debug/rspektrum --render OUT.png INPUT.wav [options]
|
||||
```
|
||||
|
||||
Options:
|
||||
|
||||
| Flag | Effect |
|
||||
|------|--------|
|
||||
| `-r, --render OUT.png` | Render to `OUT.png` and exit (no window) |
|
||||
| `-a, --annotations` | Force the annotation overlay **on** (solid, for review) |
|
||||
| `--no-annotations` | Force the overlay off |
|
||||
| `--annotation-opacity=V` | Resting overlay alpha `0..1` (default `0.06`, faint) |
|
||||
| `--pane` | Capture only the spectrogram pane (no sidebar/scope) |
|
||||
| `--width N` / `--height N` | Output size (default `1280×800`) |
|
||||
| `-h, --help` | Usage |
|
||||
|
||||
Default annotation opacity is intentionally faint (the overlay is meant to stay
|
||||
out of the way until hovered), so for a screenshot you actually want to *review*,
|
||||
pass `--annotations`. Example against the bundled sample:
|
||||
|
||||
```bash
|
||||
./bin/Debug/rspektrum --render /tmp/review.png mlnl_samples.wav --annotations
|
||||
```
|
||||
|
||||
`mlnl_samples.wav` is an in-repo WAV that carries an embedded `mLnL` chunk.
|
||||
|
||||
> The hover tooltip (sched offset, per-frame detail) only appears with a live
|
||||
> mouse over a box, so it cannot show up in a static `--render`. To verify
|
||||
> tooltip behaviour you need a real (or virtual) display driving the GUI — see
|
||||
> below.
|
||||
|
||||
## Driving the GUI headlessly (for agents / CI)
|
||||
|
||||
The app can be run, screenshotted, and clicked on a virtual X display with no
|
||||
monitor or GPU (Mesa software GL under Xvfb). The accumulated playbook lives in
|
||||
[`AGENTS.md`](AGENTS.md); the working reference implementation is
|
||||
[`shot_input.sh`](shot_input.sh).
|
||||
|
||||
The loop in one breath:
|
||||
|
||||
```bash
|
||||
Xvfb :99 -screen 0 1280x800x24 >/tmp/xvfb.log 2>&1 & # 1. fake screen
|
||||
DISPLAY=:99 ./bin/Debug/rspektrum mlnl_samples.wav \
|
||||
>/tmp/app.log 2>&1 & # 2. run on it
|
||||
sleep 2 # 3. reach a steady frame
|
||||
DISPLAY=:99 import -window root /tmp/shot.png # 4. grab the frame
|
||||
```
|
||||
|
||||
Prerequisites (Debian/Ubuntu): `sudo apt-get install xvfb imagemagick xdotool`
|
||||
(plus `libgl1-mesa-dri` and `LIBGL_ALWAYS_SOFTWARE=1` if GL fails / frames are
|
||||
black). To exercise UI paths, synthesize input with `xdotool` against
|
||||
`DISPLAY=:99` — e.g. move the mouse over an annotation box and re-grab to capture
|
||||
the hover tooltip:
|
||||
|
||||
```bash
|
||||
DISPLAY=:99 xdotool mousemove 640 400 # hover a box (coords from the spectrogram)
|
||||
DISPLAY=:99 import -window root /tmp/hover.png
|
||||
DISPLAY=:99 xdotool key space # play the selection, etc.
|
||||
```
|
||||
|
||||
There is no window manager, so the window sits at `0,0` and fills the Xvfb
|
||||
screen — match the screen size to the window and a root grab equals the app's
|
||||
frame. Always capture stdout/stderr to a log; it's your only view of `TraceLog`
|
||||
output and crashes. `shot_input.sh` wraps all of this (start → settle →
|
||||
screenshot → optional input → diff); read `AGENTS.md` for the traps (input focus,
|
||||
ImageMagick v6 vs v7 command names, software-GL timing).
|
||||
|
||||
## Technical notes
|
||||
|
||||
- **STFT**: Hann-windowed, 2048-point FFT with 50% overlap by default;
|
||||
frequency resolution `sampleRate / fftSize` Hz per bin. Amplitude shown in dB.
|
||||
- **Axes**: X = time (s), Y = frequency (Hz, scaled to the file's Nyquist),
|
||||
colour = amplitude.
|
||||
- **Playback / WAV export** share the same processing path: the selected time
|
||||
span, FFT-bandpassed to the selected frequency box, peak-normalised.
|
||||
- **mLnL parsing**: walks the WAV's RIFF chunks for the four-CC `mLnL` chunk
|
||||
(UTF-8 JSON Lines); unknown chunks are skipped, so annotated files remain
|
||||
standards-compliant audio everywhere else.
|
||||
|
||||
## Source layout
|
||||
|
||||
```
|
||||
src/
|
||||
spectrogram.c # entry point, main loop, CLI args, headless render
|
||||
stft.c / fft.c # STFT + FFT
|
||||
render.c # spectrogram, annotations, tooltips, scope
|
||||
ui.c # sidebar, file browser, buttons
|
||||
audio.c # WAV load (ffmpeg fallback), bandpass, playback, WAV export
|
||||
mlnl.c / mlnl.h # mLnL annotation chunk parser
|
||||
platform_*.c # per-OS shims (linux / win32 / web)
|
||||
```
|
||||
|
||||
See [`raylib_for_desktop_applications.md`](raylib_for_desktop_applications.md)
|
||||
for the performance/idle-CPU lessons behind the desktop build.
|
||||
|
||||
@@ -1,154 +0,0 @@
|
||||
# Spectrogram Viewer (C/Raylib)
|
||||
|
||||
A real-time spectrogram viewer ported from the Unity Audio-Experiments project, with interactive region selection and audio playback.
|
||||
|
||||
## Features
|
||||
|
||||
- **Spectrogram Visualization**: Displays frequency content of audio over time using STFT
|
||||
- **Time & Frequency Selection**: Select both time regions AND frequency ranges
|
||||
- **Audio Playback**: Play back only the selected time region
|
||||
- **Multiple Colormaps**: 6 different heat map styles
|
||||
- **Adjustable Threshold**: Control the dB floor for visualization
|
||||
- **Drag & Drop**: Load files by dragging them onto the window
|
||||
|
||||
## Building
|
||||
|
||||
### Linux
|
||||
|
||||
```bash
|
||||
cd rspektrum/build
|
||||
./premake5 gmake
|
||||
cd ..
|
||||
make
|
||||
```
|
||||
|
||||
## Running
|
||||
|
||||
```bash
|
||||
cd rspektrum/bin/Debug
|
||||
./rspektrum
|
||||
```
|
||||
|
||||
## Controls
|
||||
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| **O** | Open file dialog |
|
||||
| **Drag & drop** | Load WAV file |
|
||||
| **LMB Drag** | Select time region |
|
||||
| **Shift+LMB Drag** | Select frequency range |
|
||||
| **SPACE** | Play selected time region |
|
||||
| **M** | Cycle colormap |
|
||||
| **W/S** | Adjust dB floor (up/down) |
|
||||
| **G** | Toggle grid overlay |
|
||||
| **R** | Reset all selections to full range |
|
||||
| **ESC** | Stop playback / Cancel dialog |
|
||||
|
||||
## File Loading
|
||||
|
||||
Two ways to load a WAV file:
|
||||
|
||||
1. **Drag & Drop**: Simply drag a `.wav` file onto the application window
|
||||
2. **File Dialog**: Press **O** to open a file path input dialog
|
||||
|
||||
## Selection Modes
|
||||
|
||||
### Time Selection (Left Mouse Button)
|
||||
- Click and drag horizontally to select a time range
|
||||
- The non-selected areas are greyed out
|
||||
- Yellow borders indicate the selection boundaries
|
||||
|
||||
### Frequency Selection (Shift + Left Mouse Button)
|
||||
- Hold **Shift** and drag vertically to select a frequency range
|
||||
- Cyan borders indicate the frequency selection
|
||||
- Useful for isolating specific frequency bands
|
||||
|
||||
## Colormaps
|
||||
|
||||
Press **M** to cycle through available colormaps:
|
||||
|
||||
1. **Grays** - Classic grayscale
|
||||
2. **Inferno** - Dark purple to bright yellow (default)
|
||||
3. **Viridis** - Purple to yellow (perceptually uniform)
|
||||
4. **Plasma** - Purple to yellow-orange
|
||||
5. **Hot** - Black to red to yellow to white
|
||||
6. **Cool** - Cyan to magenta
|
||||
|
||||
## Threshold Control
|
||||
|
||||
Use **W** and **S** keys to adjust the amplitude floor:
|
||||
- **W**: Raise the floor (show only louder signals)
|
||||
- **S**: Lower the floor (show quieter signals too)
|
||||
|
||||
The current dB floor is displayed in the bottom right corner.
|
||||
|
||||
## Technical Details
|
||||
|
||||
### STFT Parameters
|
||||
- **FFT Size**: 2048 samples
|
||||
- **Hop Size**: 1024 samples (50% overlap)
|
||||
- **Window**: Hann window
|
||||
- **Frequency Resolution**: `sampleRate / 2048` Hz per bin
|
||||
|
||||
### Audio Format Support
|
||||
- WAV files (any sample rate)
|
||||
- Automatically detected sample rate (displayed in info panel)
|
||||
- 8-bit, 16-bit PCM, and 32-bit float supported
|
||||
- Stereo files are converted to mono
|
||||
|
||||
### Display
|
||||
- X-axis: Time (seconds)
|
||||
- Y-axis: Frequency (Hz), scaled to actual sample rate
|
||||
- Color/brightness: Amplitude in dB
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
rspektrum/
|
||||
├── src/
|
||||
│ ├── spectrogram.c # Main application (~1000 lines)
|
||||
│ └── icon.ico # Windows icon
|
||||
├── libs/
|
||||
│ └── ... # Optional external libraries
|
||||
├── build/
|
||||
│ ├── premake5.lua # Build configuration
|
||||
│ └── external/ # Downloaded dependencies (raylib)
|
||||
└── bin/
|
||||
├── Debug/ # Debug build
|
||||
└── Release/ # Release build
|
||||
```
|
||||
|
||||
## Comparison: Unity vs C/Raylib
|
||||
|
||||
| Aspect | Unity Original | C/Raylib Port |
|
||||
|--------|---------------|---------------|
|
||||
| Lines of Code | ~2000+ (multiple files) | ~1000 (single file) |
|
||||
| Build Time | Minutes | Seconds |
|
||||
| Dependencies | Unity Editor, .NET | raylib only |
|
||||
| GPU Acceleration | Compute shaders | CPU-based |
|
||||
| Colormaps | Single gradient | 6 presets |
|
||||
| Freq Selection | No | Yes |
|
||||
| Startup Time | Slow | Fast |
|
||||
|
||||
## Tips
|
||||
|
||||
1. **For 16kHz audio**: The max frequency will show as 8kHz (Nyquist)
|
||||
2. **Better visibility**: Use Inferno or Viridis colormap for better contrast
|
||||
3. **Quiet signals**: Lower the dB floor with 'S' to see quieter content
|
||||
4. **Isolate frequencies**: Use Shift+drag to focus on specific frequency bands
|
||||
5. **Playback**: Only the time selection is played, full frequency range
|
||||
|
||||
## Future Improvements
|
||||
|
||||
- [ ] Logarithmic frequency scale option
|
||||
- [ ] Zoom in/out on frequency axis
|
||||
- [ ] Real-time microphone input
|
||||
- [ ] Export selection as WAV
|
||||
- [ ] Faster FFT (pffft/kissfft)
|
||||
- [ ] Save/load presets
|
||||
|
||||
## License
|
||||
|
||||
Based on Unity Audio-Experiments by Sebastian Lague (Coding Adventure series)
|
||||
|
||||
C/Raylib port created for educational purposes.
|
||||
Reference in New Issue
Block a user