More work on the CELT encoder description, fixed Opus figures
[opus.git] / doc / draft-ietf-codec-opus.xml
index 97e5247..bc7d374 100644 (file)
@@ -433,7 +433,7 @@ When a packet contains multiple VBR frames, the compressed length of one or
  more of these frames is indicated with a one or two byte sequence, with the
  meaning of the first byte as follows:
 <list style="symbols">
  more of these frames is indicated with a one or two byte sequence, with the
  meaning of the first byte as follows:
 <list style="symbols">
-<t>0:          No frame (DTX or lost packet)</t>
+<t>0:          No frame (discontinuous transmission (DTX) or lost packet)</t>
 <!--TODO: Would be nice to be clearer about the distinction between "frame
  size" (in samples or ms) and "the compressed size of the frame" (in bytes).
 "the compressed length of the frame" is maybe a little better, but not when we
 <!--TODO: Would be nice to be clearer about the distinction between "frame
  size" (in samples or ms) and "the compressed size of the frame" (in bytes).
 "the compressed length of the frame" is maybe a little better, but not when we
@@ -758,11 +758,11 @@ may be active.
 bit-    +-------+   |  |       |    |conversion|    v
 stream  | Range |---+  +-------+    +----------+  /---\  audio
 ------->|decoder|                                 | + |------>
 bit-    +-------+   |  |       |    |conversion|    v
 stream  | Range |---+  +-------+    +----------+  /---\  audio
 ------->|decoder|                                 | + |------>
-        |       |---+  +-------+    +----------+  \---/
-        +-------+   |  | CELT  |    | Delay    |    ^
-                    +->|decoder|----| compens- |----+
-                       |       |    | ation    |
-                       +-------+    +----------+
+        |       |---+  +-------+                  \---/
+        +-------+   |  | CELT  |                    ^
+                    +->|decoder|--------------------+
+                       |       |
+                       +-------+
 ]]>
 </artwork>
 </figure>
 ]]>
 </artwork>
 </figure>
@@ -1472,7 +1472,7 @@ The quantized excitation signal follows these at the end of the frame.
 <c/>
 
 <c>Normalized LSF Stage 2 Residual</c>
 <c/>
 
 <c>Normalized LSF Stage 2 Residual</c>
-<c><xref target="silk_nlsfs"/></c>
+<c><xref target="silk_nlsf_stage2"/></c>
 <c/>
 
 <c>Normalized LSF Interpolation Weight</c>
 <c/>
 
 <c>Normalized LSF Interpolation Weight</c>
@@ -1531,14 +1531,13 @@ Order of the symbols in an individual SILK frame.
 <section anchor="silk_stereo_pred" title="Stereo Prediction Weights">
 <t>
 A SILK frame corresponding to the mid channel of a stereo Opus frame begins
 <section anchor="silk_stereo_pred" title="Stereo Prediction Weights">
 <t>
 A SILK frame corresponding to the mid channel of a stereo Opus frame begins
- with a pair of mid-side prediction weights, designed such that zeros indicate
"no coupling".
+ with a pair of side channel prediction weights, designed such that zeros
indicate normal mid-side coupling.
 Since these weights can change on every frame, the first portion of each frame
  linearly interpolates between the previous weights and the current ones, using
  zeros for the previous weights if none are available.
 These prediction weights are never included in a mono Opus frame, and the
 Since these weights can change on every frame, the first portion of each frame
  linearly interpolates between the previous weights and the current ones, using
  zeros for the previous weights if none are available.
 These prediction weights are never included in a mono Opus frame, and the
- previous weights are reset to zeros on any transition from a mono to a stereo
- frame.
+ previous weights are reset to zeros on any transition from a mono to stereo.
 They are also not included in an LBRR frame for the side channel, even if the
  LBRR flags indicate the corresponding mid channel was not coded.
 In that case, the previous weights are used, again substituting in zeros if no
 They are also not included in an LBRR frame for the side channel, even if the
  LBRR flags indicate the corresponding mid channel was not coded.
 In that case, the previous weights are used, again substituting in zeros if no
@@ -1634,16 +1633,22 @@ w0_Q13 = w_Q13[wi0]
 <t>
 A flag appears after the stereo prediction weights that indicates if only the
  mid channel is coded for this time interval.
 <t>
 A flag appears after the stereo prediction weights that indicates if only the
  mid channel is coded for this time interval.
-It is only present if the stereo prediction weights are, i.e., if the frame
- corresponds to the mid channel of a stereo Opus frame, and is also decoded by
- silk_stereo_decode_pred() (silk_decode_stereo_pred.c).
-The decoder reads a single value using the PDF in
- <xref target="silk_mid_only_pdf"/>, and if the result is 1, then there is no
- corresponding SILK frame for the side channel.
-This flag is still coded in LBRR frames, even though the LBRR flags already
- indicate whether or not the side channel is coded.
-If the two conflict, the LBRR flags are given precedence, and this flag is
- ignored.
+It is omitted when there are no stereo weights, i.e., unless the SILK frame
+ corresponds to the mid channel of a stereo Opus frame, and it is also omitted
+ for an LBRR frame when the corresponding LBRR flags indicate the side channel
+ is present.
+When present, the decoder reads a single value using the PDF in
+ <xref target="silk_mid_only_pdf"/>, as implemented in
+ silk_stereo_decode_mid_only() (silk_decode_stereo_pred.c).
+If the flag is set, then there is no corresponding SILK frame for the side
+ channel, the entire decoding process for the side channel is skipped, and
+ zeros are used during the stereo unmixing process<!--TODO: ref-->.
+As stated above, LBRR frames still include this flag when the LBRR flag
+ indicates that the side channel is not coded.
+In that case, if this flag is zero (indicating that there should be a side
+ channel), then Packet Loss Concealment (PLC, see
+ <xref target="Packet Loss Concealment"/>) SHOULD be invoked to recover a
+ side channel signal.
 </t>
 
 <texttable anchor="silk_mid_only_pdf" title="Mid-Only Flag PDF">
 </t>
 
 <texttable anchor="silk_mid_only_pdf" title="Mid-Only Flag PDF">
@@ -1681,12 +1686,12 @@ If the frame is an LBRR frame or a regular SILK frame whose VAD flag was set
 <ttcol>Frame Type</ttcol>
 <ttcol>Signal Type</ttcol>
 <ttcol align="right">Quantization Offset Type</ttcol>
 <ttcol>Frame Type</ttcol>
 <ttcol>Signal Type</ttcol>
 <ttcol align="right">Quantization Offset Type</ttcol>
-<c>0</c> <c>Inactive</c> <c>0</c>
-<c>1</c> <c>Inactive</c> <c>1</c>
-<c>2</c> <c>Unvoiced</c> <c>0</c>
-<c>3</c> <c>Unvoiced</c> <c>1</c>
-<c>4</c> <c>Voiced</c>   <c>0</c>
-<c>5</c> <c>Voiced</c>   <c>1</c>
+<c>0</c> <c>Inactive</c> <c>Low</c>
+<c>1</c> <c>Inactive</c> <c>High</c>
+<c>2</c> <c>Unvoiced</c> <c>Low</c>
+<c>3</c> <c>Unvoiced</c> <c>High</c>
+<c>4</c> <c>Voiced</c>   <c>Low</c>
+<c>5</c> <c>Voiced</c>   <c>High</c>
 </texttable>
 
 </section>
 </texttable>
 
 </section>
@@ -1702,9 +1707,14 @@ The quantization gains are themselves uniformly quantized to 6&nbsp;bits on a
  of approximately 1.94&nbsp;dB to 88.21&nbsp;dB.
 </t>
 <t>
  of approximately 1.94&nbsp;dB to 88.21&nbsp;dB.
 </t>
 <t>
-For the first LBRR frame, an LBRR frame where the previous LBRR frame was not
- coded, or the first regular SILK frame in an Opus frame, the first subframe
- uses an independent coding method.
+For the first LBRR frame, an LBRR frame where the previous LBRR frame in the
+ same channel is not coded, or the first regular SILK frame in the current
+ channel of an Opus frame, the first subframe uses an independent coding
+ method.
+In a stereo Opus frame, the mid-only flag (from
+ <xref target="silk_mid_only_flag"/>) may cause the first regular SILK frame in
+ the side channel to occur in a later time interval than the first regular SILK
+ frame in the mid channel.
 The 3 most significant bits of the quantization gain are decoded using a PDF
  selected from <xref target="silk_independent_gain_msb_pdfs"/> based on the
  decoded signal type.
 The 3 most significant bits of the quantization gain are decoded using a PDF
  selected from <xref target="silk_independent_gain_msb_pdfs"/> based on the
  decoded signal type.
@@ -1715,8 +1725,8 @@ The 3 most significant bits of the quantization gain are decoded using a PDF
 <ttcol align="left">Signal Type</ttcol>
 <ttcol align="left">PDF</ttcol>
 <c>Inactive</c> <c>{32, 112, 68, 29, 12,  1,  1, 1}/256</c>
 <ttcol align="left">Signal Type</ttcol>
 <ttcol align="left">PDF</ttcol>
 <c>Inactive</c> <c>{32, 112, 68, 29, 12,  1,  1, 1}/256</c>
-<c>Unvoiced</c> <c>{2,   17, 45, 60, 62, 47, 19, 4}/256</c>
-<c>Voiced</c>   <c>{1,    3, 26, 71, 94, 50,  9, 2}/256</c>
+<c>Unvoiced</c>  <c>{2,  17, 45, 60, 62, 47, 19, 4}/256</c>
+<c>Voiced</c>    <c>{1,   3, 26, 71, 94, 50,  9, 2}/256</c>
 </texttable>
 
 <t>
 </texttable>
 
 <t>
@@ -1731,7 +1741,12 @@ The 3 least significant bits are decoded using a uniform PDF:
 <t>
 For all other subframes (including the first subframe of frames not listed as
  using independent coding above), the quantization gain is coded relative to
 <t>
 For all other subframes (including the first subframe of frames not listed as
  using independent coding above), the quantization gain is coded relative to
- the gain from the previous subframe.
+ the gain from the previous subframe (in the same channel).
+In particular, unlike an LBRR frame where the previous frame is not coded, in a
+ 60&nbsp;ms stereo Opus frame, if the first and third regular SILK frames
+ in the side channel are coded, but the second is not, the first subframe of
+ the third frame is still coded relative to the last subframe in the first
+ frame.
 The PDF in <xref target="silk_delta_gain_pdf"/> yields a delta gain index
  between 0 and 40, inclusive.
 </t>
 The PDF in <xref target="silk_delta_gain_pdf"/> yields a delta gain index
  between 0 and 40, inclusive.
 </t>
@@ -1784,13 +1799,14 @@ Otherwise, silk_log2lin uses
 </t>
 </section>
 
 </t>
 </section>
 
-<section anchor="silk_nlsfs" title="Normalized Line Spectral Frequencies">
-
+<section anchor="silk_nlsfs" title="Normalized Line Spectral Frequency (LSF)
+ and Linear Predictive Coding (LPC) Coefficients">
 <t>
 <t>
