ちょっとしたときに、
あらかじめ用意されているシステム音を使いたい。
AudioServicesPlaySystemSound(1000)
AudioServicesPlaySystemSound(_:) | Apple Developer Documentation
これだけで音が鳴る。
「1000」 は SystemSoundID というもののようなので、
「どんな音が鳴るのかリスト」を探すが、
公式で見つけられなかった。
以下にそれらしきもの。
AudioServices - iPhone Development Wiki
結構、古そうなので今どきの状態を確認したい。
OSやバージョンなど環境によっても違うっぽい。
なので、コードからのぞいてみる。
欠番ID
ID は 2000 ぐらいまでの整数なのですが、
非公式のリストを見る限り、番号が歯抜け状態。
音声データの長さで「欠番らしき」を見分ける。
実際に再生してその時間を取得しました。
let start = Date()
AudioServicesPlaySystemSoundWithCompletion(1000) {
let elapsed = Date().timeIntervalSince(start)
print(elapsed)
}
// 1.566209077835083
AudioServicesPlaySystemSoundWithCompletion(_:_:) | Apple Developer Documentation
おおまかに 再生時間 50ミリ秒 以下が欠番っぽい。
グリッドでボタン
ボタンを並べて Preview や Simulator や 実機 でどんな音があるのか確かめます 。
@Observable final class Sound: Identifiable { | |
var id: SystemSoundID | |
var duration: Double | |
var playing: Bool | |
var valid: Bool { self.duration > 0.01 } | |
init(_ id: Int, _ duration: Double, _ playing: Bool) { | |
self.id = SystemSoundID(id) | |
self.duration = duration | |
self.playing = playing | |
} | |
} | |
struct SystemSoundGrid: View { | |
@State private var sounds: [Sound] = [] | |
@State private var scrollPositionId: SystemSoundID? | |
var body: some View { | |
let columns: [GridItem] = Array(repeating: .init(.flexible()), count: 5) | |
VStack { | |
ScrollView { | |
LazyVGrid(columns: columns) { | |
ForEach(sounds) { sound in | |
Button { | |
sound.playing = true | |
AudioServicesPlaySystemSoundWithCompletion(sound.id) { | |
Thread.sleep(forTimeInterval: 0.1) | |
sound.playing = false | |
} | |
} label: { | |
VStack { | |
Text(String(sound.id)) | |
if sound.duration > Double.zero { | |
Text(String(format: "%.3f", sound.duration)) | |
} | |
} | |
.font(.system(size:10)) | |
.frame(maxWidth: .infinity) | |
.lineLimit(1) | |
} | |
.buttonStyle(.borderedProminent) | |
.disabled(sound.playing && sound.valid) | |
} | |
} | |
} | |
.padding() | |
.scrollPosition(id: $scrollPositionId) | |
.onChange(of: sounds.last?.id) { _, bottomId in | |
scrollPositionId = bottomId | |
} | |
.task { | |
await generate() | |
} | |
} | |
} | |
private func generate() async { | |
for i in 0 ..< 2000 { | |
sounds.append(Sound(i, Double.zero, true)) | |
let sound = await withCheckedContinuation { continuation in | |
let start = Date() | |
AudioServicesPlaySystemSoundWithCompletion(SystemSoundID(i)) { | |
let elapsed = Date().timeIntervalSince(start) | |
continuation.resume(returning: Sound(i, elapsed, false)) | |
} | |
} | |
sounds.remove(at: sounds.count - 1) | |
if sound.valid { | |
sounds.append(sound) | |
} | |
} | |
} | |
} | |
#Preview { | |
SystemSoundGrid() | |
#if os(macOS) | |
.frame(width: 300, height: 300) | |
#endif | |
} |
極力、deprecated な関数は避けていきたいです。
まとめ
実際に音声ファイルを作成する前に、雰囲気を確認したいときに使いたくなります。
しかし、ID が分からない。
そんな人用。
ファイルで探すなら、各環境内でディレクトリ名で走査するといいのですね !
Library/Audio/UISounds
❯ tree .
.
├── 3rd_party_critical.caf
├── AuthenticationMatch_Full.caf
├── AuthenticationMatch_Short.caf
...
├── ussd.caf
├── warsaw.caf
└── wheels_of_time.caf
4 directories, 321 files
あと、アプリとかショートカットもありました。