Coniにおけるプロシージャル・オーディオとWebGL WebAssemblyのエクスペリエンス

過去24時間だけで、私たちはConi WebAssemblyエコシステムの限界を押し広げ、プロシージャル・オーディオビジュアルのウェブ体験スイート全体を作成しました。Coniのマクロシステムと生のWebGL、そしてWebAudio APIを組み合わせることで、複雑なグラフィックスと音楽システムを外部アセットへの依存を一切持たずに、ブラウザ上でネイティブに構築、コンパイル、展開することに成功しました。

今回構築した5つの新しいアプリケーションを見てみましょう。これらはすべてConi WASM Galleryで、ブラウザ上でネイティブに体験できます。

1. Minimal Techno Visualizer

テーマ: ダークでドライビングなアルゴリズミック・クラブエナジー。 リンク: Minimal Techno App

Coniがリアルタイムのプロシージャル音楽生成をオーケストレーションし、それを重い3Dジオメトリのレンダリングと完璧に同期できることを証明したかったのです。

  • オーディオエンジン: カスタムの140 BPMタイムラインエンジンが、16分音符の裏拍でアナログスタイルのノコギリ波ベースラインをトリガーし、808スタイルの合成キックと組み合わせ、ドロップ部分ではクリスピーなノイズベースのスネア/クラップを導入します。
  • WebGLの繊細さ: 16小節の「ブレイクダウン」中に重力を逆転させる5,000個の雨のパーティクルと、キックの打撃ごとにアグレッシブに広がる高密度の脈動する3Dジオメトリコアをマッピングしました。シーケンサーの状態に基づいて冷たいシアンから燃えるようなオレンジ色へと変化します。

2. Divine Infinity 999Hz

テーマ: エーテル的で数学的なヒーリング。 リンク: Divine Infinity 999Hz

神聖な周波数ヒーリングのコンセプトを中心に据えたこのアプリケーションは、純粋な数学とアンビエントオーディオの融合です。

  • オーディオエンジン: 深いリラクゼーションを誘発するために、微細な8Hzのシータ波バイノーラルビートで補完された999Hzの「エンジェル周波数」のサイン波を生成します。
  • WebGLの繊細さ: GLSLの頂点シェーダー内の純粋な三角関数を使用して、500,000個のパーティクルを「ベルヌーイのレムニスケート」(無限大の記号)上にマッピングしました。繊細なアンビエントグローと深度に基づいた不透明度のフェードにより、3D空間で完璧にレンダリングされます。

3. Clear Brain Fog 40Hz

テーマ: 幾何学的な明晰さと集中。 リンク: Clear Brain Fog 40Hz

精神的な混乱を払拭することを目的としたこのアプリは、魅惑的な幾何学とグラウンディング周波数を組み合わせています。

  • オーディオエンジン: 2つのオシレーター(左耳に432Hz、右耳に472Hz)をデチューンして作成された純粋な40Hzのバイノーラルビート。
  • WebGLの繊細さ: 頂点シェーダーに5枚の花びらが回転する3Dスピログラフをプログラムしました。複雑に重なり合う曲線が、カメラを全く動かすことなく前進し続ける錯覚を生み出し、目をフロー状態に引き込みます。

4. WebGL Guided Breathing App

テーマ: 制御されたリズミカルな瞑想。 リンク: Breathing App

WebGLによるガイド付き呼吸法: 6-2-6のインタラクティブ体験

ペースの速い今日のデジタル世界において、メンタルヘルスと集中力は非常に重要です。脳波同調(ブレインウェーブ・エントレインメント)アプリケーションの成功に続き、私たちはウェルビーイングのもう一つの側面である「意識的な呼吸」に取り組むことにしました。

私たちの最新のConi WASMアプリケーション、WebGL Breathing Appを発表できることを嬉しく思います。これは、落ち着きをもたらす6-2-6の呼吸エクササイズ(6秒吸って、2秒止め、6秒吐く)をガイドするためにゼロから構築された、視覚的および聴覚的な体験です。

生きたUIを作成する

