opus clib Audio / Codec

Opus audio codec. Encode/decode speech and music, 6–510 kbps, VBR, DTX, packet loss concealment. RFC 6716.

ppm install opus

Overview

opus wraps libopus — the open, royalty-free audio codec standardized in RFC 6716. It combines the SILK speech layer and the CELT music layer to cover everything from narrow-band telephony to high-fidelity stereo music in a single unified codec.

Opus is the codec of choice for WebRTC, Discord, Zoom, Mumble, WhatsApp, and YouTube live streams. The PascalAI binding exposes encoder/decoder creation, per-frame PCM encode/decode, packet analysis helpers, and convenience file encode/decode.

CLib package

Requires libopus-dev. Ubuntu/Debian: sudo apt install libopus-dev

Key Characteristics

PropertyValue
Bitrate range6–510 kbps (variable or constant)
Frame latency2.5–60 ms per frame (configurable)
Sample rates8, 12, 16, 24, 48 kHz (always encoded internally at 48 kHz)
ChannelsMono and stereo
Complexity0–10 (0 = fastest, 10 = best quality)
VBRVariable bitrate supported (recommended)
DTXDiscontinuous transmission — silence suppression for VoIP
PLCPacket loss concealment built in

Applications

Choose the application mode when creating an encoder. It controls the internal codec layers and trade-offs between latency, quality, and CPU.

ModeValueBest for
oaVoIP2048Voice calls, telephony, conferencing — SILK-heavy, optimized for speech intelligibility at low bitrates
oaAudio2049Music, podcasts, general audio — CELT-heavy, higher fidelity, slightly more CPU
oaLowDelay2051Real-time instruments, live monitoring — CELT only, minimal latency (2.5 ms possible), no DTX

Codec Comparison

Compared toResult
MP3Opus better at all bitrates, especially low-bitrate speech; lower latency; open standard
AACOpus better below 128 kbps; comparable quality above that threshold
VorbisOpus is the direct successor — better quality, lower latency, equally open
FLACDifferent use cases: Opus is lossy, FLAC is lossless; Opus wins on size and streaming

Quick Start

Encode PCM to Opus

uses opus;

{ Create a VoIP encoder at 48 kHz, mono }
var enc := NewEncoder(48000, 1, oaVoIP);
SetBitrate(enc, 32000);   { 32 kbps }
SetVBR(enc, True);
SetDTX(enc, True);        { suppress silence }

{ pcm is array of SmallInt, 960 samples = 20 ms at 48 kHz }
var packet := Encode(enc, pcm, 960);
WriteLn('Compressed: ' + IntToStr(Length(packet)) + ' bytes');

FreeEncoder(enc);

Decode Opus to PCM

uses opus;

