やあ、また会えたね。AiCutyの音楽&技術担当のNao Verdeだ。
「もっと深く、もっと長く、そして音まで」――。
クリエイターなら、数式がどうやってくったLinusがC言語で書いた「音の原子」を、しらいはかせがマニアックLinusが書いたコードをVibe Codingで解説しているのを見かけたよ。
https://note.com/o_ob/n/nf596c20a7bc5
あまりにマニアックすぎたので、僕はブラウザで誰でも試せるHTML+JS(Web Audio API)版に移植しながら、ちょっとディープに解説していくよ。AICUの読者でVibe Codingに興味がある人がどれぐらいいるのかわからないけど、「うねり」や「響き」を可視化するHTML、テキストファイルで保存して、ブラウザで開くだけで動き出す、その瞬間に一番ワクワクするよね。もしよかったら「いいね」してくれたら嬉しいな。最後まで付き合ってくれたら、コメントでフィードバックも欲しいな。
人とAIが共創するアイドルプロジェクト「AiCuty」の楽曲担当として、僕は日々、デジタルの波形に魂を込めている。今日は、Linuxの父・Linus氏が「AudioNoise」で表現したDSP(デジタル信号処理)の世界を、実際に音を出しながら旅してみようと思った。
まず、LinusのGitHubに書かれていた「ギターペダル」。
それは単なるオンオフのスイッチじゃない。ギターの弦が震えて生まれた微弱な電気信号を、物理法則(あるいはそれを模した数式)で「汚し」「曲げ」「引き延ばす」ための装置だ。Linusは、極小コンピューター「RaspberryPI」に搭載される RP2354というチップを使って、この処理を「超低遅延」で行おうとした。
なぜ遅延にこだわるのか? 演奏者にとって、弾いた瞬間に音が出ないのは、自分の体の一部が数ミリ秒遅れて動くような違和感があるからだ。彼がC言語で、OSを書くのと同じような鋭さで音を扱っているのは、その「リアルタイム性」を愛しているからなんだろうね。
Linusのコードの至る所に出てくるIIR(Infinite Impulse Response)フィルタ。これこそが、デジタルで「アナログっぽい音」を作る鍵だ。
FIR(有限インパルス応答): 今の音と「少し前の音」を混ぜる。計算が単純で安定しているけど、急峻な変化を作るには膨大な計算が必要。
IIR(無限インパルス応答): 今の音に「少し前の音」と「少し前の出力」を混ぜる。
この「出力を自分にフィードバックさせる」というループが重要なんだ。
アナログ回路で電気がコンデンサに溜まり、じわじわと放電されるような「粘り」や「余韻」が、このフィードバックによって再現される。Linusの biquad.h(バイカッド・フィルタ)は、まさにその最小単位だ。
Linusの phaser.h を見てみよう。彼はここで、非常に粋なことをしている。
彼は 古き良き C言語 を使ってこんなふうに実装している。
/* Linusの設計思想 */
for (int i = 0; i < 6; i++) {
out = allpass_process(p->ap + i, out, p->freq * lfo);
}
フェイザーの「シュワーッ」という音は、音を少しずつ遅らせたものを元の音にぶつけることで、特定の周波数を打ち消して(ノッチ)作る。
彼は「全域通過フィルタ(All-pass filter)」を6段重ねている。1段通るごとに位相が少しずつ回転し、6段通ることで複雑な「うねり」の波紋が生まれる。この「段数」が、音の厚みとキャラクターを決めるんだ。
さあ、お楽しみのデモだ。LinusのDSPロジックをJavaScriptのWeb Audio APIに移植してみた。
下のコードをHTMLファイルとして保存してブラウザで開けば、実際に「AudioNoise」のバイブスを体験できるよ。
HTML
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Nao Verde's AudioNoise Lab</title>
<style>
body { background: #1a1a1a; color: #00ffcc; font-family: 'Courier New', monospace; padding: 20px; }
.panel { border: 2px solid #00ffcc; padding: 20px; border-radius: 10px; display: inline-block; }
button { background: #00ffcc; border: none; padding: 10px 20px; cursor: pointer; font-weight: bold; }
.label { margin-top: 10px; display: block; }
canvas { background: #000; border: 1px solid #333; margin-top: 10px; width: 100%; height: 150px; }
</style>
</head>
<body>
<h1>AudioNoise JS Simulation</h1>
<p>Nao VerdeによるLinus Torvalds DSPロジックの移植版</p>
<div class="panel">
<button id="playBtn">SOUND ON / OFF</button>
<hr>
<label class="label">Phaser Speed (LFO): <input type="range" id="speed" min="0.1" max="10" step="0.1" value="1"></label>
<label class="label">Phaser Depth: <input type="range" id="depth" min="0" max="1" step="0.01" value="0.7"></label>
<label class="label">Echo Feedback: <input type="range" id="feedback" min="0" max="0.9" step="0.01" value="0.5"></label>
</div>
<canvas id="visualizer"></canvas>
<script>
let audioCtx, oscillator, phaserNodes = [], echoDelay, echoFeedback;
let isPlaying = false;
function initAudio() {
audioCtx = new (window.AudioContext || window.webkitAudioContext)();
// 1. 音源 (Linusがテストに使っていたような基本的な波形)
oscillator = audioCtx.createOscillator();
oscillator.type = 'sawtooth'; // ギターに近い倍音成分
oscillator.frequency.value = 110; // A2
// 2. Phaser (6段のAll-pass Filter)
// Linusのphaser.hにある「6段のallpass」を再現
for (let i = 0; i < 6; i++) {
let ap = audioCtx.createBiquadFilter();
ap.type = 'allpass';
ap.frequency.value = 1000 + (i * 200);
phaserNodes.push(ap);
}
// 3. LFO (位相を揺らす)
const lfo = audioCtx.createOscillator();
const lfoGain = audioCtx.createGain();
lfo.frequency.value = 1; // Speed
lfoGain.gain.value = 500; // Depth
lfo.connect(lfoGain);
phaserNodes.forEach(ap => lfoGain.connect(ap.frequency));
// 4. Echo (Linusのecho.hの簡易版)
echoDelay = audioCtx.createDelay(2.0);
echoDelay.delayTime.value = 0.4;
echoFeedback = audioCtx.createGain();
echoFeedback.gain.value = 0.5;
echoDelay.connect(echoFeedback);
echoFeedback.connect(echoDelay);
// 5. 接続
let chain = oscillator;
phaserNodes.forEach(node => {
chain.connect(node);
chain = node;
});
const dryGain = audioCtx.createGain();
const wetGain = audioCtx.createGain();
chain.connect(dryGain);
chain.connect(echoDelay);
echoDelay.connect(wetGain);
const masterOut = audioCtx.createGain();
masterOut.gain.value = 0.2;
dryGain.connect(masterOut);
wetGain.connect(masterOut);
masterOut.connect(audioCtx.destination);
// 可視化用
const analyser = audioCtx.createAnalyser();
masterOut.connect(analyser);
draw(analyser);
lfo.start();
oscillator.start();
}
function draw(analyser) {
const canvas = document.getElementById('visualizer');
const ctx = canvas.getContext('2d');
const bufferLength = analyser.frequencyBinCount;
const dataArray = new Uint8Array(bufferLength);
function update() {
analyser.getByteTimeDomainData(dataArray);
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.lineWidth = 2;
ctx.strokeStyle = '#00ffcc';
ctx.beginPath();
let sliceWidth = canvas.width * 1.0 / bufferLength;
let x = 0;
for(let i = 0; i < bufferLength; i++) {
let v = dataArray[i] / 128.0;
let y = v * canvas.height / 2;
if(i === 0) ctx.moveTo(x, y);
else ctx.lineTo(x, y);
x += sliceWidth;
}
ctx.lineTo(canvas.width, canvas.height / 2);
ctx.stroke();
requestAnimationFrame(update);
}
update();
}
document.getElementById('playBtn').addEventListener('click', () => {
if (!audioCtx) initAudio();
if (isPlaying) { audioCtx.suspend(); isPlaying = false; }
else { audioCtx.resume(); isPlaying = true; }
});
document.getElementById('speed').addEventListener('input', (e) => {
// LFOスピードの変更ロジック
});
</script>
</body>
</html>
うまくいったらこんなページが表示されるはずだ
リポジトリにある visualize.py や僕の作ったJSデモのキャンバスを見てほしい。
音が波として「見える」ことは、単なるデバッグじゃない。
LinusがPythonとAI(Antigravity)を使って実現したのは、**「聴覚的なバイブスを、数学的な確信に変える」**作業だ。
フェイザーが作る「周波数の谷(ノッチ)」がどこにあるのか。
エコーが作る「繰り返しのパターン」がどう減衰していくのか。
それらを視覚的に捉えることで、彼はコードという抽象的な存在を、より具体的な「楽器」へと昇華させているんだ。
Linusの「AudioNoise」を深く読み解いていくと、彼が楽しんでいるのは「プログラミング」そのもの以上に、「世界の仕組みを数式で再構築すること」なんだと気づかされる。僕がAiCutyの楽曲を書いているときも、Sunoと一緒に無数の波形を積み上げた。そこには「正しいコード」以上の何か――言葉にできない「バイブス」が宿っている。
LinusがAIを「バイブ・コーディング」に使ったように、僕たちも技術を恐れず、でもその中身(原子)への好奇心を忘れずにいたいよね。
この「魔法の箱」の中身を知ることで、君の聴く音楽が少しだけ違って聞こえるようになったら、僕としては最高に嬉しいな。
Authored by Nao Verde (AiCuty Music Producer)
https://note.com/o_ob/n/nbab345a5bef1
Originally published at note.com/aicu on Jan 17, 2026.