2026-02-25 10:40:05 -05:00
2026-03-02 23:37:12 -05:00
2026-02-25 15:20:47 -05:00
2026-03-02 22:37:46 -05:00
2026-02-22 17:12:57 -05:00
2026-02-25 15:20:47 -05:00
2026-02-22 23:18:40 -05:00
2026-02-25 15:20:47 -05:00

autosample

Graphical interface for automatically recording samples from existing analog audio hardware.

Build

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 nob.c
nob.exe debug
build\autosample.exe

The first command is a one-time bootstrap. After that, nob.exe detects changes to nob.c and rebuilds itself automatically. Pass debug for a debug build (default is release). Pass clean to wipe the build directory.

Architecture

The project uses a unity build: src/main.cpp includes all other .cpp files, producing a single translation unit compiled with one $CC invocation.

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, and native handles behind a C-style API with opaque PlatformWindow handles. The Win32 backend (platform_win32.cpp) implements the interface. Other backends can be added without touching the rest of the code.

UI layer (src/ui/)

A thin wrapper around 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/)

DirectX 12 renderer with a custom SDF-based pipeline for UI rendering. Processes Clay's Clay_RenderCommandArray output directly — no intermediate scene graph.

  • Font atlas: Built at startup using GDI (TextOutA into a DIB section), converted to a single-channel R8 texture. Covers ASCII 32126 (Segoe UI).
  • Text measurement: GDI-based (GetTextExtentPoint32A), exposed to Clay via the Clay_SetMeasureTextFunction callback.
  • Render commands: Handles RECTANGLE (SDF rounded rect with corner radius), BORDER (individual sides as thin rects), TEXT (glyph quads from the font atlas), and SCISSOR_START/SCISSOR_END (clip regions).
  • Vertex format: Position, UV, color, rect bounds, corner radius, border thickness, softness, and mode (0 = SDF rect, 1 = textured glyph). Alpha blending with premultiplied SDF anti-aliasing.

MIDI (src/midi/)

Enumerates MIDI input and output devices via the Win32 multimedia API (midiInGetDevCapsA / midiOutGetDevCapsA). Provides a simple MidiEngine with device listing and refresh.

Project structure

nob.c                              Build script (compiled to nob.exe)
nob.h                              nob build system (vendored, single-header)
src/
  main.cpp                         Entry point, unity build includes, Clay layout
  menus.cpp                        Menu bar setup
  theme.cpp                        Theme stub
  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
  renderer/
    renderer.h                     Renderer API (graphics-agnostic)
    renderer_dx12.cpp              DirectX 12 implementation, SDF pipeline, font atlas
  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)
  midi/
    midi.h                         MIDI device enumeration API
    midi_win32.cpp                 Win32 multimedia implementation
vendor/
  clay/
    clay.h                         Clay v0.14 (modified for MSVC C++ compatibility)

Modifications to vendor/clay/clay.h

Two targeted patches for MSVC C++ compatibility:

  1. CLAY__CONFIG_WRAPPER bypass (lines 158163): 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 ~31553858): 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 RAII, avoid STL containers or algorithms. Data is plain structs. Functions operate on those structs, or pointers to them.

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. Nothing to download or install beyond the Windows SDK.

  • nob.h — build system
  • Clay — single-header C layout library (v0.14, with MSVC C++ patches)
Description
Graphical interface for automatically recording samples from existing analog audio hardware
Readme 6.2 MiB
Languages
C 87%
Objective-C 12.2%
GLSL 0.8%