LemonGateway.Voice.AudioConversion (lemon_gateway v0.1.0)

View Source

Pure-Elixir audio format conversion for Twilio voice calls.

Twilio expects 8-bit mu-law (G.711) at 8000 Hz, mono channel. ElevenLabs returns MP3-encoded audio by default.

This module provides:

  • 16-bit signed PCM to 8-bit mu-law encoding
  • MP3 frame detection (to identify MP3 input that requires external decoding)

Mu-law encoding

Mu-law compresses 16-bit linear PCM samples into 8-bit values using the ITU-T G.711 standard. The algorithm applies logarithmic compression with mu = 255, preserving dynamic range while halving bandwidth.

The implementation uses only Elixir binary pattern matching and integer arithmetic — no external C libraries or NIFs are required.

Summary

Functions

Encode a single 16-bit signed PCM sample to an 8-bit mu-law byte.

Returns true if the binary appears to start with an MP3 sync word.

Converts raw 16-bit signed little-endian PCM data to 8-bit mu-law.

Functions

encode_mulaw_sample(sample)

@spec encode_mulaw_sample(integer()) :: byte()

Encode a single 16-bit signed PCM sample to an 8-bit mu-law byte.

Implements the ITU-T G.711 mu-law compression algorithm:

  1. Determine sign bit
  2. Take absolute value, apply bias
  3. Clip to prevent overflow
  4. Find segment via top bits
  5. Pack sign + segment + quantization step into one byte
  6. Invert all bits (per G.711 convention)

mp3_data?(audio_data)

@spec mp3_data?(binary()) :: boolean()

Returns true if the binary appears to start with an MP3 sync word.

When ElevenLabs returns MP3-encoded audio, callers should decode to PCM first before calling pcm16_to_mulaw/1. This function provides a quick header check.

pcm16_to_mulaw(pcm_data)

@spec pcm16_to_mulaw(binary()) :: binary()

Converts raw 16-bit signed little-endian PCM data to 8-bit mu-law.

Each pair of input bytes (one 16-bit sample) produces one output byte. If the input length is odd, the trailing byte is dropped.

Example

iex> pcm = <<0x00, 0x00>>  # silence
iex> LemonGateway.Voice.AudioConversion.pcm16_to_mulaw(pcm)
<<0xFF>>