Audio Data API

Original Code : https://wiki.mozilla.org/Audio_Data_API

by ethertank

HTML

<input type="text" size="4" id="freq" value="440">
<label for="hz">Hz</label>
<button onclick="start()">play</button>  
<button onclick="stop()">stop</button>

JavaScript

function AudioDataDestination(sampleRate, readFn) { // オーディオ出力の初期化   
    var audio = new Audio();
    audio.mozSetup(1, sampleRate);
    var currentWritePosition = 0;
    var prebufferSize = sampleRate / 2; // バッファ 500ms   
    var tail = null,
        tailPosition;
    // The function called with regular interval to populate  
    // the audio output buffer.
    setInterval(function() {
        var written;
        // Check if some data was not written in previous attempts.         
        if (tail) {
            written = audio.mozWriteAudio(tail.subarray(tailPosition));
            currentWritePosition += written;
            tailPosition += written;
            if (tailPosition < tail.length) {
                // Not all the data was written, saving the tail...        
                return; // ... and exit the function.  
            }
            tail = null;
        } // Check if we need add some data to the audio output.  
        var currentPosition = audio.mozCurrentSampleOffset();
        var available = currentPosition + prebufferSize - currentWritePosition;
        if (available > 0) { // Request some sound data from the callback function.   
            var soundData = new Float32Array(available);
            readFn(soundData);
            // Writting the data.       
            written = audio.mozWriteAudio(soundData);
            if (written < soundData.length) { // Not all the data was written, saving the tail.            
                tail = soundData;
                tailPosition = written;
            }
            currentWritePosition += written;
        }
    }, 100);
}


// コントロールと音の作成  
var frequency = 0,
    currentSoundSample;
var sampleRate = 44100;

function requestSoundData(soundData) {
    if (!frequency) { // 音が選択されていない場合
        return;    
    }
    
    var k = 2 * Math.PI * frequency / sampleRate;
    for (var i = 0, size = soundData.length; i < size; i++) {
        soundData[i] = Math.sin(k * currentSoundSample++);
   ...