MMitB - AudioBuffer

by Keith McMillen

HTML

<div class='controls'>
    <button class="play" disabled>Loading...</button>
    <button class="stop" disabled>Stop</button>
</div>
<div class='play-controls'>
    <label for='loop'>loop
        <input type='checkbox' name='loop' class="loop" />
    </label>
    <label for='loop-start'>loop start (seconds)
        <input class="loop-start" type="number" min="0" max="10" step="1" value="0" name="loop-start" disabled>
    </label>
    <label for='loop-end'>loop end (seconds)
        <input class="loop-end" type="number" min="0" max="10" step="1" value="0" name="loop-end" disabled>
    </label>
    <hr>
    <label for='playbackRate'>playback rate <span class='rate'>1</span>
        <input class='playback-slider' name='playbackRate' type='range' min='0' max='10' step='0.05' value='1' disabled />
    </label>
</div>

CSS

body {
  background-color: rgb(250, 250, 250);
}

button {
  display: inline-block;
  margin-bottom: 20px;
}

label {
  display: block;
  font-family: monospace;
  line-height: 20px;
  text-shadow: 1px 1px 3px #ccc;
}

input {
  display: inline-block;
  float: right;
  width: 45%;
}

span {
  display: inline-block;
  width: 75px;
  text-align: center;
  font-weight: bold;
  border: 1px solid #efefef;
  border-radius: 3px;
  background-color: white;
}

hr {
  border-color: rgba(200, 200, 200, 0.1);
}

JavaScript

var audioContext = new(window.AudioContext || window.webkitAudioContext)(),
    sampleURL = 'https://files.keithmcmillen.com/blog/mmitb/dinky-jam.mp3',
    sampleBuffer, sound, playButton = document.querySelector('.play'),
    stopButton = document.querySelector('.stop'),
    loop = false,
    loopButton = document.querySelector('.loop'),
    loopStart = document.querySelector('.loop-start'),
    loopEnd = document.querySelector('.loop-end'),
    playbackSlider = document.querySelector('.playback-slider'),
    playbackRate = document.querySelector('.rate');

// load our sound
init();

function init() {
    loadSound(sampleURL);
}

playButton.onclick = function () {
    playSound();
};

stopButton.onclick = function () {
    stopSound();
};

loopButton.onclick = function (event) {
    loopOn(event);
};

playbackSlider.oninput = function () {
    changeRate(playbackSlider.value);
};

loopStart.oninput = function() {
    setLoopStart(loopStart.value);
};

loopEnd.oninput = function() {
    setLoopEnd(loopEnd.value);
};

// function to load sounds via AJAX
function loadSound(url) {
    // Use a CORS proxy to fetch the audio file
    var proxyUrl = 'https://cors-anywhere.herokuapp.com/';
    var requestUrl = proxyUrl + url;
    
var request = new XMLHttpRequest();
    request.open('GET', requestUrl, true);
    request.responseType = 'arraybuffer';

    request.onload = function () {
        audioContext.decodeAudioData(request.response, function (buffer) {
            var soundLength = buffer.duration;
            sampleBuffer = buffer;
            loopStart.setAttribute('max', Math.floor(soundLength));
            loopEnd.setAttribute('max', Math.floor(soundLength));
            playButton.disabled = false;
            playButton.innerHTML = 'play';
        });
    };

    request.send();
}

// set our sound buffer, loop, and connect to destination
function setupSound() {
    sound = audioContext.createBufferSource();
    sound.buffer = sampleBuffer;
    sound.loop =...