コンテンツにスキップ

エフェクトとフェード

このガイドでは、nodesfadeplay モジュールを使用して、audio effect とフェード効果を実装する方法を説明します。

デモ

Sound Source

または

使用モジュール

  • nodes: Audio node のファクトリー関数(createGaincreatePannerchain など)
  • fade: フェードイン/アウト、クロスフェードユーティリティ
  • play: コア再生エンジン(through オプションで effect chain をルーティング)

コード例

1. ボリューム制御

createGain() で GainNode を作成し、play()through オプションでルーティングします。rampGain() を使用することで、クリックノイズなく滑らかに音量を変更できます。

import { WaaPlayer } from "waa-play";
const waa = new WaaPlayer();
await waa.ensureRunning();
const buffer = await waa.load("/audio/track.mp3");
const gain = waa.createGain(0.5); // Initial volume 50%
const playback = waa.play(buffer, { through: [gain] });
// Ramp to 100% volume over 3 seconds
waa.rampGain(gain, 1.0, 3);

through オプションに GainNode を渡すと、play() が自動的に音源からゲインノード、そして destination へと接続します。

関数 API 版
import { createContext, ensureRunning } from "waa-play/context";
import { loadBuffer } from "waa-play/buffer";
import { createGain, rampGain } from "waa-play/nodes";
import { play } from "waa-play/play";
const ctx = createContext();
await ensureRunning(ctx);
const buffer = await loadBuffer(ctx, "/audio/track.mp3");
const gain = createGain(ctx, 0.5);
const playback = play(ctx, buffer, { through: [gain] });
rampGain(gain, 1.0, 3);

2. ステレオパン

createPanner() で StereoPannerNode を作成し、左右のパンを制御できます。値は -1(左)から 1(右)の範囲です。

import { WaaPlayer } from "waa-play";
const waa = new WaaPlayer();
await waa.ensureRunning();
const buffer = await waa.load("/audio/track.mp3");
const panner = waa.createPanner(0); // Center
const playback = waa.play(buffer, { through: [panner] });
// Pan left
panner.pan.value = -1;
// Pan right
panner.pan.value = 1;
// Back to center
panner.pan.value = 0;
関数 API 版
import { createContext, ensureRunning } from "waa-play/context";
import { loadBuffer } from "waa-play/buffer";
import { createPanner } from "waa-play/nodes";
import { play } from "waa-play/play";
const ctx = createContext();
await ensureRunning(ctx);
const buffer = await loadBuffer(ctx, "/audio/track.mp3");
const panner = createPanner(ctx, 0);
const playback = play(ctx, buffer, { through: [panner] });
panner.pan.value = -1; // Left

3. Effect Chain

複数の effect を組み合わせて、リッチなサウンド処理を実現できます。through に配列でノードを渡すと、自動的にチェーン接続されます。

import { WaaPlayer } from "waa-play";
const waa = new WaaPlayer();
await waa.ensureRunning();
const buffer = await waa.load("/audio/track.mp3");
// Build effect chain
const gain = waa.createGain(0.8);
const filter = waa.createFilter({ type: "lowpass", frequency: 1000 });
const compressor = waa.createCompressor();
const panner = waa.createPanner(0.5);
// Auto-chain: gain → filter → compressor → panner → destination
const playback = waa.play(buffer, {
through: [gain, filter, compressor, panner],
});
// Adjust filter frequency
filter.frequency.value = 500;

through オプションを使う場合、play() が自動的にノードを接続するため、chain() は不要です。chain()play() の外でノードグラフを構築する場合に使用します。

関数 API 版

chain() を使って明示的にノードグラフを構築する例です。

import { createContext, ensureRunning } from "waa-play/context";
import { loadBuffer } from "waa-play/buffer";
import {
createGain,
createFilter,
createCompressor,
createPanner,
chain,
} from "waa-play/nodes";
import { play } from "waa-play/play";
const ctx = createContext();
await ensureRunning(ctx);
const buffer = await loadBuffer(ctx, "/audio/track.mp3");
const gain = createGain(ctx, 0.8);
const filter = createFilter(ctx, { type: "lowpass", frequency: 1000 });
const compressor = createCompressor(ctx);
const panner = createPanner(ctx, 0.5);
// Explicitly connect with chain()
chain(gain, filter, compressor, panner);
const playback = play(ctx, buffer, { through: [gain] });

4. フェードイン/アウト

fadeIn()fadeOut() を使用して、滑らかなフェード効果を実現できます。autoFade() を使えば、再生開始時と終了時のフェードを自動化できます。

import { WaaPlayer } from "waa-play";
const waa = new WaaPlayer();
await waa.ensureRunning();
const buffer = await waa.load("/audio/track.mp3");
const gain = waa.createGain(0); // Start at 0 volume
const playback = waa.play(buffer, { through: [gain] });
// Fade in over 2 seconds (equal-power curve)
waa.fadeIn(gain, 1, { duration: 2, curve: "equal-power" });
// Fade out over 2 seconds
setTimeout(() => {
waa.fadeOut(gain, { duration: 2 });
}, 5000);

autoFade() を使用すると、再生開始時と終了時のフェードを自動的に設定できます。

import { WaaPlayer } from "waa-play";
const waa = new WaaPlayer();
await waa.ensureRunning();
const buffer = await waa.load("/audio/track.mp3");
const gain = waa.createGain(0);
const playback = waa.play(buffer, { through: [gain] });
// Fade in 1s at start, fade out 2s over the last 2 seconds
waa.autoFade(playback, gain, { fadeIn: 1, fadeOut: 2 });
関数 API 版
import { createContext, ensureRunning } from "waa-play/context";
import { loadBuffer } from "waa-play/buffer";
import { createGain } from "waa-play/nodes";
import { play } from "waa-play/play";
import { fadeIn, fadeOut, autoFade } from "waa-play/fade";
const ctx = createContext();
await ensureRunning(ctx);
const buffer = await loadBuffer(ctx, "/audio/track.mp3");
const gain = createGain(ctx, 0);
const playback = play(ctx, buffer, { through: [gain] });
// Fade in
fadeIn(gain, 1, { duration: 2, curve: "equal-power" });
// Auto fade
autoFade(playback, gain, { fadeIn: 1, fadeOut: 2 });

5. DJ クロスフェード

2つのトラック間でクロスフェードを行い、DJ ミックスのようなシームレスな切り替えを実現できます。

import { WaaPlayer } from "waa-play";
const waa = new WaaPlayer();
await waa.ensureRunning();
const bufferA = await waa.load("/audio/track-a.mp3");
const bufferB = await waa.load("/audio/track-b.mp3");
// Track A (full volume)
const gainA = waa.createGain(1);
const playbackA = waa.play(bufferA, { through: [gainA], loop: true });
// Track B (muted)
const gainB = waa.createGain(0);
const playbackB = waa.play(bufferB, { through: [gainB], loop: true });
// Crossfade from track A to track B over 3 seconds
setTimeout(() => {
waa.crossfade(gainA, gainB, { duration: 3, curve: "equal-power" });
}, 5000);

crossfade() は、一方の GainNode を 1 から 0 へ、もう一方を 0 から 1 へ同時にフェードします。curve: "equal-power" を使用することで、知覚的に均一な音量でクロスフェードが行われます。

関数 API 版
import { createContext, ensureRunning } from "waa-play/context";
import { loadBuffer } from "waa-play/buffer";
import { createGain } from "waa-play/nodes";
import { play } from "waa-play/play";
import { crossfade } from "waa-play/fade";
const ctx = createContext();
await ensureRunning(ctx);
const bufferA = await loadBuffer(ctx, "/audio/track-a.mp3");
const bufferB = await loadBuffer(ctx, "/audio/track-b.mp3");
const gainA = createGain(ctx, 1);
const playbackA = play(ctx, bufferA, { through: [gainA], loop: true });
const gainB = createGain(ctx, 0);
const playbackB = play(ctx, bufferB, { through: [gainB], loop: true });
setTimeout(() => {
crossfade(gainA, gainB, { duration: 3, curve: "equal-power" });
}, 5000);

関連 API