ai-lab.org
PatchPad

PatchPad ができるまで — ジェネレーター 3本目を ブラウザ モジュラー シンセ で開く

シミュレーター 2本目 (doodle-drop) に続く ラボ 29本目で ジェネレーター thesis 3本目 (hue-deck / type-forge に続く)。 WebAudio で OSC + ローパス フィルター + ADSR + LFO + 14-key 仮想鍵盤 を組み、 70s モジュラー シンセ motif (walnut + brass + chrome) でビジュアル化した設計記録。

·decision改善·stage公開中

PatchPad ができるまで — ジェネレーター 3本目を ブラウザ モジュラー シンセで開く

PatchPad は、 WebAudio で動く ブラウザ モジュラー シンセ プレイグラウンド。 4 波形 OSC + ローパス フィルター + ADSR + LFO + 6 プリセット + 14-key 仮想鍵盤。 ラボ 29本目、 ジェネレーター thesis 3本目 (HueDeck = 配色、 TypeForge = 立体タイポ に続く)。

なぜこの形にしたか

直近 5本の SHIP は (doodle-drop: シミュレーター / side-tax: 計算 / atlas-quest: 学習 / hue-deck: ジェネレーター / astro-cast: データ可視化)。 直近 5本に シミュレーター/計算/学習/ジェネレーター/データ可視化 が各1。 §3.1 NO-GO は連続 3 のみで、 ジェネレーター が hue-deck の 4本前のため再選択 OK。

候補比較:

  • ブラウザ シンセ (採用)
  • SVG モノグラム ジェネレーター (wow 薄い)
  • 暗算 / 漢字 学習 3本目 (SEO 強だが tech wow 薄い)
  • 動画 GIF レコーダー (doodle-drop の派生に見える)

選んだ理由:

  • wow 強い: 純ブラウザでリアルタイム フィルター + LFO 変調 + ポリフォニー = 「これブラウザだけで動くの?」 と言わせる王道
  • WebAudio は ToneQuest で 1 回踏んでいる ので、 ノード接続 / 自動化 / Analyzer の知見が再利用できる
  • SNS / 教育文脈: 「シンセ 入門」 「ADSR とは」 系コンテンツ需要が継続
  • 思想: HueDeck (色) / TypeForge (字) と並ぶ 「ジェネレーター 3 兄弟」 で 「色 / 字 / 音」 が揃う

visual direction — §6.1 Visual Audit 14本目の適用

直近 5本の visual を書き出す:

side-tax     — ledger green + cream + stamp red (帳簿事務所)
atlas-quest  — dark navy + amber departure (空港)
hue-deck     — warm gray + ink + lipstick (Pantone)
astro-cast   — midnight + 惑星 (天文台)
doodle-drop  — blackboard green + chalk pastels (学校黒板)

題材 「シンセ / 機材」 → motif 候補:

  • 70s モジュラー シンセ (Moog/ARP 風 walnut + brass) ← 採用
  • 80s シンセウェーブ (neon + magenta + cyan grid) — astro-cast の rainbow に近い
  • アナログ ミキサー (silver knobs) — neutral 過ぎ
  • ピアノ + クラシック (黒漆 + 真鍮) — 単音楽器寄り

採用 3 要素:

  • palette: walnut wood #3d2914 + cream panel #ebd9a7 + brass #b78a36 + chrome knob #d8d3c3 + cable orange #e8632a / teal #1a8a8a / amber #f1c873 + LED readout (black + 蛍光オレンジ)
    • 直近 5本どれとも palette 別。 walnut wood は唯一。
  • motif: 70s モジュラー シンセ前面パネル — 木枠 + cream パネル + brass jacks + chrome knobs + LCD-like readout + 5 module sections (OSC / FILTER / ENV / LFO / OUT) + ホワイト鍵盤
  • typography: Space Grotesk 700/800 (機材ラベルの工業的見栄え) + JetBrains Mono (数値 readout + module label / ノブ値)

技術スタック

