こんにちは!新しい音楽体験研究所 “チームサイリウム” です。チームサイリウムは今回のMaker Faire Tokyo 2023出展に向けて、「サイリズム」という音ゲーのプロトタイプを制作し、出展しました。今回はこのサイリズムの内部の仕組みについてチームメンバー全員で解説する記事を書いてみました!
- サイリズムとは (河野)
- システム構成 (河野)
- センサー (寺島)
- 描画 (澁谷)
- 3Dモデル (塚本)
- 実現できなかったこと (全員)
- まとめ (全員)
サイリズムとは
サイリズムとは「音楽 × サイリウム × ジェネラティブアート」をコンセプトにした体験型音楽ゲームのプロトタイプ作品です。プレイヤーが楽曲に合わせてサイリウムをテンポよく振ると、振りに応じてジェネラティブアートと呼ばれるデジタルアートをベースにしたグラフィックがディスプレイ上に生成されていきます。振りのテンポ感がアートの生成過程に反映される仕組みとなっているため、プレイヤーはサイリウムを振りながら楽曲を楽しみ、同時に唯一無二のアートができていく様子を楽しむことができます。
写真は株式会社ジュニさんが来訪された際のものになります。 Xアカウント:@junni_jp
従来の音楽ゲームでは、譜面と呼ばれる正解パターンのものが用意され、その正解パターンに合わせて正確に(そしてスマートに)アクションをしていくことが醍醐味かと思いますが、サイリズムでは譜面に当たるような正解パターンを用意せず、サイリウムが振られるテンポからのみをゲーム結果(アート)に反映するという仕組みを採用しました。この仕組みによって熟練したスキルや慣れがなくても、自分なりのリズムでサイリウムを振りながら、誰でも楽しめるゲームを目指しました。実際、Maker Faire Tokyo 2023当日は小さなお子様から大人の方まで幅広い層の方にゲームをプレイしてもらうことができました。
システム構成
サイリズムのシステム構成は以下の通りです。
- サイリウムの内部にM5StickC Plusを内蔵し、加速度センサーとジャイロセンサーから移動量を取得
- M5StickC Plusのセンサーから取得した移動量から高速フーリエ変換(FFT)により、周波数成分(=振りのテンポ)を抽出する
- 直近の代表周波数とそれまでの周波数移動平均との差分から”盛り上がり度”を内部的に算出する
- ”盛り上がり度”に応じて、ディスプレイ上に描画するアートを生成する
以下のセクションで各パーツについて解説します。
センサーについて
サイリウムの内蔵されていたセンサーでは、以下の3つを行いました。
- ジャイロの値取得
- 盛り上がり度合いの計算
- サイリウムの発光色の変更
これらはすべてM5StickC Plusを用いて取得した値をもとに処理を行っています。
ジャイロの値取得
M5StickC Plusには、以下の値を取得することのできるセンサーが備わってます。
- 加速度(X, Y, Z)
- ジャイロ(X, Y, Z)
今回はジャイロの値のみを使用するので、ジャイロについて簡単に説明します。
M5StickC Plus とジャイロ3軸(X, Y, Z軸) 画像出典元: Plus ESP32-PICOミニIoT開発ボード iotキット フィンガーコンピューターカラーLCD
これらの各軸の角速度を取得できるのが、ジャイロセンサーになります。
M5StickC Plusから角速度を取得するのに、Arduinoを使用しています。Arduinoを使用して、ジャイロセンサーの値を取得するには、以下のコードを書く必要があります。
float gyroX = 0, gyroY = 0, gyroZ = 0;
M5.IMU.getGyroData(&gyroX, &gyroY, &gyroZ);
取得した値は、シリアル通信を用いて、Processingに送っています。Processingに値を送るときの処理は以下になります。
Serial.printf("%.2f,%.2f,%.2f, o/s \r\n", &gyroX, &gyroY, &gyroZ)
※ ここではあくまでジャイロの値をシリアル通信で送る例を示してます。
M5StickC Plus は、常にループ処理を行っています。以下の作業を繰り返し行うようになってます。
- ジャイロセンサーの値を取得
- 盛り上がり度合い計算のための値を計算
- サイリウムが光るようにジャイロの値から色を計算
- シリアル通信でProcessingに必要な値を送信
シリアル通信で送った文字列は、Processing側で処理し、値として使えるようにしています。また、盛り上がり度合いの計算については次の章で説明します。
実際にジャイロセンサーを取得する際に役に立った記事は以下です。
また、シリアル通信については以下を参考にすると良さそうです。
ここまでがジャイロの値取得についてです。次は盛り上がり度合いの計算方法について説明していきます。
盛り上がり度合いの計算
盛り上がり度合いは、一定のテンポでサイリウムを振れている事を目安にして、計算することにしました。曲などのテンポとは関係なく、一定のリズムで振れれば高得点が出るように取り決めました。Maker Faire Tokyo 2023では、小さなお子様が多く来場します。したがって、曲のテンポが分からなくてもある程度高得点を出せるようにしたいという思惑がありました。
「一定のテンポでサイリウムを振れている」ことを検知するために、振っているサイリウムの周期性を取得する事になりました。
X軸を軸として振った時に周期性がみれるグラフ
上記のように、実際にサイリウムを振った時のジャイロセンサーの値の変化の仕方を見ると、周期性が表れていました。そこで、今回は高速フーリエ変換を使用して、周期性を取得する事になりました。Arduinoには、高速フーリエ変換を行うことができるライブラリがあります。そのライブラリ ”arduinoFFT” を使用して、指定の値をフーリエ変換しました。
周期性を見るために以下の手順を踏みました。
- ジャイロのXYZの値を取得する
- 各軸の値を足し合わせる
- 足し合わせた値を高速フーリエ変換する
- 変換した結果の代表周波数を振りのテンポとする
この時のテンポが一定であればあるほど、高得点になるという仕組みにしていました。
任意のフレームごとにテンポを出し、次のテンポと比較をして、差が小さければ小さいほどスコアは高くなるように補正をかけました。この時、スコアは 0 〜 100の値になるように調整しています。
Maker Faire Tokyo 2023本番も上記の実装で遊んでもらうことになりました。良かった点・悪かった点があったため、それぞれ列挙します。
〜良かった点〜
- サイリウムを振ると点数が上がる
- 振っているか否かで、高得点と低得点がはっきり分かれたため、アートに良し悪しが出た
- 振ったことは検知できるような仕組みになっていた
〜悪かった点〜
- 厳密に一定のテンポで振ることで、点数が高くなる仕組みでは無かった
- 自分が実装した方法が本当に意図していた点数になっているか分からなかった
- 実装上でFFTを使用した処理がコード的にあっているか担保できなかった
- 採点よりは描画の仕組みに助けられている感が強い
今後の課題として、「どのように振ったか?」や「曲のテンポに合っているか?」を認識できる機能を追加し、サイリウムを振ることでアートを描いているという感覚をより強く感じられるようにすることが挙げられます。
澁谷太智