Aller au contenu

Whoa Type

A macOS utility that adds sound to typing and clicks, with 38 built-in sound packs, previews, and a native audio engine.

  • Swift
  • SwiftUI
  • Core Graphics
  • AVAudioEngine
Whoa Type: character in every keystroke.

Character in every keystroke.

A utility for macOS 26.5 and later that gives your keyboard, mouse, and trackpad a voice. Everything lives in the menu bar, with 38 built-in sound packs.

Features · Architecture


About

Part of the appeal of a mechanical keyboard is its sound: a deeper key, a heavier space bar, a little texture with every press.

Whoa Type brings that idea to a native app. Choose a sound, adjust the volume, and let the app accompany each press and release.

Everything runs locally: no account, no network service, and no recording of typed text. Global input monitoring requires permission from macOS. Sound is off on first launch.


✨ Features

⌨️ A different feel across the keyboard

Sound plays on both press and release. Automatic repeats from holding a key are ignored.

Space, Return, and Delete carry more weight; modifier keys sound lighter. Across the keyboard, the sound shifts from warmer and deeper on the left to brighter and higher on the right, with matching stereo placement.

Physical ANSI, ISO, and JIS keyboard geometries are selectable in Settings.

🎛️ 38 packs with previews

The built-in library lets you hear a pack before selecting it. Preview uses the same engine as live typing and works without Input Monitoring permission, or while Sound is off. It follows your volume setting.

Pack names describe the recordings rather than identifying switch hardware. In this initial library, each pack reuses the same keyboard recording for press and release; differences between keys come from audio processing.

  • Library · selection and preview

🖱️ Mouse and trackpad clicks

Left, right, and auxiliary buttons trigger their own press and release sounds.

Six press recordings alternate randomly without immediate repeats. Mouse and trackpad share this library and use the same volume as the keyboard. Movement, scrolling, and gestures produce no sound.

⚙️ At home in the menu bar

Toggle sound and open Settings from the menu. A dedicated window groups playback, the sound library, permissions, and launch at login.

Volume, selected pack, keyboard geometry, and sound activation persist between launches. Closing Settings keeps the utility running.


🧱 Architecture

One application, with separate responsibilities for the interface, input capture, sound loading, and audio rendering.

whoa_typeApp.swift — Entry point and SwiftUI scenes
App/ — Application coordination and state
AppShell/ — Menu, settings, and permission onboarding
Input/ — Passive capture, keys, and buttons
Permissions/ — Input Monitoring access
SoundPacks/ — Manifests, validation, and PCM loading
Audio/ — Bounded queues, mixing, and audio output
Settings/ — Preferences and launch at login
Resources/SoundPacks/ — 38 bundled packs
Package.swift — Testable core through Swift Package Manager
Tests/WhoaTypeCoreTests/ — Swift Testing tests
Tools/ — Audio preparation, probes, benchmark, and distribution

🧠 The core: separating input from audio rendering

Most of the work happens between a physical input and the sound it produces.

  • Passive listening. The Core Graphics tap observes events without modifying them. Keyboard input is handled through physical key codes, without converting it to text.
  • A bounded queue. Capture sends small audio commands through a single-producer, single-consumer queue synchronized with atomic operations. If the queue is full, the incoming sound is dropped without waiting.
  • Sounds ready before you type. Manifests are validated, then files are decoded and converted to PCM on a dedicated queue.
  • A 64-voice mixer. The renderer layers sounds, adjusts pitch, tone, and stereo placement, and applies fades during transitions.
  • Coordinated pack switching. The old sound bank stays available until the renderer acknowledges the change. Preview pauses live capture, then restores the selected pack.

The app distinguishes missing permission from capture failure. macOS Secure Input contexts can suppress keyboard sounds; that boundary is respected.


🛠️ Tech stack

  1. Application

    • Swift
    • SwiftUI
    • Observation
    • macOS 26.5 minimum
  2. Input

    • Core Graphics
    • CGEventTap (listenOnly)
    • CFRunLoop
  3. Audio

    • AVFoundation
    • AVAudioEngine
    • AVAudioSourceNode
    • AVAudioConverter
  4. Synchronization

    • Synchronization.Atomic
    • DispatchQueue
    • Bounded SPSC queues
  5. Preferences

    • UserDefaults
    • ServiceManagement (SMAppService)
  6. Quality

    • Swift Package Manager
    • Swift Testing
    • Probes and synthetic benchmark

No third-party runtime dependencies.


💡 What I learned

  • Prepare before playing. Decoding samples and allocating voices ahead of time keeps the rendering path short and bounded.
  • Give each queue a clear responsibility. The interface, capture, loading, and audio control run at different rhythms. Explicit handoffs make pack changes and cancellations easier to manage.
  • Create texture from a small set of recordings. Pitch, gain, filtering, and stereo position can give the same recording a different character.
  • Separate benchmarks from the real experience. Synthetic tests verify the mixer; they do not measure the delay between a physical key press and the speaker. That still needs hardware validation.

📸 Screenshots

  • Menu · sound toggle and settings

  • Playback · volume and keyboard geometry

  • Permissions · Input Monitoring


🛣️ Roadmap

  • SwiftUI menu bar interface
  • Passive keyboard and button capture
  • Library of 38 packs with previews
  • Pitch, tone, and stereo placement variations
  • Persistent settings and launch at login
  • Core tests and synthetic benchmark
  • Complete permission validation in the signed app
  • Validate keyboard geometries, audio devices, and sleep/wake on hardware
  • Measure physical latency and complete Instruments profiling
  • Add distinct keyboard release recordings
  • Complete recording provenance and license documentation
  • Notarize the application and publish a GitHub release