時区間駆動型API
v0.4.0 で新しく実装されたAPI です
利用例を見たい方は サンプルコード textalive-app-lyric-sheet の最新版をご参照ください
時区間駆動型APIとは?
従来から player.findBeat(player.timer.position) のようにして特定の時刻に関係する音楽的要素(ビート、サビ、発声中のフレーズや単語など)を取得することはできました
これを「時刻駆動型API (time-driven API)」と呼びます
新しく実装されたAPIでは player.findBeatChange(lastPosition, position) のようにして特定の区間に起きたこと(起きること)をまとめて取得できるようになりました
これを「時区間駆動型API (time-range-driven API)」と呼びます
描画ループごとに呼び出すことを念頭に設計されており、楽曲再生中にパーティクルを生成したり破棄したりといった処理に便利です
具体的には、 Web標準の requestAnimationFrame() や p5.js の loop() といった描画ループにおいて、最後に呼び出されたときの再生時刻 lastPosition を記録しておき、次の呼び出し時に現在の再生時刻 position までの区間を引数で与えることにより、各フレームの描画で行うべき処理をまとめて計算できます
例えば以下のような使い方ができます:
code:script.js
// https://github.com/TextAliveJp/textalive-app-lyric-sheet/blob/ff4918ed88a15a571739d4e5e452a0ff80c63c73/script.js#L121-L138
const beats = player.findBeatChange(lastTime, position);
if (
lastTime >= 0 &&
// ↑初期化された直後はビート検出しない
beats.entered.length > 0
// ↑二拍ごとにしたければ
// && beats.entered.find((b) => b.position % 2 === 1)
// のような条件を足してチェックすればよい
) {
// ビート同期のアニメーションを発火させる
requestAnimationFrame(() => {
bar.className = "active";
requestAnimationFrame(() => {
bar.className = "active beat";
});
});
}
同じ処理を「時刻駆動型API」で書いた場合と「時区間駆動API」で書いた場合の比較については、 サンプルコード textalive-app-lyric-sheet のdiff をご確認ください
APIの返値は?
返値は以下のような構造を持ちます:
上の例では entered プロパティのみを利用しています
code:TimedObjectsInRange.ts
// https://developer.textalive.jp/packages/textalive-app-api/interfaces/TimedObjectsInRange.html
interface TimedObjectsInRange<T> {
// T は取得したい情報(イベント)の型
// ※ 例えば IBeat https://developer.textalive.jp/packages/textalive-app-api/interfaces/IBeat.html
// 区間の最後と重複しているイベント
current: T;
// 区間内に発生したイベント
entered: T[];
// 区間内に終わったイベント
left: T[];
// 区間の外にあり、次に起きる最初のイベント
next: T;
// 区間の前にあり、すでに完了した最後のイベント
previous: T;
}
API設計についてさらに詳しく
関連するAPI設計の比較は以下の図をご覧ください:
この図は Lyric App Framework の研究ページからアクセスできる「インタラクション 2024」「第138回 音楽情報科学研究会」などの論文にも掲載されており、詳しく説明されています
https://gyazo.com/6d04d9441d023424ec106f18e359131f
APIリファレンス
Player.findBeatChange
Player.findChordChange
Player.findChorusChange
Player.video.findPhraseChange
Player.video.findWordChange
Player.video.findCharChange
返値: TimedObjectsInRange型
#TextAlive_App_API