Skip to content

Instantly share code, notes, and snippets.

@uupaa
Created March 3, 2016 11:25
Show Gist options
  • Save uupaa/e92fbd3643391806918f to your computer and use it in GitHub Desktop.
Save uupaa/e92fbd3643391806918f to your computer and use it in GitHub Desktop.
WebAudio.js test
<button onclick="play()">play</button>
<script>
var bufsize = 4096 / 2;
var audioctx = new webkitAudioContext();
var scrproc = audioctx.createScriptProcessor(bufsize, 2);
scrproc.onaudioprocess = processHandler;
scrproc.connect(audioctx.destination);
var osc = null;
var currentTimeArray = [];
var timeStampArray = [];
var lastCurrentTime = 0;
var lastPlayBackTime = 0;
// 44.1kHz = 44100 = 1็ง’ใซ44100ใƒ•ใƒฌใƒผใƒ ใฎใ‚ตใƒณใƒ—ใƒชใƒณใ‚ฐใƒฌใƒผใƒˆ
// = 1ใƒ•ใƒฌใƒผใƒ ่พบใ‚Š 0.00002267573696 ็ง’
// * 4096ใƒ•ใƒฌใƒผใƒ  = 0.09287981858816็ง’
// 4096 = 0.09287981859410431
// 44.1kHz ใง 2048ใƒ•ใƒฌใƒผใƒ ๆฏŽใซใ‚ณใƒผใƒซใƒใƒƒใ‚ฏใ™ใ‚‹ใจ
// ๅ‘ผใณๅ‡บใ—้–“้š”ใฏใ€ 0.04643990929705216
function processHandler(event) {
var currentTime = audioctx.currentTime;
var playbackTime = event.playbackTime;
currentTimeArray.push(currentTime - lastCurrentTime);
timeStampArray.push(playbackTime - lastPlayBackTime);
lastCurrentTime = currentTime;
lastPlayBackTime = playbackTime;
var buf0 = event.outputBuffer.getChannelData(0);
for(var i = 0; i < bufsize; ++i) {
buf0[i] = (Math.random() * 2) - 1;
}
if (currentTimeArray.length > 100) {
scrproc.disconnect();
console.dir(currentTimeArray);
console.dir(timeStampArray);
}
}
function play() {
osc = audioctx.createOscillator();
osc.connect(scrproc);
osc.start(0);
}
play();
</script>
<button onclick="play()">play</button><br />
<button onclick="stop()">stop</button><br />
<input id="a" type="text" value="" /><br />
<input id="b" type="text" value="" /><br />
<input id="c" type="text" value="" /><br />
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
<script>
var bufferSize = 4096 / 2;
var audioContext = new webkitAudioContext();
var scriptProcessor = audioContext.createScriptProcessor(bufferSize, 1, 1);
scriptProcessor.onaudioprocess = processHandler;
scriptProcessor.connect(audioContext.destination);
var oscillator = null;
var currentTimeArray = [];
var timeStampArray = [];
var lastCurrentTime = 0;
var lastPlayBackTime = 0;
var now = performance.now();
/*
var diffTime1 = (now / 1000) - audioContext.currentTime;
*/
var nodeA = document.querySelector("#a");
var nodeB = document.querySelector("#b");
var nodeC = document.querySelector("#c");
/*
## WebAudio ใฎ AudioContext.currentTime ใ‚’็”จใ„ใŸใ‚คใƒ™ใƒณใƒˆใ‚ญใƒฅใƒผ่จญ่จˆใฎใƒใ‚คใƒณใƒˆ
WebAudio ใฎ ScriptProcessorNode ใ‚’ไธŠๆ‰‹ใไฝฟใ†ใจใ€
็ฒพๅบฆใŒ้ซ˜ใๅฎ‰ๅฎšใ—ใŸใ‚ณใƒผใƒซใƒใƒƒใ‚ฏใ‚’ๅฎšๆœŸ็š„ใซ็™บ็”Ÿใ•ใ›ใ‚‹ไบ‹ใŒใงใใพใ™ใ€‚
ใ“ใฎ็‰นๆ€งใ‚’ๅˆฉ็”จใ™ใ‚‹ใจใ€ๅฎ‰ๅฎšใ—ใŸใƒชใƒƒใƒ—ใ‚ทใƒณใ‚ฏ(้Ÿณๅฃฐใจๅ‹•็”ปใฎๅŒๆœŸๅ‡ฆ็†)ใ‚’ๅฎŸ็พใ™ใ‚‹ไบ‹ใŒๅฏ่ƒฝใซใชใ‚Šใพใ™ใ€‚
### ๅฎ‰ๅฎšใ—ใŸใƒชใƒƒใƒ—ใ‚ทใƒณใ‚ฏใ‚’ๅฎŸ็พใ™ใ‚‹ใŸใ‚ใซ
ใƒชใƒƒใƒ—ใ‚ทใƒณใ‚ฏใ‚’ๅฎ‰ๅฎšใ•ใ›ใ‚‹ใซใฏใ€ไปฅไธ‹ใฎๆกไปถใ‚’ๅฏ่ƒฝใช้™ใ‚Šๆบ€ใŸใ™ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚
- ใงใใ‚‹ใ ใ‘็ฒพๅบฆใฎ้ซ˜ใ„ใ‚ฏใƒญใƒƒใ‚ฏใŒๅฟ…่ฆใงใ™
- setTimeout, setInterval ใฎๆœ€ๅฐๅˆ†่งฃ่ƒฝใฏ 4ms ใงใ™(ไป•ๆง˜ไธŠใฎๅ€คใงใ€ๅฎŸ่ฃ…ๆฌก็ฌฌใงใ™)
- requestAnimationFrame ใฎๆœ€ๅฐๅˆ†่งฃ่ƒฝใฏ 16.666ms ใงใ™(iPhone 5, iOS 9 ใงใฏ็ด„33ms ใซใชใ‚Šใพใ™)
- ใƒกใ‚คใƒณใ‚นใƒฌใƒƒใƒ‰ใฎๆทท้›‘็Šถๆณใฎๅฝฑ้Ÿฟใ‚’ๅ—ใ‘ใšใซๅ‹•ไฝœใ™ใ‚‹ไป•็ต„ใฟใŒๅฟ…่ฆใงใ™
- setTimeout ใฏใƒกใ‚คใƒณใ‚นใƒฌใƒƒใƒ‰ใฎๅฝฑ้Ÿฟใ‚’ๅผทใๅ—ใ‘ใพใ™
- requestAnimationFrame ใฏใƒชใƒ•ใƒฌใƒƒใ‚ทใƒฅใƒฌใƒผใƒˆใฎๅฝฑ้Ÿฟใ‚’ๅผทใๅ—ใ‘ใพใ™
- AudioContext#currentTime ใฏๅˆฅใ‚นใƒฌใƒƒใƒ‰ใงๅ‹•ไฝœใ™ใ‚‹ใŸใ‚ใƒกใ‚คใƒณใ‚นใƒฌใƒƒใƒ‰ใฎๅฝฑ้Ÿฟใ‚’ๅ—ใ‘ใพใ›ใ‚“
ๅŸบๆœฌ็š„ใชๆง‹้€ ใฏใ€ไปฅไธ‹ใฎใ‚ˆใ†ใซใชใ‚Šใพใ™ใ€‚
```js
var bufferSize = 2048;
var audioContext = new AudioContext();
var oscillatorNode = null;
var scriptProcessorNode = audioContext.createScriptProcessor(bufferSize, 1, 1);
scriptProcessorNode.onaudioprocess = processHandler;
scriptProcessorNode.connect(audioContext.destination);
function processHandler(event) {
var currentTime = audioContext.currentTime;
var inputBuffer0 = event.inputBuffer.getChannelData(0); // Float32Array
var outputBuffer0 = event.outputBuffer.getChannelData(0); // Float32Array
outputBuffer0.set(inputBuffer0, 0); // inputBuffer ใ‚’ outputBuffe ใซใ‚ณใƒ”ใƒผใ™ใ‚‹
// currentTime ใซๅฟœใ˜ใŸใ‚นใ‚ฑใ‚ธใƒฅใƒผใƒชใƒณใ‚ฐๅ‡ฆ็†ใ‚’ใ“ใ“ใซ่จ˜่ฟฐใ™ใ‚‹
}
function play() {
if (oscillatorNode) { return; }
oscillatorNode = audioContext.createOscillator();
oscillatorNode.type = "sine";
oscillatorNode.frequency.value = 440; // 440Hz
oscillatorNode.connect(scriptProcessorNode);
oscillatorNode.start();
}
```
ใ“ใฎ็‰นๆ€งใ‚’ไฝฟใ†ใจใ€
AudioContext.currentTime
่จญ่จˆใฎๆ‰‹ๆˆปใ‚Šใ‚’้ฟใ‘ใ‚‹ใŸใ‚ใซใ€ไบ‹ๅ‰ใซๆ˜Ž็ขบใซใ™ในใใƒใ‚คใƒณใƒˆใ€‚
- performance.now() ใจ AudioContext.currentTime ใฎใ‚ฏใƒญใƒƒใ‚ฏ็‰นๆ€งใ‚’่ชฟๆŸปใ™ใ‚‹
- ๅ˜ไฝใฏ?
- ็ฒพๅบฆใฏ?
- ๆฌก็ฌฌใซใ‚บใƒฌใŒ็™บ็”Ÿใ™ใ‚‹?
- tab hidden ็Šถๆ…‹ใงใฏใฉใ†ใชใ‚‹?
- ๆ›ดๆ–ฐ้ ปๅบฆใŒ่ฝใกใฆใ‚บใƒฌใ‚‹ไบ‹ใฏใชใ„ใ‹?
- WebAudio ใฎ็‰นๆ€งใ‚’่ชฟๆŸปใ™ใ‚‹
- tab hidden ใงใฉใ†ใชใ‚‹?
- ้Ÿณใฏๅœๆญขใ™ใ‚‹ใใ‚Œใจใ‚‚ๅ†็”Ÿใ—็ถšใ‘ใ‚‹?
่ชฟๆŸป็ตๆžœใงใ™ใ€‚
- ใ‚ฏใƒญใƒƒใ‚ฏ็‰นๆ€ง
- performance.now()
- ๅ˜ไฝใฏ ms (ms.microsec)
- tab hidden ็Šถๆ…‹
- ๅข—ๅŠ ใ™ใ‚‹
- OSใ‚ทใƒฃใƒƒใƒˆใƒ€ใ‚ฆใƒณ
- ๅœๆญขใ—ใ€ใƒชใ‚ธใƒฅใƒผใƒ ใงๅ†้–‹ใ™ใ‚‹
- AudioContext.currentTime
- ๅ˜ไฝใฏ sec (sec.ms)
- tab hidden ็Šถๆ…‹
- Chrome, Safari
- ๅข—ๅŠ ใ™ใ‚‹
- iOS
- ๅœๆญขใ™ใ‚‹
- OSใ‚ทใƒฃใƒƒใƒˆใƒ€ใ‚ฆใƒณ
- ๅœๆญขใ—ใ€ใƒชใ‚ธใƒฅใƒผใƒ ใงๅ†้–‹ใ™ใ‚‹
- ใ‚ตใ‚ฆใƒณใƒ‰็‰นๆ€ง
- tab hidden ็Šถๆ…‹
- Chrome, Safari
- ๅ†็”Ÿใ—็ถšใ‘ใ‚‹
- iOS
- ๅœๆญขใ™ใ‚‹
*/
/*
console.dir({
diffTime1: diffTime1,
"performance.now": now,
"audioContext.currentTime": audioContext.currentTime,
});
*/
// performance.now ใฎๅˆ†่งฃ่ƒฝใฏ ms ๅ˜ไฝ
// performance.now() -> 1000 -> 1็ง’
// ไธ€ๆ–น AudioContext.currentTime ใฎๅˆ†่งฃ่ƒฝใฏใ€็ง’ๅ˜ไฝ
// 44.1kHz = 44100 = 1็ง’ใซ44100ใƒ•ใƒฌใƒผใƒ ใฎใ‚ตใƒณใƒ—ใƒชใƒณใ‚ฐใƒฌใƒผใƒˆ
// = 1ใƒ•ใƒฌใƒผใƒ ่พบใ‚Š 0.00002267573696 ็ง’
// * 4096ใƒ•ใƒฌใƒผใƒ  = 0.09287981858816็ง’
// 4096 = 0.09287981859410431
// 44.1kHz ใง 2048ใƒ•ใƒฌใƒผใƒ ๆฏŽใซใ‚ณใƒผใƒซใƒใƒƒใ‚ฏใ™ใ‚‹ใจ
// ๅ‘ผใณๅ‡บใ—้–“้š”ใฏใ€ 0.04643990929705216
// ่จˆ็ฎ—ไธŠใฏ 44100 ใฎ 2048 ใƒ•ใƒฌใƒผใƒ ใง 0.04643990929408
// iPhone 6s ใฎๅฎŸๆธฌๅ€คใ ใจ 44100 ใฎ 2048 ใƒ•ใƒฌใƒผใƒ ใง 0.04643990929705211 (46ms)
// iPhone 5 ใฎๅฎŸๆธฌๅ€คใ ใจ 44100 ใฎ 2048 ใƒ•ใƒฌใƒผใƒ ใง 0.04643990929705211 (46ms)
// iPhone 5 ใฎๅฎŸๆธฌๅ€คใ ใจ 44100 ใฎ 256 ใƒ•ใƒฌใƒผใƒ ใง 0.005804988662131527 (5ms)
// MBP Chrome 48 ใฎๅฎŸๆธฌๅ€คใ ใจ 44100 ใฎ 2048 ใƒ•ใƒฌใƒผใƒ ใง 0.04643990929705211 (46ms)
// 16384 ใƒ•ใƒฌใƒผใƒ ใ ใจ ๅฎŸๆธฌๅ€คใง 0.3715192743764173 (371ms) ใซใชใ‚‹
function processHandler(event) {
var now = performance.now();
var currentTime = audioContext.currentTime;
var playbackTime = event.playbackTime;
nodeA.value = (now / 1000).toFixed(2);
nodeB.value = (currentTime).toFixed(2);
nodeC.value = (playbackTime).toFixed(2);
/*
currentTimeArray.push(currentTime - lastCurrentTime);
timeStampArray.push(playbackTime - lastPlayBackTime);
lastCurrentTime = currentTime;
lastPlayBackTime = playbackTime;
*/
/*
if (currentTimeArray.length > 100) {
scriptProcessor.disconnect();
console.dir(currentTimeArray);
console.dir(timeStampArray);
var now = performance.now();
var diffTime2 = (now / 1000) - currentTime;
console.dir({
diffTime1: diffTime1,
diffTime2: diffTime2,
"performance.now": now,
"audioContext.currentTime": currentTime,
"event.playbackTime": playbackTime,
});
}
*/
var input0 = event.inputBuffer.getChannelData(0); // Float32Array
var output0 = event.outputBuffer.getChannelData(0); // Float32Array
//for(var i = 0; i < bufferSize; ++i) {
// output0[i] = (Math.random() * 2) - 1;
//}
// for (var i = 0; i < bufferSize; ++i) {
// output0[i] = input0[i];
// }
output0.set(input0, 0);
}
function play() {
if (!oscillator) {
oscillator = audioContext.createOscillator();
oscillator.type = "sine";
oscillator.frequency.value = 440;
oscillator.connect(scriptProcessor);
oscillator.start();
}
}
function stop() {
if (oscillator) {
oscillator.stop();
oscillator = null;
}
}
</script>
<!-- take 3 -->
<button onclick="play()">play</button><br />
<button onclick="stop()">stop</button><br />
<input id="a" type="text" value="" /><br />
<input id="b" type="text" value="" /><br />
<input id="c" type="text" value="" /><br />
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
ใ„ใทใ•ใ‚€<br>
<script>
var bufferSize = 4096 / 2;
var audioContext = new webkitAudioContext();
var scriptProcessor = audioContext.createScriptProcessor(bufferSize, 1, 1);
scriptProcessor.onaudioprocess = processHandler;
scriptProcessor.connect(audioContext.destination);
var oscillator = null;
var currentTimeArray = [];
var timeStampArray = [];
var lastCurrentTime = 0;
var lastPlayBackTime = 0;
var now = performance.now();
/*
var diffTime1 = (now / 1000) - audioContext.currentTime;
*/
var nodeA = document.querySelector("#a");
var nodeB = document.querySelector("#b");
var nodeC = document.querySelector("#c");
function processHandler(event) {
var now = performance.now();
var currentTime = audioContext.currentTime;
var playbackTime = event.playbackTime;
nodeA.value = (now / 1000).toFixed(2);
nodeB.value = (currentTime).toFixed(2);
nodeC.value = (playbackTime).toFixed(2);
/*
currentTimeArray.push(currentTime - lastCurrentTime);
timeStampArray.push(playbackTime - lastPlayBackTime);
lastCurrentTime = currentTime;
lastPlayBackTime = playbackTime;
*/
/*
if (currentTimeArray.length > 100) {
scriptProcessor.disconnect();
console.dir(currentTimeArray);
console.dir(timeStampArray);
var now = performance.now();
var diffTime2 = (now / 1000) - currentTime;
console.dir({
diffTime1: diffTime1,
diffTime2: diffTime2,
"performance.now": now,
"audioContext.currentTime": currentTime,
"event.playbackTime": playbackTime,
});
}
*/
var input0 = event.inputBuffer.getChannelData(0); // Float32Array
var output0 = event.outputBuffer.getChannelData(0); // Float32Array
//for(var i = 0; i < bufferSize; ++i) {
// output0[i] = (Math.random() * 2) - 1;
//}
// for (var i = 0; i < bufferSize; ++i) {
// output0[i] = input0[i];
// }
output0.set(input0, 0);
}
function play() {
if (!oscillator) {
oscillator = audioContext.createOscillator();
oscillator.type = "sine";
oscillator.frequency.value = 440;
oscillator.connect(scriptProcessor);
oscillator.start();
}
}
function stop() {
if (oscillator) {
oscillator.stop();
oscillator = null;
}
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment