A professional metronome for iOS and macOS built with SwiftUI. Precise timing, multiple time signatures, five click sounds, home screen widgets, and Siri Shortcuts — everything a musician needs for focused practice.
Currently available via TestFlight — public App Store release coming soon.
- 30–300 BPM range with fine-grained +/- control and keyboard arrow key support
- High-precision engine using pre-calculated tick times and drift compensation
- Sample-accurate audio scheduling via
AVAudioPlayerNode - Tap tempo detection
| Time Signature | Feel |
|---|---|
| 4/4 — Common Time | Standard |
| 3/4 — Waltz | Triple |
| 2/4 — March | Duple |
| 6/8 — Compound | Compound |
| 5/4 — Take Five | Asymmetric |
| 7/8, 7/4, 9/8, 12/8, and more | Odd meters |
Note durations: whole, half, quarter, eighth, sixteenth, dotted eighth, dotted sixteenth, and triplets.
- 5 click sounds: Wood Block, Chime, Drum, Snare, Click
- Separate accent and normal beat volumes
- Animated visual beat indicator
- Background audio playback (iOS)
- Home screen widgets — small and large; adjust BPM directly from the widget without opening the app
- Siri Shortcuts — set tempo, change sound, change time signature, toggle playback
- Haptic feedback — on supported iOS devices
- Preset management — save and recall named configurations
| Minimum | |
|---|---|
| Xcode | 15.0+ |
| iOS | 17.0+ |
| macOS | 14.0+ |
| Swift | 5.9+ |
# Clone the repo
git clone https://github.com/drewmerc/metronomeFriend.git
cd metronomeFriend
# Open in Xcode
open metronomeFriend.xcodeprojSelect your target (iOS or macOS), then Cmd+R to build and run.
The app ships with a sine-wave fallback so it works immediately without audio assets. To use the full sound set, add .wav or .caf files named after each sound type to the Resources/Sounds/ folder and include them in the app target's "Copy Bundle Resources" build phase.
Expected filenames follow the pattern <sound>_normal.wav / <sound>_accent.wav, e.g. wood_block_normal.wav.
The project follows a layered MVVM architecture with clear separation between the engine, services, and UI.
metronomeFriend/
├── App/ # Entry point & root view
├── Core/
│ ├── Engine/ # MetronomeEngine, BeatPattern, NoteDuration, SoundType
│ ├── Models/ # MetronomeSettings, MetronomePreset
│ └── Constants/ # BPM range, defaults, logging subsystem
├── Services/
│ ├── Audio/ # AudioPlaybackService protocol + AVFoundation implementation
│ ├── Persistence/ # SettingsManager (UserDefaults), PresetManager (SwiftData)
│ └── Utilities/ # HapticService, TapTempoDetector, Logger extensions
├── UI/
│ ├── ViewModels/ # MetronomeViewModel — main app state
│ ├── Views/ # MetronomeView, SettingsView, PresetsView
│ └── Components/ # RoundedButton, OptionSelector, VolumeSlider
└── Features/
├── AppIntents/ # Siri Shortcuts & widget intents
├── Shortcuts/ # Keyboard shortcut bindings
└── Widgets/ # WidgetKit small & large widget
Protocol-oriented audio — AudioPlaybackService is a protocol, making AVFoundationAudioService swappable with MockAudioService in tests without any mocking framework.
Drift-free timing — instead of firing a timer and playing immediately, the engine pre-calculates the next beat timestamp and schedules audio against the audio clock. This keeps timing accurate over long sessions even under CPU load.
Intents without opening the app — AdjustBPMIntent and SetBPMIntent write to shared UserDefaults and call WidgetCenter.reloadAllTimelines(), so BPM changes from a widget are reflected instantly.
# Run the full test suite
xcodebuild test \
-project metronomeFriend.xcodeproj \
-scheme metronomeFriend \
-destination 'platform=macOS'The test suite covers:
MetronomeEngine— timing accuracy, BPM clamping, beat pattern cyclingAVFoundationAudioService— buffer loading, cache hits, error pathsSettingsManager— UserDefaults round-trips, defaults on first launch
All 47 tests pass.
MIT License — see LICENSE for details.
Created by Andrew Mercurio.