-Normalized Line Spectral Frequencies (LSFs) follow the quantization gains in
- the bitstream, and represent the Linear Prediction Coefficients (LPCs) for the
- current SILK frame.
-Once decoded, they form an increasing list of Q15 values between 0 and 1.
+Normalized Line Spectral Frequency (LSF) coefficients follow the quantization
+ gains in the bitstream, and represent the Linear Predictive Coding (LPC)
+ coefficients for the current SILK frame.
+Once decoded, the normalized LSFs form an increasing list of Q15 values between
+ 0 and 1.
 These represent the interleaved zeros on the unit circle between 0 and pi
  (hence "normalized") in the standard decomposition of the LPC filter into a
  symmetric part and an anti-symmetric part (P and Q in
 These represent the interleaved zeros on the unit circle between 0 and pi
  (hence "normalized") in the standard decomposition of the LPC filter into a
  symmetric part and an anti-symmetric part (P and Q in
@@ -1800,9 +1816,23 @@ Because of non-linear effects in the decoding process, an implementation SHOULD
 An encoder SHOULD also use the same process.
 </t>
 <t>
 An encoder SHOULD also use the same process.
 </t>
 <t>
-The normalized LSFs are coded using a two-stage vector quantizer (VQ).
+The normalized LSFs are coded using a two-stage vector quantizer (VQ)
+ (<xref target="silk_nlsf_stage1"/> and <xref target="silk_nlsf_stage2"/>).
 NB and MB frames use an order-10 predictor, while WB frames use an order-16
  predictor, and thus have different sets of tables.
 NB and MB frames use an order-10 predictor, while WB frames use an order-16
  predictor, and thus have different sets of tables.
+After reconstructing the normalized LSFs
+ (<xref target="silk_nlsf_reconstruction"/>), the decoder runs them through a
+ stabilization process (<xref target="silk_nlsf_stabilization"/>), interpolates
+ them between frames (<xref target="silk_nlsf_interpolation"/>), converts them
+ back into LPC coefficients (<xref target="silk_nlsf2lpc"/>), and then runs
+ them through further processes to limit the range of the coefficients
+ (<xref target="silk_lpc_range_limit"/>) and the gain of the filter
+ (<xref target="silk_lpc_gain_limit"/>).
+All of this is necessary to ensure the reconstruction process is stable.
+</t>
+
+<section anchor="silk_nlsf_stage1" title="Stage 1 Normalized LSF Decoding">
+<t>
 The first VQ stage uses a 32-element codebook, coded with one of the PDFs in
  <xref target="silk_nlsf_stage1_pdfs"/>, depending on the audio bandwidth and
  the signal type of the current SILK frame.
 The first VQ stage uses a 32-element codebook, coded with one of the PDFs in
  <xref target="silk_nlsf_stage1_pdfs"/>, depending on the audio bandwidth and
  the signal type of the current SILK frame.
@@ -1851,6 +1881,9 @@ The actual codebook elements are listed in
 </c>
 </texttable>
 
 </c>
 </texttable>
 
+</section>
+
+<section anchor="silk_nlsf_stage2" title="Stage 2 Normalized LSF Decoding">
 <t>
 A total of 16 PDFs are available for the LSF residual in the second stage: the
  8 (a...h) for NB and MB frames given in
 <t>
 A total of 16 PDFs are available for the LSF residual in the second stage: the
  8 (a...h) for NB and MB frames given in
@@ -2105,8 +2138,8 @@ Let d_LPC be the order of the codebook, i.e., 10 for NB and MB, and 16 for WB,
 Then, the stage-2 residual for each coefficient is computed via
 <figure align="center">
 <artwork align="center"><![CDATA[
 Then, the stage-2 residual for each coefficient is computed via
 <figure align="center">
 <artwork align="center"><![CDATA[
-  res_Q10[k] = (k+1 < d_LPC ? (res_Q10[k+1]*pred_Q8[k])>>8 : 0)
-               + ((((I2[k]<<10) + sign(I2[k])*102)*qstep)>>16) ,
+res_Q10[k] = (k+1 < d_LPC ? (res_Q10[k+1]*pred_Q8[k])>>8 : 0)
+             + ((((I2[k]<<10) + sign(I2[k])*102)*qstep)>>16) ,
 ]]></artwork>
 </figure>
  where qstep is the Q16 quantization step size, which is 11796 for NB and MB
 ]]></artwork>
 </figure>
  where qstep is the Q16 quantization step size, which is 11796 for NB and MB
@@ -2258,10 +2291,19 @@ Then, the stage-2 residual for each coefficient is computed via
 <c><spanx style="vbare">C&nbsp;&nbsp;C&nbsp;&nbsp;D&nbsp;&nbsp;C&nbsp;&nbsp;C&nbsp;&nbsp;D&nbsp;&nbsp;D&nbsp;&nbsp;D&nbsp;&nbsp;C&nbsp;&nbsp;C&nbsp;&nbsp;D&nbsp;&nbsp;C&nbsp;&nbsp;C&nbsp;&nbsp;D&nbsp;&nbsp;C</spanx></c>
 </texttable>
 
 <c><spanx style="vbare">C&nbsp;&nbsp;C&nbsp;&nbsp;D&nbsp;&nbsp;C&nbsp;&nbsp;C&nbsp;&nbsp;D&nbsp;&nbsp;D&nbsp;&nbsp;D&nbsp;&nbsp;C&nbsp;&nbsp;C&nbsp;&nbsp;D&nbsp;&nbsp;C&nbsp;&nbsp;C&nbsp;&nbsp;D&nbsp;&nbsp;C</spanx></c>
 </texttable>
 
+</section>
+
+<section anchor="silk_nlsf_reconstruction"
+ title="Reconstructing the Normalized LSF Coefficients">
+<t>
+Once the stage-1 index I1 and the stage-2 residual res_Q10[] have been decoded,
+ the final normalized LSF coefficients can be reconstructed.
+</t>
 <t>
 The spectral distortion introduced by the quantization of each LSF coefficient
  varies, so the stage-2 residual is weighted accordingly, using the
 <t>
 The spectral distortion introduced by the quantization of each LSF coefficient
  varies, so the stage-2 residual is weighted accordingly, using the
- low-complexity weighting function proposed in <xref target="laroia-icassp"/>.
+ low-complexity Inverse Harmonic Mean Weighting (IHMW) function proposed in
+ <xref target="laroia-icassp"/>.
 The weights are derived directly from the stage-1 codebook vector.
 Let cb1_Q8[k] be the k'th entry of the stage-1 codebook vector from
  <xref target="silk_nlsf_nbmb_codebook"/> or
 The weights are derived directly from the stage-1 codebook vector.
 Let cb1_Q8[k] be the k'th entry of the stage-1 codebook vector from
  <xref target="silk_nlsf_nbmb_codebook"/> or
@@ -2301,7 +2343,7 @@ The reference implementation already requires code to compute these weights on
 <texttable anchor="silk_nlsf_nbmb_codebook"
            title="Codebook Vectors for NB/MB Normalized LSF Stage 1 Decoding">
 <ttcol>I1</ttcol>
 <texttable anchor="silk_nlsf_nbmb_codebook"
            title="Codebook Vectors for NB/MB Normalized LSF Stage 1 Decoding">
 <ttcol>I1</ttcol>
-<ttcol>Codebook</ttcol>
+<ttcol>Codebook (Q8)</ttcol>
 <c/>
 <c><spanx style="vbare">&nbsp;0&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;9</spanx></c>
 <c>0</c>
 <c/>
 <c><spanx style="vbare">&nbsp;0&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;9</spanx></c>
 <c>0</c>
@@ -2373,7 +2415,7 @@ The reference implementation already requires code to compute these weights on
 <texttable anchor="silk_nlsf_wb_codebook"
            title="Codebook Vectors for WB Normalized LSF Stage 1 Decoding">
 <ttcol>I1</ttcol>
 <texttable anchor="silk_nlsf_wb_codebook"
            title="Codebook Vectors for WB Normalized LSF Stage 1 Decoding">
 <ttcol>I1</ttcol>
-<ttcol>Codebook</ttcol>
+<ttcol>Codebook (Q8)</ttcol>
 <c/>
 <c><spanx style="vbare">&nbsp;0&nbsp;&nbsp;1&nbsp;&nbsp;2&nbsp;&nbsp;3&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;9&nbsp;&nbsp;10&nbsp;&nbsp;11&nbsp;&nbsp;12&nbsp;&nbsp;13&nbsp;&nbsp;14&nbsp;&nbsp;15</spanx></c>
 <c>0</c>
 <c/>
 <c><spanx style="vbare">&nbsp;0&nbsp;&nbsp;1&nbsp;&nbsp;2&nbsp;&nbsp;3&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;9&nbsp;&nbsp;10&nbsp;&nbsp;11&nbsp;&nbsp;12&nbsp;&nbsp;13&nbsp;&nbsp;14&nbsp;&nbsp;15</spanx></c>
 <c>0</c>
@@ -2461,6 +2503,8 @@ The next section describes a stabilization procedure used to make these
  guarantees.
 </t>
 
  guarantees.
 </t>
 
+</section>
+
 <section anchor="silk_nlsf_stabilization" title="Normalized LSF Stabilization">
 <t>
 The normalized LSF stabilization procedure is implemented in
 <section anchor="silk_nlsf_stabilization" title="Normalized LSF Stabilization">
 <t>
 The normalized LSF stabilization procedure is implemented in
@@ -2567,7 +2611,8 @@ min(NLSF_Q15[k], NLSF_Q15[k+1] - NDeltaMin_Q15[k+1]) .
 <t>
 For 20&nbsp;ms SILK frames, the first half of the frame (i.e., the first two
  subframes) may use normalized LSF coefficients that are interpolated between
 <t>
 For 20&nbsp;ms SILK frames, the first half of the frame (i.e., the first two
  subframes) may use normalized LSF coefficients that are interpolated between
- the decoded LSFs for the previous frame and the current frame.
+ the decoded LSFs for the most recent coded frame (in the same channel) and the
+ current frame.
 A Q2 interpolation factor follows the LSF coefficient indices in the bitstream,
  which is decoded using the PDF in <xref target="silk_nlsf_interp_pdf"/>.
 This happens in silk_decode_indices() (silk_decode_indices.c).
 A Q2 interpolation factor follows the LSF coefficient indices in the bitstream,
  which is decoded using the PDF in <xref target="silk_nlsf_interp_pdf"/>.
 This happens in silk_decode_indices() (silk_decode_indices.c).
@@ -2600,7 +2645,7 @@ This interpolation is performed in silk_decode_parameters()
 </section>
 
 <section anchor="silk_nlsf2lpc"
 </section>
 
 <section anchor="silk_nlsf2lpc"
        title="Converting Normalized LSF Coefficients to LPCs">
title="Converting Normalized LSFs to LPC Coefficients">
 <t>
 Any LPC filter A(z) can be split into a symmetric part P(z) and an
  anti-symmetric part Q(z) such that
 <t>
 Any LPC filter A(z) can be split into a symmetric part P(z) and an
  anti-symmetric part Q(z) such that
@@ -2798,7 +2843,7 @@ The promotion of the expression from Q16 to Q17 implicitly scales the result
 </t>
 </section>
 
 </t>
 </section>
 
-<section anchor="silk_lpc_range"
+<section anchor="silk_lpc_range_limit"
  title="Limiting the Range of the LPC Coefficients">
 <t>
 The a32_Q17[] coefficients are too large to fit in a 16-bit value, which
  title="Limiting the Range of the LPC Coefficients">
 <t>
 The a32_Q17[] coefficients are too large to fit in a 16-bit value, which
@@ -2872,7 +2917,8 @@ This saturation is not performed if maxabs_Q12 drops to 32767 or less prior to
 </t>
 </section>
 
 </t>
 </section>
 
-<section title="Limiting the Prediction Gain of the LPC Filter">
+<section anchor="silk_lpc_gain_limit"
+ title="Limiting the Prediction Gain of the LPC Filter">
 <t>
 Even if the Q12 coefficients would fit, the resulting filter may still have a
  significant gain (especially for voiced sounds), making the filter unstable.
 <t>
 Even if the Q12 coefficients would fit, the resulting filter may still have a
  significant gain (especially for voiced sounds), making the filter unstable.
@@ -2973,7 +3019,7 @@ a_Q12[k] = (a32_Q17[k] + 16) >> 5 .
 ]]></artwork>
 </figure>
 Otherwise, a round of bandwidth expansion is applied using the same procedure
 ]]></artwork>
 </figure>
 Otherwise, a round of bandwidth expansion is applied using the same procedure
