summaryrefslogtreecommitdiff
path: root/audio_codec/libcook/rasl.c (plain)
blob: 63ca73eebfc38305288fe8f5835c22bd0e843177
1/* ***** BEGIN LICENSE BLOCK *****
2 * Source last modified: $Id: rasl.c,v 1.1.1.1.2.1 2005/05/04 18:21:33 hubbe Exp $
3 *
4 * REALNETWORKS CONFIDENTIAL--NOT FOR DISTRIBUTION IN SOURCE CODE FORM
5 * Portions Copyright (c) 1995-2005 RealNetworks, Inc.
6 * All Rights Reserved.
7 *
8 * The contents of this file, and the files included with this file,
9 * are subject to the current version of the Real Format Source Code
10 * Porting and Optimization License, available at
11 * https://helixcommunity.org/2005/license/realformatsource (unless
12 * RealNetworks otherwise expressly agrees in writing that you are
13 * subject to a different license). You may also obtain the license
14 * terms directly from RealNetworks. You may not use this file except
15 * in compliance with the Real Format Source Code Porting and
16 * Optimization License. There are no redistribution rights for the
17 * source code of this file. Please see the Real Format Source Code
18 * Porting and Optimization License for the rights, obligations and
19 * limitations governing use of the contents of the file.
20 *
21 * RealNetworks is the developer of the Original Code and owns the
22 * copyrights in the portions it created.
23 *
24 * This file, and the files included with this file, is distributed and
25 * made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND,
26 * EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL
27 * SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT
29 * OR NON-INFRINGEMENT.
30 *
31 * Technology Compatibility Kit Test Suite(s) Location:
32 * https://rarvcode-tck.helixcommunity.org
33 *
34 * Contributor(s):
35 *
36 * ***** END LICENSE BLOCK ***** */
37
38#include <memory.h>
39#include "helix_types.h"
40#include "rasl.h"
41
42/*
43 * The interleave table was created with the following properties:
44 * -equal contributions from each block
45 * -symmetric (if table[i] = j, then table[j] = i), allows in-place interleave
46 * -random spacing between lost frames, except
47 * -no double losses
48 * Solution was generated by a random-walk optimization loop.
49 *
50 */
51/* Loss patterns for a five-block solution:
52...X..X....X.X.....X.X.X........X..........X...X.X....X........X..X..X..X.......
53.X..X....X........X...X..X.....X.X........X...X....X...X..X......X....X.......X.
54..X..X.X.........X..........X.X...X...X..X...X.......X.....X.X.....X......X.X...
55..........X.X..X....X......X.X......X...X...X...X.X.....X.....X.X......X.X......
56X.......X.....X.X.......X.X........X.X.X............X....X..X.......X......X.X.X
57*/
58/*
59static int RASL_InterleaveTable[RASL_NFRAMES * RASL_NBLOCKS] = {
60 66, 21, 43, 3, 23, 47, 6, 32, 72, 19, 49, 11, 54, 13, 69, 63,
61 65, 42, 18, 9, 58, 1, 22, 4, 78, 25, 70, 51, 33, 55, 46, 31,
62 7, 28, 34, 74, 61, 76, 38, 67, 59, 41, 17, 2, 53, 45, 30, 5,
63 48, 10, 50, 27, 71, 44, 12, 29, 56, 73, 20, 40, 64, 36, 62, 15,
64 60, 16, 0, 39, 68, 14, 26, 52, 8, 57, 35, 75, 37, 77, 24, 79
65};
66*/
67
68/* Loss pattern for a six-block solution
69....X.X....X..........X........X....X..X....X........X....X....X....X....X.......X....X...X.....
70.X.....X..........X....X...X..X...X...........X...X...X..X...........X.X...X............X.....X.
71..X.......X..X......X...X............X...X.....X........X..X.....X....X...X..........X.X....X...
72X........X.....X.X........X..X..........X....X......X.......X.X.............X..X.........X...X.X
73............X.X.X....X......X...X..X.......X....X............X..X.X.....X.....X.X..X............
74...X.X..X..........X.....X.......X....X...X......X.X...X...........X.........X....X.X......X....
75*/
76static const int RASL_InterleaveTable[RASL_NFRAMES * RASL_NBLOCKS] = {
77 63, 22, 44, 90, 4, 81, 6, 31, 86, 58, 36, 11, 68, 39, 73, 53,
78 69, 57, 18, 88, 34, 71, 1, 23, 46, 94, 54, 27, 75, 50, 30, 7,
79 70, 92, 20, 74, 10, 37, 85, 13, 56, 41, 87, 65, 2, 59, 24, 47,
80 79, 93, 29, 89, 52, 15, 26, 95, 40, 17, 9, 45, 60, 76, 62, 0,
81 64, 43, 66, 83, 12, 16, 32, 21, 72, 14, 35, 28, 61, 80, 78, 48,
82 77, 5, 82, 67, 84, 38, 8, 42, 19, 51, 3, 91, 33, 49, 25, 55
83};
84
85/*
86 * DeInterleave operates in-place!.
87 *
88 * Entry:
89 * buf points to NCODEBYTES * NFRAMES * NBLOCKS bytes of interleaved data.
90 * If an input block is bad, flag[block] should be set.
91 *
92 * Exit:
93 * data in buf is deinterleaved.
94 * flags[block] stores a bit array for each output block,
95 * where (flags[block] & (1 << F)) is set if Fth frame is bad.
96 */
97void
98RASL_DeInterleave(char *buf, unsigned long ulBufSize, int type, ULONG32 * pFlags)
99{
100 char temp[RASL_MAXCODEBYTES]; /* space for swapping */ /* Flawfinder: ignore */
101 INT32 inFlags[RASL_NBLOCKS]; /* save input flags */
102 int nCodeBytes, nCodeBits;
103 int fi, fo; /* frame in/out */
104 int blk;
105 int bitOffsetTo, bitOffsetFrom; /* for bit maniputlations */
106 char *toPtr, *fromPtr; /* for bit maniputlations */
107 unsigned long ulToBufSize;
108 unsigned long ulFromBufSize;
109
110 nCodeBits = 0;
111 if (type == 0) {
112 nCodeBits = RA65_NCODEBITS;
113 }
114 if (type == 1) {
115 nCodeBits = RA85_NCODEBITS;
116 }
117 if (type == 2) {
118 nCodeBits = RA50_NCODEBITS;
119 }
120 if (type == 3) {
121 nCodeBits = RA160_NCODEBITS;
122 } else {
123 // wrong nCodeBits
124 while (1) {
125 ;
126 }
127 }
128
129
130 /* Save input flags, and initialize output flags */
131 if (pFlags)
132 for (blk = 0; blk < RASL_NBLOCKS; blk++) {
133 inFlags[blk] = pFlags[blk]; /* save input */
134 pFlags[blk] = 0; /* init output to no error */
135 }
136
137
138 if (nCodeBits % 8 == 0) {
139 nCodeBytes = nCodeBits >> 3;
140 for (fi = 0; fi < RASL_NFRAMES * RASL_NBLOCKS; fi++) {
141
142 fo = RASL_InterleaveTable[fi]; /* frame to swap with */
143 /*
144 * Note that when (fo == fi), the frame doesn't move,
145 * and if (fo < fi), we have swapped it already.
146 */
147 if (fo > fi) { /* do the swap if needed */
148 memcpy(temp, buf + fo * nCodeBytes, nCodeBytes); /* Flawfinder: ignore */
149 memcpy(buf + fo * nCodeBytes, buf + fi * nCodeBytes, nCodeBytes); /* Flawfinder: ignore */
150 memcpy(buf + fi * nCodeBytes, temp, nCodeBytes); /* Flawfinder: ignore */
151 }
152
153 /*
154 * If frame came from bad block, set bit corresponding to new position.
155 * Only check one of the swapped pair, since other will be done when
156 * fi gets there.
157 */
158 if (pFlags && inFlags[RASL_BLOCK_NUM(fi)]) {
159 pFlags[RASL_BLOCK_NUM(fo)] |= (1 << RASL_BLOCK_OFF(fo));
160 }
161 }
162 } else {
163 for (fi = 0; fi < RASL_NFRAMES * RASL_NBLOCKS; fi++) {
164
165 fo = RASL_InterleaveTable[fi]; /* frame to swap with */
166 /*
167 * Note that when (fo == fi), the frame doesn't move,
168 * and if (fo < fi), we have swapped it already.
169 */
170 if (fo > fi) { /* do the swap if needed */
171 toPtr = temp;
172 ulToBufSize = RASL_MAXCODEBYTES;
173 fromPtr = buf;
174 ulFromBufSize = ulBufSize;
175 bitOffsetTo = 0;
176 bitOffsetFrom = fo * nCodeBits;
177 ra_bitcopy((unsigned char *)toPtr, ulToBufSize, (unsigned char *)fromPtr, ulFromBufSize, bitOffsetTo, bitOffsetFrom, nCodeBits);
178
179 toPtr = buf;
180 ulToBufSize = ulBufSize;
181 fromPtr = buf;
182 ulFromBufSize = ulBufSize;
183 bitOffsetTo = fo * nCodeBits;
184 bitOffsetFrom = fi * nCodeBits;
185 ra_bitcopy((unsigned char *)toPtr, ulToBufSize, (unsigned char *)fromPtr, ulFromBufSize, bitOffsetTo, bitOffsetFrom, nCodeBits);
186
187 toPtr = buf;
188 ulToBufSize = ulBufSize;
189 fromPtr = temp;
190 ulFromBufSize = RASL_MAXCODEBYTES;
191 bitOffsetTo = fi * nCodeBits;
192 bitOffsetFrom = 0;
193 ra_bitcopy((unsigned char *)toPtr, ulToBufSize, (unsigned char *)fromPtr, ulFromBufSize, bitOffsetTo, bitOffsetFrom, nCodeBits);
194 }
195
196 /*
197 * If frame came from bad block, set bit corresponding to new position.
198 * Only check one of the swapped pair, since other will be done when
199 * fi gets there.
200 */
201 if (pFlags && inFlags[RASL_BLOCK_NUM(fi)]) {
202 pFlags[RASL_BLOCK_NUM(fo)] |= (1 << RASL_BLOCK_OFF(fo));
203 }
204 }
205 }
206}
207
208void ra_bitcopy(unsigned char* toPtr,
209 unsigned long ulToBufSize,
210 unsigned char* fromPtr,
211 unsigned long ulFromBufSize,
212 int bitOffsetTo,
213 int bitOffsetFrom,
214 int numBits)
215{
216 unsigned char* pToLimit = toPtr + ulToBufSize;
217 unsigned char* pFromLimit = fromPtr + ulFromBufSize;
218 int bofMod8, botMod8, nbMod8, eightMinusBotMod8, eightMinusBofMod8, i, iMax;
219 unsigned char rightInword, leftInword, *byteOffsetFrom, *byteOffsetTo,
220 alignWord, endWord;
221 unsigned char lmask[9] = {0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff}; /* Flawfinder: ignore */
222 unsigned char rmask[9] = {0, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff}; /* Flawfinder: ignore */
223
224 int nibbleAlignFrom, nibbleAlignTo, alignCase = 30; // special case variables
225 unsigned char mask[2] = {0x0f, 0xf0}; /* Flawfinder: ignore */
226
227 bofMod8 = bitOffsetFrom & 0x07; // same as %8
228 botMod8 = bitOffsetTo & 0x07;
229 nbMod8 = numBits & 0x07;
230 eightMinusBofMod8 = 8 - bofMod8; // don't want these evaluated every loop
231 eightMinusBotMod8 = 8 - botMod8;
232 byteOffsetFrom = fromPtr + (bitOffsetFrom >> 3);
233 byteOffsetTo = toPtr + (bitOffsetTo >> 3);
234 iMax = (numBits >> 3) - 1; // last output byte not handled inside a loop
235
236 if (numBits >> 3 == 0)
237 // quick and easy if we have fewer than 8 bits to align
238
239 {
240 leftInword = *(byteOffsetFrom++);
241 rightInword = *(byteOffsetFrom);
242 alignWord = (leftInword >> bofMod8) + (rightInword << (eightMinusBofMod8));
243 alignWord &= rmask[nbMod8];
244
245 if (nbMod8 >= eightMinusBotMod8) // have more extra input bits than
246 // free space in current output byte
247 {
248 *(byteOffsetTo) &= rmask[botMod8];
249 *(byteOffsetTo++) += (alignWord << botMod8);
250 *(byteOffsetTo) = ((*byteOffsetTo) & lmask[8 - (nbMod8 - eightMinusBotMod8)])
251 + (alignWord >> eightMinusBotMod8);
252 }
253
254 else // have fewer input bits than free space in current output byte
255 // be careful not to overwrite extra bits already in output byte
256 {
257 endWord = *(byteOffsetTo) & lmask[8 - (nbMod8 + botMod8)];
258 *(byteOffsetTo) &= rmask[botMod8];
259 *(byteOffsetTo) += ((alignWord << botMod8) + endWord);
260 }
261 return; // finished, return to calling function
262 }
263
264 if (bitOffsetFrom % 4 == 0 && bitOffsetTo % 4 == 0)
265 // byte-packing done here is optimized for the common case of nibble-alignment
266
267 {
268 nibbleAlignFrom = (bitOffsetFrom & 0x04) >> 2; // 0 implies whole-byte alignment
269 nibbleAlignTo = (bitOffsetTo & 0x04) >> 2; // 1 implies half-byte alignment
270
271
272 if (nibbleAlignFrom == nibbleAlignTo) // either src and dest both byte-aligned
273 // or both half byte-aligned
274 if (nibbleAlignFrom == 0) {
275 alignCase = 0;
276 } else {
277 alignCase = 3;
278 }
279
280
281 if (nibbleAlignFrom != nibbleAlignTo)
282 if (nibbleAlignFrom == 0) {
283 alignCase = 1; // src aligned, dest half aligned
284 } else {
285 alignCase = 2; // src half aligned, dest aligned
286 }
287
288 switch (alignCase) {
289 case 0:
290 for (i = 0; i < iMax; i++) {
291 *byteOffsetTo++ = *byteOffsetFrom++; // copy byte-by-byte directly
292 }
293 break;
294
295 case 1:
296 for (i = 0; i < iMax; i++) { // move two nibbles from src to dest each loop
297 // shift bits as necessary
298 *byteOffsetTo = (*byteOffsetTo & mask[0]) +
299 ((*byteOffsetFrom & mask[0]) << 4);
300 *++byteOffsetTo = ((*byteOffsetFrom++ & mask[1]) >> 4);
301 }
302 break;
303
304 case 2:
305 for (i = 0; i < iMax; i++) { // same as case 1, but shift other direction
306 *byteOffsetTo = ((*byteOffsetFrom & mask[1]) >> 4);
307 *byteOffsetTo++ += ((*++byteOffsetFrom & mask[0]) << 4);
308 }
309 break;
310
311 case 3: {
312 *byteOffsetTo &= mask[0]; // align first nibble, thereafter this is
313 *byteOffsetTo += (*byteOffsetFrom & mask[1]); // just like case 0
314 for (i = 0; i < iMax; i++) {
315 *++byteOffsetTo = *++byteOffsetFrom; // copy byte-by-byte directly
316 }
317 }
318 break;
319 }
320 }
321
322 else
323 // this code can handle all source and destination buffer offsets
324
325 {
326 // take the first 8 desired bits from the input buffer, store them
327 // in alignWord, then break up alignWord into two pieces to
328 // fit in the free space in two consecutive output buffer bytes
329
330 for (i = 0; i < iMax; i++) {
331 leftInword = *(byteOffsetFrom++);
332 rightInword = *(byteOffsetFrom);
333 alignWord = (leftInword >> bofMod8) + (rightInword << (eightMinusBofMod8));
334 *(byteOffsetTo) = (*(byteOffsetTo) & rmask[botMod8]) +
335 (alignWord << (botMod8));
336 *(++byteOffsetTo) = alignWord >> (eightMinusBotMod8);
337 }
338 }
339 // special section to set last byte in fromBuf correctly
340
341 // even if byte packing was done with the code optimized for nibble-alignment,
342 // the tricky job of setting the last output byte is still done here
343
344 leftInword = *(byteOffsetFrom++);
345 rightInword = *(byteOffsetFrom);
346 alignWord = (leftInword >> bofMod8) + (rightInword << (eightMinusBofMod8));
347 *(byteOffsetTo) = (*(byteOffsetTo) & rmask[botMod8]) +
348 (alignWord << (botMod8));
349
350 if (nbMod8 >= eightMinusBotMod8) {
351 *(++byteOffsetTo) = alignWord >> (eightMinusBotMod8);
352
353 leftInword = *(byteOffsetFrom++);
354 rightInword = *(byteOffsetFrom);
355 alignWord = (leftInword >> bofMod8) + (rightInword << (eightMinusBofMod8));
356 alignWord &= rmask[nbMod8];
357 *(byteOffsetTo++) += (alignWord << botMod8);
358 if (byteOffsetTo >= toPtr && byteOffsetTo < pToLimit) {
359 *(byteOffsetTo) = ((*byteOffsetTo) & lmask[8 - (nbMod8 - eightMinusBotMod8)])
360 + (alignWord >> eightMinusBotMod8);
361 }
362 }
363
364 else {
365 endWord = *(++byteOffsetTo) & lmask[8 - (nbMod8 + botMod8)];
366 *(byteOffsetTo) = alignWord >> (eightMinusBotMod8);
367 leftInword = *(byteOffsetFrom++);
368 rightInword = *(byteOffsetFrom);
369 alignWord = (leftInword >> bofMod8) + (rightInword << (eightMinusBofMod8));
370 alignWord &= rmask[nbMod8];
371 *(byteOffsetTo) += ((alignWord << botMod8) + endWord);
372 }
373
374
375}
376
377