Web Audio API 간단 정리하기

박성룡 ( Andrew park )
9 min readSep 29, 2019

--

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(출력)로 나눌 수 있다.

대략적으로 아래 과정을 거친다.

  1. AudioContext 를 생성한다.
  2. Source 를 생성하기 위해, <audio>AudioBuffer 등의 Input AudioNode 을 생성한다.
  3. Source 에 효과를 주기 위해, GainNode (볼륨 조절) 나 StereoPannerNode(채널제어) 등의 Effects AudioNode 를 생성한다.
  4. AudioContext 의 Source 가 출력될 destination 설정한다.
  5. Input AudioNode 에 각종 Effects AudioNode 를 연결한다.
  6. AudioContext 으로 재생 여부를 제어한다.

Web Audio API 요소

AudioContext | BaseAudioContext

  1. 모든 작업은 컨텍스트 내에서 이루어진다.
  2. State 를 가지고 있다.
    suspended: 중지
    running: 실행 중
    closed: 닫힘
  3. resume() 실행 와 suspend() 중지 으로 Context 상태를 변경할 수 있다.
  4. 출력 위치를 나타내는 Destination 를 가지고 있다.

AudioDestinationNode

  1. 컨텍스트의 작업물을 어디로 출력할지 결정한다. 보통 스피커이다.
  2. maxChannelCount 을 가지며 최대 나갈수 있는 채널을 의미한다.

AudioNode

  1. AudioContext 여러 AudioNode 를 가지고 작업물을 제어한다.
  2. 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);
  1. new AudioContext() 으로 컨텍스트를 생성한다.
  2. AudioContext.destination 기본 출력은 스피커이다.
  3. AudioContext.createMediaElementSource 에 audio tag 를 전달하고, MediaElementAudioSourceNode 생성한다.
  4. 볼륨을 제어할 GainNode 를 생성한다.
  5. MediaElementAudioSourceNodeGainNode 를 연결한다.
  6. MediaElementAudioSourceNode 의 출력으로 AudioContext.destination 를 연결한다.
  7. Button Tag 에서 click 이벤트가 발생할때마다, AudioContext 상태를 확인하고, suspended 상태라면, resume 진행상태로 변경하고, playState 에 따라 Play / Pause 를 결정한다.
  8. Input Tag 에서 값을 입력받을 때마다, AudioParam 인 GainNode 의 value 를 수정한다.
  9. AudioContext 내에 연결된 Audio 는 Connect Pipe 에 따라 GainNode 에 설정되어 있는 효과로 수정 되어 출력된다.

AudioWorkletNode

Web Audio API 는 Main Thread 에서 실행된다.

만약 다른 Javascript 작업이나 UI 작업이 들어온다면, Audio 작업에 영향을 받을 수 있다.

AudioWorkletNodeAudioWorkletGlobalScope 내에서 실행되므로써, 다른 작업에 영향받지않고 실행될 수 있다.

AudioWorkletNodeAudioWorkletProcessorAudioWorkletNode 로 이루어진다.

  1. AudioWorkletProcessor
    Audio Worklet Global Scope에 속하며 Audio 작업을 처리한다.
  2. 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 를 이용하여, 파형을 그리는 예제를 만들어 보고 싶다.

--

--

박성룡 ( Andrew park )
박성룡 ( Andrew park )

Written by 박성룡 ( Andrew park )

Javascript is great We may not be great

No responses yet