アプリサウンドデザイン は何をしますか?
アプリケーションにおいて、いつ、どのような、どのようにサウンドを表示すべきかについて設計判断を下します。これはオーディオエンジニアリング(sound-engineer)やレトロな効果音(win31-audio-design)に関するものではありません。このスキルは、UIサウンドにおける最も難しい疑問、「このインタラクションはそもそも音を鳴らすべきか?」そして、もし鳴らすならどんな音か、という問いに答えます。
使用するタイミング
使用するケース:
- Webアプリやモバイルアプリのどのインタラクションに音声フィードバックを付与するかの判断
- 通知、確認、エラーに適したサウンド特性の選択
- ElevenLabs、AudioCraft、Stable Audioを使用したAI生成UIサウンドの作成
- Web Audio APIを使用した手続き型サウンドの実装
- iOS/Androidでの触覚フィードバックと音声のペアリング
- 製品の音響ブランド・アイデンティティの確立
- アプリの既存サウンドデザインの、不快感と有用性の観点からの監査
使用しないケース:
- プロフェッショナルなオーディオミキシング/マスタリング -> sound-engineerを使用
- Windows 3.1テーマのシステムサウンド -> win31-audio-designを使用
- 音楽作曲やサウンドトラック -> sound-engineerを使用
- アクセシビリティのスクリーンリーダー音声 -> accessibility-expertを使用
- ゲーム用オーディオシステム(3D位置オーディオ、動的音楽) -> sound-engineerを使用
根本的な問い:これは音を鳴らすべきか?
インタラクションにフィードバックは必要か?
|
+-- ユーザーが開始したアクション(タップ、クリック、送信)?
| +-- 結果が画面上で見えるか?
| | +-- はい、かつ明らか --> サウンドはオプション(多くの場合スキップ)
| | +-- はい、だが微妙 --> サウンドは役立つ(穏やかな確認音)
| | +-- いいえ(バックグラウンド処理) --> サウンド推奨
| +-- アクションは破壊的か?
| +-- はい --> サウンド推奨(明確な警告音)
| +-- いいえ --> サウンドはオプション
|
+-- システムが開始したイベント(通知、アラート)?
| +-- ユーザーはアプリ内にいるか?
| | +-- はい --> 控えめなアプリ内サウンド
| | +-- いいえ --> 通知音(OSの規約に従う)
| +-- 時間に敏感か?
| +-- はい --> より緊急度/注意を引くサウンド
| +-- いいえ --> 無音またはアンビエントでも可
|
+-- アンビエント/雰囲気(バックグラウンド状態)?
+-- アプリに存在感が役立つか? --> 控えめなアンビエント
+-- ユーザーは作業中/集中中か? --> 無音
UIサウンド語彙
すべてのアプリケーションには、これらのカテゴリのサウンドが必要です。すべてのカテゴリが必要とは限りません。ほとんどのアプリは3~5つ必要です。
ティア1:必須(ほとんどのアプリが必要)
| サウンドタイプ | 目的 | 特性 | 持続時間 | 例 |
|---|---|---|---|---|
| 確認(Confirm) | アクション成功 | 明るく上昇するピッチ | 100~300ms | Slackメッセージ送信 |
| エラー(Error) | アクション失敗 | 低く平坦または下降 | 200~400ms | フォーム検証失敗 |
| 通知(Notification) | 新着情報到着 | 特徴的で中程度のエネルギー | 300~600ms | Slack受信メッセージ |
ティア2:洗練(こだわるアプリ向け)
| サウンドタイプ | 目的 | 特性 | 持続時間 | 例 |
|---|---|---|---|---|
| 遷移(Transition) | ビュー間のナビゲーション | 控えめなウィッシュ音やタップ音 | 50~150ms | iOSのページめくり |
| トグル(Toggle) | バイナリ状態変更 | シャープなクリック音やスナップ音 | 50~100ms | スイッチのオン/オフ |
| ホバー(Hover) | マウスオーバーフィードバック | かろうじて聞こえるチック音 | 20~50ms | メニューアイテムホバー |
| 選択(Selection) | リストから項目選択 | ソフトなポップ音やプルック音 | 50~150ms | ドロップダウン選択 |
| 削除(Delete) | 破壊的な削除 | 空洞なサウンドやスウッシュ音 | 150~300ms | ゴミ箱アクション |
ティア3:喜び(個性のあるアプリ向け)
| サウンドタイプ | 目的 | 特性 | 持続時間 | 例 |
|---|---|---|---|---|
| 達成(Achievement) | マイルストーン到達 | 音楽的でお祝い感 | 500ms~2s | Duolingoレッスン完了 |
| アンビエント(Ambient) | バックグラウンド存在感 | ループする雰囲気音 | 連続的 | Noisli、Forestアプリ |
| ブランドステイング(Brand Sting) | アプリ開閉 | 象徴的で記憶に残る | 500ms~1.5s | Netflixのタダム |
| イースターエッグ(Easter Egg) | 隠れた喜び | 遊び心があり予想外 | 可変 | コナミコマンド報酬 |
プラットフォーム規約
Apple(iOS / macOS)
Apple HIGは特定のオーディオ動作を義務付けています:
- システムサウンドは神聖: システムアラートサウンドをオーバーライドまたは置き換えてはいけません
- 消音スイッチを尊重: 物理的なミュートスイッチがオンの場合、アプリのサウンドは停止します(メディア再生を除く)
- オーディオセッションカテゴリが重要:
ambient— 他のオーディオと混ざり、消音スイッチを尊重soloAmbient— 他のオーディオを消音し、消音スイッチを尊重playback— 消音スイッチを無視(メディアアプリのみ)
- 触覚とサウンドのペアリング:
UIImpactFeedbackGeneratorをオーディオと共に使用
Appleのサウンド特性:
- クリーンなサイン波とフィルター処理されたトーン
- 最小限の倍音(純粋で、ブーンという感じではない)
- 短い減衰(サウンドが長引かない)
- システムサウンドと比較して一貫した音量
// iOS: システムサウンドを再生
import AudioToolbox
AudioServicesPlaySystemSound(1057) // 標準のキーボードクリック
// iOS: 触覚 + カスタムサウンド
let generator = UIImpactFeedbackGenerator(style: .light)
generator.impactOccurred()
// カスタムサウンドを同時に再生
マテリアルデザイン(Android)
Googleのサウンドデザイン原則:
- 機能性優先: サウンドは装飾ではなく情報を伝えるべき
- デフォルトで控えめ: UIサウンドはメディアよりも小さくする
- Androidでは触覚優先: 触覚フィードバックを優先し、触覚だけでは不十分な場合のみサウンドを追加
- 意味がある場合のみサウンドON: ほとんどのインタラクションではデフォルトを無音にする
マテリアルサウンド特性:
- 短くシャープな打楽器的サウンド
- 控えめな倍音成分(純粋なサイン波ではない)
- Appleよりもわずかに暖かい(より中域周波数)
- 低品質の電話スピーカーでも機能するように設計
Webアプリ
Webは最も弱いサウンド規約を持っており、自由度が高い一方で、不快感を与えるリスクも高くなります。
- オートプレイは絶対不可 — ブラウザはブロックし、ユーザーは嫌います
- 最初にユーザージェスチャーが必要: Web Audio APIは再生前にユーザーのインタラクションが必要
- 音量コントロールを提供: ユーザーがミュートや調整を常にできるように
- ヘッドホンユーザーを考慮: ノートPCスピーカーで問題ない音でも、ヘッドホンでは耳障りになる可能性あり
AIによるサウンド作成
ElevenLabs 効果音
最適な用途: 特定の特性を説明した、リアルで高品質なUIサウンド。
# 確認チャイムを生成
curl -X POST "https://api.elevenlabs.io/v1/sound-generation" \
-H "xi-api-key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "Short bright upward chime, digital, clean sine wave, 200ms, UI confirmation sound",
"duration_seconds": 0.5
}'
ElevenLabs向け効果的なプロンプト:
- 確認: "Short bright ascending two-note chime, clean digital, warm, 200ms"
- エラー: "Low hollow thud with slight buzz, digital, 300ms, not harsh"
- 通知: "Gentle three-note xylophone melody, friendly, 400ms"
- トグル: "Crisp mechanical click, plastic switch, 50ms"
- 削除: "Soft hollow swoosh moving downward, 200ms"
- 達成: "Bright ascending arpeggio, sparkly, celebratory, 1 second"
Meta AudioCraft(オープンソース)
最適な用途: 完全な制御を望み、APIコストをかけたくない開発者向け。
from audiocraft.models import AudioGen
from audiocraft.data.audio import audio_write
model = AudioGen.get_pretrained('facebook/audiogen-medium')
model.set_generation_params(duration=0.5)
# UIサウンドを生成
descriptions = [
"short digital confirmation beep, ascending pitch, clean",
"low error buzz, brief, not harsh, digital",
"gentle notification chime, two notes, pleasant",
]
wav = model.generate(descriptions)
for i, w in enumerate(wav):
audio_write(f'ui_sound_{i}', w.cpu(), model.sample_rate)
Stable Audio Open
最適な用途: より長いアンビエントサウンド、バックグラウンドテクスチャ、ブランドステイング。
import torch
from stable_audio_tools import get_pretrained_model
from stable_audio_tools.inference.generation import generate_diffusion_cond
model, model_config = get_pretrained_model("stabilityai/stable-audio-open-1.0")
# アンビエントバックグラウンドを生成
conditioning = [{
"prompt": "calm ambient digital texture, warm low hum, suitable for productivity app background, loopable",
"seconds_total": 10
}]
後処理チェックリスト
AI生成サウンドは出荷前にクリーンアップが必要です:
- 無音部分をトリミング — 先頭/末尾の無音を除去
- 音量を正規化 — すべてのUIサウンドの知覚ラウドネスを一定に
- フェードイン/アウト — 5~10msのフェードでクリックノイズを防止
- ダイナミックレンジを圧縮 — UIサウンドは一貫した音量に
- WAV(ネイティブ用)またはOGG/MP3(Web用、サウンドあたり50KB未満)でエクスポート
- ターゲットスピーカーでテスト — 電話スピーカーは200Hz以下の周波数をカット
Web Audio API: 手続き型サウンド
Webアプリの場合、サウンドを手続き的に生成することで、オーディオファイル自体が不要になります。バンドルサイズが小さくなり、即座に利用可能です。
class UISound {
private ctx: AudioContext | null = null;
private getContext(): AudioContext {
if (!this.ctx) {
this.ctx = new AudioContext();
}
return this.ctx;
}
/** 明るく上昇する確認音 */
confirm(): void {
const ctx = this.getContext();
const osc = ctx.createOscillator();
const gain = ctx.createGain();
osc.connect(gain);
gain.connect(ctx.destination);
osc.type = 'sine';
osc.frequency.setValueAtTime(600, ctx.currentTime);
osc.frequency.linearRampToValueAtTime(900, ctx.currentTime + 0.15);
gain.gain.setValueAtTime(0.15, ctx.currentTime);
gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.2);
osc.start(ctx.currentTime);
osc.stop(ctx.currentTime + 0.2);
}
/** 低く下降するエラー音 */
error(): void {
const ctx = this.getContext();
const osc = ctx.createOscillator();
const gain = ctx.createGain();
osc.connect(gain);
gain.connect(ctx.destination);
osc.type = 'triangle';
osc.frequency.setValueAtTime(400, ctx.currentTime);
osc.frequency.linearRampToValueAtTime(200, ctx.currentTime + 0.3);
gain.gain.setValueAtTime(0.12, ctx.currentTime);
gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.35);
osc.start(ctx.currentTime);
osc.stop(ctx.currentTime + 0.35);
}
/** トグルや選択用の控えめなクリック音 */
click(): void {
const ctx = this.getContext();
const osc = ctx.createOscillator();
const gain = ctx.createGain();
osc.connect(gain);
gain.connect(ctx.destination);
osc.type = 'square';
osc.frequency.setValueAtTime(800, ctx.currentTime);
gain.gain.setValueAtTime(0.08, ctx.currentTime);
gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.05);
osc.start(ctx.currentTime);
osc.stop(ctx.currentTime + 0.05);
}
/** 3音の通知メロディ */
notify(): void {
const ctx = this.getContext();
const notes = [523, 659, 784]; // C5, E5, G5
notes.forEach((freq, i) => {
const osc = ctx.createOscillator();
const gain = ctx.createGain();
osc.connect(gain);
gain.connect(ctx.destination);
osc.type = 'sine';
osc.frequency.setValueAtTime(freq, ctx.currentTime);
const start = ctx.currentTime + i * 0.12;
gain.gain.setValueAtTime(0, start);
gain.gain.linearRampToValueAtTime(0.12, start + 0.02);
gain.gain.exponentialRampToValueAtTime(0.001, start + 0.15);
osc.start(start);
osc.stop(start + 0.15);
});
}
}
// 使用例
const sound = new UISound();
document.querySelector('#submit')?.addEventListener('click', () => sound.confirm());
触覚-音声ペアリング(モバイル)
モバイルでは、触覚と音声はユニットとして設計されるべきです。触覚が先に到着し(即時の物理的フィードバック)、音声が後から到着します(確認と特性)。
ペアリングガイド
| インタラクション | 触覚 | 音声 | タイミング |
|---|---|---|---|
| ボタンをタップ | 軽いインパクト | 短いクリック | 同時 |
| トグルスイッチ | 中程度のインパクト | シャープなスナップ | 触覚が音声より10ms先行 |
| プル・トゥ・リフレッシュ | プル中の選択チック、完了時に通知 | 控えめなストレッチ音、確認チャイム | 触覚が20ms先行 |
| スワイプ削除 | しきい値で重いインパクト | 空洞なスウッシュ | 触覚はコミット時点 |
| ロングプレス | 硬く連続的 | 低く持続するハム音 | 触覚は音声と同時に開始 |
| 成功 | 成功パターン(トリプルタップ) | 上昇するアルペジオ | ビートに合わせて |
iOS実装
import UIKit
import AVFoundation
class FeedbackManager {
static let shared = FeedbackManager()
private let lightImpact = UIImpactFeedbackGenerator(style: .light)
private let mediumImpact = UIImpactFeedbackGenerator(style: .medium)
private let heavyImpact = UIImpactFeedbackGenerator(style: .heavy)
private let notificationFeedback = UINotificationFeedbackGenerator()
func tapConfirm() {
lightImpact.impactOccurred()
SoundPlayer.play(.confirm)
}
func errorShake() {
notificationFeedback.notificationOccurred(.error)
SoundPlayer.play(.error)
}
func deleteCommit() {
heavyImpact.impactOccurred()
SoundPlayer.play(.delete)
}
}
満足感のあるサウンドの心理学
なぜ一部のUIサウンドは「正しい」と感じられ、他のサウンドは「安っぽい」と感じられるのか:
満足感のあるサウンドの特性
| 特性 | なぜ機能するか | 例 |
|---|---|---|
| ピッチが上昇する | 進歩、楽観、完了を知らせる | 確認チャイムは上がる |
| 減衰が短い | 応答性が高く制御されていると感じる | Nintendoのメニューサウンド |
| 倍音の豊かさ | 有機的で温かみがあると感じる | Slackの「ノック」音 |
| 一貫した音量 | プロフェッショナルで予測可能と感じる | Appleのシステムサウンド |
| リズミカルな調和 | 意図的でデザインされていると感じる | Duolingoのストリークカウンター |
不快なサウンドの特性
| 特性 | なぜ不快か | 回避方法 |
|---|---|---|
| バリエーションなく繰り返し | 人間は慣れ、その後イライラする | 1日100回同じ音 |
| コンテキストに対して大きすぎる | 集中を妨げる |