# Codecs

> The codecs helpers of @morevoice/sdk.

Helpers exported by `@morevoice/sdk` from `src/lib/codecs.ts`.

## API

Exported from `@morevoice/sdk` (source: `packages/sdk-ts/src/lib/codecs.ts`).

### `MediaEncoding`

*type*

The encodings a MoreVoice media stream carries. Open: an unknown encoding is reported, not guessed.

```ts
type MediaEncoding = "audio/x-mulaw" | "audio/l16";
```

### `MediaFormat`

*interface*

```ts
interface MediaFormat {
	encoding: MediaEncoding | (string & {});
	/** 8000 for μ-law; 16000 or 8000 for L16. */
	sampleRate: number;
	channels: number;
	/** MoreVoice states the L16 byte order explicitly (always "little-endian"); absent for μ-law. */
	byteOrder?: "little-endian" | (string & {});
}
```

### `MULAW_8K`

*constant*

μ-law, 8 kHz, mono: the Twilio-compatible default.

```ts
const MULAW_8K: MediaFormat;
```

### `L16_16K`

*constant*

16-bit linear PCM (little-endian), 16 kHz, mono.

```ts
const L16_16K: MediaFormat;
```

### `L16_BYTE_ORDER`

*constant*

Byte order of `audio/l16` payloads on the MoreVoice wire (see the file header).

```ts
const L16_BYTE_ORDER;
```

### `FRAME_MS`

*constant*

Media frames are 20 ms of audio (160 μ-law bytes at 8 kHz, 320 samples = 640 bytes of L16 at 16 kHz).

```ts
const FRAME_MS = 20;
```

### `CodecError`

*class*

```ts
class CodecError extends Error {
	readonly name = "CodecError";
}
```

### `linearToMulaw()`

*function*

One PCM16 sample → one μ-law byte (G.711, the same algorithm as server/audio/g711.ts).

```ts
function linearToMulaw(sample: number): number;
```

### `mulawToLinear()`

*function*

One μ-law byte → one PCM16 sample.

```ts
function mulawToLinear(byte: number): number;
```

### `encodeMulaw()`

*function*

PCM16 samples → μ-law bytes.

```ts
function encodeMulaw(pcm: Int16Array): Uint8Array;
```

### `decodeMulaw()`

*function*

μ-law bytes → PCM16 samples.

```ts
function decodeMulaw(bytes: Uint8Array): Int16Array;
```

### `encodeL16()`

*function*

PCM16 samples → little-endian bytes (the `audio/l16` payload).

```ts
function encodeL16(pcm: Int16Array): Uint8Array;
```

### `decodeL16()`

*function*

Little-endian bytes → PCM16 samples. An odd trailing byte is a broken frame.

```ts
function decodeL16(bytes: Uint8Array): Int16Array;
```

### `isSupportedFormat()`

*function*

Whether this SDK can encode and decode `format`.

```ts
function isSupportedFormat(format: MediaFormat): boolean;
```

### `encodePcm()`

*function*

PCM16 at the format's own rate → payload bytes.

```ts
function encodePcm(pcm: Int16Array, format: MediaFormat): Uint8Array;
```

### `decodePayloadBytes()`

*function*

Payload bytes → PCM16 at the format's own rate.

```ts
function decodePayloadBytes(bytes: Uint8Array, format: MediaFormat): Int16Array;
```

### `decodePayload()`

*function*

A base64 `media.payload` → PCM16 at the format's rate.

```ts
function decodePayload(payload: string, format: MediaFormat): Int16Array;
```

### `frameBytes()`

*function*

Bytes per 20 ms frame of `format`.

```ts
function frameBytes(format: MediaFormat, frameMs = FRAME_MS): number;
```

### `framePayloads()`

*function*

Payload bytes → base64 payloads of `frameMs` each (the last may be shorter). L16 frames never split a sample.
This is how the SDK frames outbound `media` messages.

```ts
function framePayloads(bytes: Uint8Array, format: MediaFormat, frameMs = FRAME_MS): string[];
```

### `encodeFrames()`

*function*

PCM16 (at `sampleRate`, default the format's) → base64 payloads of 20 ms in `format`. Stateless: one utterance.

```ts
function encodeFrames(pcm: Int16Array, format: MediaFormat, sampleRate = format.sampleRate): string[];
```

### `Resampler`

*class*

A streaming sample-rate converter for mono PCM16: band-limited (windowed sinc), zero phase and stateful, so audio
pushed in 20 ms pieces converts exactly like the whole signal at once. It holds back a few milliseconds of output
until it has seen the input those samples depend on; `flush()` releases them at the end.

```ts
const up = new Resampler(8000, 16000);
const a = up.push(frame1); const b = up.push(frame2); const tail = up.flush();
```

```ts
class Resampler {
	readonly fromRate: number;
	readonly toRate: number;
	constructor(fromRate: number, toRate: number);
	/** Convert the next piece of input; returns what is ready (a few ms are held back until more input or flush()). */
	push(input: Int16Array): Int16Array;
	/** The held-back output (the input's end is padded with silence). The resampler then starts over. */
	flush(): Int16Array;
	/** Forget everything (after a `clear`). */
	reset(): void;
	/** Output samples per input sample. */
	get ratio(): number;
}
```

### `resample()`

*function*

Convert a whole signal between sample rates (band-limited, zero phase; length = ⌊n · to / from⌋).

```ts
function resample(pcm: Int16Array, fromRate: number, toRate: number): Int16Array;
```

### `snrDb()`

*function*

Signal-to-noise ratio (dB) of `actual` against `reference` over `[from, to)` — for codec tests and diagnostics.

```ts
function snrDb(reference: Int16Array, actual: Int16Array, from = 0, to = Math.min(reference.length, actual.length)): number;
```

### `codecs`

*constant*

The codec helpers as one namespace (`codecs.encodeMulaw(…)`).

```ts
const codecs;
```
