1# Clover Pitch
2
3A native macOS real-time pitch visualiser — a from-scratch clone of
4[pitchreader.com](https://pitchreader.com). It listens to a microphone, detects
5the fundamental frequency you sing or play, and scrolls it across a piano-roll
6timeline against note gridlines.
7
8Live only — there is no recording mode.
9
10## Features
11
12- **Live pitch-over-time graph** — a scrolling piano-roll where the last few
13 seconds of your pitch are drawn as a glowing trace, weighted by detection
14 confidence. Sharps/flats rows are shaded like piano keys; octave C lines are
15 emphasised and labelled.
16- **Active note readout** — a large current-note display with octave, exact Hz,
17 and a ±50-cent tuner needle ("in tune" when within 5¢).
18- **Top bar**
19 - **Microphone** — pick any CoreAudio input device; switching is live.
20 - **Transpose** — ±12 semitones; shifts every displayed label (like a capo).
21 - **Note labels** — Sharps, Flats, Solfège (fixed Do), or German (H/B).
22 - **Range** — vocal/instrument presets (Bass … Soprano, Wide, Full) that set
23 the visible vertical span.
24
25## How it works
26
27- `AudioEngine` captures mono audio via `AVAudioEngine`, down-mixes, and runs a
28 YIN pitch detector (`PitchDetector.swift`) at a 512-sample hop over a 2048
29 window. Detected samples land in a lock-guarded ring buffer.
30- `PitchGraphView` is a SwiftUI `Canvas` driven by `TimelineView(.animation)`;
31 each frame it snapshots the ring buffer and repaints the trace against the
32 note grid. The clock is `CACurrentMediaTime()` so the trace stays in sync
33 with the audio timeline.
34- Input-device enumeration/selection goes through the CoreAudio HAL
35 (`CoreAudioDevices.swift`), and the selected device is set on the input
36 AudioUnit via `kAudioOutputUnitProperty_CurrentDevice`.
37
38The detector is accurate to a fraction of a cent on synthetic tones across the
39full E2–A5 range (see the note-name test compiled from `PitchDetector.swift`).
40
41## Build & run
42
43```sh
44./run.sh # builds a signed Pitch.app and launches it
45./build.sh # just build Pitch.app
46```
47
48The app must be a signed `.app` bundle (not a bare binary) so the microphone
49TCC prompt appears — `NSMicrophoneUsageDescription` lives in the generated
50`Info.plist`. `build.sh` signs with the first available codesigning identity,
51or run `./build.sh --create-cert` once to mint a reusable self-signed
52`Pitch Dev` identity (same pattern as the Sequencer).