Advertisement
wswartzendruber

Opus Range Encoder Implementation

Feb 14th, 2015
327
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 2.33 KB | None | 0 0
  1. #include <stdint.h>
  2.  
  3. #include "rcode.h"
  4.  
  5. #define RCODE_N 256
  6.  
  7. /*
  8.  * INTERNAL MEMBERS
  9.  */
  10.  
  11. void carryout(uint_fast16_t c, int_fast16_t* rem, uint_fast16_t* ext
  12.         , unsigned char* output, size_t* out_index);
  13.  
  14. /*
  15.  * EXTERNAL MEMBERS
  16.  */
  17.  
  18. size_t range_encode(unsigned char* input, unsigned char* output, size_t in_length)
  19. {
  20.     /* Model */
  21.     size_t f[RCODE_N]  = { 0 };
  22.     size_t fl[RCODE_N] = { 0 };
  23.     size_t fh[RCODE_N] = { 0 };
  24.     size_t ft          = 0;
  25.    
  26.     /* State */
  27.     uint_fast32_t val = 0;
  28.     uint_fast32_t rng = 2147483648;
  29.     int_fast16_t  rem = -1;
  30.     uint_fast16_t ext = 0;
  31.    
  32.     size_t out_index   = 0;
  33.    
  34.     /*
  35.      * Compute frequency values.
  36.      */
  37.    
  38.     for (size_t index = 0; index < in_length; index++)
  39.         f[input[index]]++;
  40.    
  41.     for (size_t k = 0; k < RCODE_N; k++)
  42.         for (size_t i = 0; i < k; i++)
  43.             fl[k] += f[i];
  44.    
  45.     for (size_t k = 0; k < RCODE_N; k++)
  46.         fh[k] = fl[k] + f[k];
  47.    
  48.     for (size_t i = 0; i < RCODE_N; i++)
  49.         ft += f[i];
  50.    
  51.     /*
  52.      * Main loop
  53.      */
  54.      
  55.     for (size_t in_index = 0; in_index < in_length; in_index++)
  56.     {
  57.         /*
  58.          * Encode
  59.          */
  60.        
  61.         unsigned char k = input[in_index];
  62.        
  63.         if (fl[k] > 0)
  64.         {
  65.             val = val + rng - (rng / ft) * (ft - fl[k]);
  66.             rng = (rng / ft) * (fh[k] - fl[k]);
  67.         }
  68.         else
  69.         {
  70.             rng = rng - (rng / ft) * (fh[k] - fl[k]);
  71.         }
  72.        
  73.         /*
  74.          * Renormalize
  75.          */
  76.        
  77.         while (rng <= 8388608)
  78.         {
  79.             carryout(val >> 23, &rem, &ext, output, &out_index);
  80.            
  81.             val = (val << 8) & 0x7fffffff;
  82.             rng <<= 8;
  83.         }
  84.     }
  85.        
  86.     /*
  87.      * Finalize
  88.      */
  89.    
  90.     uint_fast32_t end = val;
  91.    
  92.     while (end)
  93.     {
  94.         carryout(end >> 23, &rem, &ext, output, &out_index);
  95.        
  96.         end = (end << 8) & 0x7fffffff;
  97.     }
  98.    
  99.     if ((rem && rem != -1) || ext > 0)
  100.         carryout(0, &rem, &ext, output, &out_index);
  101.    
  102.     return out_index;
  103. }
  104.  
  105. void carryout(uint_fast16_t c, int_fast16_t* rem, uint_fast16_t* ext
  106.         , unsigned char* output, size_t* out_index)
  107. {
  108.     if (c == 255)
  109.     {
  110.         *ext = *ext + 1;
  111.     }
  112.     else
  113.     {
  114.         uint_fast16_t b = c >> 8;
  115.        
  116.         if (*rem != -1)
  117.             output[*out_index = *out_index + 1] = *rem + b;
  118.        
  119.         if (*ext)
  120.         {
  121.             if (b)
  122.                 for (uint_fast16_t count = 0; count < *ext; count++)
  123.                     output[*out_index = *out_index + 1] = 0;
  124.             else
  125.                 for (uint_fast16_t count = 0; count < *ext; count++)
  126.                     output[*out_index = *out_index + 1] = 255;
  127.            
  128.             *ext = 0;
  129.         }
  130.        
  131.         *rem = c & 255;
  132.     }
  133. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement