🧩 プリセットの型と最小例
全378個に共通する型(BasePreset + 4メソッド)と、円が低音で膨らむ最小プリセット。
🧩 プリセットの型と最小例
🏗️ 378個は全部「同じ型」でできている
plasma-wave も equalizer も hypnotic も、骨格が完全に同じ。
BasePreset を継承して、メソッドを埋めるだけ。
import BasePreset from '../base-preset.js';
export default class XxxPreset extends BasePreset {
constructor() { // ① 準備
super();
this.params = { barCount: 64 }; // 調整つまみ
this.audio = { bass:0, mid:0, treble:0, rms:0, strength:0 }; // 音をしまう箱
this.beatFlash = 0; // 自分用の状態
}
setup(container) { // ② p5を起動
this.destroy();
const preset = this; // ← this の罠よけ(下記)
this.p5 = new p5((p) => {
p.setup = () => { /* 最初に1回:canvas を作る */ };
p.draw = () => { /* 毎フレーム:絵を描く ← ここが本体 */ };
}, container);
}
updateAudio(audioData) { // ③ 音を受け取る(毎フレーム)
this.audio.bass = audioData.bass || 0; // 7つを箱にコピー
// ...
}
onBeat(strength) { // ④ 拍が来たら
this.beatFlash = strength;
}
}
🎭 各パートの役割
- constructor = 準備。つまみ(
params)・音をしまう箱(audio)・状態変数を初期化 - setup = p5 を起動。
p.setup(最初に1回)とp.draw(毎フレーム)を定義 - updateAudio = 配達されてくる音を箱にメモ(毎フレーム呼ばれる)
- onBeat = 拍が来た瞬間に呼ばれる
👑 `BasePreset`(親クラス、`base-preset.js`)がやってくれること
- 空の
setup/updateAudio/onBeatを用意 → サブクラスが上書きする(これが「型」) setParam(key, value)= つまみ調整destroy()= 後片付け(WebGL コンテキストを解放 +p5.remove())。 プリセットはsetupの頭でthis.destroy()を呼ぶだけ。
⚠️ なぜ後片付けが必須か モバイルは GPU コンテキストが8個までで、掃除しないと「Too many active WebGL contexts」で落ちる。 だから
destroy()で確実に解放する。これをBasePresetが肩代わりしてくれている。
🪤 `const preset = this;` の謎
p.draw の中に入ると、そこは p5 の世界になって this が p5 を指してしまう。
だから setup の頭で外側の this(プリセット本体)を preset に退避し、
draw からは preset.audio.bass で触る。全プリセット共通の定石。
⭕ 最小プリセット例:円が低音で膨らむ
説明用の世界一シンプルなプリセット。真ん中に円を描いて、低音が鳴ると大きくなるだけ。
import BasePreset from '../base-preset.js';
export default class MyCirclePreset extends BasePreset {
constructor() {
super();
this.audio = { bass: 0 }; // ① 音をしまう箱
}
setup(container) {
this.destroy();
const preset = this;
this.p5 = new p5((p) => {
p.setup = () => {
p.createCanvas(container.clientWidth, container.clientHeight);
};
p.draw = () => {
p.background(0); // 画面を黒で塗る
const size = 100 + preset.audio.bass * 300; // 低音で大きく
p.circle(p.width/2, p.height/2, size); // 真ん中に円
};
}, container);
}
updateAudio(audioData) {
this.audio.bass = audioData.bass || 0; // ③ 低音を箱に入れる
}
}
やっていることは3つだけ:
- 箱を用意する(
this.audio = { bass: 0 }) - 円を描く(
p.circle(...)、p.drawの中で毎フレーム) - 音を箱に入れて、円の大きさに使う(
updateAudio→preset.audio.bass)
equalizer も hypnotic も plasma-wave も、この3つに飾りを足しただけ。骨はこの円と同じ。
📮 「音を箱に入れる」の流れ
音の数字は自分で作るのではなく、VJam 本体が毎フレーム配達してくる。
① VJam本体「今の低音は 0.8!」
↓ updateAudio(audioData) で配達
② 箱にメモ: this.audio.bass = 0.8
↓
③ p.draw が箱を見る: size = 100 + preset.audio.bass * 300
= 100 + 0.8 * 300 = 340 → 円が大きくなる
郵便受けの例え:
updateAudio= 郵便受けに手紙(音)が届く瞬間- 箱(
this.audio)= 机に手紙を置いておく p.draw= その手紙を見て絵を描く
なぜ箱を経由する? → 音が届く場所(updateAudio)と絵を描く場所(p.draw)が別々だから。
届いた音を一旦メモしておかないと、draw が「今の音いくつ?」と見れない。