Skip to content

About

What a sound is, using the classifier macOS already ships: 303 classes, per-window results with timestamps and confidence. On-device, no model download, no network.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

4 Commits

Folders and files

Repository files navigation

Swift SoundClassifier

What a sound is, using the classifier macOS already has, and which song it is, through Shazam's catalogue.

import SoundClassifier

for window in try SoundClassifier.classify(fileAt: url) {
    print(window.start, window.top?.name ?? "—", window.top?.confidence ?? 0)
}

try SoundClassifier.knownClasses().count   // 303

Why

SNClassifySoundRequest(classifierIdentifier: .version1) — Apple's built-in classifier, already installed. No model to download, no network, no permission prompt. 303 classes: speech and its varieties (shouting, whispering, laughter, crying), animals, vehicles, tools, alarms, water, music, and the noises a room makes.

Deliberately not music analysis. swift-music-analysis measures BPM, key and structure; this answers "what is that noise". They overlap only in that both listen.

Two things the API will not tell you

The window is fixed at 3 seconds. Audio shorter than one window produces zero results and no error — which reads as "nothing in this audio" rather than "too short to ask". So a short file throws instead, naming both durations.

The confidences are not calibrated. Apple documents no meaning for them. They order results reliably and mean nothing in absolute terms: a 0.8 is not "80% likely", it is "more than the 0.6 beside it". minimumConfidence is a noise gate, not a probability threshold, and this package says so rather than implying otherwise by naming it one.

Labels stay exactly as the classifier returns them — dog_bark, not "Dog bark" — because renaming would make the printed name and the filterable label disagree. name does the prettifying at the point of printing.

Which song it is

if let song = try await SongRecognizer.identify(fileAt: url) {
    print(song.title, song.artist ?? "", song.isrc ?? "", song.slicesAgreeing, "of", song.slicesAsked)
}

SongRecognizer asks Shazam's catalogue (ShazamKit) about 12-second slices of a file. Measured on macOS 27.0.1 with a released 6-minute track:

  • The catalogue answers only a team-signed binary. The binary must be signed by a team whose App ID has the ShazamKit App Service (developer.apple.com › Identifiers), with that bundle id inside the signature. A command-line tool embeds an Info.plist as __TEXT,__info_plist. No entitlement, provisioning profile or app bundle is needed. SongRecognizer.isSigned checks the running process.
  • An unsigned binary is told nothing useful. It gets the same ShazamCore error 102 as a slice that simply doesn't match. So check the signature first; this package can't tell the two apart.
  • Slices, not files. A whole track is refused (ShazamKit 201, duration invalid). Slices go to Shazam spread through the middle, at 40, 65, 20 and 85 %.
  • One slice is not believed. A slice of the bare DJ drum intro matched a different trance track. Slices are asked until two name the same recording (by ISRC), and the answer carries slicesAgreeing of slicesAsked.
  • What comes back: title, artist, genres, ISRC, Apple Music and web links, artwork, and where in the song the slice was (±2 s of the truth). A match took 1.8–2.6 s.

Only a fingerprint of each slice leaves the machine, not the audio.

Tested

7 tests on synthetic audio: the classifier is present without a download, the window really is 3 seconds, short audio is refused rather than silently empty, results come back strongest-first, and the confidence gate actually drops things. 7 more for songs: the slicing rule, signatures from stereo 48 kHz audio, the too-short and unreadable cases, the agreement vote (a lone or outvoted slice loses), and that a test build is not team-signed. The catalogue itself is checked on the signed hear release.

Licence

MIT.

About

What a sound is, using the classifier macOS already ships: 303 classes, per-window results with timestamps and confidence. On-device, no model download, no network.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages