Skip to content

GitLab

  • Projects
  • Groups
  • Snippets
  • Help
    • Loading...
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
Opus
Opus
  • Project overview
    • Project overview
    • Details
    • Activity
    • Releases
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 25
    • Issues 25
    • List
    • Boards
    • Labels
    • Service Desk
    • Milestones
  • Merge Requests 3
    • Merge Requests 3
  • CI / CD
    • CI / CD
    • Pipelines
    • Jobs
    • Schedules
  • Operations
    • Operations
    • Incidents
    • Environments
  • Packages & Registries
    • Packages & Registries
    • Container Registry
  • Analytics
    • Analytics
    • CI / CD
    • Repository
    • Value Stream
  • Wiki
    • Wiki
  • Members
    • Members
  • Collapse sidebar
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
  • Xiph.Org
  • OpusOpus
  • Issues
  • #1954

Closed
Open
Opened May 03, 2013 by J.Dods@jdods

celt_decode_lost() - very poor precision/wrong result in application of frac_div32( arg1, arg2 )

Looking in celt_decode_lost() under the comment:

/* Check if the waveform is decaying (and if so how fast)
   We do this to avoid adding energy when concealing in a segment
   with decaying energy */
     
decay = celt_sqrt( frac_div32(SHR32(E1,1),E2) );

We see that if E1=1 then the 1-bit right shift of E1 makes E1=0. Therefore ANY E1, E2 combinations like 1/2, 1/3, ... 1/n will evaluate to zero. Similarly, for small values of E1 the precision of the result is needlessly poor (see table below).

Suggested fix: If the intent of shifting was done to bound the output of frac_div32 to (0.5,0] then an alternate solution which avoids the E1=1 pitfall (and poor precision on small values of E1) is to shift the result of frac_div32(), instead.

 decay   = celt_sqrt( frac_div32(E1,E2)>>1 );

Here is a small table of test values to illustrate:

decay = celt_sqrt ( frac_div32(SHR32(E1,1),E2) );

====================================================

7FEB = celt_sqrt( 3FF36D10 = frac_div32(1303/1303)) <-- so-so

687C = celt_sqrt( 2AAAAAA0 = frac_div32( 11/ 15)) <-- not great

5A86 = celt_sqrt( 1FFFFFF0 = frac_div32( 3/ 4)) <-- very bad

0000 = celt_sqrt( 00000000 = frac_div32( 1/ 1)) <-- wrong

With suggested code fix:

decay = celt_sqrt( frac_div32(E1,E2)>>1 );

====================================================

7FF6 = celt_sqrt( 3FFFFFF8 = frac_div32(1303/1303))

6D97 = celt_sqrt( 2EEEEEE8 = frac_div32( 11/ 15))

6ED5 = celt_sqrt( 2FFFFFF8 = frac_div32( 3/ 4))

7FF6 = celt_sqrt( 3FFFFFF8 = frac_div32( 1/ 1))

Assignee
Assign to
None
Milestone
None
Assign milestone
Time tracking
None
Due date
None
Reference: xiph/opus#1954