opus_pure/config.rs
1//! Encoder and decoder configuration types.
2
3/// What the encoder is being asked to optimise for, fixed when it is created.
4///
5/// This is the one setting that cannot be changed afterwards, because it
6/// decides which coding layers the encoder is allowed to use at all. It biases
7/// the SILK/CELT decision rather than dictating it: [`Audio`](Self::Audio) and
8/// [`Voip`](Self::Voip) both reach all three modes, and speech still codes as
9/// SILK under `Audio` when the content analysis says so.
10///
11/// The discriminants are libopus's `OPUS_APPLICATION_*` values, so a caller
12/// bridging to a C API can cast between the two.
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub enum Application {
15 /// Speech over a network. Shifts the mode threshold 8 kHz toward SILK
16 /// (`opus_encoder.c`), so borderline content codes as speech, and enables
17 /// the speech-oriented machinery: the analysis-driven bandwidth cap, DTX,
18 /// and in-band FEC being worth spending bits on.
19 Voip = 2048,
20 /// General audio, and the right default when the content is unknown or
21 /// mixed. Favours reproducing the input over making speech intelligible at
22 /// low rates.
23 Audio = 2049,
24 /// Lowest achievable latency, at a cost in quality.
25 ///
26 /// Forces CELT for every frame and removes the 2.5 ms CELT lookahead that
27 /// the other two spend to keep the layers aligned across a mode switch
28 /// (`opus_encoder.c:1904`), since with no mode switching there is nothing to
29 /// align. That lookahead is part of what
30 /// [`OpusHead::RECOMMENDED_PRE_SKIP`](crate::ogg::OpusHead::RECOMMENDED_PRE_SKIP)
31 /// counts, so a stream encoded this way has less delay to skip.
32 RestrictedLowDelay = 2051,
33}
34
35/// How the encoder is allowed to vary the size of each packet.
36///
37/// Opus is a variable-rate codec, and the bitrate a caller sets is an average
38/// the encoder spends around rather than a size it emits every time. This
39/// chooses how much it is allowed to deviate.
40///
41/// [`ConstrainedVbr`](Self::ConstrainedVbr) is the default, and matches
42/// libopus. The difference from [`Vbr`](Self::Vbr) only shows up on content
43/// whose difficulty changes quickly: constrained VBR keeps a reservoir so that
44/// any window of packets stays near the target, which is what a network with a
45/// fixed budget needs, while unconstrained VBR spends whatever a frame is
46/// worth. For encoding a file, where nothing downstream is metering the rate,
47/// unconstrained is usually the better picture per byte โ it is what `opusenc`
48/// uses by default.
49#[derive(Debug, Clone, Copy, PartialEq, Eq)]
50pub enum RateControl {
51 /// Spend what each frame is worth, with no reservoir. Best quality per byte
52 /// over a whole file; the instantaneous rate can wander a long way from the
53 /// target.
54 Vbr,
55 /// Vary per packet, but hold a reservoir so any short window stays near the
56 /// target. The default, and libopus's.
57 ConstrainedVbr,
58 /// One size for every packet. Costs roughly a twelfth of the working
59 /// bitrate against the other two, because the encoder can no longer move
60 /// bits from an easy frame to a hard one; pick it only when something
61 /// downstream genuinely needs a fixed packet size.
62 Cbr,
63}
64
65impl RateControl {
66 /// Whether this is [`Cbr`](Self::Cbr), which is the distinction almost
67 /// every decision inside the encoder actually turns on.
68 pub(crate) fn is_cbr(self) -> bool {
69 matches!(self, RateControl::Cbr)
70 }
71}
72
73/// OPUS_SET_SIGNAL hint: bias mode selection toward speech or music. `None` =
74/// OPUS_AUTO (let the analysis decide).
75///
76/// Setting this pins the answer the content analysis would otherwise reach, so
77/// it also makes the analysis cheap to skip. That matters for
78/// [`encode_parallel`](crate::encode_parallel), where every worker would
79/// otherwise have to re-derive it from its own warm-up audio.
80#[derive(Debug, Clone, Copy, PartialEq, Eq)]
81pub enum Signal {
82 /// Speech: code it as SILK, or as hybrid where the rate allows.
83 Voice,
84 /// Music: code it as CELT.
85 Music,
86}
87
88/// The audio bandwidth a packet carries, which is what Opus varies instead of
89/// the sample rate.
90///
91/// An Opus decoder always produces audio at the rate it was created with; a
92/// narrowband packet is not a slower stream, it is one whose upper spectrum was
93/// never coded. Each name gives the audio bandwidth, and the sample rate that
94/// would be needed to represent it: 4 kHz of audio needs 8 kHz of sampling.
95///
96/// The encoder chooses this per packet from the bitrate, and a caller normally
97/// leaves it alone. To constrain it, prefer
98/// [`max_bandwidth`](crate::OpusEncoder::max_bandwidth), which caps the
99/// automatic choice, over
100/// [`force_bandwidth`](crate::OpusEncoder::force_bandwidth), which overrides it
101/// and can spend bits on spectrum the rate cannot afford.
102///
103/// The discriminants are libopus's `OPUS_BANDWIDTH_*` values.
104#[derive(Debug, Clone, Copy, PartialEq, Eq)]
105pub enum Bandwidth {
106 /// 4 kHz of audio, as an 8 kHz sample rate would carry.
107 Narrowband = 1101,
108 /// 6 kHz of audio (12 kHz sampling). Retained because it appears in the
109 /// bitstream and a decoder must handle it, but libopus's encoder no longer
110 /// selects it automatically and neither does this one.
111 Mediumband = 1102,
112 /// 8 kHz of audio (16 kHz sampling), the usual top of speech coding.
113 Wideband = 1103,
114 /// 12 kHz of audio (24 kHz sampling). Hybrid and CELT only.
115 Superwideband = 1104,
116 /// 20 kHz of audio (48 kHz sampling), the full audible range. Hybrid and
117 /// CELT only.
118 Fullband = 1105,
119}
120
121/// Which coding layers a packet actually used.
122///
123/// Opus is two codecs behind one bitstream, and the TOC byte says which of them
124/// coded a given packet. A caller normally does not care โ the decoder handles
125/// all three โ but the layer decides what some other operations mean. In-band
126/// FEC, in particular, only exists in SILK and hybrid packets, so
127/// [`OpusDecoder::decode_fec`](crate::OpusDecoder::decode_fec) on a
128/// [`CeltOnly`](Self::CeltOnly) packet can only conceal.
129///
130/// RFC 6716 ยง3.1 fixes these three, so the set will not grow.
131#[derive(Debug, Clone, Copy, PartialEq, Eq)]
132pub enum OpusMode {
133 /// SILK alone: speech, up to wideband, 10 ms and longer.
134 SilkOnly,
135 /// SILK below and CELT above: speech at super-wideband or fullband.
136 Hybrid,
137 /// CELT alone: music, any bandwidth, and every frame shorter than 10 ms.
138 CeltOnly,
139}