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