Skip to content

Repository files navigation

Metronome Friend

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.


Features

Tempo & Timing

  • 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

Beat Patterns & Note Durations

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.

Sound & Visual

  • 5 click sounds: Wood Block, Chime, Drum, Snare, Click
  • Separate accent and normal beat volumes
  • Animated visual beat indicator
  • Background audio playback (iOS)

Platform Integrations

  • 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

Screenshots

Main view — tempo control and beat indicator Note duration and time signature selectors Presets — save, export, and import Settings — click sound and volume Settings — colorblind-friendly color schemes


Requirements

Minimum
Xcode 15.0+
iOS 17.0+
macOS 14.0+
Swift 5.9+

Building

# Clone the repo
git clone https://github.com/drewmerc/metronomeFriend.git
cd metronomeFriend

# Open in Xcode
open metronomeFriend.xcodeproj

Select your target (iOS or macOS), then Cmd+R to build and run.

Audio Files

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.


Architecture

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

Key Design Decisions

Protocol-oriented audioAudioPlaybackService 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 appAdjustBPMIntent and SetBPMIntent write to shared UserDefaults and call WidgetCenter.reloadAllTimelines(), so BPM changes from a widget are reflected instantly.


Testing

# 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 cycling
  • AVFoundationAudioService — buffer loading, cache hits, error paths
  • SettingsManager — UserDefaults round-trips, defaults on first launch

All 47 tests pass.


License

MIT License — see LICENSE for details.

Created by Andrew Mercurio.

About

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.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages