Web Audio API 간단 정리하기
Web Audio API 를 익히고 이를 간단히 정리해보고자 한다.
HTML5 에서는 <audio>
Element 를 이용해서 음악 파일을 재생할 수 있다.
<audio controls src="파일이름.mp3" >지원안함</audio><audio controls>
<source src="파일이름.mp4" type='audio/mp4' />
<source src="파일이름.oga" type='audio/ogg; codecs=vorbis' />
지원안함
</audio>
controls 를 세팅할 경우 각각의 브라우저마다, 사용자에게 GUI 를 제공하여, Play / Pause / Stop 제어를 돕는다.
만약 WEB 에서 소리를 복합적으로 제어해야 한다면, audio 에서 제공하는 기능 만으로는 부족할 수 있다.
이럴 경우 Web Audio API 를 이용할 수 있다.
Web Audio API
Web Audio API 는 웹에서 오디오에 이펙트를 추가하거나, 파형을 시각화 하는등 다양한 기능을 구현할 수 있도록 도와준다.
Web Audio API 는 모든 작업을 AudioContext 내에서 처리한다.
AudioContext 내에서는 각각의 AudioNode 들로 소리를 제어하게 되는데, 크게 Inputs(입력), Effects(수정), Destination(출력)로 나눌 수 있다.
대략적으로 아래 과정을 거친다.
- AudioContext 를 생성한다.
- Source 를 생성하기 위해, <audio> 나 AudioBuffer 등의 Input AudioNode 을 생성한다.
- Source 에 효과를 주기 위해, GainNode (볼륨 조절) 나 StereoPannerNode(채널제어) 등의 Effects AudioNode 를 생성한다.
- AudioContext 의 Source 가 출력될 destination 설정한다.
- Input AudioNode 에 각종 Effects AudioNode 를 연결한다.
- AudioContext 으로 재생 여부를 제어한다.
Web Audio API 요소
AudioContext | BaseAudioContext
- 모든 작업은 컨텍스트 내에서 이루어진다.
- State 를 가지고 있다.
suspended: 중지
running: 실행 중
closed: 닫힘 - resume() 실행 와 suspend() 중지 으로 Context 상태를 변경할 수 있다.
- 출력 위치를 나타내는 Destination 를 가지고 있다.
AudioDestinationNode
- 컨텍스트의 작업물을 어디로 출력할지 결정한다. 보통 스피커이다.
- maxChannelCount 을 가지며 최대 나갈수 있는 채널을 의미한다.
AudioNode
- AudioContext 여러 AudioNode 를 가지고 작업물을 제어한다.
- connect() 연결 | disconnect() 해제 로 오디오의 효과를 연결할 수 있다.
Web Audio API 간단한 예제
// index.html
<audio src="파일이름.mp3"></audio>
<button name="play">재생버튼</button>
<input name="volume" type="number" value="1" />
audio Element 에 오디오 파일을 세팅하고 이를 제어하고자 한다.
button 으로 재생 여부를 결정하고, input 으로 볼륨을 조절한다.
// index.js
const $audioEl = document.querySelector('audio');
const $buttonEl = document.querySelector('button');
const $inputEl = document.querySelector('input');// AudioContext
const audioContext = new AudioContext();
// AudioDestinationNode
const audioDestination = audioContext.destination;// MediaElementAudioSourceNode
const audioSourceNode = audioContext.createMediaElementSource($audioEl);
// GainNode
const gainNode = audioContext.createGain();audioSourceNode
.connect(gainNode)
.connect(audioDestination);let playState = false;$buttonEl.addEventListener('click', function () {
// 중지 상태가 라면
if (audioContext.state === 'suspended') {
// 실행 상태로 변경
audioContext.resume();
}playState = !playState
if (playState) {
$audio.play()
} else {
$audio.pause()
}
}, false);$inputEl.addEventListener('input', function () {
// 입력받은 값으로 GainNode 의 볼륨 효과를 제어한다.
gainNode.gain.value = this.value;
}, false);
- new AudioContext() 으로 컨텍스트를 생성한다.
- AudioContext.destination 기본 출력은 스피커이다.
- AudioContext.createMediaElementSource 에 audio tag 를 전달하고, MediaElementAudioSourceNode 생성한다.
- 볼륨을 제어할 GainNode 를 생성한다.
- MediaElementAudioSourceNode 에 GainNode 를 연결한다.
- MediaElementAudioSourceNode 의 출력으로 AudioContext.destination 를 연결한다.
- Button Tag 에서 click 이벤트가 발생할때마다, AudioContext 상태를 확인하고, suspended 상태라면, resume 진행상태로 변경하고, playState 에 따라 Play / Pause 를 결정한다.
- Input Tag 에서 값을 입력받을 때마다, AudioParam 인 GainNode 의 value 를 수정한다.
- AudioContext 내에 연결된 Audio 는 Connect Pipe 에 따라 GainNode 에 설정되어 있는 효과로 수정 되어 출력된다.
AudioWorkletNode
Web Audio API 는 Main Thread 에서 실행된다.
만약 다른 Javascript 작업이나 UI 작업이 들어온다면, Audio 작업에 영향을 받을 수 있다.
AudioWorkletNode 는 AudioWorkletGlobalScope 내에서 실행되므로써, 다른 작업에 영향받지않고 실행될 수 있다.
AudioWorkletNode 은 AudioWorkletProcessor 와 AudioWorkletNode 로 이루어진다.
- AudioWorkletProcessor 는
Audio Worklet Global Scope에 속하며 Audio 작업을 처리한다. - AudioWorkletNode 는
Main Global Scope 에 속하며 다른 AudioNode 와의 연결을 관리한다.
다른쓰레드에 존재 하므로 메시지를 교환할때는, MessagePort 로 양방향 통신이 가능하다.
// processor.js
class SomeProcessor extends AudioWorkletProcessor {
constructor() {
super();
this.port.onmessage = (event) => {
// event.data === SomeAudioWorkletNode
};
this.port.postMessage('SomeProcessor');
}
process(inputs, outputs, parameters) {
//...
return true
}
}registerProcessor('some-processor', WhiteNoiseProcessor)
processor 는 외부 파일로 작성되어야 한다.
class SomeWorklet extends AudioWorkletNode {
constructor(context) {
super(context, 'some-processor');
}
}const audioContext = new AudioContext();audioContext.audioWorklet.addModule('processor.js').then(() => {
const someWorklet = new SomeWorklet(audioContext);
someWorklet.port.onmessage = (event) => {
// event.data === 'Processor'
};
someWorklet.port.postMessage('SomeWorklet');
});
마무리
Web Audio API 는 Web 에서 소리를 제어하는 강력한 방법을 제공한다.
소리는 Video 나 WebRTC 에서도 사용하므로, 다양한 곳에서 사용될 수 있을것 같다.
마이크 권한을 navigator.mediaDevices.getUserMedia ({audio: true}) 으로 부여받고 stream 으로 전달받아 이를 AudioContext.createMediaStreamSource 으로 만들고, AnalyserNode 으로 파형 정보를 받아 시각화 하는 것도 가능하다.
AudioWorkletNode 는 아직 모든 브라우저에 구현되지 않았다.
다음 포스트로 AudioWorkletNode 를 이용하여, 파형을 그리는 예제를 만들어 보고 싶다.