Input -> Audio Nodes -> Destination
Step 1: Create HTML page
Let’s get started with a blank HTML page that has bootstrap 4, jQuery, and a file input element. It will also contain a “Compress” button for the user to click when they’re ready to process their file.<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<!-- Bootstrap 4 -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-12">
<div style="margin: 200px auto 0; width: 300px;">
<h5>Upload Audio File</h5>
<fieldset>
<input type="file" id="audio-file" accept="audio/mpeg, audio/ogg, audio/*" />
<button type="button" id="compress_btn" class="btn btn-outline-primary" style="margin-top: 20px;">Compress</button>
</fieldset>
</div>
<div>
</div>
</div>
</div>
</body>
</html>
Step 2: Define our audio processing in compressor.js
Next, we’ll create a JavaScript file called compressor.js and add it add the bottom of the page just above the body tag. Don’t forget to change the path.<script type="text/javascript" src="/wp-content/themes/your-theme/js/compressor.js"></script>
Now we can start adding the Audio Processing functionality to compressor.js. First, to get the file that the user uploaded, we select it.
var fileInput = document.getElementById('audio-file');
Next, we create an AudioContext.
var audioCtx = new (AudioContext || webkitAudioContext)();
Once the user uploads a file, they’ll need to click the button to kick off the processing. We’ll add an event listener to that button, and check for the file inside the event listener callback.
var compress_btn = document.getElementById('compress_btn');
//Load audio file listener
compress_btn.addEventListener("click", function() {
// check for file
if(fileInput.files[0] == undefined) {
// Stop the process and tell the user they need to upload a file.
return false;
}
// Reader will go here
}, false);
Now, that we’ve checked for the input file, we can create a FileReader and start reading the file to an ArrayBuffer. Once it’s finished, we will call decodeAudioData(ArrayBuffer) on the AudioContext we created, passing in the ArrayBuffer of audio data.
We will use the Promise version of decodeAudioData as opposed to the event based version. After decodeAudioData is through, we’ll pass the resulting AudioBuffer to the then() function of the Promise. Inside the decodeAudioData() function, we call createBufferSource() on the AudioContext to create a BufferSourceNode. Then we set it’s buffer to the buffer passed in from the Promise. The BufferSourceNode is the first node the audio will travel through. After this node, we can send it to any node(s) we want.
// Reader will go here
var reader1 = new FileReader();
reader1.onload = function(ev) {
// Decode audio
audioCtx.decodeAudioData(ev.target.result).then(function(buffer) {
var soundSource = audioCtx.createBufferSource();
soundSource.buffer = buffer;
// Create Compressor Node
});
};
reader1.readAsArrayBuffer(fileInput.files[0]);
Process the AudioBuffer
Finally, we’re ready to create the Compressor Node. We use createDynamicsCompressor() and then put in our compressor settings. You can put whatever you want here, but these settings tell our compressor how to work.// Create Compressor Node
var compressor = audioCtx.createDynamicsCompressor();
compressor.threshold.setValueAtTime(-20, audioCtx.currentTime);
compressor.knee.setValueAtTime(-30, audioCtx.currentTime);
compressor.ratio.setValueAtTime(5, audioCtx.currentTime);
compressor.attack.setValueAtTime(.05, audioCtx.currentTime);
compressor.release.setValueAtTime(.25, audioCtx.currentTime);
soundSource.buffer = buffer;
soundSource.buffer = buffer;
soundSource.connect(compressor);
Finally, connect the last node to the AudioContext destination and play the audio.
compressor.connect(audioCtx.destination);
soundSource.start(0);
You’re compressor.js should like something like this:
var fileInput = document.getElementById('audio-file');
var audioCtx = new (AudioContext || webkitAudioContext)();
var compress_btn = document.getElementById('compress_btn');
//Load audio file listener
compress_btn.addEventListener("click", function() {
// check for file
if(fileInput.files[0] == undefined) {
// Stop the process and tell user they need to upload a file.
return false;
}
var reader1 = new FileReader();
reader1.onload = function(ev) {
// Decode audio
audioCtx.decodeAudioData(ev.target.result).then(function(buffer) {
var soundSource = audioCtx.createBufferSource();
soundSource.buffer = buffer;
// Create Compressor Node
compressor = audioCtx.createDynamicsCompressor();
compressor.threshold.setValueAtTime(-20, audioCtx.currentTime);
compressor.knee.setValueAtTime(-30, audioCtx.currentTime);
compressor.ratio.setValueAtTime(5, audioCtx.currentTime);
compressor.attack.setValueAtTime(.05, audioCtx.currentTime);
compressor.release.setValueAtTime(.25, audioCtx.currentTime);
soundSource.connect(compressor);
compressor.connect(audioCtx.destination);
soundSource.start(0);
});
};
reader1.readAsArrayBuffer(fileInput.files[0]);
}, false);
Now you should be able to upload a file, click the Compress button, and hear the processed audio played back.
yes it works great but you omitted the
Var
Var compressor = audioCtx.createDynamicsCompressor();
Great stuff!!;
Thanks..
Good catch Steve. Thanks. I updated the code example.