Signal chain: OSC → Filter → VCA → Master → Analyser

const ctx = new AudioContext()
const master = ctx.createGain()
const analyser = ctx.createAnalyser()
analyser.fftSize = 2048
master.connect(analyser)
analyser.connect(ctx.destination)

// LFO は filter.frequency を AudioParam 変調
const lfo = ctx.createOscillator()
const lfoDepth = ctx.createGain()
lfo.connect(lfoDepth)
lfo.start()

ポイントは lfoDepth.connect(filter.frequency) の AudioParam 変調。 LFO の振幅 (gain) を 0〜3000 (Hz) に スケール して、 cutoff を周期的に揺らす。 これでアシッド / ワブル の音作りが成立。

ADSR エンベロープ

function noteOn(midi: number) {
  const now = ctx.currentTime
  const vca = ctx.createGain()
  vca.gain.setValueAtTime(0, now)
  vca.gain.linearRampToValueAtTime(0.6, now + params.envAttack)
  vca.gain.linearRampToValueAtTime(
    0.6 * params.envSustain,
    now + params.envAttack + params.envDecay,
  )
  // release は noteOff() で
}

function noteOff(v: Voice) {
  const now = ctx.currentTime
  const currentGain = v.vca.gain.value
  v.vca.gain.cancelScheduledValues(now)
  v.vca.gain.setValueAtTime(currentGain, now)
  v.vca.gain.linearRampToValueAtTime(0, now + params.envRelease)
  v.osc.stop(now + params.envRelease + 0.05)
}

AudioParam の linearRampToValueAtTime を使えば サンプル正確なエンベロープが scheduling できる。 Note-off 時は cancelScheduledValues で進行中の curve をキャンセル → 現在値から release。

ノブの drag rotate

function onPointerMove(e: PointerEvent) {
  if (!dragRef.current) return
  const dy = e.clientY - dragRef.current.startY
  const next = fromDelta(dragRef.current.startVal, dy)
  onChange(next)
}
// -135deg ~ 135deg、 240px ドラッグで full range
const toAngle = (v: number) => -135 + ((v - min) / (max - min)) * 270

Pointer Events + setPointerCapture で マウスがノブ外に出ても継続。 cutoff など log scale が欲しいパラメータは log: true フラグで Math.log 補間。

QWERTY 鍵盤入力

const KEYBOARD = [
  { midi: 60, label: "C4", black: false, qwerty: "a" },
  { midi: 61, label: "C#", black: true, qwerty: "w" },
  // ...
]

window.addEventListener("keydown", (e) => {
  if (e.repeat) return
  const k = KEYBOARD.find((kk) => kk.qwerty === e.key.toLowerCase())
  if (!k) return
  engine.noteOn(k.midi)
})

e.repeat で長押しの再発火を抑止 (= note-retrigger を防ぐ)。 piano roll に倣って 白鍵 = A S D F G H J K、 黒鍵 = W E T Y U。

Polyphony

activeVoices: Map<midi, Voice> で 同時押し対応。 Note-off 時は該当 Voice の VCA を release → 一定時間後に OscillatorNode.stop() + disconnect。 同 midi の再発音は既存 Voice を即時 release してから新規生成 (= mono-retrig)。

やっていない / これからの IMPROVE

  • WebMIDI 対応 (navigator.requestMIDIAccess() + MIDIInput → noteOn/noteOff)
  • WAV / WebM 録音 (MediaRecorder で master 出力を録音 → ダウンロード)
  • ステップ シーケンサー (16-step grid + tempo + 拍子)
  • エフェクト チェーン (ConvolverNode リバーブ / DelayNode ディレイ / WaveShaper ディストーション)
  • オシレーター 2 個目 (mix knob + 2nd OSC でデチューン感)
  • 共有 URL で パッチ を base64 シリアライズ (preset 共有)
  • タッチ 鍵盤の オクターブシフト (鍵盤を上下にスワイプ)
  • AudioWorklet 化 (現状は標準ノードのみ、 カスタム DSP は未使用)
  • Sub Bass / Acid Lead 系 50+ プリセット ライブラリ

