Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit fefcae5

Browse files
Version 2.0.2
- Guitar distortion effect including Marshall cabinet, ADA cabinet and V-Twin preamp simulation, 5-band equalizer, bass and treble tone controls and two distortion sounds. - Guitar distortion example.
1 parent 14de404 commit fefcae5

File tree

8 files changed

+323
-4
lines changed

8 files changed

+323
-4
lines changed

‎docs.html‎

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1243,6 +1243,50 @@ <h3>Filter</h3>
12431243
filter.destruct();
12441244
</code></pre>
12451245

1246+
<h3>Guitar Distortion</h3>
1247+
1248+
<p>Guitar distortion effect including Marshall cabinet, ADA cabinet and V-Twin preamp simulation, 5-band equalizer, bass and treble tone controls and two distortion sounds. One instance allocates around 32 kb memory.</p>
1249+
1250+
<pre><code class="language-js">
1251+
// Constructor. Enabled is false by default.
1252+
let gd = Superpowered.new('GuitarDistortion',
1253+
44100 // The initial sample rate in Hz.
1254+
);
1255+
1256+
// Do this when the sample rate changes.
1257+
gd.samplerate = 48000;
1258+
1259+
// Turns the effect on/off. False by default. The actual switch will happen on the next process() call for smooth, audio-artifact free operation.
1260+
gd.enable = true;
1261+
1262+
gd.gainDecibel = 0; // Gain value in decibel. Limit: -96 to 24.
1263+
gd.drive = 0.2; // Drive percentage, from 0 to 1.
1264+
gd.bassFrequency = 25; // High-pass filter frequency in Hz. From 1 Hz to 250 Hz.
1265+
gd.trebleFrequency = 8000; // Low-pass filter frequency in Hz. From 6000 Hz to the half of the current sample rate.
1266+
gd.eq80HzDecibel = 0; // EQ 80 Hz decibel gain. Limit: -96 to 24.
1267+
gd.eq240HzDecibel = 0; // EQ 240 Hz decibel gain. Limit: -96 to 24.
1268+
gd.eq750HzDecibel = 0; // EQ 750 Hz decibel gain. Limit: -96 to 24.
1269+
gd.eq2200HzDecibel = 0; // EQ 2200 Hz decibel gain. Limit: -96 to 24.
1270+
gd.eq6600HzDecibel = 0; // EQ 6600 Hz decibel gain. Limit: -96 to 24.
1271+
gd.distortion0 = false; // Enables the first distortion sound, that is similar to Boss DS-1.
1272+
gd.distortion1 = true; // Enables the second distortion sound, that is similar to Tyrian.
1273+
gd.marshall = true; // Enables Marshall cabinet simulation.
1274+
gd.ada = false; // Enables ADA cabinet simulation. Adds a lot of bass and treble.
1275+
gd.vtwin = false; // Enables V-Twin preamp simulation. Recommended for blues/jazz.
1276+
1277+
// Processes interleaved stereo audio. Always call it in the audio processing callback, regardless if the effect is enabled or not for smooth, audio-artifact free operation.
1278+
// It's never blocking for real-time usage. You can change all properties on any thread, concurrently with process(). Do not call any method concurrently with process().
1279+
// If process() returns with true, the contents of output are replaced with the audio output. If process() returns with false, the contents of output are not changed.
1280+
gd.process(
1281+
input, // Pointer to floating point numbers. 32-bit interleaved stereo input.
1282+
output, // Pointer to floating point numbers. 32-bit interleaved stereo output. Can point to the same location with input (in-place processing).
1283+
128 // Number of frames to process. Recommendations for best performance: multiply of 4, minimum 64.
1284+
);
1285+
1286+
// Destructor (to free up memory).
1287+
gd.destruct();
1288+
</code></pre>
1289+
12461290
<h3>Spatializer</h3>
12471291

12481292
<p>CPU-friendly 3D audio spatializer. One instance allocates around 140 kb memory.</p>

