|  | 
|  | 1 | +import SuperpoweredModule from '../superpowered.js' | 
|  | 2 | + | 
|  | 3 | +var audioContext = null; // Reference to the audio context. | 
|  | 4 | +var audioNode = null; // This example uses one audio node only. | 
|  | 5 | +var Superpowered = null; // Reference to the Superpowered module. | 
|  | 6 | +var content = null; // The <div> displaying everything. | 
|  | 7 | + | 
|  | 8 | +const presets = { | 
|  | 9 | + transparent: { | 
|  | 10 | + distortion0: false, | 
|  | 11 | + distortion1: false, | 
|  | 12 | + marshall: false, | 
|  | 13 | + ada: false, | 
|  | 14 | + vtwin: false, | 
|  | 15 | + drive: 0, | 
|  | 16 | + gainDecibel: 0, | 
|  | 17 | + bassFrequency: 1, | 
|  | 18 | + trebleFrequency: 22050, | 
|  | 19 | + eq80HzDecibel: 0, | 
|  | 20 | + eq240HzDecibel: 0, | 
|  | 21 | + eq750HzDecibel: 0, | 
|  | 22 | + eq2200HzDecibel: 0, | 
|  | 23 | + eq6600HzDecibel: 0 | 
|  | 24 | + }, | 
|  | 25 | + preset1: { | 
|  | 26 | + distortion0: false, | 
|  | 27 | + distortion1: true, | 
|  | 28 | + marshall: false, | 
|  | 29 | + ada: false, | 
|  | 30 | + vtwin: false, | 
|  | 31 | + drive: 80, | 
|  | 32 | + gainDecibel: -10, | 
|  | 33 | + bassFrequency: 1, | 
|  | 34 | + trebleFrequency: 22050, | 
|  | 35 | + eq80HzDecibel: 0, | 
|  | 36 | + eq240HzDecibel: -6, | 
|  | 37 | + eq750HzDecibel: -12, | 
|  | 38 | + eq2200HzDecibel: -6, | 
|  | 39 | + eq6600HzDecibel: 0 | 
|  | 40 | + }, | 
|  | 41 | + preset2: { | 
|  | 42 | + distortion0: true, | 
|  | 43 | + distortion1: false, | 
|  | 44 | + marshall: true, | 
|  | 45 | + ada: false, | 
|  | 46 | + vtwin: false, | 
|  | 47 | + drive: 10, | 
|  | 48 | + gainDecibel: -12, | 
|  | 49 | + bassFrequency: 25, | 
|  | 50 | + trebleFrequency: 22050, | 
|  | 51 | + eq80HzDecibel: 0, | 
|  | 52 | + eq240HzDecibel: -6, | 
|  | 53 | + eq750HzDecibel: -3, | 
|  | 54 | + eq2200HzDecibel: -6, | 
|  | 55 | + eq6600HzDecibel: 3 | 
|  | 56 | + } | 
|  | 57 | +} | 
|  | 58 | + | 
|  | 59 | +// click on play/pause | 
|  | 60 | +function togglePlayback(e) { | 
|  | 61 | + let button = document.getElementById('playPause'); | 
|  | 62 | + if (button.value == 1) { | 
|  | 63 | + button.value = 0; | 
|  | 64 | + button.innerText = 'START PLAYBACK'; | 
|  | 65 | + audioContext.suspend(); | 
|  | 66 | + } else { | 
|  | 67 | + button.value = 1; | 
|  | 68 | + button.innerText = 'PAUSE'; | 
|  | 69 | + audioContext.resume(); | 
|  | 70 | + } | 
|  | 71 | +} | 
|  | 72 | + | 
|  | 73 | +// applies a preset on all controls | 
|  | 74 | +function applyPreset(preset) { | 
|  | 75 | + let sliders = document.getElementsByClassName('slider'); | 
|  | 76 | + for (let slider of sliders) { | 
|  | 77 | + slider.value = preset[slider.id]; | 
|  | 78 | + slider.oninput(); | 
|  | 79 | + } | 
|  | 80 | + let checkboxes = document.getElementsByClassName('checkbox'); | 
|  | 81 | + for (let checkbox of checkboxes) { | 
|  | 82 | + checkbox.checked = preset[checkbox.id]; | 
|  | 83 | + checkbox.oninput(); | 
|  | 84 | + } | 
|  | 85 | +} | 
|  | 86 | + | 
|  | 87 | +// we have the audio system created, let's display the UI and start playback | 
|  | 88 | +function onAudioDecoded(buffer) { | 
|  | 89 | + // send the PCM audio to the audio node | 
|  | 90 | + audioNode.sendMessageToAudioScope({ | 
|  | 91 | + left: buffer.getChannelData(0), | 
|  | 92 | + right: buffer.getChannelData(1) } | 
|  | 93 | + ); | 
|  | 94 | + | 
|  | 95 | + // audioNode -> audioContext.destination (audio output) | 
|  | 96 | + audioContext.suspend(); | 
|  | 97 | + audioNode.connect(audioContext.destination); | 
|  | 98 | + | 
|  | 99 | + // UI: innerHTML may be ugly but keeps this example relatively small | 
|  | 100 | + content.innerHTML = '\ | 
|  | 101 | + <h3>Choose from these presets for A/B comparison:</h3>\ | 
|  | 102 | + <p id="presets"></p>\ | 
|  | 103 | + <h3>Play/pause:</h3>\ | 
|  | 104 | + <button id="playPause" value="0">START PLAYBACK</button>\ | 
|  | 105 | + <h3>Fine tune all controls:</h3>\ | 
|  | 106 | + <p>Distortion Sound 1 <input type="checkbox" class="checkbox" id="distortion0"></p>\ | 
|  | 107 | + <p>Distortion Sound 2 <input type="checkbox" class="checkbox" id="distortion1"></p>\ | 
|  | 108 | + <p>Marshall Cabinet Simulation <input type="checkbox" class="checkbox" id="marshall"></p>\ | 
|  | 109 | + <p>ADA Cabinet Simulation <input type="checkbox" class="checkbox" id="ada"></p>\ | 
|  | 110 | + <p>V-Twin Preamp Simulation <input type="checkbox" class="checkbox" id="vtwin"></p>\ | 
|  | 111 | + <p>Drive (<span id="driveValue"></span>%): <input type="range" min="0" max="100" data-multiplier="0.01" class="slider" id="drive"></p>\ | 
|  | 112 | + <p>Gain (<span id="gainDecibelValue"></span>db): <input type="range" min="-96" max="24" class="slider" id="gainDecibel"></p>\ | 
|  | 113 | + <p>Bass (<span id="bassFrequencyValue"></span>Hz): <input type="range" min="1" max="250" class="slider" id="bassFrequency"></p>\ | 
|  | 114 | + <p>Treble (<span id="trebleFrequencyValue"></span>Hz): <input type="range" min="6000" max="22050" class="slider" id="trebleFrequency"></p>\ | 
|  | 115 | + <p>EQ 80 Hz (<span id="eq80HzDecibelValue"></span>db): <input type="range" min="-96" max="24" class="slider" id="eq80HzDecibel"></p>\ | 
|  | 116 | + <p>EQ 240 Hz (<span id="eq240HzDecibelValue"></span>db): <input type="range" min="-96" max="24" class="slider" id="eq240HzDecibel"></p>\ | 
|  | 117 | + <p>EQ 750 Hz (<span id="eq750HzDecibelValue"></span>db): <input type="range" min="-96" max="24" class="slider" id="eq750HzDecibel"></p>\ | 
|  | 118 | + <p>EQ 2200 Hz (<span id="eq2200HzDecibelValue"></span>db): <input type="range" min="-96" max="24" class="slider" id="eq2200HzDecibel"></p>\ | 
|  | 119 | + <p>EQ 6600 Hz (<span id="eq6600HzDecibelValue"></span>db): <input type="range" min="-96" max="24" class="slider" id="eq6600HzDecibel"></p>\ | 
|  | 120 | + '; | 
|  | 121 | + | 
|  | 122 | + // make the preset buttons | 
|  | 123 | + let p = document.getElementById('presets'); | 
|  | 124 | + for (let preset in presets) { | 
|  | 125 | + let button = document.createElement('button'); | 
|  | 126 | + button.id = preset; | 
|  | 127 | + button.innerText = preset; | 
|  | 128 | + button.addEventListener('click', function() { | 
|  | 129 | + applyPreset(presets[this.id]); | 
|  | 130 | + if (document.getElementById('playPause').value != 1) togglePlayback(); | 
|  | 131 | + }); | 
|  | 132 | + p.appendChild(button); | 
|  | 133 | + p.appendChild(document.createTextNode(' ')); | 
|  | 134 | + } | 
|  | 135 | + | 
|  | 136 | + document.getElementById('playPause').addEventListener('click', togglePlayback); | 
|  | 137 | + | 
|  | 138 | + // slider actions | 
|  | 139 | + let sliders = document.getElementsByClassName('slider'); | 
|  | 140 | + for (let slider of sliders) { | 
|  | 141 | + slider.oninput = function() { | 
|  | 142 | + if (audioNode == null) return; | 
|  | 143 | + document.getElementById(this.id + 'Value').innerText = this.value; | 
|  | 144 | + let message = {}; | 
|  | 145 | + let multiplier = slider.hasAttribute('data-multiplier') ? parseFloat(slider.getAttribute('data-multiplier')) : 1; | 
|  | 146 | + message[this.id] = this.value * multiplier; | 
|  | 147 | + audioNode.sendMessageToAudioScope(message); | 
|  | 148 | + } | 
|  | 149 | + } | 
|  | 150 | + | 
|  | 151 | + // checkbox actions | 
|  | 152 | + let checkboxes = document.getElementsByClassName('checkbox'); | 
|  | 153 | + for (let checkbox of checkboxes) { | 
|  | 154 | + checkbox.oninput = function() { | 
|  | 155 | + if (audioNode == null) return; | 
|  | 156 | + let message = {}; | 
|  | 157 | + message[this.id] = this.checked; | 
|  | 158 | + audioNode.sendMessageToAudioScope(message); | 
|  | 159 | + } | 
|  | 160 | + } | 
|  | 161 | + | 
|  | 162 | + applyPreset(presets.transparent); | 
|  | 163 | +} | 
|  | 164 | + | 
|  | 165 | +// when the START button is clicked | 
|  | 166 | +function start() { | 
|  | 167 | + content.innerText = 'Creating the audio context and node...'; | 
|  | 168 | + audioContext = Superpowered.getAudioContext(44100); | 
|  | 169 | + let currentPath = window.location.pathname.substring(0, window.location.pathname.lastIndexOf('/')); | 
|  | 170 | + | 
|  | 171 | + Superpowered.createAudioNode(audioContext, currentPath + '/processor.js', 'MyProcessor', | 
|  | 172 | + // runs after the audio node is created | 
|  | 173 | + function(newNode) { | 
|  | 174 | + audioNode = newNode; | 
|  | 175 | + content.innerText = 'Downloading music...'; | 
|  | 176 | + | 
|  | 177 | + // downloading the music | 
|  | 178 | + let request = new XMLHttpRequest(); | 
|  | 179 | + request.open('GET', 'track.wav', true); | 
|  | 180 | + request.responseType = 'arraybuffer'; | 
|  | 181 | + request.onload = function() { | 
|  | 182 | + content.innerText = 'Decoding audio...'; | 
|  | 183 | + audioContext.decodeAudioData(request.response, onAudioDecoded); | 
|  | 184 | + } | 
|  | 185 | + request.send(); | 
|  | 186 | + }, | 
|  | 187 | + | 
|  | 188 | + // runs when the audio node sends a message | 
|  | 189 | + function(message) { | 
|  | 190 | + console.log('Message received from the audio node: ' + message); | 
|  | 191 | + } | 
|  | 192 | + ); | 
|  | 193 | +} | 
|  | 194 | + | 
|  | 195 | +Superpowered = SuperpoweredModule({ | 
|  | 196 | + licenseKey: 'ExampleLicenseKey-WillExpire-OnNextUpdate', | 
|  | 197 | + enableAudioEffects: true, | 
|  | 198 | + | 
|  | 199 | + onReady: function() { | 
|  | 200 | + content = document.getElementById('content'); | 
|  | 201 | + content.innerHTML = '<button id="startButton">START</button>'; | 
|  | 202 | + document.getElementById('startButton').addEventListener('click', start); | 
|  | 203 | + } | 
|  | 204 | +}); | 
0 commit comments