summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-01-31 14:08:00 +0100
committerskal <pascal.massimino@gmail.com>2026-01-31 14:08:00 +0100
commite4aadd83ffe0d0ff33d8ca058c192decbb25974b (patch)
tree6884fb70359e7db8009c4ef7e5235d33242ef059
parent50d4bd635a5fd8aaf6f19b713c10bbb445301b97 (diff)
update state in .md files
-rw-r--r--PROJECT_CONTEXT.md85
-rwxr-xr-xscripts/build_win.sh3
-rw-r--r--src/gpu/gpu.cc36
3 files changed, 62 insertions, 62 deletions
diff --git a/PROJECT_CONTEXT.md b/PROJECT_CONTEXT.md
index 650189a..0e47b33 100644
--- a/PROJECT_CONTEXT.md
+++ b/PROJECT_CONTEXT.md
@@ -27,14 +27,16 @@ Incoming tasks in no particular order:
- [x] 1. add a fullscreen mode (as command line option)
- [x] 2. parse the keyboard key. Exit the demo when 'esc' is pressed. Toggle full-screen when 'f' is pressed.
- [x] 3. add binary crunchers for all platforms
-- 4. add cross-compilation for PC+linux (x86_64) and PC+Windows (.exe binary)
+- [ ] 4. add cross-compilation for PC+linux (x86_64) and PC+Windows (.exe binary)
+ - [x] PC+Windows (.exe binary) via MinGW
+ - [ ] PC+linux (x86_64)
- 5. implement a spectrogram editor for representing .spec with elementary shapes (bezier curves, lines, random noise, rectangles...) as a mean of compression / spec generation
- 6. add a scripting tool to edit the demo (compiled into the binary at the end)
- [x] 7. compile wgpu-native in optimized mode (not unoptimized)
- [x] 8. add a #define STRIP_ALL to remove all unnecessary code for the final build (for instance, command-line args parsing, or unnecessary options, constant parameters to function calls, etc.)
- [x] 9. work on the compact in-line and off-line asset system (@ASSET_SYSTEM.md)
-- 10. optimize spectool to remove trailing zeroes from a spec file before saving it
-- 11. implement a general [time / timer / beat] system in the demo, for effects timing
+- [x] 10. optimize spectool to remove trailing zeroes from a spec file before saving it
+- [x] 11. implement a general [time / timer / beat] system in the demo, for effects timing
## Session Decisions and Current State
@@ -48,37 +50,48 @@ Incoming tasks in no particular order:
### Build System:
- **Production Pipeline**: Automated the entire assembly process via a `final` CMake target (`make final`).
- **Automation**: This target builds the tools, runs the `gen_assets.sh` script to re-analyze audio and regenerate sources, and then performs final binary stripping and crunching (using `strip` and `gzexe` on macOS).
-- **Scripts**:
- - `scripts/gen_assets.sh`: Re-analyzes source audio files into `.spec` format and triggers the `asset_packer`.
- - `scripts/crunch_demo.sh`: Performs the final size optimization and compression.
+- **Windows Cross-Compilation**: Implemented a full pipeline from macOS to Windows x86_64 using MinGW.
+ - `scripts/fetch_win_deps.sh`: Downloads pre-compiled GLFW and `wgpu-native` binaries.
+ - `scripts/build_win.sh`: Cross-compiles the demo, bundles MinGW DLLs, and crunches the binary.
+ - `scripts/run_win.sh`: Executes the resulting `.exe` using Wine.
+ - `scripts/crunch_win.sh`: Strips and packs the Windows binary using UPX (LZMA).
+ - `scripts/analyze_win_bloat.sh`: Reports section sizes and top symbols for size optimization.
### Audio Engine (Synth):
- **Architecture**: Real-time additive synthesis from spectrograms using Inverse Discrete Cosine Transform (IDCT).
-- **Dynamic Updates**: Implemented a double-buffering (flip-flop) mechanism for thread-safe, real-time updates of spectrogram data. The main thread writes to a back buffer, which is then atomically swapped to become the active front buffer for the audio thread, avoiding real-time allocations and locks.
+- **Dynamic Updates**: Implemented a double-buffering (flip-flop) mechanism for thread-safe, real-time updates of spectrogram data.
- **Peak Detection**: Real-time output peak detection with exponential decay for smooth visual synchronization.
-- **Sample Generation**: Samples are generated in the frequency domain (spectrograms) and converted to time-domain audio using IDCT with a Hamming window.
-- **Audio Input Support (`spectool`)**: Supports WAV and MP3 input for analysis (leveraging `miniaudio`'s built-in decoders). AAC is explicitly *not* supported due to complexity and dependency constraints.
-
-### Tools Developed:
-- `spectool`: A command-line tool for analyzing WAV/MP3 files into `.spec` spectrogram format and for playing back `.spec` files through the synth engine.
-- `specview`: A command-line tool for visualizing `.spec` spectrogram files in ASCII art.
-- `asset_packer`: A build-time tool for embedding assets into the binary.
+- **Procedural Melody**: Implemented a shared library (`src/audio/gen.cc`) for generating note spectrograms at runtime. Supports melody pasting with overlapping frames and spectral post-processing.
+- **Spectral Filters**: Implemented runtime spectral effects including noise (grit), lowpass filtering, and comb filtering (phaser/flanger effects).
+- **Timing System**: Implemented a beat-based timing system (BPM) used for both audio generation and visual synchronization.
### WebGPU Integration:
-- **Strategy**: Uses system-installed `wgpu-native` (e.g., via Homebrew) for the implementation.
-- **Surface Creation**: Uses `glfw3webgpu` helper library to abstract platform-specific surface creation from GLFW windows, keeping the codebase clean and cross-platform.
-- **Headers**: Uses standard `<webgpu.h>` provided by the system install.
-- **Visuals**: Pulsating heptagon synchronized with audio peaks, with automatic aspect ratio correction.
+- **Resource Management**: Introduced `GpuBuffer`, `RenderPass`, and `ComputePass` abstractions to group pipeline and bind group resources.
+- **Compute Shaders**: Implemented a high-performance particle system (10,000 particles) using compute shaders for physics and audio-reactive updates.
+- **Visuals**: Pulsating heptagon and a compute-driven particle field synchronized with audio peaks and global time.
-### Coding Style:
-- **Standard**: Adopted a consistent coding style enforced by `.clang-format`.
-- **Rules**: 2-space indentation, no tabs, 80-column line limit.
-- **Headers**: Mandatory 3-line descriptive header at the top of every `.h` and `.cc` file.
-- **File Extension**: All C++ source files renamed from `.cpp` to `.cc`.
+### WebGPU Integration Fixes:
+Several critical issues were resolved to ensure stable WebGPU operation across platforms:
+- **Surface Creation (macOS)**: Fixed a `g_surface` assertion failure by adding platform-specific compile definitions (`-DGLFW_EXPOSE_NATIVE_COCOA`) to `CMakeLists.txt`. This allows `glfw3webgpu` to access the native window handles required for surface creation.
+- **Texture Usage**: Resolved a validation error (`RENDER_ATTACHMENT` usage missing) by explicitly setting `g_config.usage = WGPUTextureUsage_RenderAttachment` in the surface configuration.
+- **Render Pass Validation**: Fixed a "Depth slice provided but view is not 3D" error by ensuring `WGPURenderPassColorAttachment` is correctly initialized, specifically setting `resolveTarget = nullptr` and `depthSlice = WGPU_DEPTH_SLICE_UNDEFINED`.
-### Platform & Input:
-- **Windowing**: Uses GLFW for cross-platform window management.
-- **Input**: Supports 'Esc' and 'Q' for quitting, and 'F' for toggling fullscreen.
+### WebGPU Portability Layer:
+To maintain a single codebase while supporting different `wgpu-native` versions (Native macOS/Linux headers vs. Windows/MinGW v0.19.4.1), a portability layer was implemented in `src/gpu/gpu.cc`:
+- **Header Mapping**: Conditional inclusion of `<webgpu/webgpu.h>` for Windows vs. `<webgpu.h>` for native builds.
+- **Type Shims**: Implementation of `WGPUStringView` as a simple `const char*` for older APIs, with `str_view()` and `label_view()` helpers to abstract the transition from raw strings to view structs.
+- **API Lifecycle**:
+ - **Wait Mechanism**: Abstraction of `wgpuInstanceWaitAny` (new) vs. `wgpuInstanceProcessEvents` (old).
+ - **Request Methods**: Handling of callback signatures for `wgpuInstanceRequestAdapter` and `wgpuAdapterRequestDevice` which changed from struct-based callbacks to direct function pointers.
+- **Struct Differences**:
+ - **Color Attachments**: Conditional removal of the `depthSlice` member in `WGPURenderPassColorAttachment`, which is not present in v0.19.
+ - **Error Handling**: Abstracted `wgpuDeviceSetUncapturedErrorCallback` via a `set_error_callback` helper to account for its relocation into the device descriptor in newer versions.
+- **Surface Creation**: Custom logic in `glfw3webgpu.c` to handle `WGPUSurfaceSourceWindowsHWND` (new) vs. `WGPUSurfaceDescriptorFromWindowsHWND` (old).
+
+### Coding Style:
+- **Standard**: Strictly enforced project-specific rules in `CONTRIBUTING.md`.
+- **Cleanup**: Automate removal of trailing whitespaces and addition of missing newlines at EOF across all source files.
+- **Constraints**: No `auto`, no C++ style casts (`static_cast`, etc.), mandatory 3-line headers.
### Design Decision: Spectrogram Data Representation
@@ -87,22 +100,6 @@ Incoming tasks in no particular order:
* Store frequencies logarithmically.
* Use `uint16_t` instead of `float` for spectral values.
* **Impact:** This aims to achieve better compression while retaining fine frequency resolution relevant to human perception. It will primarily affect the code responsible for saving to and reading from `.spec` files, requiring conversions between the new format and the linear float format used internally by the audio engine.
-### Development Workflow:
-- **Commit Policy**: Explicit rule to always run the full test suite before preparing any commit, documented in `CONTRIBUTING.md`.
-- **Testing**: Comprehensive test suite including `AssetManagerTest`, `SynthEngineTest`, `HammingWindowTest`, and `SpectoolEndToEndTest`.
-
-### Spectrogram Generation Module
-* **Goal:** Introduce programmatic functions to synthesize `.spec` data for creating custom sounds and textures.
-* **Core Functionality:** Implemented `NoteParams` struct and `generate_note_spectrogram_data` function.
-* **Key Features:**
- * Synthesizes notes with configurable `base_freq`, `duration`, `amplitude`, and `delay`.
- * Supports basic ADSR-like envelope (Attack).
- * Includes vibrato (rate, depth).
- * Allows control over harmonic content (`num_harmonics`, `harmonic_amplitude_decay`).
- * Adds subtle variations via `pitch_randomness_stddev` and `amplitude_randomness_stddev`.
-* **Data Flow:**
- 1. `NoteParams` -> `generate_note_time_domain()` (produces time-domain samples using project constants for `SAMPLE_RATE` and `DCT_SIZE`)
- 2. Time-domain samples -> `generate_spectral_data_from_time_domain()` (applies window, DCT, produces spectral frames)
- 3. Spectral frames -> `save_spectrogram_to_spec_file()` (writes to `.spec` file).
-* **Future Work:** Extend envelopes (Sustain, Decay, Release), add more waveform types, implement noise generation, advanced harmonic control, and explore `.spec` file format optimizations.
+### Development Workflow:
+- **Testing**: Comprehensive test suite including `AssetManagerTest`, `SynthEngineTest`, `HammingWindowTest`, and `SpectoolEndToEndTest`. All tests are verified before committing. \ No newline at end of file
diff --git a/scripts/build_win.sh b/scripts/build_win.sh
index 493e322..db95416 100755
--- a/scripts/build_win.sh
+++ b/scripts/build_win.sh
@@ -31,4 +31,7 @@ else
echo "Warning: Could not find MinGW DLLs. You might need them to run the exe."
fi
+# 4. Crunch the binary
+./scripts/crunch_win.sh
+
echo "Build complete. Output: build_win/demo64k.exe"
diff --git a/src/gpu/gpu.cc b/src/gpu/gpu.cc
index 40be1d2..b1f3f14 100644
--- a/src/gpu/gpu.cc
+++ b/src/gpu/gpu.cc
@@ -26,8 +26,12 @@
// Type Shims
using WGPUStringView = const char *;
-static const char *str_view(const char *str) { return str; }
-static const char *label_view(const char *str) { return str; }
+static const char *str_view(const char *str) {
+ return str;
+}
+static const char *label_view(const char *str) {
+ return str;
+}
// Renamed Types/Enums
#define WGPUSType_ShaderSourceWGSL WGPUSType_ShaderModuleWGSLDescriptor
@@ -48,8 +52,7 @@ static void wgpuInstanceWaitAny(WGPUInstance instance, size_t, void *,
}
// Uncaptured Error Callback Helper
-static void set_error_callback(WGPUDevice device,
- WGPUErrorCallback callback) {
+static void set_error_callback(WGPUDevice device, WGPUErrorCallback callback) {
wgpuDeviceSetUncapturedErrorCallback(device, callback, nullptr);
}
@@ -75,11 +78,11 @@ static WGPUStringView str_view(const char *str) {
return {str, strlen(str)};
}
-static void set_error_callback(WGPUDevice device,
- WGPUErrorCallback callback) {
- // Handled in descriptor for new API, mostly.
- // But we can also set it here if needed, or define a no-op if descriptor handles it.
- // For new API, we set it in WGPUDeviceDescriptor.uncapturedErrorCallbackInfo.
+static void set_error_callback(WGPUDevice device, WGPUErrorCallback callback) {
+ // Handled in descriptor for new API, mostly.
+ // But we can also set it here if needed, or define a no-op if descriptor
+ // handles it. For new API, we set it in
+ // WGPUDeviceDescriptor.uncapturedErrorCallbackInfo.
}
#endif
@@ -109,8 +112,7 @@ struct Particle {
// --- Helper Functions ---
-GpuBuffer gpu_create_buffer(size_t size, uint32_t usage,
- const void *data) {
+GpuBuffer gpu_create_buffer(size_t size, uint32_t usage, const void *data) {
WGPUBufferDescriptor desc = {};
desc.label = label_view("GpuBuffer");
desc.usage = (WGPUBufferUsage)usage; // Cast for C++ strictness with enums
@@ -317,7 +319,6 @@ static void handle_request_device(WGPURequestDeviceStatus status,
// ... (Shaders omitted for brevity, they are unchanged) ...
-
const char *main_shader_wgsl = R"(
struct Uniforms {
audio_peak : f32,
@@ -568,12 +569,11 @@ void gpu_init(GLFWwindow *window) {
initial_particles[i].color[3] = 1.0f;
}
- g_particle_buffer =
- gpu_create_buffer(sizeof(Particle) * NUM_PARTICLES,
- (WGPUBufferUsage)(WGPUBufferUsage_Storage |
- WGPUBufferUsage_CopyDst |
- WGPUBufferUsage_Vertex),
- initial_particles.data());
+ g_particle_buffer = gpu_create_buffer(
+ sizeof(Particle) * NUM_PARTICLES,
+ (WGPUBufferUsage)(WGPUBufferUsage_Storage | WGPUBufferUsage_CopyDst |
+ WGPUBufferUsage_Vertex),
+ initial_particles.data());
// Initialize Particle Compute Pass
ResourceBinding compute_bindings[] = {