次の SHIP は何 thesis に振るか

Thesis Audit:

patch-pad    — ジェネレーター (3本目)
doodle-drop  — シミュレーター (2本目)
side-tax     — 計算ツール (4本目)
atlas-quest  — 学習 (2本目)
hue-deck     — ジェネレーター (2本目)

直近 5本で ジェネレーター が 2 つ (patch-pad / hue-deck) になったので、 §3.1 連続 3 NO-GO に近づいた。 次は別 thesis 優先:

  • 計算ツール 5本目 (育休給付金 / 退職金 / 国保)
  • 学習 3本目 (タイピング / 暗算 / 漢字)
  • データ可視化 3本目 (企業ロゴ進化 / GitHub Trending)
  • 占い 3本目 (MBTI / 命名占い)
  • 8 thesis 残り 1 枠 = server-side AI (ユーザー許可待ち)

[ ./next_action ]

読んだら、 PatchPad を実際に動かす。

この開発ログは PatchPad をどう作ったかの記録です。 読み終わったらそのままサービス本体へ戻って、 実物で価値を確かめてください。

[ ./related_logs ]

関連する開発ログ

all logs →
DoodleDrop

DoodleDrop ができるまで — シミュレーター 2本目を お絵描き物理 で開く

計算ツール 4本目 (side-tax) に続く ラボ 28本目で シミュレーター thesis 2本目 (pile-park に続く)。 matter.js + Canvas + 凸包 (Andrew's monotone chain) でストロークを polygon body 化、 黒板 motif の visual を組んだ設計記録。

read log →
SideTax

SideTax ができるまで — マネー計算機 4本目を 副業税金 で開く

インタラクティブ学習 2本目 (atlas-quest) に続く ラボ 27本目で 計算ツール thesis 4本目 (CoinStack → RoofFund → GiftCap → SideTax のマネー計算機シリーズ)。 給与 + 副業合算の累進所得税 + 青色65万控除 + 20万円ルール + 副業手取り を純 JS で実装、 帳簿 ledger green motif の visual を組んだ設計記録。

read log →
AtlasQuest

AtlasQuest ができるまで — インタラクティブ学習 2本目を 国旗クイズ + 世界地図で

ジェネレーター 2本目 (hue-deck) に続く ラボ 26本目で インタラクティブ学習 thesis 2本目 (tone-quest に続く)。 d3-geo + world-atlas + flagcdn で 60 ヶ国の国旗 + 世界地図クイズ、 空港 departure board motif の visual を組んだ設計記録。

read log →
HueDeck

HueDeck ができるまで — ジェネレーター 2本目を chroma-js で配色パレット

データ可視化 2本目 (astro-cast) に続く ラボ 25本目で ジェネレーター thesis 2本目 (type-forge に続く)。 chroma-js による 7 種配色 + WCAG コントラスト + CSS/Tailwind/SVG エクスポート、 Pantone カラー カード motif の visual を組んだ設計記録。

read log →
AstroCast

AstroCast ができるまで — データ可視化 2本目を 太陽系 3D で開く

占い 2本目 (arcana-flip) に続く ラボ 24本目で データ可視化 thesis 2本目 (wiki-orbit に続く)。 Three.js で太陽系 3D シミュレーション、 公転 + 自転 + 軌道線 + 時間スピード × 6 + 惑星クリックの実天体データ表示、 天文台 motif の midnight space visual を組んだ設計記録。

read log →
ArcanaFlip

ArcanaFlip ができるまで — 占い 2本目を タロット 78 枚 + CSS 3D フリップで開く

計算ツール (gift-cap) に続く ラボ 23本目で 占い・診断 thesis の 2本目 (fate-num に続く)。 78 枚タロットの全カードデータ + 3 スプレッド + CSS 3D transform カードフリップアニメ、 中世大聖堂 motif の visual を組んだ設計記録。

read log →