# Audio

## Web Audio API <a href="#id-74cd" id="id-74cd"></a>

> audio element로 불가능한 복잡한 인터렉티브한 오디오 기능을 구현하려 할 때 사용 된다.

* 그래프에 기반한 오디오 프로그래밍 API
* **`Audio Node`**&#xB77C; 불리우는 다양한 요소들을 연결하여 그래프를 만든다.

### Audio Element

* 미디어 재생

### Web Audio API

* 게임
* 화상회의
* 음악 제작
* 음악 교육
* 입체 음향

## AudioContext <a href="#id-74cd" id="id-74cd"></a>

> 모든 웹 오디오 기능에 모체가 되는 객체

* 다양한 오디오 노드를 만듦&#x20;
* 오디오 재생을 시작하거나 멈추는 기능을 제공

```typescript
const ctx = new AudioContext();
```

### AudioBuffer <a href="#dc9e" id="dc9e"></a>

> 오디오 데이터를 저장하는 객체

AudioBuffer를 사용해서 mp3 파일과 같은 외부 오디오 리소스를 웹에서 재생시키는 방법은 다음과 같다.

1. 외부 오디오 파일을 로드하고, **arrayBuffer** 객체로 변환 후 audio context에 전달한다.
2. **decodeAudioData**를 활용하여 arrayBuffer를 web audio api가 이해할 수 있는 형식으로 변환(decode)한다.
3. **AudioBufferSourceNode**를 통해 오디오를 재생시킨다.

```typescript
const ctx = new AudioContext();
const res = await window.fetch(url);
const arrayBuffer = await res.arrayBuffer();
const audioBuffer = await ctx.decodeAudioData(arrayBuffer);
const source = ctx.createBufferSource();

source.buffer = audioBuffer;
source.connect(ctx.destination);
source.start();
```

{% hint style="info" %}
**버퍼**는 데이터를 임시로 저장하는 공간이나 장치를 의미

* **arrayBuffer** → 2진 데이터로 구성된 버퍼를 나타내는 객체
  {% endhint %}

### Oscillator <a href="#dc9e" id="dc9e"></a>

> 파동 생성을 담당

#### 파동 타입

* `"sine"`, `"square"`, `"sawtooth"`, `"triangle"`, `"custom"`

```typescript
const osc = ctx.createOscillator();
osc.type = "sign";
```

### Gain

> 볼륨 담당

```typescript
const amp = ctx.createGain();
```

### Compressor <a href="#a42b" id="a42b"></a>

> 음향의 `Dynamic Range`를  좁히는데 사용

```typescript
const convolver = ctx.createDynamicsCompressor();
```

* Dyanmic Range를 의도적으로 줄인뒤 소리의 전체적인 음량을 증가시켜서 조금 더 박력있는 소리를 나타내게 한다. (with Gain)

{% hint style="info" %}
**Dynamic Range** 재생가는한 음량의 큰 부분과 작은 부분의 차
{% endhint %}

#### 파라미터 <a href="#a42b" id="a42b"></a>

* **Threshold** → Compressor가 시작될 음량
  * 입력 음향이 해당 파라미터보다 크면 **Compressor**가 동작해 출력 음량을 줄이게 된다.
* **Ratio** → 음량을 얼마나 줄인것인지
  * Threshold와 조합하여 소리가 가진  **`Dynamic Range`**&#xB97C; 제어할 수 있다.
* **Makeup Gain** → 압축된 **`Dynamic Range`**&#xB97C; 보상해주는 역할
  * 압축된 만큼 소리를 올려주면 박력있는 소리를 나타낼 수 있다.

### 버스 이펙트 <a href="#a42b" id="a42b"></a>

> **여러 소리가 하나로 합쳐지는 경로**를 **버스**라 한다.&#x20;

* 컴프레서는 버스 길목에 삽입되어져야 한다.&#x20;
* Dynamic Compressor Node는 **CPU 소모가 꽤 크다.**
* 각 샘플마다 개별적으로 적용시키기 보다는 최종 출력에 적용하는게 효율적이다.
* 모든 소리가 하나의 컴프레서를 통과시키게 함으로써 전체적인 음색의 일관성도 지킬 수 있다.

### Convolver <a href="#a42b" id="a42b"></a>

> 리벌브(잔향) 효과 담당&#x20;

* Convolver Node만으로는 아무런 효과를 낼 수 없다.
* 임펄스 응답(Impuls Response)이라 불리는 오디오 파일을 오디오 버퍼로 불러들여서 컨볼버에 할당해줘야 한다
* 마찬가지로 CPU소모가 크기 때문에 버스이펙트를 사용해서 최종 출력에 적용하자.

```typescript
const convolver = ctx.createConvolver();
```

{% hint style="info" %}
임펄스 응답(Impuls Response)

* 소리의 울림소리의 특성을 가지고 있는 것
* 공간 자체가 가지고 있는 음색, 울림의 길고 짧음
* 즉 공간의 특성을 가지고 있음
  {% endhint %}

### Analyser <a href="#id-634a" id="id-634a"></a>

> 분석 및 시각화 목적으로 실시간 정보를 추출

```typescript
const analyser = ctx.createAnalyser();
```

### MediaElementAudioSourceNode

> 음원으로 입력되어 있는 Audio의 출력을 자동으로 트래킹한다.

```typescript
const mediaElementSource = ctx.createMediaElementSource(audio);
```

{% hint style="info" %}
생성자 방식: 일부 브라우저에서 지원되지 않을 수 있다.

```typescript
const mediaElementSource = new MediaElementAudioSourceNode(ctx, {mediaElement: audio});
```

{% endhint %}