単に拡大する円を表示する従来の呼吸タイマーとは異なり、私たちは「生きている」と感じられるものを作りたいと考えました。そこで、Calm(シアン)、Warm(オレンジ)、Focus(パープル)からムードを設定できるインタラクティブなメニューを設計しました。

../breathe_in_01.png

エクササイズを開始すると、バックグラウンドの環境ノイズとプロシージャルに生成されたチャイムが再生され始めます。これらのサウンドはWeb Audio APIのみによって駆動され、ネイティブのConi関数によってシームレスにスケジューリングされます。ロジックを標準的なJSランタイムの遅延(ヒカップ)から分離することで、オーディオは完全に一貫性を保ち、ジッター(乱れ)のない状態を維持します。

GPUのパワー

内部では、アプリケーションはネイティブに計算され、WebAssemblyにキャッシュされた30,000個の幾何学的なパーティクルのクラスターを生成します。これらのポイントは、選択したムードカラーと連続的な u_breath_factor とともにWebGLシェーダーに渡されます。

息を吸うと、球体は拡大し、頂点シェーダーで直接適用される三角関数のサインとコサインの操作によって頂点が緩やかに波打ちながら、半径が動的に拡大します。色の強さも増し、エネルギーの膨張を模倣します。

息を吐くと、球体はタイトなコアへと収縮します。

../breathe_in_02.png

