forked from autonome/aframe-ar
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsoundsize.js
112 lines (88 loc) · 3.17 KB
/
soundsize.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
function onReady() {
var vid = document.querySelector('#inputVideo');
cameraSource.start({
videoElement: vid,
constraints: {
video: true,
audio: true,
facingMode: "environment"
},
callback: onCameraStream
});
}
document.addEventListener('DOMContentLoaded', onReady);
function onCameraStream(stream) {
// Show object after stream is live.
var htmlStr = '<a-obj-model id="duck" src="#ducky-obj" position="0 1200 -3000" rotation="-210 -120 180" scale="3 3 3" material="color: orange"><a-animation easing="linear" attribute="rotation" dur="10000" to="0 0 360" repeat="indefinite"></a-animation> </a-obj-model>';
//var htmlStr = '<a-box id="duck" position="0 2 0" rotation="50 0 0" material="color: red;"><a-animation easing="linear" attribute="rotation" dur="10000" to="0 0 360" repeat="indefinite"></a-animation></a-box>';
var obj = document.querySelector('#aScene').appendChild(new DOMParser().parseFromString(htmlStr, 'text/html').body.firstChild);
// Wait for A-Frame entity to complete loading before manipulating it.
obj.addEventListener('loaded', onObjectLoaded);
function onObjectLoaded() {
// Save original scale as baseline
var origScale = obj.object3D.scale
// Listen for audio stats, modify model based on input.
var maxDecibel, maxScale, origDecibel = 0;
audioStats(stream, function(data) {
// Get largest decibel value in the sample
var decibel = Math.max.apply(null, data);
// Set starting values
if (!maxDecibel) {
origDecibel = decibel;
maxDecibel = decibel;
maxScale = origScale;
}
// vec3all callback
var cb = function(k, v) {
return rescale(decibel, [origDecibel, maxDecibel], [3, 4.5]);
};
// Apply changes to position
var newScale = vec3all(origScale, cb);
obj.object3D.scale = newScale;
if (decibel > maxDecibel) {
maxDecibel = decibel;
maxScale = newScale;
}
});
}
}
function changeByPercentage(val, percdiff) {
return val + ((percdiff/100) * val);
}
// Apply a function to all properties of a vec3.
function vec3all(vec, fn) {
Object.keys(vec).forEach((k) => {
vec[k] = fn(k, vec[k]);
});
return vec;
}
function audioStats(aStream, cb) {
// Set up forked web audio context, for multiple browsers
// window. is needed otherwise Safari explodes
var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var stream = aStream;
var analyser = audioCtx.createAnalyser();
analyser.minDecibels = -90;
analyser.maxDecibels = -10;
analyser.smoothingTimeConstant = 0.85;
var source = audioCtx.createMediaStreamSource(stream);
source.connect(analyser);
analyser.fftSize = 256;
var bufferLength = analyser.fftSize;
var dataArray = new Uint8Array(bufferLength);
// rAF driver
(function onRAF() {
requestAnimationFrame(onRAF);
analyser.getByteTimeDomainData(dataArray);
cb(dataArray);
})();
}
function rescale(inputY, r1, r2) {
var xMax = r2[1];
var xMin = r2[0];
var yMax = r1[1];
var yMin = r1[0];
var percent = (inputY - yMin) / (yMax - yMin);
var outputX = percent * (xMax - xMin) + xMin;
return Math.round(outputX);
}