forked from lichen-community-systems/signaletic
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
…sm bindings for several Signals, with example. This commit temporarily breaks the midiToFreq example and running the wasm unit tests in Node.js
- Loading branch information
1 parent
58832af
commit f4a1482
Showing
13 changed files
with
539 additions
and
90 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<title>Oscillator - libstar wasm example</title> | ||
<link href="web-bluemchen.css" rel="stylesheet"> | ||
<script src="https://g200kg.github.io/webaudio-controls/webaudio-controls.js"></script> | ||
</head> | ||
|
||
<body> | ||
<div id="bluemchen"> | ||
<!-- encoder --> | ||
<webaudio-knob id="enc" colors="#000;#000;#fff"></webaudio-knob> | ||
|
||
<canvas id="oled"></canvas> | ||
|
||
<!-- knobs --> | ||
<webaudio-knob id="blueKnob" colors="#fff;#00f;#fff"></webaudio-knob> | ||
<webaudio-knob id="redKnob" colors="#fff;#f00;#fff"></webaudio-knob> | ||
|
||
<!-- jacks midi out, cv, in, out--> | ||
<div class="jack"></div> | ||
<div>midi</div> | ||
<span class="jack"></span> | ||
<span class="jack"></span> | ||
<div>cv</div> | ||
<span class="jack"></span> | ||
<span class="jack"></span> | ||
<div>in</div> | ||
<span class="jack"></span> | ||
<span class="jack"></span> | ||
<div>out</div> | ||
<div> </div> | ||
<div>bluem</div> | ||
<div>chen</div> | ||
</div> | ||
<script> | ||
async function initAudioGraph() { | ||
let context = new AudioContext(); | ||
|
||
let stream = await navigator.mediaDevices.getUserMedia({ | ||
audio: { | ||
channelCount: 2, | ||
echoCancellation: false, | ||
noiseSuppression: false, | ||
autoGainControl: false | ||
}, | ||
video: false | ||
}); | ||
|
||
let source = context.createMediaStreamSource(stream); | ||
|
||
await context.audioWorklet.addModule( | ||
"signaletic-oscillator-worklet.js"); | ||
|
||
const signaleticOsc = new AudioWorkletNode(context, | ||
"SignaleticOscillator"); | ||
|
||
source.connect(signaleticOsc); | ||
signaleticOsc.connect(context.destination); | ||
|
||
function bindKnobChange(knobEl, param) { | ||
knobEl.addEventListener("input", (event) => { | ||
if (context.state === "suspended") { | ||
context.resume(); | ||
} | ||
|
||
param.value = event.target.value / 100; | ||
}); | ||
} | ||
|
||
bindKnobChange(document.getElementById("blueKnob"), | ||
signaleticOsc.parameters.get("blueKnobParam")); | ||
bindKnobChange(document.getElementById("redKnob"), | ||
signaleticOsc.parameters.get("redKnobParam")); | ||
} | ||
|
||
initAudioGraph(); | ||
|
||
// set resolution to same as device | ||
var oled = document.getElementById("oled"); | ||
oled.width = 64; | ||
oled.height = 32; | ||
</script> | ||
</body> | ||
</html> |
132 changes: 132 additions & 0 deletions
132
hosts/web/examples/oscillator/signaletic-oscillator-worklet.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
import ModuleLoader from "../../../../libstar/build/wasm/libstar.js"; | ||
|
||
let Module = ModuleLoader(); | ||
let star = new Module.Starlings(); | ||
|
||
star.TYPED_VIEWS = { | ||
"int8": "Int8Array", | ||
"uint8": "Uint8Array", | ||
"int16": "Int16Array", | ||
"uint16": "Uint16Array", | ||
"int32": "Int16Array", | ||
"uint32": "Uint16Array", | ||
"float32": "Float32Array" | ||
}; | ||
|
||
star.dereferenceArray = function(ptr, length, type) { | ||
let arrayViewType = star.TYPED_VIEWS[type]; | ||
if (arrayViewType === undefined) { | ||
throw Error("Can't dereference an array of type " + type); | ||
} | ||
|
||
return new globalThis[arrayViewType](Module.HEAP8.buffer, | ||
ptr, length); | ||
}; | ||
|
||
class SignaleticOscillator extends AudioWorkletProcessor { | ||
constructor() { | ||
super(); | ||
|
||
this.allocator = star.Allocator_new(1024 * 256); | ||
this.audioSettings = star.AudioSettings_new(this.allocator); | ||
this.audioSettings.sampleRate = sampleRate; | ||
this.audioSettings.blockSize = 128; | ||
this.audioSettings.numChannels = 2; | ||
|
||
/** Modulators **/ | ||
this.freqMod = star.sig.Value_new(this.allocator, | ||
this.audioSettings); | ||
this.freqMod.parameters.value = 440.0; | ||
this.ampMod = star.sig.Value_new(this.allocator, | ||
this.audioSettings); | ||
this.ampMod.parameters.value = 1.0; | ||
|
||
|
||
/** Carrier **/ | ||
this.carrierInputs = star.sig.Sine_Inputs_new( | ||
this.allocator, | ||
this.freqMod.signal.output, | ||
star.AudioBlock_newWithValue(this.allocator, | ||
this.audioSettings, 0.0), | ||
this.ampMod.signal.output, | ||
star.AudioBlock_newWithValue(this.allocator, | ||
this.audioSettings, 0.0) | ||
); | ||
|
||
this.carrier = star.sig.Sine_new(this.allocator, | ||
this.audioSettings, this.carrierInputs); | ||
|
||
/** Gain **/ | ||
this.gainValue = star.sig.Value_new(this.allocator, | ||
this.audioSettings); | ||
this.gainValue.parameters.value = 0.85; | ||
|
||
this.gainInputs = star.sig.Gain_Inputs_new( | ||
this.allocator, | ||
this.gainValue.signal.output, | ||
this.carrier.signal.output | ||
); | ||
|
||
this.gain = star.sig.Gain_new(this.allocator, | ||
this.audioSettings, this.gainInputs); | ||
|
||
this.gainOutput = star.dereferenceArray( | ||
this.gain.signal.output, | ||
this.audioSettings.blockSize, | ||
"float32"); | ||
} | ||
|
||
static get parameterDescriptors() { | ||
return [ | ||
{ | ||
name: 'blueKnobParam', | ||
defaultValue: 0.0, | ||
minValue: 0.0, | ||
maxValue: 1.0, | ||
automation: 'k-rate' | ||
}, | ||
{ | ||
name: 'redKnobParam', | ||
defaultValue: 0.0, | ||
minValue: 0.0, | ||
maxValue: 1.0, | ||
automation: 'k-rate' | ||
} | ||
] | ||
} | ||
|
||
process (inputs, outputs, parameters) { | ||
// TODO: Signaletic needs value mapping functions | ||
// like libDaisy, or control values should always | ||
// mapped using Signals. | ||
this.gainValue.parameters.value = | ||
parameters.blueKnobParam[0]; | ||
|
||
// TODO: Read inputs at audio rate. | ||
this.ampMod.parameters.value = inputs[0][0][0]; | ||
|
||
// Map to MIDI notes between 0..120 | ||
let freqNote = inputs[0][1][0] * 60.0 + 60.0; | ||
this.freqMod.parameters.value = star.midiToFreq(freqNote); | ||
|
||
for (let output of outputs) { | ||
// Evaluate the Signaletic graph. | ||
this.ampMod.signal.generate(this.ampMod); | ||
this.freqMod.signal.generate(this.freqMod); | ||
this.carrier.signal.generate(this.carrier); | ||
this.gainValue.signal.generate(this.gainValue); | ||
this.gain.signal.generate(this.gain); | ||
|
||
for (let channel of output) { | ||
for (let i = 0; i < channel.length; i++) { | ||
// channel[i] = inputs[0][0][i]; | ||
channel[i] = this.gainOutput[i]; | ||
} | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
} | ||
|
||
registerProcessor('SignaleticOscillator', SignaleticOscillator); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
#bluemchen { | ||
width: 20.32mm; | ||
height: 128.5mm; | ||
background-color: black; | ||
color: white; | ||
position: absolute; | ||
left: 50%; | ||
top: 50%; | ||
-webkit-transform: translate(-50%, -50%); | ||
transform: translate(-50%, -50%); | ||
text-align:center; | ||
align-content: center; | ||
} | ||
|
||
#oled { | ||
width: 11.2mm; | ||
height: 5.6mm; | ||
} | ||
|
||
.jack { | ||
height: 9mm; | ||
width: 9mm; | ||
background-color: silver; | ||
border-radius: 50%; | ||
display: inline-block; | ||
} | ||
|
||
canvas { | ||
background-color: slateblue; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.