Skip to content

Commit 1f71bc9

Browse files
committed
2 parents 23315f2 + b8cb3d2 commit 1f71bc9

2 files changed

Lines changed: 161 additions & 137 deletions

File tree

WebSource/patch.html

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,23 @@
66
<!-- <meta name="viewport" content="width=device-width, initial-scale=1.0"> -->
77
<!-- <link href="css/custom.css" rel="stylesheet"> -->
88
</head>
9-
109
<body>
11-
1210
<div class="center">
1311
<h1>OWL Patch</h1>
12+
<h2>Input select</h2>
13+
<div class="input-select no-input">
14+
<input type="button" onclick="patch.clearInput(); return false;" value="No input"/>
15+
<input type="button" onclick="patch.useMicrophoneInput(); return false;" value="Microphone"/>
16+
<input type="button" onclick="patch.useFileInput(); return false;" value="File"/>
17+
<div class="file-input-controls">
18+
<input type="file" id="file-input-selector" onchange="patch.onFileSelect(this.files)" />
19+
<audio id="file-input-audio" controls></audio>
20+
</div>
21+
</div>
22+
<h2>Diagnostics</h2>
1423
<div>
15-
<p><input type="button" onclick="patch.play(); return false;"/>Play</p>
16-
<p><input type="button" onclick="patch.pause(); return false;"/>Stop</p>
17-
<p><input type="button" onclick="getMessage(); return false;"/>Message</p>
18-
<p><input type="button" onclick="getStatus(); return false;"/>Status</p>
24+
<input type="button" onclick="getMessage(); return false;" value="Message"/>
25+
<input type="button" onclick="getStatus(); return false;" value="Status"/>
1926
</div>
2027
<div id="patchname"></div>
2128
<div id="p1"></div>
@@ -42,22 +49,23 @@ <h1>OWL Patch</h1>
4249
document.getElementById("p2").innerHTML = "<h3>"+patch.getParameterName(1)+"</h3>";
4350
document.getElementById("p3").innerHTML = "<h3>"+patch.getParameterName(2)+"</h3>";
4451
document.getElementById("p4").innerHTML = "<h3>"+patch.getParameterName(3)+"</h3>";
45-
<!-- patch.update("Volume", 0.1); -->
46-
<!-- patch.play(); -->
52+
53+
// patch.update("Volume", 0.1);
54+
// patch.play();
4755
var getMessage = function(){
4856
var msg = patch.getMessage();
49-
if(msg)
50-
console.log("Program message: "+msg);
51-
document.getElementById("message").innerHTML = msg;
57+
if(msg)
58+
console.log("Program message: "+msg);
59+
document.getElementById("message").innerHTML = msg;
5260
};
5361
var getStatus = function(){
54-
document.getElementById("status").innerHTML = patch.getStatus();
62+
document.getElementById("status").innerHTML = patch.getStatus();
5563
};
5664
</script>
5765

5866
<div>
59-
<p id="message"></p>
60-
<p id="status"></p>
67+
<p id="message"></p>
68+
<p id="status"></p>
6169
</div>
6270
</body>
6371

WebSource/webaudio.js

Lines changed: 139 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,15 @@ var owl = owl || {};
88

99
if (!owl.context)
1010
{
11-
owl.context = new AudioContext();
11+
owl.context = new AudioContext();
1212
}
1313

14+
// Cross-browser compatibility for getUserMedia
15+
navigator.getUserMedia = navigator.getUserMedia ||
16+
navigator.webkitGetUserMedia ||
17+
navigator.mozGetUserMedia ||
18+
navigator.msGetUserMedia;
19+
1420
var WEB_setup = Module.cwrap('WEB_setup', 'number', ['number', 'number']);
1521
var WEB_processBlock = Module.cwrap('WEB_processBlock', 'number', ['number', 'number']);
1622
var WEB_setParameter = Module.cwrap('WEB_setParameter', 'number', ['number', 'number']);
@@ -20,142 +26,152 @@ var WEB_getMessage = Module.cwrap('WEB_getMessage', 'string', []);
2026
var WEB_getStatus = Module.cwrap('WEB_getStatus', 'string', []);
2127

