Mercurial > hg > sv-dependency-builds
comparison src/libvorbis-1.3.3/doc/07-floor1.tex @ 1:05aa0afa9217
Bring in flac, ogg, vorbis
author | Chris Cannam |
---|---|
date | Tue, 19 Mar 2013 17:37:49 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:c7265573341e | 1:05aa0afa9217 |
---|---|
1 % -*- mode: latex; TeX-master: "Vorbis_I_spec"; -*- | |
2 %!TEX root = Vorbis_I_spec.tex | |
3 % $Id$ | |
4 \section{Floor type 1 setup and decode} \label{vorbis:spec:floor1} | |
5 | |
6 \subsection{Overview} | |
7 | |
8 Vorbis floor type one uses a piecewise straight-line representation to | |
9 encode a spectral envelope curve. The representation plots this curve | |
10 mechanically on a linear frequency axis and a logarithmic (dB) | |
11 amplitude axis. The integer plotting algorithm used is similar to | |
12 Bresenham's algorithm. | |
13 | |
14 | |
15 | |
16 \subsection{Floor 1 format} | |
17 | |
18 \subsubsection{model} | |
19 | |
20 Floor type one represents a spectral curve as a series of | |
21 line segments. Synthesis constructs a floor curve using iterative | |
22 prediction in a process roughly equivalent to the following simplified | |
23 description: | |
24 | |
25 \begin{itemize} | |
26 \item the first line segment (base case) is a logical line spanning | |
27 from x_0,y_0 to x_1,y_1 where in the base case x_0=0 and x_1=[n], the | |
28 full range of the spectral floor to be computed. | |
29 | |
30 \item the induction step chooses a point x_new within an existing | |
31 logical line segment and produces a y_new value at that point computed | |
32 from the existing line's y value at x_new (as plotted by the line) and | |
33 a difference value decoded from the bitstream packet. | |
34 | |
35 \item floor computation produces two new line segments, one running from | |
36 x_0,y_0 to x_new,y_new and from x_new,y_new to x_1,y_1. This step is | |
37 performed logically even if y_new represents no change to the | |
38 amplitude value at x_new so that later refinement is additionally | |
39 bounded at x_new. | |
40 | |
41 \item the induction step repeats, using a list of x values specified in | |
42 the codec setup header at floor 1 initialization time. Computation | |
43 is completed at the end of the x value list. | |
44 | |
45 \end{itemize} | |
46 | |
47 | |
48 Consider the following example, with values chosen for ease of | |
49 understanding rather than representing typical configuration: | |
50 | |
51 For the below example, we assume a floor setup with an [n] of 128. | |
52 The list of selected X values in increasing order is | |
53 0,16,32,48,64,80,96,112 and 128. In list order, the values interleave | |
54 as 0, 128, 64, 32, 96, 16, 48, 80 and 112. The corresponding | |
55 list-order Y values as decoded from an example packet are 110, 20, -5, | |
56 -45, 0, -25, -10, 30 and -10. We compute the floor in the following | |
57 way, beginning with the first line: | |
58 | |
59 \begin{center} | |
60 \includegraphics[width=8cm]{floor1-1} | |
61 \captionof{figure}{graph of example floor} | |
62 \end{center} | |
63 | |
64 We now draw new logical lines to reflect the correction to new_Y, and | |
65 iterate for X positions 32 and 96: | |
66 | |
67 \begin{center} | |
68 \includegraphics[width=8cm]{floor1-2} | |
69 \captionof{figure}{graph of example floor} | |
70 \end{center} | |
71 | |
72 Although the new Y value at X position 96 is unchanged, it is still | |
73 used later as an endpoint for further refinement. From here on, the | |
74 pattern should be clear; we complete the floor computation as follows: | |
75 | |
76 \begin{center} | |
77 \includegraphics[width=8cm]{floor1-3} | |
78 \captionof{figure}{graph of example floor} | |
79 \end{center} | |
80 | |
81 \begin{center} | |
82 \includegraphics[width=8cm]{floor1-4} | |
83 \captionof{figure}{graph of example floor} | |
84 \end{center} | |
85 | |
86 A more efficient algorithm with carefully defined integer rounding | |
87 behavior is used for actual decode, as described later. The actual | |
88 algorithm splits Y value computation and line plotting into two steps | |
89 with modifications to the above algorithm to eliminate noise | |
90 accumulation through integer roundoff/truncation. | |
91 | |
92 | |
93 | |
94 \subsubsection{header decode} | |
95 | |
96 A list of floor X values is stored in the packet header in interleaved | |
97 format (used in list order during packet decode and synthesis). This | |
98 list is split into partitions, and each partition is assigned to a | |
99 partition class. X positions 0 and [n] are implicit and do not belong | |
100 to an explicit partition or partition class. | |
101 | |
102 A partition class consists of a representation vector width (the | |
103 number of Y values which the partition class encodes at once), a | |
104 'subclass' value representing the number of alternate entropy books | |
105 the partition class may use in representing Y values, the list of | |
106 [subclass] books and a master book used to encode which alternate | |
107 books were chosen for representation in a given packet. The | |
108 master/subclass mechanism is meant to be used as a flexible | |
109 representation cascade while still using codebooks only in a scalar | |
110 context. | |
111 | |
112 \begin{Verbatim}[commandchars=\\\{\}] | |
113 | |
114 1) [floor1\_partitions] = read 5 bits as unsigned integer | |
115 2) [maximum\_class] = -1 | |
116 3) iterate [i] over the range 0 ... [floor1\_partitions]-1 \{ | |
117 | |
118 4) vector [floor1\_partition\_class\_list] element [i] = read 4 bits as unsigned integer | |
119 | |
120 \} | |
121 | |
122 5) [maximum\_class] = largest integer scalar value in vector [floor1\_partition\_class\_list] | |
123 6) iterate [i] over the range 0 ... [maximum\_class] \{ | |
124 | |
125 7) vector [floor1\_class\_dimensions] element [i] = read 3 bits as unsigned integer and add 1 | |
126 8) vector [floor1\_class\_subclasses] element [i] = read 2 bits as unsigned integer | |
127 9) if ( vector [floor1\_class\_subclasses] element [i] is nonzero ) \{ | |
128 | |
129 10) vector [floor1\_class\_masterbooks] element [i] = read 8 bits as unsigned integer | |
130 | |
131 \} | |
132 | |
133 11) iterate [j] over the range 0 ... (2 exponent [floor1\_class\_subclasses] element [i]) - 1 \{ | |
134 | |
135 12) array [floor1\_subclass\_books] element [i],[j] = | |
136 read 8 bits as unsigned integer and subtract one | |
137 \} | |
138 \} | |
139 | |
140 13) [floor1\_multiplier] = read 2 bits as unsigned integer and add one | |
141 14) [rangebits] = read 4 bits as unsigned integer | |
142 15) vector [floor1\_X\_list] element [0] = 0 | |
143 16) vector [floor1\_X\_list] element [1] = 2 exponent [rangebits]; | |
144 17) [floor1\_values] = 2 | |
145 18) iterate [i] over the range 0 ... [floor1\_partitions]-1 \{ | |
146 | |
147 19) [current\_class\_number] = vector [floor1\_partition\_class\_list] element [i] | |
148 20) iterate [j] over the range 0 ... ([floor1\_class\_dimensions] element [current\_class\_number])-1 \{ | |
149 21) vector [floor1\_X\_list] element ([floor1\_values]) = | |
150 read [rangebits] bits as unsigned integer | |
151 22) increment [floor1\_values] by one | |
152 \} | |
153 \} | |
154 | |
155 23) done | |
156 \end{Verbatim} | |
157 | |
158 An end-of-packet condition while reading any aspect of a floor 1 | |
159 configuration during setup renders a stream undecodable. In addition, | |
160 a \varname{[floor1\_class\_masterbooks]} or | |
161 \varname{[floor1\_subclass\_books]} scalar element greater than the | |
162 highest numbered codebook configured in this stream is an error | |
163 condition that renders the stream undecodable. Vector | |
164 [floor1\_x\_list] is limited to a maximum length of 65 elements; a | |
165 setup indicating more than 65 total elements (including elements 0 and | |
166 1 set prior to the read loop) renders the stream undecodable. All | |
167 vector [floor1\_x\_list] element values must be unique within the | |
168 vector; a non-unique value renders the stream undecodable. | |
169 | |
170 \subsubsection{packet decode} \label{vorbis:spec:floor1-decode} | |
171 | |
172 Packet decode begins by checking the \varname{[nonzero]} flag: | |
173 | |
174 \begin{Verbatim}[commandchars=\\\{\}] | |
175 1) [nonzero] = read 1 bit as boolean | |
176 \end{Verbatim} | |
177 | |
178 If \varname{[nonzero]} is unset, that indicates this channel contained | |
179 no audio energy in this frame. Decode immediately returns a status | |
180 indicating this floor curve (and thus this channel) is unused this | |
181 frame. (A return status of 'unused' is different from decoding a | |
182 floor that has all points set to minimum representation amplitude, | |
183 which happens to be approximately -140dB). | |
184 | |
185 | |
186 Assuming \varname{[nonzero]} is set, decode proceeds as follows: | |
187 | |
188 \begin{Verbatim}[commandchars=\\\{\}] | |
189 1) [range] = vector \{ 256, 128, 86, 64 \} element ([floor1\_multiplier]-1) | |
190 2) vector [floor1\_Y] element [0] = read \link{vorbis:spec:ilog}{ilog}([range]-1) bits as unsigned integer | |
191 3) vector [floor1\_Y] element [1] = read \link{vorbis:spec:ilog}{ilog}([range]-1) bits as unsigned integer | |
192 4) [offset] = 2; | |
193 5) iterate [i] over the range 0 ... [floor1\_partitions]-1 \{ | |
194 | |
195 6) [class] = vector [floor1\_partition\_class] element [i] | |
196 7) [cdim] = vector [floor1\_class\_dimensions] element [class] | |
197 8) [cbits] = vector [floor1\_class\_subclasses] element [class] | |
198 9) [csub] = (2 exponent [cbits])-1 | |
199 10) [cval] = 0 | |
200 11) if ( [cbits] is greater than zero ) \{ | |
201 | |
202 12) [cval] = read from packet using codebook number | |
203 (vector [floor1\_class\_masterbooks] element [class]) in scalar context | |
204 \} | |
205 | |
206 13) iterate [j] over the range 0 ... [cdim]-1 \{ | |
207 | |
208 14) [book] = array [floor1\_subclass\_books] element [class],([cval] bitwise AND [csub]) | |
209 15) [cval] = [cval] right shifted [cbits] bits | |
210 16) if ( [book] is not less than zero ) \{ | |
211 | |
212 17) vector [floor1\_Y] element ([j]+[offset]) = read from packet using codebook | |
213 [book] in scalar context | |
214 | |
215 \} else [book] is less than zero \{ | |
216 | |
217 18) vector [floor1\_Y] element ([j]+[offset]) = 0 | |
218 | |
219 \} | |
220 \} | |
221 | |
222 19) [offset] = [offset] + [cdim] | |
223 | |
224 \} | |
225 | |
226 20) done | |
227 \end{Verbatim} | |
228 | |
229 An end-of-packet condition during curve decode should be considered a | |
230 nominal occurrence; if end-of-packet is reached during any read | |
231 operation above, floor decode is to return 'unused' status as if the | |
232 \varname{[nonzero]} flag had been unset at the beginning of decode. | |
233 | |
234 | |
235 Vector \varname{[floor1\_Y]} contains the values from packet decode | |
236 needed for floor 1 synthesis. | |
237 | |
238 | |
239 | |
240 \subsubsection{curve computation} \label{vorbis:spec:floor1-synth} | |
241 | |
242 Curve computation is split into two logical steps; the first step | |
243 derives final Y amplitude values from the encoded, wrapped difference | |
244 values taken from the bitstream. The second step plots the curve | |
245 lines. Also, although zero-difference values are used in the | |
246 iterative prediction to find final Y values, these points are | |
247 conditionally skipped during final line computation in step two. | |
248 Skipping zero-difference values allows a smoother line fit. | |
249 | |
250 Although some aspects of the below algorithm look like inconsequential | |
251 optimizations, implementors are warned to follow the details closely. | |
252 Deviation from implementing a strictly equivalent algorithm can result | |
253 in serious decoding errors. | |
254 | |
255 {\em Additional note:} Although \varname{[floor1\_final\_Y]} values in | |
256 the prediction loop and at the end of step 1 are inherently limited by | |
257 the prediction algorithm to [0, \varname{[range]}), it is possible to | |
258 abuse the setup and codebook machinery to produce negative or | |
259 over-range results. We suggest that decoder implementations guard | |
260 the values in vector \varname{[floor1\_final\_Y]} by clamping each | |
261 element to [0, \varname{[range]}) after step 1. Variants of this | |
262 suggestion are acceptable as valid floor1 setups cannot produce | |
263 out of range values. | |
264 | |
265 \begin{description} | |
266 \item[step 1: amplitude value synthesis] | |
267 | |
268 Unwrap the always-positive-or-zero values read from the packet into | |
269 +/- difference values, then apply to line prediction. | |
270 | |
271 \begin{Verbatim}[commandchars=\\\{\}] | |
272 1) [range] = vector \{ 256, 128, 86, 64 \} element ([floor1\_multiplier]-1) | |
273 2) vector [floor1\_step2\_flag] element [0] = set | |
274 3) vector [floor1\_step2\_flag] element [1] = set | |
275 4) vector [floor1\_final\_Y] element [0] = vector [floor1\_Y] element [0] | |
276 5) vector [floor1\_final\_Y] element [1] = vector [floor1\_Y] element [1] | |
277 6) iterate [i] over the range 2 ... [floor1\_values]-1 \{ | |
278 | |
279 7) [low\_neighbor\_offset] = \link{vorbis:spec:low:neighbor}{low\_neighbor}([floor1\_X\_list],[i]) | |
280 8) [high\_neighbor\_offset] = \link{vorbis:spec:high:neighbor}{high\_neighbor}([floor1\_X\_list],[i]) | |
281 | |
282 9) [predicted] = \link{vorbis:spec:render:point}{render\_point}( vector [floor1\_X\_list] element [low\_neighbor\_offset], | |
283 vector [floor1\_final\_Y] element [low\_neighbor\_offset], | |
284 vector [floor1\_X\_list] element [high\_neighbor\_offset], | |
285 vector [floor1\_final\_Y] element [high\_neighbor\_offset], | |
286 vector [floor1\_X\_list] element [i] ) | |
287 | |
288 10) [val] = vector [floor1\_Y] element [i] | |
289 11) [highroom] = [range] - [predicted] | |
290 12) [lowroom] = [predicted] | |
291 13) if ( [highroom] is less than [lowroom] ) \{ | |
292 | |
293 14) [room] = [highroom] * 2 | |
294 | |
295 \} else [highroom] is not less than [lowroom] \{ | |
296 | |
297 15) [room] = [lowroom] * 2 | |
298 | |
299 \} | |
300 | |
301 16) if ( [val] is nonzero ) \{ | |
302 | |
303 17) vector [floor1\_step2\_flag] element [low\_neighbor\_offset] = set | |
304 18) vector [floor1\_step2\_flag] element [high\_neighbor\_offset] = set | |
305 19) vector [floor1\_step2\_flag] element [i] = set | |
306 20) if ( [val] is greater than or equal to [room] ) \{ | |
307 | |
308 21) if ( [highroom] is greater than [lowroom] ) \{ | |
309 | |
310 22) vector [floor1\_final\_Y] element [i] = [val] - [lowroom] + [predicted] | |
311 | |
312 \} else [highroom] is not greater than [lowroom] \{ | |
313 | |
314 23) vector [floor1\_final\_Y] element [i] = [predicted] - [val] + [highroom] - 1 | |
315 | |
316 \} | |
317 | |
318 \} else [val] is less than [room] \{ | |
319 | |
320 24) if ([val] is odd) \{ | |
321 | |
322 25) vector [floor1\_final\_Y] element [i] = | |
323 [predicted] - (([val] + 1) divided by 2 using integer division) | |
324 | |
325 \} else [val] is even \{ | |
326 | |
327 26) vector [floor1\_final\_Y] element [i] = | |
328 [predicted] + ([val] / 2 using integer division) | |
329 | |
330 \} | |
331 | |
332 \} | |
333 | |
334 \} else [val] is zero \{ | |
335 | |
336 27) vector [floor1\_step2\_flag] element [i] = unset | |
337 28) vector [floor1\_final\_Y] element [i] = [predicted] | |
338 | |
339 \} | |
340 | |
341 \} | |
342 | |
343 29) done | |
344 | |
345 \end{Verbatim} | |
346 | |
347 | |
348 | |
349 \item[step 2: curve synthesis] | |
350 | |
351 Curve synthesis generates a return vector \varname{[floor]} of length | |
352 \varname{[n]} (where \varname{[n]} is provided by the decode process | |
353 calling to floor decode). Floor 1 curve synthesis makes use of the | |
354 \varname{[floor1\_X\_list]}, \varname{[floor1\_final\_Y]} and | |
355 \varname{[floor1\_step2\_flag]} vectors, as well as [floor1\_multiplier] | |
356 and [floor1\_values] values. | |
357 | |
358 Decode begins by sorting the scalars from vectors | |
359 \varname{[floor1\_X\_list]}, \varname{[floor1\_final\_Y]} and | |
360 \varname{[floor1\_step2\_flag]} together into new vectors | |
361 \varname{[floor1\_X\_list]'}, \varname{[floor1\_final\_Y]'} and | |
362 \varname{[floor1\_step2\_flag]'} according to ascending sort order of the | |
363 values in \varname{[floor1\_X\_list]}. That is, sort the values of | |
364 \varname{[floor1\_X\_list]} and then apply the same permutation to | |
365 elements of the other two vectors so that the X, Y and step2\_flag | |
366 values still match. | |
367 | |
368 Then compute the final curve in one pass: | |
369 | |
370 \begin{Verbatim}[commandchars=\\\{\}] | |
371 1) [hx] = 0 | |
372 2) [lx] = 0 | |
373 3) [ly] = vector [floor1\_final\_Y]' element [0] * [floor1\_multiplier] | |
374 4) iterate [i] over the range 1 ... [floor1\_values]-1 \{ | |
375 | |
376 5) if ( [floor1\_step2\_flag]' element [i] is set ) \{ | |
377 | |
378 6) [hy] = [floor1\_final\_Y]' element [i] * [floor1\_multiplier] | |
379 7) [hx] = [floor1\_X\_list]' element [i] | |
380 8) \link{vorbis:spec:render:line}{render\_line}( [lx], [ly], [hx], [hy], [floor] ) | |
381 9) [lx] = [hx] | |
382 10) [ly] = [hy] | |
383 \} | |
384 \} | |
385 | |
386 11) if ( [hx] is less than [n] ) \{ | |
387 | |
388 12) \link{vorbis:spec:render:line}{render\_line}( [hx], [hy], [n], [hy], [floor] ) | |
389 | |
390 \} | |
391 | |
392 13) if ( [hx] is greater than [n] ) \{ | |
393 | |
394 14) truncate vector [floor] to [n] elements | |
395 | |
396 \} | |
397 | |
398 15) for each scalar in vector [floor], perform a lookup substitution using | |
399 the scalar value from [floor] as an offset into the vector \link{vorbis:spec:floor1:inverse:dB:table}{[floor1\_inverse\_dB\_static\_table]} | |
400 | |
401 16) done | |
402 | |
403 \end{Verbatim} | |
404 | |
405 \end{description} |