145 lines
7.2 KiB
Markdown
145 lines
7.2 KiB
Markdown
# autosample
|
||
|
||
Graphical interface for automatically recording samples from existing analog audio hardware.
|
||
|
||
## Build
|
||
|
||
### Windows
|
||
|
||
Requires MSVC (Visual Studio 2019 Build Tools or later) with the Windows SDK and C++20 support.
|
||
|
||
Open a Developer Command Prompt, then:
|
||
|
||
```
|
||
cl /nologo build.c
|
||
build.exe debug
|
||
build_debug\autosample.exe
|
||
```
|
||
|
||
### macOS
|
||
|
||
Requires Xcode Command Line Tools (`xcode-select --install`).
|
||
|
||
```
|
||
cc build.c -o build
|
||
./build debug
|
||
open build_debug/autosample.app
|
||
```
|
||
|
||
The first command is a one-time bootstrap. After that, `./build` detects changes to `build.c` and rebuilds itself automatically. Pass `debug` for a debug build (output in `build_debug/`) or omit for release (`build_release/`). Pass `clean` to wipe the build directory.
|
||
|
||
## Architecture
|
||
|
||
The project uses a **unity build**: `src/main.cpp` includes all other `.cpp`/`.mm` files, producing a single translation unit compiled with one compiler invocation. Platform selection is handled with `#ifdef __APPLE__` guards.
|
||
|
||
### Base layer (`src/base/`)
|
||
|
||
Foundational types and utilities shared across the project. Provides sized integer/float typedefs (`U8`, `S32`, `F32`, `B32`, etc.), math primitives (`Vec2F32`), string helpers, and arena allocators. This layer has no dependencies beyond the C standard library.
|
||
|
||
### Platform layer (`src/platform/`)
|
||
|
||
Abstracts window creation, event polling, menus, clipboard, and native handles behind a C-style API with opaque `PlatformWindow` handles.
|
||
|
||
- **Windows**: `platform_win32.cpp` — Win32/HWND, `WM_*` message loop
|
||
- **macOS**: `platform_macos.mm` — Cocoa/AppKit, NSWindow, NSTextInputClient
|
||
|
||
### UI layer (`src/ui/`)
|
||
|
||
A thin wrapper around [Clay](https://github.com/nicbarker/clay) (v0.14), a single-header C layout library. Clay uses macros (`CLAY()`, `CLAY_TEXT()`, etc.) for declarative layout with automatic sizing, flex-like child arrangement, and built-in text measurement.
|
||
|
||
- `ui_core.h` / `ui_core.cpp` — Defines `UI_Context` and `UI_Theme`, handles Clay initialization, lifecycle (`ui_begin_frame` / `ui_end_frame`), text measurement bridge, and error handling. `CLAY_IMPLEMENTATION` is defined here.
|
||
- `ui_widgets.h` / `ui_widgets.cpp` — Widget abstractions (currently stubs, reserved for future use).
|
||
|
||
The application layout is built in `main.cpp` using Clay macros directly. Panel builder functions (`build_browser_panel`, `build_main_panel`, etc.) compose the UI each frame.
|
||
|
||
### Renderer (`src/renderer/`)
|
||
|
||
Custom SDF-based pipeline for UI rendering. Processes Clay's `Clay_RenderCommandArray` output directly — no intermediate scene graph.
|
||
|
||
- **Windows**: `renderer_dx12.cpp` — DirectX 12, HLSL shaders, GDI font atlas (Segoe UI)
|
||
- **macOS**: `renderer_metal.mm` — Metal, MSL shaders, Core Text font atlas (SF Pro)
|
||
|
||
Both renderers share the same vertex format (18 floats), SDF rounded-rect shader, and Clay command processing logic. Text measurement uses GDI on Windows and Core Text on macOS.
|
||
|
||
### Audio (`src/audio/`)
|
||
|
||
Audio device enumeration and output with test tone generation.
|
||
|
||
- **Windows**: `audio_asio.cpp` — ASIO driver via COM, registry enumeration, multi-format sample writing
|
||
- **macOS**: `audio_coreaudio.cpp` — CoreAudio with AUGraph/HAL Output, Float32 non-interleaved
|
||
|
||
### MIDI (`src/midi/`)
|
||
|
||
MIDI device enumeration with real-time input monitoring.
|
||
|
||
- **Windows**: `midi_win32.cpp` — Win32 multimedia API (`midiIn*` / `midiOut*`)
|
||
- **macOS**: `midi_coremidi.cpp` — CoreMIDI client with single input port, source connection
|
||
|
||
## Project structure
|
||
|
||
```
|
||
build.c Build script (cc build.c -o nob)
|
||
vendor/
|
||
nob/
|
||
nob.h nob build system (vendored, single-header)
|
||
clay/
|
||
clay.h Clay v0.14 (modified for MSVC C++ compatibility)
|
||
src/
|
||
main.cpp Entry point, unity build includes, Clay layout
|
||
menus.cpp Menu bar setup
|
||
base/
|
||
base_core.h Sized types, macros
|
||
base_arena.h / .cpp Arena allocator
|
||
base_math.h Vec2, min/max
|
||
base_strings.h / .cpp String utilities
|
||
base_inc.h / .cpp Aggregate include/impl
|
||
platform/
|
||
platform.h Window management API (platform-agnostic)
|
||
platform_win32.cpp Win32 implementation
|
||
platform_macos.mm macOS Cocoa implementation
|
||
renderer/
|
||
renderer.h Renderer API (graphics-agnostic)
|
||
renderer_dx12.cpp DirectX 12 implementation
|
||
renderer_metal.mm Metal implementation
|
||
ui/
|
||
ui_core.h Clay wrapper types and lifecycle API
|
||
ui_core.cpp Clay init, text measurement bridge, theme
|
||
ui_widgets.h / .cpp Widget stubs (reserved)
|
||
audio/
|
||
audio.h Audio device and playback API
|
||
audio_asio.cpp Windows ASIO implementation
|
||
audio_coreaudio.cpp macOS CoreAudio implementation
|
||
midi/
|
||
midi.h MIDI device enumeration API
|
||
midi_win32.cpp Win32 multimedia implementation
|
||
midi_coremidi.cpp macOS CoreMIDI implementation
|
||
```
|
||
|
||
### Modifications to `vendor/clay/clay.h`
|
||
|
||
Two targeted patches for MSVC C++ compatibility:
|
||
|
||
1. **`CLAY__CONFIG_WRAPPER` bypass** (lines 158–163): MSVC C++ rejects designated initializers inside function-style casts. In C++ mode, the wrapper struct is bypassed: `(type { __VA_ARGS__ })` instead of `(WrapperType { .field = ... }).wrapped`.
|
||
|
||
2. **Debug view stub** (lines ~3155–3858): Clay's built-in debug view functions use `CLAY__INIT(type) { .field = ... }` directly (not through `CLAY__CONFIG_WRAPPER`), which also fails in MSVC C++. An `#ifdef __cplusplus` guard stubs out the 4 debug view functions as empty no-ops. The debug overlay is not needed.
|
||
|
||
These patches allow the entire project (including Clay) to compile as a single C++20 translation unit, avoiding C/C++ ABI mismatches with `CLAY_PACKED_ENUM` (which controls enum sizing differently in C vs C++ mode).
|
||
|
||
## Code style
|
||
|
||
This project is written in C-style C++. We use `.cpp` files and a small subset of C++ features (default struct values, function overloading, namespaces where useful) but avoid the rest. No classes, no inheritance, limit templates, no exceptions, no RTTI, avoid STL containers or algorithms. Data is plain structs. Functions operate on those structs, or pointers to them. macOS files use `.mm` extension for Objective-C++ interop.
|
||
|
||
Memory should be managed with arena allocators where possible rather than individual `malloc`/`free` or `new`/`delete` calls. Arenas make allocation fast, avoid fragmentation, and simplify cleanup.
|
||
|
||
### Syntax style
|
||
|
||
- Opening braces go on the same line as the function signature (K&R style), not on the next line.
|
||
- Use `CAPS_SNAKE_CASE` for constants, `lower_snake_case` for functions and variables, and `CapsCamelCase` for types.
|
||
|
||
## Dependencies
|
||
|
||
All dependencies are vendored as source. On Windows, nothing to install beyond the Windows SDK. On macOS, only Xcode Command Line Tools are needed — all frameworks (Metal, Cocoa, CoreAudio, CoreMIDI, CoreText, etc.) ship with the OS.
|
||
|
||
- [nob.h](https://github.com/tsoding/nob.h) — build system
|
||
- [Clay](https://github.com/nicbarker/clay) — single-header C layout library (v0.14, with MSVC C++ patches)
|