"Fossies" - the Fresh Open Source Software Archive

Member "quicktime4linux-2.3/thirdparty/libvorbis-1.1.1/doc/xml/07-floor1.xml" (31 May 2008, 16080 Bytes) of package /linux/privat/old/quicktime4linux-2.3-src.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) XML source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file.

    1 <?xml version="1.0" standalone="no"?>
    2 <!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
    3                 "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
    4 
    5 ]>
    6 
    7 <section id="vorbis-spec-floor1">
    8 <sectioninfo>
    9 <releaseinfo>
   10  $Id: 07-floor1.xml 7186 2004-07-20 07:19:25Z xiphmont $
   11 </releaseinfo>
   12 </sectioninfo>
   13 <title>Floor type 1 setup and decode</title>
   14 
   15 <section>
   16 <title>Overview</title>
   17 
   18 <para>
   19 Vorbis floor type one uses a piecewise straight-line representation to
   20 encode a spectral envelope curve. The representation plots this curve
   21 mechanically on a linear frequency axis and a logarithmic (dB)
   22 amplitude axis. The integer plotting algorithm used is similar to
   23 Bresenham's algorithm.</para>
   24 
   25 </section>
   26 
   27 <section>
   28 <title>Floor 1 format</title>
   29 
   30 <section><title>model</title>
   31 
   32 <para>
   33 Floor type one represents a spectral curve as a series of
   34 line segments.  Synthesis constructs a floor curve using iterative
   35 prediction in a process roughly equivalent to the following simplified
   36 description:</para>
   37 
   38 <itemizedlist>
   39  <listitem><simpara> the first line segment (base case) is a logical line spanning
   40 from x_0,y_0 to x_1,y_1 where in the base case x_0=0 and x_1=[n], the
   41 full range of the spectral floor to be computed.</simpara></listitem>
   42 
   43 <listitem><simpara>the induction step chooses a point x_new within an existing
   44 logical line segment and produces a y_new value at that point computed
   45 from the existing line's y value at x_new (as plotted by the line) and
   46 a difference value decoded from the bitstream packet.</simpara></listitem>
   47 
   48 <listitem><simpara>floor computation produces two new line segments, one running from
   49 x_0,y_0 to x_new,y_new and from x_new,y_new to x_1,y_1. This step is
   50 performed logically even if y_new represents no change to the
   51 amplitude value at x_new so that later refinement is additionally
   52 bounded at x_new.</simpara></listitem>
   53 
   54 <listitem><simpara>the induction step repeats, using a list of x values specified in
   55 the codec setup header at floor 1 initialization time.  Computation
   56 is completed at the end of the x value list.</simpara></listitem>
   57 
   58 </itemizedlist>
   59 
   60 <para>
   61 Consider the following example, with values chosen for ease of
   62 understanding rather than representing typical configuration:</para>
   63 
   64 <para>
   65 For the below example, we assume a floor setup with an [n] of 128.
   66 The list of selected X values in increasing order is
   67 0,16,32,48,64,80,96,112 and 128.  In list order, the values interleave
   68 as 0, 128, 64, 32, 96, 16, 48, 80 and 112.  The corresponding
   69 list-order Y values as decoded from an example packet are 110, 20, -5,
   70 -45, 0, -25, -10, 30 and -10.  We compute the floor in the following
   71 way, beginning with the first line:</para>
   72 
   73 <mediaobject>
   74 <imageobject>
   75  <imagedata fileref="floor1-1.png" format="PNG"/>
   76 </imageobject>
   77 <textobject>
   78  <phrase>[graph of example floor]</phrase>
   79 </textobject>
   80 </mediaobject>
   81 
   82 <para>
   83 We now draw new logical lines to reflect the correction to new_Y, and
   84 iterate for X positions 32 and 96:</para>
   85 
   86 <mediaobject>
   87 <imageobject>
   88  <imagedata fileref="floor1-2.png" format="PNG"/> 
   89  </imageobject>
   90  <textobject>
   91   <phrase>[graph of example floor]</phrase>
   92  </textobject>
   93 </mediaobject>
   94   
   95 <para>
   96 Although the new Y value at X position 96 is unchanged, it is still
   97 used later as an endpoint for further refinement.  From here on, the
   98 pattern should be clear; we complete the floor computation as follows:</para>
   99 
  100 <mediaobject>
  101 <imageobject>
  102  <imagedata fileref="floor1-3.png" format="PNG"/> 
  103  </imageobject>
  104  <textobject>
  105   <phrase>[graph of example floor]</phrase>
  106  </textobject>
  107 </mediaobject>
  108   
  109 <mediaobject>
  110 <imageobject>
  111  <imagedata fileref="floor1-4.png" format="PNG"/> 
  112  </imageobject>
  113  <textobject>
  114   <phrase>[graph of example floor]</phrase>
  115  </textobject>
  116 </mediaobject>
  117   
  118 
  119 <para>
  120 A more efficient algorithm with carefully defined integer rounding
  121 behavior is used for actual decode, as described later.  The actual
  122 algorithm splits Y value computation and line plotting into two steps
  123 with modifications to the above algorithm to eliminate noise
  124 accumulation through integer roundoff/truncation. </para>
  125 
  126 </section>
  127 
  128 <section><title>header decode</title>
  129 
  130 <para>
  131 A list of floor X values is stored in the packet header in interleaved
  132 format (used in list order during packet decode and synthesis).  This
  133 list is split into partitions, and each partition is assigned to a
  134 partition class.  X positions 0 and [n] are implicit and do not belong
  135 to an explicit partition or partition class.</para>
  136 
  137 <para>
  138 A partition class consists of a representation vector width (the
  139 number of Y values which the partition class encodes at once), a
  140 'subclass' value representing the number of alternate entropy books
  141 the partition class may use in representing Y values, the list of
  142 [subclass] books and a master book used to encode which alternate
  143 books were chosen for representation in a given packet.  The
  144 master/subclass mechanism is meant to be used as a flexible
  145 representation cascade while still using codebooks only in a scalar
  146 context.</para>
  147 
  148 <screen>
  149 
  150   1) [floor1_partitions] = read 5 bits as unsigned integer
  151   2) [maximum_class] = -1
  152   3) iterate [i] over the range 0 ... [floor1_partitions]-1 {
  153        
  154         4) vector [floor1_partition_class_list] element [i] = read 4 bits as unsigned integer
  155 
  156      }
  157 
  158   5) [maximum_class] = largest integer scalar value in vector [floor1_partition_class_list]
  159   6) iterate [i] over the range 0 ... [maximum_class] {
  160 
  161         7) vector [floor1_class_dimensions] element [i] = read 3 bits as unsigned integer and add 1
  162     8) vector [floor1_class_subclasses] element [i] = read 2 bits as unsigned integer
  163         9) if ( vector [floor1_class_subclasses] element [i] is nonzero ) {
  164             
  165              10) vector [floor1_class_masterbooks] element [i] = read 8 bits as unsigned integer
  166            
  167            }
  168 
  169        11) iterate [j] over the range 0 ... (2 exponent [floor1_class_subclasses] element [i]) - 1  {
  170 
  171              12) array [floor1_subclass_books] element [i],[j] = 
  172                  read 8 bits as unsigned integer and subtract one
  173            }
  174       }
  175 
  176  13) [floor1_multiplier] = read 2 bits as unsigned integer and add one
  177  14) [rangebits] = read 4 bits as unsigned integer
  178  15) vector [floor1_X_list] element [0] = 0
  179  16) vector [floor1_X_list] element [1] = 2 exponent [rangebits];
  180  17) [floor1_values] = 2
  181  18) iterate [i] over the range 0 ... [floor1_partitions]-1 {
  182 
  183        19) [current_class_number] = vector [floor1_partition_class_list] element [i]
  184        20) iterate [j] over the range 0 ... ([floor1_class_dimensions] element [current_class_number])-1 {
  185              21) vector [floor1_X_list] element ([j] + [floor1_values]) = 
  186                  read [rangebits] bits as unsigned integer
  187              22) increment [floor1_values] by one
  188            }
  189      }
  190  
  191  23) done
  192 </screen>
  193 
  194 <para>
  195 An end-of-packet condition while reading any aspect of a floor 1
  196 configuration during setup renders a stream undecodable.  In
  197 addition, a <varname>[floor1_class_masterbooks]</varname> or
  198 <varname>[floor1_subclass_books]</varname> scalar element greater than the
  199 highest numbered codebook configured in this stream is an error
  200 condition that renders the stream undecodable.</para>
  201 
  202 <section id="vorbis-spec-floor1-decode">
  203 <title>packet decode</title>
  204 
  205 <para>
  206 Packet decode begins by checking the <varname>[nonzero]</varname> flag:</para>
  207 
  208 <screen>
  209   1) [nonzero] = read 1 bit as boolean
  210 </screen>
  211 
  212 <para>
  213 If <varname>[nonzero]</varname> is unset, that indicates this channel contained
  214 no audio energy in this frame.  Decode immediately returns a status
  215 indicating this floor curve (and thus this channel) is unused this
  216 frame.  (A return status of 'unused' is different from decoding a
  217 floor that has all points set to minimum representation amplitude,
  218 which happens to be approximately -140dB).
  219 </para>
  220 
  221 <para>
  222 Assuming <varname>[nonzero]</varname> is set, decode proceeds as follows:</para>
  223 
  224 <screen>
  225   1) [range] = vector { 256, 128, 86, 64 } element ([floor1_multiplier]-1)
  226   2) vector [floor1_Y] element [0] = read <link linkend="vorbis-spec-ilog">ilog</link>([range]-1) bits as unsigned integer
  227   3) vector [floor1_Y] element [1] = read <link linkend="vorbis-spec-ilog">ilog</link>([range]-1) bits as unsigned integer
  228   4) [offset] = 2;
  229   5) iterate [i] over the range 0 ... [floor1_partitions]-1 {
  230 
  231        6) [class] = vector [floor1_partition_class]  element [i]
  232        7) [cdim]  = vector [floor1_class_dimensions] element [class]
  233        8) [cbits] = vector [floor1_class_subclasses] element [class]
  234        9) [csub]  = (2 exponent [cbits])-1
  235       10) [cval]  = 0
  236       11) if ( [cbits] is greater than zero ) {
  237  
  238              12) [cval] = read from packet using codebook number
  239                  (vector [floor1_class_masterbooks] element [class]) in scalar context
  240           }
  241       
  242       13) iterate [j] over the range 0 ... [cdim]-1 {
  243        
  244              14) [book] = array [floor1_subclass_books] element [class],([cval] bitwise AND [csub])
  245              15) [cval] = [cval] right shifted [cbits] bits
  246          16) if ( [book] is not less than zero ) {
  247          
  248                17) vector [floor1_Y] element ([j]+[offset]) = read from packet using codebook 
  249                        [book] in scalar context
  250 
  251                  } else [book] is less than zero {
  252 
  253                18) vector [floor1_Y] element ([j]+[offset]) = 0
  254 
  255                  }
  256           }
  257              
  258       19) [offset] = [offset] + [cdim]
  259          
  260      }
  261   
  262  20) done
  263 </screen>
  264 
  265 <para>
  266 An end-of-packet condition during curve decode should be considered a
  267 nominal occurrence; if end-of-packet is reached during any read
  268 operation above, floor decode is to return 'unused' status as if the
  269 <varname>[nonzero]</varname> flag had been unset at the beginning of decode.
  270 </para>
  271 
  272 <para>
  273 Vector <varname>[floor1_Y]</varname> contains the values from packet decode
  274 needed for floor 1 synthesis.</para>
  275 
  276 </section>
  277 
  278 <section id="vorbis-spec-floor1-synth">
  279 <title>curve computation</title>
  280 
  281 <para>
  282 Curve computation is split into two logical steps; the first step
  283 derives final Y amplitude values from the encoded, wrapped difference
  284 values taken from the bitstream.  The second step plots the curve
  285 lines.  Also, although zero-difference values are used in the
  286 iterative prediction to find final Y values, these points are
  287 conditionally skipped during final line computation in step two.
  288 Skipping zero-difference values allows a smoother line fit.  </para>
  289 
  290 <para>
  291 Although some aspects of the below algorithm look like inconsequential
  292 optimizations, implementors are warned to follow the details closely.
  293 Deviation from implementing a strictly equivalent algorithm can result
  294 in serious decoding errors.</para>
  295 
  296 <section>
  297 <title>step 1: amplitude value synthesis</title>
  298 
  299 <para>
  300 Unwrap the always-positive-or-zero values read from the packet into
  301 +/- difference values, then apply to line prediction.</para>
  302 
  303 <screen>
  304   1) [range] = vector { 256, 128, 86, 64 } element ([floor1_multiplier]-1)
  305   2) vector [floor1_step2_flag] element [0] = set
  306   3) vector [floor1_step2_flag] element [1] = set
  307   4) vector [floor1_final_Y] element [0] = vector [floor1_Y] element [0]
  308   5) vector [floor1_final_Y] element [1] = vector [floor1_Y] element [1]
  309   6) iterate [i] over the range 2 ... [floor1_values]-1 {
  310     
  311        7) [low_neighbor_offset] = <link linkend="vorbis-spec-low_neighbor">low_neighbor</link>([floor1_X_list],[i])
  312        8) [high_neighbor_offset] = <link linkend="vorbis-spec-high_neighbor">high_neighbor</link>([floor1_X_list],[i])
  313 
  314        9) [predicted] = <link linkend="vorbis-spec-render_point">render_point</link>( vector [floor1_X_list] element [low_neighbor_offset],
  315                       vector [floor1_final_Y] element [low_neighbor_offset],
  316                                       vector [floor1_X_list] element [high_neighbor_offset],
  317                       vector [floor1_final_Y] element [high_neighbor_offset],
  318                                       vector [floor1_X_list] element [i] )
  319 
  320       10) [val] = vector [floor1_Y] element [i]
  321       11) [highroom] = [range] - [predicted]
  322       12) [lowroom]  = [predicted]
  323       13) if ( [highroom] is less than [lowroom] ) {
  324 
  325             14) [room] = [highroom] * 2
  326          
  327           } else [highroom] is not less than [lowroom] {
  328               
  329             15) [root] = [lowroom] * 2
  330         
  331           }
  332 
  333       16) if ( [val] is nonzero ) {
  334 
  335             17) vector [floor1_step2_flag] element [low_neighbor_offset] = set
  336             18) vector [floor1_step2_flag] element [high_neighbor_offset] = set
  337             19) vector [floor1_step2_flag] element [i] = set
  338             20) if ( [val] is greater than or equal to [room] ) {
  339  
  340                   21) if ( [highroom] is greater than [lowroom] ) {
  341 
  342                         22) vector [floor1_final_Y] element [i] = [val] - [lowroom] + [predicted]
  343              
  344               } else [highroom] is not greater than [lowroom] {
  345               
  346                         23) vector [floor1_final_Y] element [i] = [predicted] - [val] + [highroom] - 1
  347                    
  348                       }
  349                
  350                 } else [val] is less than [room] {
  351          
  352           24) if ([val] is odd) {
  353                  
  354                         25) vector [floor1_final_Y] element [i] = 
  355                             [predicted] - (([val] + 1) divided by  2 using integer division)
  356 
  357                       } else [val] is even {
  358 
  359                         26) vector [floor1_final_Y] element [i] = 
  360                             [predicted] + ([val] / 2 using integer division)
  361                           
  362                       }
  363 
  364                 }      
  365 
  366           } else [val] is zero {
  367 
  368             27) vector [floor1_step2_flag] element [i] = unset
  369             28) vector [floor1_final_Y] element [i] = [predicted]
  370 
  371           }
  372 
  373      }
  374 
  375  29) done
  376 
  377 </screen>
  378 
  379 </section>
  380 
  381 <section>
  382 <title>step 2: curve synthesis</title>
  383 
  384 <para>
  385 Curve synthesis generates a return vector <varname>[floor]</varname> of length
  386 <varname>[n]</varname> (where <varname>[n]</varname> is provided by the decode process
  387 calling to floor decode).  Floor 1 curve synthesis makes use of the
  388 <varname>[floor1_X_list]</varname>, <varname>[floor1_final_Y]</varname> and
  389 <varname>[floor1_step2_flag]</varname> vectors, as well as [floor1_multiplier]
  390 and [floor1_values] values.</para>
  391 
  392 <para>
  393 Decode begins by sorting the scalars from vectors
  394 <varname>[floor1_X_list]</varname>, <varname>[floor1_final_Y]</varname> and
  395 <varname>[floor1_step2_flag]</varname> together into new vectors
  396 <varname>[floor1_X_list]'</varname>, <varname>[floor1_final_Y]'</varname> and
  397 <varname>[floor1_step2_flag]'</varname> according to ascending sort order of the
  398 values in <varname>[floor1_X_list]</varname>.  That is, sort the values of
  399 <varname>[floor1_X_list]</varname> and then apply the same permutation to
  400 elements of the other two vectors so that the X, Y and step2_flag
  401 values still match.</para>
  402 
  403 <para>
  404 Then compute the final curve in one pass:</para>
  405 
  406 <screen>
  407   1) [hx] = 0
  408   2) [lx] = 0
  409   3) [ly] = vector [floor1_final_Y]' element [0] * [floor1_multiplier]
  410   4) iterate [i] over the range 1 ... [floor1_values]-1 {
  411 
  412        5) if ( [floor1_step2_flag]' is set ) {
  413 
  414              6) [hy] = [floor1_final_Y]' element [i] * [floor1_multiplier]
  415          7) [hx] = [floor1_X_list]' element [i]
  416              8) <link linkend="vorbis-spec-render_line">render_line</link>( [lx], [ly], [hx], [hy], [floor] )
  417              9) [lx] = [hx]
  418         10) [ly] = [hy]
  419           }
  420      }
  421  
  422  11) if ( [hx] is less than [n] ) {
  423 
  424         12) <link linkend="vorbis-spec-render_line">render_line</link>( [hx], [hy], [n], [hy], [floor] )
  425 
  426      }
  427 
  428  13) if ( [hx] is greater than [n] ) {
  429 
  430             14) truncate vector [floor] to [n] elements
  431 
  432      }
  433  
  434  15) for each scalar in vector [floor], perform a lookup substitution using 
  435      the scalar value from [floor] as an offset into the vector <link linkend="vorbis-spec-floor1_inverse_dB_table">[floor1_inverse_dB_static_table]</link>
  436 
  437  16) done
  438 
  439 </screen>
  440 
  441 </section>
  442 
  443 </section>
  444 
  445 </section>
  446 </section>
  447 </section>
  448