Web Audio API Demo :: PeriodicWave

by mohayonao

HTML

<h1>PeriodicWave Demo</h1>
<ul>
    <li>Firefox: 非常に不安定 → 音が出なくなる</li>
    <li>Chrome: 音が小さくなる?? (PeriodicWaveじゃなくても)</li>
</ul>

<button id="start">start</button>
<div id="message"></div>

CSS

* { font-size: 0.95em }

JavaScript

var context = new AudioContext();

var INTERVAL = 0.125;
var DURATION = 0.25;

var timerId = 0;
var square = (function() {
    var real = new Float32Array(2048);
    var imag = new Float32Array(2048);
    
    for (var i  = 1; i < 2048; i++) {
        if (i % 2 === 1) {
            imag[i] = 1 / i;
      }
    }
    
    return context.createPeriodicWave(real, imag);
})();

function play(t) {
    var osc = context.createOscillator();
    var amp = context.createGain();
    
    osc.setPeriodicWave(square);
    // osc.type = "square";
    
    amp.gain.setValueAtTime(0.125, t);
    amp.gain.exponentialRampToValueAtTime(1e-2, t + DURATION);
    
    osc.connect(amp);
    amp.connect(context.destination);
    
    osc.start(t);
    
    setTimeout(function() {
        osc.stop(t);
        osc.disconnect();
        amp.disconnect();
    }, DURATION * 1000);
}

function start() {
    var startTime = context.currentTime + 0.01;
    var counter = 0;
    timerId = setInterval(function() {
        counter += 1;
        play(startTime + counter * INTERVAL);
        $("#message").text(counter);
    }, INTERVAL * 1000);
}

function stop() {
    clearInterval(timerId);
}

var isPlaying = false;

$("#start").on("click", function() {
    isPlaying = !isPlaying;
    if (isPlaying) {
        start();
        $(this).text("stop");
    } else {
        stop();
        $(this).text("start");
    }
});