diff options
Diffstat (limited to 'doc/HOWTO.md')
| -rw-r--r-- | doc/HOWTO.md | 468 |
1 files changed, 109 insertions, 359 deletions
diff --git a/doc/HOWTO.md b/doc/HOWTO.md index 55580ba..967b554 100644 --- a/doc/HOWTO.md +++ b/doc/HOWTO.md @@ -1,468 +1,218 @@ # 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. -* **Unified Audio Engine**: The `AudioEngine` class manages audio subsystem initialization, ensuring correct setup order and eliminating initialization fragility. +Common commands for building and testing. ## 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 +cmake --build build -j4 +./build/demo64k ``` -To run in a specific resolution, use the `--resolution` option: -```bash -./build/demo64k --resolution 1024x768 -``` +Options: +- `--fullscreen`: Run in fullscreen +- `--resolution WxH`: Set window size (e.g., 1024x768) +- `--seek TIME`: Jump to timestamp (debug builds only) -Keyboard Controls: -* `Esc`: Exit the demo. -* `F`: Toggle fullscreen mode. +Keyboard: `Esc` (exit), `F` (toggle fullscreen) ### Size-Optimized Build - ```bash cmake -S . -B build -DDEMO_SIZE_OPT=ON -cmake --build build +cmake --build build -j4 ``` -### 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: - +### Strip Build (64k Target) ```bash cmake -S . -B build -DDEMO_STRIP_ALL=ON -cmake --build build +cmake --build build -j4 ``` -In this mode, the demo will always start in fullscreen. - -### Final-Final Build (Maximum Stripping) - -For the absolute smallest binary (removing ALL error checking), use the `DEMO_FINAL_STRIP` option: +Always starts in fullscreen. Full error checking enabled. +### Final Build (Maximum Stripping) ```bash -# Method 1: CMake target (from normal build directory) -cd build -make final - -# Method 2: Convenience script (creates build_final/ directory) ./scripts/build_final.sh - -# Method 3: Manual CMake configuration +# or cmake -S . -B build_final -DDEMO_FINAL_STRIP=ON -cmake --build build_final +cmake --build build_final -j4 ``` +⚠️ Removes ALL error checking. Use only for final release. -**⚠️ WARNING:** FINAL_STRIP removes ALL error checking (bounds checks, null checks, assertions). This saves ~500-600 bytes but means crashes will have no error messages. Use ONLY for final release builds, never for development or testing. - -**Build Mode Hierarchy:** -- **Debug**: Full error checking + debug features -- **STRIP_ALL**: Full error checking, no debug features (~64k target) -- **FINAL_STRIP**: No error checking, no debug features (absolute minimum size) - -### Developer Build (All Options) - -To enable all features at once (tests, tools, size optimizations, and stripping) for a comprehensive check: +**Build Hierarchy:** +- Debug: Full checks + debug features +- STRIP_ALL: Full checks, no debug (~64k target) +- FINAL_STRIP: No checks, no debug (absolute minimum) +### Developer Build ```bash cmake -S . -B build -DDEMO_ALL_OPTIONS=ON -cmake --build build +cmake --build build -j4 ``` +Enables tests, tools, size optimizations. -### Build System Notes +## Build System -**Incremental Builds**: The build system tracks all source files (.cc, .h) and asset files (.wgsl shaders, .spec audio, .obj meshes) as dependencies. Editing any file will trigger the necessary rebuilds automatically. +**Dependency Tracking**: CMake tracks 42 demo + 17 test assets. Editing shaders/audio auto-triggers rebuild. -**Asset Dependency Tracking**: CMake tracks 42 demo assets and 17 test assets individually. Changing a shader file (e.g., `assets/final/shaders/renderer_3d.wgsl`) automatically regenerates the asset bundle and recompiles dependent files. No manual workarounds needed. - -**Header Organization**: The `asset_manager` system is split into three headers for faster incremental builds: -- `asset_manager_dcl.h`: Forward declarations (use in headers) +**Header Organization**: +- `asset_manager_dcl.h`: Forward declarations - `asset_manager.h`: Core API (GetAsset/DropAsset) -- `asset_manager_utils.h`: Typed helpers (TextureAsset/MeshAsset) - -Include only what you need to minimize rebuild times. - -## 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` +- `asset_manager_utils.h`: Typed helpers -to clone the repo and work on it. +## Git Clone +```bash +git clone ssh://git@51.38.51.127/~/demo.git +``` ## Audio System -### AudioEngine - -The audio subsystem uses `AudioEngine` to manage initialization and lifecycle. This ensures correct setup order and eliminates initialization fragility. - -**Usage in production code:** - +### AudioEngine API ```cpp #include "audio/audio_engine.h" -// Initialize audio backend (miniaudio) audio_init(); - -// Initialize audio engine (manages synth + tracker) static AudioEngine g_audio_engine; g_audio_engine.init(); -// In main loop: update with music time +// Main loop g_audio_engine.update(music_time); -// Cleanup g_audio_engine.shutdown(); audio_shutdown(); ``` -**What to use AudioEngine for:** -- Initialization: `engine.init()` replaces separate `synth_init()` + `tracker_init()` calls -- Updates: `engine.update(music_time)` replaces `tracker_update()` -- Cleanup: `engine.shutdown()` ensures proper teardown -- Seeking: `engine.seek(time)` for timeline navigation (debug builds only) +**Methods:** +- `init()`: Initialize synth + tracker +- `update(music_time)`: Update music state +- `shutdown()`: Cleanup +- `seek(time)`: Jump to timestamp (debug only) -**Direct synth API usage:** -For performance-critical or low-level operations, direct synth API calls are valid: -- `synth_register_spectrogram()` - Register audio samples -- `synth_trigger_voice()` - Trigger sound playback -- `synth_get_output_peak()` - Get audio peak for visualization -- `synth_render()` - Low-level audio rendering +**Direct Synth APIs** (performance-critical): +- `synth_register_spectrogram()`: Register samples +- `synth_trigger_voice()`: Trigger playback +- `synth_get_output_peak()`: Get audio level +- `synth_render()`: Low-level rendering **Testing:** -Tests should use `AudioEngine` for initialization: - ```cpp -#include "audio/audio_engine.h" - -void test_example() { - AudioEngine engine; - engine.init(); - - // Test code here - engine.update(1.0f); - - engine.shutdown(); -} +AudioEngine engine; +engine.init(); +engine.update(1.0f); +engine.shutdown(); ``` -For low-level synth-only tests, you can still call `synth_init()` directly. - ## Auxiliary Texture Masking -The project supports inter-effect texture sharing via the auxiliary texture registry. This allows effects to generate textures (masks, shadow maps, etc.) and make them available to other effects within the same frame. - -**Common use case:** Screen-space partitioning where different scenes render to complementary regions. - +Share textures between effects: ```cpp -class MaskGeneratorEffect : public Effect { - void init(MainSequence* demo) override { - demo_ = demo; - // Register a named auxiliary texture - demo->register_auxiliary_texture("my_mask", width_, height_); - } - - void compute(WGPUCommandEncoder encoder, ...) override { - // Generate mask to auxiliary texture - WGPUTextureView mask_view = demo_->get_auxiliary_view("my_mask"); - // ... render mask - } - - void render(WGPURenderPassEncoder pass, ...) override { - // Use mask in scene rendering - WGPUTextureView mask_view = demo_->get_auxiliary_view("my_mask"); - // ... render scene with mask - } -}; - -class MaskUserEffect : public Effect { - void render(WGPURenderPassEncoder pass, ...) override { - // Reuse mask from MaskGeneratorEffect - WGPUTextureView mask_view = demo_->get_auxiliary_view("my_mask"); - // ... render scene with inverted mask - } -}; -``` - -See `doc/MASKING_SYSTEM.md` for detailed architecture and examples. - -## 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. +// Generator effect +demo->register_auxiliary_texture("mask_name", width, height); +WGPUTextureView view = demo_->get_auxiliary_view("mask_name"); -```bash -./build/demo64k --seek 15.5 +// Consumer effect +WGPUTextureView view = demo_->get_auxiliary_view("mask_name"); ``` +See `doc/MASKING_SYSTEM.md` for details. -## 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. +## Demo Timeline -**Format:** +Edit `assets/demo.seq`: ```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 ``` +Rebuild to update timeline. -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. +## Testing +**Run all tests:** ```bash cmake -S . -B build -DDEMO_BUILD_TESTS=ON -cmake --build build -cd build -ctest -cd .. +cmake --build build -j4 +cd build && ctest ``` -### Code Coverage (macOS only) - -To generate an HTML code coverage report for the project: - -1. **Install lcov:** - ```bash - brew install lcov - ``` - -2. **Run the coverage script:** - ```bash - ./scripts/gen_coverage_report.sh [optional_target_dir] - ``` - This script will configure the build with `-DDEMO_ENABLE_COVERAGE=ON`, run the tests, and generate a report in `build_coverage/coverage_report/`. It will then attempt to open the report in your browser. - - **Examples:** - * Full project report: - ```bash - ./scripts/gen_coverage_report.sh - ``` - * Report for `src/procedural` only: - ```bash - ./scripts/gen_coverage_report.sh src/procedural - ``` - -## Tools - -### Updating Submodules - -To ensure all `third_party/` submodules are updated to the latest "Tip of Tree" (ToT) from their respective remote repositories and to resolve any local diffs, follow these steps: - -1. **Enter the submodule directory** (e.g., `third_party/wgpu-native`): - ```bash - cd third_party/wgpu-native - ``` - -2. **Fetch the latest changes from the remote**: - ```bash - git fetch - ``` - -3. **Identify the default branch** (e.g., `main`, `master`, `trunk`). You can see remote branches with `git branch -r`. For `wgpu-native`, the main development branch is typically `trunk`. - -4. **Checkout the default branch and hard reset to its remote state** (this discards any local changes and ensures a clean ToT): - ```bash - git checkout trunk - git reset --hard origin/trunk - ``` - (Replace `trunk` with the correct branch name if different for other submodules.) - -5. **Return to the superproject's root directory**: - ```bash - cd ../.. - ``` - -6. **Update the superproject's record of the submodule**: This stages the change in the superproject's `.git` index, updating the commit hash for the submodule. - ```bash - git add third_party/wgpu-native - ``` - -7. **Commit the submodule update** in the superproject: - ```bash - git commit -m "chore: Update third_party/wgpu-native submodule" - ``` - (Adjust the commit message as appropriate for other submodules.) - -Repeat these steps for any other submodules in `third_party/` that need updating. - -### 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. +**Key tests:** +- `HammingWindowTest`: Window function properties +- `MathUtilsTest`: Math utilities +- `SynthEngineTest`: Audio synthesis +- `SequenceSystemTest`: Timeline logic +## Code Coverage (macOS) ```bash -cmake -S . -B build -DDEMO_BUILD_TOOLS=ON -cmake --build build +brew install lcov +./scripts/gen_coverage_report.sh [target_dir] ``` -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 -``` +## Tools -**Play a spectrogram file:** +### Windows Cross-Compilation ```bash -./build/spectool play path/to/input.spec +./scripts/fetch_win_deps.sh +./scripts/build_win.sh +./scripts/run_win.sh ``` -### 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`. - +### spectool (Audio Analysis) ```bash cmake -S . -B build -DDEMO_BUILD_TOOLS=ON -cmake --build build -``` -The executable will be located at `build/specview`. +cmake --build build -j4 -#### Usage +# Analyze +./build/spectool analyze input.wav output.spec -**View a spectrogram file:** -```bash -./build/specview path/to/input.spec +# Play +./build/spectool play input.spec ``` -### Audio Analysis & Playback Tool (`specplay`) - -A diagnostic tool for analyzing and playing .spec spectrogram files and .wav audio files. Useful for debugging audio issues, detecting clipping, and comparing spectrograms to source audio. - -#### Building the Tool - -`specplay` is built along with other tools when enabling `DEMO_BUILD_TOOLS`. - +### specview (Visualization) ```bash -cmake -S . -B build -DDEMO_BUILD_TOOLS=ON -cmake --build build +./build/specview input.spec ``` -The executable will be located at `build/specplay`. - -#### Usage -**Play and analyze a .spec file:** +### specplay (Diagnostic) ```bash -./build/specplay path/to/input.spec +./build/specplay input.spec +# or +./build/specplay input.wav ``` +Output: Peak, RMS, clipping detection. -**Play and analyze a .wav file:** +### Submodule Updates ```bash -./build/specplay path/to/input.wav +cd third_party/wgpu-native +git fetch +git checkout trunk +git reset --hard origin/trunk +cd ../.. +git add third_party/wgpu-native +git commit -m "chore: Update wgpu-native" ``` -#### Output Example -``` -Loading .spec: version=1, dct_size=512, frames=68 -PCM stats: Peak=0.403, RMS=0.058 -Playing 1.09 seconds... Press Ctrl+C to stop. -[CLIP at sample 1234: 1.523] # Only shown if clipping detected -Playback complete. -``` - -#### Use Cases -- **Detect clipping**: Peak > 1.0 indicates samples will clip -- **Compare loudness**: RMS shows average energy (loudness) -- **Verify spectrograms**: Ensure .spec matches source .wav -- **Debug distortion**: Quickly test individual samples - -See `tools/specplay_README.md` for detailed documentation and future enhancement ideas. - -### Asset Management System - -This system allows embedding binary assets directly into the demo executable. - -#### Defining Assets +## Asset Management -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: +### Define Assets +Edit `assets/final/demo_assets.txt`: ``` -KICK_1, kick1.spec, NONE, "A drum kick sample" +KICK_1, kick1.spec, NONE, "Drum kick" ``` -#### 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: - +### Regenerate ```bash ./scripts/gen_assets.sh ``` +Converts WAV → .spec, packs into C++ arrays. -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: - +### Use Assets ```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); +size_t size; +const uint8_t* data = GetAsset(AssetId::KICK_1, &size); +// Use data... +// DropAsset(AssetId::KICK_1, data); // For compressed assets only ``` + +Build system auto-runs `asset_packer` when asset lists change. |