- as in <xref target="silk_lpc_range"/>, with
+ as in <xref target="silk_lpc_range_limit"/>, with
 <figure align="center">
 <artwork align="center"><![CDATA[
 sc_Q16[0] = 65536 - i*(i+9) .
 <figure align="center">
 <artwork align="center"><![CDATA[
 sc_Q16[0] = 65536 - i*(i+9) .
@@ -3002,9 +3048,14 @@ Each subframe also gets its own prediction gain coefficient.
 The primary lag index is coded either relative to the primary lag of the prior
  frame or as an absolute index.
 Like the quantization gains, the first LBRR frame, an LBRR frame where the
 The primary lag index is coded either relative to the primary lag of the prior
  frame or as an absolute index.
 Like the quantization gains, the first LBRR frame, an LBRR frame where the
- previous LBRR frame was not coded, and the first regular SILK frame in an Opus
- frame all code the pitch lag as an absolute index.
-When the prior frame was not voiced, this also forces absolute coding.
+ previous LBRR frame was not coded, and the first regular SILK frame in each
+ channel of an Opus frame all code the pitch lag as an absolute index.
+When the most recent coded frame in the current channel was not voiced, this
+ also forces absolute coding.
+In particular, unlike an LBRR frame where the previous frame is not coded, in a
+ 60&nbsp;ms stereo Opus frame, if the first and third regular SILK frames
+ in the side channel are coded, voiced frames, but the second is not coded, the
+ third still uses relative coding.
 </t>
 <t>
 With absolute coding, the primary pitch lag may range from 2&nbsp;ms
 </t>
 <t>
 With absolute coding, the primary pitch lag may range from 2&nbsp;ms
@@ -3059,8 +3110,8 @@ Otherwise, the final primary pitch lag is then
 lag = lag_prev + (delta_lag_index - 9)
 ]]></artwork>
 </figure>
 lag = lag_prev + (delta_lag_index - 9)
 ]]></artwork>
 </figure>
- where lag_prev is the primary pitch lag from the previous frame and
- delta_lag_index is the value just decoded.
+ where lag_prev is the primary pitch lag from the most recent frame in the same
channel and delta_lag_index is the value just decoded.
 This allows a per-frame change in the pitch lag of -8 to +11 samples.
 The decoder does no clamping at this point, so this value can fall outside the
  range of 2&nbsp;ms to 18&nbsp;ms, and the decoder must use this unclamped
 This allows a per-frame change in the pitch lag of -8 to +11 samples.
 The decoder does no clamping at this point, so this value can fall outside the
  range of 2&nbsp;ms to 18&nbsp;ms, and the decoder must use this unclamped
