Library / Custom Core Haptics patterns

Heartbeat (lub-dub loop)

A health, meditation, or connection feature that plays a realistic looping heartbeat.

0ms 165ms 330ms 495ms 660ms
Feel
A strong round "lub" and a softer "dub", repeating ~60 bpm. Low sharpness keeps it organic.
APIs
CHHapticAdvancedPatternPlayerloopEnabled
Minimum OS
iOS 13+
Raw .md
Core Haptics
import CoreHaptics

final class HeartbeatPlayer {
    private let engine: CHHapticEngine
    private var player: CHHapticAdvancedPatternPlayer?

    init?() {
        guard CHHapticEngine.capabilitiesForHardware().supportsHaptics,
              let engine = try? CHHapticEngine() else { return nil }
        self.engine = engine
        try? engine.start()
    }

    func start(bpm: Double = 60) throws {
        let beat = 60.0 / bpm
        func hit(at t: TimeInterval, intensity: Float) -> CHHapticEvent {
            CHHapticEvent(eventType: .hapticTransient, parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: intensity),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.15),
            ], relativeTime: t)
        }

        // lub ... dub ......... (loop)
        let events = [hit(at: 0, intensity: 1.0),
                      hit(at: 0.14, intensity: 0.6)]

        let pattern = try CHHapticPattern(events: events, parameters: [])
        player = try engine.makeAdvancedPlayer(with: pattern)
        player?.loopEnabled = true
        player?.loopEnd = beat          // loop length = one full beat
        try player?.start(atTime: CHHapticTimeImmediate)
    }

    func stop() {
        try? player?.stop(atTime: CHHapticTimeImmediate)
    }
}

// let heart = HeartbeatPlayer()
// try? heart?.start(bpm: 72)
Copied