MMitB - Filter

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>
</div>
<div class='filter-controls'>
    <label for='filterFreq'>filter frequency <span class='freq'>2500Hz</span>

        <input class='filter-slider' name='filterFreq' type='range' min='0' max='20000' step='10' value='2500' disabled />
    </label>
    <label>quality (Q) value <span class='filter-q-value'>1</span> 
        <input class="filter-q-slider" type="range" min=".0001" max="10" step=".0005" value="1" disabled/>
    </label>
    <label>filter gain value <span class='filter-gain-value'>0</span> 
        <input class="filter-gain-slider" type="range" min="-40" max="40" step="1" value="0" disabled/>
    </label>
    <p>filter type</p>
    <select name="filterType" class="filtertype">
        <option value="lowpass">lowpass</option>
        <option value="highpass">highpass</option>
        <option value="bandpass">bandpass</option>
        <option value="lowshelf">lowshelf</option>
        <option value="highshelf">highshelf</option>
        <option value="peaking">peaking</option>
        <option value="notch">notch</option>
        <option value="allpass">allpass</option>
    </select>
</div>

CSS

body { background-color: rgb(250,250,250); font-family: monospace; }
button {display: inline-block; margin-bottom: 20px;}
label {display: block;  line-height: 20px;}
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)(),
    filter = audioContext.createBiquadFilter(),
    sampleURL = 'https://files.keithmcmillen.com/blog/mmitb/dinky-jam-2.mp3',
    sampleBuffer, sound, playButton = document.querySelector('.play'),
    stopButton = document.querySelector('.stop'),
    loop = false,
    loopButton = document.querySelector('.loop'),

    filterType = document.querySelector('.filtertype'),
    filterFreq = document.querySelector('.freq'),
    filterFreqSlider = document.querySelector('.filter-slider'),

    filterQ = document.querySelector('.filter-q-value'),
    filterQSlider = document.querySelector('.filter-q-slider'),

    filterGain = document.querySelector('.filter-gain-value'),
    filterGainSlider = document.querySelector('.filter-gain-slider');

// load our sound
init();

function init() {
    loadSound(sampleURL);
}

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

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

loopButton.onclick = function () {
    loop = event.target.checked;
};

filterType.oninput = function () {
    changeFilterType(filterType.value);
};

filterFreqSlider.oninput = function () {
    changeFilterFreq(filterFreqSlider.value);
};

filterQSlider.oninput = function () {
    changeFilterQ(filterQSlider.value);
};

filterGainSlider.oninput = function () {
    changeFilterGain(event.target.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) {
            sampleBuffer = buffer;
            playButton.disabled = false;
            playButton.innerHTML = 'play';
        });
   ...