@@ -3221,8 +3272,21 @@ pitch_lags[k] = clamp(lag_min, lag + lag_cb[contour_index][k],
 <t>
 SILK can use a separate 5-tap pitch filter for each subframe.
 It selects the filter to use from one of three codebooks.
 <t>
 SILK can use a separate 5-tap pitch filter for each subframe.
 It selects the filter to use from one of three codebooks.
-All of the subframes in a SILK frame must choose their filter from the same
- codebook, itself chosen via an explicitly-coded "periodicity index".
+The three codebooks each represent different rate-distortion trade-offs, with
+ average rates of 1.61&nbsp;bits/subframe, 3.68&nbsp;bits/subframe, and
+ 4.85&nbsp;bits/subframe, respectively.
+</t>
+
+<t>
+The importance of the filter coefficients generally depends on two factors: the
+ periodicity of the signal and relative energy between the current subframe and
+ the signal from one period earlier.
+Greater periodicity and decaying energy both lead to more important filter
+ coefficients, and thus should be coded with lower distortion and higher rate.
+These properties are relatively stable over the duration of a single SILK
+ frame, hence all of the subframes in a SILK frame must choose their filter
+ from the same codebook.
+This is signaled with an explicitly-coded "periodicity index".
 This immediately follows the subframe pitch lags, and is coded using the
  3-entry PDF from <xref target="silk_perindex_pdf"/>.
 </t>
 This immediately follows the subframe pitch lags, and is coded using the
  3-entry PDF from <xref target="silk_perindex_pdf"/>.
 </t>
@@ -3233,7 +3297,7 @@ This immediately follows the subframe pitch lags, and is coded using the
 </texttable>
 
 <t>
 </texttable>
 
 <t>
-The index of the filter for use for each subframe follows.
+The index of the filter to use for each subframe follows.
 They are all coded using the PDF from <xref target="silk_ltp_filter_pdfs"/>
  corresponding to the periodicity index.
 <xref target="silk_ltp_filter_coeffs0"/> through
 They are all coded using the PDF from <xref target="silk_ltp_filter_pdfs"/>
  corresponding to the periodicity index.
 <xref target="silk_ltp_filter_coeffs0"/> through
@@ -3395,10 +3459,11 @@ This allows the encoder to trade off the prediction gain between
  packets against the recovery time after packet loss.
 Like the quantization gains, only the first LBRR frame in an Opus frame,
  an LBRR frame where the prior LBRR frame was not coded, and the first regular
  packets against the recovery time after packet loss.
 Like the quantization gains, only the first LBRR frame in an Opus frame,
  an LBRR frame where the prior LBRR frame was not coded, and the first regular
- SILK frame in an Opus frame include this field, and, like all of the other
- LTP parameters, only for frames that are also voiced.
+ SILK frame in each channel of an Opus frame include this field, and, like all
of the other LTP parameters, only for frames that are also voiced.
 Unlike absolute-coding for pitch lags, a regular SILK frame other than the
 Unlike absolute-coding for pitch lags, a regular SILK frame other than the
- first one will not include this field even if the prior frame was not voiced.
+ first one in a channel will not include this field even if the prior frame was
+ not voiced.
 </t>
 <t>
 If present, the value is coded using the 3-entry PDF in
 </t>
 <t>
 If present, the value is coded using the 3-entry PDF in
@@ -3751,42 +3816,42 @@ In that case, any non-zero coefficients use a positive sign.
 <ttcol>Quantization Offset Type</ttcol>
 <ttcol>Pulse Count</ttcol>
 <ttcol>PDF</ttcol>
 <ttcol>Quantization Offset Type</ttcol>
 <ttcol>Pulse Count</ttcol>
 <ttcol>PDF</ttcol>
-<c>Inactive</c> <c>0</c> <c>1</c>         <c>{207, 49}/256</c>
-<c>Inactive</c> <c>0</c> <c>2</c>         <c>{189, 67}/256</c>
-<c>Inactive</c> <c>0</c> <c>3</c>         <c>{179, 77}/256</c>
-<c>Inactive</c> <c>0</c> <c>4</c>         <c>{174, 82}/256</c>
-<c>Inactive</c> <c>0</c> <c>5</c>         <c>{163, 93}/256</c>
-<c>Inactive</c> <c>0</c> <c>6 or more</c> <c>{157, 99}/256</c>
-<c>Inactive</c> <c>1</c> <c>1</c>         <c>{245, 11}/256</c>
-<c>Inactive</c> <c>1</c> <c>2</c>         <c>{238, 18}/256</c>
-<c>Inactive</c> <c>1</c> <c>3</c>         <c>{232, 24}/256</c>
-<c>Inactive</c> <c>1</c> <c>4</c>         <c>{225, 31}/256</c>
-<c>Inactive</c> <c>1</c> <c>5</c>         <c>{220, 36}/256</c>
-<c>Inactive</c> <c>1</c> <c>6 or more</c> <c>{211, 45}/256</c>
-<c>Unvoiced</c> <c>0</c> <c>1</c>         <c>{210, 46}/256</c>
-<c>Unvoiced</c> <c>0</c> <c>2</c>         <c>{190, 66}/256</c>
-<c>Unvoiced</c> <c>0</c> <c>3</c>         <c>{178, 78}/256</c>
-<c>Unvoiced</c> <c>0</c> <c>4</c>         <c>{169, 87}/256</c>
-<c>Unvoiced</c> <c>0</c> <c>5</c>         <c>{162, 94}/256</c>
-<c>Unvoiced</c> <c>0</c> <c>6 or more</c> <c>{152, 104}/256</c>
-<c>Unvoiced</c> <c>1</c> <c>1</c>         <c>{242, 14}/256</c>
-<c>Unvoiced</c> <c>1</c> <c>2</c>         <c>{235, 21}/256</c>
-<c>Unvoiced</c> <c>1</c> <c>3</c>         <c>{224, 32}/256</c>
-<c>Unvoiced</c> <c>1</c> <c>4</c>         <c>{214, 42}/256</c>
-<c>Unvoiced</c> <c>1</c> <c>5</c>         <c>{205, 51}/256</c>
-<c>Unvoiced</c> <c>1</c> <c>6 or more</c> <c>{190, 66}/256</c>
-<c>Voiced</c>   <c>0</c> <c>1</c>         <c>{162, 94}/256</c>
-<c>Voiced</c>   <c>0</c> <c>2</c>         <c>{152, 104}/256</c>
-<c>Voiced</c>   <c>0</c> <c>3</c>         <c>{147, 109}/256</c>
-<c>Voiced</c>   <c>0</c> <c>4</c>         <c>{144, 112}/256</c>
-<c>Voiced</c>   <c>0</c> <c>5</c>         <c>{141, 115}/256</c>
-<c>Voiced</c>   <c>0</c> <c>6 or more</c> <c>{138, 118}/256</c>
-<c>Voiced</c>   <c>1</c> <c>1</c>         <c>{203, 53}/256</c>
-<c>Voiced</c>   <c>1</c> <c>2</c>         <c>{187, 69}/256</c>
-<c>Voiced</c>   <c>1</c> <c>3</c>         <c>{176, 80}/256</c>
-<c>Voiced</c>   <c>1</c> <c>4</c>         <c>{168, 88}/256</c>
-<c>Voiced</c>   <c>1</c> <c>5</c>         <c>{161, 95}/256</c>
-<c>Voiced</c>   <c>1</c> <c>6 or more</c> <c>{154, 102}/256</c>
+<c>Inactive</c> <c>Low</c>  <c>1</c>         <c>{207, 49}/256</c>
+<c>Inactive</c> <c>Low</c>  <c>2</c>         <c>{189, 67}/256</c>
+<c>Inactive</c> <c>Low</c>  <c>3</c>         <c>{179, 77}/256</c>
+<c>Inactive</c> <c>Low</c>  <c>4</c>         <c>{174, 82}/256</c>
+<c>Inactive</c> <c>Low</c>  <c>5</c>         <c>{163, 93}/256</c>
+<c>Inactive</c> <c>Low</c>  <c>6 or more</c> <c>{157, 99}/256</c>
+<c>Inactive</c> <c>High</c> <c>1</c>         <c>{245, 11}/256</c>
+<c>Inactive</c> <c>High</c> <c>2</c>         <c>{238, 18}/256</c>
+<c>Inactive</c> <c>High</c> <c>3</c>         <c>{232, 24}/256</c>
+<c>Inactive</c> <c>High</c> <c>4</c>         <c>{225, 31}/256</c>
+<c>Inactive</c> <c>High</c> <c>5</c>         <c>{220, 36}/256</c>
+<c>Inactive</c> <c>High</c> <c>6 or more</c> <c>{211, 45}/256</c>
+<c>Unvoiced</c> <c>Low</c>  <c>1</c>         <c>{210, 46}/256</c>
+<c>Unvoiced</c> <c>Low</c>  <c>2</c>         <c>{190, 66}/256</c>
+<c>Unvoiced</c> <c>Low</c>  <c>3</c>         <c>{178, 78}/256</c>
+<c>Unvoiced</c> <c>Low</c>  <c>4</c>         <c>{169, 87}/256</c>
+<c>Unvoiced</c> <c>Low</c>  <c>5</c>         <c>{162, 94}/256</c>
+<c>Unvoiced</c> <c>Low</c>  <c>6 or more</c> <c>{152, 104}/256</c>
+<c>Unvoiced</c> <c>High</c> <c>1</c>         <c>{242, 14}/256</c>
+<c>Unvoiced</c> <c>High</c> <c>2</c>         <c>{235, 21}/256</c>
+<c>Unvoiced</c> <c>High</c> <c>3</c>         <c>{224, 32}/256</c>
+<c>Unvoiced</c> <c>High</c> <c>4</c>         <c>{214, 42}/256</c>
+<c>Unvoiced</c> <c>High</c> <c>5</c>         <c>{205, 51}/256</c>
+<c>Unvoiced</c> <c>High</c> <c>6 or more</c> <c>{190, 66}/256</c>
+<c>Voiced</c>   <c>Low</c>  <c>1</c>         <c>{162, 94}/256</c>
+<c>Voiced</c>   <c>Low</c>  <c>2</c>         <c>{152, 104}/256</c>
+<c>Voiced</c>   <c>Low</c>  <c>3</c>         <c>{147, 109}/256</c>
+<c>Voiced</c>   <c>Low</c>  <c>4</c>         <c>{144, 112}/256</c>
+<c>Voiced</c>   <c>Low</c>  <c>5</c>         <c>{141, 115}/256</c>
+<c>Voiced</c>   <c>Low</c>  <c>6 or more</c> <c>{138, 118}/256</c>
+<c>Voiced</c>   <c>High</c> <c>1</c>         <c>{203, 53}/256</c>
+<c>Voiced</c>   <c>High</c> <c>2</c>         <c>{187, 69}/256</c>
+<c>Voiced</c>   <c>High</c> <c>3</c>         <c>{176, 80}/256</c>
+<c>Voiced</c>   <c>High</c> <c>4</c>         <c>{168, 88}/256</c>
+<c>Voiced</c>   <c>High</c> <c>5</c>         <c>{161, 95}/256</c>
+<c>Voiced</c>   <c>High</c> <c>6 or more</c> <c>{154, 102}/256</c>
 </texttable>
 
 </section>
 </texttable>
 
 </section>
@@ -4159,7 +4224,7 @@ of K that produces the number of bits nearest to the allocated value
 (rounding down if exactly halfway between two values), not to exceed
 the total number of bits available. For efficiency reasons, the search is performed against a
 precomputed allocation table which only permits some K values for each N. The number of
 (rounding down if exactly halfway between two values), not to exceed
 the total number of bits available. For efficiency reasons, the search is performed against a
 precomputed allocation table which only permits some K values for each N. The number of
-codebook entries can be computed as explained in <xref target="cwrs-encoding"></xref>. The difference
+codebook entries can be computed as explained in <xref target="cwrs-decoder"></xref>. The difference
 between the number of bits allocated and the number of bits used is accumulated to a
 "balance" (initialized to zero) that helps adjust the
 allocation for the next bands. One third of the balance is applied to the
 between the number of bits allocated and the number of bits used is accumulated to a
 "balance" (initialized to zero) that helps adjust the
 allocation for the next bands. One third of the balance is applied to the
@@ -4194,12 +4259,60 @@ they are equivalent to the mathematical definition.
 <t>
 The decoding of the codeword from the index is performed as specified in
 <xref target="PVQ"></xref>, as implemented in function
 <t>
 The decoding of the codeword from the index is performed as specified in
 <xref target="PVQ"></xref>, as implemented in function
-decode_pulses() (cwrs.c).
+decode_pulses() (cwrs.c). The decoded codeword is then normalised such that it's
+L2-norm equals one.
 </t>
 </section>
 
 <section anchor="spreading" title="Spreading">
 <t>
 </t>
 </section>
 
 <section anchor="spreading" title="Spreading">
 <t>
+The normalised vector decoded in <xref target="cwrs-decoder"/> is then rotated
+for the purpose of avoiding tonal artefacts. The rotation gain is equal to
+<figure align="center">
+<artwork align="center"><![CDATA[
+g_r = N / (N + f_r*K)
+]]></artwork>
+</figure>
+
+where N is the number of dimensions, K is the number of pulses, and f_r depends on
+the value of the "spread" parameter in the bit-stream.
+</t>
+
+<texttable anchor="spread values" title="Spreading values">
+<ttcol>Spread value</ttcol>
+<ttcol>f_r</ttcol>
+ <c>0</c> <c>infinite (no rotation)</c>
+ <c>1</c> <c>15</c>
+ <c>2</c> <c>10</c>
+ <c>3</c> <c>5</c>
+</texttable>
+
+<t>
+The rotation angle is then calculated as
+<figure align="center">
+<artwork align="center"><![CDATA[
+                 2
+        pi *  g_r
+theta = ----------
+            4
+]]></artwork>
+</figure>
+A 2-D rotation R(i,j) between points x_i and x_j is defined as:
+<figure align="center">
+<artwork align="center"><![CDATA[
+x_i' =  cos(theta)*x_i + sin(theta)*x_j
+x_j' = -sin(theta)*x_i + cos(theta)*x_j
+]]></artwork>
+</figure>
+
+An N-D rotation is then achieved by applying a series of 2-D rotations back and forth, in the
+following order: R(x_1, x_2), R(x_2, x_3), ..., R(x_N-2, X_N-1), R(x_N-1, X_N),
+R(x_N-2, X_N-1), ..., R(x_1, x_2).
+</t>
+
+<t>
+If the decoded vector represents more
+than one time block, then the following process is applied separately on each time block.
 </t>
 </section>
 
 </t>
 </section>
 
@@ -4248,13 +4361,37 @@ multiplied by the square root of the decoded energy. This is done by denormalise
 </section>
 
 <section anchor="inverse-mdct" title="Inverse MDCT">
 </section>
 
 <section anchor="inverse-mdct" title="Inverse MDCT">
+
+
+<t>The MDCT implementation has no special characteristics. The
+input is a windowed signal (after pre-emphasis) of 2*N samples and the output is N
+frequency-domain samples. A "low-overlap" window is used to reduce the algorithmic delay.
+It is derived from a basic (full overlap) window that is the same as the one used in the Vorbis codec:
+<figure align="center">
+<artwork align="center"><![CDATA[
+            pi       pi   n + 1/2   2
+W(n) = [sin(-- * sin(-- * -------))] .
+            2        2       L
+]]></artwork>
+</figure>
+The low-overlap window is created by zero-padding the basic window and inserting ones in the middle, such that the resulting window still satisfies power complementarity. The MDCT is computed in mdct_forward() (mdct.c), which includes the windowing operation and a scaling of 2/N.
+</t>
+
+
 <t>The inverse MDCT implementation has no special characteristics. The
 input is N frequency-domain samples and the output is 2*N time-domain
 <t>The inverse MDCT implementation has no special characteristics. The
 input is N frequency-domain samples and the output is 2*N time-domain
-samples, while scaling by 1/2. The output is windowed using the same window
-as the encoder. The IMDCT and windowing are performed by mdct_backward
-(mdct.c). If a time-domain pre-emphasis
-window was applied in the encoder, the (inverse) time-domain de-emphasis window
-is applied on the IMDCT result.
+samples, while scaling by 1/2. A "low-overlap" window is used to reduce the algorithmic delay.
+It is derived from a basic (full overlap) 240-sample version of the window used by the Vorbis codec:
+<figure align="center">
+<artwork align="center"><![CDATA[
+            pi       pi   n + 1/2   2
+W(n) = [sin(-- * sin(-- * -------))] .
+            2        2       L
+]]></artwork>
+</figure>
+The low-overlap window is created by zero-padding the basic window and inserting ones in the 
+middle, such that the resulting window still satisfies power complementarity. The IMDCT and 
+windowing are performed by mdct_backward (mdct.c).
 </t>
 
 <section anchor="post-filter" title="Post-filter">
 </t>
 
 <section anchor="post-filter" title="Post-filter">
@@ -4407,11 +4544,11 @@ Opus encoder block diagram.
       |  |conversion|    |       |  |
 audio |  +----------+    +-------+  |    +-------+
 ------+                             +--->| Range |
       |  |conversion|    |       |  |
 audio |  +----------+    +-------+  |    +-------+
 ------+                             +--->| Range |
-      |  +-------+                       |encoder|---->
-      |  | CELT  |                  +--->|       | bitstream
-      +->|encoder|------------------+    +-------+
-         |       |
-         +-------+
+      |  +------------+  +-------+       |encoder|---->
+      |  |   Delay    |  | CELT  |  +--->|       | bitstream
+      +->|Compensation|->|encoder|--+    +-------+
+         |            |  |       |
+         +------------+  +-------+
 ]]>
 </artwork>
 </figure>
 ]]>
 </artwork>
 </figure>
@@ -4430,7 +4567,7 @@ used in three different ways, to encode:
 
 <t>
 The range encoder maintains an internal state vector composed of the
 
 <t>
 The range encoder maintains an internal state vector composed of the
-four-tuple (low,rng,rem,ext), representing the low end of the current
+four-tuple (low,rng,rem,ext) representing the low end of the current
 range, the size of the current range, a single buffered output octet,
 and a count of additional carry-propagating output octets. Both rng
 and low are 32-bit unsigned integer values, rem is an octet value or
 range, the size of the current range, a single buffered output octet,
 and a count of additional carry-propagating output octets. Both rng
 and low are 32-bit unsigned integer values, rem is an octet value or
@@ -4504,7 +4641,7 @@ fl=sum(f(i),i<k), fh=fl+f(i), and ft=sum(f(i)).
    The raw bits are packed at the end of the packet, starting by storing the
    least significant bit of the value to be packed in the least significant bit
    of the last byte, filling up to the most significant bit in
    The raw bits are packed at the end of the packet, starting by storing the
    least significant bit of the value to be packed in the least significant bit
    of the last byte, filling up to the most significant bit in
-   the last byte, and the continuing in the least significant bit of the
+   the last byte, and then continuing in the least significant bit of the
    penultimate byte, and so on.
    This packing may continue into the last byte output by the range coder,
    though the format should render it impossible to overwrite any set bit
    penultimate byte, and so on.
    This packing may continue into the last byte output by the range coder,
    though the format should render it impossible to overwrite any set bit
@@ -4640,7 +4777,7 @@ fl=sum(f(i),i<k), fh=fl+f(i), and ft=sum(f(i)).
 
           <section title='Voice Activity Detection'>
             <t>
 
           <section title='Voice Activity Detection'>
             <t>