;; フェーズを完全にWASM内で計算します
(defn update-phase [t phase-text]
  (let [cycle-time (fmod t 14000.0)
        inhale-time 6000.0
        hold-time 2000.0
        exhale-time 6000.0]
    (if (< cycle-time inhale-time)
      ;; ... 拡張をスムーズに緩和するための数学ロジック

視覚的な変換をGPUにオフロードし、厳格な状態の同期をネイティブにWASM内で維持することで、ロボット的ではなく有機的に感じられる、シルクのように滑らかな60fpsの体験を実現しました。

今すぐ試す

新しいアプリケーションを私たちのWASMアプリ環境にデプロイしました。こちらから直接アクセスできます:

Conimoフレームワークで最小限のCMSを構築する

ConimoはConiの公式フルスタックWebフレームワークです。驚異的に高速なWASMのフロントエンド機能と、堅牢なバックエンドサーバー環境を統合し、まとまりのある合理化された開発者体験をもたらします。

最近、コアとなるConimo CLIスクリプトをconimoライブラリのbinディレクトリに直接組み込むことで、開発者体験を大幅に改善しました。つまり、外部のセットアップスクリプトは不要で、すべてがネイティブのConiコードによって駆動されます。

このガイドでは、新しいアプリケーションの足場作り(スキャフォールディング)、ローカル開発サーバーの実行、そして強力なpatomデータベースを利用した最小限のコンテンツ管理システム(CMS)の迅速な構築について説明します。

1. createによる足場作り

始めるには、組み込みのconimo createコマンドを使用します。Conimoは、最小限のSSR(サーバーサイドレンダリング)セットアップから、完全なリアルタイムWebSocketアーキテクチャ、さらにはネイティブなAIチャットアプリまで、様々な組み込みテンプレートを提供しています。

CMSの場合、永続性が必要です。csv-storeテンプレートはこれに最適で、patomを介して堅牢なCSVファイル・データベースを活用します。

次のコマンドを実行してプロジェクトの足場を作ります:

coni conimo create my-cms --template csv-store

スキャフォールディング・スクリプトは即座にフルスタックのディレクトリ構造を生成します:

  • backend/: バックエンドのHTTP/WebSocketサーバー。
  • frontend/: WASMコンパイルされるフロントエンドコード。
  • coni.edn: プロジェクト設定。ネイティブのWASMビルドがシームレスに機能するように、現在のコンパイラパスが自動的に注入されます。

2. 開発サーバーの実行

プロジェクトが作成されたら、conimo devコマンドを実行するだけで開発環境を起動できます。

cd my-cms
coni conimo dev

内部では、Conimoの開発サーバーは以下のことを行います:

  1. frontend/コードのためのWASMコンパイルプロセスをバックグラウンドで起動します。
  2. main.wasmと必要なJSブリッジが完全にコンパイルされるまで待機します。
  3. 自動的にbackend/main.coniサーバーを起動します。

これで、バックエンドサーバーとWASMフロントエンドがシームレスに接続されたライブのフルスタック環境が整いました。

3. CMSを書く

../conimo-todo.png

csv-storeテンプレートを使用すると、CMSの構築は信じられないほど高速になります。バックエンドはすでに、Coniの永続的なアトミック状態管理システムであるpatomを使用するように配線されています。

「投稿(Posts)」を管理するための最小限のCMSバックエンドを定義する方法は以下の通りです:

;; backend/main.coni
(require "libs/http/src/server.coni" :as http)
(require "libs/patom/src/core.coni" :as patom)

;; 永続的なCSVバックドアトムを初期化
(def *db* (patom/create-store "cms_data.csv" []))

(defn handle-get-posts [req]
  (http/json-response @*db*))

(defn handle-create-post [req]
  (let [body (http/parse-json (:body req))
        new-post {:id (rand-int 10000)
                  :title (:title body)
                  :content (:content body)}]
    ;; アトミックに状態をスワップし、CSVに永続化する
    (patom/swap! *db* conj new-post)
    (http/json-response new-post)))

(defn start-server []
  (let [mux (http/serve-mux)]
    (http/handle mux "GET /api/posts" handle-get-posts)
    (http/handle mux "POST /api/posts" handle-create-post)
    
    (println "CMS API running on port 8080")
    (http/listen-and-serve ":8080" mux)))

(start-server)

わずか数行のコードで、永続的なCSVストアに裏打ちされた完全に機能するJSON APIが完成します。

ConiのネイティブFloat32配列のためのハードコア・カオステスト

ブラウザで高性能なアプリケーションを構築する場合、JavaScriptの汎用的なNumber型では不十分なことがよくあります。連続した生のメモリ配列が必要になるのです。Coni WASMでは、最も数学的に集約的なアプリケーションのために、ネイティブなWebAssemblyのfloat32配列に大きく依存しています。

Float32は実際にConiのどこで使われているのか?

ネイティブのfloat32配列(make-float32-arrayf32-set!f32-get)は、Coniのパフォーマンス・レイヤーの絶対的なバックボーンです。これらは以下のような機能を駆動しています:

  1. WebGLジオメトリ: deep-focus-webglアプリでは、float32配列を使用して80,000頂点のブレイン・マトリックス(240,000個の浮点数!)をネイティブに数学的に形成し、その後js/float32-bufferを介して一撃でGPUに転送します。
  2. ゲームエンジンのパーティクルシステム: flappy-birdneon-boidsのようなゲームでは、並行するfloat32配列が数千のX/Y座標、速度、寿命を、ガベージコレクションの停止を発生させることなく追跡します。
  3. 生(Raw)のDSPオーディオ: 私たちのsound-nodesシンセサイザーは、複雑なインパルス応答とノイズ波形をWebAudioチャンネルにマッピングする前に、float32配列を使用してネイティブに計算します。

バグ:型強制とf64.reinterpret_i64

これらの配列は非常に重要であるため、そこでのバグは壊滅的です。最近、正確な整数(例えば150)をf32-set!に渡すと、なぜか0.0が返ってくるという問題を発見しました。

何が起きていたのでしょうか?以前のバージョンのWASMコンパイラでは、整数を浮動小数点数のセッターに渡すと、コンパイラがビットを解釈するために誤ってf64.reinterpret_i64を使用し、基礎となる値を完全に文字化けさせていたのです。

解決策:Float32カオステスト

私たちはコンパイラにパッチを当て、メモリへの挿入前に整数を正しく浮動小数点数に強制(コアーション)するようにしましたが、二度と退行(リグレッション)しないという保証が欲しかったのです。そこでカオステストの登場です。

新しいfloat32_coercion_test.coniスイートに、ハードコアなカオステストを構築しました。少数のハッピーパス(正常系)の数値をテストするだけでなく、巨大な配列を割り当て、決定論的な擬似ランダムループでそれを激しく叩きます。

(deftest test-f32-chaos
  "float32配列の境界と型強制のためのハードコアなカオステスト"
  (let [size 1000
        arr (make-float32-array size)]
    (loop [i 0]
      (if (< i size)
        (let [
          ;; 極端なエッジケースを混ぜて生成:
          val (if (= (mod i 4) 0) (- 0 i)                   ;; 負の整数
                (if (= (mod i 4) 1) (* i 10000)             ;; 大きな正の整数
                  (if (= (mod i 4) 2) (+ i 0.5)             ;; 正確なfloat32の分数
                    0)))                                    ;; ゼロ(整数)
        ]
          (f32-set! arr i val)
          (recur (+ i 1)))
        nil))
    ;; ... 検証ループ ...

極端な正の整数、負の境界値、純粋なゼロ、そして小数部を持つ浮動小数点数の残酷なミックスを意図的に1,000回f32-set!関数に投げつけることで、WASMのトラップを回避し、型強制が防弾(完璧)であることを保証します。

Coni WASMによる40Hzの認知的集中アプリの構築

ブラウザ上のWebAssemblyは常に信じられないほどのパフォーマンスを約束してきましたが、WebAudioやWebGLといったWeb APIとスムーズに連携させることは、時にパズルを解くような感覚になることがあります。本日は、Coniエコシステムがこれをいかにエレガントに解決するかを、認知的集中のために設計された2つの新しいWebアプリを通じて紹介できることを嬉しく思います。

これら2つのアプリケーションは、バイノーラルビートを使用して、深い集中力、記憶の想起、認知機能の向上に関連する特定の脳波周波数である40Hzのガンマ波を生成します。しかし、本当の魔法はその裏側にあります。これらはすべて完全にConi WASMで書かれているのです。

40Hzガンマ波の科学

技術的な話に入る前に、なぜ40Hzなのでしょうか?ガンマ波は脳波の中で最も速い周波数です。研究によると、脳が40Hzの範囲で活動している時、それは知覚の高まり、問題解決、そしてピーク時の集中力と相関しています。

左耳に60Hz、右耳に100Hzのサイン波を流すことで、脳は正確に40Hzの周波数差(ビート)を知覚します。このプロセスは脳波の同調(ブレインウェーブ・エントレインメント)として知られ、あなたの認知状態を優しくガンマ波へと導きます。

この体験を提供する上でのConiアーキテクチャの柔軟性を実証するために、2つの異なるバージョンのアプリを構築しました。

1. Canvasエディション: deep-focus-40hz

../deepfocus.png

最初のアプリケーションは、従来の2D CanvasとDOM APIに依存しています。私たちは独自のreframe_wasmライブラリを活用し、WebAssemblyから直接HiccupスタイルのDOM生成を行うことでUIの状態とレンダリングを処理しました。

オーディオエンジンは、オシレーターをネイティブに近い速度で完全に管理しています。さらに、その場でエンベロープを変調する自動ジェネレーティブ・チャイムシステムを構築し、JSのオーバーヘッドを完全に回避しました。

;; JSバインディング不要の表現力豊かなWebAudioエンベロープ!
(doto (.-gain gain)
  (.linearRampToValueAtTime 0.15 (+ now 2.0))
  (.exponentialRampToValueAtTime 0.001 (+ now 8.0)))

これは、純粋なConiでリアクティブで高性能なオーディオエンジンを構築する完璧な例です。

2. WebGLパワーハウス: deep-focus-webgl

../deepfocus-webgl.png

Canvasバージョンも素晴らしいですが、Coniのネイティブ処理能力をどこまで押し上げることができるか試してみたくなりました。そこで登場したのがdeep-focus-webgl(社内呼称:Amplifocus)です。

2D Canvasに依存するのではなく、このバージョンは純粋なWebGLを使用して80,000パーティクルのブレイン・マトリックスをレンダリングします。 何がそんなにエキサイティングなのでしょうか?

  • 100%純粋なConi: GPUで加速される頂点変換と大規模なパーティクル配列のロジックは、Coni WASM内でネイティブに処理されます。
  • 数学計算のJSオーバーヘッド・ゼロ: Coniの数学ライブラリ(libs/math)を使用することで、高価なJS-WASMブリッジを渡ることなく、数万の頂点に対する複雑な三角関数の変換を計算します。

ネイティブのFloatバッファで3Dジオメトリを形成し、それをGPUに送るのがいかに簡単かをご覧ください。

;; WASMメモリ内で80kの頂点を計算し、一気にGPUへ送信!
(f32-set! *base-points* idx final-x)
(f32-set! *base-points* (+ idx 1) final-sy)
(f32-set! *base-points* (+ idx 2) (* z 1.1))

;; 静的ジオメトリを一度だけアップロード
(gl/upload-static-data @*gl-state* (js/float32-buffer *base-points*))

Float配列を一度割り当て、ネイティブにジオメトリを計算し、バッファリングされた一撃でGPUに転送します。

純粋なConi LispでWebGLシェーダーを書く!

前回の記事では、80,000パーティクルのWebGLマトリックスをオーケストレーションすることで、Coni WASMの生み出すパワーを紹介しました。しかし、WebGLのパイプラインには常に一つの厄介な問題が残っていました。それはシェーダーそのものです。

WebGLコードを書いたことがある人なら、その面倒さを知っているはずです。頂点シェーダーとフラグメントシェーダーを、コードベース全体に連結された巨大で厄介な文字列リテラルとして書くことになります。構文のハイライトもフォーマットも失われ、さらにLispハッカーにとって最も悲劇的なことに、構造的編集(Paredit/Slurp/Barf)も失われてしまいます。

本日、新しいlibs/webgl/src/glsl.coniライブラリにより、私たちがその最後のフロンティアを征服したことを発表できることを嬉しく思います。

GLSLシェーダーをConiのネイティブLisp構文で完全に記述できるようになりました。

defshaderの登場

Coniの強力なAST(抽象構文木)とマクロシステムを活用することで、私たちはdefshaderを構築しました。これは標準的なLispのフォーム、型、数学的演算を受け取り、それらがGPUに到達する前に自動的に厳密なGLSLへとトランスパイルします。

私たちのAmplifocusパーティクルエンジンのために、このフラグメントシェーダーがいかに美しく書かれているかを見てください:

(require "libs/webgl/src/glsl.coni" :all)

(defshader fs-src
  (precision mediump float)
  (varying vec4 v_color)
  
  (defn void main []
    ;; ネイティブの数学と座標マッピング!
    (set vec2 coord (- gl_PointCoord (vec2 0.5 0.5)))
    (set float dist (length coord))
    
    (if (> dist 0.5)
      (discard))
    
    ;; LispのS式を使った発光(グロー)の計算
    (set float glow (- 1.0 (* dist 2.0)))
    (set vec4 final_color (* v_color glow))
    (set gl_FragColor final_color)))

なぜこれがゲームチェンジャーなのか?

  1. 文字列リテラルからの解放: シェーダーはファーストクラスのコードになります。アプリケーションの他の部分と完全にフォーマットが統一されます。
  2. ASTレベルの検証: Coniコンパイラは、ブラウザでWebGLプログラムをコンパイルしようとする前に、シェーダーの構造をパースして検証できます。
  3. 構造的編集: 標準的なLispの構造的編集ツールを使用して、複雑なGPU計算をスラープ、バーフ、そして操作することができます。CスタイルのGLSL文字列でそれをやろうとしてみてください!
  4. シームレスな統合: 使用可能なWebGLシェーダーへのコンパイルは、core-gl/gl-shader関数を呼び出すだけというシンプルさです:(core-gl/gl-shader gl (.-FRAGMENT_SHADER gl) fs-src)

ブラウザのためのフルスタックLisp

このアップデートにより、パイプラインは完成しました。reframeによるDOM操作から、WebAudioの合成、WASMのFloatバッファ、そして今や実際のGPU頂点変換に至るまで、100% Coniで実現できます。