万華鏡アプリの BGM を「コード」じゃなく「モチーフ」で作り直した話
| デザイン | 万華鏡
タグ: #音楽 #UX #デザイン
万華鏡アプリで流していたヒーリング BGM が、聴いているうちに飽きる。コード進行で作るのをやめて、モチーフベースに作り直したら印象が変わった話です。
ヒーリング BGM の難しさ
万華鏡アプリは「画面をぼーっと眺めるアプリ」なので、BGM の良し悪しが体験に直結します。初期版では、3 つのコード(I → IV → V)を繰り返すヒーリング系の BGM を流していました。
が、自分で長時間流しっぱなしにしてみると、5 分くらいで飽きるのです。コード進行のループ感が、リラックスどころか軽くストレスになる。
モチーフベースという発想
音楽理論的にいうと、コードベースの BGM は「縦の構造」を組み立てる作り方です。これに対して、モチーフベースは「短い旋律フレーズ(モチーフ)」を複数用意し、それを変奏・転調しながら繋いでいく「横の構造」のアプローチです。
万華鏡のように「常に変化していく視覚」と相性が良いのはモチーフベースだろう、と判断して BGM を作り直しました。
実装はランダム遷移
4 つのモチーフ(各 8 小節程度)を用意し、再生中はそれらをランダムに遷移させます。同じモチーフが連続しないようにメモリを持たせ、転調も挿入して飽きにくくしました。
コードベースの BGM に比べて、聴いていて「次に何が来るか分からない」感が出るので、ぼーっと眺めている時間が延びました。
遷移ロジック自体はとてもシンプルで、「直前と同じモチーフは選ばない」「キーは小さい確率で転調する」の 2 ルールだけです。
class MotifScheduler {
MotifScheduler(this.motifs, {Random? rng})
: _rng = rng ?? Random();
final List<Motif> motifs;
final Random _rng;
Motif? _previous;
int _key = 0; // semitone offset
Motif next() {
final candidates = motifs.where((m) => m != _previous).toList();
final picked = candidates[_rng.nextInt(candidates.length)];
if (_rng.nextDouble() < 0.15) {
const transposes = [-2, -1, 1, 2];
_key = (_key + transposes[_rng.nextInt(transposes.length)]) % 12;
}
_previous = picked;
return picked.transposed(_key);
}
}
アプリ名を「万華鏡」へ
BGM リメイクと同時に、アプリ名を「万華鏡」というシンプルな日本語ひとことに変更しました。サブタイトルも「ヒーリング訴求」に変え、「物理シミュレーション」と「カメラ取り込み」を打ち出すようにしました。
アプリの方向性として「数学的な美しさ」「リラックス」「触っていて気持ちいい」というキーワードを軸に据え直したのです。
スパークル 5 段階の設定
ユーザーごとに「派手さ」の好みが違うので、スパークル(キラキラ感)を 5 段階で調整できるようにしました。
- レベル 1: 控えめ(ヒーリング向け)
- レベル 3: 標準
- レベル 5: 派手(賑やかし向け)
設定が増えると UI が散らかるので、5 段階に絞った上で「変えたい人だけ深掘りできる」階層に置きました。
カラー+写真+ブレンドのデバッグ画面
開発中、テッセレーション(敷き詰め)のデバッグ用画面で「色」「写真」「ブレンド」モードを切り替えられる隠し機能を作り、これが意外と楽しかったので一部を製品 UI にも組み込みました。
開発ツールがそのまま製品の機能になるパターンは、個人開発ならではです。
まとめ
- ループする BGM は意外と飽きる、モチーフ遷移にすると延命できる
- アプリ名・サブタイトル・BGM はセットで方向性を再定義できる
- 派手さは段階で可変にして、好みに合わせる
「ヒーリング」を本気で作るのは、思ったより難しい仕事でした。