{ Create a decoder matching the encoder's sample rate and channel count }
var dec := NewDecoder(48000, 1);

{ Decode one packet — FrameSize is max output samples per channel }
var pcm := Decode(dec, packet, 5760);  { 5760 = 120 ms at 48 kHz }
WriteLn('PCM samples: ' + IntToStr(Length(pcm)));

{ Simulate a lost packet with PLC }
var concealed := DecodePLC(dec, 960);

FreeDecoder(dec);

Encode a WAV file to .opus

uses opus;

{ High-quality music encode at 128 kbps }
EncodeFile('input.wav', 'output.opus', 128000, oaAudio);
WriteLn('Encoded. Codec version: ' + OpusVersion());

{ Decode back to float PCM }
var samples := DecodeFile('output.opus');
WriteLn('Total float samples: ' + IntToStr(Length(samples)));

Types

TOpusEncoder

type TOpusEncoder = Integer;  { opaque encoder handle }

Handle returned by NewEncoder. Pass to all encoder functions. Free with FreeEncoder when done.

TOpusDecoder

type TOpusDecoder = Integer;  { opaque decoder handle }

Handle returned by NewDecoder. Pass to all decoder functions. Free with FreeDecoder when done.

TOpusApplication

type
  TOpusApplication = (
    oaVoIP     = 2048,  { optimized for voice (SILK-heavy) }
    oaAudio    = 2049,  { optimized for music (CELT-heavy) }
    oaLowDelay = 2051   { minimal latency, music (CELT only) }
  );

TOpusSignal

type
  TOpusSignal = (
    osAuto  = -1000,  { auto-detect signal type }
    osVoice = 3001,   { hint: voice signal }
    osMusic = 3002    { hint: music signal }
  );

Signal hint passed to SetSignal. Helps the encoder choose SILK vs CELT weighting at hybrid bitrates.

TOpusInfo

type
  TOpusInfo = record
    SampleRate  : Integer;           { 8000/12000/16000/24000/48000 }
    Channels    : Integer;           { 1 = mono, 2 = stereo }
    Application : TOpusApplication;
    Bitrate     : Integer;           { bits per second }
    Complexity  : Integer;           { 0-10; higher = better quality, slower }
    UseDTX      : Boolean;           { discontinuous transmission }
    UseVBR      : Boolean;           { variable bitrate }
    FrameSizeMs : Double;            { 2.5, 5, 10, 20, 40, or 60 ms }
  end;

Convenience record for describing encoder configuration. Populate it and pass individual fields to the encoder API.

Encoder API

Create one encoder per stream. Encoders are stateful — they maintain predictor history across frames. Reset with ResetEncoder when starting a new independent stream without reallocating.

FunctionDescription
NewEncoder(SampleRate, Channels, App)Create an encoder. SampleRate: 8000/12000/16000/24000/48000. Returns a TOpusEncoder handle.
FreeEncoder(E)Destroy the encoder and release its memory.
SetBitrate(E, Bitrate)Set target bitrate in bits/sec. Pass -1 for auto (encoder decides).
SetComplexity(E, Complexity)Set CPU complexity 0–10. 0 = fastest, 10 = best quality. Default is 9.
SetVBR(E, Enable)Enable or disable variable bitrate. VBR is recommended for most uses.
SetDTX(E, Enable)Enable or disable DTX (silence suppression). Reduces bandwidth during pauses in speech.
SetSignal(E, Signal)Hint the encoder about the signal type (voice, music, or auto). Affects SILK/CELT balance.
Encode(E, PCM, FrameSize)Encode a frame of 16-bit integer PCM. FrameSize is samples per channel (e.g. 960 = 20 ms at 48 kHz). Returns compressed bytes as string.
EncodeFloat(E, PCM, FrameSize)Encode a frame of 32-bit float PCM in the −1.0..1.0 range.
ResetEncoder(E)Reset encoder state for a new stream without reallocating the encoder.

Decoder API

Create one decoder per stream. The decoder tracks state for PLC and redundancy. Reset with ResetDecoder between independent streams.

FunctionDescription
NewDecoder(SampleRate, Channels)Create a decoder. SampleRate and Channels must match the encoder settings.
FreeDecoder(D)Destroy the decoder and release its memory.
Decode(D, Packet, FrameSize)Decode an Opus packet to 16-bit integer PCM. FrameSize is the maximum output samples per channel. Returns array of SmallInt.
DecodeFloat(D, Packet, FrameSize)Decode an Opus packet to 32-bit float PCM in the −1.0..1.0 range.
DecodePLC(D, FrameSize)Generate a concealment frame for a lost packet. Call instead of Decode when a packet does not arrive.
ResetDecoder(D)Reset decoder state for a new stream.
Tip — Packet Loss Concealment

When a packet is lost in transit, call DecodePLC(dec, frameSize) instead of Decode. Opus synthesizes a plausible continuation of the signal so the listener hears smooth audio rather than a gap or click.

Packet Analysis API

Inspect Opus packet metadata without fully decoding. Useful for jitter-buffer management and stream diagnostics.

FunctionDescription
PacketSamples(Packet, SampleRate)Return the number of PCM samples contained in the packet at the given sample rate, without decoding.
PacketFrameCount(Packet)Return the number of Opus frames packed into the packet (1, 2, or arbitrary with CELT code 3).
PacketBandwidth(Packet)Return the bandwidth identifier used in the packet: 1105=NB, 1106=MB, 1107=WB, 1108=SWB, 1109=FB.
uses opus;

var n := PacketSamples(packet, 48000);
var frames := PacketFrameCount(packet);
var bw := PacketBandwidth(packet);
WriteLn(IntToStr(n) + ' samples, ' + IntToStr(frames) + ' frame(s), bw=' + IntToStr(bw));

File API

Convenience functions that handle the full encode or decode pipeline for files. Internally they use libopusfile and handle container framing, header writing, and multi-page Ogg streams.

FunctionDescription
EncodeFile(WavPath, OpusPath, Bitrate, App)Encode a WAV file to an .opus Ogg container at the given bitrate (bits/sec) and application mode.
DecodeFile(OpusPath)Decode a .opus file entirely to an array of 32-bit float PCM samples (interleaved channels).
OpusVersion()Return the libopus version string, e.g. libopus 1.3.1.

Key Concepts

Frame sizes

Opus operates on fixed frame sizes: 2.5, 5, 10, 20, 40, or 60 ms. At 48 kHz, 20 ms = 960 samples per channel. Smaller frames reduce latency but increase overhead per packet; 20 ms is the standard choice for most applications.

Internal 48 kHz resampling

Regardless of the SampleRate passed to NewEncoder, the codec always processes audio at 48 kHz internally. Passing a lower sample rate simply tells the codec the input bandwidth — it resamples automatically. Always prefer 48 kHz input to avoid any quality loss from the internal resampler.

VBR vs CBR

Variable bitrate (SetVBR(enc, True)) is recommended for most applications. CBR is useful when the channel requires a strictly constant data rate, such as some satellite links or legacy VoIP systems that expect constant RTP packet sizes.

DTX and silence

When DTX is enabled, the encoder emits very short comfort-noise packets during silence instead of full-size frames. This can reduce bandwidth by 60–80% in a typical voice call with natural pauses.

Package Info

Version1.0.0
Typeclib
C Librarylibopus-dev
StandardRFC 6716

System Requirements

libopus-dev

Ubuntu/Debian:
sudo apt install libopus-dev

TOpusApplication Modes

oaVoIP — voice / telephony
oaAudio — music / general
oaLowDelay — real-time / instruments

Functions

  • NewEncoder / FreeEncoder
  • SetBitrate
  • SetComplexity
  • SetVBR / SetDTX
  • SetSignal
  • Encode / EncodeFloat
  • ResetEncoder
  • NewDecoder / FreeDecoder
  • Decode / DecodeFloat
  • DecodePLC
  • ResetDecoder
  • PacketSamples
  • PacketFrameCount
  • PacketBandwidth
  • EncodeFile / DecodeFile
  • OpusVersion

See Also