I've been looking at the opus paper (https://arxiv.org/pdf/1602.04845.pdf); in particular, in section 4.1, they describe the predictor for the current band energy based on energy from both the current band from the previous frames, and the previous bands in the current frame. This makes sense; I would interpret this as "some linear combination of the previous values". Where I get a bit stuck (due to unfamiliarity) is that the predictor is described in the paper by its z-transform. To quote:

"The 2D $z$-transform of the predictor is


where $\ell$ is the frame index and $b$ is the band."

My main questions are: how might I interpret this as a difference equation, and why is it presented as a $z$-transform in the first place?

Here's what I've got so far:

So, it appears to be describing some kind of filter $a(\ell,b)$. This filter seems to be made up of two separate filters (one based on the previous frame energy and one based on the previous band). The former appears to be a basic FIR filter with one tap and the coefficient $\alpha$; the latter appears to be an IIR filter with one input tap with coefficient $-1$ and one output tap with coefficient $\beta$. so, first questions:

  • why $a$? Is it just arbitrary? I would have expected that this was a transfer function, in which case I would have expected $h$.
  • is my interpretation of the two filters separately correct?

assuming I've interpreted them correctly separately, I would convert them to difference equations, eg. the first one might be:


and the second one might be:


next question:

  • is this correct?

These filters are multiplied in the z-domain, which I would interpret as being applied in series somehow (as that should correspond to convolution in the time domain), but they have different subscripts for the z values so I'm not totally sure.

To gain a better understanding, I took a look at the code for the filter (in unquant_coarse_energy in quant_bands.c in the latest libopus). I tried to simplify it as much as possible (removing multichannel/fixed point/etc) and came up with this:

// On input, bandEnergies represents the energies from previous frame (or zeros if first frame)
void decodeBandEnergies(float bandEnergies[], int numBands, bool intra)
    float alpha = <something based on intra etc>f;
    float beta = <something based on intra etc>f;
    float prev = 0.0f;
    for (int band = 0; band < numBands; band++)
        float q = <decode from bitstream>;
        bandEnergies[band] = alpha * bandEnergies[band] + prev + q;
        prev = prev + q - beta * q;

I think I did this right but there may be mistakes. Anyway, q in this case represents the residual energy for the current frame/band, so q[l,b]=a[l,b]-x[l,b] if x is the previous band energies.

From this simplified code it looks like my interpretation of the filter for the last frame energy is correct, but I'm very confused about how prev and its usage matches both the previous band predictor, as well as why they're composed here with addition.

Any help/tips would be appreciated!


This seems a 2D filter.


Is a FIR on the $\ell$ dimension and recursive in the $b$ dimension.

Let's express in terms of inputs $X(z_\ell,z_b)$ and $Y(z_\ell,z_b)$,

$$Y(z_\ell,z_b) = (1-\alpha{z_\ell^{-1}})\cdot\frac{1-{z_b^{-1}}}{1-\beta{z_b^{-1}}} X(z_\ell,z_b)$$

Let's eliminate the fraction by multiplying $(1 - \beta z_b^{-1})$

$$(1 - \beta z_b^{-1})Y(z_\ell,z_b) = (1-\alpha{z_\ell^{-1}})\cdot (1-{z_b^{-1}}) X(z_\ell,z_b)$$

We can expand these equations and then use the identities $z_\ell^{-1} F(z_\ell,z_b) \leftrightarrow f(\ell-1,b)$ and $z_b^{-1} F(z_\ell,z_b) \leftrightarrow f(\ell,b-1)$ to get the corresponding difference equations.

$$y(\ell, b) - \beta y(\ell, b-1) = (x(\ell, b) - \alpha x(\ell-1, b)) - (x(\ell, b-1) - \alpha x(\ell-1, b-1))$$

If you introduce the intermediate quantity $q(\ell, b) = x(\ell, b) - \alpha x(\ell-1, b)$ this can be written as $$y(\ell, b) - \beta y(\ell, b-1) = q(\ell, b) - q(\ell, b-1)$$

You probably want to make it explicit as a step equation

$$ y(\ell, b-1) = \frac{1}{\beta}\left(y(\ell, b) - q(\ell, b) + q(\ell, b-1)\right)$$


$$y(\ell, b) = \beta y(\ell, b-1) + q(\ell, b) - q(\ell, b-1)$$

  • $\begingroup$ Aha, even though the paper mentions "the 2D $z$-transform of the predictor" I didn't think to actually look for a 2D $z$-transform! I think there may be a couple mistakes in the above explanation. I think it's actually $q(\ell, b) = x(\ell, b) - \alpha x(\ell+1, b)$, and then as before, we get: $$y(\ell, b) - \beta y(\ell, b+1) = q(\ell, b) - q(\ell, b+1)$$ I'm not entirely sure what you meant as a step equation but I think we want the $y(\ell, b+1)$ by itself, so that would be: $$y(\ell, b+1) = \frac{1}{\beta}(y(\ell, b) - q(\ell, b) + q(\ell, b+1))$$ Is this correct? $\endgroup$
    – ferris
    Jun 24 at 20:05
  • $\begingroup$ Yes you are right about the definition of $q(\ell, b)$. By step meant an explicit formula that you can go one step forward calculating $y(\ell, b+1)$ given the input and the $y(\ell, b)$. $\endgroup$
    – Bob
    Jun 24 at 20:15
  • $\begingroup$ One more thing, isn't the identity actually supposed to be $z_\ell^{-1} F(z_\ell,z_b) \leftrightarrow f(\ell-1,b)$, without flipping the sign of the time shift? And in that case, we actually want to isolate $y(\ell,b)$ instead of $y(\ell,b+1)$ ? $\endgroup$
    – ferris
    Jun 24 at 20:22
  • $\begingroup$ Sorry, you must be right. The convention on wikipedia is $z^{-1}F(z)$ for delay. In my own derivations I always use to think in $z$ as the delay operator, since we can only delay a signal and not advance it, then we have always positive exponents on $z$ that is handy. $\endgroup$
    – Bob
    Jun 24 at 20:38
  • $\begingroup$ Thank you for the sharp review :) $\endgroup$
    – Bob
    Jun 24 at 20:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.