MMitB - Panner
by Keith McMillen
HTML
<div class='controls'>
<button class="btn play" disabled>loading...</button>
<button class="btn stop" disabled>stop</button>
</div>
<div class='play-controls'>
<label for='loop'>loop
<input type='checkbox' name='loop' class="loop" />
</label>
<label for='mousepan'>mouse panner << 🐭 >>
<input type='checkbox' name='mousepan' class="mousepan" />
</label>
</div>
<div class='panning-controls'>
<label>Panning <span class='panning-value'>0</span>
<input class="panning-slider" type="range" min="-1" max="1" step="0.1" value="0" 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
// Mouse Control and / or two tracks/panners
var audioContext = new(window.AudioContext || window.webkitAudioContext)(),
sampleURL = 'https://files.keithmcmillen.com/blog/mmitb/dinky-jam-2.mp3',
sampleBuffer, sound, playButton = document.querySelector('.play'),
stopButton = document.querySelector('.stop'),
loop = false, mousepan = false,
loopButton = document.querySelector('.loop'),
mousePanButton = document.querySelector('.mousepan'),
panningSlider = document.querySelector('.panning-slider'),
panningValue = document.querySelector('.panning-value'),
pannner = audioContext.createStereoPanner();
// load our sound
init();
function init() {
loadSound(sampleURL);
}
// listen for changes to panning slider and update
panningSlider.oninput = function () {
pannner.pan.value = panningSlider.value;
panningValue.innerHTML = panningSlider.value;
};
playButton.onclick = function () {
playSound();
};
stopButton.onclick = function () {
stopSound();
};
loopButton.onclick = function (event) {
loop = event.target.checked;
panningSlider.disabled = false;
};
// mouse movement panning
document.onmousemove = mousePan;
mousePanButton.onclick = function (event) {
mousepan = event.target.checked;
if(mousepan){
panningSlider.disabled = true;
document.documentElement.style.cursor="ew-resize";
} else {
panningSlider.disabled = false;
document.documentElement.style.cursor="default";
}
};
// 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;
...