-              The input signal is processed by a VAD (Voice Activity Detector) to produce a measure of voice activity, and also spectral tilt and signal-to-noise estimates, for each frame. The VAD uses a sequence of half-band filterbanks to split the signal in four subbands: 0 - Fs/16, Fs/16 - Fs/8, Fs/8 - Fs/4, and Fs/4 - Fs/2, where Fs is the sampling frequency, that is, 8, 12, 16, or 24&nbsp;kHz. The lowest subband, from 0 - Fs/16 is high-pass filtered with a first-order MA (Moving Average) filter (with transfer function H(z) = 1-z**(-1)) to reduce the energy at the lowest frequencies. For each frame, the signal energy per subband is computed. In each subband, a noise level estimator tracks the background noise level and an SNR (Signal-to-Noise Ratio) value is computed as the logarithm of the ratio of energy to noise level. Using these intermediate variables, the following parameters are calculated for use in other SILK modules:
+              The input signal is processed by a Voice Activity Detector (VAD) to produce a measure of voice activity, spectral tilt, and signal-to-noise estimates for each frame. The VAD uses a sequence of half-band filterbanks to split the signal into four subbands: 0 - Fs/16, Fs/16 - Fs/8, Fs/8 - Fs/4, and Fs/4 - Fs/2, where Fs is the sampling frequency (8, 12, 16, or 24&nbsp;kHz). The lowest subband, from 0 - Fs/16, is high-pass filtered with a first-order moving average (MA) filter (with transfer function H(z) = 1-z**(-1)) to reduce the energy at the lowest frequencies. For each frame, the signal energy per subband is computed. In each subband, a noise level estimator tracks the background noise level and a Signal-to-Noise Ratio (SNR) value is computed as the logarithm of the ratio of energy to noise level. Using these intermediate variables, the following parameters are calculated for use in other SILK modules:
               <list style="symbols">
                 <t>
                   Average SNR. The average of the subband SNR values.
               <list style="symbols">
                 <t>
                   Average SNR. The average of the subband SNR values.
@@ -4663,7 +4800,7 @@ fl=sum(f(i),i<k), fh=fl+f(i), and ft=sum(f(i)).
 
           <section title='High-Pass Filter'>
             <t>
 
           <section title='High-Pass Filter'>
             <t>
-              The input signal is filtered by a high-pass filter to remove the lowest part of the spectrum that contains little speech energy and may contain background noise. This is a second order ARMA (Auto Regressive Moving Average) filter with a cut-off frequency around 70&nbsp;Hz.
+              The input signal is filtered by a high-pass filter to remove the lowest part of the spectrum that contains little speech energy and may contain background noise. This is a second order Auto Regressive Moving Average (ARMA) filter with a cut-off frequency around 70&nbsp;Hz.
             </t>
             <t>
               In the future, a music detector may also be used to lower the cut-off frequency when the input signal is detected to be music rather than speech.
             </t>
             <t>
               In the future, a music detector may also be used to lower the cut-off frequency when the input signal is detected to be music rather than speech.
@@ -4712,7 +4849,7 @@ fl=sum(f(i),i<k), fh=fl+f(i), and ft=sum(f(i)).
                 <t>In the first stage, the whitened signal is downsampled to 4&nbsp;kHz (from 8&nbsp;kHz) and the current frame is correlated to a signal delayed by a range of lags, starting from a shortest lag corresponding to 500&nbsp;Hz, to a longest lag corresponding to 56&nbsp;Hz.</t>
 
                 <t>
                 <t>In the first stage, the whitened signal is downsampled to 4&nbsp;kHz (from 8&nbsp;kHz) and the current frame is correlated to a signal delayed by a range of lags, starting from a shortest lag corresponding to 500&nbsp;Hz, to a longest lag corresponding to 56&nbsp;Hz.</t>
 
                 <t>
-                  The second stage operates on a 8&nbsp;kHz signal ( downsampled from 12, 16, or 24&nbsp;kHz ) and measures time correlations only near the lags corresponding to those that had sufficiently high correlations in the first stage. The resulting correlations are adjusted for a small bias towards short lags to avoid ending up with a multiple of the true pitch lag. The highest adjusted correlation is compared to a threshold depending on:
+                  The second stage operates on an 8&nbsp;kHz signal (downsampled from 12, 16, or 24&nbsp;kHz) and measures time correlations only near the lags corresponding to those that had sufficiently high correlations in the first stage. The resulting correlations are adjusted for a small bias towards short lags to avoid ending up with a multiple of the true pitch lag. The highest adjusted correlation is compared to a threshold depending on:
                   <list style="symbols">
                     <t>
                       Whether the previous frame was classified as voiced
                   <list style="symbols">
                     <t>
                       Whether the previous frame was classified as voiced
@@ -4815,7 +4952,7 @@ Wsyn(z) = (1 - \ (a_syn(k) * z  )*(1 - z  * \ b_syn(k) * z  ).
               </figure>
             </t>
             <t>
               </figure>
             </t>
             <t>
-              All noise shaping parameters are computed and applied per subframe of 5 milliseconds. First, an LPC analysis is performed on a windowed signal block of 15 milliseconds. The signal block has a look-ahead of 5 milliseconds relative to the current subframe, and the window is an asymmetric sine window. The LPC analysis is done with the autocorrelation method, with an order of 16 for best quality or 12 in low complexity operation. The quantization gain is found as the square-root of the residual energy from the LPC analysis, multiplied by a value inversely proportional to the coding quality control parameter and the pitch correlation.
+              All noise shaping parameters are computed and applied per subframe of 5&nbsp;ms. First, an LPC analysis is performed on a windowed signal block of 15&nbsp;ms. The signal block has a look-ahead of 5&nbsp;ms relative to the current subframe, and the window is an asymmetric sine window. The LPC analysis is done with the autocorrelation method, with an order of 16 for best quality or 12 in low complexity operation. The quantization gain is found by taking the square root of the residual energy from the LPC analysis and multiplying it by a value inversely proportional to the coding quality control parameter and the pitch correlation.
             </t>
             <t>
               Next we find the two sets of short-term noise shaping coefficients a_ana(k) and a_syn(k), by applying different amounts of bandwidth expansion to the coefficients found in the LPC analysis. This bandwidth expansion moves the roots of the LPC polynomial towards the origin, using the formulas
             </t>
             <t>
               Next we find the two sets of short-term noise shaping coefficients a_ana(k) and a_syn(k), by applying different amounts of bandwidth expansion to the coefficients found in the LPC analysis. This bandwidth expansion moves the roots of the LPC polynomial towards the origin, using the formulas
@@ -4830,7 +4967,7 @@ Wsyn(z) = (1 - \ (a_syn(k) * z  )*(1 - z  * \ b_syn(k) * z  ).
             ]]>
                 </artwork>
               </figure>
             ]]>
                 </artwork>
               </figure>
