WebAudio API

WebAudio API를 이용하여 소리를 시각화

HTML5에서는 audio가 출력이되기전에 데이터를 가로채서 활용을 할 수 있습니다.
아래와 같이 input과 output 중간에서 AnalyserNode를 이용하여 data를 가로챌 수 있게 됩니다.

audioAnalyser
이미지 출처 : https://developer.mozilla.org/ko/docs/Web/API/AnalyserNode

AnalyserNode는 AuidoContext의 createAnalyser 메소드를 사용하여, 주파수를 시각화 할 수 있는 AnalyserNode를 만들어줍니다.

우선 오디오를 시각화 하기 위해서는 AnalyserNode와 GainNode이 필요합니다.
필요한 AnalyserNode와 GainNode에 대해 알아보겠습니다.

AnalyserNode

  • 시간대 별로 실시간 주파수의 정보를 표현합니다.
  • 하나의 입력에 하나의 출력을 가지고, 출력이 명시되지 않아도 동작에 이상이 없습니다.

Properties

  • AnalyserNode.fftSize

    • 주파수 영역을 결정하는데 사용되는 FFT ( 고속 푸리에 변환 )의 크기를 정의합니다.

    • 설정된 수가 클수록 세밀하지만 시간이 오래걸리고, 시간이 적으면 빨라집니다.

    • 2의 거듭제곱이여야 합니다. ( 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768 )

    • 기본값 2048

    • 고속 푸리에 변환 : 시간영역의 신호를 주파수 영역으로 변환 시키는 알고리즘

  • AnalyserNode.frequencyBinCount (Read Only)

    • 일반적으로 시각화를 위해 재생되야하는 데이터 값입니다.

    • 고속푸리에 변환과 관련된 기술적 이유로 항상 fftsize의 절반 값을 정의합니다.

    • fftSize 설정하지 않으면 기본값 1024 (fftSize 기본값인 2048의 절반값이기 때문)

  • AnalyserNode.minDecibels

    • fft 데이터 범위의 최소값을 지정합니다. ( -100 ~ 0 )

    • 단 maxDecibels 보다 클 수 없습니다.

  • AnalyserNode.maxDecibels

    • fft 데이터 범위의 최대값을 지정합니다. ( -100 ~ 0 )

    • 단 minDecibels 보다 작을 수 없습니다.

method

  • getByteFrequencyData

    • getByteFrequencyData는 현재의 주파수 데이터를 복사합니다.

    • 주파수 데이터는 0에서 255까지의 정수로 구성됩니다.

    • 배열의 각 항목은 특정 주파수에 대한 데시벨 값을 나타냅니다.

    • 주파수는 샘플 속도의 0에서 1/2까지 분산됩니다.

    • ex) [ 0, 0, 0, 0, 0 ] -> [ 255, 255, 255, 0, 0 ]

    • ex) 0번째 요소 주파수 = ( n x samplerate ( 기본 44100Hz ) / fftsize) / 2

  • getByteTimeDomainData

    • getByteTimeDomainData는 현재의 파형 테이터를 복사합니다.

    • ex) [ 127, 127, 127, 127, 127 ] -> [ 200, 100, 222, 127, 127 ]

GainNode

  • 볼륨을 조절할 수 있게 해주는 인터페이스입니다.

Properties

  • gain

    • 해당 오디오의 볼륨값을 조절합니다.

그 외의 오디오 이팩트 노드

  • BiquadFilterNode
  • ConvolerNode
  • DelayNode
  • DynamicsCompressorNode
  • StereoPannerNode
  • WaveShaperNode

사용법

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const audioContext = new AudioContext();
const analyser = audioContext.createAnalyser();
const gainNode = audioContext.createGain();

// mediaStream 사용시 createMediaStreamSource
const source = audioContext.createMediaStreamSource(MediaStream);
// audio tag의 mp3 파일이라면 createMediaElementSource
const audioSource = audioContext.createMediaElementSource(audioElm);

source.connect(gainNode);
source.connect(analyser);

// 만약 오디오 출력을 하고싶다면 auidoNode에 해당 audioContext의 destination을 연결
source.connect(this.audioContext.destination);

const dataArray = new Uint8Array(analyser.frequencyBinCount);

analyser.getByteFrequencyData(dataArray);
  1. audioContext를 생성한 후

  2. audioContext의 createAnalyser를 사용하여 analyserNode를 생성합니다.

  3. audioContext의 createGain 사용하여 GainNode 생성합니다.

  4. audio의 주체?에 따라서 createMediaStreamSource 혹은 createMediaElementSource 사용하여 audioSoure를 가져옵니다.

  5. 해당 audio source에 GainNode를 연결시켜줍니다.

  6. Uint8Array를 사용하여 [ 0 ~ 255 ] 제한 값을 가지는 배열을 frequencyBinCount 길이 만큼 만들어줍니다.

  7. analyserNode의 getByteFrequencyData를 사용하여 dataArray에 주파수 데이터를 복사합니다.

  8. 7을 반복하여 dataArray를 UI로 시각화

source -> effectNode -> destination순으로 연결 시키는데 destination은 상황에 따라 연결시키지 않아도 무관합니다.
AudioNode들은 connect 메서드를 가지고 있고, 자기 자신까지 연결된 객체를 반환합니다.

추가로 위에서 언급했던 그 외의 오디오 이팩트 노드를 사용하면 더 많은 오디오 효과를 낼 수 있다고 합니다. ( 아직 해보진 않아서.. )



Comments: