Skip to content

Commit 4e86cd3

Browse files
authored
Merge pull request #43 from superpoweredSDK/v2.6.7
Superpowered v2.6.7
2 parents 9d2b1bd + 12ff9c8 commit 4e86cd3

17 files changed

+1242
-9
lines changed

Diff for: dist/Superpowered.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
/* eslint-disable */
2+
// @ts-nocheck
23

34
class SuperpoweredGlue {
45

5-
static wasmCDNUrl = "https://cdn.jsdelivr.net/npm/@superpoweredsdk/web@2.6.6/dist/superpowered-npm.wasm"
6+
static wasmCDNUrl = "https://cdn.jsdelivr.net/npm/@superpoweredsdk/web@2.6.7/dist/superpowered-npm.wasm"
67

78
niceSize(bytes) {
89
if (bytes == 0) return '0 byte'; else if (bytes == 1) return '1 byte';
@@ -748,7 +749,7 @@ class SuperpoweredWebAudio {
748749
}.bind(node);
749750
});
750751
} else {
751-
import(/* webpackIgnore: true */ url).then((processorModule) => {
752+
import(/* webpackIgnore: true */ /* viteIgnore: true */ url).then((processorModule) => {
752753
const node = this.audioContext.createScriptProcessor(1024, 2, 2);
753754
node.trackLoaderID = this.Superpowered.registerTrackLoader(node);
754755
node.samplerate = this.audioContext.sampleRate;

Diff for: dist/superpowered-npm.wasm

274 Bytes
Binary file not shown.

Diff for: dist/superpowered.wasm

276 Bytes
Binary file not shown.

Diff for: examples/example_effects/Superpowered.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
/* eslint-disable */
2+
// @ts-nocheck
23

34
class SuperpoweredGlue {
45

5-
static wasmCDNUrl = "https://cdn.jsdelivr.net/npm/@superpoweredsdk/web@2.6.6/dist/superpowered-npm.wasm"
6+
static wasmCDNUrl = "https://cdn.jsdelivr.net/npm/@superpoweredsdk/web@2.6.7/dist/superpowered-npm.wasm"
67

78
niceSize(bytes) {
89
if (bytes == 0) return '0 byte'; else if (bytes == 1) return '1 byte';
@@ -748,7 +749,7 @@ class SuperpoweredWebAudio {
748749
}.bind(node);
749750
});
750751
} else {
751-
import(/* webpackIgnore: true */ url).then((processorModule) => {
752+
import(/* webpackIgnore: true */ /* viteIgnore: true */ url).then((processorModule) => {
752753
const node = this.audioContext.createScriptProcessor(1024, 2, 2);
753754
node.trackLoaderID = this.Superpowered.registerTrackLoader(node);
754755
node.samplerate = this.audioContext.sampleRate;

Diff for: examples/example_guitardistortion/Superpowered.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
/* eslint-disable */
2+
// @ts-nocheck
23

34
class SuperpoweredGlue {
45

5-
static wasmCDNUrl = "https://cdn.jsdelivr.net/npm/@superpoweredsdk/web@2.6.6/dist/superpowered-npm.wasm"
6+
static wasmCDNUrl = "https://cdn.jsdelivr.net/npm/@superpoweredsdk/web@2.6.7/dist/superpowered-npm.wasm"
67

78
niceSize(bytes) {
89
if (bytes == 0) return '0 byte'; else if (bytes == 1) return '1 byte';
@@ -748,7 +749,7 @@ class SuperpoweredWebAudio {
748749
}.bind(node);
749750
});
750751
} else {
751-
import(/* webpackIgnore: true */ url).then((processorModule) => {
752+
import(/* webpackIgnore: true */ /* viteIgnore: true */ url).then((processorModule) => {
752753
const node = this.audioContext.createScriptProcessor(1024, 2, 2);
753754
node.trackLoaderID = this.Superpowered.registerTrackLoader(node);
754755
node.samplerate = this.audioContext.sampleRate;

Diff for: examples/example_pitchbend/assets/Superpowered.js

+869
Large diffs are not rendered by default.

Diff for: examples/example_pitchbend/assets/processor.js

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import "./Superpowered.js";
2+
3+
class MyProcessor extends SuperpoweredWebAudio.AudioWorkletProcessor {
4+
cancelledPitchBend = true;
5+
6+
onReady() {
7+
this.player = new this.Superpowered.AdvancedAudioPlayer(this.samplerate, 2, 2, 0, 0.501, 2, false);
8+
}
9+
10+
onDestruct() {
11+
this.player.destruct();
12+
}
13+
14+
onMessageFromMainScope(message) {
15+
if (message.SuperpoweredLoaded) {
16+
this.player.openMemory(this.Superpowered.arrayBufferToWASM(message.SuperpoweredLoaded.buffer), false, false);
17+
this.player.play();
18+
this.sendMessageToMainScope({ loaded: true });
19+
}
20+
if (typeof message.rate !== 'undefined') this.player.playbackRate = message.rate / 10000.0;
21+
if (typeof message.pitchShift !== 'undefined') this.player.pitchShiftCents = parseInt(message.pitchShift) * 100;
22+
if (typeof message.requestPitchBend !== 'undefined') this.sendMessageToMainScope({ pitchBendDetails: {currentPitchBend: this.currentPitchBend, currentPitchBendMsOffset: this.currentPitchBendMsOffset} })
23+
if (message.pitchBend) this.pitchBend = message.maxPercent !== 0 ? {
24+
maxPercent: message.maxPercent,
25+
bendStretch: message.bendStretch,
26+
faster: message.faster,
27+
holdMs: message.holdMs
28+
} : undefined;
29+
}
30+
31+
processAudio(inputBuffer, outputBuffer, buffersize, parameters) {
32+
if (this.pitchBend) {
33+
this.player.pitchBend(this.pitchBend.maxPercent, this.pitchBend.bendStretch, this.pitchBend.faster, this.pitchBend.holdMs);
34+
this.cancelledPitchBend = false;
35+
} else if (!this.cancelledPitchBend) {
36+
this.player.endContinuousPitchBend();
37+
this.cancelledPitchBend = true;
38+
}
39+
this.currentPitchBend = this.player.getCurrentPitchBendPercent();
40+
this.currentPitchBendMsOffset = this.player.getBendOffsetMs();
41+
if (!this.player.processStereo(outputBuffer.pointer, false, buffersize, 1)) this.Superpowered.memorySet(outputBuffer.pointer, 0, buffersize * 8);
42+
}
43+
}
44+
45+
if (typeof AudioWorkletProcessor === 'function') registerProcessor('MyProcessor', MyProcessor);
46+
export default MyProcessor;
1.25 MB
Binary file not shown.

Diff for: examples/example_pitchbend/assets/superpowered.svg

+14
Loading

Diff for: examples/example_pitchbend/assets/track.mp3

1.84 MB
Binary file not shown.

Diff for: examples/example_pitchbend/assets/wave.svg

+20
Loading

Diff for: examples/example_pitchbend/index.html

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<title>Superpowered WebAssembly Audio Player Time Stretching and Pitch Shifting Example</title>
5+
<script type="module" src="./polyfill_worklet_import.js"></script>
6+
<link href="/style.css" rel="stylesheet" />
7+
</head>
8+
<body>
9+
<div class="container">
10+
<img class="logo" src="/assets/superpowered.svg" />
11+
<div class="controls">
12+
<h2>AAP pitch/speed controls</h2>
13+
<p>A demonstration of pitch bend, pitch shift and playback rate changes with the Advanced Audio Player class</p>
14+
<div id="content">Initializing...</div>
15+
</div>
16+
</div>
17+
18+
<script src="main.js" type="module"></script>
19+
</body>
20+
</html>

Diff for: examples/example_pitchbend/main.js

+163
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
import "./assets/Superpowered.js";
2+
3+
var webaudioManager = null; // The SuperpoweredWebAudio helper class managing Web Audio for us.
4+
var Superpowered = null; // A Superpowered instance.
5+
var audioNode = null; // This example uses one audio node only.
6+
var content = null; // The <div> displaying everything.
7+
var pitchShift = 0; // The current pitch shift value.
8+
var currentPath = null;
9+
var pbPerc = null;
10+
11+
function changePitchShift(e) {
12+
// limiting the new pitch shift value
13+
// let value = parseInt(e.target.value);
14+
// pitchShift += value;
15+
16+
pitchShift = Math.min(12, Math.max(-12, pitchShift + parseInt(e.target.value)));
17+
18+
// if (pitchShift < -12) pitchShift = -12; else if (pitchShift > 12) pitchShift = 12;
19+
// displaying the value
20+
document.getElementById('pitch-shift-display').textContent = ' pitch shift: ' + ((pitchShift < 1) ? pitchShift : '+' + pitchShift) + ' ';
21+
// sending the new value to the audio node
22+
audioNode.sendMessageToAudioScope({ 'pitchShift': pitchShift });
23+
}
24+
25+
// on change by the rate slider
26+
function changeRate() {
27+
// displaying the new rate
28+
let value = document.getElementById('rateSlider').value, text;
29+
if (value == 10000) text = 'original tempo';
30+
else if (value < 10000) text = '-' + (100 - value / 100).toPrecision(2) + '%';
31+
else text = '+' + (value / 100 - 100).toPrecision(2) + '%';
32+
document.getElementById('rateDisplay').textContent = text;
33+
// sending the new rate to the audio node
34+
audioNode.sendMessageToAudioScope({ rate: value });
35+
}
36+
37+
function changePitchBend(e) {
38+
console.log(Number(document.getElementById('holdMsSelect').value));
39+
const value = e.target.value;
40+
audioNode.sendMessageToAudioScope({
41+
'pitchBend': true,
42+
maxPercent: Math.abs(value/100),
43+
bendStretch: 0,
44+
faster: value < 0 ? 0 : 1,
45+
holdMs: Number(document.getElementById('holdMsSelect').value)
46+
});
47+
}
48+
49+
// double click on the rate slider
50+
function changeRateDbl() {
51+
document.getElementById('rateSlider').value = 10000;
52+
changeRate();
53+
}
54+
55+
// double click on the rate slider
56+
function changeBendDbl() {
57+
document.getElementById('pitchBend').value = 0;
58+
audioNode.sendMessageToAudioScope({
59+
'pitchBend': true,
60+
maxPercent: 0,
61+
bendStretch: 0,
62+
faster: 0,
63+
holdMs: Number(document.getElementById('holdMsSelect').value)
64+
});
65+
}
66+
67+
// click on play/pause
68+
function togglePlayback(e) {
69+
let button = document.getElementById('playPause');
70+
if (button.value == 1) {
71+
button.value = 0;
72+
button.textContent = 'Play audio';
73+
webaudioManager.audioContext.suspend();
74+
} else {
75+
button.value = 1;
76+
button.textContent = 'Pause audio';
77+
webaudioManager.audioContext.resume();
78+
}
79+
}
80+
81+
function onMessageFromAudioScope(message) {
82+
if (message.loaded) {
83+
// UI: innerHTML may be ugly but keeps this example small
84+
content.innerHTML = '\
85+
<button id="playPause" value="0">Play audio</button>\
86+
<h3>Pitch bend holdMs</h3>\
87+
<select id="holdMsSelect"><option>40</option><option>200</option><option>300</option><option>600</option><option>1000</option></select><span>ms</span>\
88+
<h3>Pitch bend percentage</h3>\
89+
<div style="width: 100%; display: flex; justify-content: space-between;"><span>-30%</span><span>0%</span><span>+30%</span></div>\
90+
<input id="pitchBend" type="range" min="-30" max="30" value="0" style="width: 100%">\
91+
<div style="overflow: hidden; border-radius: 5px; background: #909090; width: 100%; postion: relative;" id="bend-container"><div style="width: 50%; height: 10px; background: black;" id="bend-value"></div></div>\
92+
<div style="text-align: center;"><span><span id="pitch-bend-percentage">100</span>%</span></div><br />\
93+
<button id="reset-bend">Reset pitch bend</button>\
94+
<h3>Playback rate</h3>\
95+
<span id="rateDisplay">original tempo</span>\
96+
<div style="width: 100%; display: flex; justify-content: space-between;"><span>-50%</span><span>+100%</span></div>\
97+
<input id="rateSlider" type="range" min="5000" max="20000" value="10000" style="width: 100%">\
98+
<button id="reset-rate">Reset playback rate</button> <br /><br />\
99+
<div>\
100+
<button id="pitchMinus" value="-1">-</button>\
101+
<span id="pitch-shift-display"> pitch shift: 0 </span>\
102+
<button id="pitchPlus" value="1">+</button>\
103+
</div>\
104+
';
105+
document.getElementById('rateSlider').addEventListener('input', changeRate);
106+
document.getElementById('pitchBend').addEventListener('input', changePitchBend);
107+
document.getElementById('pitchBend').addEventListener('dblclick', changeBendDbl);
108+
document.getElementById('rateSlider').addEventListener('dblclick', changeRateDbl);
109+
document.getElementById('reset-bend').addEventListener('click', changeBendDbl);
110+
document.getElementById('reset-rate').addEventListener('click', changeRateDbl);
111+
document.getElementById('pitchMinus').addEventListener('click', changePitchShift);
112+
document.getElementById('pitchPlus').addEventListener('click', changePitchShift);
113+
document.getElementById('playPause').addEventListener('click', togglePlayback);
114+
pbPerc = document.getElementById('pitch-bend-percentage');
115+
}
116+
if (message.pitchBendDetails && document.getElementById('bend-value')) {
117+
if (pbPerc && (typeof message.pitchBendDetails.currentPitchBend !== 'undefined')) {
118+
pbPerc.textContent = message.pitchBendDetails.currentPitchBend * 100;
119+
document.getElementById('bend-value').style.width = convertRange(message.pitchBendDetails.currentPitchBend * 100, [70, 130], [0, 100]) + '%';
120+
document.getElementById('bend-value').style.background = message.pitchBendDetails.currentPitchBend === 1 ? 'black' : message.pitchBendDetails.currentPitchBend < 1 ? 'red' : 'green';
121+
}
122+
}
123+
}
124+
125+
function convertRange( value, r1, r2 ) {
126+
return ( value - r1[ 0 ] ) * ( r2[ 1 ] - r2[ 0 ] ) / ( r1[ 1 ] - r1[ 0 ] ) + r2[ 0 ];
127+
}
128+
129+
function requestPitchBendDetails() {
130+
audioNode.sendMessageToAudioScope({ requestPitchBend: true });
131+
requestAnimationFrame(requestPitchBendDetails)
132+
}
133+
134+
// when the START button is clicked
135+
async function start() {
136+
webaudioManager = new SuperpoweredWebAudio(44100, Superpowered);
137+
currentPath = window.location.href.substring(0, window.location.href.lastIndexOf('/'));
138+
audioNode = await webaudioManager.createAudioNodeAsync(window.location.href + '/assets/processor.js?date=' + Date.now(), 'MyProcessor', onMessageFromAudioScope);
139+
// audioNode -> audioContext.destination (audio output)
140+
webaudioManager.audioContext.suspend();
141+
audioNode.connect(webaudioManager.audioContext.destination);
142+
143+
// start polling of pitch bend details from audioworklet
144+
requestAnimationFrame(requestPitchBendDetails)
145+
}
146+
147+
async function loadFromMainThread() {
148+
Superpowered.downloadAndDecode(window.location.href + '/assets/track.mp3', audioNode);
149+
}
150+
151+
async function loadJS() {
152+
Superpowered = await SuperpoweredGlue.Instantiate('ExampleLicenseKey-WillExpire-OnNextUpdate', `${window.location.href}/assets/superpowered-npm.wasm`);
153+
154+
// display the START button
155+
content = document.getElementById('content');
156+
content.innerHTML = `<div>
157+
<button id="startApplication">Start</button>
158+
</div>`;
159+
document.getElementById('startApplication').addEventListener('click', loadFromMainThread);
160+
start();
161+
}
162+
163+
loadJS();

0 commit comments

Comments
 (0)