-              where a(k) is the k'th LPC coefficient and the bandwidth expansion factors g_ana and g_syn are calculated as
+              where a(k) is the k'th LPC coefficient, and the bandwidth expansion factors g_ana and g_syn are calculated as
               <figure align="center">
                 <artwork align="center">
                   <![CDATA[
               <figure align="center">
                 <artwork align="center">
                   <![CDATA[
@@ -4871,7 +5008,7 @@ c_tilt = 0.04 + 0.06 * C
               for voiced frames, where C again is the coding quality control parameter and is between 0 and 1.
             </t>
             <t>
               for voiced frames, where C again is the coding quality control parameter and is between 0 and 1.
             </t>
             <t>
-              The adjustment gain G serves to correct any level mismatch between original and decoded signal that might arise from the noise shaping and de-emphasis. This gain is computed as the ratio of the prediction gain of the short-term analysis and synthesis filter coefficients. The prediction gain of an LPC synthesis filter is the square-root of the output energy when the filter is excited by a unit-energy impulse on the input. An efficient way to compute the prediction gain is by first computing the reflection coefficients from the LPC coefficients through the step-down algorithm, and extracting the prediction gain from the reflection coefficients as
+              The adjustment gain G serves to correct any level mismatch between the original and decoded signals that might arise from the noise shaping and de-emphasis. This gain is computed as the ratio of the prediction gain of the short-term analysis and synthesis filter coefficients. The prediction gain of an LPC synthesis filter is the square root of the output energy when the filter is excited by a unit-energy impulse on the input. An efficient way to compute the prediction gain is by first computing the reflection coefficients from the LPC coefficients through the step-down algorithm, and extracting the prediction gain from the reflection coefficients as
               <figure align="center">
                 <artwork align="center">
                   <![CDATA[
               <figure align="center">
                 <artwork align="center">
                   <![CDATA[
@@ -4892,35 +5029,35 @@ c_tilt = 0.04 + 0.06 * C
 
           <section title='Prefilter'>
             <t>
 
           <section title='Prefilter'>
             <t>
-              In the prefilter the input signal is filtered using the spectral valley de-emphasis filter coefficients from the noise shaping analysis, see <xref target='noise_shaping_analysis_overview_section' />. By applying only the noise shaping analysis filter to the input signal, it provides the input to the noise shaping quantizer.
+              In the prefilter the input signal is filtered using the spectral valley de-emphasis filter coefficients from the noise shaping analysis (see <xref target='noise_shaping_analysis_overview_section'/>). By applying only the noise shaping analysis filter to the input signal, it provides the input to the noise shaping quantizer.
             </t>
           </section>
           <section title='Prediction Analysis' anchor='pred_ana_overview_section'>
             <t>
             </t>
           </section>
           <section title='Prediction Analysis' anchor='pred_ana_overview_section'>
             <t>
-              The prediction analysis is performed in one of two ways depending on how the pitch estimator classified the frame. The processing for voiced and unvoiced speech are described in <xref target='pred_ana_voiced_overview_section' /> and <xref target='pred_ana_unvoiced_overview_section' />, respectively. Inputs to this function include the pre-whitened signal from the pitch estimator, see <xref target='pitch_estimator_overview_section' />.
+              The prediction analysis is performed in one of two ways depending on how the pitch estimator classified the frame. The processing for voiced and unvoiced speech is described in <xref target='pred_ana_voiced_overview_section' /> and <xref target='pred_ana_unvoiced_overview_section' />, respectively. Inputs to this function include the pre-whitened signal from the pitch estimator (see <xref target='pitch_estimator_overview_section'/>).
             </t>
 
             <section title='Voiced Speech' anchor='pred_ana_voiced_overview_section'>
               <t>
             </t>
 
             <section title='Voiced Speech' anchor='pred_ana_voiced_overview_section'>
               <t>
-                For a frame of voiced speech the pitch pulses will remain dominant in the pre-whitened input signal. Further whitening is desirable as it leads to higher quality at the same available bitrate. To achieve this, a Long-Term Prediction (LTP) analysis is carried out to estimate the coefficients of a fifth order LTP filter for each of four subframes. The LTP coefficients are used to find an LTP residual signal with the simulated output signal as input to obtain better modeling of the output signal. This LTP residual signal is the input to an LPC analysis where the LPCs are estimated using Burgs method, such that the residual energy is minimized. The estimated LPCs are converted to a Line Spectral Frequency (LSF) vector, and quantized as described in <xref target='lsf_quantizer_overview_section' />. After quantization, the quantized LSF vector is converted to LPC coefficients and hence by using these quantized coefficients the encoder remains fully synchronized with the decoder. The LTP coefficients are quantized using a method described in <xref target='ltp_quantizer_overview_section' />. The quantized LPC and LTP coefficients are now used to filter the high-pass filtered input signal and measure a residual energy for each of the four subframes.
+                For a frame of voiced speech the pitch pulses will remain dominant in the pre-whitened input signal. Further whitening is desirable as it leads to higher quality at the same available bitrate. To achieve this, a Long-Term Prediction (LTP) analysis is carried out to estimate the coefficients of a fifth-order LTP filter for each of four subframes. The LTP coefficients are used to find an LTP residual signal with the simulated output signal as input to obtain better modeling of the output signal. This LTP residual signal is the input to an LPC analysis where the LPCs are estimated using Burg's method, such that the residual energy is minimized. The estimated LPCs are converted to a Line Spectral Frequency (LSF) vector and quantized as described in <xref target='lsf_quantizer_overview_section' />. After quantization, the quantized LSF vector is converted back to LPC coefficients using the full procedure in <xref target="silk_nlsfs"/>. By using LPC coefficients derived from the quantized LSF coefficients, the encoder remains fully synchronized with the decoder. The LTP coefficients are quantized using a method described in <xref target='ltp_quantizer_overview_section' />. The quantized LPC and LTP coefficients are then used to filter the high-pass filtered input signal and measure residual energy for each of the four subframes.
               </t>
             </section>
             <section title='Unvoiced Speech' anchor='pred_ana_unvoiced_overview_section'>
               <t>
               </t>
             </section>
             <section title='Unvoiced Speech' anchor='pred_ana_unvoiced_overview_section'>
               <t>
-                For a speech signal that has been classified as unvoiced there is no need for LTP filtering as it has already been determined that the pre-whitened input signal is not periodic enough within the allowed pitch period range for an LTP analysis to be worth-while the cost in terms of complexity and rate. Therefore, the pre-whitened input signal is discarded and instead the high-pass filtered input signal is used for LPC analysis using Burgs method. The resulting LPC coefficients are converted to an LSF vector, quantized as described in the following section and transformed back to obtain quantized LPC coefficients. The quantized LPC coefficients are used to filter the high-pass filtered input signal and measure a residual energy for each of the four subframes.
+                For a speech signal that has been classified as unvoiced, there is no need for LTP filtering, as it has already been determined that the pre-whitened input signal is not periodic enough within the allowed pitch period range for LTP analysis to be worth the cost in terms of complexity and rate. The pre-whitened input signal is therefore discarded, and instead the high-pass filtered input signal is used for LPC analysis using Burg's method. The resulting LPC coefficients are converted to an LSF vector and quantized as described in the following section. They are then transformed back to obtain quantized LPC coefficients, which are then used to filter the high-pass filtered input signal and measure residual energy for each of the four subframes.
               </t>
             </section>
           </section>
 
           <section title='LSF Quantization' anchor='lsf_quantizer_overview_section'>
               </t>
             </section>
           </section>
 
           <section title='LSF Quantization' anchor='lsf_quantizer_overview_section'>
-            <t>The purpose of quantization in general is to significantly lower the bit rate at the cost of some introduced distortion. A higher rate should always result in lower distortion, and lowering the rate will generally lead to higher distortion. A commonly used but generally sub-optimal approach is to use a quantization method with a constant rate where only the error is minimized when quantizing.</t>
+            <t>In general, the purpose of quantization is to significantly lower the bitrate at the cost of introducing some distortion. A higher rate should always result in lower distortion, and lowering the rate will generally lead to higher distortion. A commonly used but generally suboptimal approach is to use a quantization method with a constant rate, where only the error is minimized when quantizing.</t>
             <section title='Rate-Distortion Optimization'>
             <section title='Rate-Distortion Optimization'>
-              <t>Instead, we minimize an objective function that consists of a weighted sum of rate and distortion, and use a codebook with an associated non-uniform rate table. Thus, we take into account that the probability mass function for selecting the codebook entries are by no means guaranteed to be uniform in our scenario. The advantage of this approach is that it ensures that rarely used codebook vector centroids, which are modeling statistical outliers in the training set can be quantized with a low error but with a relatively high cost in terms of a high rate. At the same time this approach also provides the advantage that frequently used centroids are modeled with low error and a relatively low rate. This approach will lead to equal or lower distortion than the fixed rate codebook at any given average rate, provided that the data is similar to the data used for training the codebook.</t>
+              <t>Instead, we minimize an objective function that consists of a weighted sum of rate and distortion, and use a codebook with an associated non-uniform rate table. Thus, we take into account that the probability mass function for selecting the codebook entries is by no means guaranteed to be uniform in our scenario. This approach has several advantages. It ensures that rarely used codebook vector centroids, which are modeling statistical outliers in the training set, are quantized with low error at the expense of a high rate. At the same time, it allows modeling frequently used centroids with low error and a relatively low rate. This approach leads to equal or lower distortion than the fixed-rate codebook at any given average rate, provided that the data is similar to that used for training the codebook.</t>
             </section>
 
             <section title='Error Mapping' anchor='lsf_error_mapping_overview_section'>
               <t>
             </section>
 
             <section title='Error Mapping' anchor='lsf_error_mapping_overview_section'>
               <t>
-                Instead of minimizing the error in the LSF domain, we map the errors to better approximate spectral distortion by applying an individual weight to each element in the error vector. The weight vectors are calculated for each input vector using the Inverse Harmonic Mean Weighting (IHMW) function proposed by Laroia et al., see <xref target="laroia-icassp" />.
+                Instead of minimizing the error in the LSF domain, we map the errors to better approximate spectral distortion by applying an individual weight to each element in the error vector. The weight vectors are calculated for each input vector using the Inverse Harmonic Mean Weighting (IHMW) function proposed by Laroia et al. (see <xref target="laroia-icassp" />).
                 Consequently, we solve the following minimization problem, i.e.,
                 <figure align="center">
                   <artwork align="center">
                 Consequently, we solve the following minimization problem, i.e.,
                 <figure align="center">
                   <artwork align="center">
@@ -4935,7 +5072,7 @@ LSF_q = argmin { (LSF - c)' * W * (LSF - c) + mu * rate },
             </section>
             <section title='Multi-Stage Vector Codebook'>
               <t>
             </section>
             <section title='Multi-Stage Vector Codebook'>
               <t>
-                We arrange the codebook in a multiple stage structure to achieve a quantizer that is both memory efficient and highly scalable in terms of computational complexity, see e.g. <xref target="sinervo-norsig" />. In the first stage the input is the LSF vector to be quantized, and in any other stage s > 1, the input is the quantization error from the previous stage, see <xref target='lsf_quantizer_structure_overview_figure' />.
+                We arrange the codebook in a multiple-stage structure to achieve a quantizer that is both memory efficient and highly scalable in terms of computational complexity (see, e.g., <xref target="sinervo-norsig"/>). In the first stage the input is the LSF vector to be quantized, and in any other stage s > 1, the input is the quantization error from the previous stage (see <xref target='lsf_quantizer_structure_overview_figure'/>).
               </t>
                 <figure align="center" anchor="lsf_quantizer_structure_overview_figure">
                   <artwork align="center">
               </t>
                 <figure align="center" anchor="lsf_quantizer_structure_overview_figure">
                   <artwork align="center">
@@ -4958,7 +5095,7 @@ LSF +----------+ res_1 +----------+  res_{S-1} +----------+
                 </figure>
 
               <t>
                 </figure>
 
               <t>
-                By storing total of M codebook vectors, i.e.,
+                By storing total of M codebook vectors, i.e.,
                 <figure align="center">
                   <artwork align="center">
                     <![CDATA[
                 <figure align="center">
                   <artwork align="center">
                     <![CDATA[
@@ -4981,16 +5118,16 @@ T = | | Ms
 ]]>
                   </artwork>
                 </figure>
 ]]>
                   </artwork>
                 </figure>
-                possible combinations for generating the quantized vector. It is for example possible to represent 2**36 uniquely combined vectors using only 216 vectors in memory, as done in SILK for voiced speech at all sample frequencies above 8&nbsp;kHz.
+                possible combinations for generating the quantized vector. It is, for example, possible to represent 2**36 uniquely combined vectors using only 216 vectors in memory, as is done in SILK for voiced speech at all sample frequencies above 8&nbsp;kHz.
               </t>
             </section>
             <section title='Survivor Based Codebook Search'>
               <t>
               </t>
             </section>
             <section title='Survivor Based Codebook Search'>
               <t>
-                This number of possible combinations is far too high for a full search to be carried out for each frame so for all stages but the last, i.e., s smaller than S, only the best min( L, Ms ) centroids are carried over to stage s+1. In each stage the objective function, i.e., the weighted sum of accumulated bitrate and distortion, is evaluated for each codebook vector entry and the results are sorted. Only the best paths and the corresponding quantization errors are considered in the next stage. In the last stage S the single best path through the multistage codebook is determined. By varying the maximum number of survivors from each stage to the next L, the complexity can be adjusted in real-time at the cost of a potential increase when evaluating the objective function for the resulting quantized vector. This approach scales all the way between the two extremes, L=1 being a greedy search, and the desirable but infeasible full search, L=T/MS. In fact, a performance almost as good as what can be achieved with the infeasible full search can be obtained at a substantially lower complexity by using this approach, see e.g. <xref target='leblanc-tsap' />.
+                This number of possible combinations is far too high to carry out a full search for each frame, so for all stages but the last (i.e., s smaller than S), only the best min(L, Ms) centroids are carried over to stage s+1. In each stage, the objective function (i.e., the weighted sum of accumulated bitrate and distortion) is evaluated for each codebook vector entry and the results are sorted. Only the best paths and their corresponding quantization errors are considered in the next stage. In the last stage, S, the single best path through the multistage codebook is determined. By varying the maximum number of survivors from each stage to the next, L, the complexity can be adjusted in real time, at the cost of a potential increase when evaluating the objective function for the resulting quantized vector. This approach scales all the way between the two extremes, L=1 being a greedy search, and the desirable but infeasible full search, L=T/MS. Performance almost as good as that of the infeasible full search can be obtained at substantially lower complexity by using this approach (see, e.g., <xref target='leblanc-tsap'/>).
               </t>
             </section>
             <section title='LSF Stabilization' anchor='lsf_stabilizer_overview_section'>
               </t>
             </section>
             <section title='LSF Stabilization' anchor='lsf_stabilizer_overview_section'>
-              <t>If the input is stable, finding the best candidate will usually result in the quantized vector also being stable, but due to the multi-stage approach it could in theory happen that the best quantization candidate is unstable and because of this there is a need to explicitly ensure that the quantized vectors are stable. Therefore we apply a LSF stabilization method which ensures that the LSF parameters are within valid range, increasingly sorted, and have minimum distances between each other and the border values that have been pre-determined as the 0.01 percentile distance values from a large training set.</t>
+              <t>If the input is stable, finding the best candidate usually results in a quantized vector that is also stable. Due to the multi-stage approach, however, it is theoretically possible that the best quantization candidate is unstable. Because of this, it is necessary to explicitly ensure that the quantized vectors are stable. Therefore we apply an LSF stabilization method which ensures that the LSF parameters are within valid range, increasingly sorted, and have minimum distances between each other and the border values that have been predetermined as the 0.01 percentile distance values from a large training set.</t>
             </section>
             <section title='Off-Line Codebook Training'>
               <t>
             </section>
             <section title='Off-Line Codebook Training'>
               <t>
@@ -5001,7 +5138,7 @@ T = | | Ms
 
           <section title='LTP Quantization' anchor='ltp_quantizer_overview_section'>
             <t>
 
           <section title='LTP Quantization' anchor='ltp_quantizer_overview_section'>
             <t>
-              For voiced frames, the prediction analysis described in <xref target='pred_ana_voiced_overview_section' /> resulted in four sets (one set per subframe) of five LTP coefficients, plus four weighting matrices. Also, the LTP coefficients for each subframe are quantized using entropy constrained vector quantization. A total of three vector codebooks are available for quantization, with different rate-distortion trade-offs. The three codebooks have 10, 20 and 40 vectors and average rates of about 3, 4, and 5 bits per vector, respectively. Consequently, the first codebook has larger average quantization distortion at a lower rate, whereas the last codebook has smaller average quantization distortion at a higher rate. Given the weighting matrix W_ltp and LTP vector b, the weighted rate-distortion measure for a codebook vector cb_i with rate r_i is give by
+              For voiced frames, the prediction analysis described in <xref target='pred_ana_voiced_overview_section' /> resulted in four sets (one set per subframe) of five LTP coefficients, plus four weighting matrices. The LTP coefficients for each subframe are quantized using entropy constrained vector quantization. A total of three vector codebooks are available for quantization, with different rate-distortion trade-offs. The three codebooks have 10, 20, and 40 vectors and average rates of about 3, 4, and 5 bits per vector, respectively. Consequently, the first codebook has larger average quantization distortion at a lower rate, whereas the last codebook has smaller average quantization distortion at a higher rate. Given the weighting matrix W_ltp and LTP vector b, the weighted rate-distortion measure for a codebook vector cb_i with rate r_i is give by
               <figure align="center">
                 <artwork align="center">
                   <![CDATA[
               <figure align="center">
                 <artwork align="center">
                   <![CDATA[
@@ -5010,11 +5147,11 @@ T = | | Ms
                 </artwork>
               </figure>
               where u is a fixed, heuristically-determined parameter balancing the distortion and rate. Which codebook gives the best performance for a given LTP vector depends on the weighting matrix for that LTP vector. For example, for a low valued W_ltp, it is advantageous to use the codebook with 10 vectors as it has a lower average rate. For a large W_ltp, on the other hand, it is often better to use the codebook with 40 vectors, as it is more likely to contain the best codebook vector.
                 </artwork>
               </figure>
               where u is a fixed, heuristically-determined parameter balancing the distortion and rate. Which codebook gives the best performance for a given LTP vector depends on the weighting matrix for that LTP vector. For example, for a low valued W_ltp, it is advantageous to use the codebook with 10 vectors as it has a lower average rate. For a large W_ltp, on the other hand, it is often better to use the codebook with 40 vectors, as it is more likely to contain the best codebook vector.
-              The weighting matrix W_ltp depends mostly on two aspects of the input signal. The first is the periodicity of the signal; the more periodic the larger W_ltp. The second is the change in signal energy in the current subframe, relative to the signal one pitch lag earlier. A decaying energy leads to a larger W_ltp than an increasing energy. Both aspects do not fluctuate very fast which causes the W_ltp matrices for different subframes of one frame often to be similar. As a result, one of the three codebooks typically gives good performance for all subframes. Therefore the codebook search for the subframe LTP vectors is constrained to only allow codebook vectors to be chosen from the same codebook, resulting in a rate reduction.
+              The weighting matrix W_ltp depends mostly on two aspects of the input signal. The first is the periodicity of the signal; the more periodic, the larger W_ltp. The second is the change in signal energy in the current subframe, relative to the signal one pitch lag earlier. A decaying energy leads to a larger W_ltp than an increasing energy. Both aspects fluctuate relatively slowly, which causes the W_ltp matrices for different subframes of one frame often to be similar. Because of this, one of the three codebooks typically gives good performance for all subframes, and therefore the codebook search for the subframe LTP vectors is constrained to only allow codebook vectors to be chosen from the same codebook, resulting in a rate reduction.
             </t>
 
             <t>
             </t>
 
             <t>
-              To find the best codebook, each of the three vector codebooks is used to quantize all subframe LTP vectors and produce a combined weighted rate-distortion measure for each vector codebook and the vector codebook with the lowest combined rate-distortion over all subframes is chosen. The quantized LTP vectors are used in the noise shaping quantizer, and the index of the codebook plus the four indices for the four subframe codebook vectors are passed on to the range encoder.
+              To find the best codebook, each of the three vector codebooks is used to quantize all subframe LTP vectors and produce a combined weighted rate-distortion measure for each vector codebook. The vector codebook with the lowest combined rate-distortion over all subframes is chosen. The quantized LTP vectors are used in the noise shaping quantizer, and the index of the codebook plus the four indices for the four subframe codebook vectors are passed on to the range encoder.
             </t>
           </section>
 
             </t>
           </section>
 
@@ -5031,7 +5168,7 @@ T = | | Ms
 
           <section title='Range Encoder'>
             <t>
 
           <section title='Range Encoder'>
             <t>
-              Range encoding is a well known method for entropy coding in which a bitstream sequence is continually updated with every new symbol, based on the probability for that symbol. It is similar to arithmetic coding but rather than being restricted to generating binary output symbols, it can generate symbols in any chosen number base. In SILK all side information is range encoded. Each quantized parameter has its own cumulative density function based on histograms for the quantization indices obtained by running a training database.
+              Range encoding is a well known method for entropy coding in which a bitstream sequence is continually updated with every new symbol, based on the probability for that symbol. It is similar to arithmetic coding, but rather than being restricted to generating binary output symbols, it can generate symbols in any chosen number base. In SILK all side information is range encoded. Each quantized parameter has its own cumulative density function based on histograms for the quantization indices obtained by running a training database.
             </t>
 
             <section title='Bitstream Encoding Details'>
             </t>
 
             <section title='Bitstream Encoding Details'>
@@ -5045,30 +5182,25 @@ T = | | Ms
 
 <section title="CELT Encoder">
 <t>
 
 <section title="CELT Encoder">
 <t>
-Copy from CELT draft.
+Most of the aspects of the CELT encoder can be directly derived from the description 
+of the decoder. For example, the filters and rotations in the encoder are simply the
+inverse of the operation performed by the decoder. Similarly, the quantizers generally
+optimize for the mean square error (because noise shaping is part of the bit-stream itself),
+so no special search is required. For this reason, only the less straightforward aspects of the 
+encoder are described here.
 </t>
 
 </t>
 
-<section anchor="prefilter" title="Pre-filter">
-<t>
-Inverse of the post-filter
-</t>
-</section>
-
-
-<section anchor="forward-mdct" title="Forward MDCT">
-
-<t>The MDCT implementation has no special characteristics. The
-input is a windowed signal (after pre-emphasis) of 2*N samples and the output is N
-frequency-domain samples. A "low-overlap" window is used to reduce the algorithmic delay.
-It is derived from a basic (full overlap) window that is the same as the one used in the Vorbis codec:
-<figure align="center">
-<artwork align="center"><![CDATA[
-            pi       pi   n + 1/2   2
-W(n) = [sin(-- * sin(-- * -------))] .
-            2        2       L
-]]></artwork>
-</figure>
-The low-overlap window is created by zero-padding the basic window and inserting ones in the middle, such that the resulting window still satisfies power complementarity. The MDCT is computed in mdct_forward() (mdct.c), which includes the windowing operation and a scaling of 2/N.
+<section anchor="pitch-prefilter" title="Pitch prefilter">
+<t>The pitch prefilter is applied after the pre-emphasis and before the de-emphasis. It's applied 
+in such a way as to be the inverse of the decoder's post-filter. The main non-obvious aspect of the
+prefilter is the selection of the pitch period. The pitch search should be optimised for the 
+following criteria:
+<list style="symbols">
+<t>continuity: it is important that the pitch period
+does not change abruptly between frames; and</t>
+<t>avoidance of pitch multiples: when the period used is a multiple of the real period 
+(lower frequency fundamental), the post-filter loses most of its ability to reduce noise</t>
+</list>
 </t>
 </section>
 
 </t>
 </section>
 
@@ -5076,7 +5208,7 @@ The low-overlap window is created by zero-padding the basic window and inserting
 <t>
 The MDCT output is divided into bands that are designed to match the ear's critical
 bands for the smallest (2.5&nbsp;ms) frame size. The larger frame sizes use integer
 <t>
 The MDCT output is divided into bands that are designed to match the ear's critical
 bands for the smallest (2.5&nbsp;ms) frame size. The larger frame sizes use integer
-multiplies of the 2.5&nbsp;ms layout. For each band, the encoder
+multiples of the 2.5&nbsp;ms layout. For each band, the encoder
 computes the energy that will later be encoded. Each band is then normalized by the
 square root of the <spanx style="strong">unquantized</spanx> energy, such that each band now forms a unit vector X.
 The energy and the normalization are computed by compute_band_energies()
 computes the energy that will later be encoded. Each band is then normalized by the
 square root of the <spanx style="strong">unquantized</spanx> energy, such that each band now forms a unit vector X.
 The energy and the normalization are computed by compute_band_energies()
@@ -5087,78 +5219,13 @@ and normalise_bands() (bands.c), respectively.
 <section anchor="energy-quantization" title="Energy Envelope Quantization">
 
 <t>
 <section anchor="energy-quantization" title="Energy Envelope Quantization">
 
 <t>
-It is important to quantize the energy with sufficient resolution because
-any energy quantization error cannot be compensated for at a later
-stage. Regardless of the resolution used for encoding the shape of a band,
-it is perceptually important to preserve the energy in each band. CELT uses a
-coarse-fine strategy for encoding the energy in the base-2 log domain,
-as implemented in quant_bands.c</t>
-
-<section anchor="coarse-energy" title="Coarse energy quantization">
-<t>
-The coarse quantization of the energy uses a fixed resolution of 6 dB.
-To minimize the bitrate, prediction is applied both in time (using the previous frame)
-and in frequency (using the previous bands). The prediction using the
-previous frame can be disabled, creating an "intra" frame where the energy
-is coded without reference to prior frames. An encoder is able to choose the
-mode used at will based on both loss robustness and efficiency
-considerations.
-The 2-D z-transform of
-the prediction filter is:
-<figure align="center">
-<artwork align="center"><![CDATA[
-                            -1          -1
-              (1 - alpha*z_l  )*(1 - z_b  )
-A(z_l, z_b) = -----------------------------
-                                 -1
-                     1 - beta*z_b
-]]></artwork>
-</figure>
-where b is the band index and l is the frame index. The prediction coefficients
-applied depend on the frame size in use when not using intra energy and are alpha=0, beta=4915/32768
-when using intra energy.
-The time-domain prediction is based on the final fine quantization of the previous
-frame, while the frequency domain (within the current frame) prediction is based
-on coarse quantization only (because the fine quantization has not been computed
-yet). The prediction is clamped internally so that fixed point implementations with
-limited dynamic range do not suffer desynchronization.  Identical prediction
-clamping must be implemented in all encoders and decoders.
-We approximate the ideal
-probability distribution of the prediction error using a Laplace distribution
-with separate parameters for each frame size in intra and inter-frame modes. The
-coarse energy quantization is performed by quant_coarse_energy() and
-quant_coarse_energy() (quant_bands.c). The encoding of the Laplace-distributed values is
-implemented in ec_laplace_encode() (laplace.c).
+Energy quantization (both coarse and fine) can be easily understood from the decoding process.
+The quantizer simply minimizes the log energy error for each band, with the exception that at
+very low rate, larger errors are allowed in the coarse energy to minimize the bit-rate. When the
+avaialble CPU requirements allow it, it is best to try encoding the coarse energy both with and without
+inter-frame prediction such that the best prediction mode can be selected. The optimal mode depends on
+the coding rate, the available bit-rate, and the current rate of packet loss. 
 </t>
 </t>
-
-<!-- FIXME: bit budget consideration -->
-</section> <!-- coarse energy -->
-
-<section anchor="fine-energy" title="Fine energy quantization">
-<t>
-After the coarse energy quantization and encoding, the bit allocation is computed
-(<xref target="allocation"></xref>) and the number of bits to use for refining the
-energy quantization is determined for each band. Let B_i be the number of fine energy bits
-for band i; the refinement is an integer f in the range [0,2**B_i-1]. The mapping between f
-and the correction applied to the coarse energy is equal to (f+1/2)/2**B_i - 1/2. Fine
-energy quantization is implemented in quant_fine_energy()
-(quant_bands.c).
-</t>
-
-<t>
-If any bits are unused at the end of the encoding process, these bits are used to
-increase the resolution of the fine energy encoding in some bands. Priority is given
-to the bands for which the allocation (<xref target="allocation"></xref>) was rounded
-down. At the same level of priority, lower bands are encoded first. Refinement bits
-are added until there is no more room for fine energy or until each band
-has gained an additional bit of precision or has the maximum fine
-energy precision. This is implemented in quant_energy_finalise()
-(quant_bands.c).
-</t>
-
-</section> <!-- fine energy -->
-
-
 </section> <!-- Energy quant -->
 
 
 </section> <!-- Energy quant -->
 
 
@@ -5185,7 +5252,7 @@ L2 norm.
 <t>
 The search for the best codevector y is performed by alg_quant()
 (vq.c). There are several possible approaches to the
 <t>
 The search for the best codevector y is performed by alg_quant()
 (vq.c). There are several possible approaches to the
-search with a trade-off between quality and complexity. The method used in the reference
+search, with a trade-off between quality and complexity. The method used in the reference
 implementation computes an initial codeword y1 by projecting the residual signal
 R = X - p' onto the codebook pyramid of K-1 pulses:
 </t>
 implementation computes an initial codeword y1 by projecting the residual signal
 R = X - p' onto the codebook pyramid of K-1 pulses:
 </t>
@@ -5214,57 +5281,12 @@ codebook and the implementers MAY use any other search methods.
 </section>
 
 
 </section>
 
 
-<section anchor="cwrs-encoding" title="Index Encoding">
-<t>
-The best PVQ codeword is encoded as a uniformly-distributed integer value
-by encode_pulses() (cwrs.c).
-The codeword is converted from a unique index in the same way as specified in
-<xref target="PVQ"></xref>. The indexing is based on the calculation of V(N,K)
-(denoted N(L,K) in <xref target="PVQ"></xref>), which is the number of possible
-combinations of K pulses in N samples.
-</t>
-
 </section>
 
 </section>
 
-</section>
-
-
-<section anchor="stereo" title="Stereo support">
-<t>
-When encoding a stereo stream, some parameters are shared across the left and right channels, while others are transmitted separately for each channel, or jointly encoded. Only one copy of the flags for the features, transients and pitch (pitch
-period and filter parameters) are transmitted. The coarse and fine energy parameters are transmitted separately for each channel. Both the coarse energy and fine energy (including the remaining fine bits at the end of the stream) have the left and right bands interleaved in the stream, with the left band encoded first.
-</t>
-
-<t>
-The main difference between mono and stereo coding is the PVQ coding of the normalized vectors. In stereo mode, a normalized mid-side (M-S) encoding is used. Let L and R be the normalized vector of a certain band for the left and right channels, respectively. The mid and side vectors are computed as M=L+R and S=L-R and no longer have unit norm.
-</t>
 
 
-<t>
-From M and S, an angular parameter theta=2/pi*atan2(||S||, ||M||) is computed. The theta parameter is converted to a Q14 fixed-point parameter itheta, which is quantized on a scale from 0 to 1 with an interval of 2**(-qb), where qb is
-based the number of bits allocated to the band. From here on, the value of itheta MUST be treated in a bit-exact manner since both the encoder and decoder rely on it to infer the bit allocation.
-</t>
-<t>
-Let m=M/||M|| and s=S/||S||; m and s are separately encoded with the PVQ encoder described in <xref target="pvq"></xref>. The number of bits allocated to m and s depends on the value of itheta.
-</t>
 
 
-</section>
 
 
 
 
-<section anchor="synthesis" title="Synthesis">
-<t>
-After all the quantization is completed, the quantized energy is used along with the
-quantized normalized band data to resynthesize the MDCT spectrum. The inverse MDCT (<xref target="inverse-mdct"></xref>) and the weighted overlap-add are applied and the signal is stored in the "synthesis
-buffer".
-The encoder MAY omit this step of the processing if it does not need the decoded output.
-</t>
-</section>
-
-<section anchor="vbr" title="Variable Bitrate (VBR)">
-<t>
-Each CELT frame can be encoded in a different number of octets, making it possible to vary the bitrate at will. This property can be used to implement source-controlled variable bitrate (VBR). Support for VBR is OPTIONAL for the encoder, but a decoder MUST be prepared to decode a stream that changes its bitrate dynamically. The method used to vary the bitrate in VBR mode is left to the implementer, as long as each frame can be decoded by the reference decoder.
-</t>
-</section>
-
 </section>
 
 </section>
 </section>
 
 </section>
@@ -5292,10 +5314,10 @@ Compliance with this specification means that a decoder's output MUST be
 To complement the Opus specification, the "Opus Custom" codec is defined to
 handle special sampling rates and frame rates that are not supported by the
 main Opus specification. Use of Opus Custom is discouraged for all but very
 To complement the Opus specification, the "Opus Custom" codec is defined to
 handle special sampling rates and frame rates that are not supported by the
 main Opus specification. Use of Opus Custom is discouraged for all but very
-special applications for which a frame size different from 2.5, 5, 10, 20 ms is
+special applications for which a frame size different from 2.5, 5, 10, or 20&nbsp;ms is
 needed (for either complexity or latency reasons). Such applications will not
 be compatible with the "main" Opus codec. In Opus Custom operation,
 needed (for either complexity or latency reasons). Such applications will not
 be compatible with the "main" Opus codec. In Opus Custom operation,
-only the CELT later is available, which is available using the celt_* function
+only the CELT layer is available, which is available using the celt_* function
 calls in celt.h.
 </t>
 
 calls in celt.h.
 </t>
 
@@ -5304,7 +5326,7 @@ calls in celt.h.
 <section anchor="security" title="Security Considerations">
 
 <t>
 <section anchor="security" title="Security Considerations">
 
 <t>
-The codec needs to take appropriate security considerations
+Implementations of the Opus codec need to take appropriate security considerations
 into account, as outlined in <xref target="DOS"/> and <xref target="SECGUIDE"/>.
 It is extremely important for the decoder to be robust against malicious
 payloads.
 into account, as outlined in <xref target="DOS"/> and <xref target="SECGUIDE"/>.
 It is extremely important for the decoder to be robust against malicious
 payloads.
@@ -5312,7 +5334,7 @@ Malicious payloads must not cause the decoder to overrun its allocated memory
  or to take an excessive amount of resources to decode.
 Although problems
 in encoders are typically rarer, the same applies to the encoder. Malicious
  or to take an excessive amount of resources to decode.
 Although problems
 in encoders are typically rarer, the same applies to the encoder. Malicious
-audio stream must not cause the encoder to misbehave because this would
+audio streams must not cause the encoder to misbehave because this would
 allow an attacker to attack transcoding gateways.
 </t>
 <t>
 allow an attacker to attack transcoding gateways.
 </t>
 <t>
@@ -5320,18 +5342,33 @@ The reference implementation contains no known buffer overflow or cases where
  a specially crafted packet or audio segment could cause a significant increase
  in CPU load.
 However, on certain CPU architectures where denormalized floating-point
  a specially crafted packet or audio segment could cause a significant increase
  in CPU load.
 However, on certain CPU architectures where denormalized floating-point
- operations are much slower than normal floating-point operations it is
- possible for some audio content (e.g., silence or near-silence) to cause such
+ operations are much slower than normal floating-point operations, it is
+ possible for some audio content (e.g., silence or near-silence) to cause a certain
  an increase in CPU load.
 Denormals can be introduced by reordering operations in the compiler and depend
  an increase in CPU load.
 Denormals can be introduced by reordering operations in the compiler and depend
- on the target architecture, so it is difficult to guarantee an implementation
+ on the target architecture, so it is difficult to guarantee that an implementation
  avoids them.
  avoids them.
-For such architectures, it is RECOMMENDED that one add very small
- floating-point offsets to prevent significant numbers of denormalized
- operations or to configure the hardware to treat denormals as zero (DAZ).
-<!--TODO: Add small offsets to what? We should be explicit-->
+For architectures on which denormals are problematic, it is RECOMMENDED to 
+add very small floating-point offsets to the affected signals
+to prevent significant numbers of denormalized
+ operations. Alternatively, it is often possible to configure the hardware to treat
+ denormals as zero (DAZ).
 No such issue exists for the fixed-point reference implementation.
 </t>
 No such issue exists for the fixed-point reference implementation.
 </t>
+<t>The reference implementation was validated in the following conditions:
+<list style="numbers">
+<t>Sending the decoder valid packets generated by the reference encoder and 
+verifying that the decoder's final range coder state matches that of the encoder.</t>
+<t>Sending the decoder packets generated by the reference encoder, after random corruption.</t>
+<t>Sending the decoder random packets to the decoder.</t>
+<t>Altering the encoder to make random coding decisions (internal fuzzing), including
+mode switching and verifying that the range coder final states match.</t>
+</list>
+In all of the conditions above, both the encoder and the decoder were run inside
+the Valgrind memory debugger, which tracks reads and writes to invalid memory 
+regions, as well as use of uninitialized memory. There were no error reported
+on any of the tested conditions.
+</t>
 </section>
 
 
 </section>
 
 
@@ -5345,9 +5382,10 @@ This document has no actions for IANA.
 <t>
 Thanks to all other developers, including Raymond Chen, Soeren Skak Jensen, Gregory Maxwell,
 Christopher Montgomery, and Karsten Vandborg Soerensen. We would also
 <t>
 Thanks to all other developers, including Raymond Chen, Soeren Skak Jensen, Gregory Maxwell,
 Christopher Montgomery, and Karsten Vandborg Soerensen. We would also
-like to thank Igor Dyakonov, Jan Skoglund for their help with subjective testing of the
-Opus codec. Thanks to John Ridges, Keith Yan and many others on the Opus and CELT mailing lists
-for their bug reports and feeback.
+like to thank Igor Dyakonov and Jan Skoglund for their help with subjective testing of the
+Opus codec. Thanks to John Ridges, Keith Yan, and many others on the Opus and CELT mailing lists
+for their bug reports and feedback, as well as Ralph Giles, Christian Hoene, and
+Kat Walsh, for their feedback on the draft.
 </t>
 </section>
 
 </t>
 </section>
 
@@ -5587,7 +5625,7 @@ It is RECOMMENDED that a transport layer choose exactly one framing scheme,
 For example, although a regular Opus stream does not support more than two
  channels, a multi-channel Opus stream may be formed from several one- and
  two-channel streams.
 For example, although a regular Opus stream does not support more than two
  channels, a multi-channel Opus stream may be formed from several one- and
  two-channel streams.
-To pack an Opus packets from each of these streams together in a single packet
+To pack an Opus packet from each of these streams together in a single packet
  at the transport layer, one could use the self-delimiting framing for all but
  the last stream, and then the regular, undelimited framing for the last one.
 Reverting to the undelimited framing for the last stream saves overhead
  at the transport layer, one could use the self-delimiting framing for all but
  the last stream, and then the regular, undelimited framing for the last one.
 Reverting to the undelimited framing for the last stream saves overhead