2228
owl.dsp = function () {
23-
var that = {};
24-
that.model = {
25-
playing: false
26-
};
27-
that.vectorsize = 2048;
28-
console.log("setup[fs "+owl.context.sampleRate+"][bs "+that.vectorsize+"]");
29-
WEB_setup(owl.context.sampleRate, that.vectorsize);
30-
for (i = 0; i < 5; i++)
31-
console.log("parameter "+i+": "+WEB_getParameterName(i));
32-
33-
// Bind to C++ Member Functions
34-
that.getNumInputs = function () {
35-
return 2; // DSP_getNumInputs(that.ptr);
36-
};
37-
38-
that.getNumOutputs = function () {
39-
return 2; //DSP_getNumOutputs(that.ptr);
40-
};
41-
42-
that.getMessage = function() {
43-
return WEB_getMessage();
44-
}
45-
46-
that.getStatus = function() {
47-
return WEB_getStatus();
48-
}
49-
50-
that.compute = function (e) {
51-
var dspOutChans = HEAP32.subarray(that.outs >> 2, (that.outs + that.numOut * that.ptrsize) >> 2);
52-
var dspInChans = HEAP32.subarray(that.ins >> 2, (that.ins + that.ins * that.ptrsize) >> 2);
53-
var i, j;
54-
for (i = 0; i < that.numIn; i++)
55-
{
56-
var input = e.inputBuffer.getChannelData(i);
57-
var dspInput = HEAPF32.subarray(dspInChans[i] >> 2, (dspInChans[i] + that.vectorsize * that.ptrsize) >> 2);
58-
59-
for (j = 0; j < input.length; j++) {
60-
dspInput[j] = input[j];
61-
}
29+
var that = {};
30+
that.model = {
31+
inputNode: null,
32+
fileNode: owl.context.createMediaElementSource(document.getElementById('file-input-audio')),
33+
micNode: null
34+
};
35+
that.vectorsize = 2048;
36+
console.log("setup[fs "+owl.context.sampleRate+"][bs "+that.vectorsize+"]");
37+
WEB_setup(owl.context.sampleRate, that.vectorsize);
38+
for (i = 0; i < 5; i++)
39+
console.log("parameter "+i+": "+WEB_getParameterName(i));
40+
41+
// Bind to C++ Member Functions
42+
that.getNumInputs = function () {
43+
return 2; // DSP_getNumInputs(that.ptr);
44+
};
45+
46+
that.getNumOutputs = function () {
47+
return 2; //DSP_getNumOutputs(that.ptr);
48+
};
49+
50+
that.getMessage = function() {
51+
return WEB_getMessage();
6252
}
6353

64-
WEB_processBlock(that.ins, that.outs);
65-
66-
for(i = 0; i < that.numOut; i++){
67-
var output = e.outputBuffer.getChannelData(i);
68-
var dspOutput = HEAPF32.subarray(dspOutChans[i] >> 2, (dspOutChans[i] + that.vectorsize * that.ptrsize) >> 2);
69-
for (j = 0; j < output.length; j++) {
70-
output[j] = dspOutput[j];
71-
}
72-
}
73-
return that;
74-
};
75-
76-
// Connect to another node
77-
that.connect = function (node) {
78-
if(node.scriptProcessor){
79-
that.scriptProcessor.connect(node.scriptProcessor);
80-
}else{
81-
that.scriptProcessor.connect(node);
54+
that.getStatus = function() {
55+
return WEB_getStatus();
8256
}
83-
return that;
84-
};
8557

86-
// Bind to Web Audio
87-
that.getParameterName = function(pid){
88-
return WEB_getParameterName(pid);
89-
}
58+
that.compute = function (e) {
59+
var dspOutChans = HEAP32.subarray(that.outs >> 2, (that.outs + that.numOut * that.ptrsize) >> 2);
60+
var dspInChans = HEAP32.subarray(that.ins >> 2, (that.ins + that.ins * that.ptrsize) >> 2);
61+
var i, j;
62+
for (i = 0; i < that.numIn; i++)
63+
{
64+
var input = e.inputBuffer.getChannelData(i);
65+
var dspInput = HEAPF32.subarray(dspInChans[i] >> 2, (dspInChans[i] + that.vectorsize * that.ptrsize) >> 2);
66+
67+
for (j = 0; j < input.length; j++) {
68+
dspInput[j] = input[j];
69+
}
70+
}
71+
72+
WEB_processBlock(that.ins, that.outs);
73+
74+
for(i = 0; i < that.numOut; i++){
75+
var output = e.outputBuffer.getChannelData(i);
76+
var dspOutput = HEAPF32.subarray(dspOutChans[i] >> 2, (dspOutChans[i] + that.vectorsize * that.ptrsize) >> 2);
77+
for (j = 0; j < output.length; j++) {
78+
output[j] = dspOutput[j];
79+
}
80+
}
81+
return that;
82+
};
83+
84+
// Change the input into the OWL patch node
85+
that.connectInput = function (node) {
86+
that.clearInput();
87+
node.connect(that.scriptProcessor);
88+
that.model.inputNode = node;
89+
}
9090

91-
that.getPatchName = function(){
92-
return WEB_getPatchName();
93-
}
91+
that.clearInput = function () {
92+
if (that.model.inputNode) {
93+
that.model.inputNode.disconnect(that.scriptProcessor);
94+
}
95+
that.model.inputNode = null;
96+
}
9497

95-
that.play = function () {
96-
that.scriptProcessor.connect(owl.context.destination);
97-
that.model.playing = true;
98-
return that;
99-
};
98+
that.useMicrophoneInput = function () {
99+
if (that.model.micNode) {
100+
that.connectInput(that.model.micNode);
101+
} else {
102+
navigator.getUserMedia.call(navigator, {audio: true}, function (stream) {
103+
that.model.micNode = owl.context.createMediaStreamSource(stream);
104+
that.connectInput(that.model.micNode);
105+
}, function (err) {
106+
console.error(err);
107+
});
108+
}
109+
}
100110

101-
that.pause = function () {
102-
that.scriptProcessor.disconnect(owl.context.destination);
103-
that.model.playing = false;
104-
return that;
105-
};
111+
that.useFileInput = function () {
112+
that.connectInput(that.model.fileNode);
113+
}
106114

107-
that.toggle = function() {
108-
if (that.model.playing) {
109-
that.pause()
115+
that.onFileSelect = function (files) {
116+
var fileUrl = files[0] ? URL.createObjectURL(files[0]) : '';
117+
var audioElement = document.getElementById('file-input-audio');
118+
audioElement.src = fileUrl;
110119
}
111-
else {
112-
that.play();
120+
121+
// Bind to Web Audio
122+
that.getParameterName = function(pid){
123+
return WEB_getParameterName(pid);
113124
}
114-
return that;
115-
}
116125

117-
that.update = function (key, val) {
118-
WEB_setParameter(key, val);
119-
console.log("set parameter "+key+": "+val);
120-
return that;
121-
};
122-
123-
that.init = function () {
124-
var i;
125-
that.ptrsize = 4; // assuming pointer in emscripten are 32bits
126-
// that.vectorsize = 2048;
127-
that.samplesize = 4;
128-
129-
// Get input / output counts
130-
that.numIn = that.getNumInputs();
131-
that.numOut = that.getNumOutputs();
132-
133-
// Setup web audio context
134-
that.scriptProcessor = owl.context.createScriptProcessor(that.vectorsize, that.numIn, that.numOut);
135-
that.scriptProcessor.onaudioprocess = that.compute;
136-
137-
// TODO the below calls to malloc are not yet being freed, potential memory leak
138-
// allocate memory for input / output arrays
139-
that.ins = Module._malloc(that.ptrsize * that.numIn);
140-
141-
// assign to our array of pointer elements an array of 32bit floats, one for each channel. currently we assume pointers are 32bits
142-
for (i = 0; i < that.numIn; i++) {
143-
// assign memory at that.ins[i] to a new ptr value. maybe there's an easier way, but this is clearer to me than any typedarray magic beyond the presumably TypedArray HEAP32
144-
HEAP32[(that.ins >> 2) + i] = Module._malloc(that.vectorsize * that.samplesize);
126+
that.getPatchName = function(){
127+
return WEB_getPatchName();
145128
}
146129

147-
//ptrsize, change to eight or use Runtime.QUANTUM? or what?
148-
that.outs = Module._malloc(that.ptrsize * that.numOut);
130+
that.update = function (key, val) {
131+
WEB_setParameter(key, val);
132+
console.log("set parameter "+key+": "+val);
133+
return that;
134+
};
149135

150-
// assign to our array of pointer elements an array of 64bit floats, one for each channel. currently we assume pointers are 32bits
151-
for (i = 0; i < that.numOut; i++) {
152-
// assign memory at that.ins[i] to a new ptr value. maybe there's an easier way, but this is clearer to me than any typedarray magic beyond the presumably TypedArray HEAP32
153-
HEAP32[(that.outs >> 2) + i] = Module._malloc(that.vectorsize * that.samplesize);
154-
}
155-
return that;
156-
};
136+
that.init = function () {
137+
var i;
138+
that.ptrsize = 4; // assuming pointer in emscripten are 32bits
139+
// that.vectorsize = 2048;
140+
that.samplesize = 4;
141+
142+
// Get input / output counts
143+
that.numIn = that.getNumInputs();
144+
that.numOut = that.getNumOutputs();
145+
146+
// Create OWL patch web audio node
147+
that.scriptProcessor = owl.context.createScriptProcessor(that.vectorsize, that.numIn, that.numOut);
148+
that.scriptProcessor.onaudioprocess = that.compute;
157149

158-
that.init();
150+
// Connect output of OWL processor to audio out
151+
that.scriptProcessor.connect(owl.context.destination);
159152

160-
return that;
153+
// TODO the below calls to malloc are not yet being freed, potential memory leak
154+
// allocate memory for input / output arrays
155+
that.ins = Module._malloc(that.ptrsize * that.numIn);
156+
157+
// assign to our array of pointer elements an array of 32bit floats, one for each channel. currently we assume pointers are 32bits
158+
for (i = 0; i < that.numIn; i++) {
159+
// assign memory at that.ins[i] to a new ptr value. maybe there's an easier way, but this is clearer to me than any typedarray magic beyond the presumably TypedArray HEAP32
160+
HEAP32[(that.ins >> 2) + i] = Module._malloc(that.vectorsize * that.samplesize);
161+
}
162+
163+
//ptrsize, change to eight or use Runtime.QUANTUM? or what?
164+
that.outs = Module._malloc(that.ptrsize * that.numOut);
165+
166+
// assign to our array of pointer elements an array of 64bit floats, one for each channel. currently we assume pointers are 32bits
167+
for (i = 0; i < that.numOut; i++) {
168+
// assign memory at that.ins[i] to a new ptr value. maybe there's an easier way, but this is clearer to me than any typedarray magic beyond the presumably TypedArray HEAP32
169+
HEAP32[(that.outs >> 2) + i] = Module._malloc(that.vectorsize * that.samplesize);
170+
}
171+
return that;
172+
};
173+
174+
that.init();
175+
176+
return that;
161177
};

0 commit comments

Comments
 (0)