|
1 | 1 | mergeInto(LibraryManager.library, {
|
2 |
| - InitWebGLMicrophone: function(targetObjectNamePtr) { |
3 |
| - // Initialize webGLMicrophone |
4 |
| - document.webGLMicrophone = new Object(); |
5 |
| - document.webGLMicrophone.isRecording = 0; |
6 |
| - document.webGLMicrophone.targetObjectName = UTF8ToString(targetObjectNamePtr); |
7 |
| - document.webGLMicrophone.audioContext = new (window.AudioContext || window.webkitAudioContext)(); |
8 |
| - document.webGLMicrophone.source = null; |
9 |
| - document.webGLMicrophone.scriptNode = null; |
| 2 | + InitWebGLMicrophone: function(targetObjectNamePtr) { |
| 3 | + var mic = document.webGLMicrophone = {}; |
| 4 | + mic.isRecording = 0; |
| 5 | + mic.targetObjectName = UTF8ToString(targetObjectNamePtr); |
| 6 | + mic.audioContext = new (window.AudioContext || window.webkitAudioContext)(); |
| 7 | + mic.source = null; |
| 8 | + mic.workletNode = null; |
| 9 | + mic.processorModuleUrl = "StreamingAssets/WebGLMicrophoneProcessor.js"; |
| 10 | + mic._buffer = []; |
| 11 | + mic._bufferSize = 4096; |
10 | 12 |
|
11 |
| - // Observe the state of audio context for microphone and resume if disabled |
12 |
| - setInterval(function() { |
13 |
| - if (document.webGLMicrophone.audioContext.state === "suspended" || document.webGLMicrophone.audioContext.state === "interrupted") { |
14 |
| - console.log("Resuming AudioContext: " + document.webGLMicrophone.audioContext.state); |
15 |
| - document.webGLMicrophone.audioContext.resume(); |
16 |
| - } |
17 |
| - }, 300); |
18 |
| - }, |
| 13 | + setInterval(function() { |
| 14 | + var ac = mic.audioContext; |
| 15 | + if (ac.state === "suspended" || ac.state === "interrupted") { |
| 16 | + console.log("Resuming AudioContext:", ac.state); |
| 17 | + ac.resume(); |
| 18 | + } |
| 19 | + }, 300); |
| 20 | + }, |
| 21 | + |
| 22 | + StartWebGLMicrophone: function() { |
| 23 | + var mic = document.webGLMicrophone; |
| 24 | + mic.isRecording = 1; |
| 25 | + |
| 26 | + if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) { |
| 27 | + console.error("getUserMedia not supported"); |
| 28 | + mic.isRecording = 0; |
| 29 | + return; |
| 30 | + } |
19 | 31 |
|
20 |
| - StartWebGLMicrophone: function() { |
21 |
| - document.webGLMicrophone.isRecording = 1; |
| 32 | + navigator.mediaDevices.getUserMedia({ |
| 33 | + audio: { echoCancellation: true, noiseSuppression: true, channelCount: 1 } |
| 34 | + }) |
| 35 | + .then(function(stream) { |
| 36 | + var ac = mic.audioContext; |
| 37 | + ac.audioWorklet.addModule(mic.processorModuleUrl) |
| 38 | + .then(function() { |
| 39 | + mic.source = ac.createMediaStreamSource(stream); |
| 40 | + mic.workletNode = new AudioWorkletNode(ac, "webgl-microphone-processor"); |
22 | 41 |
|
23 |
| - if (navigator.mediaDevices.getUserMedia) { |
24 |
| - navigator.mediaDevices.getUserMedia({ audio: { echoCancellation: true, noiseSuppression: true, channelCount: 1} }) |
25 |
| - .then(function(stream) { |
26 |
| - // Setup nodes |
27 |
| - var audioContext = document.webGLMicrophone.audioContext; |
28 |
| - var source = audioContext.createMediaStreamSource(stream); |
29 |
| - var scriptNode = audioContext.createScriptProcessor(4096, 1, 1); |
30 |
| - scriptNode.onaudioprocess = function (event) { |
31 |
| - SendMessage(document.webGLMicrophone.targetObjectName, "SetSamplingData", event.inputBuffer.getChannelData(0).join(',')); |
32 |
| - }; |
33 |
| - // Connect nodes; |
34 |
| - source.connect(scriptNode); |
35 |
| - scriptNode.connect(audioContext.destination); |
| 42 | + mic.workletNode.port.onmessage = function(event) { |
| 43 | + var float32Array = event.data; |
| 44 | + for (var i = 0; i < float32Array.length; i++) { |
| 45 | + mic._buffer.push(float32Array[i]); |
| 46 | + } |
| 47 | + if (mic._buffer.length >= mic._bufferSize) { |
| 48 | + var chunk = mic._buffer.slice(0, mic._bufferSize); |
| 49 | + mic._buffer = mic._buffer.slice(mic._bufferSize); |
| 50 | + var csv = Array.prototype.join.call(chunk, ","); |
| 51 | + SendMessage(mic.targetObjectName, "SetSamplingData", csv); |
| 52 | + } |
| 53 | + }; |
36 | 54 |
|
37 |
| - document.webGLMicrophone.scriptNode = scriptNode; |
38 |
| - document.webGLMicrophone.source = source; |
| 55 | + mic.source.connect(mic.workletNode); |
| 56 | + mic.workletNode.connect(ac.destination); |
39 | 57 |
|
40 |
| - console.log("WebGLMicrophone started recording"); |
41 |
| - }) |
42 |
| - .catch(function(err) { |
43 |
| - console.log("Failed in GetUserMedia: " + error); |
44 |
| - document.webGLMicrophone.isRecording = 0; |
45 |
| - }); |
46 |
| - } |
47 |
| - }, |
| 58 | + console.log("WebGLMicrophone started recording"); |
| 59 | + }) |
| 60 | + .catch(function(err) { |
| 61 | + console.error("Failed to load AudioWorklet module:", err); |
| 62 | + mic.isRecording = 0; |
| 63 | + }); |
| 64 | + }) |
| 65 | + .catch(function(err) { |
| 66 | + console.error("Failed in getUserMedia:", err); |
| 67 | + mic.isRecording = 0; |
| 68 | + }); |
| 69 | + }, |
48 | 70 |
|
49 |
| - EndWebGLMicrophone: function() { |
50 |
| - console.log("EndWebGLMicrophone"); |
51 |
| - if (document.webGLMicrophone.source != null) { |
52 |
| - document.webGLMicrophone.source.disconnect(document.webGLMicrophone.scriptNode); |
53 |
| - document.webGLMicrophone.source = null; |
54 |
| - } |
55 |
| - if (document.webGLMicrophone.scriptNode != null) { |
56 |
| - document.webGLMicrophone.scriptNode.disconnect(); |
57 |
| - document.webGLMicrophone.scriptNode = null; |
58 |
| - } |
59 |
| - document.webGLMicrophone.isRecording = 0; |
60 |
| - }, |
| 71 | + EndWebGLMicrophone: function() { |
| 72 | + var mic = document.webGLMicrophone; |
| 73 | + console.log("EndWebGLMicrophone"); |
| 74 | + if (mic.source && mic.workletNode) { |
| 75 | + mic.source.disconnect(mic.workletNode); |
| 76 | + mic.workletNode.disconnect(); |
| 77 | + } |
| 78 | + mic.source = null; |
| 79 | + mic.workletNode = null; |
| 80 | + mic._buffer = []; |
| 81 | + mic.isRecording = 0; |
| 82 | + }, |
61 | 83 |
|
62 |
| - IsWebGLMicrophoneRecording: function() { |
63 |
| - return document.webGLMicrophone.isRecording == 1; |
64 |
| - }, |
| 84 | + IsWebGLMicrophoneRecording: function() { |
| 85 | + return document.webGLMicrophone && |
| 86 | + document.webGLMicrophone.isRecording === 1; |
| 87 | + }, |
65 | 88 | });
|
0 commit comments