<html><head></head><body>Glad you figured it out!<br> -r<br><br><div class="gmail_quote">On July 3, 2021 4:51:57 AM PDT, Jake Taylor <yupferris@gmail.com> wrote:<blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
<div dir="ltr"><div dir="ltr"><div>Hi again all,</div><div><br></div><div>I've solved it (in fact the clues showed up in earlier notes, but I didn't put it together entirely until now)! I was making a crucial conceptual mistake. I assumed the output of the predictor was the <i>prediction</i>, however, this is incorrect - instead it outputs the <i>residual</i> directly. Under that interpretation, everything falls into place. So I no longer need help with this, and sorry for the noise while I figured it out!<br></div></div><div><br></div><div>
<div><span class="gmail-im"><div>For the curious, once again, notes in pdf/lyx format are attached, as well as on my dropbox:</div></span><div>pdf: <a href="https://www.dropbox.com/s/l4tzyvq1mne8jan/predictor-confusion-4.pdf?dl=0" target="_blank">https://www.dropbox.com/s/rzm08055hytjy6c/predictor-confusion-5.pdf?dl=0</a></div><div>lyx: <a href="https://www.dropbox.com/s/map3slkbnhyctui/predictor-confusion-4.lyx?dl=0" target="_blank">https://www.dropbox.com/s/vj1s3pbm8q914vf/predictor-confusion-5.lyx?dl=0</a></div><span class="gmail-im"><div>and plaintext below.</div><div><br></div><div>Thanks again,</div><div>Jake</div><div><br></div><div>---</div><div><br></div><div>Opus Coarse Energy Predictor Notes (Round 5)<br><br>Jake Taylor (<a href="mailto:yupferris@gmail.com">yupferris@gmail.com</a>), 3 July 2021<br><br>I've solved it - I was simply mistaken about what the output of <br>the filters should be. Instead of the filters outputting the <br>prediction, they output the residual directly. Under this <br>interpretation, everything falls into place.<br><br>According to the paper[0]/RFC[1], the 2D z-transform should be:<br><br>A(z_{\ell},z_{b})=(1-\alpha z_{\ell}^{-1})\cdot\frac{1-z_{b}^{-1}}{1-\beta z_{b}^{-1}}<br><br>I've simplified the source code (in unquant_coarse_energy in <br>quant_bands.c in libopus 1.3.1[2]) to the following C (pseudo)code:<br><br>void unquant_coarse_energy(float *e, int bands) {<br>  float alpha = /* ... */;<br>  float beta = /* ... */;<br>  float prev = 0.0f;<br>  for (int b = 0; b < bands; b++) {<br>    float r = /* read from bitstream */;<br>    e[i] = alpha * e[i] + prev + r;<br>    prev = prev + (1 - beta) * r;<br>  }<br>}<br><br>The goal is simple: extract difference equations from the code, <br>derive the corresponding z-transforms, and then solve the final z<br>-transform which should hopefully match what the paper/RFC list.<br><br>The code is governed by the following difference equations:<br><br>e[\ell,b]=\alpha e[\ell-1,b]+prev[\ell,b-1]+r[\ell,b]<br><br>prev[\ell,b]=prev[\ell,b-1]+(1-\beta)r[\ell,b]<br><br>The corresponding z-transforms are:<br><br>E(z_{\ell},z_{b})=\alpha z_{\ell}^{-1}E(z_{\ell},z_{b})+z_{b}^{-1}Prev(z_{\ell},z_{b})+R(z_{\ell},z_{b})<br><br>Prev(z_{\ell},z_{b})=z_{b}^{-1}Prev(z_{\ell},z_{b})+(1-\beta)R(z_{\ell},z_{b})<br><br>We expect the domain of the predictor to be e (the 2D “energy <br>plane”) and the range of the predictor to be r (the final coded <br>residual). So, these two z-transforms should be all we need to <br>reach the z-transform from the paper/RFC.<br><br>First, let's simplify the latter equation by isolating Prev:<br><br>Prev(z_{\ell},z_{b})=\frac{1-\beta}{1-z_{b}^{-1}}R(z_{\ell},z_{b})<br><br>Now, we can substitute this definition in the first equation, <br>which leaves only E and R signals (our expected domain and range, <br>respectively):<br><br>E(z_{\ell},z_{b})=\alpha z_{\ell}^{-1}E(z_{\ell},z_{b})+z_{b}^{-1}\cdot\frac{1-\beta}{1-z_{b}^{-1}}R(z_{\ell},z_{b})+R(z_{\ell},z_{b})<br><br>Simplifying this yields:<br><br>R(z_{\ell},z_{b})=(1-\alpha z_{\ell}^{-1})\cdot\frac{1-z_{b}^{-1}}{1-\beta z_{b}^{-1}}E(z_{\ell},z_{b})<br><br>Or, equivalently:<br><br>A(z_{\ell},z_{b})=(1-\alpha z_{\ell}^{-1})\cdot\frac{1-z_{b}^{-1}}{1-\beta z_{b}^{-1}}<br><br>Just as expected!</div><div><br></div><div>[0] 
<span class="gmail-im"><a href="https://arxiv.org/abs/1602.04845">https://arxiv.org/abs/1602.04845</a></span></div><div><span class="gmail-im">[1] 
<span class="gmail-im"><a href="https://datatracker.ietf.org/doc/html/rfc6716#section-4.3.2">https://datatracker.ietf.org/doc/html/rfc6716#section-4.3.2</a></span></span></div><div><span class="gmail-im"><span class="gmail-im">[2] 
<span class="gmail-im"><a href="https://opus-codec.org/release/stable/2019/04/12/libopus-1_3_1.html">https://opus-codec.org/release/stable/2019/04/12/libopus-1_3_1.html</a></span></span></span><br><br></div></span></div>

</div></div>
</blockquote></div></body></html>