From dc47af28f09705d28e9975867d7fad9a395f9163 Mon Sep 17 00:00:00 2001 From: skal Date: Mon, 2 Feb 2026 12:19:10 +0100 Subject: refactor(build): Centralize generated files and clean up project layout - Task A: Centralized all generated code (assets, timeline) into a single directory to create a single source of truth. - Task A: Isolated test asset generation into a temporary build directory, preventing pollution of the main source tree. - Task B: Vertically compacted all C/C++ source files by removing superfluous newlines. - Task C: Created a top-level README.md with project overview and file descriptions. - Task D: Moved non-essential documentation into a directory to reduce root-level clutter. --- doc/ASSET_SYSTEM.md | 57 +++++++++++++ doc/BUILD.md | 29 +++++++ doc/CONTRIBUTING.md | 189 +++++++++++++++++++++++++++++++++++++++++++ doc/FETCH_DEPS.md | 68 ++++++++++++++++ doc/HOWTO.md | 225 ++++++++++++++++++++++++++++++++++++++++++++++++++++ doc/PROCEDURAL.md | 24 ++++++ doc/SPEC_EDITOR.md | 44 ++++++++++ 7 files changed, 636 insertions(+) create mode 100644 doc/ASSET_SYSTEM.md create mode 100644 doc/BUILD.md create mode 100644 doc/CONTRIBUTING.md create mode 100644 doc/FETCH_DEPS.md create mode 100644 doc/HOWTO.md create mode 100644 doc/PROCEDURAL.md create mode 100644 doc/SPEC_EDITOR.md (limited to 'doc') diff --git a/doc/ASSET_SYSTEM.md b/doc/ASSET_SYSTEM.md new file mode 100644 index 0000000..250be07 --- /dev/null +++ b/doc/ASSET_SYSTEM.md @@ -0,0 +1,57 @@ +# compact asset system for the 64k demo + +This file describe the features of a compact asset system used in the demo. + +The idea is the following: + +# run-time asset retrieval: + All assets are const byte arrays. We need a 'const uint8_t* GetAsset(uint16 asset_id)' + The asset ID is defined in a 'assets.h' header, generated during the final + compile by our own assembling tool. assets.h needs to be re-generated + infrequently. + +# assembling the assets: + +## description file 'assets.txt' + All assets are just files in the assets/final/ directory + This directory needs a assets.txt text file to describe the asset files. + Each line of the assets.txt file contain, comma-separated: + * the name of the asset (that will be used by the #define in assets.h), + * the name of the file associated + * the compression to use for this asset (default NONE. More options later) + * and optionally the type of assets. + +## example For instance, a line in assets.txt will read: + +SAMPLE_142, sample_142.spec, NONE, "this is a drum kick sample" + +This instructs the final assembled file assets.h to have a code line: + #define ASSET_SAMPLE_142 6323 + +(6323 is just an associated id) + +(or an enum instead of #define's) + +so that we can call +``` +#include "asset.h" +const uint8_t* mysample = GetAsset(ASSET_SAMPLE_142); +...etc +``` + +(if we use enums, GetAssert() signature needs to be changed) + +### Lazy decompression +to save memory some assets can be decompressed 'at retrieval time' but kept +compressed in memory until then. +This means that we need a 'void DropAsset(uint16 asset_id, const uint8* asset)' +method to handle memory disallocation depending on the asset type. + +### assembling tool + +we need a simple tool that: + * takes the assets.txt file and parse it + * generates the assets.h file with asset enums + * generates the assets_data.cc file with all the data + * put these in the source tree + * this process needs a script for automation diff --git a/doc/BUILD.md b/doc/BUILD.md new file mode 100644 index 0000000..3a581b1 --- /dev/null +++ b/doc/BUILD.md @@ -0,0 +1,29 @@ +# Build Instructions + +Debug build: +cmake -S . -B build +cmake --build build + +Size-optimized build: +cmake -S . -B build -DDEMO_SIZE_OPT=ON +cmake --build build + +## Windows Cross-Compilation (from macOS) + +Requires `mingw-w64` and `wine-stable` (for testing). + +1. Fetch Windows binaries: + ```bash + ./scripts/fetch_win_deps.sh + ``` + +2. Build for Windows: + ```bash + ./scripts/build_win.sh + ``` + This will produce `build_win/demo64k_packed.exe`. + +3. Run with Wine: + ```bash + ./scripts/run_win.sh + ``` diff --git a/doc/CONTRIBUTING.md b/doc/CONTRIBUTING.md new file mode 100644 index 0000000..7ae2e52 --- /dev/null +++ b/doc/CONTRIBUTING.md @@ -0,0 +1,189 @@ +# Contributing Guidelines + +This document outlines the conventions to follow when contributing to this project. + +## Commit Policy + +### Verify Build and Tests Before Committing + +Before preparing or proposing a commit, you **must** perform the following verifications to prevent regressions: + +1. **MacOS / Linux (Native)**: + * Build the project (debug or release). + * Run the entire test suite (`ctest`). + * Ensure all tests pass. + +2. **Windows (Cross-Compilation)**: + * If `mingw-w64` is installed on your system, you **must** also verify the Windows build. + * Run `./scripts/build_win.sh`. + * Ensure the build succeeds and produces the `demo64k_packed.exe` binary. + * Check the size report to ensure no unexpected bloat. + +Refer to the "Testing" and "Windows Cross-Compilation" sections in `HOWTO.md` for detailed instructions. + +### Format Code Before Committing + +All code **must** be formatted using `clang-format` before committing. This ensures a consistent coding style across the entire codebase. + +To format your code, run the following command from the project root: +```bash +clang-format -i $(git ls-files | grep -E '\.(h|cc)$' | grep -vE '^(assets|archive|third_party)/') +``` + +Refer to the `.clang-format` file in the project root for the specific style rules. + +### Ensure Newline at End of File + +All source files (`.h`, `.cc`, `.cpp`, etc.) must end with a newline character. This prevents "No newline at end of file" errors from linters and ensures consistent file handling. + +### Source File Headers + +Every source file (`.h`, `.cc`) must begin with a concise 3-line comment header describing its purpose. + +Example: +```cpp +// This file is part of the 64k demo project. +// It implements the core audio synthesis engine. +// This is not a user-facing header, but an internal one. +``` + +### Function and method comments + +Functions and methods, especially if they are internal non user-facing, +should at least have a 1-line comment describing what they do or their +how/when they should be called. Except if they are just 1-line function +or very very short, obvious ones. + +### '#endif' directive + +The closing #endif directive must recall the corresponding opening #ifdef +clause they are closing + +Example: +```cpp +#ifdef MY_TAG +...some code +#endif /* MY TAG */ +``` + +We must also prefer '#if defined(MY_QUITE_LONG_TAG)' over '#ifdef MY_QUITE_LONG_TAG' +especially if there's a risk of having later something like: +```cpp +#if defined(MY_TAG_1) && !defined(MY_TAG_2) +``` + +### use and abuse 'const' directives + +Especially for local variable, use 'const' qualification as much as +possible. + +As an example, don't use: +```cpp +StructA variable_name = StructA(...); +``` + +but prefer instead: +```cpp +const StructA variable_name = StructA(...); +``` + +if variable_name is not mutated afterward. + +Also: pass parameter as "const ref" as much as possible +(```const Struct& param``` instead of pointers or non-const refs) + +### put spaces around code and operators (cosmetics) + +Don't compact the code to much horizontally, and prefer adding extra +spaces around code and operators. + +Example: +```cpp +const bool v = my_variable && (my_function() / 3. > (1. / x)); +const y = function_call(3, x, 2.); +for (int x = 0; x < 24; ++x) { ... } +``` + +instead of +```cpp +const bool v=my_variable&&my_function()/3.>(1./x); +const y = function_call(3,x,2); +for(int x=0;x<24;++x){ ... } +``` + +### prefer prefixed incrementation over suffixed + +Use pre-incrementation: +```cpp +++x +``` + +instead of post-incrementation: + +```cpp +x++ +``` + +### use extra () for boolean operations + +Even if they are not strictly needed due to operator precedence rules, +prefer adding extra ()'s around tests for clarity, with parcimony. + +### c++ cast + +don't use reinterpret_cast<>, static_cast<> or const_cast<>. + +### pointer declaration + +prefer ```const T* name``` to ```const T *name```. + +### 'auto' type + +Don't use 'auto' as type, unless for complex iterators or very complex +types. + +### don't use trailing whitespaces + +don't. + +### no missing \newline at the end of file + +make sure each file has a final \n newline. + +### c++ keyword indentation: + +The keyword 'public', 'protected', 'private' should be intended 1 character +less than the methods. + +Example: +```cpp + private: + int field_; +``` + +instead of: +```cpp +private: + int field_; +``` + +### vertical space + +keep the code compact vertically. That includes shader code, too. +Use only one statement per line. + +### finally + +Make sure everything is reflected in clang-format. + +## Development Protocols + +### Adding a New Visual Effect + +1. **Implement**: Create or update a class in `src/gpu/demo_effects.cc` (and declare in `demo_effects.h`) that inherits from `Effect`. + - Implement `init()` for one-time resource setup (e.g., using the asset system). + - Implement `compute()` if you need GPU-side physics or state updates. + - Implement `render()` to record WebGPU draw commands. +2. **Register**: Add an `EFFECT` entry to `assets/demo.seq` specifying the class name, start/end times, and any constructor arguments. +3. **Verify**: Build with `DEMO_ALL_OPTIONS=ON` and use `--seek` to test your effect at its specific timestamp. + diff --git a/doc/FETCH_DEPS.md b/doc/FETCH_DEPS.md new file mode 100644 index 0000000..ce62db2 --- /dev/null +++ b/doc/FETCH_DEPS.md @@ -0,0 +1,68 @@ +# Fetching Third-Party Dependencies + +This project intentionally does NOT vendor large third-party libraries. + +Currently required: + +## miniaudio + +Single-header audio library. + +Source: +https://github.com/mackron/miniaudio + +Required file: +- miniaudio.h + +Expected location: +third_party/miniaudio.h + +### Automatic fetch + +Use one of the provided scripts: +- scripts/project_init.sh +- scripts/project_init.bat + +### Manual fetch + +Download miniaudio.h from: +https://raw.githubusercontent.com/mackron/miniaudio/master/miniaudio.h + +and place it into: +third_party/miniaudio.h + +## wgpu-native + +WebGPU implementation via wgpu-native. + +### Installation + +**macOS:** +```bash +brew install wgpu-native +``` + +**Other platforms:** +Please install `wgpu-native` such that `libwgpu_native` (static or shared) is in your library path and headers are in your include path (under `webgpu/`). + +## glfw3webgpu + +Helper library for creating WebGPU surfaces from GLFW windows. + +### Automatic fetch + +Use one of the provided scripts: +- scripts/project_init.sh +- scripts/project_init.bat + +These scripts will download `glfw3webgpu.h` and `glfw3webgpu.c` into `third_party/glfw3webgpu`. + +## UPX + +Executable packer for binary compression (Linux/Windows only). +On macOS, the build script defaults to `strip` and `gzexe` due to UPX compatibility issues. + +### Installation + +**Linux/Windows:** +Download the appropriate release from https://github.com/upx/upx/releases and ensure the `upx` executable is in your PATH. diff --git a/doc/HOWTO.md b/doc/HOWTO.md new file mode 100644 index 0000000..e97380e --- /dev/null +++ b/doc/HOWTO.md @@ -0,0 +1,225 @@ +# How To + +This document describes the common commands for building and testing the project. + +## Features + +* **Real-time Audio Synthesis**: The demo features a multi-voice synthesizer that generates audio in real-time from spectrograms. +* **Dynamic Sound Updates**: Spectrograms can be updated dynamically and safely during runtime for evolving soundscapes. + +## Building + +### Debug Build + +To run the demo in fullscreen mode, use the `--fullscreen` command-line option: + +```bash +cmake -S . -B build +cmake --build build +./build/demo64k --fullscreen +``` + +To run in a specific resolution, use the `--resolution` option: +```bash +./build/demo64k --resolution 1024x768 +``` + +Keyboard Controls: +* `Esc`: Exit the demo. +* `F`: Toggle fullscreen mode. + +### Size-Optimized Build + +```bash +cmake -S . -B build -DDEMO_SIZE_OPT=ON +cmake --build build +``` + +### Final / Strip Build + +To produce the smallest possible binary (stripping all unnecessary code like command-line parsing and debug info), use the `DEMO_STRIP_ALL` option: + +```bash +cmake -S . -B build -DDEMO_STRIP_ALL=ON +cmake --build build +``` +In this mode, the demo will always start in fullscreen. + +### Developer Build (All Options) + +To enable all features at once (tests, tools, size optimizations, and stripping) for a comprehensive check: + +```bash +cmake -S . -B build -DDEMO_ALL_OPTIONS=ON +cmake --build build +``` + +## git cloning + +if you have the public ssh key authorized on the VPS, you can use + +`git clone ssh://git@51.38.51.127/~/demo.git` + +to clone the repo and work on it. + +## Debugging + +### Seeking / Fast-Forward +In non-stripped builds, you can jump to any timestamp in the demo. This will simulate all audio logic and GPU physics (compute shaders) frame-by-frame from the start until the target time, then begin real-time playback. + +```bash +./build/demo64k --seek 15.5 +``` + +## Demo Choreography + +### Sequence Compiler +The demo timeline is managed via a textual description in `assets/demo.seq`. This file is transpiled into C++ code during the build process. + +**Format:** +```text +# Starts a new sequence layer (global_start, priority) +SEQUENCE 0.0 0 + # Adds an effect to the sequence (ClassName, local_start, local_end, priority, [constructor_args...]) + EFFECT HeptagonEffect 0.0 60.0 0 +``` + +To update the demo's timing or layering, simply edit `assets/demo.seq` and rebuild. + +## Tools + +If you are on macOS and want to test the Windows build: + +1. Build it: `./scripts/build_win.sh` +2. Run it: `./scripts/run_win.sh` + +Note: WebGPU support in Wine requires a Vulkan-capable backend (like MoltenVK on macOS). +Note2: make sure you run the script `./scripts/fetch_win_deps.sh` before, to install Win64 dependencies. + +### Testing + +**Commit Policy**: Always run tests before committing. Refer to `CONTRIBUTING.md` for details. + +To build and run the tests, you need to enable the `DEMO_BUILD_TESTS` option in CMake. Refer to the "Developer Build (All Options)" section for the easiest way to enable this. + +Available test suites: +* `HammingWindowTest`: Verifies the properties of the Hamming window function. +* `MathUtilsTest`: Verifies basic math utilities. +* `SynthEngineTest`: Verifies the core functionality of the audio synthesizer. +* `SpectoolEndToEndTest`: Performs an end-to-end test of the `spectool` by generating a WAV file, analyzing it, and verifying the output. +* `SequenceSystemTest`: Tests the logic of the sequence and effect system (activation, timing, priority), but **not** actual GPU rendering output, as this requires extensive mocking. + +```bash +cmake -S . -B build -DDEMO_BUILD_TESTS=ON +cmake --build build +cd build +ctest +cd .. +``` + +## Tools + +### Spectrogram Tool (`spectool`) + +A command-line tool for analyzing WAV and MP3 files into spectrograms and playing them back. + +#### Building the Tool + +To build `spectool`, you need to enable the `DEMO_BUILD_TOOLS` option in CMake. + +```bash +cmake -S . -B build -DDEMO_BUILD_TOOLS=ON +cmake --build build +``` +The executable will be located at `build/spectool`. + +#### Usage + +**Analyze an audio file:** +```bash +./build/spectool analyze path/to/input.wav path/to/output.spec +# or +./build/spectool analyze path/to/input.mp3 path/to/output.spec +``` + +**Play a spectrogram file:** +```bash +./build/spectool play path/to/input.spec +``` + +### Spectrogram Viewer (`specview`) + +A command-line tool for visualizing spectrogram files in ASCII art. + +#### Building the Tool + +`specview` is built along with `spectool` when enabling `DEMO_BUILD_TOOLS`. + +```bash +cmake -S . -B build -DDEMO_BUILD_TOOLS=ON +cmake --build build +``` +The executable will be located at `build/specview`. + +#### Usage + +**View a spectrogram file:** +```bash +./build/specview path/to/input.spec +``` + +### Asset Management System + +This system allows embedding binary assets directly into the demo executable. + +#### Defining Assets + +Assets are defined in `assets/final/demo_assets.txt` (for the demo) and `assets/final/test_assets_list.txt` (for tests). Each line specifies: +* `ASSET_NAME`: The identifier for the asset in C++ (e.g., `KICK_1`). +* `filename.ext`: The path to the asset file (relative to `assets/final/`). +* `NONE`: Compression type (currently only `NONE` is supported). +* `"Description"`: An optional description. + +Example `assets/final/demo_assets.txt` entry: +``` +KICK_1, kick1.spec, NONE, "A drum kick sample" +``` + +#### Re-generating Assets + +To re-analyze source audio files (WAV/MP3) into spectrograms and update the embedded assets in the source tree, use the provided script: + +```bash +./scripts/gen_assets.sh +``` + +This script: +1. Ensures `spectool` and `asset_packer` are built. +2. Converts source audio files in `assets/wav/` to `.spec` files in `assets/final/`. +3. Runs `asset_packer` to update `src/assets.h` and `src/assets_data.cc`. + +#### Building with Assets + +The build system automatically runs `asset_packer` whenever the asset lists are modified. The generated files are located in the build directory (`build/src/`). + +To build the demo with the latest assets: + +```bash +cmake -S . -B build +cmake --build build +``` + +#### Accessing Assets in Code + +Include `assets.h` and use the `GetAsset` function: + +```cpp +#include "assets.h" + +// ... +size_t asset_size; +const uint8_t* my_asset = GetAsset(AssetId::ASSET_SAMPLE_142, &asset_size); +// ... +// For lazy decompression (scaffolding only): +// DropAsset(AssetId::ASSET_SAMPLE_142, my_asset); +``` diff --git a/doc/PROCEDURAL.md b/doc/PROCEDURAL.md new file mode 100644 index 0000000..c6bf688 --- /dev/null +++ b/doc/PROCEDURAL.md @@ -0,0 +1,24 @@ +# Procedural textures + +## the idea +We need a way to produce textures procedurally. +These texture can be generated on the CPU or the +GPU with a shader and the proper rendering target, +and then sent back to main memory. + +## What textures? + +The procedure can be use to pre-calc env maps +and lighting maps, or textures (fractals, fonts, etc.) + +## how + +This could be integrated in the asset system as +a special "compression" case (instead of "NONE", you +have "PROC(the_function_name_to_call)" as compression +type). + +## code + +let's have a proper 'src/procedural' sub-directory +with all the code related to procedural textures. diff --git a/doc/SPEC_EDITOR.md b/doc/SPEC_EDITOR.md new file mode 100644 index 0000000..cde0cdd --- /dev/null +++ b/doc/SPEC_EDITOR.md @@ -0,0 +1,44 @@ +# spectrogram editing tool in a browser + +The sub-project is about have an editing tool in a browser +that will allow generating, editing, compacting .spec files + +## the idea + +We want a web page (html+javascript) capable of: + * loading a .wav file and showing the spectrogram (IDCT_SIZE=512) + * compacting this spectrogram if needed + * generating the .spec file + * allowing some editing on the spectrogram + * and most importantly: allowing the compression of this spectrogram using elementary bricks like bezier-curves (with a large stroke width / + brushes), rectangle, noise addition, etc. + +These tools must be available in the web editor (in javascript) as well as +in c++ equivalent too. + +The idea is the compress the .wav spectrogram using elementary bricks and +simple representation (as well as being dynamic) during the demo: we +generate the audio on the fly by 'drawing' the spectrograms and passing them +to the synth + +## the work + +Analyze the requirement for the HTML tool. It must remain simple and easy to +use. Don't over-engineer it. +Still, the tool must have a decent load/save offer, to: + * load the .wav + * save the .spec + * save/export the descriptive compressed version in vectorial form (like the SVG format, in fact) + * be able to load this vectorial form + +Then we need a reader for the vectorial form in c++ to use in the demo. +We also need to elementary tools / bricks to: draw a line / bezier curve / +rectangle, ellipse, etc. in frequency domain, to generate the spectrogram on +the flight. +We also need controllable random noise generation to add some 'texture' to +the spectrogram. + +## the files +the HTML/JS tool should be under tools/editor +the c++ code should be added to the library under src/audio/ + -- cgit v1.2.3