Web Audio API ììí기를 íë² ë´ ë´ ìë¤. ì°ë¦¬ë ëª ê°ì§ ê°ë ë¤ì ê°ëµíê² ì´í´ë³´ê³ , ê·¸ ë¤ìì ì¤ëì¤ í¸ëì ë¡ë, ì¬ì, ì ì§íê³ ë³¼ë¥¨ ë° ì¤í ë ì¤ í¨ëì ë³ê²½í ì ìë ê°ë¨í ì¹´ì¸í¸ íë ì´ì´ ìì 를 ê³µë¶í ê²ì ëë¤.
<canvas>
ê° <img>
ììì ëëí 공존íë ê²ì²ë¼, Web Audio APIë <audio>
미ëì´ ìì를 ëì²´í기보ë¤ë ë³´ìí©ëë¤. ì¬ì©íë ê²½ì°ì ë°ë¼ ì¤ëì¤ë¥¼ 구íí기 ìí´ ë¬´ì¨ ë구를 ì¬ì©í´ì¼ í ì§ê° ê²°ì ë ê²ì
ëë¤. ë¨ìí ì¤ëì¤ í¸ëì ì¬ìì ì ì´íë ¤ë ê²½ì° <audio>
미ëì´ ììë Web Audio APIë³´ë¤ ë ë¹ ë¥´ê³ ëì í´ê²°ì±
ì ì ê³µí©ëë¤. ëì± ë³µì¡í ì¤ëì¤ íë¡ì¸ì±ì ìíí기를 ìíë¤ë©´, Web Audio APIê° ëì± ê°í 기ë¥ê³¼ ì ì´ë¥¼ ì ê³µí©ëë¤.
Web Audio APIì ê°ë ¥í 기ë¥ì ì´ê²ì´ ì격í "ì¬ì´ë í¸ì¶ ì í(sound call limitation)"ì ê°ì§ê³ ìì§ ìë¤ë ê²ì ëë¤. ì를 ë¤ì´, í ë²ì 32 ëë 64ê°ì ì¬ì´ë í¸ì¶ ì íì´ ììµëë¤. ì¼ë¶ íë¡ì¸ìë ë²ë² 거림 ìì´ 1,000ê° ì´ìì ì¬ì´ë를 ëìì ì¬ìí ì ìì ì§ë ëª¨ë¦ ëë¤.
ìì ì½ëì°ë¦¬ì ì¹´ì¸í¸ íë ì´ì´ë ë¤ìê³¼ ê°ì´ ìê²¼ìµëë¤:
íë ì´ ì¬ì ë²í¼ê³¼, ìëê³¼ ì¤í ë ì¤ í¨ëì ì¡°ì í ì ìë 볼륨 ê·¸ë¦¬ê³ í¨ë ì¬ë¼ì´ëê° ìë ë³µê³ íì ì¹´ì¸í¸ ë±ì ì£¼ëª©í´ ì£¼ì¸ì. ì°ë¦¬ë ì´ ë¼ëì¤ë¥¼ ëì± ë³µì¡íê² ë§ë¤ ìë ìì§ë§, ì´ ë¨ê³ììì ê°ë¨í íìµì ìí´ìë ì´ê²ì ì´ìì ì ëë¤.
Codepenìì ìµì¢ ë°ëª¨ë¥¼ íì¸íê±°ë, GitHubìì ìì¤ ì½ë를 íì¸íì¤ ì ììµëë¤.
ë¸ë¼ì°ì ì§ìíëì ë¸ë¼ì°ì ë¤ì Web Audio APIì ëë¶ë¶ì 기ë¥ë¤ì ëí´ ì¢ì ì§ìì ê°ì§ê³ ììµëë¤. ì´ APIìë ë§ì 기ë¥ë¤ì´ ìì¼ë¯ë¡, ëì± ì íí ì 보를 ìí´ìë ê° ì°¸ì¡° íì´ì§ íë¨ì ë¸ë¼ì°ì í¸íì± ëª©ë¡ì íì¸í´ì¼ í ê²ì ëë¤.
ì¤ëì¤ ê·¸ëíWeb Audio API ë´ë¶ì 모ë ê²ì ì¤ëì¤ ê·¸ëíì ê°ë ì 근거íê³ ìëë°, ì´ë ë ¸ëë¡ êµ¬ì±ëì´ ììµëë¤.
Web Audio APIë ì¤ëì¤ ì»¨í ì¤í¸ë´ìì ì¤ëì¤ ìì ì ë¤ë£¨ê³ , 모ëë¬ ë¼ì°í (modular routing)ì íì©íëë¡ ì¤ê³ëììµëë¤. 기본ì ì¸ ì¤ëì¤ ìì ì ì¤ëì¤ ë ¸ëì í¨ê» ìíëëë°, ì´ë ì¤ëì¤ ë¼ì°í ê·¸ëí를 íì±í기 ìí´ í¨ê» ì°ê²°ëì´ ììµëë¤. ì¬ë¬ë¶ì ì¡°ìí ì¬ì´ë ìì¤ì¸ ì ë ¥ ë ¸ë, ì¬ì´ë를 ìíë ëë¡ ë³ê²½íë ìì ë ¸ë, ì¬ì´ë를 ì ì¥íê±°ë ë£ê² íì©íë ì¶ë ¥ ë ¸ë(ëì°©ì§)를 ê°ì§ê³ ììµëë¤.
ë¤ë¥¸ ì±ë ë ì´ììì ê°ì§ ëªëª ì¤ëì¤ ìì¤ë¤ì ì¬ì§ì´ ë¨ì¼ 컨í ì¤í¸ ë´ììë ì§ìë©ëë¤. ì´ ëª¨ëë¬ ëìì¸ ë문ì, ì¬ë¬ë¶ì ìëì ì¸ í¨ê³¼ë¥¼ ê°ì§ ë³µì¡í ì¤ëì¤ ê¸°ë¥ì ìì±í ì ììµëë¤.
ì¤ëì¤ ì»¨í ì¤í¸Web Audio APIë¡ ë¬´ìì¸ê°ë¥¼ í기 ìí´ìë ì¤ëì¤ ì»¨í ì¤í¸ì ì¸ì¤í´ì¤ë¥¼ ìì±í íìê° ììµëë¤. ì´ë ì°ë¦¬ìê² APIì 모ë 기ë¥ì ì ê·¼í ì ìê² í©ëë¤.
// ë ê±°ì ë¸ë¼ì°ì 를 ìí´
const AudioContext = window.AudioContext || window.webkitAudioContext;
const audioContext = new AudioContext();
ì°ë¦¬ê° ì´ê²ì í ë ë¬´ì¨ ì¼ì´ ë²ì´ì§ê¹ì? BaseAudioContext
ê° ìëì ì¼ë¡ ìì±ëê³ ì¨ë¼ì¸ ì¤ëì¤ ì»¨í
ì¤í¸ë¡ íì¥ë©ëë¤. ì°ë¦¬ë ë¼ì´ë¸ ì¬ì´ë를 ì¬ìí기 ë문ì ì´ê²ì ìí ê²ì
ëë¤.
ì°¸ê³ : ì를 ë¤ì´, ë§ì½ ì¬ë¬ë¶ì´ ë¨ì§ ì¤ëì¤ ë°ì´í°ë¥¼ ì²ë¦¬íê³ , ê·¸ê²ì ë²í¼ë§íê³ ì¤í¸ë¦¬ë° íì§ë§ ì¬ìí기를 ìíì§ ìëë¤ë©´, ì¬ë¬ë¶ì OfflineAudioContext
를 ë§ëë ë°©ë²ì ì´í´ë³¼ ì ììµëë¤.
ì´ì , ìì±ë ì¤ëì¤ ì»¨í
ì¤í¸ë ì¬ìí ì¬ì´ëê° íìí©ëë¤. API를 ì¬ì©í´ ì¬ì´ë를 ì¬ìíë ëª ê°ì§ ë°©ë²ì´ ììµëë¤. ê°ë¨í ë°©ë²ì¼ë¡ ììí´ ë´
ìë¤ â ì°ë¦¬ë ì¹´ì¸í¸ íë ì´ì´ë¥¼ ê°ì§ê³ ìì¼ë¯ë¡, ë
¸ëì ì ì²´ í¸ëì ì¬ìí기를 ìí ê²ì
ëë¤. ëí, ì ê·¼ì±ì ìí´ì, í¸ëì DOMì ë
¸ì¶ìí¤ë ê²ì ì¢ìµëë¤. ì°ë¦¬ë <audio>
ìì를 ì¬ì©íì¬ íì´ì§ì ë
¸ë를 ë
¸ì¶ìí¬ ê²ì
ëë¤.
<audio src="myCoolTrack.mp3"></audio>
ì°¸ê³ : ë§ì½ ë¡ë©í ì¬ì´ë íì¼ì´ ë¤ë¥¸ ëë©ì¸ì ìë¤ë©´ crossorigin
í¹ì±ì ì¬ì©í íìê° ììµëë¤; ë ë§ì ì 보를 ë³´ìë ¤ë©´ Cross Origin Resource Sharing (CORS)를 ì°¸ê³ í´ ë³´ì¸ì.
Web Audio APIë¡ ì»ì ì ìë 모ë ê²ì ì¬ì©íë ¤ë©´ ì´ ìììì ìì¤ë¥¼ ê°ì ¸ì ì°ë¦¬ê° ë§ë 컨í
ì¤í¸ì ì°ê²°í´ì¼ í©ëë¤. ì´ ì¢ê²ë ì´ê±¸ í ì ìë ë©ìëê° ììµëë¤ â AudioContext.createMediaElementSource
ì
ëë¤:
// ì¤ëì¤ ìì를 ì»ìµëë¤
const audioElement = document.querySelector("audio");
// ì¤ëì¤ ìì를 ì¤ëì¤ ì»¨í
ì¤í¸ì ì ë¬í©ëë¤
const track = audioContext.createMediaElementSource(audioElement);
ì°¸ê³ :
ìì <audio>
ììë HTMLMediaElement
ì íì ê°ì²´ì ìí´ DOMì ííëëë°, ì´ë ê³ ì í 기ë¥ì ê°ì§ê³ ììµëë¤.
ì´ê²ì 모ë ê²ì ê·¸ëë¡ ë¨ì ììµëë¤. Web Audio APIìì ì¬ì´ë를 ì¬ì©í ì ìëë¡ íì©í ë¿ì ëë¤.
ì¬ì´ë ì ì´í기ì¹ìì ì¬ì´ëê° ì¬ìë ë, ì¬ì©ìê° ì¬ì´ë를 ì ì´í ì ìê² íì©íë ê²ì ì¤ìí©ëë¤. ì¬ì©íë ê²½ì°ì ë°ë¼, 무ìí ìµì ì´ ìì§ë§, ì°ë¦¬ë ì¬ì´ë를 ì¬ì/ì ì§íê³ , í¸ëì 볼륨ì ë³ê²½íê³ , ê·¸ë¦¬ê³ ì¢ìì ì°ë¡ ì´ëíë 기ë¥ì ì ê³µí ê²ì ëë¤.
JavaScript ì½ëìì íë¡ê·¸ëë°ì ì¼ë¡ ì¬ì´ë를 ì ì´íë ê²ì ë¸ë¼ì°ì ì ìë ì¬ì ì§ì ì ì± ì ìí´ ë¤ë¤ì§ëë°, ê·¸ë¬í ê²ì íê°ê° ì¬ì©ì (ëë íì´í¸ë¦¬ì¤í¸)ì ìí´ ì¹ì¸ëì§ ìì ì±ë¡ ì°¨ë¨ë ê°ë¥ì±ì´ ììµëë¤. ìë ì¬ì ì ì± ì ë³´íµ ì¤í¬ë¦½í¸ê° ì¤ëì¤ë¥¼ ì¬ìíê² í ì ìê² í기 ì ì íì´ì§ìì ëª ìì ì¸ íê°ë ì¬ì©ìì íë½ ì¤ íë를 ì구í©ëë¤.
ì´ í¹ë³í ì구ë íìì ì¼ë¡ ê°ë ì¤ì¸ë° ê·¸ ì´ì ë ìê¸°ì¹ ìì ì¬ì´ëë ì§ì¦ëê³ ê±°ì¬ë¦´ ì ìê³ , ì ê·¼ì± ë¬¸ì 를 ì ë°í ì ì기 ë문ì ëë¤. 미ëì´ì Web Audio APIì ëí ìë ì¬ì ê°ì´ë 문ììì ì´ê²ì ëí´ ë ë°°ì¸ ì ììµëë¤.
ì°ë¦¬ì ì¤í¬ë¦½í¸ë ì¬ì©ìì ì ë ¥ ì´ë²¤í¸ (ì를 ë¤ìë©´ ì¬ì ë²í¼ì í´ë¦)ì ìëµíì¬ ì¤ëì¤ë¥¼ ì¬ìíë¯ë¡, ì°ë¦¬ë ì´ìì´ ìê³ ìë ì¬ì ë°©ì§ë¡ë¶í° 문ì ê° ìì´ì¼ë§ í©ëë¤. ê·¸ë¬ë¯ë¡, ì°ë¦¬ì ì¬ìê³¼ ì ì§ ê¸°ë¥ì ì´í´ë´ì¼ë¡ì¨ ììí´ ë´ ìë¤. ì°ë¦¬ë í¸ëì´ ì¬ìì¤ì¼ ë ì ì§ ë²í¼ì¼ë¡ ë°ëë ì¬ì ë²í¼ì ê°ì§ê³ ììµëë¤:
<button data-playing="false" role="switch" aria-checked="false">
<span>Play/Pause</span>
</button>
í¸ëì ì¬ìí기 ì ì ì°ë¦¬ë ì¤ëì¤ ìì¤/ì ë ¥ ë ¸ëìì 목ì ì§ë¡ ì¤ëì¤ ê·¸ëí를 ì°ê²°í íìê° ììµëë¤.
ì°ë¦¬ë ì´ë¯¸ ì¤ëì¤ ìì를 APIì ì ë¬í¨ì¼ë¡ì¨ ì
ë ¥ ë
¸ë를 ìì±íìµëë¤. ëê° ì¬ë¬ë¶ì ì¶ë ¥ ë
¸ë를 ìì±í íìê° ììµëë¤, ì¬ë¬ë¶ì ë¨ì§ ë¤ë¥¸ ë
¸ë를, ì¬ë¬ë¶ì ìí´ ìí©ì ë¤ë£¨ë BaseAudioContext.destination
ì ì°ê²°í ì ììµëë¤.
track.connect(audioContext.destination);
ì´ ë ¸ëë¤ì ìê°ííë ì¢ì ë°©ë²ì ì¤ëì¤ ê·¸ëí를 그리ë ê²ì ëë¤. ì´ê²ì´ íì¬ ì°ë¦¬ì ì¤ëì¤ ê·¸ëíì ëë¤:
ì´ì ì°ë¦¬ë ì¬ìê³¼ ì ì§ ê¸°ë¥ì ì¶ê°í ì ììµëë¤.
// ì¬ì ë²í¼ì ì íí©ëë¤
const playButton = document.querySelector("button");
playButton.addEventListener(
"click",
function () {
// 컨í
ì¤í¸ê° ì°ê¸°ë(suspended) ìíì ìëì§ ê²ì¬í©ëë¤ (ìë ì¬ì ì ì±
)
if (audioContext.state === "suspended") {
audioContext.resume();
}
// ìíì ë°ë¼ í¸ëì ì¬ìíê±°ë ì ì§í©ëë¤
if (this.dataset.playing === "false") {
audioElement.play();
this.dataset.playing = "true";
} else if (this.dataset.playing === "true") {
audioElement.pause();
this.dataset.playing = "false";
}
},
false,
);
ì°ë¦¬ë ëí í¸ëì´ ì¬ìì ë§ì³¤ì ë 무ìì í ì§ë¥¼ ê³ ë ¤í íìê° ììµëë¤. HTMLMediaElement
ë ì¬ìì´ ìë£ëìì ë ended
ì´ë²¤í¸ë¥¼ í ë² ë°ììí¤ë¯ë¡, ì°ë¦¬ë ê·¸ì ë§ì¶° ì½ë를 ì¤íìí¬ ì ììµëë¤.
audioElement.addEventListener(
"ended",
() => {
playButton.dataset.playing = "false";
},
false,
);
ì¬ì´ë ìì í기
ì°ë¦¬ê° ê°ì§ê³ ìë ì¬ì´ë를 ë³ê²½í기 ìí´, ëªëª 기본ì ì¸ ìì ë
¸ëì ëí´ ê³µë¶í´ ë´
ìë¤. ì¬ê¸°ê° Web Audio APIê° ì ë§ ì¸ëª¨ìì´ì§ê¸° ììíë ê³³ì
ëë¤. ì°ì , 볼륨ì ë³ê²½í´ ë´
ìë¤. ì´ê²ì GainNode
를 ì¬ì©íì¬ êµ¬íë ì ìëë°, ì´ë ìíê° ì¼ë§ë í°ì§ë¥¼ ííí©ëë¤.
Web Audio APIë¡ ë
¸ë를 ìì±íë ë ê°ì§ ë°©ë²ì´ ììµëë¤. 컨í
ì¤í¸ ê·¸ ìì²´ì ìë í©í 리 ë©ìë를 ì¬ì©íê±°ë (ì: audioContext.createGain()
) ë
¸ëì ìì±ì(constructor)를 ì¬ì©í ì ììµëë¤ (ì: new GainNode()
). ì°ë¦¬ë í©í 리 ë©ìë를 ì¬ì©í ê²ì
ëë¤.
const gainNode = audioContext.createGain();
ì´ì ì°ë¦¬ë ì ë ¥ì´ gainì ì°ê²°ëê³ , ê·¸ë¦¬ê³ gain ë ¸ëê° ëª©ì ì§ì ì°ê²°ëëë¡ ì´ì ì¼ë¡ë¶í° ì°ë¦¬ì ì¤ëì¤ ê·¸ëí를 ì ë°ì´í¸í´ì¼ í©ëë¤:
track.connect(gainNode).connect(audioContext.destination);
ì´ë ì°ë¦¬ì ì¤ëì¤ ê·¸ëí를 ë¤ìê³¼ ê°ì´ ë³´ì´ê² ë§ë¤ ê²ì ëë¤:
gainì 기본ê°ì 1ì ëë¤; ì´ê²ì íì¬ ë³¼ë¥¨ì ê°ê² ì ì§í ê²ì ëë¤. gainì ì½ -3.4ì ìµìê°ê³¼ ì½ 3.4ì ìµëê°ì¼ë¡ ì¤ì ë ì ììµëë¤. ì¬ê¸°ì ì°ë¦¬ë ì¹´ì¸í¸ íë ì´ì´ê° gainì 2ê¹ì§ (기존 볼륨ì 2ë°°) ê·¸ë¦¬ê³ 0ê¹ì§ (ì´ê²ì í¨ê³¼ì ì¼ë¡ ì¬ì´ë를 무ìì¼ë¡ ë§ë¤ ê²ì ëë¤) ìì§ì¼ ì ìê² íì©í ê²ì ëë¤.
ì¬ì©ììê² ì´ê²ì í기 ìí ì ì´ ë°©ë²ì ì ê³µí©ìë¤ â ì°ë¦¬ë ë²ì ì ë ¥ì ì¬ì©í ê²ì ëë¤:
<input type="range" id="volume" min="0" max="2" value="1" step="0.01" />
ì°¸ê³ : ë²ì ì ë ¥ì ì¤ëì¤ ë ¸ëì ê°ì ê°±ì íë ë° ìì´ ì ë§ë¡ ì ì©í ì ë ¥ ì íì ëë¤. ì¬ë¬ë¶ì ë²ìì ê°ì ëª ìí ì ìê³ ì¤ëì¤ ë ¸ëì íë¼ë¯¸í°ì í¨ê» ì´ê²ì ë°ë¡ ì¬ì©í ì ììµëë¤.
ê·¸ë¬ë¯ë¡ ì´ ì ë ¥ê°ì ì·¨íê³ ì ë ¥ ë ¸ëê° ì ì ì ìí´ ë°ë ê°ì ê°ì§ê³ ìì ë gain ê°ì ì ë°ì´í¸í´ ë´ ìë¤:
const volumeControl = document.querySelector("#volume");
volumeControl.addEventListener(
"input",
function () {
gainNode.gain.value = this.value;
},
false,
);
ì°¸ê³ : ë
¸ë ê°ì²´ì ê° (ì: GainNode.gain
)ì ë¨ìí ê°ì´ ìëëë¤. ì´ ê°ì ì¤ì ë¡ë AudioParam
ì íì ê°ì²´ì
ëë¤ â ì´ê²ì íë¼ë¯¸í°ë¼ê³ ë¶ë¦½ëë¤. ì´ê²ì´ ë°ë¡ gain
ì ì§ì ê°ì ì¤ì í기보ë¤, GainNode.gain
ì value
ìì±ì ì¤ì í´ì¼ íë ì´ì ì
ëë¤. ì´ë ê² í¨ì ì´ ê°ì²´ê° ì¢ ë ì ì°í´ ì§ ì ìê² íëë°, ì를 ë¤ìë©´ íë¼ë¯¸í°ì 주ì´ì§ ìê° ì¬ì´ìì ë³íìí¬ ê°ë¤ì ì§í©ì ì ë¬íë ê²ì ê³ ë ¤í´ ë³¼ ì ìê² ìµëë¤.
ì¢ìµëë¤, ì´ì ì¬ì©ìë í¸ëì 볼륨ì ì ë°ì´í¸í ì ììµëë¤! gain ë ¸ëë ë§ì½ ì¬ë¬ë¶ì´ 무ì 기ë¥ì ì¶ê°í기를 ìíë¤ë©´ ì¬ì©í기ì ìë²½í ë ¸ëì ëë¤.
ì¤í ë ì¤ í¨ëì ì¶ê°í기ì°ë¦¬ê° ë°©ê¸ ë°°ì´ ê²ì ì°ìµí기 ìí´ ë ë¤ë¥¸ ìì ë ¸ë를 ì¶ê°í´ ë´ ìë¤.
StereoPannerNode
ë
¸ëê° ìëë°, ì´ë ë§ì½ ì¬ì©ìê° ì¤í
ë ì¤ë¥¼ ì¬ì©í ì ìë¤ë©´, ì¢ì¸¡ê³¼ ì°ì¸¡ ì¤í¼ì»¤ ì¬ì´ì ì리ì ê· íì ë³íìíµëë¤.
ì°¸ê³ :
StereoPannerNode
ë ì¬ë¬ë¶ì´ ë¨ì§ ì¢ìì ì°ë¡ ì¤í
ë ì¤ í¨ëì ìíë ë¨ìí ìí©ì ìí ê²ì
ëë¤. PannerNode
ë ìëë°, ì´ë ëì± ë³µì¡í í¨ê³¼ë¥¼ ìì±í기 ìí´, 3D ê³µê°, ì¦ ì¬ì´ë ê³µê°í ì ì´ì íë¥í ë°©ë²ì ê³ ë ¤í©ëë¤. ì를 ë¤ìë©´ ì´ê²ì 머리 ì를 ëë ìë ì¬ì©ìì ë¤ë¡ë¶í° ì¤ë ì리를 ìì±í기 ìí´ ê²ìê³¼ 3D ì±ìì ì¬ì©ë©ëë¤.
ì´ê²ì ìê°íí기 ìí´ì, ì°ë¦¬ë ì°ë¦¬ì ì¤ëì¤ ê·¸ëí를 ë¤ìê³¼ ê°ì´ ë³´ì´ê² ë§ë¤ ê²ì ëë¤.
ì´ë²ì ë ¸ë ìì±ì ìì±ì ë©ìë를 ì¬ì©í´ ë´ ìë¤. ì´ ë°©ë²ì¼ë¡ í ëìë, ì´ í¹ì í ë ¸ëê° ì·¨í ì§ë 모르ë ì´ë í ìµì ë¤ê³¼ 컨í ì¤í¸ë¥¼ ì ë¬í´ì¼ë§ í©ëë¤.
const pannerOptions = { pan: 0 };
const panner = new StereoPannerNode(audioContext, pannerOptions);
ì°¸ê³ :
ë ¸ë ìì±ì ìì±ì ë©ìëë ì´ ìì ìì 모ë ë¸ë¼ì°ì ìì ì§ìëì§ ììµëë¤. ì¤ëë í©í 리 ë©ìëë ëì± ë리 ì§ìë©ëë¤.
ì¬ê¸°ì ì°ë¦¬ì ê°ì ë²ìê° -1 (ê·¹ì¢)ìì 1 (ê·¹ì°)ê¹ì§ì ëë¤. ì´ íë¼ë¯¸í°ë¥¼ ë¬ë¼ì§ê² í기 ìí´ ë¤ì ë²ì ì í ì ë ¥ì ì¬ì©í©ìë¤:
<input type="range" id="panner" min="-1" max="1" value="0" step="0.01" />
í¨ëì ê°ì ì¡°ì í기 ìí´ ì ì íë ê²ê³¼ ê°ì ë°©ë²ì¼ë¡ ì°ë¦¬ë ì´ ì ë ¥ì¼ë¡ë¶í°ì ê°ì ì¬ì©í©ëë¤:
const pannerControl = document.querySelector("#panner");
pannerControl.addEventListener(
"input",
function () {
panner.pan.value = this.value;
},
false,
);
모ë ë ¸ë를 ê°ì´ ì°ê²°í기 ìí´, ì°ë¦¬ì ì¤ëì¤ ê·¸ëí를 ë¤ì ì¡°ì í´ ë´ ìë¤:
track.connect(gainNode).connect(panner).connect(audioContext.destination);
ì ì¼íê² ë¨ì ê²ì í ì¤í¸í´ë³´ë ê²ì ëë¤. Codepenìì ìµì¢ ë°ëª¨ë¥¼ íì¸í´ ë³´ì¸ì.
ìì½íë¥í©ëë¤! ì°ë¦¬ë ì°ë¦¬ì 'í ì´í'를 ì¬ìíë ì¹´ì¸í¸ íë ì´ì´ë¥¼ ê°ì§ê³ ìê³ , 볼륨과 ì¤í ë ì¤ í¨ëì ì¡°ì í ì ìëë°, ì´ë ì°ë¦¬ìê² ìëíë ìë¹í 기본ì ì¸ ì¤ëì¤ ê·¸ëí를 ì ê³µí©ëë¤.
ì´ê²ì ì¬ë¬ë¶ì ì¹ì¬ì´í¸ë ì¹ ì±ì ì¤ëì¤ë¥¼ ì¶ê°í기 ìí´ íìí ìë¹ìì 기본ì 구ì±í©ëë¤. Web Audio APIìë ë ë§ì 기ë¥ì´ ìì§ë§, ì¬ë¬ë¶ì´ í ë² ë ¸ëì ê°ë ì ì¡ê³ ì¤ëì¤ ê·¸ëí를 í¨ê» í©íë©´, ì°ë¦¬ë ëì± ë³µì¡í 기ë¥ì ë³´ë ê²ì¼ë¡ ì´ëí ì ììµëë¤.
ë ë§ì ìì Web Audio APIì ëí´ ë ë°°ì°ê¸° ìí´ ì´ì©í´ë³¼ ì ìë ë¤ë¥¸ ìì ë¤ì´ ììµëë¤.
Voice-change-O-maticë ë¤ë¥¸ í¨ê³¼ì ìê°í를 ê³ ë¥¼ ì ìê² íì©íë ì¬ë¯¸ìë 목ì리 ë³ì¡°ê¸°ì ì리 ìê°í ì¹ ì±ì ëë¤. ì´ ì í리ì¼ì´ì ì ìë¹í 기본ì ì´ì§ë§, ë¤ìì Web Audio API 기ë¥ì ëì ì¬ì©ì ë³´ì¬ì¤ëë¤. (Voice-change-O-matic를 ì¤íí´ ë³´ì¸ì).
Web Audio API를 ë³´ì¬ì£¼ê¸° ìí´ ëª ííê² ê°ë°ë ë ë¤ë¥¸ ì í리ì¼ì´ì ì Violent Thereminì¸ë°, ì´ë ë§ì°ì¤ í¬ì¸í°ë¥¼ ìì§ìì¼ë¡ì¨ ì ëì´(pitch)ì 볼륨ì ë³ê²½íë ê²ì íì©íë ê°ë¨í ì¹ ì í리ì¼ì´ì ì ëë¤. ì´ê²ì ëí ì¬ì´í¤ë¸ë¦í ë¼ì´í¸ ì¼ë¥¼ ì ê³µí©ëë¤ (Violent Theremin ìì¤ ì½ë를 íì¸í´ ë³´ì¸ì).
ëí ë ë§ì ìì를 ë³´ìë ¤ë©´ webaudio-examples repo를 ì°¸ê³ í´ ë³´ì¸ì.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4