JavaScript
HTML5
WebAudioAPI

WebAudioAPI ディレイ/エコーの制作

今までの学習のまとめです。

ローカルの音声ファイルをMediaElementで読み込み、AudioBufferでFXを付与して出力しています。

ディレイは原音とエフェクト音を分けて出力(センド・エフェクト)できるようにしています。

エフェクト音は通常のaudioContext.createDelay()に対してディレイタイムにLFOを掛け、HPFを通したものを出力しています。
これは音程に揺らぎを与え、低域の飽和を抑える役目をしています。

MEMO 追加予定
テープの劣化 = ディストーション
走行時のノイズ = ヒスノイズ
走行速度の揺れ = ディレイタイムにLFO
ハイダンプ/ローダンプ

<!DOCTYPE html>
<html lang="jp">

<head>
    <meta charset="UTF-8">
</head>

<body>
    <input id="Afile" type="file">
    <audio id="Aplayer"></audio>
    <input type="checkbox" id="play_pause">PLAY/PAUSE
    <input type="checkbox" id="loop">LOOP
    <br>
    <input type="range" id="volume" value="1" min="0" max="1" step="0.05">GAIN
    <input type="range" id="pitchAdj" value="1.00" min="0.7" max="1.16" step="0.01">PITCH
    <br>
    <input type="range" id="inputVolume" value="0.95" min="0" max="0.95" step="0.05">InputVolume
    <input type="range" id="repeatRate" value="0" min="0" max="1" step="0.05">RepeatRate
    <input type="range" id="intensity" value="0" min="0" max="1" step="0.05">Intensity
    <input type="range" id="echoVolume" value="0" min="0" max="1.3" step="0.05">EchoVolume
    <script>
        window.onload = () => {
            //ファイルの読み込み
            var Actx = new(window.AudioContext || window.webkitAudioContext)();
            var gain = Actx.createGain();
            var source = Actx.createMediaElementSource(Aplayer);
            Afile.onchange = function() {
                Aplayer.src = URL.createObjectURL(this.files[0]);
                Aplayer.currentTime = 0;
                play_pause.checked = false;
            };
            //再生、一時停止
            play_pause.onchange = () => {
                (play_pause.checked) ? Aplayer.play(): Aplayer.pause();
            };
            //ループ
            loop.onchange = () => {
                (loop.checked) ? Aplayer.loop = true: Aplayer.loop = false;
            };
            volume.addEventListener('input', () => gain.gain.value = volume.valueAsNumber);
            pitchAdj.addEventListener('input', () => Aplayer.playbackRate = pitchAdj.valueAsNumber);

            //エコー
            var delay = Actx.createDelay();
            var dry = Actx.createGain();
            var wet = Actx.createGain();
            var feedback = Actx.createGain();
            var delayFilter = Actx.createBiquadFilter();
            var lfo = Actx.createOscillator();
            var lfoG = Actx.createGain();

            lfo.frequency.value = 1;
            lfoG.gain.value = 0.0025;
            lfo.start(0);
            delayFilter.type = 'highpass';
            delayFilter.frequency.value = 200;
            delayFilter.Q.value = 0;
            dry.gain.value = 1.0;
            wet.gain.value = feedback.gain.value = 0.0;

            //ドライ、ディレイタイム、フィードバック、音量
            inputVolume.addEventListener('input', () => dry.gain.value = inputVolume.valueAsNumber);
            repeatRate.addEventListener('input', () => delay.delayTime.value = repeatRate.valueAsNumber);
            intensity.addEventListener('input', () => feedback.gain.value = intensity.valueAsNumber);
            echoVolume.addEventListener('input', () => wet.gain.value = echoVolume.valueAsNumber);

            //ルーティング
            source.connect(dry).connect(gain);
            source.connect(delay).connect(wet).connect(delayFilter).connect(gain);
            delay.connect(feedback).connect(delay);
            lfo.connect(lfoG).connect(delay.delayTime);

            gain.connect(Actx.destination);

            Aplayer.onended = () => {
                play_pause.checked = false;
                Aplayer.currentTime = 0;
            };
        };
    </script>
</body>

</html>

別ファイルをロードした際にクリップするので、次回はその部分の修正とリバーブの制作を予定しています。