‎example_effects/main.js‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ function setState(newState) {
1515
// called when the user provided permission for the microphone
1616
function onStreamCreated(micStream) {
1717
let currentPath = window.location.pathname.substring(0, window.location.pathname.lastIndexOf('/'));
18-
18+
1919
Superpowered.createAudioNode(audioContext, currentPath + '/processor.js', 'MyProcessor',
2020
// runs after the audio node is created
2121
function(newNode) {
@@ -70,7 +70,7 @@ Superpowered = SuperpoweredModule({
7070
onReady: function() {
7171
// UI: innerHTML may be ugly but keeps this example small
7272
document.getElementById('content').innerHTML = '\
73-
<p>Put on your headphones fiirst, you\'ll be deaf due audio feedback otherwise.</p>\
73+
<p>Put on your headphones first, you\'ll be deaf due audio feedback otherwise.</p>\
7474
<p id="audioStack" style="font-style: italic"></p>\
7575
<p><button id="btn">-</button></p>\
7676
<p>Reverb wet: <input type="range" min="0" max="100" value="50" class="reverbslider" id="wet"></p>\

‎example_guitardistortion/index.html‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<title>Superpowered WebAssembly Guitar Distortion Example</title>
5+
<style type="text/css">
6+
body {font-family: Arial, sans-serif; margin: 20px;}
7+
input[type=range] { width: 100%;}
8+
</style>
9+
</head>
10+
<body>
11+
<div id="content">Initializing...</div>
12+
<script src="main.js" type="module"></script>
13+
</body>
14+
</html>

‎example_guitardistortion/main.js‎

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
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+
});
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import SuperpoweredModule from '../superpowered.js'
2+
3+
var Superpowered = null;
4+
5+
class MyProcessor extends SuperpoweredModule.AudioWorkletProcessor {
6+
// runs after the constructor
7+
onReady() {
8+
Superpowered = this.Superpowered;
9+
this.posFrames = -1;
10+
// allocating some WASM memory for passing audio to the time stretcher
11+
this.pcm = Superpowered.createFloatArray(2048 * 2);
12+
// the star of the show
13+
this.distortion = Superpowered.new('GuitarDistortion', Superpowered.samplerate);
14+
this.distortion.enabled = true;
15+
}
16+
17+
onMessageFromMainScope(message) {
18+
// did we receive the audio from the main thread?
19+
if (message.left && message.right) {
20+
// left and right channels are NOT stored in WASM memory
21+
this.left = message.left;
22+
this.right = message.right;
23+
24+
this.lengthFrames = Math.min(message.left.length, message.right.length);
25+
this.posFrames = 0;
26+
}
27+
if (message.left) delete message.left;
28+
if (message.right) delete message.right;
29+
for (let property in message) {
30+
if (typeof this.distortion[property] !== 'undefined') this.distortion[property] = message[property];
31+
}
32+
}
33+
34+
processAudio(inputBuffer, outputBuffer, buffersize, parameters) {
35+
// did we receive the left and right channels already?
36+
if (this.posFrames == -1) { // if not, output silence
37+
for (let n = 0; n < buffersize * 2; n++) outputBuffer.array[n] = 0;
38+
return;
39+
}
40+
41+
// if we're near the end just play from the beginning
42+
if (this.posFrames + buffersize >= this.lengthFrames) this.posFrames = 0;
43+
44+
// copy the audio samples to the WASM memory and step posFrames
45+
for (let n = 0, to = buffersize * 2; n < to; n++) {
46+
this.pcm.array[n++] = this.left[this.posFrames];
47+
this.pcm.array[n] = this.right[this.posFrames++];
48+
}
49+
50+
// actual audio processing
51+
this.distortion.process(this.pcm.pointer, outputBuffer.pointer, buffersize);
52+
return true;
53+
}
54+
}
55+
56+
if (typeof AudioWorkletProcessor === 'function') registerProcessor('MyProcessor', MyProcessor);
57+
export default MyProcessor;

‎example_guitardistortion/track.wav‎

5.76 MB
Binary file not shown.

‎superpowered-worker.js‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎superpowered.js‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /