# ck2739046/bpm-measurer architecture

> Architecture diagram of the GitHub repository ck2739046/bpm-measurer, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-11-10). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/ck2739046/bpm-measurer
- Repository: https://github.com/ck2739046/bpm-measurer

## Overview

BPM-Measurer is a desktop audio tool for inspecting audio and editing beat timing. The main workflow loads audio, prepares waveform and spectrogram data for synchronized visualization, and lets users edit timing points with undo/redo and metronome playback. Timing configurations can be imported or exported; command-line modes also support headless parsing and host notification. The graph reflects README capabilities and indexed references; some UI wiring is documented by the index rather than shown in excerpts, so only directly supported relationships are drawn.

Main entry points: [`App.xaml.cs`](https://github.com/ck2739046/bpm-measurer/blob/main/App.xaml.cs) (App startup), [`MainWindow.Timing.cs`](https://github.com/ck2739046/bpm-measurer/blob/main/MainWindow.Timing.cs) (Timing editor UI), [`MainWindow.Playback.cs`](https://github.com/ck2739046/bpm-measurer/blob/main/MainWindow.Playback.cs) (Playback controls), [`App.HeadlessExport.cs`](https://github.com/ck2739046/bpm-measurer/blob/main/App.HeadlessExport.cs) (Headless export)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_startup["Startup and export"]
  node_app["App startup<br/>[App.xaml.cs]"]
  node_headless["Headless export"]
  node_configparse["Config parser"]
  node_notifyfile["Notify JSON file"]
end

subgraph group_audio["Audio visualization"]
  node_audioinput["Audio input<br/>[BpmAudioLoader.cs]"]
  node_precompute["Audio precompute"]
  node_fft["FFTW native bridge<br/>[FftwNative.cs]"]
  node_waveview["Waveform tiles<br/>[WaveformTileSet.cs]"]
  node_spectview["Spectrogram tiles"]
  node_tiles["Tile transforms<br/>[TileSet.cs]"]
  node_waverender["Waveform renderer"]
  node_spectrender["Spectrogram renderer"]
  node_colormap["Spectrogram colormaps"]
  node_playback["Playback controls"]
  node_plots["Plot coordination"]
end

subgraph group_timing["Timing editor"]
  node_editor["Timing editor UI"]
  node_timingengine["Timing calculations<br/>[TimingEngine.cs]"]
  node_timingmodel["Timing points<br/>[TimingPoint.cs]"]
  node_beatgrid["Beat grid math<br/>[BeatGridMath.cs]"]
  node_undo["Undo and redo<br/>[TimingUndo.cs]"]
  node_metronome["Metronome controls"]
  node_click["Metronome audio<br/>[MetronomeClick.cs]"]
  node_configui["Config UI"]
  node_serializer["Config serializer"]
  node_segments["Segment row factory"]
end

subgraph group_support["Shared services"]
  node_localization["Localization resources<br/>[Langs.resx]"]
  node_debug["Crash logging<br/>[DebugLog.cs]"]
  node_loadlog["Load timing log"]
end

node_user(("User"))
node_host(("HachimiDX host"))

node_user -->|"launches"| node_app
node_host -->|"supplies options"| node_app
node_app -->|"dispatches"| node_headless
node_headless -->|"parses with"| node_configparse
node_headless -->|"writes JSON"| node_notifyfile
node_app -->|"opens GUI"| node_playback
node_playback -->|"loads audio"| node_audioinput
node_playback -->|"precomputes audio"| node_precompute
node_precompute -->|"uses FFTW"| node_fft
node_plots -->|"creates tiles"| node_waveview
node_plots -->|"creates tiles"| node_spectview
node_waveview -->|"renders with"| node_waverender
node_spectview -->|"renders with"| node_spectrender
node_spectrender -->|"uses palette"| node_colormap
node_waveview -->|"inherits transforms"| node_tiles
node_spectview -->|"inherits transforms"| node_tiles
node_user -->|"edits timing"| node_editor
node_editor -->|"recalculates"| node_timingengine
node_editor -->|"maintains points"| node_timingmodel
node_editor -->|"builds rows"| node_segments
node_editor -->|"uses grid math"| node_beatgrid
node_user -->|"undoes edits"| node_undo
node_user -->|"checks timing"| node_metronome
node_metronome -->|"queries timing"| node_timingengine
node_metronome -->|"plays clicks"| node_click
node_configui -->|"imports config"| node_configparse
node_configui -->|"exports config"| node_serializer
node_user -->|"imports or exports"| node_configui
node_app -->|"sets language"| node_localization
node_app -->|"logs crashes"| node_debug
node_playback -->|"records load timing"| node_loadlog

click node_app "https://github.com/ck2739046/bpm-measurer/blob/main/App.xaml.cs"
click node_headless "https://github.com/ck2739046/bpm-measurer/blob/main/App.HeadlessExport.cs"
click node_configparse "https://github.com/ck2739046/bpm-measurer/blob/main/TimingConfigParser.cs"
click node_audioinput "https://github.com/ck2739046/bpm-measurer/blob/main/BpmAudioLoader.cs"
click node_precompute "https://github.com/ck2739046/bpm-measurer/blob/main/PrecomputedAudioData.cs"
click node_fft "https://github.com/ck2739046/bpm-measurer/blob/main/FftwNative.cs"
click node_waveview "https://github.com/ck2739046/bpm-measurer/blob/main/TileRendering/WaveformTileSet.cs"
click node_spectview "https://github.com/ck2739046/bpm-measurer/blob/main/TileRendering/SpectrogramTileSet.cs"
click node_tiles "https://github.com/ck2739046/bpm-measurer/blob/main/TileRendering/TileSet.cs"
click node_waverender "https://github.com/ck2739046/bpm-measurer/blob/main/WaveformBitmapRenderer.cs"
click node_spectrender "https://github.com/ck2739046/bpm-measurer/blob/main/SpectrogramBitmapRenderer.cs"
click node_colormap "https://github.com/ck2739046/bpm-measurer/blob/main/WaveSpectrogramColormap.cs"
click node_playback "https://github.com/ck2739046/bpm-measurer/blob/main/MainWindow.Playback.cs"
click node_plots "https://github.com/ck2739046/bpm-measurer/blob/main/MainWindow.Plots.cs"
click node_editor "https://github.com/ck2739046/bpm-measurer/blob/main/MainWindow.Timing.cs"
click node_timingengine "https://github.com/ck2739046/bpm-measurer/blob/main/TimingEngine.cs"
click node_timingmodel "https://github.com/ck2739046/bpm-measurer/blob/main/Models/TimingPoint.cs"
click node_beatgrid "https://github.com/ck2739046/bpm-measurer/blob/main/BeatGridMath.cs"
click node_undo "https://github.com/ck2739046/bpm-measurer/blob/main/Undo/TimingUndo.cs"
click node_metronome "https://github.com/ck2739046/bpm-measurer/blob/main/MainWindow.Metronome.cs"
click node_click "https://github.com/ck2739046/bpm-measurer/blob/main/MetronomeClick.cs"
click node_configui "https://github.com/ck2739046/bpm-measurer/blob/main/MainWindow.Config.cs"
click node_serializer "https://github.com/ck2739046/bpm-measurer/blob/main/TimingConfigSerializer.cs"
click node_segments "https://github.com/ck2739046/bpm-measurer/blob/main/SegmentRowFactory.cs"
click node_localization "https://github.com/ck2739046/bpm-measurer/blob/main/Langs/Langs.resx"
click node_debug "https://github.com/ck2739046/bpm-measurer/blob/main/DebugLog.cs"
click node_loadlog "https://github.com/ck2739046/bpm-measurer/blob/main/LoadTimingLogger.cs"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_app,node_headless,node_configparse,node_notifyfile,node_user toneBlue
class node_audioinput,node_precompute,node_fft,node_waveview,node_spectview,node_tiles,node_waverender,node_spectrender,node_colormap,node_playback,node_plots toneAmber
class node_editor,node_timingengine,node_timingmodel,node_beatgrid,node_undo,node_metronome,node_click,node_configui,node_serializer,node_segments toneMint
class node_localization,node_debug,node_loadlog toneRose
class node_host toneIndigo
```

## Components

### Startup and export

- [App startup](https://github.com/ck2739046/bpm-measurer/blob/main/App.xaml.cs): `App.xaml.cs`
- [Headless export](https://github.com/ck2739046/bpm-measurer/blob/main/App.HeadlessExport.cs): `App.HeadlessExport.cs`
- [Config parser](https://github.com/ck2739046/bpm-measurer/blob/main/TimingConfigParser.cs): `TimingConfigParser.cs`
- **Notify JSON file**

### Audio visualization

- [Audio input](https://github.com/ck2739046/bpm-measurer/blob/main/BpmAudioLoader.cs): `BpmAudioLoader.cs`
- [Audio precompute](https://github.com/ck2739046/bpm-measurer/blob/main/PrecomputedAudioData.cs): `PrecomputedAudioData.cs`
- [FFTW native bridge](https://github.com/ck2739046/bpm-measurer/blob/main/FftwNative.cs): `FftwNative.cs`
- [Waveform tiles](https://github.com/ck2739046/bpm-measurer/blob/main/TileRendering/WaveformTileSet.cs): `TileRendering/WaveformTileSet.cs`
- [Spectrogram tiles](https://github.com/ck2739046/bpm-measurer/blob/main/TileRendering/SpectrogramTileSet.cs): `TileRendering/SpectrogramTileSet.cs`
- [Tile transforms](https://github.com/ck2739046/bpm-measurer/blob/main/TileRendering/TileSet.cs): `TileRendering/TileSet.cs`
- [Waveform renderer](https://github.com/ck2739046/bpm-measurer/blob/main/WaveformBitmapRenderer.cs): `WaveformBitmapRenderer.cs`
- [Spectrogram renderer](https://github.com/ck2739046/bpm-measurer/blob/main/SpectrogramBitmapRenderer.cs): `SpectrogramBitmapRenderer.cs`
- [Spectrogram colormaps](https://github.com/ck2739046/bpm-measurer/blob/main/WaveSpectrogramColormap.cs): `WaveSpectrogramColormap.cs`
- [Playback controls](https://github.com/ck2739046/bpm-measurer/blob/main/MainWindow.Playback.cs): `MainWindow.Playback.cs`
- [Plot coordination](https://github.com/ck2739046/bpm-measurer/blob/main/MainWindow.Plots.cs): `MainWindow.Plots.cs`

### Timing editor

- [Timing editor UI](https://github.com/ck2739046/bpm-measurer/blob/main/MainWindow.Timing.cs): `MainWindow.Timing.cs`
- [Timing calculations](https://github.com/ck2739046/bpm-measurer/blob/main/TimingEngine.cs): `TimingEngine.cs`
- [Timing points](https://github.com/ck2739046/bpm-measurer/blob/main/Models/TimingPoint.cs): `Models/TimingPoint.cs`
- [Beat grid math](https://github.com/ck2739046/bpm-measurer/blob/main/BeatGridMath.cs): `BeatGridMath.cs`
- [Undo and redo](https://github.com/ck2739046/bpm-measurer/blob/main/Undo/TimingUndo.cs): `Undo/TimingUndo.cs`
- [Metronome controls](https://github.com/ck2739046/bpm-measurer/blob/main/MainWindow.Metronome.cs): `MainWindow.Metronome.cs`
- [Metronome audio](https://github.com/ck2739046/bpm-measurer/blob/main/MetronomeClick.cs): `MetronomeClick.cs`
- [Config UI](https://github.com/ck2739046/bpm-measurer/blob/main/MainWindow.Config.cs): `MainWindow.Config.cs`
- [Config serializer](https://github.com/ck2739046/bpm-measurer/blob/main/TimingConfigSerializer.cs): `TimingConfigSerializer.cs`
- [Segment row factory](https://github.com/ck2739046/bpm-measurer/blob/main/SegmentRowFactory.cs): `SegmentRowFactory.cs`

### Shared services

- [Localization resources](https://github.com/ck2739046/bpm-measurer/blob/main/Langs/Langs.resx): `Langs/Langs.resx`
- [Crash logging](https://github.com/ck2739046/bpm-measurer/blob/main/DebugLog.cs): `DebugLog.cs`
- [Load timing log](https://github.com/ck2739046/bpm-measurer/blob/main/LoadTimingLogger.cs): `LoadTimingLogger.cs`

### Other components

- **User**
- **HachimiDX host**

## Connections

- User → App startup: launches (evidence: `README.md`)
- HachimiDX host → App startup: supplies options (evidence: `README.md`)
- App startup → Headless export: dispatches (evidence: `App.xaml.cs`)
- Headless export → Config parser: parses with (evidence: `App.HeadlessExport.cs`)
- Headless export → Notify JSON file: writes JSON (evidence: `App.HeadlessExport.cs`)
- App startup → Playback controls: opens GUI (evidence: `README.md`)
- Playback controls → Audio input: loads audio (evidence: `MainWindow.Playback.cs`)
- Playback controls → Audio precompute: precomputes audio (evidence: `MainWindow.Playback.cs`)
- Audio precompute → FFTW native bridge: uses FFTW (evidence: `PrecomputedAudioData.cs`)
- Plot coordination → Waveform tiles: creates tiles (evidence: `MainWindow.Plots.cs`)
- Plot coordination → Spectrogram tiles: creates tiles (evidence: `MainWindow.Plots.cs`)
- Waveform tiles → Waveform renderer: renders with (evidence: `TileRendering/WaveformTileSet.cs`)
- Spectrogram tiles → Spectrogram renderer: renders with (evidence: `TileRendering/SpectrogramTileSet.cs`)
- Spectrogram renderer → Spectrogram colormaps: uses palette (evidence: `SpectrogramBitmapRenderer.cs`)
- Waveform tiles → Tile transforms: inherits transforms (evidence: `TileRendering/WaveformTileSet.cs`)
- Spectrogram tiles → Tile transforms: inherits transforms (evidence: `TileRendering/SpectrogramTileSet.cs`)
- User → Timing editor UI: edits timing (evidence: `README.md`)
- Timing editor UI → Timing calculations: recalculates (evidence: `MainWindow.Timing.cs`)
- Timing editor UI → Timing points: maintains points (evidence: `MainWindow.Timing.cs`)
- Timing editor UI → Segment row factory: builds rows (evidence: `MainWindow.Timing.cs`)
- Timing editor UI → Beat grid math: uses grid math
- User → Undo and redo: undoes edits (evidence: `README.md`)
- User → Metronome controls: checks timing (evidence: `README.md`)
- Metronome controls → Timing calculations: queries timing (evidence: `MainWindow.Metronome.cs`)
- Metronome controls → Metronome audio: plays clicks (evidence: `MainWindow.Metronome.cs`)
- Config UI → Config parser: imports config (evidence: `MainWindow.Config.cs`)
- Config UI → Config serializer: exports config (evidence: `MainWindow.Config.cs`)
- User → Config UI: imports or exports (evidence: `README.md`)
- App startup → Localization resources: sets language (evidence: `App.xaml.cs`)
- App startup → Crash logging: logs crashes (evidence: `App.xaml.cs`)
- Playback controls → Load timing log: records load timing (evidence: `MainWindow.Playback.cs`)
