diff options
Diffstat (limited to 'lib/rbcodec/codecs/libwavpack')
-rw-r--r-- | lib/rbcodec/codecs/libwavpack/LICENSE | 25 | ||||
-rw-r--r-- | lib/rbcodec/codecs/libwavpack/README | 52 | ||||
-rw-r--r-- | lib/rbcodec/codecs/libwavpack/README.rockbox | 15 | ||||
-rw-r--r-- | lib/rbcodec/codecs/libwavpack/SOURCES | 15 | ||||
-rw-r--r-- | lib/rbcodec/codecs/libwavpack/arm.S | 477 | ||||
-rw-r--r-- | lib/rbcodec/codecs/libwavpack/arml.S | 506 | ||||
-rw-r--r-- | lib/rbcodec/codecs/libwavpack/bits.c | 170 | ||||
-rw-r--r-- | lib/rbcodec/codecs/libwavpack/coldfire.S | 537 | ||||
-rw-r--r-- | lib/rbcodec/codecs/libwavpack/float.c | 47 | ||||
-rw-r--r-- | lib/rbcodec/codecs/libwavpack/libwavpack.make | 18 | ||||
-rw-r--r-- | lib/rbcodec/codecs/libwavpack/make.bat | 1 | ||||
-rw-r--r-- | lib/rbcodec/codecs/libwavpack/metadata.c | 171 | ||||
-rw-r--r-- | lib/rbcodec/codecs/libwavpack/pack.c | 470 | ||||
-rw-r--r-- | lib/rbcodec/codecs/libwavpack/unpack.c | 780 | ||||
-rw-r--r-- | lib/rbcodec/codecs/libwavpack/wavpack.h | 447 | ||||
-rw-r--r-- | lib/rbcodec/codecs/libwavpack/words.c | 786 | ||||
-rw-r--r-- | lib/rbcodec/codecs/libwavpack/wputils.c | 555 |
17 files changed, 5072 insertions, 0 deletions
diff --git a/lib/rbcodec/codecs/libwavpack/LICENSE b/lib/rbcodec/codecs/libwavpack/LICENSE new file mode 100644 index 0000000000..3ee485817d --- /dev/null +++ b/lib/rbcodec/codecs/libwavpack/LICENSE | |||
@@ -0,0 +1,25 @@ | |||
1 | Copyright (c) 1998 - 2004 Conifer Software | ||
2 | All rights reserved. | ||
3 | |||
4 | Redistribution and use in source and binary forms, with or without | ||
5 | modification, are permitted provided that the following conditions are met: | ||
6 | |||
7 | * Redistributions of source code must retain the above copyright notice, | ||
8 | this list of conditions and the following disclaimer. | ||
9 | * Redistributions in binary form must reproduce the above copyright notice, | ||
10 | this list of conditions and the following disclaimer in the | ||
11 | documentation and/or other materials provided with the distribution. | ||
12 | * Neither the name of Conifer Software nor the names of its contributors | ||
13 | may be used to endorse or promote products derived from this software | ||
14 | without specific prior written permission. | ||
15 | |||
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
19 | ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR | ||
20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||
22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||
23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||
24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
diff --git a/lib/rbcodec/codecs/libwavpack/README b/lib/rbcodec/codecs/libwavpack/README new file mode 100644 index 0000000000..b373235e1c --- /dev/null +++ b/lib/rbcodec/codecs/libwavpack/README | |||
@@ -0,0 +1,52 @@ | |||
1 | //////////////////////////////////////////////////////////////////////////// | ||
2 | // **** WAVPACK **** // | ||
3 | // Hybrid Lossless Wavefile Compressor // | ||
4 | // Copyright (c) 1998 - 2004 Conifer Software. // | ||
5 | // All Rights Reserved. // | ||
6 | // Distributed under the BSD Software License (see license.txt) // | ||
7 | //////////////////////////////////////////////////////////////////////////// | ||
8 | |||
9 | This package contains a tiny version of the WavPack 4.0 decoder that might | ||
10 | be used in a "resource limited" CPU environment or form the basis for a | ||
11 | hardware decoding implementation. It is packaged with a demo command-line | ||
12 | program that accepts a WavPack audio file on stdin and outputs a RIFF wav | ||
13 | file to stdout. The program is standard C, and a win32 executable is | ||
14 | included which was compiled under MS Visual C++ 6.0 using this command: | ||
15 | |||
16 | cl /O1 /DWIN32 wvfilter.c wputils.c unpack.c float.c metadata.c words.c bits.c | ||
17 | |||
18 | WavPack data is read with a stream reading callback. No direct seeking is | ||
19 | provided for, but it is possible to start decoding anywhere in a WavPack | ||
20 | stream. In this case, WavPack will be able to provide the sample-accurate | ||
21 | position when it synchs with the data and begins decoding. | ||
22 | |||
23 | For demonstration purposes this uses a single static copy of the | ||
24 | WavpackContext structure, so obviously it cannot be used for more than one | ||
25 | file at a time. Also, this decoder will not handle "correction" files, plays | ||
26 | only the first two channels of multi-channel files, and is limited in | ||
27 | resolution in some large integer or floating point files (but always | ||
28 | provides at least 24 bits of resolution). It also will not accept WavPack | ||
29 | files from before version 4.0. | ||
30 | |||
31 | To make this code viable on the greatest number of hardware platforms, the | ||
32 | following are true: | ||
33 | |||
34 | speed is about 4x realtime on an AMD K6 300 MHz | ||
35 | ("high" mode 16/44 stereo; normal mode is about twice that fast) | ||
36 | |||
37 | no floating-point math required; just 32b * 32b = 32b int multiply | ||
38 | |||
39 | large data areas are static and less than 4K total | ||
40 | executable code and tables are less than 32K | ||
41 | no malloc / free usage | ||
42 | |||
43 | To maintain compatibility on various platforms, the following conventions | ||
44 | are used: | ||
45 | |||
46 | a "short" must be 16-bits | ||
47 | a "long" must be 32-bits | ||
48 | an "int" must be at least 16-bits, but may be larger | ||
49 | a "char" must default to signed | ||
50 | |||
51 | |||
52 | Questions or comments should be directed to david@wavpack.com | ||
diff --git a/lib/rbcodec/codecs/libwavpack/README.rockbox b/lib/rbcodec/codecs/libwavpack/README.rockbox new file mode 100644 index 0000000000..a74b0c511c --- /dev/null +++ b/lib/rbcodec/codecs/libwavpack/README.rockbox | |||
@@ -0,0 +1,15 @@ | |||
1 | Library: wavpack - Release 4.1 - September 14, 2004 | ||
2 | Imported: 2005-02-25 by Christian Gmeiner | ||
3 | |||
4 | |||
5 | This directory contains a "tiny" decoder version of wavpack for version 4.x. | ||
6 | |||
7 | LICENSING INFORMATION | ||
8 | |||
9 | wavpack is released under the BSD License as described | ||
10 | in the LICENSE file in this directory. | ||
11 | |||
12 | |||
13 | IMPORT DETAILS | ||
14 | |||
15 | Excluded is wvfilter.c, because it is only a test programm. | ||
diff --git a/lib/rbcodec/codecs/libwavpack/SOURCES b/lib/rbcodec/codecs/libwavpack/SOURCES new file mode 100644 index 0000000000..b2518e59e0 --- /dev/null +++ b/lib/rbcodec/codecs/libwavpack/SOURCES | |||
@@ -0,0 +1,15 @@ | |||
1 | bits.c | ||
2 | float.c | ||
3 | metadata.c | ||
4 | unpack.c | ||
5 | pack.c | ||
6 | words.c | ||
7 | wputils.c | ||
8 | #if defined(CPU_COLDFIRE) | ||
9 | coldfire.S | ||
10 | #endif | ||
11 | #if defined(CPU_ARM) | ||
12 | arm.S | ||
13 | arml.S | ||
14 | #endif | ||
15 | |||
diff --git a/lib/rbcodec/codecs/libwavpack/arm.S b/lib/rbcodec/codecs/libwavpack/arm.S new file mode 100644 index 0000000000..32de1df7de --- /dev/null +++ b/lib/rbcodec/codecs/libwavpack/arm.S | |||
@@ -0,0 +1,477 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2006 by David Bryant | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | /* This is an assembly optimized version of the following WavPack function: | ||
23 | * | ||
24 | * void decorr_stereo_pass_cont_arm (struct decorr_pass *dpp, | ||
25 | * long *buffer, long sample_count); | ||
26 | * | ||
27 | * It performs a single pass of stereo decorrelation on the provided buffer. | ||
28 | * Note that this version of the function requires that the 8 previous stereo | ||
29 | * samples are visible and correct. In other words, it ignores the "samples_*" | ||
30 | * fields in the decorr_pass structure and gets the history data directly | ||
31 | * from the buffer. It does, however, return the appropriate history samples | ||
32 | * to the decorr_pass structure before returning. | ||
33 | * | ||
34 | * This is written to work on a ARM7TDMI processor. This version only uses the | ||
35 | * 32-bit multiply-accumulate instruction and so will overflow with 24-bit | ||
36 | * WavPack files. | ||
37 | */ | ||
38 | |||
39 | #include "config.h" | ||
40 | |||
41 | .text | ||
42 | .align | ||
43 | .global decorr_stereo_pass_cont_arm | ||
44 | |||
45 | /* | ||
46 | * on entry: | ||
47 | * | ||
48 | * r0 = struct decorr_pass *dpp | ||
49 | * r1 = long *buffer | ||
50 | * r2 = long sample_count | ||
51 | */ | ||
52 | |||
53 | decorr_stereo_pass_cont_arm: | ||
54 | |||
55 | stmfd sp!, {r4 - r8, r10, r11, lr} | ||
56 | mov r5, r0 @ r5 = dpp | ||
57 | mov r11, #512 @ r11 = 512 for rounding | ||
58 | ldrsh r6, [r0, #2] @ r6 = dpp->delta | ||
59 | ldrsh r4, [r0, #4] @ r4 = dpp->weight_A | ||
60 | ldrsh r0, [r0, #6] @ r0 = dpp->weight_B | ||
61 | cmp r2, #0 @ exit if no samples to process | ||
62 | beq common_exit | ||
63 | |||
64 | add r7, r1, r2, asl #3 @ r7 = buffer ending position | ||
65 | ldrsh r2, [r5, #0] @ r2 = dpp->term | ||
66 | cmp r2, #0 | ||
67 | bmi minus_term | ||
68 | |||
69 | ldr lr, [r1, #-16] @ load 2 sample history from buffer | ||
70 | ldr r10, [r1, #-12] @ for terms 2, 17, and 18 | ||
71 | ldr r8, [r1, #-8] | ||
72 | ldr r3, [r1, #-4] | ||
73 | cmp r2, #17 | ||
74 | beq term_17_loop | ||
75 | cmp r2, #18 | ||
76 | beq term_18_loop | ||
77 | cmp r2, #2 | ||
78 | beq term_2_loop | ||
79 | b term_default_loop @ else handle default (1-8, except 2) | ||
80 | |||
81 | minus_term: | ||
82 | mov r10, #1024 @ r10 = -1024 for weight clipping | ||
83 | rsb r10, r10, #0 @ (only used for negative terms) | ||
84 | cmn r2, #1 | ||
85 | beq term_minus_1 | ||
86 | cmn r2, #2 | ||
87 | beq term_minus_2 | ||
88 | cmn r2, #3 | ||
89 | beq term_minus_3 | ||
90 | b common_exit | ||
91 | |||
92 | /* | ||
93 | ****************************************************************************** | ||
94 | * Loop to handle term = 17 condition | ||
95 | * | ||
96 | * r0 = dpp->weight_B r8 = previous left sample | ||
97 | * r1 = bptr r9 = | ||
98 | * r2 = current sample r10 = second previous left sample | ||
99 | * r3 = previous right sample r11 = 512 (for rounding) | ||
100 | * r4 = dpp->weight_A ip = current decorrelation value | ||
101 | * r5 = dpp sp = | ||
102 | * r6 = dpp->delta lr = second previous right sample | ||
103 | * r7 = eptr pc = | ||
104 | ******************************************************************************* | ||
105 | */ | ||
106 | |||
107 | term_17_loop: | ||
108 | rsbs ip, lr, r8, asl #1 @ decorr value = (2 * prev) - 2nd prev | ||
109 | mov lr, r8 @ previous becomes 2nd previous | ||
110 | ldr r2, [r1], #4 @ get sample & update pointer | ||
111 | mla r8, ip, r4, r11 @ mult decorr value by weight, round, | ||
112 | add r8, r2, r8, asr #10 @ shift, and add to new sample | ||
113 | strne r8, [r1, #-4] @ if change possible, store sample back | ||
114 | cmpne r2, #0 | ||
115 | beq .L325 | ||
116 | teq ip, r2 @ update weight based on signs | ||
117 | submi r4, r4, r6 | ||
118 | addpl r4, r4, r6 | ||
119 | |||
120 | .L325: rsbs ip, r10, r3, asl #1 @ do same thing for right channel | ||
121 | mov r10, r3 | ||
122 | ldr r2, [r1], #4 | ||
123 | mla r3, ip, r0, r11 | ||
124 | add r3, r2, r3, asr #10 | ||
125 | strne r3, [r1, #-4] | ||
126 | cmpne r2, #0 | ||
127 | beq .L329 | ||
128 | teq ip, r2 | ||
129 | submi r0, r0, r6 | ||
130 | addpl r0, r0, r6 | ||
131 | |||
132 | .L329: cmp r7, r1 @ loop back if more samples to do | ||
133 | bhi term_17_loop | ||
134 | b store_1718 @ common exit for terms 17 & 18 | ||
135 | |||
136 | /* | ||
137 | ****************************************************************************** | ||
138 | * Loop to handle term = 18 condition | ||
139 | * | ||
140 | * r0 = dpp->weight_B r8 = previous left sample | ||
141 | * r1 = bptr r9 = | ||
142 | * r2 = current sample r10 = second previous left sample | ||
143 | * r3 = previous right sample r11 = 512 (for rounding) | ||
144 | * r4 = dpp->weight_A ip = decorrelation value | ||
145 | * r5 = dpp sp = | ||
146 | * r6 = dpp->delta lr = second previous right sample | ||
147 | * r7 = eptr pc = | ||
148 | ******************************************************************************* | ||
149 | */ | ||
150 | |||
151 | term_18_loop: | ||
152 | sub ip, r8, lr @ decorr value = | ||
153 | mov lr, r8 @ ((3 * prev) - 2nd prev) >> 1 | ||
154 | adds ip, r8, ip, asr #1 | ||
155 | ldr r2, [r1], #4 @ get sample & update pointer | ||
156 | mla r8, ip, r4, r11 @ mult decorr value by weight, round, | ||
157 | add r8, r2, r8, asr #10 @ shift, and add to new sample | ||
158 | strne r8, [r1, #-4] @ if change possible, store sample back | ||
159 | cmpne r2, #0 | ||
160 | beq .L337 | ||
161 | teq ip, r2 @ update weight based on signs | ||
162 | submi r4, r4, r6 | ||
163 | addpl r4, r4, r6 | ||
164 | |||
165 | .L337: sub ip, r3, r10 @ do same thing for right channel | ||
166 | mov r10, r3 | ||
167 | adds ip, r3, ip, asr #1 | ||
168 | ldr r2, [r1], #4 | ||
169 | mla r3, ip, r0, r11 | ||
170 | add r3, r2, r3, asr #10 | ||
171 | strne r3, [r1, #-4] | ||
172 | cmpne r2, #0 | ||
173 | beq .L341 | ||
174 | teq ip, r2 | ||
175 | submi r0, r0, r6 | ||
176 | addpl r0, r0, r6 | ||
177 | |||
178 | .L341: cmp r7, r1 @ loop back if more samples to do | ||
179 | bhi term_18_loop | ||
180 | |||
181 | /* common exit for terms 17 & 18 */ | ||
182 | |||
183 | store_1718: | ||
184 | str r3, [r5, #40] @ store sample history into struct | ||
185 | str r8, [r5, #8] | ||
186 | str r10, [r5, #44] | ||
187 | str lr, [r5, #12] | ||
188 | b common_exit @ and return | ||
189 | |||
190 | /* | ||
191 | ****************************************************************************** | ||
192 | * Loop to handle term = 2 condition | ||
193 | * (note that this case can be handled by the default term handler (1-8), but | ||
194 | * this special case is faster because it doesn't have to read memory twice) | ||
195 | * | ||
196 | * r0 = dpp->weight_B r8 = previous left sample | ||
197 | * r1 = bptr r9 = | ||
198 | * r2 = current sample r10 = second previous left sample | ||
199 | * r3 = previous right sample r11 = 512 (for rounding) | ||
200 | * r4 = dpp->weight_A ip = decorrelation value | ||
201 | * r5 = dpp sp = | ||
202 | * r6 = dpp->delta lr = second previous right sample | ||
203 | * r7 = eptr pc = | ||
204 | ******************************************************************************* | ||
205 | */ | ||
206 | |||
207 | term_2_loop: | ||
208 | movs ip, lr @ get decorrelation value & test | ||
209 | mov lr, r8 @ previous becomes 2nd previous | ||
210 | ldr r2, [r1], #4 @ get sample & update pointer | ||
211 | mla r8, ip, r4, r11 @ mult decorr value by weight, round, | ||
212 | add r8, r2, r8, asr #10 @ shift, and add to new sample | ||
213 | strne r8, [r1, #-4] @ if change possible, store sample back | ||
214 | cmpne r2, #0 | ||
215 | beq .L225 | ||
216 | teq ip, r2 @ update weight based on signs | ||
217 | submi r4, r4, r6 | ||
218 | addpl r4, r4, r6 | ||
219 | |||
220 | .L225: movs ip, r10 @ do same thing for right channel | ||
221 | mov r10, r3 | ||
222 | ldr r2, [r1], #4 | ||
223 | mla r3, ip, r0, r11 | ||
224 | add r3, r2, r3, asr #10 | ||
225 | strne r3, [r1, #-4] | ||
226 | cmpne r2, #0 | ||
227 | beq .L229 | ||
228 | teq ip, r2 | ||
229 | submi r0, r0, r6 | ||
230 | addpl r0, r0, r6 | ||
231 | |||
232 | .L229: cmp r7, r1 @ loop back if more samples to do | ||
233 | bhi term_2_loop | ||
234 | b default_term_exit @ this exit updates all dpp->samples | ||
235 | |||
236 | /* | ||
237 | ****************************************************************************** | ||
238 | * Loop to handle default term condition | ||
239 | * | ||
240 | * r0 = dpp->weight_B r8 = result accumulator | ||
241 | * r1 = bptr r9 = | ||
242 | * r2 = dpp->term r10 = | ||
243 | * r3 = decorrelation value r11 = 512 (for rounding) | ||
244 | * r4 = dpp->weight_A ip = current sample | ||
245 | * r5 = dpp sp = | ||
246 | * r6 = dpp->delta lr = | ||
247 | * r7 = eptr pc = | ||
248 | ******************************************************************************* | ||
249 | */ | ||
250 | |||
251 | term_default_loop: | ||
252 | ldr ip, [r1] @ get original sample | ||
253 | ldr r3, [r1, -r2, asl #3] @ get decorrelation value based on term | ||
254 | mla r8, r3, r4, r11 @ mult decorr value by weight, round, | ||
255 | add r8, ip, r8, asr #10 @ shift and add to new sample | ||
256 | str r8, [r1], #4 @ store update sample | ||
257 | cmp r3, #0 | ||
258 | cmpne ip, #0 | ||
259 | beq .L350 | ||
260 | teq ip, r3 @ update weight based on signs | ||
261 | submi r4, r4, r6 | ||
262 | addpl r4, r4, r6 | ||
263 | |||
264 | .L350: ldr ip, [r1] @ do the same thing for right channel | ||
265 | ldr r3, [r1, -r2, asl #3] | ||
266 | mla r8, r3, r0, r11 | ||
267 | add r8, ip, r8, asr #10 | ||
268 | str r8, [r1], #4 | ||
269 | cmp r3, #0 | ||
270 | cmpne ip, #0 | ||
271 | beq .L354 | ||
272 | teq ip, r3 | ||
273 | submi r0, r0, r6 | ||
274 | addpl r0, r0, r6 | ||
275 | |||
276 | .L354: cmp r7, r1 @ loop back if more samples to do | ||
277 | bhi term_default_loop | ||
278 | |||
279 | /* | ||
280 | * This exit is used by terms 1-8 to store the previous 8 samples into the decorr | ||
281 | * structure (even if they are not all used for the given term) | ||
282 | */ | ||
283 | |||
284 | default_term_exit: | ||
285 | ldrsh r3, [r5, #0] | ||
286 | sub ip, r3, #1 | ||
287 | mov lr, #7 | ||
288 | |||
289 | .L358: and r3, ip, #7 | ||
290 | add r3, r5, r3, asl #2 | ||
291 | ldr r2, [r1, #-4] | ||
292 | str r2, [r3, #40] | ||
293 | ldr r2, [r1, #-8]! | ||
294 | str r2, [r3, #8] | ||
295 | sub ip, ip, #1 | ||
296 | sub lr, lr, #1 | ||
297 | cmn lr, #1 | ||
298 | bne .L358 | ||
299 | b common_exit | ||
300 | |||
301 | /* | ||
302 | ****************************************************************************** | ||
303 | * Loop to handle term = -1 condition | ||
304 | * | ||
305 | * r0 = dpp->weight_B r8 = | ||
306 | * r1 = bptr r9 = | ||
307 | * r2 = intermediate result r10 = -1024 (for clipping) | ||
308 | * r3 = previous right sample r11 = 512 (for rounding) | ||
309 | * r4 = dpp->weight_A ip = current sample | ||
310 | * r5 = dpp sp = | ||
311 | * r6 = dpp->delta lr = updated left sample | ||
312 | * r7 = eptr pc = | ||
313 | ******************************************************************************* | ||
314 | */ | ||
315 | |||
316 | term_minus_1: | ||
317 | ldr r3, [r1, #-4] | ||
318 | |||
319 | term_minus_1_loop: | ||
320 | ldr ip, [r1] @ for left channel the decorrelation value | ||
321 | mla r2, r3, r4, r11 @ is the previous right sample (in r3) | ||
322 | add lr, ip, r2, asr #10 | ||
323 | str lr, [r1], #8 | ||
324 | cmp r3, #0 | ||
325 | cmpne ip, #0 | ||
326 | beq .L361 | ||
327 | teq ip, r3 @ update weight based on signs | ||
328 | submi r4, r4, r6 | ||
329 | addpl r4, r4, r6 | ||
330 | cmp r4, #1024 | ||
331 | movgt r4, #1024 | ||
332 | cmp r4, r10 | ||
333 | movlt r4, r10 | ||
334 | |||
335 | .L361: ldr r2, [r1, #-4] @ for right channel the decorrelation value | ||
336 | mla r3, lr, r0, r11 @ is the just updated right sample (in lr) | ||
337 | add r3, r2, r3, asr #10 | ||
338 | str r3, [r1, #-4] | ||
339 | cmp lr, #0 | ||
340 | cmpne r2, #0 | ||
341 | beq .L369 | ||
342 | teq r2, lr | ||
343 | submi r0, r0, r6 | ||
344 | addpl r0, r0, r6 | ||
345 | cmp r0, #1024 @ then clip weight to +/-1024 | ||
346 | movgt r0, #1024 | ||
347 | cmp r0, r10 | ||
348 | movlt r0, r10 | ||
349 | |||
350 | .L369: cmp r7, r1 @ loop back if more samples to do | ||
351 | bhi term_minus_1_loop | ||
352 | |||
353 | str r3, [r5, #8] @ else store right sample and exit | ||
354 | b common_exit | ||
355 | |||
356 | /* | ||
357 | ****************************************************************************** | ||
358 | * Loop to handle term = -2 condition | ||
359 | * (note that the channels are processed in the reverse order here) | ||
360 | * | ||
361 | * r0 = dpp->weight_B r8 = | ||
362 | * r1 = bptr r9 = | ||
363 | * r2 = intermediate result r10 = -1024 (for clipping) | ||
364 | * r3 = previous left sample r11 = 512 (for rounding) | ||
365 | * r4 = dpp->weight_A ip = current sample | ||
366 | * r5 = dpp sp = | ||
367 | * r6 = dpp->delta lr = updated right sample | ||
368 | * r7 = eptr pc = | ||
369 | ******************************************************************************* | ||
370 | */ | ||
371 | |||
372 | term_minus_2: | ||
373 | ldr r3, [r1, #-8] | ||
374 | |||
375 | term_minus_2_loop: | ||
376 | ldr ip, [r1, #4] @ for right channel the decorrelation value | ||
377 | mla r2, r3, r0, r11 @ is the previous left sample (in r3) | ||
378 | add lr, ip, r2, asr #10 | ||
379 | str lr, [r1, #4] | ||
380 | cmp r3, #0 | ||
381 | cmpne ip, #0 | ||
382 | beq .L380 | ||
383 | teq ip, r3 @ update weight based on signs | ||
384 | submi r0, r0, r6 | ||
385 | addpl r0, r0, r6 | ||
386 | cmp r0, #1024 @ then clip weight to +/-1024 | ||
387 | movgt r0, #1024 | ||
388 | cmp r0, r10 | ||
389 | movlt r0, r10 | ||
390 | |||
391 | .L380: ldr r2, [r1, #0] @ for left channel the decorrelation value | ||
392 | mla r3, lr, r4, r11 @ is the just updated left sample (in lr) | ||
393 | add r3, r2, r3, asr #10 | ||
394 | str r3, [r1], #8 | ||
395 | cmp lr, #0 | ||
396 | cmpne r2, #0 | ||
397 | beq .L388 | ||
398 | teq r2, lr | ||
399 | submi r4, r4, r6 | ||
400 | addpl r4, r4, r6 | ||
401 | cmp r4, #1024 | ||
402 | movgt r4, #1024 | ||
403 | cmp r4, r10 | ||
404 | movlt r4, r10 | ||
405 | |||
406 | .L388: cmp r7, r1 @ loop back if more samples to do | ||
407 | bhi term_minus_2_loop | ||
408 | |||
409 | str r3, [r5, #40] @ else store left channel and exit | ||
410 | b common_exit | ||
411 | |||
412 | /* | ||
413 | ****************************************************************************** | ||
414 | * Loop to handle term = -3 condition | ||
415 | * | ||
416 | * r0 = dpp->weight_B r8 = previous left sample | ||
417 | * r1 = bptr r9 = | ||
418 | * r2 = current left sample r10 = -1024 (for clipping) | ||
419 | * r3 = previous right sample r11 = 512 (for rounding) | ||
420 | * r4 = dpp->weight_A ip = intermediate result | ||
421 | * r5 = dpp sp = | ||
422 | * r6 = dpp->delta lr = | ||
423 | * r7 = eptr pc = | ||
424 | ******************************************************************************* | ||
425 | */ | ||
426 | |||
427 | term_minus_3: | ||
428 | ldr r3, [r1, #-4] @ load previous samples | ||
429 | ldr r8, [r1, #-8] | ||
430 | |||
431 | term_minus_3_loop: | ||
432 | ldr ip, [r1] | ||
433 | mla r2, r3, r4, r11 | ||
434 | add r2, ip, r2, asr #10 | ||
435 | str r2, [r1], #4 | ||
436 | cmp r3, #0 | ||
437 | cmpne ip, #0 | ||
438 | beq .L399 | ||
439 | teq ip, r3 @ update weight based on signs | ||
440 | submi r4, r4, r6 | ||
441 | addpl r4, r4, r6 | ||
442 | cmp r4, #1024 @ then clip weight to +/-1024 | ||
443 | movgt r4, #1024 | ||
444 | cmp r4, r10 | ||
445 | movlt r4, r10 | ||
446 | |||
447 | .L399: movs ip, r8 @ ip = previous left we use now | ||
448 | mov r8, r2 @ r8 = current left we use next time | ||
449 | ldr r2, [r1], #4 | ||
450 | mla r3, ip, r0, r11 | ||
451 | add r3, r2, r3, asr #10 | ||
452 | strne r3, [r1, #-4] | ||
453 | cmpne r2, #0 | ||
454 | beq .L407 | ||
455 | teq ip, r2 | ||
456 | submi r0, r0, r6 | ||
457 | addpl r0, r0, r6 | ||
458 | cmp r0, #1024 | ||
459 | movgt r0, #1024 | ||
460 | cmp r0, r10 | ||
461 | movlt r0, r10 | ||
462 | |||
463 | .L407: cmp r7, r1 @ loop back if more samples to do | ||
464 | bhi term_minus_3_loop | ||
465 | |||
466 | str r3, [r5, #8] @ else store previous samples & exit | ||
467 | str r8, [r5, #40] | ||
468 | |||
469 | /* | ||
470 | * Before finally exiting we must store weights back for next time | ||
471 | */ | ||
472 | |||
473 | common_exit: | ||
474 | strh r4, [r5, #4] | ||
475 | strh r0, [r5, #6] | ||
476 | ldmpc regs="r4-r8, r10-r11" | ||
477 | |||
diff --git a/lib/rbcodec/codecs/libwavpack/arml.S b/lib/rbcodec/codecs/libwavpack/arml.S new file mode 100644 index 0000000000..60818aa1e6 --- /dev/null +++ b/lib/rbcodec/codecs/libwavpack/arml.S | |||
@@ -0,0 +1,506 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2006 by David Bryant | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | /* This is an assembly optimized version of the following WavPack function: | ||
23 | * | ||
24 | * void decorr_stereo_pass_cont_arml (struct decorr_pass *dpp, | ||
25 | * long *buffer, long sample_count); | ||
26 | * | ||
27 | * It performs a single pass of stereo decorrelation on the provided buffer. | ||
28 | * Note that this version of the function requires that the 8 previous stereo | ||
29 | * samples are visible and correct. In other words, it ignores the "samples_*" | ||
30 | * fields in the decorr_pass structure and gets the history data directly | ||
31 | * from the buffer. It does, however, return the appropriate history samples | ||
32 | * to the decorr_pass structure before returning. | ||
33 | * | ||
34 | * This is written to work on a ARM7TDMI processor. This version uses the | ||
35 | * 64-bit multiply-accumulate instruction and so can be used with all | ||
36 | * WavPack files. However, for optimum performance with 16-bit WavPack | ||
37 | * files, there is a faster version that only uses the 32-bit MLA | ||
38 | * instruction. | ||
39 | */ | ||
40 | |||
41 | #include "config.h" | ||
42 | |||
43 | .text | ||
44 | .align | ||
45 | .global decorr_stereo_pass_cont_arml | ||
46 | |||
47 | /* | ||
48 | * on entry: | ||
49 | * | ||
50 | * r0 = struct decorr_pass *dpp | ||
51 | * r1 = long *buffer | ||
52 | * r2 = long sample_count | ||
53 | */ | ||
54 | |||
55 | decorr_stereo_pass_cont_arml: | ||
56 | |||
57 | stmfd sp!, {r4 - r8, r10, r11, lr} | ||
58 | mov r5, r0 @ r5 = dpp | ||
59 | mov r11, #512 @ r11 = 512 for rounding | ||
60 | ldrsh r6, [r0, #2] @ r6 = dpp->delta | ||
61 | ldrsh r4, [r0, #4] @ r4 = dpp->weight_A | ||
62 | ldrsh r0, [r0, #6] @ r0 = dpp->weight_B | ||
63 | cmp r2, #0 @ exit if no samples to process | ||
64 | beq common_exit | ||
65 | |||
66 | mov r0, r0, asl #18 @ for 64-bit math we use weights << 18 | ||
67 | mov r4, r4, asl #18 | ||
68 | mov r6, r6, asl #18 | ||
69 | add r7, r1, r2, asl #3 @ r7 = buffer ending position | ||
70 | ldrsh r2, [r5, #0] @ r2 = dpp->term | ||
71 | cmp r2, #0 | ||
72 | blt minus_term | ||
73 | |||
74 | ldr lr, [r1, #-16] @ load 2 sample history from buffer | ||
75 | ldr r10, [r1, #-12] @ for terms 2, 17, and 18 | ||
76 | ldr r8, [r1, #-8] | ||
77 | ldr r3, [r1, #-4] | ||
78 | |||
79 | cmp r2, #18 | ||
80 | beq term_18_loop | ||
81 | mov lr, lr, asl #4 | ||
82 | mov r10, r10, asl #4 | ||
83 | cmp r2, #2 | ||
84 | beq term_2_loop | ||
85 | cmp r2, #17 | ||
86 | beq term_17_loop | ||
87 | b term_default_loop | ||
88 | |||
89 | minus_term: | ||
90 | mov r10, #(1024 << 18) @ r10 = -1024 << 18 for weight clipping | ||
91 | rsb r10, r10, #0 @ (only used for negative terms) | ||
92 | cmn r2, #1 | ||
93 | beq term_minus_1 | ||
94 | cmn r2, #2 | ||
95 | beq term_minus_2 | ||
96 | cmn r2, #3 | ||
97 | beq term_minus_3 | ||
98 | b common_exit | ||
99 | |||
100 | /* | ||
101 | ****************************************************************************** | ||
102 | * Loop to handle term = 17 condition | ||
103 | * | ||
104 | * r0 = dpp->weight_B r8 = previous left sample | ||
105 | * r1 = bptr r9 = | ||
106 | * r2 = current sample r10 = second previous left sample << 4 | ||
107 | * r3 = previous right sample r11 = lo accumulator (for rounding) | ||
108 | * r4 = dpp->weight_A ip = current decorrelation value | ||
109 | * r5 = dpp sp = | ||
110 | * r6 = dpp->delta lr = second previous right sample << 4 | ||
111 | * r7 = eptr pc = | ||
112 | ******************************************************************************* | ||
113 | */ | ||
114 | |||
115 | term_17_loop: | ||
116 | rsbs ip, lr, r8, asl #5 @ decorr value = (2 * prev) - 2nd prev | ||
117 | mov lr, r8, asl #4 @ previous becomes 2nd previous | ||
118 | ldr r2, [r1], #4 @ get sample & update pointer | ||
119 | mov r11, #0x80000000 | ||
120 | mov r8, r2 | ||
121 | smlalne r11, r8, r4, ip | ||
122 | strne r8, [r1, #-4] @ if change possible, store sample back | ||
123 | cmpne r2, #0 | ||
124 | beq .L325 | ||
125 | teq ip, r2 @ update weight based on signs | ||
126 | submi r4, r4, r6 | ||
127 | addpl r4, r4, r6 | ||
128 | |||
129 | .L325: rsbs ip, r10, r3, asl #5 @ do same thing for right channel | ||
130 | mov r10, r3, asl #4 | ||
131 | ldr r2, [r1], #4 | ||
132 | mov r11, #0x80000000 | ||
133 | mov r3, r2 | ||
134 | smlalne r11, r3, r0, ip | ||
135 | strne r3, [r1, #-4] | ||
136 | cmpne r2, #0 | ||
137 | beq .L329 | ||
138 | teq ip, r2 | ||
139 | submi r0, r0, r6 | ||
140 | addpl r0, r0, r6 | ||
141 | |||
142 | .L329: cmp r7, r1 @ loop back if more samples to do | ||
143 | bhi term_17_loop | ||
144 | mov lr, lr, asr #4 | ||
145 | mov r10, r10, asr #4 | ||
146 | b store_1718 @ common exit for terms 17 & 18 | ||
147 | |||
148 | /* | ||
149 | ****************************************************************************** | ||
150 | * Loop to handle term = 18 condition | ||
151 | * | ||
152 | * r0 = dpp->weight_B r8 = previous left sample | ||
153 | * r1 = bptr r9 = | ||
154 | * r2 = current sample r10 = second previous left sample | ||
155 | * r3 = previous right sample r11 = lo accumulator (for rounding) | ||
156 | * r4 = dpp->weight_A ip = decorrelation value | ||
157 | * r5 = dpp sp = | ||
158 | * r6 = dpp->delta lr = second previous right sample | ||
159 | * r7 = eptr pc = | ||
160 | ******************************************************************************* | ||
161 | */ | ||
162 | |||
163 | term_18_loop: | ||
164 | rsb ip, lr, r8 @ decorr value = | ||
165 | mov lr, r8 @ ((3 * prev) - 2nd prev) >> 1 | ||
166 | add ip, lr, ip, asr #1 | ||
167 | movs ip, ip, asl #4 | ||
168 | ldr r2, [r1], #4 @ get sample & update pointer | ||
169 | mov r11, #0x80000000 | ||
170 | mov r8, r2 | ||
171 | smlalne r11, r8, r4, ip | ||
172 | strne r8, [r1, #-4] @ if change possible, store sample back | ||
173 | cmpne r2, #0 | ||
174 | beq .L337 | ||
175 | teq ip, r2 @ update weight based on signs | ||
176 | submi r4, r4, r6 | ||
177 | addpl r4, r4, r6 | ||
178 | |||
179 | .L337: rsb ip, r10, r3 @ do same thing for right channel | ||
180 | mov r10, r3 | ||
181 | add ip, r10, ip, asr #1 | ||
182 | movs ip, ip, asl #4 | ||
183 | ldr r2, [r1], #4 | ||
184 | mov r11, #0x80000000 | ||
185 | mov r3, r2 | ||
186 | smlalne r11, r3, r0, ip | ||
187 | strne r3, [r1, #-4] | ||
188 | cmpne r2, #0 | ||
189 | beq .L341 | ||
190 | teq ip, r2 | ||
191 | submi r0, r0, r6 | ||
192 | addpl r0, r0, r6 | ||
193 | |||
194 | .L341: cmp r7, r1 @ loop back if more samples to do | ||
195 | bhi term_18_loop | ||
196 | |||
197 | /* common exit for terms 17 & 18 */ | ||
198 | |||
199 | store_1718: | ||
200 | str r3, [r5, #40] @ store sample history into struct | ||
201 | str r8, [r5, #8] | ||
202 | str r10, [r5, #44] | ||
203 | str lr, [r5, #12] | ||
204 | b common_exit @ and return | ||
205 | |||
206 | /* | ||
207 | ****************************************************************************** | ||
208 | * Loop to handle term = 2 condition | ||
209 | * (note that this case can be handled by the default term handler (1-8), but | ||
210 | * this special case is faster because it doesn't have to read memory twice) | ||
211 | * | ||
212 | * r0 = dpp->weight_B r8 = previous left sample | ||
213 | * r1 = bptr r9 = | ||
214 | * r2 = current sample r10 = second previous left sample << 4 | ||
215 | * r3 = previous right sample r11 = lo accumulator (for rounding) | ||
216 | * r4 = dpp->weight_A ip = decorrelation value | ||
217 | * r5 = dpp sp = | ||
218 | * r6 = dpp->delta lr = second previous right sample << 4 | ||
219 | * r7 = eptr pc = | ||
220 | ******************************************************************************* | ||
221 | */ | ||
222 | |||
223 | term_2_loop: | ||
224 | movs ip, lr @ get decorrelation value & test | ||
225 | ldr r2, [r1], #4 @ get sample & update pointer | ||
226 | mov lr, r8, asl #4 @ previous becomes 2nd previous | ||
227 | mov r11, #0x80000000 | ||
228 | mov r8, r2 | ||
229 | smlalne r11, r8, r4, ip | ||
230 | strne r8, [r1, #-4] @ if change possible, store sample back | ||
231 | cmpne r2, #0 | ||
232 | beq .L225 | ||
233 | teq ip, r2 @ update weight based on signs | ||
234 | submi r4, r4, r6 | ||
235 | addpl r4, r4, r6 | ||
236 | |||
237 | .L225: movs ip, r10 @ do same thing for right channel | ||
238 | ldr r2, [r1], #4 | ||
239 | mov r10, r3, asl #4 | ||
240 | mov r11, #0x80000000 | ||
241 | mov r3, r2 | ||
242 | smlalne r11, r3, r0, ip | ||
243 | strne r3, [r1, #-4] | ||
244 | cmpne r2, #0 | ||
245 | beq .L229 | ||
246 | teq ip, r2 | ||
247 | submi r0, r0, r6 | ||
248 | addpl r0, r0, r6 | ||
249 | |||
250 | .L229: cmp r7, r1 @ loop back if more samples to do | ||
251 | bhi term_2_loop | ||
252 | |||
253 | b default_term_exit @ this exit updates all dpp->samples | ||
254 | |||
255 | /* | ||
256 | ****************************************************************************** | ||
257 | * Loop to handle default term condition | ||
258 | * | ||
259 | * r0 = dpp->weight_B r8 = result accumulator | ||
260 | * r1 = bptr r9 = | ||
261 | * r2 = dpp->term r10 = | ||
262 | * r3 = decorrelation value r11 = lo accumulator (for rounding) | ||
263 | * r4 = dpp->weight_A ip = current sample | ||
264 | * r5 = dpp sp = | ||
265 | * r6 = dpp->delta lr = | ||
266 | * r7 = eptr pc = | ||
267 | ******************************************************************************* | ||
268 | */ | ||
269 | |||
270 | term_default_loop: | ||
271 | ldr r3, [r1, -r2, asl #3] @ get decorrelation value based on term | ||
272 | ldr ip, [r1], #4 @ get original sample and bump ptr | ||
273 | movs r3, r3, asl #4 | ||
274 | mov r11, #0x80000000 | ||
275 | mov r8, ip | ||
276 | smlalne r11, r8, r4, r3 | ||
277 | strne r8, [r1, #-4] @ if possibly changed, store updated sample | ||
278 | cmpne ip, #0 | ||
279 | beq .L350 | ||
280 | teq ip, r3 @ update weight based on signs | ||
281 | submi r4, r4, r6 | ||
282 | addpl r4, r4, r6 | ||
283 | |||
284 | .L350: ldr r3, [r1, -r2, asl #3] @ do the same thing for right channel | ||
285 | ldr ip, [r1], #4 | ||
286 | movs r3, r3, asl #4 | ||
287 | mov r11, #0x80000000 | ||
288 | mov r8, ip | ||
289 | smlalne r11, r8, r0, r3 | ||
290 | strne r8, [r1, #-4] | ||
291 | cmpne ip, #0 | ||
292 | beq .L354 | ||
293 | teq ip, r3 | ||
294 | submi r0, r0, r6 | ||
295 | addpl r0, r0, r6 | ||
296 | |||
297 | .L354: cmp r7, r1 @ loop back if more samples to do | ||
298 | bhi term_default_loop | ||
299 | |||
300 | /* | ||
301 | * This exit is used by terms 1-8 to store the previous 8 samples into the decorr | ||
302 | * structure (even if they are not all used for the given term) | ||
303 | */ | ||
304 | |||
305 | default_term_exit: | ||
306 | ldrsh r3, [r5, #0] | ||
307 | sub ip, r3, #1 | ||
308 | mov lr, #7 | ||
309 | |||
310 | .L358: and r3, ip, #7 | ||
311 | add r3, r5, r3, asl #2 | ||
312 | ldr r2, [r1, #-4] | ||
313 | str r2, [r3, #40] | ||
314 | ldr r2, [r1, #-8]! | ||
315 | str r2, [r3, #8] | ||
316 | sub ip, ip, #1 | ||
317 | sub lr, lr, #1 | ||
318 | cmn lr, #1 | ||
319 | bne .L358 | ||
320 | b common_exit | ||
321 | |||
322 | /* | ||
323 | ****************************************************************************** | ||
324 | * Loop to handle term = -1 condition | ||
325 | * | ||
326 | * r0 = dpp->weight_B r8 = | ||
327 | * r1 = bptr r9 = | ||
328 | * r2 = intermediate result r10 = -1024 (for clipping) | ||
329 | * r3 = previous right sample r11 = lo accumulator (for rounding) | ||
330 | * r4 = dpp->weight_A ip = current sample | ||
331 | * r5 = dpp sp = | ||
332 | * r6 = dpp->delta lr = updated left sample | ||
333 | * r7 = eptr pc = | ||
334 | ******************************************************************************* | ||
335 | */ | ||
336 | |||
337 | term_minus_1: | ||
338 | ldr r3, [r1, #-4] | ||
339 | |||
340 | term_minus_1_loop: | ||
341 | ldr ip, [r1], #8 @ for left channel the decorrelation value | ||
342 | movs r3, r3, asl #4 @ is the previous right sample (in r3) | ||
343 | mov r11, #0x80000000 | ||
344 | mov lr, ip | ||
345 | smlalne r11, lr, r4, r3 | ||
346 | strne lr, [r1, #-8] | ||
347 | cmpne ip, #0 | ||
348 | beq .L361 | ||
349 | teq ip, r3 @ update weight based on signs | ||
350 | submi r4, r4, r6 | ||
351 | addpl r4, r4, r6 | ||
352 | cmp r4, #(1024 << 18) | ||
353 | movgt r4, #(1024 << 18) | ||
354 | cmp r4, r10 | ||
355 | movlt r4, r10 | ||
356 | |||
357 | .L361: ldr r2, [r1, #-4] @ for right channel the decorrelation value | ||
358 | movs lr, lr, asl #4 | ||
359 | mov r11, #0x80000000 | ||
360 | mov r3, r2 | ||
361 | smlalne r11, r3, r0, lr | ||
362 | strne r3, [r1, #-4] | ||
363 | cmpne r2, #0 | ||
364 | beq .L369 | ||
365 | teq r2, lr | ||
366 | submi r0, r0, r6 | ||
367 | addpl r0, r0, r6 | ||
368 | cmp r0, #(1024 << 18) @ then clip weight to +/-1024 | ||
369 | movgt r0, #(1024 << 18) | ||
370 | cmp r0, r10 | ||
371 | movlt r0, r10 | ||
372 | |||
373 | .L369: cmp r7, r1 @ loop back if more samples to do | ||
374 | bhi term_minus_1_loop | ||
375 | |||
376 | str r3, [r5, #8] @ else store right sample and exit | ||
377 | b common_exit | ||
378 | |||
379 | /* | ||
380 | ****************************************************************************** | ||
381 | * Loop to handle term = -2 condition | ||
382 | * (note that the channels are processed in the reverse order here) | ||
383 | * | ||
384 | * r0 = dpp->weight_B r8 = | ||
385 | * r1 = bptr r9 = | ||
386 | * r2 = intermediate result r10 = -1024 (for clipping) | ||
387 | * r3 = previous left sample r11 = lo accumulator (for rounding) | ||
388 | * r4 = dpp->weight_A ip = current sample | ||
389 | * r5 = dpp sp = | ||
390 | * r6 = dpp->delta lr = updated right sample | ||
391 | * r7 = eptr pc = | ||
392 | ******************************************************************************* | ||
393 | */ | ||
394 | |||
395 | term_minus_2: | ||
396 | ldr r3, [r1, #-8] | ||
397 | |||
398 | term_minus_2_loop: | ||
399 | ldr ip, [r1, #4] @ for right channel the decorrelation value | ||
400 | movs r3, r3, asl #4 @ is the previous left sample (in r3) | ||
401 | mov r11, #0x80000000 | ||
402 | mov lr, ip | ||
403 | smlalne r11, lr, r0, r3 | ||
404 | strne lr, [r1, #4] | ||
405 | cmpne ip, #0 | ||
406 | beq .L380 | ||
407 | teq ip, r3 @ update weight based on signs | ||
408 | submi r0, r0, r6 | ||
409 | addpl r0, r0, r6 | ||
410 | cmp r0, #(1024 << 18) @ then clip weight to +/-1024 | ||
411 | movgt r0, #(1024 << 18) | ||
412 | cmp r0, r10 | ||
413 | movlt r0, r10 | ||
414 | |||
415 | .L380: ldr r2, [r1], #8 @ for left channel the decorrelation value | ||
416 | movs lr, lr, asl #4 | ||
417 | mov r11, #0x80000000 | ||
418 | mov r3, r2 | ||
419 | smlalne r11, r3, r4, lr | ||
420 | strne r3, [r1, #-8] | ||
421 | cmpne r2, #0 | ||
422 | beq .L388 | ||
423 | teq r2, lr | ||
424 | submi r4, r4, r6 | ||
425 | addpl r4, r4, r6 | ||
426 | cmp r4, #(1024 << 18) | ||
427 | movgt r4, #(1024 << 18) | ||
428 | cmp r4, r10 | ||
429 | movlt r4, r10 | ||
430 | |||
431 | .L388: cmp r7, r1 @ loop back if more samples to do | ||
432 | bhi term_minus_2_loop | ||
433 | |||
434 | str r3, [r5, #40] @ else store left channel and exit | ||
435 | b common_exit | ||
436 | |||
437 | /* | ||
438 | ****************************************************************************** | ||
439 | * Loop to handle term = -3 condition | ||
440 | * | ||
441 | * r0 = dpp->weight_B r8 = previous left sample | ||
442 | * r1 = bptr r9 = | ||
443 | * r2 = current left sample r10 = -1024 (for clipping) | ||
444 | * r3 = previous right sample r11 = lo accumulator (for rounding) | ||
445 | * r4 = dpp->weight_A ip = intermediate result | ||
446 | * r5 = dpp sp = | ||
447 | * r6 = dpp->delta lr = | ||
448 | * r7 = eptr pc = | ||
449 | ******************************************************************************* | ||
450 | */ | ||
451 | |||
452 | term_minus_3: | ||
453 | ldr r3, [r1, #-4] @ load previous samples | ||
454 | ldr r8, [r1, #-8] | ||
455 | |||
456 | term_minus_3_loop: | ||
457 | ldr ip, [r1], #4 | ||
458 | movs r3, r3, asl #4 | ||
459 | mov r11, #0x80000000 | ||
460 | mov r2, ip | ||
461 | smlalne r11, r2, r4, r3 | ||
462 | strne r2, [r1, #-4] | ||
463 | cmpne ip, #0 | ||
464 | beq .L399 | ||
465 | teq ip, r3 @ update weight based on signs | ||
466 | submi r4, r4, r6 | ||
467 | addpl r4, r4, r6 | ||
468 | cmp r4, #(1024 << 18) @ then clip weight to +/-1024 | ||
469 | movgt r4, #(1024 << 18) | ||
470 | cmp r4, r10 | ||
471 | movlt r4, r10 | ||
472 | |||
473 | .L399: movs ip, r8, asl #4 @ ip = previous left we use now | ||
474 | mov r8, r2 @ r8 = current left we use next time | ||
475 | ldr r2, [r1], #4 | ||
476 | mov r11, #0x80000000 | ||
477 | mov r3, r2 | ||
478 | smlalne r11, r3, r0, ip | ||
479 | strne r3, [r1, #-4] | ||
480 | cmpne r2, #0 | ||
481 | beq .L407 | ||
482 | teq ip, r2 | ||
483 | submi r0, r0, r6 | ||
484 | addpl r0, r0, r6 | ||
485 | cmp r0, #(1024 << 18) | ||
486 | movgt r0, #(1024 << 18) | ||
487 | cmp r0, r10 | ||
488 | movlt r0, r10 | ||
489 | |||
490 | .L407: cmp r7, r1 @ loop back if more samples to do | ||
491 | bhi term_minus_3_loop | ||
492 | |||
493 | str r3, [r5, #8] @ else store previous samples & exit | ||
494 | str r8, [r5, #40] | ||
495 | |||
496 | /* | ||
497 | * Before finally exiting we must store weights back for next time | ||
498 | */ | ||
499 | |||
500 | common_exit: | ||
501 | mov r0, r0, asr #18 @ restore weights to real magnitude | ||
502 | mov r4, r4, asr #18 | ||
503 | strh r4, [r5, #4] | ||
504 | strh r0, [r5, #6] | ||
505 | ldmpc regs="r4-r8, r10-r11" | ||
506 | |||
diff --git a/lib/rbcodec/codecs/libwavpack/bits.c b/lib/rbcodec/codecs/libwavpack/bits.c new file mode 100644 index 0000000000..0f0e79c292 --- /dev/null +++ b/lib/rbcodec/codecs/libwavpack/bits.c | |||
@@ -0,0 +1,170 @@ | |||
1 | //////////////////////////////////////////////////////////////////////////// | ||
2 | // **** WAVPACK **** // | ||
3 | // Hybrid Lossless Wavefile Compressor // | ||
4 | // Copyright (c) 1998 - 2004 Conifer Software. // | ||
5 | // All Rights Reserved. // | ||
6 | // Distributed under the BSD Software License (see license.txt) // | ||
7 | //////////////////////////////////////////////////////////////////////////// | ||
8 | |||
9 | // bits.c | ||
10 | |||
11 | // This module provides utilities to support the BitStream structure which is | ||
12 | // used to read and write all WavPack audio data streams. It also contains a | ||
13 | // wrapper for the stream I/O functions and a set of functions dealing with | ||
14 | // endian-ness, both for enhancing portability. Finally, a debug wrapper for | ||
15 | // the malloc() system is provided. | ||
16 | |||
17 | #include "wavpack.h" | ||
18 | #include "system.h" | ||
19 | |||
20 | #include <string.h> | ||
21 | |||
22 | ////////////////////////// Bitstream functions //////////////////////////////// | ||
23 | |||
24 | // Open the specified BitStream and associate with the specified buffer. | ||
25 | |||
26 | static void bs_read (Bitstream *bs); | ||
27 | |||
28 | void bs_open_read (Bitstream *bs, uchar *buffer_start, uchar *buffer_end, read_stream file, uint32_t file_bytes) | ||
29 | { | ||
30 | CLEAR (*bs); | ||
31 | bs->buf = buffer_start; | ||
32 | bs->end = buffer_end; | ||
33 | |||
34 | if (file) { | ||
35 | bs->ptr = bs->end - 1; | ||
36 | bs->file_bytes = file_bytes; | ||
37 | bs->file = file; | ||
38 | } | ||
39 | else | ||
40 | bs->ptr = bs->buf - 1; | ||
41 | |||
42 | bs->wrap = bs_read; | ||
43 | } | ||
44 | |||
45 | // This function is only called from the getbit() and getbits() macros when | ||
46 | // the BitStream has been exhausted and more data is required. Sinve these | ||
47 | // bistreams no longer access files, this function simple sets an error and | ||
48 | // resets the buffer. | ||
49 | |||
50 | static void bs_read (Bitstream *bs) | ||
51 | { | ||
52 | if (bs->file && bs->file_bytes) { | ||
53 | uint32_t bytes_read, bytes_to_read = bs->end - bs->buf; | ||
54 | |||
55 | if (bytes_to_read > bs->file_bytes) | ||
56 | bytes_to_read = bs->file_bytes; | ||
57 | |||
58 | bytes_read = bs->file (bs->buf, bytes_to_read); | ||
59 | |||
60 | if (bytes_read) { | ||
61 | bs->end = bs->buf + bytes_read; | ||
62 | bs->file_bytes -= bytes_read; | ||
63 | } | ||
64 | else { | ||
65 | memset (bs->buf, -1, bs->end - bs->buf); | ||
66 | bs->error = 1; | ||
67 | } | ||
68 | } | ||
69 | else | ||
70 | bs->error = 1; | ||
71 | |||
72 | if (bs->error) | ||
73 | memset (bs->buf, -1, bs->end - bs->buf); | ||
74 | |||
75 | bs->ptr = bs->buf; | ||
76 | } | ||
77 | |||
78 | // Open the specified BitStream using the specified buffer pointers. It is | ||
79 | // assumed that enough buffer space has been allocated for all data that will | ||
80 | // be written, otherwise an error will be generated. | ||
81 | |||
82 | static void bs_write (Bitstream *bs); | ||
83 | |||
84 | void bs_open_write (Bitstream *bs, uchar *buffer_start, uchar *buffer_end) | ||
85 | { | ||
86 | bs->error = bs->sr = bs->bc = 0; | ||
87 | bs->ptr = bs->buf = buffer_start; | ||
88 | bs->end = buffer_end; | ||
89 | bs->wrap = bs_write; | ||
90 | } | ||
91 | |||
92 | // This function is only called from the putbit() and putbits() macros when | ||
93 | // the buffer is full, which is now flagged as an error. | ||
94 | |||
95 | static void bs_write (Bitstream *bs) | ||
96 | { | ||
97 | bs->ptr = bs->buf; | ||
98 | bs->error = 1; | ||
99 | } | ||
100 | |||
101 | // This function forces a flushing write of the specified BitStream, and | ||
102 | // returns the total number of bytes written into the buffer. | ||
103 | |||
104 | uint32_t bs_close_write (Bitstream *bs) | ||
105 | { | ||
106 | uint32_t bytes_written; | ||
107 | |||
108 | if (bs->error) | ||
109 | return (uint32_t) -1; | ||
110 | |||
111 | while (bs->bc || ((bs->ptr - bs->buf) & 1)) putbit_1 (bs); | ||
112 | bytes_written = bs->ptr - bs->buf; | ||
113 | CLEAR (*bs); | ||
114 | return bytes_written; | ||
115 | } | ||
116 | |||
117 | /////////////////////// Endian Correction Routines //////////////////////////// | ||
118 | |||
119 | void little_endian_to_native (void *data, char *format) | ||
120 | { | ||
121 | uchar *cp = (uchar *) data; | ||
122 | |||
123 | while (*format) { | ||
124 | switch (*format) { | ||
125 | case 'L': | ||
126 | *(long *)cp = letoh32(*(long *)cp); | ||
127 | cp += 4; | ||
128 | break; | ||
129 | |||
130 | case 'S': | ||
131 | *(short *)cp = letoh16(*(short *)cp); | ||
132 | cp += 2; | ||
133 | break; | ||
134 | |||
135 | default: | ||
136 | if (*format >= '0' && *format <= '9') | ||
137 | cp += *format - '0'; | ||
138 | |||
139 | break; | ||
140 | } | ||
141 | |||
142 | format++; | ||
143 | } | ||
144 | } | ||
145 | |||
146 | void native_to_little_endian (void *data, char *format) | ||
147 | { | ||
148 | uchar *cp = (uchar *) data; | ||
149 | |||
150 | while (*format) { | ||
151 | switch (*format) { | ||
152 | case 'L': | ||
153 | *(long *)cp = htole32(*(long *)cp); | ||
154 | cp += 4; | ||
155 | break; | ||
156 | |||
157 | case 'S': | ||
158 | *(short *)cp = htole16(*(short *)cp); | ||
159 | cp += 2; | ||
160 | break; | ||
161 | |||
162 | default: | ||
163 | if (*format >= '0' && *format <= '9') | ||
164 | cp += *format - '0'; | ||
165 | break; | ||
166 | } | ||
167 | |||
168 | format++; | ||
169 | } | ||
170 | } | ||
diff --git a/lib/rbcodec/codecs/libwavpack/coldfire.S b/lib/rbcodec/codecs/libwavpack/coldfire.S new file mode 100644 index 0000000000..884a0ac90f --- /dev/null +++ b/lib/rbcodec/codecs/libwavpack/coldfire.S | |||
@@ -0,0 +1,537 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2005 by David Bryant | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | /* This is an assembly optimized version of the following WavPack function: | ||
23 | * | ||
24 | * void decorr_stereo_pass_cont_mcf5249 (struct decorr_pass *dpp, | ||
25 | * long *buffer, long sample_count); | ||
26 | * | ||
27 | * It performs a single pass of stereo decorrelation on the provided buffer. | ||
28 | * Note that this version of the function requires that the 8 previous stereo | ||
29 | * samples are visible and correct. In other words, it ignores the "samples_*" | ||
30 | * fields in the decorr_pass structure and gets the history data directly | ||
31 | * from the buffer. It does, however, return the appropriate history samples | ||
32 | * to the decorr_pass structure before returning. | ||
33 | * | ||
34 | * This is written to work on a MCF5249 processor, or any processor based on | ||
35 | * the ColdFire V2 core with an EMAC unit. The EMAC is perfectly suited for | ||
36 | * the "apply_weight" function of WavPack decorrelation because it provides | ||
37 | * the requires 40-bit product. The fractional rounding mode of the EMAC is not | ||
38 | * configurable and uses "round to even" while WavPack uses "round to larger", | ||
39 | * so the rounding has to be done manually. | ||
40 | */ | ||
41 | |||
42 | .text | ||
43 | .align 2 | ||
44 | .global decorr_stereo_pass_cont_mcf5249 | ||
45 | |||
46 | decorr_stereo_pass_cont_mcf5249: | ||
47 | |||
48 | lea (-44, %sp), %sp | ||
49 | movem.l %d2-%d7/%a2-%a6, (%sp) | ||
50 | move.l 44+4(%sp), %a2 | a2 = dpp-> | ||
51 | move.l 44+8(%sp), %a1 | a1 = bptr | ||
52 | move.w 2(%a2), %a3 | a3 = dpp->delta | ||
53 | move.w 4(%a2), %d3 | d3 = dpp->weight_A (sign extended) | ||
54 | ext.l %d3 | ||
55 | move.w 6(%a2), %d4 | d4 = dpp->weight_B (sign extended) | ||
56 | ext.l %d4 | ||
57 | move.l 44+12(%sp), %d0 | d0 = sample_count | ||
58 | jbeq return_only | if zero, nothing to do | ||
59 | |||
60 | lsl.l #3, %d0 | d5 = bptr + (sample_count * 8) | ||
61 | move.l %d0, %d5 | ||
62 | add.l %a1, %d5 | ||
63 | |||
64 | moveq.l #17, %d0 | left shift weights & delta 17 places | ||
65 | asl.l %d0, %d3 | ||
66 | asl.l %d0, %d4 | ||
67 | move.l %a3, %d1 | ||
68 | asl.l %d0, %d1 | ||
69 | move.l %d1, %a3 | ||
70 | |||
71 | moveq.l #0x20, %d6 | ||
72 | move.l %d6, %macsr | set fractional mode for MAC | ||
73 | move.l #0x800000, %accext01 | acc1 = 0x00 0000 80 (for rounding) | ||
74 | |||
75 | move.l #1024<<17, %d6 | d6 & d7 are weight clipping limits | ||
76 | move.l #-1024<<17, %d7 | (only used by negative terms) | ||
77 | |||
78 | move.w (%a2), %d0 | d0 = term | ||
79 | ext.l %d0 | ||
80 | cmp.l #17, %d0 | ||
81 | jbeq term_17 | term = 17 | ||
82 | cmp.l #18, %d0 | ||
83 | jbeq term_18 | term = 18 | ||
84 | addq.l #1, %d0 | ||
85 | jbeq term_minus_1 | term = -1 | ||
86 | addq.l #1, %d0 | ||
87 | jbeq term_minus_2 | term = -2 | ||
88 | addq.l #1, %d0 | ||
89 | jbeq term_minus_3 | term = -3 | ||
90 | jbra term_default | default term = 1 - 8 | ||
91 | |||
92 | |------------------------------------------------------------------------------ | ||
93 | | Loop to handle term = 17 condition | ||
94 | | | ||
95 | | a0 = d0 = (2 * bptr [-1]) - bptr [-2] | ||
96 | | a1 = bptr d1 = initial bptr [0] | ||
97 | | a2 = dpp-> d2 = updated bptr [0] | ||
98 | | a3 = dpp->delta << 17 d3 = dpp->weight_A << 17 | ||
99 | | a4 = d4 = dpp->weight_B << 17 | ||
100 | | a5 = d5 = eptr | ||
101 | | macsr = 0x20 acc1 = 0x00 0000 80 | ||
102 | |------------------------------------------------------------------------------ | ||
103 | |||
104 | term_17: | ||
105 | move.l -8(%a1), %d0 | d0 = 2 * bptr [-1] - bptr [-2] | ||
106 | add.l %d0, %d0 | ||
107 | sub.l -16(%a1), %d0 | ||
108 | beq .L251 | if zero, skip calculation | ||
109 | move.l %acc1, %acc0 | ||
110 | asl.l #4, %d0 | acc0 = acc1 + (d0 << 4) * weight_A | ||
111 | mac.l %d0, %d3, %acc0 | ||
112 | move.l (%a1), %d1 | ||
113 | beq .L255 | ||
114 | eor.l %d1, %d0 | else compare signs | ||
115 | bge .L256 | if same, add delta to weight | ||
116 | sub.l %a3, %d3 | else subtract delta from weight | ||
117 | sub.l %a3, %d3 | subtract again instead of branch | ||
118 | .L256: add.l %a3, %d3 | add delta to weight | ||
119 | |||
120 | .L255: move.l %acc0, %d2 | d2 = rounded product | ||
121 | add.l %d1, %d2 | update bptr [0] and store | ||
122 | move.l %d2, (%a1)+ | ||
123 | |||
124 | .L253: move.l -8(%a1), %d0 | d0 = 2 * bptr [-1] - bptr [-2] | ||
125 | add.l %d0, %d0 | ||
126 | sub.l -16(%a1), %d0 | ||
127 | beq .L257 | if zero, skip calculations | ||
128 | move.l %acc1, %acc0 | ||
129 | asl.l #4, %d0 | acc0 = acc1 + (d0 << 4) * weight_B | ||
130 | mac.l %d0, %d4, %acc0 | ||
131 | move.l (%a1), %d1 | ||
132 | beq .L254 | ||
133 | eor.l %d1, %d0 | else compare signs | ||
134 | bge .L259 | if same, add delta to weight | ||
135 | sub.l %a3, %d4 | else subtract delta from weight | ||
136 | sub.l %a3, %d4 | subtract again instead of branch | ||
137 | .L259: add.l %a3, %d4 | add delta to weight | ||
138 | |||
139 | .L254: move.l %acc0, %d2 | d2 = rounded product | ||
140 | add.l %d1, %d2 | update bptr [0] and store | ||
141 | move.l %d2, (%a1)+ | ||
142 | |||
143 | .L252: cmp.l %a1, %d5 | loop if bptr < eptr | ||
144 | jbhi term_17 | ||
145 | bra term_17_18_finish | exit through common path | ||
146 | |||
147 | .L251: addq.l #4, %a1 | update point and jump back into loop | ||
148 | bra .L253 | ||
149 | |||
150 | .L257: addq.l #4, %a1 | update point and jump back into loop | ||
151 | bra .L252 | ||
152 | |||
153 | |------------------------------------------------------------------------------ | ||
154 | | Loop to handle term = 18 condition | ||
155 | | | ||
156 | | a0 = d0 = ((3 * bptr [-1]) - bptr [-2]) >> 1 | ||
157 | | a1 = bptr d1 = initial bptr [0] | ||
158 | | a2 = dpp-> d2 = updated bptr [0] | ||
159 | | a3 = dpp->delta << 17 d3 = dpp->weight_A << 17 | ||
160 | | a4 = d4 = dpp->weight_B << 17 | ||
161 | | a5 = d5 = eptr | ||
162 | | macsr = 0x20 acc1 = 0x00 0000 80 | ||
163 | |------------------------------------------------------------------------------ | ||
164 | |||
165 | term_18: | ||
166 | move.l -8(%a1), %a0 | d0 = (3 * bptr [-1] - bptr [-2]) >> 1 | ||
167 | lea (%a0,%a0.l*2), %a0 | ||
168 | move.l %a0, %d0 | ||
169 | sub.l -16(%a1), %d0 | ||
170 | asr.l #1, %d0 | ||
171 | beq .L260 | ||
172 | move.l %acc1, %acc0 | ||
173 | asl.l #4, %d0 | acc0 = acc1 + (d0 << 4) * weight_A | ||
174 | mac.l %d0, %d3, %acc0 | ||
175 | move.l (%a1), %d1 | ||
176 | beq .L266 | ||
177 | eor.l %d1, %d0 | else compare signs | ||
178 | bge .L267 | if same, add delta to weight | ||
179 | sub.l %a3, %d3 | else subtract delta from weight | ||
180 | sub.l %a3, %d3 | subtract again instead of branch | ||
181 | .L267: add.l %a3, %d3 | add delta to weight | ||
182 | |||
183 | .L266: move.l %acc0, %d2 | d2 = rounded product | ||
184 | add.l %d1, %d2 | add applied weight to bptr [0], store | ||
185 | move.l %d2, (%a1)+ | ||
186 | |||
187 | .L268: move.l -8(%a1), %a0 | d0 = (3 * bptr [-1] - bptr [-2]) >> 1 | ||
188 | lea (%a0,%a0.l*2), %a0 | ||
189 | move.l %a0, %d0 | ||
190 | sub.l -16(%a1), %d0 | ||
191 | asr.l #1, %d0 | ||
192 | beq .L261 | ||
193 | move.l %acc1, %acc0 | ||
194 | asl.l #4, %d0 | acc0 = acc1 + (d0 << 4) * weight_B | ||
195 | mac.l %d0, %d4, %acc0 | ||
196 | move.l (%a1), %d1 | ||
197 | beq .L265 | ||
198 | eor.l %d1, %d0 | else compare signs | ||
199 | bge .L270 | if same, add delta to weight | ||
200 | sub.l %a3, %d4 | else subtract delta from weight | ||
201 | sub.l %a3, %d4 | subtract again instead of branch | ||
202 | .L270: add.l %a3, %d4 | add delta to weight | ||
203 | |||
204 | .L265: move.l %acc0, %d2 | d2 = rounded product | ||
205 | add.l %d1, %d2 | add applied weight to bptr [0], store | ||
206 | move.l %d2, (%a1)+ | ||
207 | |||
208 | .L269: cmp.l %a1, %d5 | loop if bptr < eptr | ||
209 | jbhi term_18 | ||
210 | bra term_17_18_finish | exit through common path | ||
211 | |||
212 | .L260: addq.l #4, %a1 | bump pointer and jump back into loop | ||
213 | bra .L268 | ||
214 | |||
215 | .L261: addq.l #4, %a1 | bump pointer and jump back into loop | ||
216 | bra .L269 | ||
217 | |||
218 | term_17_18_finish: | ||
219 | move.l -4(%a1), 40(%a2) | restore dpp->samples_A [0-1], B [0-1] | ||
220 | move.l -8(%a1), 8(%a2) | ||
221 | move.l -12(%a1), 44(%a2) | ||
222 | move.l -16(%a1), 12(%a2) | ||
223 | jbra finish_up | ||
224 | |||
225 | |------------------------------------------------------------------------------ | ||
226 | | Loop to handle default terms (i.e. 1 - 8) | ||
227 | | | ||
228 | | a0 = tptr d0 = tptr [0] | ||
229 | | a1 = bptr d1 = initial bptr [0] | ||
230 | | a2 = dpp-> d2 = updated bptr [0] | ||
231 | | a3 = dpp->delta << 17 d3 = dpp->weight_A << 17 | ||
232 | | a4 = d4 = dpp->weight_B << 17 | ||
233 | | a5 = d5 = eptr | ||
234 | | macsr = 0x20 acc1 = 0x00 0000 80 | ||
235 | |------------------------------------------------------------------------------ | ||
236 | |||
237 | term_default: | ||
238 | move.w (%a2), %d0 | a0 = a1 - (dpp->term * 8) | ||
239 | ext.l %d0 | ||
240 | lsl.l #3, %d0 | ||
241 | move.l %a1, %a0 | ||
242 | sub.l %d0, %a0 | ||
243 | |||
244 | term_default_loop: | ||
245 | move.l (%a0)+, %d0 | d0 = tptr [0], skip ahead if zero | ||
246 | beq .L271 | ||
247 | move.l %acc1, %acc0 | ||
248 | asl.l #4, %d0 | acc0 = acc1 + (d0 << 4) * weight_A | ||
249 | mac.l %d0, %d3, %acc0 | ||
250 | move.l (%a1), %d1 | ||
251 | beq .L277 | ||
252 | eor.l %d1, %d0 | else compare signs | ||
253 | bge .L278 | if same, add delta to weight | ||
254 | sub.l %a3, %d3 | else subtract delta from weight | ||
255 | sub.l %a3, %d3 | subtract again instead of branch | ||
256 | .L278: add.l %a3, %d3 | add delta to weight | ||
257 | |||
258 | .L277: move.l %acc0, %d2 | d2 = rounded product | ||
259 | add.l %d1, %d2 | add applied weight to bptr [0], store | ||
260 | move.l %d2, (%a1)+ | ||
261 | |||
262 | .L275: move.l (%a0)+, %d0 | d0 = tptr [0], skip ahead if zero | ||
263 | beq .L272 | ||
264 | move.l %acc1, %acc0 | ||
265 | asl.l #4, %d0 | acc0 = acc1 + (d0 << 4) * weight_B | ||
266 | mac.l %d0, %d4, %acc0 | ||
267 | move.l (%a1), %d1 | ||
268 | beq .L276 | ||
269 | eor.l %d1, %d0 | else compare signs | ||
270 | bge .L281 | if same, add delta to weight | ||
271 | sub.l %a3, %d4 | else subtract delta from weight | ||
272 | sub.l %a3, %d4 | subtract again instead of branch | ||
273 | .L281: add.l %a3, %d4 | add delta to weight | ||
274 | |||
275 | .L276: move.l %acc0, %d2 | d2 = rounded product | ||
276 | add.l %d1, %d2 | add applied weight to bptr [0], store | ||
277 | move.l %d2, (%a1)+ | ||
278 | |||
279 | .L274: cmp.l %a1, %d5 | loop back if bptr < eptr | ||
280 | jbhi term_default_loop | ||
281 | move.w (%a2), %d0 | d0 = term - 1 | ||
282 | moveq.l #8, %d1 | d1 = loop counter | ||
283 | |||
284 | .L323: subq.l #1, %d0 | back up & mask index | ||
285 | and.l #7, %d0 | ||
286 | move.l -(%a1), 40(%a2,%d0.l*4) | store dpp->samples_B [d0] | ||
287 | move.l -(%a1), 8(%a2,%d0.l*4) | store dpp->samples_A [d0] | ||
288 | subq.l #1, %d1 | loop on count | ||
289 | jbne .L323 | ||
290 | jbra finish_up | ||
291 | |||
292 | .L271: addq.l #4, %a1 | bump pointer and jump back into loop | ||
293 | bra .L275 | ||
294 | |||
295 | .L272: addq.l #4, %a1 | bump pointer and jump back into loop | ||
296 | bra .L274 | ||
297 | |||
298 | |||
299 | |------------------------------------------------------------------------------ | ||
300 | | Loop to handle term = -1 condition | ||
301 | | | ||
302 | | a0 = d0 = decorrelation sample | ||
303 | | a1 = bptr d1 = initial bptr [0] | ||
304 | | a2 = dpp-> d2 = updated bptr [0] | ||
305 | | a3 = dpp->delta << 17 d3 = dpp->weight_A << 17 | ||
306 | | a4 = d4 = dpp->weight_B << 17 | ||
307 | | a5 = d5 = eptr | ||
308 | | a6 = d6 = 1024 << 17 | ||
309 | | a7 = d7 = -1024 << 17 | ||
310 | | macsr = 0x20 acc1 = 0x00 0000 80 | ||
311 | |------------------------------------------------------------------------------ | ||
312 | |||
313 | term_minus_1: | ||
314 | move.l -4(%a1), %d0 | d0 = bptr [-1] | ||
315 | beq .L402 | ||
316 | move.l %acc1, %acc0 | ||
317 | asl.l #4, %d0 | acc0 = acc1 + ((d0 << 4) * weight_A) | ||
318 | mac.l %d0, %d3, %acc0 | ||
319 | move.l (%a1), %d1 | ||
320 | beq .L405 | ||
321 | eor.l %d1, %d0 | else compare signs | ||
322 | bge .L404 | if same, add delta to weight | ||
323 | sub.l %a3, %d3 | else subtract delta from weight | ||
324 | cmp.l %d7, %d3 | check for negative clip limit | ||
325 | bge .L405 | ||
326 | move.l %d7, %d3 | ||
327 | bra .L405 | ||
328 | |||
329 | .L404: add.l %a3, %d3 | add delta to weight | ||
330 | cmp.l %d6, %d3 | check for positive clip limit | ||
331 | ble .L405 | ||
332 | move.l %d6, %d3 | ||
333 | |||
334 | .L405: move.l %acc0, %d0 | d2 = rounded product | ||
335 | add.l %d1, %d0 | add applied weight to bptr [0], store | ||
336 | move.l %d0, (%a1)+ | ||
337 | beq .L401 | ||
338 | |||
339 | .L410: move.l %acc1, %acc0 | ||
340 | asl.l #4, %d0 | acc0 = acc1 + ((d0 << 4) * weight_B) | ||
341 | mac.l %d0, %d4, %acc0 | ||
342 | move.l (%a1), %d1 | ||
343 | beq .L403 | ||
344 | eor.l %d1, %d0 | else compare signs | ||
345 | bge .L407 | if same, add delta to weight | ||
346 | sub.l %a3, %d4 | else subtract delta from weight | ||
347 | cmp.l %d7, %d4 | check for negative clip limit | ||
348 | bge .L403 | ||
349 | move.l %d7, %d4 | ||
350 | bra .L403 | ||
351 | |||
352 | .L407: add.l %a3, %d4 | add delta to weight | ||
353 | cmp.l %d6, %d4 | check for positive clip limit | ||
354 | ble .L403 | ||
355 | move.l %d6, %d4 | ||
356 | |||
357 | .L403: move.l %acc0, %d2 | d2 = rounded product | ||
358 | add.l %d1, %d2 | add applied weight to bptr [1], store | ||
359 | move.l %d2, (%a1)+ | ||
360 | |||
361 | .L411: cmp.l %a1, %d5 | loop back if bptr < eptr | ||
362 | jbhi term_minus_1 | ||
363 | move.l -4(%a1), 8(%a2) | dpp->samples_A [0] = bptr [-1] | ||
364 | jbra finish_up | ||
365 | |||
366 | .L402: move.l (%a1)+, %d0 | ||
367 | bne .L410 | ||
368 | |||
369 | .L401: addq.l #4, %a1 | ||
370 | bra .L411 | ||
371 | |||
372 | |||
373 | |------------------------------------------------------------------------------ | ||
374 | | Loop to handle term = -2 condition | ||
375 | | | ||
376 | | a0 = d0 = decorrelation sample | ||
377 | | a1 = bptr d1 = initial bptr [0] | ||
378 | | a2 = dpp-> d2 = updated bptr [0] | ||
379 | | a3 = dpp->delta << 17 d3 = dpp->weight_A << 17 | ||
380 | | a4 = d4 = dpp->weight_B << 17 | ||
381 | | a5 = d5 = eptr | ||
382 | | a6 = d6 = 1024 << 17 | ||
383 | | a7 = d7 = -1024 << 17 | ||
384 | | macsr = 0x20 acc1 = 0x00 0000 80 | ||
385 | |------------------------------------------------------------------------------ | ||
386 | |||
387 | term_minus_2: | ||
388 | move.l -8(%a1), %d0 | d0 = bptr [-2] | ||
389 | beq .L511 | ||
390 | move.l %acc1, %acc0 | ||
391 | asl.l #4, %d0 | acc0 = acc1 + ((d0 << 4) * weight_B) | ||
392 | mac.l %d0, %d4, %acc0 | ||
393 | move.l 4(%a1), %d1 | ||
394 | beq .L505 | ||
395 | eor.l %d1, %d0 | else compare signs | ||
396 | bge .L504 | if same, add delta to weight | ||
397 | sub.l %a3, %d4 | else subtract delta from weight | ||
398 | cmp.l %d7, %d4 | ckeck for negative clip limit | ||
399 | bge .L505 | ||
400 | move.l %d7, %d4 | ||
401 | bra .L505 | ||
402 | |||
403 | .L504: add.l %a3, %d4 | add delta to weight | ||
404 | cmp.l %d6, %d4 | check for positive clip limit | ||
405 | ble .L505 | ||
406 | move.l %d6, %d4 | ||
407 | |||
408 | .L505: move.l %acc0, %d0 | d2 = rounded product | ||
409 | add.l %d1, %d0 | add applied weight to bptr [0], store | ||
410 | move.l %d0, 4(%a1) | ||
411 | beq .L512 | ||
412 | |||
413 | .L510: move.l %acc1, %acc0 | ||
414 | asl.l #4, %d0 | acc0 = acc1 + ((d0 << 4) * weight_A) | ||
415 | mac.l %d0, %d3, %acc0 | ||
416 | move.l (%a1), %d1 | ||
417 | beq .L503 | ||
418 | eor.l %d1, %d0 | else compare signs | ||
419 | bge .L507 | if same, add delta to weight | ||
420 | sub.l %a3, %d3 | else subtract delta from weight | ||
421 | cmp.l %d7, %d3 | check for negative clip limit | ||
422 | bge .L503 | ||
423 | move.l %d7, %d3 | ||
424 | bra .L503 | ||
425 | |||
426 | .L507: add.l %a3, %d3 | add delta to weight | ||
427 | cmp.l %d6, %d3 | check for negative clip limit | ||
428 | ble .L503 | ||
429 | move.l %d6, %d3 | ||
430 | |||
431 | .L503: move.l %acc0, %d2 | d2 = rounded product | ||
432 | add.l %d1, %d2 | add applied weight to bptr [1], store | ||
433 | move.l %d2, (%a1) | ||
434 | |||
435 | .L512: addq.l #8, %a1 | ||
436 | cmp.l %a1, %d5 | loop if bptr < eptr | ||
437 | jbhi term_minus_2 | ||
438 | move.l -8(%a1), 40(%a2) | dpp->samples_B [0] = bptr [-4] | ||
439 | jbra finish_up | ||
440 | |||
441 | .L511: move.l 4(%a1), %d0 | ||
442 | beq .L512 | ||
443 | bra .L510 | ||
444 | |||
445 | |||
446 | |------------------------------------------------------------------------------ | ||
447 | | Loop to handle term = -3 condition | ||
448 | | | ||
449 | | a0 = d0 = decorrelation sample | ||
450 | | a1 = bptr d1 = initial bptr [0] | ||
451 | | a2 = dpp-> d2 = updated bptr [0] | ||
452 | | a3 = dpp->delta << 17 d3 = dpp->weight_A << 17 | ||
453 | | a4 = d4 = dpp->weight_B << 17 | ||
454 | | a5 = d5 = eptr | ||
455 | | a6 = d6 = 1024 << 17 | ||
456 | | a7 = d7 = -1024 << 17 | ||
457 | | macsr = 0x20 acc1 = 0x00 0000 80 | ||
458 | |------------------------------------------------------------------------------ | ||
459 | |||
460 | term_minus_3: | ||
461 | move.l -4(%a1), %d0 | d0 = bptr [-1] | ||
462 | beq .L301 | ||
463 | move.l %acc1, %acc0 | ||
464 | asl.l #4, %d0 | acc0 = acc1 + ((d0 << 4) * weight_A) | ||
465 | mac.l %d0, %d3, %acc0 | ||
466 | move.l (%a1), %d1 | ||
467 | beq .L320 | ||
468 | eor.l %d1, %d0 | else compare signs | ||
469 | bge .L319 | if same, add delta to weight | ||
470 | sub.l %a3, %d3 | else subtract delta from weight | ||
471 | cmp.l %d7, %d3 | check for negative clip limit | ||
472 | bge .L320 | ||
473 | move.l %d7, %d3 | ||
474 | bra .L320 | ||
475 | |||
476 | .L319: add.l %a3, %d3 | add delta to weight | ||
477 | cmp.l %d6, %d3 | check for positive clip limit | ||
478 | ble .L320 | ||
479 | move.l %d6, %d3 | ||
480 | |||
481 | .L320: move.l %acc0, %d2 | d2 = rounded product | ||
482 | add.l %d1, %d2 | add applied weight to bptr [0], store | ||
483 | move.l %d2, (%a1)+ | ||
484 | |||
485 | .L330: move.l -12(%a1), %d0 | d0 = bptr [-2] | ||
486 | beq .L302 | ||
487 | move.l %acc1, %acc0 | ||
488 | asl.l #4, %d0 | acc0 = acc1 + ((d0 << 4) * weight_B) | ||
489 | mac.l %d0, %d4, %acc0 | ||
490 | move.l (%a1), %d1 | ||
491 | beq .L318 | ||
492 | eor.l %d1, %d0 | else compare signs | ||
493 | bge .L322 | if same, add delta to weight | ||
494 | sub.l %a3, %d4 | else subtract delta from weight | ||
495 | cmp.l %d7, %d4 | check for negative clip limit | ||
496 | bge .L318 | ||
497 | move.l %d7, %d4 | ||
498 | bra .L318 | ||
499 | |||
500 | .L322: add.l %a3, %d4 | add delta to weight | ||
501 | cmp.l %d6, %d4 | check for positive clip limit | ||
502 | ble .L318 | ||
503 | move.l %d6, %d4 | ||
504 | |||
505 | .L318: move.l %acc0, %d2 | d2 = rounded product | ||
506 | add.l %d1, %d2 | add applied weight to bptr [1], store | ||
507 | move.l %d2, (%a1)+ | ||
508 | |||
509 | .L331: cmp.l %a1, %d5 | bptr, eptr | ||
510 | jbhi term_minus_3 | ||
511 | move.l -4(%a1), 8(%a2) | dpp->samples_A [0] = bptr [-1] | ||
512 | move.l -8(%a1), 40(%a2) | dpp->samples_B [0] = bptr [-2] | ||
513 | jbra finish_up | ||
514 | |||
515 | .L301: addq.l #4, %a1 | ||
516 | bra .L330 | ||
517 | |||
518 | .L302: addq.l #4, %a1 | ||
519 | bra .L331 | ||
520 | |||
521 | | finish and return | ||
522 | |||
523 | finish_up: | ||
524 | moveq.l #17, %d0 | ||
525 | asr.l %d0, %d3 | ||
526 | asr.l %d0, %d4 | ||
527 | move.w %d3, 4(%a2) | weight_A, dpp->weight_A | ||
528 | move.w %d4, 6(%a2) | weight_B, dpp->weight_B | ||
529 | |||
530 | clr.l %d0 | clear up EMAC | ||
531 | move.l %d0, %acc0 | ||
532 | move.l %d0, %acc1 | ||
533 | |||
534 | return_only: | ||
535 | movem.l (%sp), %d2-%d7/%a2-%a6 | ||
536 | lea (44,%sp), %sp | ||
537 | rts | ||
diff --git a/lib/rbcodec/codecs/libwavpack/float.c b/lib/rbcodec/codecs/libwavpack/float.c new file mode 100644 index 0000000000..6e5c4e4f61 --- /dev/null +++ b/lib/rbcodec/codecs/libwavpack/float.c | |||
@@ -0,0 +1,47 @@ | |||
1 | //////////////////////////////////////////////////////////////////////////// | ||
2 | // **** WAVPACK **** // | ||
3 | // Hybrid Lossless Wavefile Compressor // | ||
4 | // Copyright (c) 1998 - 2004 Conifer Software. // | ||
5 | // All Rights Reserved. // | ||
6 | // Distributed under the BSD Software License (see license.txt) // | ||
7 | //////////////////////////////////////////////////////////////////////////// | ||
8 | |||
9 | // float.c | ||
10 | |||
11 | #include "wavpack.h" | ||
12 | |||
13 | int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd) | ||
14 | { | ||
15 | int bytecnt = wpmd->byte_length; | ||
16 | char *byteptr = wpmd->data; | ||
17 | |||
18 | if (bytecnt != 4) | ||
19 | return FALSE; | ||
20 | |||
21 | wps->float_flags = *byteptr++; | ||
22 | wps->float_shift = *byteptr++; | ||
23 | wps->float_max_exp = *byteptr++; | ||
24 | wps->float_norm_exp = *byteptr; | ||
25 | return TRUE; | ||
26 | } | ||
27 | |||
28 | /* This function converts WavPack floating point data into standard Rockbox | ||
29 | * 28-bit integers. It is assumed that clipping will be taken care of later. | ||
30 | */ | ||
31 | |||
32 | void float_values (WavpackStream *wps, int32_t *values, int32_t num_values) | ||
33 | { | ||
34 | int shift = wps->float_max_exp - wps->float_norm_exp + wps->float_shift + 5; | ||
35 | |||
36 | if (shift > 32) | ||
37 | shift = 32; | ||
38 | else if (shift < -32) | ||
39 | shift = -32; | ||
40 | |||
41 | if (shift > 0) | ||
42 | while (num_values--) | ||
43 | *values++ <<= shift; | ||
44 | else if (shift < 0) | ||
45 | while (num_values--) | ||
46 | *values++ >>= -shift; | ||
47 | } | ||
diff --git a/lib/rbcodec/codecs/libwavpack/libwavpack.make b/lib/rbcodec/codecs/libwavpack/libwavpack.make new file mode 100644 index 0000000000..27a2d214a1 --- /dev/null +++ b/lib/rbcodec/codecs/libwavpack/libwavpack.make | |||
@@ -0,0 +1,18 @@ | |||
1 | # __________ __ ___. | ||
2 | # Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
3 | # Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
4 | # Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
5 | # Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
6 | # \/ \/ \/ \/ \/ | ||
7 | # $Id$ | ||
8 | # | ||
9 | |||
10 | # libwavpack | ||
11 | WAVPACKLIB := $(CODECDIR)/libwavpack.a | ||
12 | WAVPACKLIB_SRC := $(call preprocess, $(RBCODECLIB_DIR)/codecs/libwavpack/SOURCES) | ||
13 | WAVPACKLIB_OBJ := $(call c2obj, $(WAVPACKLIB_SRC)) | ||
14 | OTHER_SRC += $(WAVPACKLIB_SRC) | ||
15 | |||
16 | $(WAVPACKLIB): $(WAVPACKLIB_OBJ) | ||
17 | $(SILENT)$(shell rm -f $@) | ||
18 | $(call PRINTS,AR $(@F))$(AR) rcs $@ $^ >/dev/null | ||
diff --git a/lib/rbcodec/codecs/libwavpack/make.bat b/lib/rbcodec/codecs/libwavpack/make.bat new file mode 100644 index 0000000000..0ca72d7e55 --- /dev/null +++ b/lib/rbcodec/codecs/libwavpack/make.bat | |||
@@ -0,0 +1 @@ | |||
cl /O1 /DWIN32 wvfilter.c wputils.c unpack.c float.c metadata.c words.c bits.c | |||
diff --git a/lib/rbcodec/codecs/libwavpack/metadata.c b/lib/rbcodec/codecs/libwavpack/metadata.c new file mode 100644 index 0000000000..4dce10100f --- /dev/null +++ b/lib/rbcodec/codecs/libwavpack/metadata.c | |||
@@ -0,0 +1,171 @@ | |||
1 | //////////////////////////////////////////////////////////////////////////// | ||
2 | // **** WAVPACK **** // | ||
3 | // Hybrid Lossless Wavefile Compressor // | ||
4 | // Copyright (c) 1998 - 2003 Conifer Software. // | ||
5 | // All Rights Reserved. // | ||
6 | // Distributed under the BSD Software License (see license.txt) // | ||
7 | //////////////////////////////////////////////////////////////////////////// | ||
8 | |||
9 | // metadata.c | ||
10 | |||
11 | // This module handles the metadata structure introduced in WavPack 4.0 | ||
12 | |||
13 | #include "wavpack.h" | ||
14 | |||
15 | #include <string.h> | ||
16 | |||
17 | int read_metadata_buff (WavpackContext *wpc, WavpackMetadata *wpmd) | ||
18 | { | ||
19 | uint32_t bytes_to_read; | ||
20 | uchar tchar; | ||
21 | |||
22 | if (wpc->stream.block_bytes_left < 2 || !wpc->infile (&wpmd->id, 1) || !wpc->infile (&tchar, 1)) | ||
23 | return FALSE; | ||
24 | |||
25 | wpmd->byte_length = tchar << 1; | ||
26 | wpc->stream.block_bytes_left -= 2; | ||
27 | |||
28 | if (wpmd->id & ID_LARGE) { | ||
29 | wpmd->id &= ~ID_LARGE; | ||
30 | |||
31 | if (wpc->stream.block_bytes_left < 2 || !wpc->infile (&tchar, 1)) | ||
32 | return FALSE; | ||
33 | |||
34 | wpmd->byte_length += (int32_t) tchar << 9; | ||
35 | |||
36 | if (!wpc->infile (&tchar, 1)) | ||
37 | return FALSE; | ||
38 | |||
39 | wpmd->byte_length += (int32_t) tchar << 17; | ||
40 | wpc->stream.block_bytes_left -= 2; | ||
41 | } | ||
42 | |||
43 | if ((wpc->stream.block_bytes_left -= wpmd->byte_length) < 0) | ||
44 | return FALSE; | ||
45 | |||
46 | if (wpmd->id & ID_ODD_SIZE) { | ||
47 | wpmd->id &= ~ID_ODD_SIZE; | ||
48 | wpmd->byte_length--; | ||
49 | } | ||
50 | |||
51 | if (!wpmd->byte_length || wpmd->id == ID_WV_BITSTREAM) { | ||
52 | wpmd->data = NULL; | ||
53 | return TRUE; | ||
54 | } | ||
55 | |||
56 | bytes_to_read = wpmd->byte_length + (wpmd->byte_length & 1); | ||
57 | |||
58 | if (bytes_to_read > sizeof (wpc->read_buffer)) { | ||
59 | wpmd->data = NULL; | ||
60 | |||
61 | while (bytes_to_read > sizeof (wpc->read_buffer)) | ||
62 | if (wpc->infile (wpc->read_buffer, sizeof (wpc->read_buffer)) == sizeof (wpc->read_buffer)) | ||
63 | bytes_to_read -= sizeof (wpc->read_buffer); | ||
64 | else | ||
65 | return FALSE; | ||
66 | } | ||
67 | else | ||
68 | wpmd->data = wpc->read_buffer; | ||
69 | |||
70 | if (bytes_to_read && wpc->infile (wpc->read_buffer, bytes_to_read) != (int32_t) bytes_to_read) { | ||
71 | wpmd->data = NULL; | ||
72 | return FALSE; | ||
73 | } | ||
74 | |||
75 | return TRUE; | ||
76 | } | ||
77 | |||
78 | int process_metadata (WavpackContext *wpc, WavpackMetadata *wpmd) | ||
79 | { | ||
80 | WavpackStream *wps = &wpc->stream; | ||
81 | |||
82 | switch (wpmd->id) { | ||
83 | case ID_DUMMY: | ||
84 | return TRUE; | ||
85 | |||
86 | case ID_DECORR_TERMS: | ||
87 | return read_decorr_terms (wps, wpmd); | ||
88 | |||
89 | case ID_DECORR_WEIGHTS: | ||
90 | return read_decorr_weights (wps, wpmd); | ||
91 | |||
92 | case ID_DECORR_SAMPLES: | ||
93 | return read_decorr_samples (wps, wpmd); | ||
94 | |||
95 | case ID_ENTROPY_VARS: | ||
96 | return read_entropy_vars (wps, wpmd); | ||
97 | |||
98 | case ID_HYBRID_PROFILE: | ||
99 | return read_hybrid_profile (wps, wpmd); | ||
100 | |||
101 | case ID_FLOAT_INFO: | ||
102 | return read_float_info (wps, wpmd); | ||
103 | |||
104 | case ID_INT32_INFO: | ||
105 | return read_int32_info (wps, wpmd); | ||
106 | |||
107 | case ID_CHANNEL_INFO: | ||
108 | return read_channel_info (wpc, wpmd); | ||
109 | |||
110 | case ID_SAMPLE_RATE: | ||
111 | return read_sample_rate (wpc, wpmd); | ||
112 | |||
113 | case ID_CONFIG_BLOCK: | ||
114 | return read_config_info (wpc, wpmd); | ||
115 | |||
116 | case ID_WV_BITSTREAM: | ||
117 | return init_wv_bitstream (wpc, wpmd); | ||
118 | |||
119 | case ID_SHAPING_WEIGHTS: | ||
120 | case ID_WVC_BITSTREAM: | ||
121 | case ID_WVX_BITSTREAM: | ||
122 | return TRUE; | ||
123 | |||
124 | default: | ||
125 | return (wpmd->id & ID_OPTIONAL_DATA) ? TRUE : FALSE; | ||
126 | } | ||
127 | } | ||
128 | |||
129 | int copy_metadata (WavpackMetadata *wpmd, uchar *buffer_start, uchar *buffer_end) | ||
130 | { | ||
131 | uint32_t mdsize = wpmd->byte_length + (wpmd->byte_length & 1); | ||
132 | WavpackHeader *wphdr = (WavpackHeader *) buffer_start; | ||
133 | |||
134 | if (wpmd->byte_length & 1) | ||
135 | ((char *) wpmd->data) [wpmd->byte_length] = 0; | ||
136 | |||
137 | mdsize += (wpmd->byte_length > 510) ? 4 : 2; | ||
138 | buffer_start += wphdr->ckSize + 8; | ||
139 | |||
140 | if (buffer_start + mdsize >= buffer_end) | ||
141 | return FALSE; | ||
142 | |||
143 | buffer_start [0] = wpmd->id | (wpmd->byte_length & 1 ? ID_ODD_SIZE : 0); | ||
144 | buffer_start [1] = (wpmd->byte_length + 1) >> 1; | ||
145 | |||
146 | if (wpmd->byte_length > 510) { | ||
147 | buffer_start [0] |= ID_LARGE; | ||
148 | buffer_start [2] = (wpmd->byte_length + 1) >> 9; | ||
149 | buffer_start [3] = (wpmd->byte_length + 1) >> 17; | ||
150 | } | ||
151 | |||
152 | if (wpmd->data && wpmd->byte_length) { | ||
153 | if (wpmd->byte_length > 510) { | ||
154 | buffer_start [0] |= ID_LARGE; | ||
155 | buffer_start [2] = (wpmd->byte_length + 1) >> 9; | ||
156 | buffer_start [3] = (wpmd->byte_length + 1) >> 17; | ||
157 | memcpy (buffer_start + 4, wpmd->data, mdsize - 4); | ||
158 | } | ||
159 | else | ||
160 | memcpy (buffer_start + 2, wpmd->data, mdsize - 2); | ||
161 | } | ||
162 | |||
163 | wphdr->ckSize += mdsize; | ||
164 | return TRUE; | ||
165 | } | ||
166 | |||
167 | void free_metadata (WavpackMetadata *wpmd) | ||
168 | { | ||
169 | wpmd->data = NULL; | ||
170 | } | ||
171 | |||
diff --git a/lib/rbcodec/codecs/libwavpack/pack.c b/lib/rbcodec/codecs/libwavpack/pack.c new file mode 100644 index 0000000000..a46d05fe14 --- /dev/null +++ b/lib/rbcodec/codecs/libwavpack/pack.c | |||
@@ -0,0 +1,470 @@ | |||
1 | //////////////////////////////////////////////////////////////////////////// | ||
2 | // **** WAVPACK **** // | ||
3 | // Hybrid Lossless Wavefile Compressor // | ||
4 | // Copyright (c) 1998 - 2005 Conifer Software. // | ||
5 | // All Rights Reserved. // | ||
6 | // Distributed under the BSD Software License (see license.txt) // | ||
7 | //////////////////////////////////////////////////////////////////////////// | ||
8 | |||
9 | // pack.c | ||
10 | |||
11 | // This module actually handles the compression of the audio data, except for | ||
12 | // the entropy coding which is handled by the words? modules. For efficiency, | ||
13 | // the conversion is isolated to tight loops that handle an entire buffer. | ||
14 | |||
15 | #include "wavpack.h" | ||
16 | |||
17 | #include <string.h> | ||
18 | |||
19 | // This flag provides faster encoding speed at the expense of more code. The | ||
20 | // improvement applies to 16-bit stereo lossless only. | ||
21 | |||
22 | //////////////////////////////// local tables /////////////////////////////// | ||
23 | |||
24 | // These two tables specify the characteristics of the decorrelation filters. | ||
25 | // Each term represents one layer of the sequential filter, where positive | ||
26 | // values indicate the relative sample involved from the same channel (1=prev), | ||
27 | // 17 & 18 are special functions using the previous 2 samples, and negative | ||
28 | // values indicate cross channel decorrelation (in stereo only). | ||
29 | |||
30 | static const signed char default_terms [] = { 18,18,2,3,-2,0 }; | ||
31 | static const signed char high_terms [] = { 18,18,2,3,-2,18,2,4,7,5,3,6,0 }; | ||
32 | static const signed char fast_terms [] = { 17,17,0 }; | ||
33 | |||
34 | ///////////////////////////// executable code //////////////////////////////// | ||
35 | |||
36 | // This function initializes everything required to pack WavPack bitstreams | ||
37 | // and must be called BEFORE any other function in this module. | ||
38 | |||
39 | void pack_init (WavpackContext *wpc) | ||
40 | { | ||
41 | WavpackStream *wps = &wpc->stream; | ||
42 | uint32_t flags = wps->wphdr.flags; | ||
43 | struct decorr_pass *dpp; | ||
44 | const signed char *term_string; | ||
45 | int ti; | ||
46 | |||
47 | wps->sample_index = 0; | ||
48 | CLEAR (wps->decorr_passes); | ||
49 | |||
50 | if (wpc->config.flags & CONFIG_HIGH_FLAG) | ||
51 | term_string = high_terms; | ||
52 | else if (wpc->config.flags & CONFIG_FAST_FLAG) | ||
53 | term_string = fast_terms; | ||
54 | else | ||
55 | term_string = default_terms; | ||
56 | |||
57 | for (dpp = wps->decorr_passes, ti = 0; term_string [ti]; ti++) | ||
58 | if (term_string [ti] >= 0 || (flags & CROSS_DECORR)) { | ||
59 | dpp->term = term_string [ti]; | ||
60 | dpp++->delta = 2; | ||
61 | } | ||
62 | else if (!(flags & MONO_FLAG)) { | ||
63 | dpp->term = -3; | ||
64 | dpp++->delta = 2; | ||
65 | } | ||
66 | |||
67 | wps->num_terms = dpp - wps->decorr_passes; | ||
68 | init_words (wps); | ||
69 | } | ||
70 | |||
71 | // Allocate room for and copy the decorrelation terms from the decorr_passes | ||
72 | // array into the specified metadata structure. Both the actual term id and | ||
73 | // the delta are packed into single characters. | ||
74 | |||
75 | static void write_decorr_terms (WavpackStream *wps, WavpackMetadata *wpmd) | ||
76 | { | ||
77 | int tcount = wps->num_terms; | ||
78 | struct decorr_pass *dpp; | ||
79 | char *byteptr; | ||
80 | |||
81 | byteptr = wpmd->data = wpmd->temp_data; | ||
82 | wpmd->id = ID_DECORR_TERMS; | ||
83 | |||
84 | for (dpp = wps->decorr_passes; tcount--; ++dpp) | ||
85 | *byteptr++ = ((dpp->term + 5) & 0x1f) | ((dpp->delta << 5) & 0xe0); | ||
86 | |||
87 | wpmd->byte_length = byteptr - (char *) wpmd->data; | ||
88 | } | ||
89 | |||
90 | // Allocate room for and copy the decorrelation term weights from the | ||
91 | // decorr_passes array into the specified metadata structure. The weights | ||
92 | // range +/-1024, but are rounded and truncated to fit in signed chars for | ||
93 | // metadata storage. Weights are separate for the two channels | ||
94 | |||
95 | static void write_decorr_weights (WavpackStream *wps, WavpackMetadata *wpmd) | ||
96 | { | ||
97 | int tcount = wps->num_terms; | ||
98 | struct decorr_pass *dpp; | ||
99 | signed char *byteptr; | ||
100 | |||
101 | byteptr = wpmd->data = wpmd->temp_data; | ||
102 | wpmd->id = ID_DECORR_WEIGHTS; | ||
103 | |||
104 | for (dpp = wps->decorr_passes; tcount--; ++dpp) { | ||
105 | dpp->weight_A = restore_weight (*byteptr++ = store_weight (dpp->weight_A)); | ||
106 | |||
107 | if (!(wps->wphdr.flags & MONO_FLAG)) | ||
108 | dpp->weight_B = restore_weight (*byteptr++ = store_weight (dpp->weight_B)); | ||
109 | } | ||
110 | |||
111 | wpmd->byte_length = byteptr - (signed char *) wpmd->data; | ||
112 | } | ||
113 | |||
114 | // Allocate room for and copy the decorrelation samples from the decorr_passes | ||
115 | // array into the specified metadata structure. The samples are signed 32-bit | ||
116 | // values, but are converted to signed log2 values for storage in metadata. | ||
117 | // Values are stored for both channels and are specified from the first term | ||
118 | // with unspecified samples set to zero. The number of samples stored varies | ||
119 | // with the actual term value, so those must obviously be specified before | ||
120 | // these in the metadata list. Any number of terms can have their samples | ||
121 | // specified from no terms to all the terms, however I have found that | ||
122 | // sending more than the first term's samples is a waste. The "wcount" | ||
123 | // variable can be set to the number of terms to have their samples stored. | ||
124 | |||
125 | static void write_decorr_samples (WavpackStream *wps, WavpackMetadata *wpmd) | ||
126 | { | ||
127 | int tcount = wps->num_terms, wcount = 1, temp; | ||
128 | struct decorr_pass *dpp; | ||
129 | uchar *byteptr; | ||
130 | |||
131 | byteptr = wpmd->data = wpmd->temp_data; | ||
132 | wpmd->id = ID_DECORR_SAMPLES; | ||
133 | |||
134 | for (dpp = wps->decorr_passes; tcount--; ++dpp) | ||
135 | if (wcount) { | ||
136 | if (dpp->term > MAX_TERM) { | ||
137 | dpp->samples_A [0] = exp2s (temp = log2s (dpp->samples_A [0])); | ||
138 | *byteptr++ = temp; | ||
139 | *byteptr++ = temp >> 8; | ||
140 | dpp->samples_A [1] = exp2s (temp = log2s (dpp->samples_A [1])); | ||
141 | *byteptr++ = temp; | ||
142 | *byteptr++ = temp >> 8; | ||
143 | |||
144 | if (!(wps->wphdr.flags & MONO_FLAG)) { | ||
145 | dpp->samples_B [0] = exp2s (temp = log2s (dpp->samples_B [0])); | ||
146 | *byteptr++ = temp; | ||
147 | *byteptr++ = temp >> 8; | ||
148 | dpp->samples_B [1] = exp2s (temp = log2s (dpp->samples_B [1])); | ||
149 | *byteptr++ = temp; | ||
150 | *byteptr++ = temp >> 8; | ||
151 | } | ||
152 | } | ||
153 | else if (dpp->term < 0) { | ||
154 | dpp->samples_A [0] = exp2s (temp = log2s (dpp->samples_A [0])); | ||
155 | *byteptr++ = temp; | ||
156 | *byteptr++ = temp >> 8; | ||
157 | dpp->samples_B [0] = exp2s (temp = log2s (dpp->samples_B [0])); | ||
158 | *byteptr++ = temp; | ||
159 | *byteptr++ = temp >> 8; | ||
160 | } | ||
161 | else { | ||
162 | int m = 0, cnt = dpp->term; | ||
163 | |||
164 | while (cnt--) { | ||
165 | dpp->samples_A [m] = exp2s (temp = log2s (dpp->samples_A [m])); | ||
166 | *byteptr++ = temp; | ||
167 | *byteptr++ = temp >> 8; | ||
168 | |||
169 | if (!(wps->wphdr.flags & MONO_FLAG)) { | ||
170 | dpp->samples_B [m] = exp2s (temp = log2s (dpp->samples_B [m])); | ||
171 | *byteptr++ = temp; | ||
172 | *byteptr++ = temp >> 8; | ||
173 | } | ||
174 | |||
175 | m++; | ||
176 | } | ||
177 | } | ||
178 | |||
179 | wcount--; | ||
180 | } | ||
181 | else { | ||
182 | CLEAR (dpp->samples_A); | ||
183 | CLEAR (dpp->samples_B); | ||
184 | } | ||
185 | |||
186 | wpmd->byte_length = byteptr - (uchar *) wpmd->data; | ||
187 | } | ||
188 | |||
189 | // Allocate room for and copy the configuration information into the specified | ||
190 | // metadata structure. Currently, we just store the upper 3 bytes of | ||
191 | // config.flags and only in the first block of audio data. Note that this is | ||
192 | // for informational purposes not required for playback or decoding (like | ||
193 | // whether high or fast mode was specified). | ||
194 | |||
195 | static void write_config_info (WavpackContext *wpc, WavpackMetadata *wpmd) | ||
196 | { | ||
197 | char *byteptr; | ||
198 | |||
199 | byteptr = wpmd->data = wpmd->temp_data; | ||
200 | wpmd->id = ID_CONFIG_BLOCK; | ||
201 | *byteptr++ = (char) (wpc->config.flags >> 8); | ||
202 | *byteptr++ = (char) (wpc->config.flags >> 16); | ||
203 | *byteptr++ = (char) (wpc->config.flags >> 24); | ||
204 | wpmd->byte_length = byteptr - (char *) wpmd->data; | ||
205 | } | ||
206 | |||
207 | // Pack an entire block of samples (either mono or stereo) into a completed | ||
208 | // WavPack block. It is assumed that there is sufficient space for the | ||
209 | // completed block at "wps->blockbuff" and that "wps->blockend" points to the | ||
210 | // end of the available space. A return value of FALSE indicates an error. | ||
211 | // Any unsent metadata is transmitted first, then required metadata for this | ||
212 | // block is sent, and finally the compressed integer data is sent. If a "wpx" | ||
213 | // stream is required for floating point data or large integer data, then this | ||
214 | // must be handled outside this function. To find out how much data was written | ||
215 | // the caller must look at the ckSize field of the written WavpackHeader, NOT | ||
216 | // the one in the WavpackStream. | ||
217 | |||
218 | int pack_start_block (WavpackContext *wpc) | ||
219 | { | ||
220 | WavpackStream *wps = &wpc->stream; | ||
221 | WavpackMetadata wpmd; | ||
222 | |||
223 | memcpy (wps->blockbuff, &wps->wphdr, sizeof (WavpackHeader)); | ||
224 | |||
225 | ((WavpackHeader *) wps->blockbuff)->ckSize = sizeof (WavpackHeader) - 8; | ||
226 | ((WavpackHeader *) wps->blockbuff)->block_index = wps->sample_index; | ||
227 | ((WavpackHeader *) wps->blockbuff)->block_samples = 0; | ||
228 | ((WavpackHeader *) wps->blockbuff)->crc = 0xffffffff; | ||
229 | |||
230 | if (wpc->wrapper_bytes) { | ||
231 | wpmd.id = ID_RIFF_HEADER; | ||
232 | wpmd.byte_length = wpc->wrapper_bytes; | ||
233 | wpmd.data = wpc->wrapper_data; | ||
234 | copy_metadata (&wpmd, wps->blockbuff, wps->blockend); | ||
235 | free_metadata (&wpmd); | ||
236 | wpc->wrapper_data = NULL; | ||
237 | wpc->wrapper_bytes = 0; | ||
238 | } | ||
239 | |||
240 | write_decorr_terms (wps, &wpmd); | ||
241 | copy_metadata (&wpmd, wps->blockbuff, wps->blockend); | ||
242 | free_metadata (&wpmd); | ||
243 | |||
244 | write_decorr_weights (wps, &wpmd); | ||
245 | copy_metadata (&wpmd, wps->blockbuff, wps->blockend); | ||
246 | free_metadata (&wpmd); | ||
247 | |||
248 | write_decorr_samples (wps, &wpmd); | ||
249 | copy_metadata (&wpmd, wps->blockbuff, wps->blockend); | ||
250 | free_metadata (&wpmd); | ||
251 | |||
252 | write_entropy_vars (wps, &wpmd); | ||
253 | copy_metadata (&wpmd, wps->blockbuff, wps->blockend); | ||
254 | free_metadata (&wpmd); | ||
255 | |||
256 | if ((wps->wphdr.flags & INITIAL_BLOCK) && !wps->sample_index) { | ||
257 | write_config_info (wpc, &wpmd); | ||
258 | copy_metadata (&wpmd, wps->blockbuff, wps->blockend); | ||
259 | free_metadata (&wpmd); | ||
260 | } | ||
261 | |||
262 | bs_open_write (&wps->wvbits, wps->blockbuff + ((WavpackHeader *) wps->blockbuff)->ckSize + 12, wps->blockend); | ||
263 | |||
264 | return TRUE; | ||
265 | } | ||
266 | |||
267 | static void decorr_stereo_pass (struct decorr_pass *dpp, int32_t *bptr, int32_t *eptr, int m); | ||
268 | static void decorr_stereo_pass_18 (struct decorr_pass *dpp, int32_t *bptr, int32_t *eptr); | ||
269 | static void decorr_stereo_pass_17 (struct decorr_pass *dpp, int32_t *bptr, int32_t *eptr); | ||
270 | static void decorr_stereo_pass_m2 (struct decorr_pass *dpp, int32_t *bptr, int32_t *eptr); | ||
271 | |||
272 | int pack_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample_count) | ||
273 | { | ||
274 | WavpackStream *wps = &wpc->stream; | ||
275 | uint32_t flags = wps->wphdr.flags; | ||
276 | struct decorr_pass *dpp; | ||
277 | int32_t *bptr, *eptr; | ||
278 | int tcount, m; | ||
279 | uint32_t crc; | ||
280 | |||
281 | if (!sample_count) | ||
282 | return TRUE; | ||
283 | |||
284 | eptr = buffer + sample_count * ((flags & MONO_FLAG) ? 1 : 2); | ||
285 | m = ((WavpackHeader *) wps->blockbuff)->block_samples & (MAX_TERM - 1); | ||
286 | crc = ((WavpackHeader *) wps->blockbuff)->crc; | ||
287 | |||
288 | /////////////////////// handle lossless mono mode ///////////////////////// | ||
289 | |||
290 | if (!(flags & HYBRID_FLAG) && (flags & MONO_FLAG)) | ||
291 | for (bptr = buffer; bptr < eptr;) { | ||
292 | int32_t code; | ||
293 | |||
294 | crc = crc * 3 + (code = *bptr); | ||
295 | |||
296 | for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) { | ||
297 | int32_t sam; | ||
298 | |||
299 | if (dpp->term > MAX_TERM) { | ||
300 | if (dpp->term & 1) | ||
301 | sam = 2 * dpp->samples_A [0] - dpp->samples_A [1]; | ||
302 | else | ||
303 | sam = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1; | ||
304 | |||
305 | dpp->samples_A [1] = dpp->samples_A [0]; | ||
306 | dpp->samples_A [0] = code; | ||
307 | } | ||
308 | else { | ||
309 | sam = dpp->samples_A [m]; | ||
310 | dpp->samples_A [(m + dpp->term) & (MAX_TERM - 1)] = code; | ||
311 | } | ||
312 | |||
313 | code -= apply_weight_i (dpp->weight_A, sam); | ||
314 | update_weight (dpp->weight_A, 2, sam, code); | ||
315 | } | ||
316 | |||
317 | m = (m + 1) & (MAX_TERM - 1); | ||
318 | *bptr++ = code; | ||
319 | } | ||
320 | |||
321 | //////////////////// handle the lossless stereo mode ////////////////////// | ||
322 | |||
323 | else if (!(flags & HYBRID_FLAG) && !(flags & MONO_FLAG)) { | ||
324 | if (flags & JOINT_STEREO) | ||
325 | for (bptr = buffer; bptr < eptr; bptr += 2) { | ||
326 | crc = crc * 9 + (bptr [0] * 3) + bptr [1]; | ||
327 | bptr [1] += ((bptr [0] -= bptr [1]) >> 1); | ||
328 | } | ||
329 | else | ||
330 | for (bptr = buffer; bptr < eptr; bptr += 2) | ||
331 | crc = crc * 9 + (bptr [0] * 3) + bptr [1]; | ||
332 | |||
333 | for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount-- ; dpp++) { | ||
334 | if (dpp->term == 17) | ||
335 | decorr_stereo_pass_17 (dpp, buffer, eptr); | ||
336 | else if (dpp->term == 18) | ||
337 | decorr_stereo_pass_18 (dpp, buffer, eptr); | ||
338 | else if (dpp->term >= 1 && dpp->term <= 7) | ||
339 | decorr_stereo_pass (dpp, buffer, eptr, m); | ||
340 | else if (dpp->term == -2) | ||
341 | decorr_stereo_pass_m2 (dpp, buffer, eptr); | ||
342 | } | ||
343 | } | ||
344 | |||
345 | send_words (buffer, sample_count, flags, &wps->w, &wps->wvbits); | ||
346 | ((WavpackHeader *) wps->blockbuff)->crc = crc; | ||
347 | ((WavpackHeader *) wps->blockbuff)->block_samples += sample_count; | ||
348 | wps->sample_index += sample_count; | ||
349 | |||
350 | return TRUE; | ||
351 | } | ||
352 | |||
353 | static void decorr_stereo_pass (struct decorr_pass *dpp, int32_t *bptr, int32_t *eptr, int m) | ||
354 | { | ||
355 | int k = (m + dpp->term) & (MAX_TERM - 1); | ||
356 | int32_t sam; | ||
357 | |||
358 | while (bptr < eptr) { | ||
359 | dpp->samples_A [k] = bptr [0]; | ||
360 | bptr [0] -= apply_weight_i (dpp->weight_A, (sam = dpp->samples_A [m])); | ||
361 | update_weight (dpp->weight_A, 2, sam, bptr [0]); | ||
362 | bptr++; | ||
363 | dpp->samples_B [k] = bptr [0]; | ||
364 | bptr [0] -= apply_weight_i (dpp->weight_B, (sam = dpp->samples_B [m])); | ||
365 | update_weight (dpp->weight_B, 2, sam, bptr [0]); | ||
366 | bptr++; | ||
367 | m = (m + 1) & (MAX_TERM - 1); | ||
368 | k = (k + 1) & (MAX_TERM - 1); | ||
369 | } | ||
370 | } | ||
371 | |||
372 | static void decorr_stereo_pass_18 (struct decorr_pass *dpp, int32_t *bptr, int32_t *eptr) | ||
373 | { | ||
374 | int32_t sam; | ||
375 | |||
376 | while (bptr < eptr) { | ||
377 | sam = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1; | ||
378 | dpp->samples_A [1] = dpp->samples_A [0]; | ||
379 | dpp->samples_A [0] = bptr [0]; | ||
380 | bptr [0] -= apply_weight_i (dpp->weight_A, sam); | ||
381 | update_weight (dpp->weight_A, 2, sam, bptr [0]); | ||
382 | bptr++; | ||
383 | sam = (3 * dpp->samples_B [0] - dpp->samples_B [1]) >> 1; | ||
384 | dpp->samples_B [1] = dpp->samples_B [0]; | ||
385 | dpp->samples_B [0] = bptr [0]; | ||
386 | bptr [0] -= apply_weight_i (dpp->weight_B, sam); | ||
387 | update_weight (dpp->weight_B, 2, sam, bptr [0]); | ||
388 | bptr++; | ||
389 | } | ||
390 | } | ||
391 | |||
392 | static void decorr_stereo_pass_m2 (struct decorr_pass *dpp, int32_t *bptr, int32_t *eptr) | ||
393 | { | ||
394 | int32_t sam_A, sam_B; | ||
395 | |||
396 | for (; bptr < eptr; bptr += 2) { | ||
397 | sam_A = bptr [1]; | ||
398 | sam_B = dpp->samples_B [0]; | ||
399 | dpp->samples_B [0] = bptr [0]; | ||
400 | bptr [0] -= apply_weight_i (dpp->weight_A, sam_A); | ||
401 | update_weight_clip (dpp->weight_A, 2, sam_A, bptr [0]); | ||
402 | bptr [1] -= apply_weight_i (dpp->weight_B, sam_B); | ||
403 | update_weight_clip (dpp->weight_B, 2, sam_B, bptr [1]); | ||
404 | } | ||
405 | } | ||
406 | |||
407 | static void decorr_stereo_pass_17 (struct decorr_pass *dpp, int32_t *bptr, int32_t *eptr) | ||
408 | { | ||
409 | int32_t sam; | ||
410 | |||
411 | while (bptr < eptr) { | ||
412 | sam = 2 * dpp->samples_A [0] - dpp->samples_A [1]; | ||
413 | dpp->samples_A [1] = dpp->samples_A [0]; | ||
414 | dpp->samples_A [0] = bptr [0]; | ||
415 | bptr [0] -= apply_weight_i (dpp->weight_A, sam); | ||
416 | update_weight (dpp->weight_A, 2, sam, bptr [0]); | ||
417 | bptr++; | ||
418 | sam = 2 * dpp->samples_B [0] - dpp->samples_B [1]; | ||
419 | dpp->samples_B [1] = dpp->samples_B [0]; | ||
420 | dpp->samples_B [0] = bptr [0]; | ||
421 | bptr [0] -= apply_weight_i (dpp->weight_B, sam); | ||
422 | update_weight (dpp->weight_B, 2, sam, bptr [0]); | ||
423 | bptr++; | ||
424 | } | ||
425 | } | ||
426 | |||
427 | int pack_finish_block (WavpackContext *wpc) | ||
428 | { | ||
429 | WavpackStream *wps = &wpc->stream; | ||
430 | struct decorr_pass *dpp; | ||
431 | uint32_t data_count; | ||
432 | int tcount, m; | ||
433 | |||
434 | m = ((WavpackHeader *) wps->blockbuff)->block_samples & (MAX_TERM - 1); | ||
435 | |||
436 | if (m) | ||
437 | for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) | ||
438 | if (dpp->term > 0 && dpp->term <= MAX_TERM) { | ||
439 | int32_t temp_A [MAX_TERM], temp_B [MAX_TERM]; | ||
440 | int k; | ||
441 | |||
442 | memcpy (temp_A, dpp->samples_A, sizeof (dpp->samples_A)); | ||
443 | memcpy (temp_B, dpp->samples_B, sizeof (dpp->samples_B)); | ||
444 | |||
445 | for (k = 0; k < MAX_TERM; k++) { | ||
446 | dpp->samples_A [k] = temp_A [m]; | ||
447 | dpp->samples_B [k] = temp_B [m]; | ||
448 | m = (m + 1) & (MAX_TERM - 1); | ||
449 | } | ||
450 | } | ||
451 | |||
452 | flush_word (&wps->w, &wps->wvbits); | ||
453 | data_count = bs_close_write (&wps->wvbits); | ||
454 | |||
455 | if (data_count) { | ||
456 | if (data_count != (uint32_t) -1) { | ||
457 | uchar *cptr = wps->blockbuff + ((WavpackHeader *) wps->blockbuff)->ckSize + 8; | ||
458 | |||
459 | *cptr++ = ID_WV_BITSTREAM | ID_LARGE; | ||
460 | *cptr++ = data_count >> 1; | ||
461 | *cptr++ = data_count >> 9; | ||
462 | *cptr++ = data_count >> 17; | ||
463 | ((WavpackHeader *) wps->blockbuff)->ckSize += data_count + 4; | ||
464 | } | ||
465 | else | ||
466 | return FALSE; | ||
467 | } | ||
468 | |||
469 | return TRUE; | ||
470 | } | ||
diff --git a/lib/rbcodec/codecs/libwavpack/unpack.c b/lib/rbcodec/codecs/libwavpack/unpack.c new file mode 100644 index 0000000000..69252f24ad --- /dev/null +++ b/lib/rbcodec/codecs/libwavpack/unpack.c | |||
@@ -0,0 +1,780 @@ | |||
1 | //////////////////////////////////////////////////////////////////////////// | ||
2 | // **** WAVPACK **** // | ||
3 | // Hybrid Lossless Wavefile Compressor // | ||
4 | // Copyright (c) 1998 - 2004 Conifer Software. // | ||
5 | // All Rights Reserved. // | ||
6 | // Distributed under the BSD Software License (see license.txt) // | ||
7 | //////////////////////////////////////////////////////////////////////////// | ||
8 | |||
9 | // unpack.c | ||
10 | |||
11 | // This module actually handles the decompression of the audio data, except | ||
12 | // for the entropy decoding which is handled by the words.c module. For | ||
13 | // maximum efficiency, the conversion is isolated to tight loops that handle | ||
14 | // an entire buffer. | ||
15 | |||
16 | #include "wavpack.h" | ||
17 | |||
18 | #include <stdlib.h> | ||
19 | #include <string.h> | ||
20 | |||
21 | static void strcpy_loc (char *dst, char *src) { while ((*dst++ = *src++) != 0); } | ||
22 | |||
23 | #define LOSSY_MUTE | ||
24 | |||
25 | ///////////////////////////// executable code //////////////////////////////// | ||
26 | |||
27 | // This function initializes everything required to unpack a WavPack block | ||
28 | // and must be called before unpack_samples() is called to obtain audio data. | ||
29 | // It is assumed that the WavpackHeader has been read into the wps->wphdr | ||
30 | // (in the current WavpackStream). This is where all the metadata blocks are | ||
31 | // scanned up to the one containing the audio bitstream. | ||
32 | |||
33 | int unpack_init (WavpackContext *wpc) | ||
34 | { | ||
35 | WavpackStream *wps = &wpc->stream; | ||
36 | WavpackMetadata wpmd; | ||
37 | |||
38 | if (wps->wphdr.block_samples && wps->wphdr.block_index != (uint32_t) -1) | ||
39 | wps->sample_index = wps->wphdr.block_index; | ||
40 | |||
41 | wps->mute_error = FALSE; | ||
42 | wps->crc = 0xffffffff; | ||
43 | CLEAR (wps->wvbits); | ||
44 | CLEAR (wps->decorr_passes); | ||
45 | CLEAR (wps->w); | ||
46 | |||
47 | while (read_metadata_buff (wpc, &wpmd)) { | ||
48 | if (!process_metadata (wpc, &wpmd)) { | ||
49 | strcpy_loc (wpc->error_message, "invalid metadata!"); | ||
50 | return FALSE; | ||
51 | } | ||
52 | |||
53 | if (wpmd.id == ID_WV_BITSTREAM) | ||
54 | break; | ||
55 | } | ||
56 | |||
57 | if (wps->wphdr.block_samples && !bs_is_open (&wps->wvbits)) { | ||
58 | strcpy_loc (wpc->error_message, "invalid WavPack file!"); | ||
59 | return FALSE; | ||
60 | } | ||
61 | |||
62 | if (wps->wphdr.block_samples) { | ||
63 | if ((wps->wphdr.flags & INT32_DATA) && wps->int32_sent_bits) | ||
64 | wpc->lossy_blocks = TRUE; | ||
65 | |||
66 | if ((wps->wphdr.flags & FLOAT_DATA) && | ||
67 | wps->float_flags & (FLOAT_EXCEPTIONS | FLOAT_ZEROS_SENT | FLOAT_SHIFT_SENT | FLOAT_SHIFT_SAME)) | ||
68 | wpc->lossy_blocks = TRUE; | ||
69 | } | ||
70 | |||
71 | return TRUE; | ||
72 | } | ||
73 | |||
74 | // This function initialzes the main bitstream for audio samples, which must | ||
75 | // be in the "wv" file. | ||
76 | |||
77 | int init_wv_bitstream (WavpackContext *wpc, WavpackMetadata *wpmd) | ||
78 | { | ||
79 | WavpackStream *wps = &wpc->stream; | ||
80 | |||
81 | if (wpmd->data) | ||
82 | bs_open_read (&wps->wvbits, wpmd->data, (unsigned char *) wpmd->data + wpmd->byte_length, NULL, 0); | ||
83 | else if (wpmd->byte_length) | ||
84 | bs_open_read (&wps->wvbits, wpc->read_buffer, wpc->read_buffer + sizeof (wpc->read_buffer), | ||
85 | wpc->infile, wpmd->byte_length + (wpmd->byte_length & 1)); | ||
86 | |||
87 | return TRUE; | ||
88 | } | ||
89 | |||
90 | // Read decorrelation terms from specified metadata block into the | ||
91 | // decorr_passes array. The terms range from -3 to 8, plus 17 & 18; | ||
92 | // other values are reserved and generate errors for now. The delta | ||
93 | // ranges from 0 to 7 with all values valid. Note that the terms are | ||
94 | // stored in the opposite order in the decorr_passes array compared | ||
95 | // to packing. | ||
96 | |||
97 | int read_decorr_terms (WavpackStream *wps, WavpackMetadata *wpmd) | ||
98 | { | ||
99 | int termcnt = wpmd->byte_length; | ||
100 | uchar *byteptr = wpmd->data; | ||
101 | struct decorr_pass *dpp; | ||
102 | |||
103 | if (termcnt > MAX_NTERMS) | ||
104 | return FALSE; | ||
105 | |||
106 | wps->num_terms = termcnt; | ||
107 | |||
108 | for (dpp = wps->decorr_passes + termcnt - 1; termcnt--; dpp--) { | ||
109 | dpp->term = (int)(*byteptr & 0x1f) - 5; | ||
110 | dpp->delta = (*byteptr++ >> 5) & 0x7; | ||
111 | |||
112 | if (!dpp->term || dpp->term < -3 || (dpp->term > MAX_TERM && dpp->term < 17) || dpp->term > 18) | ||
113 | return FALSE; | ||
114 | } | ||
115 | |||
116 | return TRUE; | ||
117 | } | ||
118 | |||
119 | // Read decorrelation weights from specified metadata block into the | ||
120 | // decorr_passes array. The weights range +/-1024, but are rounded and | ||
121 | // truncated to fit in signed chars for metadata storage. Weights are | ||
122 | // separate for the two channels and are specified from the "last" term | ||
123 | // (first during encode). Unspecified weights are set to zero. | ||
124 | |||
125 | int read_decorr_weights (WavpackStream *wps, WavpackMetadata *wpmd) | ||
126 | { | ||
127 | int termcnt = wpmd->byte_length, tcount; | ||
128 | signed char *byteptr = wpmd->data; | ||
129 | struct decorr_pass *dpp; | ||
130 | |||
131 | if (!(wps->wphdr.flags & MONO_DATA)) | ||
132 | termcnt /= 2; | ||
133 | |||
134 | if (termcnt > wps->num_terms) | ||
135 | return FALSE; | ||
136 | |||
137 | for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) | ||
138 | dpp->weight_A = dpp->weight_B = 0; | ||
139 | |||
140 | while (--dpp >= wps->decorr_passes && termcnt--) { | ||
141 | dpp->weight_A = restore_weight (*byteptr++); | ||
142 | |||
143 | if (!(wps->wphdr.flags & MONO_DATA)) | ||
144 | dpp->weight_B = restore_weight (*byteptr++); | ||
145 | } | ||
146 | |||
147 | return TRUE; | ||
148 | } | ||
149 | |||
150 | // Read decorrelation samples from specified metadata block into the | ||
151 | // decorr_passes array. The samples are signed 32-bit values, but are | ||
152 | // converted to signed log2 values for storage in metadata. Values are | ||
153 | // stored for both channels and are specified from the "last" term | ||
154 | // (first during encode) with unspecified samples set to zero. The | ||
155 | // number of samples stored varies with the actual term value, so | ||
156 | // those must obviously come first in the metadata. | ||
157 | |||
158 | int read_decorr_samples (WavpackStream *wps, WavpackMetadata *wpmd) | ||
159 | { | ||
160 | uchar *byteptr = wpmd->data; | ||
161 | uchar *endptr = byteptr + wpmd->byte_length; | ||
162 | struct decorr_pass *dpp; | ||
163 | int tcount; | ||
164 | |||
165 | for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) { | ||
166 | CLEAR (dpp->samples_A); | ||
167 | CLEAR (dpp->samples_B); | ||
168 | } | ||
169 | |||
170 | if (wps->wphdr.version == 0x402 && (wps->wphdr.flags & HYBRID_FLAG)) { | ||
171 | byteptr += 2; | ||
172 | |||
173 | if (!(wps->wphdr.flags & MONO_DATA)) | ||
174 | byteptr += 2; | ||
175 | } | ||
176 | |||
177 | while (dpp-- > wps->decorr_passes && byteptr < endptr) | ||
178 | if (dpp->term > MAX_TERM) { | ||
179 | dpp->samples_A [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8))); | ||
180 | dpp->samples_A [1] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8))); | ||
181 | byteptr += 4; | ||
182 | |||
183 | if (!(wps->wphdr.flags & MONO_DATA)) { | ||
184 | dpp->samples_B [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8))); | ||
185 | dpp->samples_B [1] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8))); | ||
186 | byteptr += 4; | ||
187 | } | ||
188 | } | ||
189 | else if (dpp->term < 0) { | ||
190 | dpp->samples_A [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8))); | ||
191 | dpp->samples_B [0] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8))); | ||
192 | byteptr += 4; | ||
193 | } | ||
194 | else { | ||
195 | int m = 0, cnt = dpp->term; | ||
196 | |||
197 | while (cnt--) { | ||
198 | dpp->samples_A [m] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8))); | ||
199 | byteptr += 2; | ||
200 | |||
201 | if (!(wps->wphdr.flags & MONO_DATA)) { | ||
202 | dpp->samples_B [m] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8))); | ||
203 | byteptr += 2; | ||
204 | } | ||
205 | |||
206 | m++; | ||
207 | } | ||
208 | } | ||
209 | |||
210 | return byteptr == endptr; | ||
211 | } | ||
212 | |||
213 | // Read the int32 data from the specified metadata into the specified stream. | ||
214 | // This data is used for integer data that has more than 24 bits of magnitude | ||
215 | // or, in some cases, used to eliminate redundant bits from any audio stream. | ||
216 | |||
217 | int read_int32_info (WavpackStream *wps, WavpackMetadata *wpmd) | ||
218 | { | ||
219 | int bytecnt = wpmd->byte_length; | ||
220 | char *byteptr = wpmd->data; | ||
221 | |||
222 | if (bytecnt != 4) | ||
223 | return FALSE; | ||
224 | |||
225 | wps->int32_sent_bits = *byteptr++; | ||
226 | wps->int32_zeros = *byteptr++; | ||
227 | wps->int32_ones = *byteptr++; | ||
228 | wps->int32_dups = *byteptr; | ||
229 | return TRUE; | ||
230 | } | ||
231 | |||
232 | // Read multichannel information from metadata. The first byte is the total | ||
233 | // number of channels and the following bytes represent the channel_mask | ||
234 | // as described for Microsoft WAVEFORMATEX. | ||
235 | |||
236 | int read_channel_info (WavpackContext *wpc, WavpackMetadata *wpmd) | ||
237 | { | ||
238 | int bytecnt = wpmd->byte_length, shift = 0; | ||
239 | char *byteptr = wpmd->data; | ||
240 | uint32_t mask = 0; | ||
241 | |||
242 | if (!bytecnt || bytecnt > 5) | ||
243 | return FALSE; | ||
244 | |||
245 | wpc->config.num_channels = *byteptr++; | ||
246 | |||
247 | while (--bytecnt) { | ||
248 | mask |= (uint32_t) *byteptr++ << shift; | ||
249 | shift += 8; | ||
250 | } | ||
251 | |||
252 | wpc->config.channel_mask = mask; | ||
253 | return TRUE; | ||
254 | } | ||
255 | |||
256 | // Read configuration information from metadata. | ||
257 | |||
258 | int read_config_info (WavpackContext *wpc, WavpackMetadata *wpmd) | ||
259 | { | ||
260 | int bytecnt = wpmd->byte_length; | ||
261 | uchar *byteptr = wpmd->data; | ||
262 | |||
263 | if (bytecnt >= 3) { | ||
264 | wpc->config.flags &= 0xff; | ||
265 | wpc->config.flags |= (int32_t) *byteptr++ << 8; | ||
266 | wpc->config.flags |= (int32_t) *byteptr++ << 16; | ||
267 | wpc->config.flags |= (int32_t) *byteptr << 24; | ||
268 | } | ||
269 | |||
270 | return TRUE; | ||
271 | } | ||
272 | |||
273 | // Read non-standard sampling rate from metadata. | ||
274 | |||
275 | int read_sample_rate (WavpackContext *wpc, WavpackMetadata *wpmd) | ||
276 | { | ||
277 | int bytecnt = wpmd->byte_length; | ||
278 | uchar *byteptr = wpmd->data; | ||
279 | |||
280 | if (bytecnt == 3) { | ||
281 | wpc->config.sample_rate = (int32_t) *byteptr++; | ||
282 | wpc->config.sample_rate |= (int32_t) *byteptr++ << 8; | ||
283 | wpc->config.sample_rate |= (int32_t) *byteptr++ << 16; | ||
284 | } | ||
285 | |||
286 | return TRUE; | ||
287 | } | ||
288 | |||
289 | // This monster actually unpacks the WavPack bitstream(s) into the specified | ||
290 | // buffer as 32-bit integers or floats (depending on orignal data). Lossy | ||
291 | // samples will be clipped to their original limits (i.e. 8-bit samples are | ||
292 | // clipped to -128/+127) but are still returned in int32_ts. It is up to the | ||
293 | // caller to potentially reformat this for the final output including any | ||
294 | // multichannel distribution, block alignment or endian compensation. The | ||
295 | // function unpack_init() must have been called and the entire WavPack block | ||
296 | // must still be visible (although wps->blockbuff will not be accessed again). | ||
297 | // For maximum clarity, the function is broken up into segments that handle | ||
298 | // various modes. This makes for a few extra infrequent flag checks, but | ||
299 | // makes the code easier to follow because the nesting does not become so | ||
300 | // deep. For maximum efficiency, the conversion is isolated to tight loops | ||
301 | // that handle an entire buffer. The function returns the total number of | ||
302 | // samples unpacked, which can be less than the number requested if an error | ||
303 | // occurs or the end of the block is reached. | ||
304 | |||
305 | #if defined(CPU_COLDFIRE) | ||
306 | extern void decorr_stereo_pass_cont_mcf5249 (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count); | ||
307 | #elif defined(CPU_ARM) | ||
308 | extern void decorr_stereo_pass_cont_arm (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count); | ||
309 | extern void decorr_stereo_pass_cont_arml (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count); | ||
310 | #else | ||
311 | static void decorr_stereo_pass_cont (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count); | ||
312 | #endif | ||
313 | |||
314 | static void decorr_mono_pass (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count); | ||
315 | static void decorr_stereo_pass (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count); | ||
316 | static void fixup_samples (WavpackStream *wps, int32_t *buffer, uint32_t sample_count); | ||
317 | |||
318 | int32_t unpack_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample_count) | ||
319 | { | ||
320 | WavpackStream *wps = &wpc->stream; | ||
321 | uint32_t flags = wps->wphdr.flags, crc = wps->crc, i; | ||
322 | int32_t mute_limit = (1L << ((flags & MAG_MASK) >> MAG_LSB)) + 2; | ||
323 | struct decorr_pass *dpp; | ||
324 | int32_t *bptr, *eptr; | ||
325 | int tcount; | ||
326 | |||
327 | if (wps->sample_index + sample_count > wps->wphdr.block_index + wps->wphdr.block_samples) | ||
328 | sample_count = wps->wphdr.block_index + wps->wphdr.block_samples - wps->sample_index; | ||
329 | |||
330 | if (wps->mute_error) { | ||
331 | memset (buffer, 0, sample_count * (flags & MONO_FLAG ? 4 : 8)); | ||
332 | wps->sample_index += sample_count; | ||
333 | return sample_count; | ||
334 | } | ||
335 | |||
336 | if (flags & HYBRID_FLAG) | ||
337 | mute_limit *= 2; | ||
338 | |||
339 | ///////////////////// handle version 4 mono data ///////////////////////// | ||
340 | |||
341 | if (flags & MONO_DATA) { | ||
342 | eptr = buffer + sample_count; | ||
343 | i = get_words (buffer, sample_count, flags, &wps->w, &wps->wvbits); | ||
344 | |||
345 | for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) | ||
346 | decorr_mono_pass (dpp, buffer, sample_count); | ||
347 | |||
348 | for (bptr = buffer; bptr < eptr; ++bptr) { | ||
349 | if (labs (bptr [0]) > mute_limit) { | ||
350 | i = bptr - buffer; | ||
351 | break; | ||
352 | } | ||
353 | |||
354 | crc = crc * 3 + bptr [0]; | ||
355 | } | ||
356 | } | ||
357 | |||
358 | //////////////////// handle version 4 stereo data //////////////////////// | ||
359 | |||
360 | else { | ||
361 | eptr = buffer + (sample_count * 2); | ||
362 | i = get_words (buffer, sample_count, flags, &wps->w, &wps->wvbits); | ||
363 | |||
364 | if (sample_count < 16) | ||
365 | for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) | ||
366 | decorr_stereo_pass (dpp, buffer, sample_count); | ||
367 | else | ||
368 | for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) { | ||
369 | decorr_stereo_pass (dpp, buffer, 8); | ||
370 | #if defined(CPU_COLDFIRE) | ||
371 | decorr_stereo_pass_cont_mcf5249 (dpp, buffer + 16, sample_count - 8); | ||
372 | #elif defined(CPU_ARM) | ||
373 | if (((flags & MAG_MASK) >> MAG_LSB) > 15) | ||
374 | decorr_stereo_pass_cont_arml (dpp, buffer + 16, sample_count - 8); | ||
375 | else | ||
376 | decorr_stereo_pass_cont_arm (dpp, buffer + 16, sample_count - 8); | ||
377 | #else | ||
378 | decorr_stereo_pass_cont (dpp, buffer + 16, sample_count - 8); | ||
379 | #endif | ||
380 | } | ||
381 | |||
382 | if (flags & JOINT_STEREO) | ||
383 | for (bptr = buffer; bptr < eptr; bptr += 2) { | ||
384 | bptr [0] += (bptr [1] -= (bptr [0] >> 1)); | ||
385 | |||
386 | if (labs (bptr [0]) > mute_limit || labs (bptr [1]) > mute_limit) { | ||
387 | i = (bptr - buffer) / 2; | ||
388 | break; | ||
389 | } | ||
390 | |||
391 | crc = (crc * 3 + bptr [0]) * 3 + bptr [1]; | ||
392 | } | ||
393 | else | ||
394 | for (bptr = buffer; bptr < eptr; bptr += 2) { | ||
395 | if (labs (bptr [0]) > mute_limit || labs (bptr [1]) > mute_limit) { | ||
396 | i = (bptr - buffer) / 2; | ||
397 | break; | ||
398 | } | ||
399 | |||
400 | crc = (crc * 3 + bptr [0]) * 3 + bptr [1]; | ||
401 | } | ||
402 | } | ||
403 | |||
404 | if (i != sample_count) { | ||
405 | memset (buffer, 0, sample_count * (flags & MONO_FLAG ? 4 : 8)); | ||
406 | wps->mute_error = TRUE; | ||
407 | i = sample_count; | ||
408 | } | ||
409 | |||
410 | fixup_samples (wps, buffer, i); | ||
411 | |||
412 | if (flags & FALSE_STEREO) { | ||
413 | int32_t *dptr = buffer + i * 2; | ||
414 | int32_t *sptr = buffer + i; | ||
415 | int32_t c = i; | ||
416 | |||
417 | while (c--) { | ||
418 | *--dptr = *--sptr; | ||
419 | *--dptr = *sptr; | ||
420 | } | ||
421 | } | ||
422 | |||
423 | wps->sample_index += i; | ||
424 | wps->crc = crc; | ||
425 | |||
426 | return i; | ||
427 | } | ||
428 | |||
429 | static void decorr_stereo_pass (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count) | ||
430 | { | ||
431 | int32_t delta = dpp->delta, weight_A = dpp->weight_A, weight_B = dpp->weight_B; | ||
432 | int32_t *bptr, *eptr = buffer + (sample_count * 2), sam_A, sam_B; | ||
433 | int m, k; | ||
434 | |||
435 | switch (dpp->term) { | ||
436 | |||
437 | case 17: | ||
438 | for (bptr = buffer; bptr < eptr; bptr += 2) { | ||
439 | sam_A = 2 * dpp->samples_A [0] - dpp->samples_A [1]; | ||
440 | dpp->samples_A [1] = dpp->samples_A [0]; | ||
441 | dpp->samples_A [0] = apply_weight (weight_A, sam_A) + bptr [0]; | ||
442 | update_weight (weight_A, delta, sam_A, bptr [0]); | ||
443 | bptr [0] = dpp->samples_A [0]; | ||
444 | |||
445 | sam_A = 2 * dpp->samples_B [0] - dpp->samples_B [1]; | ||
446 | dpp->samples_B [1] = dpp->samples_B [0]; | ||
447 | dpp->samples_B [0] = apply_weight (weight_B, sam_A) + bptr [1]; | ||
448 | update_weight (weight_B, delta, sam_A, bptr [1]); | ||
449 | bptr [1] = dpp->samples_B [0]; | ||
450 | } | ||
451 | |||
452 | break; | ||
453 | |||
454 | case 18: | ||
455 | for (bptr = buffer; bptr < eptr; bptr += 2) { | ||
456 | sam_A = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1; | ||
457 | dpp->samples_A [1] = dpp->samples_A [0]; | ||
458 | dpp->samples_A [0] = apply_weight (weight_A, sam_A) + bptr [0]; | ||
459 | update_weight (weight_A, delta, sam_A, bptr [0]); | ||
460 | bptr [0] = dpp->samples_A [0]; | ||
461 | |||
462 | sam_A = (3 * dpp->samples_B [0] - dpp->samples_B [1]) >> 1; | ||
463 | dpp->samples_B [1] = dpp->samples_B [0]; | ||
464 | dpp->samples_B [0] = apply_weight (weight_B, sam_A) + bptr [1]; | ||
465 | update_weight (weight_B, delta, sam_A, bptr [1]); | ||
466 | bptr [1] = dpp->samples_B [0]; | ||
467 | } | ||
468 | |||
469 | break; | ||
470 | |||
471 | default: | ||
472 | for (m = 0, k = dpp->term & (MAX_TERM - 1), bptr = buffer; bptr < eptr; bptr += 2) { | ||
473 | sam_A = dpp->samples_A [m]; | ||
474 | dpp->samples_A [k] = apply_weight (weight_A, sam_A) + bptr [0]; | ||
475 | update_weight (weight_A, delta, sam_A, bptr [0]); | ||
476 | bptr [0] = dpp->samples_A [k]; | ||
477 | |||
478 | sam_A = dpp->samples_B [m]; | ||
479 | dpp->samples_B [k] = apply_weight (weight_B, sam_A) + bptr [1]; | ||
480 | update_weight (weight_B, delta, sam_A, bptr [1]); | ||
481 | bptr [1] = dpp->samples_B [k]; | ||
482 | |||
483 | m = (m + 1) & (MAX_TERM - 1); | ||
484 | k = (k + 1) & (MAX_TERM - 1); | ||
485 | } | ||
486 | |||
487 | if (m) { | ||
488 | int32_t temp_samples [MAX_TERM]; | ||
489 | |||
490 | memcpy (temp_samples, dpp->samples_A, sizeof (dpp->samples_A)); | ||
491 | |||
492 | for (k = 0; k < MAX_TERM; k++, m++) | ||
493 | dpp->samples_A [k] = temp_samples [m & (MAX_TERM - 1)]; | ||
494 | |||
495 | memcpy (temp_samples, dpp->samples_B, sizeof (dpp->samples_B)); | ||
496 | |||
497 | for (k = 0; k < MAX_TERM; k++, m++) | ||
498 | dpp->samples_B [k] = temp_samples [m & (MAX_TERM - 1)]; | ||
499 | } | ||
500 | |||
501 | break; | ||
502 | |||
503 | case -1: | ||
504 | for (bptr = buffer; bptr < eptr; bptr += 2) { | ||
505 | sam_A = bptr [0] + apply_weight (weight_A, dpp->samples_A [0]); | ||
506 | update_weight_clip (weight_A, delta, dpp->samples_A [0], bptr [0]); | ||
507 | bptr [0] = sam_A; | ||
508 | dpp->samples_A [0] = bptr [1] + apply_weight (weight_B, sam_A); | ||
509 | update_weight_clip (weight_B, delta, sam_A, bptr [1]); | ||
510 | bptr [1] = dpp->samples_A [0]; | ||
511 | } | ||
512 | |||
513 | break; | ||
514 | |||
515 | case -2: | ||
516 | for (bptr = buffer; bptr < eptr; bptr += 2) { | ||
517 | sam_B = bptr [1] + apply_weight (weight_B, dpp->samples_B [0]); | ||
518 | update_weight_clip (weight_B, delta, dpp->samples_B [0], bptr [1]); | ||
519 | bptr [1] = sam_B; | ||
520 | dpp->samples_B [0] = bptr [0] + apply_weight (weight_A, sam_B); | ||
521 | update_weight_clip (weight_A, delta, sam_B, bptr [0]); | ||
522 | bptr [0] = dpp->samples_B [0]; | ||
523 | } | ||
524 | |||
525 | break; | ||
526 | |||
527 | case -3: | ||
528 | for (bptr = buffer; bptr < eptr; bptr += 2) { | ||
529 | sam_A = bptr [0] + apply_weight (weight_A, dpp->samples_A [0]); | ||
530 | update_weight_clip (weight_A, delta, dpp->samples_A [0], bptr [0]); | ||
531 | sam_B = bptr [1] + apply_weight (weight_B, dpp->samples_B [0]); | ||
532 | update_weight_clip (weight_B, delta, dpp->samples_B [0], bptr [1]); | ||
533 | bptr [0] = dpp->samples_B [0] = sam_A; | ||
534 | bptr [1] = dpp->samples_A [0] = sam_B; | ||
535 | } | ||
536 | |||
537 | break; | ||
538 | } | ||
539 | |||
540 | dpp->weight_A = weight_A; | ||
541 | dpp->weight_B = weight_B; | ||
542 | } | ||
543 | |||
544 | #if (!defined(CPU_COLDFIRE) && !defined(CPU_ARM)) | ||
545 | |||
546 | static void decorr_stereo_pass_cont (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count) | ||
547 | { | ||
548 | int32_t delta = dpp->delta, weight_A = dpp->weight_A, weight_B = dpp->weight_B; | ||
549 | int32_t *bptr, *tptr, *eptr = buffer + (sample_count * 2), sam_A, sam_B; | ||
550 | int k, i; | ||
551 | |||
552 | switch (dpp->term) { | ||
553 | |||
554 | case 17: | ||
555 | for (bptr = buffer; bptr < eptr; bptr += 2) { | ||
556 | sam_A = 2 * bptr [-2] - bptr [-4]; | ||
557 | bptr [0] = apply_weight (weight_A, sam_A) + (sam_B = bptr [0]); | ||
558 | update_weight (weight_A, delta, sam_A, sam_B); | ||
559 | |||
560 | sam_A = 2 * bptr [-1] - bptr [-3]; | ||
561 | bptr [1] = apply_weight (weight_B, sam_A) + (sam_B = bptr [1]); | ||
562 | update_weight (weight_B, delta, sam_A, sam_B); | ||
563 | } | ||
564 | |||
565 | dpp->samples_B [0] = bptr [-1]; | ||
566 | dpp->samples_A [0] = bptr [-2]; | ||
567 | dpp->samples_B [1] = bptr [-3]; | ||
568 | dpp->samples_A [1] = bptr [-4]; | ||
569 | break; | ||
570 | |||
571 | case 18: | ||
572 | for (bptr = buffer; bptr < eptr; bptr += 2) { | ||
573 | sam_A = (3 * bptr [-2] - bptr [-4]) >> 1; | ||
574 | bptr [0] = apply_weight (weight_A, sam_A) + (sam_B = bptr [0]); | ||
575 | update_weight (weight_A, delta, sam_A, sam_B); | ||
576 | |||
577 | sam_A = (3 * bptr [-1] - bptr [-3]) >> 1; | ||
578 | bptr [1] = apply_weight (weight_B, sam_A) + (sam_B = bptr [1]); | ||
579 | update_weight (weight_B, delta, sam_A, sam_B); | ||
580 | } | ||
581 | |||
582 | dpp->samples_B [0] = bptr [-1]; | ||
583 | dpp->samples_A [0] = bptr [-2]; | ||
584 | dpp->samples_B [1] = bptr [-3]; | ||
585 | dpp->samples_A [1] = bptr [-4]; | ||
586 | break; | ||
587 | |||
588 | default: | ||
589 | for (bptr = buffer, tptr = buffer - (dpp->term * 2); bptr < eptr; bptr += 2, tptr += 2) { | ||
590 | bptr [0] = apply_weight (weight_A, tptr [0]) + (sam_A = bptr [0]); | ||
591 | update_weight (weight_A, delta, tptr [0], sam_A); | ||
592 | |||
593 | bptr [1] = apply_weight (weight_B, tptr [1]) + (sam_A = bptr [1]); | ||
594 | update_weight (weight_B, delta, tptr [1], sam_A); | ||
595 | } | ||
596 | |||
597 | for (k = dpp->term - 1, i = 8; i--; k--) { | ||
598 | dpp->samples_B [k & (MAX_TERM - 1)] = *--bptr; | ||
599 | dpp->samples_A [k & (MAX_TERM - 1)] = *--bptr; | ||
600 | } | ||
601 | |||
602 | break; | ||
603 | |||
604 | case -1: | ||
605 | for (bptr = buffer; bptr < eptr; bptr += 2) { | ||
606 | bptr [0] = apply_weight (weight_A, bptr [-1]) + (sam_A = bptr [0]); | ||
607 | update_weight_clip (weight_A, delta, bptr [-1], sam_A); | ||
608 | bptr [1] = apply_weight (weight_B, bptr [0]) + (sam_A = bptr [1]); | ||
609 | update_weight_clip (weight_B, delta, bptr [0], sam_A); | ||
610 | } | ||
611 | |||
612 | dpp->samples_A [0] = bptr [-1]; | ||
613 | break; | ||
614 | |||
615 | case -2: | ||
616 | for (bptr = buffer; bptr < eptr; bptr += 2) { | ||
617 | bptr [1] = apply_weight (weight_B, bptr [-2]) + (sam_A = bptr [1]); | ||
618 | update_weight_clip (weight_B, delta, bptr [-2], sam_A); | ||
619 | bptr [0] = apply_weight (weight_A, bptr [1]) + (sam_A = bptr [0]); | ||
620 | update_weight_clip (weight_A, delta, bptr [1], sam_A); | ||
621 | } | ||
622 | |||
623 | dpp->samples_B [0] = bptr [-2]; | ||
624 | break; | ||
625 | |||
626 | case -3: | ||
627 | for (bptr = buffer; bptr < eptr; bptr += 2) { | ||
628 | bptr [0] = apply_weight (weight_A, bptr [-1]) + (sam_A = bptr [0]); | ||
629 | update_weight_clip (weight_A, delta, bptr [-1], sam_A); | ||
630 | bptr [1] = apply_weight (weight_B, bptr [-2]) + (sam_A = bptr [1]); | ||
631 | update_weight_clip (weight_B, delta, bptr [-2], sam_A); | ||
632 | } | ||
633 | |||
634 | dpp->samples_A [0] = bptr [-1]; | ||
635 | dpp->samples_B [0] = bptr [-2]; | ||
636 | break; | ||
637 | } | ||
638 | |||
639 | dpp->weight_A = weight_A; | ||
640 | dpp->weight_B = weight_B; | ||
641 | } | ||
642 | |||
643 | #endif | ||
644 | |||
645 | static void decorr_mono_pass (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count) | ||
646 | { | ||
647 | int32_t delta = dpp->delta, weight_A = dpp->weight_A; | ||
648 | int32_t *bptr, *eptr = buffer + sample_count, sam_A; | ||
649 | int m, k; | ||
650 | |||
651 | switch (dpp->term) { | ||
652 | |||
653 | case 17: | ||
654 | for (bptr = buffer; bptr < eptr; bptr++) { | ||
655 | sam_A = 2 * dpp->samples_A [0] - dpp->samples_A [1]; | ||
656 | dpp->samples_A [1] = dpp->samples_A [0]; | ||
657 | dpp->samples_A [0] = apply_weight (weight_A, sam_A) + bptr [0]; | ||
658 | update_weight (weight_A, delta, sam_A, bptr [0]); | ||
659 | bptr [0] = dpp->samples_A [0]; | ||
660 | } | ||
661 | |||
662 | break; | ||
663 | |||
664 | case 18: | ||
665 | for (bptr = buffer; bptr < eptr; bptr++) { | ||
666 | sam_A = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1; | ||
667 | dpp->samples_A [1] = dpp->samples_A [0]; | ||
668 | dpp->samples_A [0] = apply_weight (weight_A, sam_A) + bptr [0]; | ||
669 | update_weight (weight_A, delta, sam_A, bptr [0]); | ||
670 | bptr [0] = dpp->samples_A [0]; | ||
671 | } | ||
672 | |||
673 | break; | ||
674 | |||
675 | default: | ||
676 | for (m = 0, k = dpp->term & (MAX_TERM - 1), bptr = buffer; bptr < eptr; bptr++) { | ||
677 | sam_A = dpp->samples_A [m]; | ||
678 | dpp->samples_A [k] = apply_weight (weight_A, sam_A) + bptr [0]; | ||
679 | update_weight (weight_A, delta, sam_A, bptr [0]); | ||
680 | bptr [0] = dpp->samples_A [k]; | ||
681 | m = (m + 1) & (MAX_TERM - 1); | ||
682 | k = (k + 1) & (MAX_TERM - 1); | ||
683 | } | ||
684 | |||
685 | if (m) { | ||
686 | int32_t temp_samples [MAX_TERM]; | ||
687 | |||
688 | memcpy (temp_samples, dpp->samples_A, sizeof (dpp->samples_A)); | ||
689 | |||
690 | for (k = 0; k < MAX_TERM; k++, m++) | ||
691 | dpp->samples_A [k] = temp_samples [m & (MAX_TERM - 1)]; | ||
692 | } | ||
693 | |||
694 | break; | ||
695 | } | ||
696 | |||
697 | dpp->weight_A = weight_A; | ||
698 | } | ||
699 | |||
700 | |||
701 | // This is a helper function for unpack_samples() that applies several final | ||
702 | // operations. First, if the data is 32-bit float data, then that conversion | ||
703 | // is done in the float.c module (whether lossy or lossless) and we return. | ||
704 | // Otherwise, if the extended integer data applies, then that operation is | ||
705 | // executed first. If the unpacked data is lossy (and not corrected) then | ||
706 | // it is clipped and shifted in a single operation. Otherwise, if it's | ||
707 | // lossless then the last step is to apply the final shift (if any). | ||
708 | |||
709 | // This function has been modified for RockBox to return all integer samples | ||
710 | // as 28-bits, and clipping (for lossy mode) has been eliminated because this | ||
711 | // now happens in the dsp module. | ||
712 | |||
713 | static void fixup_samples (WavpackStream *wps, int32_t *buffer, uint32_t sample_count) | ||
714 | { | ||
715 | uint32_t flags = wps->wphdr.flags; | ||
716 | int shift = (flags & SHIFT_MASK) >> SHIFT_LSB; | ||
717 | |||
718 | shift += 21 - (flags & BYTES_STORED) * 8; // this provides RockBox with 28-bit (+sign) | ||
719 | |||
720 | if (flags & FLOAT_DATA) { | ||
721 | float_values (wps, buffer, (flags & MONO_DATA) ? sample_count : sample_count * 2); | ||
722 | return; | ||
723 | } | ||
724 | |||
725 | if (flags & INT32_DATA) { | ||
726 | uint32_t count = (flags & MONO_DATA) ? sample_count : sample_count * 2; | ||
727 | int sent_bits = wps->int32_sent_bits, zeros = wps->int32_zeros; | ||
728 | int ones = wps->int32_ones, dups = wps->int32_dups; | ||
729 | int32_t *dptr = buffer; | ||
730 | |||
731 | if (!(flags & HYBRID_FLAG) && !sent_bits && (zeros + ones + dups)) | ||
732 | while (count--) { | ||
733 | if (zeros) | ||
734 | *dptr <<= zeros; | ||
735 | else if (ones) | ||
736 | *dptr = ((*dptr + 1) << ones) - 1; | ||
737 | else if (dups) | ||
738 | *dptr = ((*dptr + (*dptr & 1)) << dups) - (*dptr & 1); | ||
739 | |||
740 | dptr++; | ||
741 | } | ||
742 | else | ||
743 | shift += zeros + sent_bits + ones + dups; | ||
744 | } | ||
745 | |||
746 | if (shift > 0) { | ||
747 | if (!(flags & MONO_DATA)) | ||
748 | sample_count *= 2; | ||
749 | |||
750 | while (sample_count--) | ||
751 | *buffer++ <<= shift; | ||
752 | } | ||
753 | else if (shift < 0) { | ||
754 | shift = -shift; | ||
755 | |||
756 | if (!(flags & MONO_DATA)) | ||
757 | sample_count *= 2; | ||
758 | |||
759 | while (sample_count--) | ||
760 | *buffer++ >>= shift; | ||
761 | } | ||
762 | } | ||
763 | |||
764 | // This function checks the crc value(s) for an unpacked block, returning the | ||
765 | // number of actual crc errors detected for the block. The block must be | ||
766 | // completely unpacked before this test is valid. For losslessly unpacked | ||
767 | // blocks of float or extended integer data the extended crc is also checked. | ||
768 | // Note that WavPack's crc is not a CCITT approved polynomial algorithm, but | ||
769 | // is a much simpler method that is virtually as robust for real world data. | ||
770 | |||
771 | int check_crc_error (WavpackContext *wpc) | ||
772 | { | ||
773 | WavpackStream *wps = &wpc->stream; | ||
774 | int result = 0; | ||
775 | |||
776 | if (wps->crc != wps->wphdr.crc) | ||
777 | ++result; | ||
778 | |||
779 | return result; | ||
780 | } | ||
diff --git a/lib/rbcodec/codecs/libwavpack/wavpack.h b/lib/rbcodec/codecs/libwavpack/wavpack.h new file mode 100644 index 0000000000..b15a176f33 --- /dev/null +++ b/lib/rbcodec/codecs/libwavpack/wavpack.h | |||
@@ -0,0 +1,447 @@ | |||
1 | //////////////////////////////////////////////////////////////////////////// | ||
2 | // **** WAVPACK **** // | ||
3 | // Hybrid Lossless Wavefile Compressor // | ||
4 | // Copyright (c) 1998 - 2004 Conifer Software. // | ||
5 | // All Rights Reserved. // | ||
6 | // Distributed under the BSD Software License (see license.txt) // | ||
7 | //////////////////////////////////////////////////////////////////////////// | ||
8 | |||
9 | // wavpack.h | ||
10 | #ifdef CODEC | ||
11 | #include "codeclib.h" | ||
12 | #endif | ||
13 | #include <inttypes.h> | ||
14 | |||
15 | // This header file contains all the definitions required by WavPack. | ||
16 | |||
17 | typedef unsigned char uchar; | ||
18 | typedef unsigned short ushort; | ||
19 | #if 0 // unused and causing compiler errrors | ||
20 | typedef unsigned int uint; | ||
21 | #endif | ||
22 | |||
23 | #include <stdio.h> | ||
24 | |||
25 | #define FALSE 0 | ||
26 | #define TRUE 1 | ||
27 | |||
28 | ////////////////////////////// WavPack Header ///////////////////////////////// | ||
29 | |||
30 | // Note that this is the ONLY structure that is written to (or read from) | ||
31 | // WavPack 4.0 files, and is the preamble to every block in both the .wv | ||
32 | // and .wvc files. | ||
33 | |||
34 | typedef struct { | ||
35 | char ckID [4]; | ||
36 | uint32_t ckSize; | ||
37 | short version; | ||
38 | uchar track_no, index_no; | ||
39 | uint32_t total_samples, block_index, block_samples, flags, crc; | ||
40 | } WavpackHeader; | ||
41 | |||
42 | #define WavpackHeaderFormat "4LS2LLLLL" | ||
43 | |||
44 | // or-values for "flags" | ||
45 | |||
46 | #define BYTES_STORED 3 // 1-4 bytes/sample | ||
47 | #define MONO_FLAG 4 // not stereo | ||
48 | #define HYBRID_FLAG 8 // hybrid mode | ||
49 | #define JOINT_STEREO 0x10 // joint stereo | ||
50 | #define CROSS_DECORR 0x20 // no-delay cross decorrelation | ||
51 | #define HYBRID_SHAPE 0x40 // noise shape (hybrid mode only) | ||
52 | #define FLOAT_DATA 0x80 // ieee 32-bit floating point data | ||
53 | |||
54 | #define INT32_DATA 0x100 // special extended int handling | ||
55 | #define HYBRID_BITRATE 0x200 // bitrate noise (hybrid mode only) | ||
56 | #define HYBRID_BALANCE 0x400 // balance noise (hybrid stereo mode only) | ||
57 | |||
58 | #define INITIAL_BLOCK 0x800 // initial block of multichannel segment | ||
59 | #define FINAL_BLOCK 0x1000 // final block of multichannel segment | ||
60 | |||
61 | #define SHIFT_LSB 13 | ||
62 | #define SHIFT_MASK (0x1fL << SHIFT_LSB) | ||
63 | |||
64 | #define MAG_LSB 18 | ||
65 | #define MAG_MASK (0x1fL << MAG_LSB) | ||
66 | |||
67 | #define SRATE_LSB 23 | ||
68 | #define SRATE_MASK (0xfL << SRATE_LSB) | ||
69 | |||
70 | #define FALSE_STEREO 0x40000000 // block is stereo, but data is mono | ||
71 | |||
72 | #define IGNORED_FLAGS 0x18000000 // reserved, but ignore if encountered | ||
73 | #define NEW_SHAPING 0x20000000 // use IIR filter for negative shaping | ||
74 | #define UNKNOWN_FLAGS 0x80000000 // also reserved, but refuse decode if | ||
75 | // encountered | ||
76 | |||
77 | #define MONO_DATA (MONO_FLAG | FALSE_STEREO) | ||
78 | |||
79 | #define MIN_STREAM_VERS 0x402 // lowest stream version we'll decode | ||
80 | #define MAX_STREAM_VERS 0x410 // highest stream version we'll decode | ||
81 | #define CUR_STREAM_VERS 0x403 // stream version we are writing now | ||
82 | |||
83 | //////////////////////////// WavPack Metadata ///////////////////////////////// | ||
84 | |||
85 | // This is an internal representation of metadata. | ||
86 | |||
87 | typedef struct { | ||
88 | uchar temp_data [64]; | ||
89 | int32_t byte_length; | ||
90 | void *data; | ||
91 | uchar id; | ||
92 | } WavpackMetadata; | ||
93 | |||
94 | #define ID_OPTIONAL_DATA 0x20 | ||
95 | #define ID_ODD_SIZE 0x40 | ||
96 | #define ID_LARGE 0x80 | ||
97 | |||
98 | #define ID_DUMMY 0x0 | ||
99 | #define ID_ENCODER_INFO 0x1 | ||
100 | #define ID_DECORR_TERMS 0x2 | ||
101 | #define ID_DECORR_WEIGHTS 0x3 | ||
102 | #define ID_DECORR_SAMPLES 0x4 | ||
103 | #define ID_ENTROPY_VARS 0x5 | ||
104 | #define ID_HYBRID_PROFILE 0x6 | ||
105 | #define ID_SHAPING_WEIGHTS 0x7 | ||
106 | #define ID_FLOAT_INFO 0x8 | ||
107 | #define ID_INT32_INFO 0x9 | ||
108 | #define ID_WV_BITSTREAM 0xa | ||
109 | #define ID_WVC_BITSTREAM 0xb | ||
110 | #define ID_WVX_BITSTREAM 0xc | ||
111 | #define ID_CHANNEL_INFO 0xd | ||
112 | |||
113 | #define ID_RIFF_HEADER (ID_OPTIONAL_DATA | 0x1) | ||
114 | #define ID_RIFF_TRAILER (ID_OPTIONAL_DATA | 0x2) | ||
115 | #define ID_REPLAY_GAIN (ID_OPTIONAL_DATA | 0x3) | ||
116 | #define ID_CUESHEET (ID_OPTIONAL_DATA | 0x4) | ||
117 | #define ID_CONFIG_BLOCK (ID_OPTIONAL_DATA | 0x5) | ||
118 | #define ID_MD5_CHECKSUM (ID_OPTIONAL_DATA | 0x6) | ||
119 | #define ID_SAMPLE_RATE (ID_OPTIONAL_DATA | 0x7) | ||
120 | |||
121 | ///////////////////////// WavPack Configuration /////////////////////////////// | ||
122 | |||
123 | // This internal structure is used during encode to provide configuration to | ||
124 | // the encoding engine and during decoding to provide fle information back to | ||
125 | // the higher level functions. Not all fields are used in both modes. | ||
126 | |||
127 | typedef struct { | ||
128 | int bits_per_sample, bytes_per_sample; | ||
129 | int flags, num_channels, float_norm_exp; | ||
130 | uint32_t sample_rate, channel_mask; | ||
131 | } WavpackConfig; | ||
132 | |||
133 | #define CONFIG_BYTES_STORED 3 // 1-4 bytes/sample | ||
134 | #define CONFIG_MONO_FLAG 4 // not stereo | ||
135 | #define CONFIG_HYBRID_FLAG 8 // hybrid mode | ||
136 | #define CONFIG_JOINT_STEREO 0x10 // joint stereo | ||
137 | #define CONFIG_CROSS_DECORR 0x20 // no-delay cross decorrelation | ||
138 | #define CONFIG_HYBRID_SHAPE 0x40 // noise shape (hybrid mode only) | ||
139 | #define CONFIG_FLOAT_DATA 0x80 // ieee 32-bit floating point data | ||
140 | |||
141 | #define CONFIG_ADOBE_MODE 0x100 // "adobe" mode for 32-bit floats | ||
142 | #define CONFIG_FAST_FLAG 0x200 // fast mode | ||
143 | #define CONFIG_VERY_FAST_FLAG 0x400 // double fast | ||
144 | #define CONFIG_HIGH_FLAG 0x800 // high quality mode | ||
145 | #define CONFIG_VERY_HIGH_FLAG 0x1000 // double high (not used yet) | ||
146 | #define CONFIG_BITRATE_KBPS 0x2000 // bitrate is kbps, not bits / sample | ||
147 | #define CONFIG_AUTO_SHAPING 0x4000 // automatic noise shaping | ||
148 | #define CONFIG_SHAPE_OVERRIDE 0x8000 // shaping mode specified | ||
149 | #define CONFIG_JOINT_OVERRIDE 0x10000 // joint-stereo mode specified | ||
150 | #define CONFIG_COPY_TIME 0x20000 // copy file-time from source | ||
151 | #define CONFIG_CREATE_EXE 0x40000 // create executable (not yet) | ||
152 | #define CONFIG_CREATE_WVC 0x80000 // create correction file | ||
153 | #define CONFIG_OPTIMIZE_WVC 0x100000 // maximize bybrid compression | ||
154 | #define CONFIG_QUALITY_MODE 0x200000 // psychoacoustic quality mode | ||
155 | #define CONFIG_RAW_FLAG 0x400000 // raw mode (not implemented yet) | ||
156 | #define CONFIG_CALC_NOISE 0x800000 // calc noise in hybrid mode | ||
157 | #define CONFIG_LOSSY_MODE 0x1000000 // obsolete (for information) | ||
158 | #define CONFIG_EXTRA_MODE 0x2000000 // extra processing mode | ||
159 | #define CONFIG_SKIP_WVX 0x4000000 // no wvx stream w/ floats & big ints | ||
160 | #define CONFIG_MD5_CHECKSUM 0x8000000 // compute & store MD5 signature | ||
161 | #define CONFIG_QUIET_MODE 0x10000000 // don't report progress % | ||
162 | |||
163 | //////////////////////////////// WavPack Stream /////////////////////////////// | ||
164 | |||
165 | // This internal structure contains everything required to handle a WavPack | ||
166 | // "stream", which is defined as a stereo or mono stream of audio samples. For | ||
167 | // multichannel audio several of these would be required. Each stream contains | ||
168 | // pointers to hold a complete allocated block of WavPack data, although it's | ||
169 | // possible to decode WavPack blocks without buffering an entire block. | ||
170 | |||
171 | typedef int32_t (*read_stream)(void *, int32_t); | ||
172 | |||
173 | typedef struct bs { | ||
174 | uchar *buf, *end, *ptr; | ||
175 | void (*wrap)(struct bs *bs); | ||
176 | uint32_t file_bytes, sr; | ||
177 | int error, bc; | ||
178 | read_stream file; | ||
179 | } Bitstream; | ||
180 | |||
181 | #define MAX_NTERMS 16 | ||
182 | #define MAX_TERM 8 | ||
183 | |||
184 | struct decorr_pass { | ||
185 | short term, delta, weight_A, weight_B; | ||
186 | int32_t samples_A [MAX_TERM], samples_B [MAX_TERM]; | ||
187 | }; | ||
188 | |||
189 | struct entropy_data { | ||
190 | uint32_t median [3], slow_level, error_limit; | ||
191 | }; | ||
192 | |||
193 | struct words_data { | ||
194 | uint32_t bitrate_delta [2], bitrate_acc [2]; | ||
195 | uint32_t pend_data, holding_one, zeros_acc; | ||
196 | int holding_zero, pend_count; | ||
197 | struct entropy_data c [2]; | ||
198 | }; | ||
199 | |||
200 | typedef struct { | ||
201 | WavpackHeader wphdr; | ||
202 | Bitstream wvbits; | ||
203 | |||
204 | struct words_data w; | ||
205 | |||
206 | int num_terms, mute_error; | ||
207 | uint32_t sample_index, crc; | ||
208 | int32_t block_bytes_left; | ||
209 | |||
210 | uchar int32_sent_bits, int32_zeros, int32_ones, int32_dups; | ||
211 | uchar float_flags, float_shift, float_max_exp, float_norm_exp; | ||
212 | uchar *blockbuff, *blockend; | ||
213 | |||
214 | struct decorr_pass decorr_passes [MAX_NTERMS]; | ||
215 | |||
216 | } WavpackStream; | ||
217 | |||
218 | // flags for float_flags: | ||
219 | |||
220 | #define FLOAT_SHIFT_ONES 1 // bits left-shifted into float = '1' | ||
221 | #define FLOAT_SHIFT_SAME 2 // bits left-shifted into float are the same | ||
222 | #define FLOAT_SHIFT_SENT 4 // bits shifted into float are sent literally | ||
223 | #define FLOAT_ZEROS_SENT 8 // "zeros" are not all real zeros | ||
224 | #define FLOAT_NEG_ZEROS 0x10 // contains negative zeros | ||
225 | #define FLOAT_EXCEPTIONS 0x20 // contains exceptions (inf, nan, etc.) | ||
226 | |||
227 | /////////////////////////////// WavPack Context /////////////////////////////// | ||
228 | |||
229 | // This internal structure holds everything required to encode or decode WavPack | ||
230 | // files. It is recommended that direct access to this structure be minimized | ||
231 | // and the provided utilities used instead. | ||
232 | |||
233 | typedef struct { | ||
234 | WavpackStream stream; | ||
235 | WavpackConfig config; | ||
236 | |||
237 | uchar *wrapper_data; | ||
238 | int wrapper_bytes; | ||
239 | |||
240 | uchar read_buffer [1024]; | ||
241 | char error_message [80]; | ||
242 | |||
243 | read_stream infile; | ||
244 | uint32_t total_samples, crc_errors, first_flags; | ||
245 | int open_flags, norm_offset, reduced_channels, lossy_blocks; | ||
246 | |||
247 | } WavpackContext; | ||
248 | |||
249 | //////////////////////// function prototypes and macros ////////////////////// | ||
250 | |||
251 | #define CLEAR(destin) memset (&destin, 0, sizeof (destin)); | ||
252 | |||
253 | // bits.c | ||
254 | |||
255 | void bs_open_read (Bitstream *bs, uchar *buffer_start, uchar *buffer_end, read_stream file, uint32_t file_bytes); | ||
256 | void bs_open_write (Bitstream *bs, uchar *buffer_start, uchar *buffer_end); | ||
257 | uint32_t bs_close_write (Bitstream *bs); | ||
258 | |||
259 | #define bs_is_open(bs) ((bs)->ptr != NULL) | ||
260 | |||
261 | #define getbit(bs) ( \ | ||
262 | (((bs)->bc) ? \ | ||
263 | ((bs)->bc--, (bs)->sr & 1) : \ | ||
264 | (((++((bs)->ptr) != (bs)->end) ? (void) 0 : (bs)->wrap (bs)), (bs)->bc = 7, ((bs)->sr = *((bs)->ptr)) & 1) \ | ||
265 | ) ? \ | ||
266 | ((bs)->sr >>= 1, 1) : \ | ||
267 | ((bs)->sr >>= 1, 0) \ | ||
268 | ) | ||
269 | |||
270 | #define getbits(value, nbits, bs) { \ | ||
271 | while ((nbits) > (bs)->bc) { \ | ||
272 | if (++((bs)->ptr) == (bs)->end) (bs)->wrap (bs); \ | ||
273 | (bs)->sr |= (int32_t)*((bs)->ptr) << (bs)->bc; \ | ||
274 | (bs)->bc += 8; \ | ||
275 | } \ | ||
276 | *(value) = (bs)->sr; \ | ||
277 | if ((bs)->bc > 32) { \ | ||
278 | (bs)->bc -= (nbits); \ | ||
279 | (bs)->sr = *((bs)->ptr) >> (8 - (bs)->bc); \ | ||
280 | } \ | ||
281 | else { \ | ||
282 | (bs)->bc -= (nbits); \ | ||
283 | (bs)->sr >>= (nbits); \ | ||
284 | } \ | ||
285 | } | ||
286 | |||
287 | #define putbit(bit, bs) { if (bit) (bs)->sr |= (1 << (bs)->bc); \ | ||
288 | if (++((bs)->bc) == 8) { \ | ||
289 | *((bs)->ptr) = (bs)->sr; \ | ||
290 | (bs)->sr = (bs)->bc = 0; \ | ||
291 | if (++((bs)->ptr) == (bs)->end) (bs)->wrap (bs); \ | ||
292 | }} | ||
293 | |||
294 | #define putbit_0(bs) { \ | ||
295 | if (++((bs)->bc) == 8) { \ | ||
296 | *((bs)->ptr) = (bs)->sr; \ | ||
297 | (bs)->sr = (bs)->bc = 0; \ | ||
298 | if (++((bs)->ptr) == (bs)->end) (bs)->wrap (bs); \ | ||
299 | }} | ||
300 | |||
301 | #define putbit_1(bs) { (bs)->sr |= (1 << (bs)->bc); \ | ||
302 | if (++((bs)->bc) == 8) { \ | ||
303 | *((bs)->ptr) = (bs)->sr; \ | ||
304 | (bs)->sr = (bs)->bc = 0; \ | ||
305 | if (++((bs)->ptr) == (bs)->end) (bs)->wrap (bs); \ | ||
306 | }} | ||
307 | |||
308 | #define putbits(value, nbits, bs) { \ | ||
309 | (bs)->sr |= (int32_t)(value) << (bs)->bc; \ | ||
310 | if (((bs)->bc += (nbits)) >= 8) \ | ||
311 | do { \ | ||
312 | *((bs)->ptr) = (bs)->sr; \ | ||
313 | (bs)->sr >>= 8; \ | ||
314 | if (++((bs)->ptr) == (bs)->end) (bs)->wrap (bs); \ | ||
315 | } while (((bs)->bc -= 8) >= 8); \ | ||
316 | } | ||
317 | |||
318 | void little_endian_to_native (void *data, char *format); | ||
319 | void native_to_little_endian (void *data, char *format); | ||
320 | |||
321 | // These macros implement the weight application and update operations | ||
322 | // that are at the heart of the decorrelation loops. Note that when there | ||
323 | // are several alternative versions of the same macro (marked with PERFCOND) | ||
324 | // then the versions are functionally equivalent with respect to WavPack | ||
325 | // decoding and the user should choose the one that provides the best | ||
326 | // performance. This may be easier to check when NOT using the assembly | ||
327 | // language optimizations. | ||
328 | |||
329 | #if 1 // PERFCOND | ||
330 | #define apply_weight_i(weight, sample) ((weight * sample + 512) >> 10) | ||
331 | #else | ||
332 | #define apply_weight_i(weight, sample) ((((weight * sample) >> 8) + 2) >> 2) | ||
333 | #endif | ||
334 | |||
335 | #define apply_weight_f(weight, sample) (((((sample & 0xffff) * weight) >> 9) + \ | ||
336 | (((sample & ~0xffff) >> 9) * weight) + 1) >> 1) | ||
337 | |||
338 | #if 1 // PERFCOND | ||
339 | #define apply_weight(weight, sample) (sample != (short) sample ? \ | ||
340 | apply_weight_f (weight, sample) : apply_weight_i (weight, sample)) | ||
341 | #else | ||
342 | #define apply_weight(weight, sample) ((int32_t)((weight * (int64_t) sample + 512) >> 10)) | ||
343 | #endif | ||
344 | |||
345 | #if 0 // PERFCOND | ||
346 | #define update_weight(weight, delta, source, result) \ | ||
347 | if (source && result) { int32_t s = (int32_t) (source ^ result) >> 31; weight = (delta ^ s) + (weight - s); } | ||
348 | #elif 1 | ||
349 | #define update_weight(weight, delta, source, result) \ | ||
350 | if (source && result) weight += (((source ^ result) >> 30) | 1) * delta | ||
351 | #else | ||
352 | #define update_weight(weight, delta, source, result) \ | ||
353 | if (source && result) (source ^ result) < 0 ? (weight -= delta) : (weight += delta) | ||
354 | #endif | ||
355 | |||
356 | #define update_weight_clip(weight, delta, source, result) \ | ||
357 | if (source && result && ((source ^ result) < 0 ? (weight -= delta) < -1024 : (weight += delta) > 1024)) \ | ||
358 | weight = weight < 0 ? -1024 : 1024 | ||
359 | |||
360 | // unpack.c | ||
361 | |||
362 | int unpack_init (WavpackContext *wpc); | ||
363 | int init_wv_bitstream (WavpackContext *wpc, WavpackMetadata *wpmd); | ||
364 | int read_decorr_terms (WavpackStream *wps, WavpackMetadata *wpmd); | ||
365 | int read_decorr_weights (WavpackStream *wps, WavpackMetadata *wpmd); | ||
366 | int read_decorr_samples (WavpackStream *wps, WavpackMetadata *wpmd); | ||
367 | int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd); | ||
368 | int read_int32_info (WavpackStream *wps, WavpackMetadata *wpmd); | ||
369 | int read_channel_info (WavpackContext *wpc, WavpackMetadata *wpmd); | ||
370 | int read_config_info (WavpackContext *wpc, WavpackMetadata *wpmd); | ||
371 | int read_sample_rate (WavpackContext *wpc, WavpackMetadata *wpmd); | ||
372 | int32_t unpack_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample_count); | ||
373 | int check_crc_error (WavpackContext *wpc); | ||
374 | |||
375 | // pack.c | ||
376 | |||
377 | void pack_init (WavpackContext *wpc); | ||
378 | int pack_start_block (WavpackContext *wpc); | ||
379 | int pack_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample_count); | ||
380 | int pack_finish_block (WavpackContext *wpc); | ||
381 | |||
382 | // metadata.c stuff | ||
383 | |||
384 | int read_metadata_buff (WavpackContext *wpc, WavpackMetadata *wpmd); | ||
385 | int process_metadata (WavpackContext *wpc, WavpackMetadata *wpmd); | ||
386 | int copy_metadata (WavpackMetadata *wpmd, uchar *buffer_start, uchar *buffer_end); | ||
387 | void free_metadata (WavpackMetadata *wpmd); | ||
388 | |||
389 | // words.c stuff | ||
390 | |||
391 | void init_words (WavpackStream *wps); | ||
392 | int read_entropy_vars (WavpackStream *wps, WavpackMetadata *wpmd); | ||
393 | void write_entropy_vars (WavpackStream *wps, WavpackMetadata *wpmd); | ||
394 | int read_hybrid_profile (WavpackStream *wps, WavpackMetadata *wpmd); | ||
395 | int32_t get_words (int32_t *buffer, int nsamples, uint32_t flags, | ||
396 | struct words_data *w, Bitstream *bs); | ||
397 | void send_word_lossless (int32_t value, int chan, | ||
398 | struct words_data *w, Bitstream *bs); | ||
399 | void send_words (int32_t *buffer, int nsamples, uint32_t flags, | ||
400 | struct words_data *w, Bitstream *bs); | ||
401 | void flush_word (struct words_data *w, Bitstream *bs); | ||
402 | int log2s (int32_t value); | ||
403 | int32_t exp2s (int log); | ||
404 | signed char store_weight (int weight); | ||
405 | int restore_weight (signed char weight); | ||
406 | |||
407 | #define WORD_EOF (1L << 31) | ||
408 | |||
409 | // float.c | ||
410 | |||
411 | int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd); | ||
412 | void float_values (WavpackStream *wps, int32_t *values, int32_t num_values); | ||
413 | void float_normalize (int32_t *values, int32_t num_values, int delta_exp); | ||
414 | |||
415 | // wputils.c | ||
416 | |||
417 | WavpackContext *WavpackOpenFileInput (read_stream infile, char *error); | ||
418 | |||
419 | int WavpackGetMode (WavpackContext *wpc); | ||
420 | |||
421 | #define MODE_WVC 0x1 | ||
422 | #define MODE_LOSSLESS 0x2 | ||
423 | #define MODE_HYBRID 0x4 | ||
424 | #define MODE_FLOAT 0x8 | ||
425 | #define MODE_VALID_TAG 0x10 | ||
426 | #define MODE_HIGH 0x20 | ||
427 | #define MODE_FAST 0x40 | ||
428 | |||
429 | uint32_t WavpackUnpackSamples (WavpackContext *wpc, int32_t *buffer, uint32_t samples); | ||
430 | uint32_t WavpackGetNumSamples (WavpackContext *wpc); | ||
431 | uint32_t WavpackGetSampleIndex (WavpackContext *wpc); | ||
432 | int WavpackGetNumErrors (WavpackContext *wpc); | ||
433 | int WavpackLossyBlocks (WavpackContext *wpc); | ||
434 | uint32_t WavpackGetSampleRate (WavpackContext *wpc); | ||
435 | int WavpackGetBitsPerSample (WavpackContext *wpc); | ||
436 | int WavpackGetBytesPerSample (WavpackContext *wpc); | ||
437 | int WavpackGetNumChannels (WavpackContext *wpc); | ||
438 | int WavpackGetReducedChannels (WavpackContext *wpc); | ||
439 | WavpackContext *WavpackOpenFileOutput (void); | ||
440 | int WavpackSetConfiguration (WavpackContext *wpc, WavpackConfig *config, uint32_t total_samples); | ||
441 | void WavpackAddWrapper (WavpackContext *wpc, void *data, uint32_t bcount); | ||
442 | int WavpackStartBlock (WavpackContext *wpc, uchar *begin, uchar *end); | ||
443 | int WavpackPackSamples (WavpackContext *wpc, int32_t *sample_buffer, uint32_t sample_count); | ||
444 | uint32_t WavpackFinishBlock (WavpackContext *wpc); | ||
445 | void WavpackUpdateNumSamples (WavpackContext *wpc, void *first_block); | ||
446 | void *WavpackGetWrapperLocation (void *first_block); | ||
447 | |||
diff --git a/lib/rbcodec/codecs/libwavpack/words.c b/lib/rbcodec/codecs/libwavpack/words.c new file mode 100644 index 0000000000..3d9e753e4b --- /dev/null +++ b/lib/rbcodec/codecs/libwavpack/words.c | |||
@@ -0,0 +1,786 @@ | |||
1 | //////////////////////////////////////////////////////////////////////////// | ||
2 | // **** WAVPACK **** // | ||
3 | // Hybrid Lossless Wavefile Compressor // | ||
4 | // Copyright (c) 1998 - 2004 Conifer Software. // | ||
5 | // All Rights Reserved. // | ||
6 | //////////////////////////////////////////////////////////////////////////// | ||
7 | |||
8 | // words.c | ||
9 | |||
10 | // This module provides entropy word encoding and decoding functions using | ||
11 | // a variation on the Rice method. This was introduced in version 3.93 | ||
12 | // because it allows splitting the data into a "lossy" stream and a | ||
13 | // "correction" stream in a very efficient manner and is therefore ideal | ||
14 | // for the "hybrid" mode. For 4.0, the efficiency of this method was | ||
15 | // significantly improved by moving away from the normal Rice restriction of | ||
16 | // using powers of two for the modulus divisions and now the method can be | ||
17 | // used for both hybrid and pure lossless encoding. | ||
18 | |||
19 | // Samples are divided by median probabilities at 5/7 (71.43%), 10/49 (20.41%), | ||
20 | // and 20/343 (5.83%). Each zone has 3.5 times fewer samples than the | ||
21 | // previous. Using standard Rice coding on this data would result in 1.4 | ||
22 | // bits per sample average (not counting sign bit). However, there is a | ||
23 | // very simple encoding that is over 99% efficient with this data and | ||
24 | // results in about 1.22 bits per sample. | ||
25 | |||
26 | #include "wavpack.h" | ||
27 | |||
28 | #include <string.h> | ||
29 | |||
30 | //////////////////////////////// local macros ///////////////////////////////// | ||
31 | |||
32 | #define LIMIT_ONES 16 // maximum consecutive 1s sent for "div" data | ||
33 | |||
34 | // these control the time constant "slow_level" which is used for hybrid mode | ||
35 | // that controls bitrate as a function of residual level (HYBRID_BITRATE). | ||
36 | #define SLS 8 | ||
37 | #define SLO ((1 << (SLS - 1))) | ||
38 | |||
39 | // these control the time constant of the 3 median level breakpoints | ||
40 | #define DIV0 128 // 5/7 of samples | ||
41 | #define DIV1 64 // 10/49 of samples | ||
42 | #define DIV2 32 // 20/343 of samples | ||
43 | |||
44 | // this macro retrieves the specified median breakpoint (without frac; min = 1) | ||
45 | #define GET_MED(med) (((c->median [med]) >> 4) + 1) | ||
46 | |||
47 | // These macros update the specified median breakpoints. Note that the median | ||
48 | // is incremented when the sample is higher than the median, else decremented. | ||
49 | // They are designed so that the median will never drop below 1 and the value | ||
50 | // is essentially stationary if there are 2 increments for every 5 decrements. | ||
51 | |||
52 | #define INC_MED0() (c->median [0] += ((c->median [0] + DIV0) / DIV0) * 5) | ||
53 | #define DEC_MED0() (c->median [0] -= ((c->median [0] + (DIV0-2)) / DIV0) * 2) | ||
54 | #define INC_MED1() (c->median [1] += ((c->median [1] + DIV1) / DIV1) * 5) | ||
55 | #define DEC_MED1() (c->median [1] -= ((c->median [1] + (DIV1-2)) / DIV1) * 2) | ||
56 | #define INC_MED2() (c->median [2] += ((c->median [2] + DIV2) / DIV2) * 5) | ||
57 | #define DEC_MED2() (c->median [2] -= ((c->median [2] + (DIV2-2)) / DIV2) * 2) | ||
58 | |||
59 | #define count_bits(av) ( \ | ||
60 | (av) < (1 << 8) ? nbits_table [av] : \ | ||
61 | ( \ | ||
62 | (av) < (1L << 16) ? nbits_table [(av) >> 8] + 8 : \ | ||
63 | ((av) < (1L << 24) ? nbits_table [(av) >> 16] + 16 : nbits_table [(av) >> 24] + 24) \ | ||
64 | ) \ | ||
65 | ) | ||
66 | |||
67 | ///////////////////////////// local table storage //////////////////////////// | ||
68 | |||
69 | static const char nbits_table [] ICONST_ATTR = { | ||
70 | 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, // 0 - 15 | ||
71 | 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // 16 - 31 | ||
72 | 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, // 32 - 47 | ||
73 | 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, // 48 - 63 | ||
74 | 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 64 - 79 | ||
75 | 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 80 - 95 | ||
76 | 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 96 - 111 | ||
77 | 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 112 - 127 | ||
78 | 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 128 - 143 | ||
79 | 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 144 - 159 | ||
80 | 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 160 - 175 | ||
81 | 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 176 - 191 | ||
82 | 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 192 - 207 | ||
83 | 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 208 - 223 | ||
84 | 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 224 - 239 | ||
85 | 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 // 240 - 255 | ||
86 | }; | ||
87 | |||
88 | static const uchar log2_table [] = { | ||
89 | 0x00, 0x01, 0x03, 0x04, 0x06, 0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x10, 0x11, 0x12, 0x14, 0x15, | ||
90 | 0x16, 0x18, 0x19, 0x1a, 0x1c, 0x1d, 0x1e, 0x20, 0x21, 0x22, 0x24, 0x25, 0x26, 0x28, 0x29, 0x2a, | ||
91 | 0x2c, 0x2d, 0x2e, 0x2f, 0x31, 0x32, 0x33, 0x34, 0x36, 0x37, 0x38, 0x39, 0x3b, 0x3c, 0x3d, 0x3e, | ||
92 | 0x3f, 0x41, 0x42, 0x43, 0x44, 0x45, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4d, 0x4e, 0x4f, 0x50, 0x51, | ||
93 | 0x52, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, | ||
94 | 0x64, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x74, 0x75, | ||
95 | 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, | ||
96 | 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, | ||
97 | 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, | ||
98 | 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb2, | ||
99 | 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc0, | ||
100 | 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcb, 0xcc, 0xcd, 0xce, | ||
101 | 0xcf, 0xd0, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd8, 0xd9, 0xda, 0xdb, | ||
102 | 0xdc, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe4, 0xe5, 0xe6, 0xe7, 0xe7, | ||
103 | 0xe8, 0xe9, 0xea, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xee, 0xef, 0xf0, 0xf1, 0xf1, 0xf2, 0xf3, 0xf4, | ||
104 | 0xf4, 0xf5, 0xf6, 0xf7, 0xf7, 0xf8, 0xf9, 0xf9, 0xfa, 0xfb, 0xfc, 0xfc, 0xfd, 0xfe, 0xff, 0xff | ||
105 | }; | ||
106 | |||
107 | static const uchar exp2_table [] ICONST_ATTR = { | ||
108 | 0x00, 0x01, 0x01, 0x02, 0x03, 0x03, 0x04, 0x05, 0x06, 0x06, 0x07, 0x08, 0x08, 0x09, 0x0a, 0x0b, | ||
109 | 0x0b, 0x0c, 0x0d, 0x0e, 0x0e, 0x0f, 0x10, 0x10, 0x11, 0x12, 0x13, 0x13, 0x14, 0x15, 0x16, 0x16, | ||
110 | 0x17, 0x18, 0x19, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1d, 0x1e, 0x1f, 0x20, 0x20, 0x21, 0x22, 0x23, | ||
111 | 0x24, 0x24, 0x25, 0x26, 0x27, 0x28, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, | ||
112 | 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3a, 0x3b, 0x3c, 0x3d, | ||
113 | 0x3e, 0x3f, 0x40, 0x41, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x48, 0x49, 0x4a, 0x4b, | ||
114 | 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, | ||
115 | 0x5b, 0x5c, 0x5d, 0x5e, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, | ||
116 | 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, | ||
117 | 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x87, 0x88, 0x89, 0x8a, | ||
118 | 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, | ||
119 | 0x9c, 0x9d, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, | ||
120 | 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, | ||
121 | 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc8, 0xc9, 0xca, 0xcb, 0xcd, 0xce, 0xcf, 0xd0, 0xd2, 0xd3, 0xd4, | ||
122 | 0xd6, 0xd7, 0xd8, 0xd9, 0xdb, 0xdc, 0xdd, 0xde, 0xe0, 0xe1, 0xe2, 0xe4, 0xe5, 0xe6, 0xe8, 0xe9, | ||
123 | 0xea, 0xec, 0xed, 0xee, 0xf0, 0xf1, 0xf2, 0xf4, 0xf5, 0xf6, 0xf8, 0xf9, 0xfa, 0xfc, 0xfd, 0xff | ||
124 | }; | ||
125 | |||
126 | static const char ones_count_table [] ICONST_ATTR = { | ||
127 | 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5, | ||
128 | 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6, | ||
129 | 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5, | ||
130 | 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7, | ||
131 | 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5, | ||
132 | 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6, | ||
133 | 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5, | ||
134 | 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,8 | ||
135 | }; | ||
136 | |||
137 | ///////////////////////////// executable code //////////////////////////////// | ||
138 | |||
139 | void init_words (WavpackStream *wps) | ||
140 | { | ||
141 | CLEAR (wps->w); | ||
142 | } | ||
143 | |||
144 | static int mylog2 (uint32_t avalue); | ||
145 | |||
146 | // Read the median log2 values from the specifed metadata structure, convert | ||
147 | // them back to 32-bit unsigned values and store them. If length is not | ||
148 | // exactly correct then we flag and return an error. | ||
149 | |||
150 | int read_entropy_vars (WavpackStream *wps, WavpackMetadata *wpmd) | ||
151 | { | ||
152 | uchar *byteptr = wpmd->data; | ||
153 | |||
154 | if (wpmd->byte_length != ((wps->wphdr.flags & MONO_DATA) ? 6 : 12)) | ||
155 | return FALSE; | ||
156 | |||
157 | wps->w.c [0].median [0] = exp2s (byteptr [0] + (byteptr [1] << 8)); | ||
158 | wps->w.c [0].median [1] = exp2s (byteptr [2] + (byteptr [3] << 8)); | ||
159 | wps->w.c [0].median [2] = exp2s (byteptr [4] + (byteptr [5] << 8)); | ||
160 | |||
161 | if (!(wps->wphdr.flags & MONO_DATA)) { | ||
162 | wps->w.c [1].median [0] = exp2s (byteptr [6] + (byteptr [7] << 8)); | ||
163 | wps->w.c [1].median [1] = exp2s (byteptr [8] + (byteptr [9] << 8)); | ||
164 | wps->w.c [1].median [2] = exp2s (byteptr [10] + (byteptr [11] << 8)); | ||
165 | } | ||
166 | |||
167 | return TRUE; | ||
168 | } | ||
169 | |||
170 | // Allocates the correct space in the metadata structure and writes the | ||
171 | // current median values to it. Values are converted from 32-bit unsigned | ||
172 | // to our internal 16-bit mylog2 values, and read_entropy_vars () is called | ||
173 | // to read the values back because we must compensate for the loss through | ||
174 | // the log function. | ||
175 | |||
176 | void write_entropy_vars (WavpackStream *wps, WavpackMetadata *wpmd) | ||
177 | { | ||
178 | uchar *byteptr; | ||
179 | int temp; | ||
180 | |||
181 | byteptr = wpmd->data = wpmd->temp_data; | ||
182 | wpmd->id = ID_ENTROPY_VARS; | ||
183 | |||
184 | *byteptr++ = temp = mylog2 (wps->w.c [0].median [0]); | ||
185 | *byteptr++ = temp >> 8; | ||
186 | *byteptr++ = temp = mylog2 (wps->w.c [0].median [1]); | ||
187 | *byteptr++ = temp >> 8; | ||
188 | *byteptr++ = temp = mylog2 (wps->w.c [0].median [2]); | ||
189 | *byteptr++ = temp >> 8; | ||
190 | |||
191 | if (!(wps->wphdr.flags & MONO_FLAG)) { | ||
192 | *byteptr++ = temp = mylog2 (wps->w.c [1].median [0]); | ||
193 | *byteptr++ = temp >> 8; | ||
194 | *byteptr++ = temp = mylog2 (wps->w.c [1].median [1]); | ||
195 | *byteptr++ = temp >> 8; | ||
196 | *byteptr++ = temp = mylog2 (wps->w.c [1].median [2]); | ||
197 | *byteptr++ = temp >> 8; | ||
198 | } | ||
199 | |||
200 | wpmd->byte_length = byteptr - (uchar *) wpmd->data; | ||
201 | read_entropy_vars (wps, wpmd); | ||
202 | } | ||
203 | |||
204 | // Read the hybrid related values from the specifed metadata structure, convert | ||
205 | // them back to their internal formats and store them. The extended profile | ||
206 | // stuff is not implemented yet, so return an error if we get more data than | ||
207 | // we know what to do with. | ||
208 | |||
209 | int read_hybrid_profile (WavpackStream *wps, WavpackMetadata *wpmd) | ||
210 | { | ||
211 | uchar *byteptr = wpmd->data; | ||
212 | uchar *endptr = byteptr + wpmd->byte_length; | ||
213 | |||
214 | if (wps->wphdr.flags & HYBRID_BITRATE) { | ||
215 | wps->w.c [0].slow_level = exp2s (byteptr [0] + (byteptr [1] << 8)); | ||
216 | byteptr += 2; | ||
217 | |||
218 | if (!(wps->wphdr.flags & MONO_DATA)) { | ||
219 | wps->w.c [1].slow_level = exp2s (byteptr [0] + (byteptr [1] << 8)); | ||
220 | byteptr += 2; | ||
221 | } | ||
222 | } | ||
223 | |||
224 | wps->w.bitrate_acc [0] = (int32_t)(byteptr [0] + (byteptr [1] << 8)) << 16; | ||
225 | byteptr += 2; | ||
226 | |||
227 | if (!(wps->wphdr.flags & MONO_DATA)) { | ||
228 | wps->w.bitrate_acc [1] = (int32_t)(byteptr [0] + (byteptr [1] << 8)) << 16; | ||
229 | byteptr += 2; | ||
230 | } | ||
231 | |||
232 | if (byteptr < endptr) { | ||
233 | wps->w.bitrate_delta [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8))); | ||
234 | byteptr += 2; | ||
235 | |||
236 | if (!(wps->wphdr.flags & MONO_DATA)) { | ||
237 | wps->w.bitrate_delta [1] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8))); | ||
238 | byteptr += 2; | ||
239 | } | ||
240 | |||
241 | if (byteptr < endptr) | ||
242 | return FALSE; | ||
243 | } | ||
244 | else | ||
245 | wps->w.bitrate_delta [0] = wps->w.bitrate_delta [1] = 0; | ||
246 | |||
247 | return TRUE; | ||
248 | } | ||
249 | |||
250 | // This function is called during both encoding and decoding of hybrid data to | ||
251 | // update the "error_limit" variable which determines the maximum sample error | ||
252 | // allowed in the main bitstream. In the HYBRID_BITRATE mode (which is the only | ||
253 | // currently implemented) this is calculated from the slow_level values and the | ||
254 | // bitrate accumulators. Note that the bitrate accumulators can be changing. | ||
255 | |||
256 | static void update_error_limit (struct words_data *w, uint32_t flags) | ||
257 | { | ||
258 | int bitrate_0 = (w->bitrate_acc [0] += w->bitrate_delta [0]) >> 16; | ||
259 | |||
260 | if (flags & MONO_DATA) { | ||
261 | if (flags & HYBRID_BITRATE) { | ||
262 | int slow_log_0 = (w->c [0].slow_level + SLO) >> SLS; | ||
263 | |||
264 | if (slow_log_0 - bitrate_0 > -0x100) | ||
265 | w->c [0].error_limit = exp2s (slow_log_0 - bitrate_0 + 0x100); | ||
266 | else | ||
267 | w->c [0].error_limit = 0; | ||
268 | } | ||
269 | else | ||
270 | w->c [0].error_limit = exp2s (bitrate_0); | ||
271 | } | ||
272 | else { | ||
273 | int bitrate_1 = (w->bitrate_acc [1] += w->bitrate_delta [1]) >> 16; | ||
274 | |||
275 | if (flags & HYBRID_BITRATE) { | ||
276 | int slow_log_0 = (w->c [0].slow_level + SLO) >> SLS; | ||
277 | int slow_log_1 = (w->c [1].slow_level + SLO) >> SLS; | ||
278 | |||
279 | if (flags & HYBRID_BALANCE) { | ||
280 | int balance = (slow_log_1 - slow_log_0 + bitrate_1 + 1) >> 1; | ||
281 | |||
282 | if (balance > bitrate_0) { | ||
283 | bitrate_1 = bitrate_0 * 2; | ||
284 | bitrate_0 = 0; | ||
285 | } | ||
286 | else if (-balance > bitrate_0) { | ||
287 | bitrate_0 = bitrate_0 * 2; | ||
288 | bitrate_1 = 0; | ||
289 | } | ||
290 | else { | ||
291 | bitrate_1 = bitrate_0 + balance; | ||
292 | bitrate_0 = bitrate_0 - balance; | ||
293 | } | ||
294 | } | ||
295 | |||
296 | if (slow_log_0 - bitrate_0 > -0x100) | ||
297 | w->c [0].error_limit = exp2s (slow_log_0 - bitrate_0 + 0x100); | ||
298 | else | ||
299 | w->c [0].error_limit = 0; | ||
300 | |||
301 | if (slow_log_1 - bitrate_1 > -0x100) | ||
302 | w->c [1].error_limit = exp2s (slow_log_1 - bitrate_1 + 0x100); | ||
303 | else | ||
304 | w->c [1].error_limit = 0; | ||
305 | } | ||
306 | else { | ||
307 | w->c [0].error_limit = exp2s (bitrate_0); | ||
308 | w->c [1].error_limit = exp2s (bitrate_1); | ||
309 | } | ||
310 | } | ||
311 | } | ||
312 | |||
313 | static uint32_t read_code (Bitstream *bs, uint32_t maxcode); | ||
314 | |||
315 | // Read the next word from the bitstream "wvbits" and return the value. This | ||
316 | // function can be used for hybrid or lossless streams, but since an | ||
317 | // optimized version is available for lossless this function would normally | ||
318 | // be used for hybrid only. If a hybrid lossless stream is being read then | ||
319 | // the "correction" offset is written at the specified pointer. A return value | ||
320 | // of WORD_EOF indicates that the end of the bitstream was reached (all 1s) or | ||
321 | // some other error occurred. | ||
322 | |||
323 | int32_t get_words (int32_t *buffer, int nsamples, uint32_t flags, | ||
324 | struct words_data *w, Bitstream *bs) | ||
325 | { | ||
326 | register struct entropy_data *c = w->c; | ||
327 | int csamples; | ||
328 | |||
329 | if (!(flags & MONO_DATA)) | ||
330 | nsamples *= 2; | ||
331 | |||
332 | for (csamples = 0; csamples < nsamples; ++csamples) { | ||
333 | uint32_t ones_count, low, mid, high; | ||
334 | |||
335 | if (!(flags & MONO_DATA)) | ||
336 | c = w->c + (csamples & 1); | ||
337 | |||
338 | if (!(w->c [0].median [0] & ~1) && !w->holding_zero && !w->holding_one && !(w->c [1].median [0] & ~1)) { | ||
339 | uint32_t mask; | ||
340 | int cbits; | ||
341 | |||
342 | if (w->zeros_acc) { | ||
343 | if (--w->zeros_acc) { | ||
344 | c->slow_level -= (c->slow_level + SLO) >> SLS; | ||
345 | *buffer++ = 0; | ||
346 | continue; | ||
347 | } | ||
348 | } | ||
349 | else { | ||
350 | for (cbits = 0; cbits < 33 && getbit (bs); ++cbits); | ||
351 | |||
352 | if (cbits == 33) | ||
353 | break; | ||
354 | |||
355 | if (cbits < 2) | ||
356 | w->zeros_acc = cbits; | ||
357 | else { | ||
358 | for (mask = 1, w->zeros_acc = 0; --cbits; mask <<= 1) | ||
359 | if (getbit (bs)) | ||
360 | w->zeros_acc |= mask; | ||
361 | |||
362 | w->zeros_acc |= mask; | ||
363 | } | ||
364 | |||
365 | if (w->zeros_acc) { | ||
366 | c->slow_level -= (c->slow_level + SLO) >> SLS; | ||
367 | CLEAR (w->c [0].median); | ||
368 | CLEAR (w->c [1].median); | ||
369 | *buffer++ = 0; | ||
370 | continue; | ||
371 | } | ||
372 | } | ||
373 | } | ||
374 | |||
375 | if (w->holding_zero) | ||
376 | ones_count = w->holding_zero = 0; | ||
377 | else { | ||
378 | int next8; | ||
379 | |||
380 | if (bs->bc < 8) { | ||
381 | if (++(bs->ptr) == bs->end) | ||
382 | bs->wrap (bs); | ||
383 | |||
384 | next8 = (bs->sr |= *(bs->ptr) << bs->bc) & 0xff; | ||
385 | bs->bc += 8; | ||
386 | } | ||
387 | else | ||
388 | next8 = bs->sr & 0xff; | ||
389 | |||
390 | if (next8 == 0xff) { | ||
391 | bs->bc -= 8; | ||
392 | bs->sr >>= 8; | ||
393 | |||
394 | for (ones_count = 8; ones_count < (LIMIT_ONES + 1) && getbit (bs); ++ones_count); | ||
395 | |||
396 | if (ones_count == (LIMIT_ONES + 1)) | ||
397 | break; | ||
398 | |||
399 | if (ones_count == LIMIT_ONES) { | ||
400 | uint32_t mask; | ||
401 | int cbits; | ||
402 | |||
403 | for (cbits = 0; cbits < 33 && getbit (bs); ++cbits); | ||
404 | |||
405 | if (cbits == 33) | ||
406 | break; | ||
407 | |||
408 | if (cbits < 2) | ||
409 | ones_count = cbits; | ||
410 | else { | ||
411 | for (mask = 1, ones_count = 0; --cbits; mask <<= 1) | ||
412 | if (getbit (bs)) | ||
413 | ones_count |= mask; | ||
414 | |||
415 | ones_count |= mask; | ||
416 | } | ||
417 | |||
418 | ones_count += LIMIT_ONES; | ||
419 | } | ||
420 | } | ||
421 | else { | ||
422 | bs->bc -= (ones_count = ones_count_table [next8]) + 1; | ||
423 | bs->sr >>= ones_count + 1; | ||
424 | } | ||
425 | |||
426 | if (w->holding_one) { | ||
427 | w->holding_one = ones_count & 1; | ||
428 | ones_count = (ones_count >> 1) + 1; | ||
429 | } | ||
430 | else { | ||
431 | w->holding_one = ones_count & 1; | ||
432 | ones_count >>= 1; | ||
433 | } | ||
434 | |||
435 | w->holding_zero = ~w->holding_one & 1; | ||
436 | } | ||
437 | |||
438 | if ((flags & HYBRID_FLAG) && ((flags & MONO_DATA) || !(csamples & 1))) | ||
439 | update_error_limit (w, flags); | ||
440 | |||
441 | if (ones_count == 0) { | ||
442 | low = 0; | ||
443 | high = GET_MED (0) - 1; | ||
444 | DEC_MED0 (); | ||
445 | } | ||
446 | else { | ||
447 | low = GET_MED (0); | ||
448 | INC_MED0 (); | ||
449 | |||
450 | if (ones_count == 1) { | ||
451 | high = low + GET_MED (1) - 1; | ||
452 | DEC_MED1 (); | ||
453 | } | ||
454 | else { | ||
455 | low += GET_MED (1); | ||
456 | INC_MED1 (); | ||
457 | |||
458 | if (ones_count == 2) { | ||
459 | high = low + GET_MED (2) - 1; | ||
460 | DEC_MED2 (); | ||
461 | } | ||
462 | else { | ||
463 | low += (ones_count - 2) * GET_MED (2); | ||
464 | high = low + GET_MED (2) - 1; | ||
465 | INC_MED2 (); | ||
466 | } | ||
467 | } | ||
468 | } | ||
469 | |||
470 | mid = (high + low + 1) >> 1; | ||
471 | |||
472 | if (!c->error_limit) | ||
473 | mid = read_code (bs, high - low) + low; | ||
474 | else while (high - low > c->error_limit) { | ||
475 | if (getbit (bs)) | ||
476 | mid = (high + (low = mid) + 1) >> 1; | ||
477 | else | ||
478 | mid = ((high = mid - 1) + low + 1) >> 1; | ||
479 | } | ||
480 | |||
481 | *buffer++ = getbit (bs) ? ~mid : mid; | ||
482 | |||
483 | if (flags & HYBRID_BITRATE) | ||
484 | c->slow_level = c->slow_level - ((c->slow_level + SLO) >> SLS) + mylog2 (mid); | ||
485 | } | ||
486 | |||
487 | return (flags & MONO_DATA) ? csamples : (csamples / 2); | ||
488 | } | ||
489 | |||
490 | // Read a single unsigned value from the specified bitstream with a value | ||
491 | // from 0 to maxcode. If there are exactly a power of two number of possible | ||
492 | // codes then this will read a fixed number of bits; otherwise it reads the | ||
493 | // minimum number of bits and then determines whether another bit is needed | ||
494 | // to define the code. | ||
495 | |||
496 | static uint32_t read_code (Bitstream *bs, uint32_t maxcode) | ||
497 | { | ||
498 | int bitcount = count_bits (maxcode); | ||
499 | uint32_t extras = (1L << bitcount) - maxcode - 1, code; | ||
500 | |||
501 | if (!bitcount) | ||
502 | return 0; | ||
503 | |||
504 | getbits (&code, bitcount - 1, bs); | ||
505 | code &= (1L << (bitcount - 1)) - 1; | ||
506 | |||
507 | if (code >= extras) { | ||
508 | code = (code << 1) - extras; | ||
509 | |||
510 | if (getbit (bs)) | ||
511 | ++code; | ||
512 | } | ||
513 | |||
514 | return code; | ||
515 | } | ||
516 | |||
517 | void send_words (int32_t *buffer, int nsamples, uint32_t flags, | ||
518 | struct words_data *w, Bitstream *bs) | ||
519 | { | ||
520 | register struct entropy_data *c = w->c; | ||
521 | |||
522 | if (!(flags & MONO_FLAG)) | ||
523 | nsamples *= 2; | ||
524 | |||
525 | while (nsamples--) { | ||
526 | int32_t value = *buffer++; | ||
527 | int sign = (value < 0) ? 1 : 0; | ||
528 | uint32_t ones_count, low, high; | ||
529 | |||
530 | if (!(flags & MONO_FLAG)) | ||
531 | c = w->c + (~nsamples & 1); | ||
532 | |||
533 | if (!(w->c [0].median [0] & ~1) && !w->holding_zero && !(w->c [1].median [0] & ~1)) { | ||
534 | if (w->zeros_acc) { | ||
535 | if (value) | ||
536 | flush_word (w, bs); | ||
537 | else { | ||
538 | w->zeros_acc++; | ||
539 | continue; | ||
540 | } | ||
541 | } | ||
542 | else if (value) { | ||
543 | putbit_0 (bs); | ||
544 | } | ||
545 | else { | ||
546 | CLEAR (w->c [0].median); | ||
547 | CLEAR (w->c [1].median); | ||
548 | w->zeros_acc = 1; | ||
549 | continue; | ||
550 | } | ||
551 | } | ||
552 | |||
553 | if (sign) | ||
554 | value = ~value; | ||
555 | |||
556 | if ((uint32_t) value < GET_MED (0)) { | ||
557 | ones_count = low = 0; | ||
558 | high = GET_MED (0) - 1; | ||
559 | DEC_MED0 (); | ||
560 | } | ||
561 | else { | ||
562 | low = GET_MED (0); | ||
563 | INC_MED0 (); | ||
564 | |||
565 | if (value - low < GET_MED (1)) { | ||
566 | ones_count = 1; | ||
567 | high = low + GET_MED (1) - 1; | ||
568 | DEC_MED1 (); | ||
569 | } | ||
570 | else { | ||
571 | low += GET_MED (1); | ||
572 | INC_MED1 (); | ||
573 | |||
574 | if (value - low < GET_MED (2)) { | ||
575 | ones_count = 2; | ||
576 | high = low + GET_MED (2) - 1; | ||
577 | DEC_MED2 (); | ||
578 | } | ||
579 | else { | ||
580 | ones_count = 2 + (value - low) / GET_MED (2); | ||
581 | low += (ones_count - 2) * GET_MED (2); | ||
582 | high = low + GET_MED (2) - 1; | ||
583 | INC_MED2 (); | ||
584 | } | ||
585 | } | ||
586 | } | ||
587 | |||
588 | if (w->holding_zero) { | ||
589 | if (ones_count) | ||
590 | w->holding_one++; | ||
591 | |||
592 | flush_word (w, bs); | ||
593 | |||
594 | if (ones_count) { | ||
595 | w->holding_zero = 1; | ||
596 | ones_count--; | ||
597 | } | ||
598 | else | ||
599 | w->holding_zero = 0; | ||
600 | } | ||
601 | else | ||
602 | w->holding_zero = 1; | ||
603 | |||
604 | w->holding_one = ones_count * 2; | ||
605 | |||
606 | if (high != low) { | ||
607 | uint32_t maxcode = high - low, code = value - low; | ||
608 | int bitcount = count_bits (maxcode); | ||
609 | uint32_t extras = (1L << bitcount) - maxcode - 1; | ||
610 | |||
611 | if (code < extras) { | ||
612 | w->pend_data |= code << w->pend_count; | ||
613 | w->pend_count += bitcount - 1; | ||
614 | } | ||
615 | else { | ||
616 | w->pend_data |= ((code + extras) >> 1) << w->pend_count; | ||
617 | w->pend_count += bitcount - 1; | ||
618 | w->pend_data |= ((code + extras) & 1) << w->pend_count++; | ||
619 | } | ||
620 | } | ||
621 | |||
622 | w->pend_data |= ((int32_t) sign << w->pend_count++); | ||
623 | |||
624 | if (!w->holding_zero) | ||
625 | flush_word (w, bs); | ||
626 | } | ||
627 | } | ||
628 | |||
629 | // Used by send_word() and send_word_lossless() to actually send most the | ||
630 | // accumulated data onto the bitstream. This is also called directly from | ||
631 | // clients when all words have been sent. | ||
632 | |||
633 | void flush_word (struct words_data *w, Bitstream *bs) | ||
634 | { | ||
635 | int cbits; | ||
636 | |||
637 | if (w->zeros_acc) { | ||
638 | cbits = count_bits (w->zeros_acc); | ||
639 | |||
640 | while (cbits--) { | ||
641 | putbit_1 (bs); | ||
642 | } | ||
643 | |||
644 | putbit_0 (bs); | ||
645 | |||
646 | while (w->zeros_acc > 1) { | ||
647 | putbit (w->zeros_acc & 1, bs); | ||
648 | w->zeros_acc >>= 1; | ||
649 | } | ||
650 | |||
651 | w->zeros_acc = 0; | ||
652 | } | ||
653 | |||
654 | if (w->holding_one) { | ||
655 | if (w->holding_one >= LIMIT_ONES) { | ||
656 | putbits ((1L << LIMIT_ONES) - 1, LIMIT_ONES + 1, bs); | ||
657 | w->holding_one -= LIMIT_ONES; | ||
658 | cbits = count_bits (w->holding_one); | ||
659 | |||
660 | while (cbits--) { | ||
661 | putbit_1 (bs); | ||
662 | } | ||
663 | |||
664 | putbit_0 (bs); | ||
665 | |||
666 | while (w->holding_one > 1) { | ||
667 | putbit (w->holding_one & 1, bs); | ||
668 | w->holding_one >>= 1; | ||
669 | } | ||
670 | |||
671 | w->holding_zero = 0; | ||
672 | } | ||
673 | else | ||
674 | putbits ((1L << w->holding_one) - 1, w->holding_one, bs); | ||
675 | |||
676 | w->holding_one = 0; | ||
677 | } | ||
678 | |||
679 | if (w->holding_zero) { | ||
680 | putbit_0 (bs); | ||
681 | w->holding_zero = 0; | ||
682 | } | ||
683 | |||
684 | if (w->pend_count) { | ||
685 | |||
686 | while (w->pend_count > 24) { | ||
687 | putbit (w->pend_data & 1, bs); | ||
688 | w->pend_data >>= 1; | ||
689 | w->pend_count--; | ||
690 | } | ||
691 | |||
692 | putbits (w->pend_data, w->pend_count, bs); | ||
693 | w->pend_data = w->pend_count = 0; | ||
694 | } | ||
695 | } | ||
696 | |||
697 | // The concept of a base 2 logarithm is used in many parts of WavPack. It is | ||
698 | // a way of sufficiently accurately representing 32-bit signed and unsigned | ||
699 | // values storing only 16 bits (actually fewer). It is also used in the hybrid | ||
700 | // mode for quickly comparing the relative magnitude of large values (i.e. | ||
701 | // division) and providing smooth exponentials using only addition. | ||
702 | |||
703 | // These are not strict logarithms in that they become linear around zero and | ||
704 | // can therefore represent both zero and negative values. They have 8 bits | ||
705 | // of precision and in "roundtrip" conversions the total error never exceeds 1 | ||
706 | // part in 225 except for the cases of +/-115 and +/-195 (which error by 1). | ||
707 | |||
708 | |||
709 | // This function returns the log2 for the specified 32-bit unsigned value. | ||
710 | // The maximum value allowed is about 0xff800000 and returns 8447. | ||
711 | |||
712 | static int mylog2 (uint32_t avalue) | ||
713 | { | ||
714 | int dbits; | ||
715 | |||
716 | if ((avalue += avalue >> 9) < (1 << 8)) { | ||
717 | dbits = nbits_table [avalue]; | ||
718 | return (dbits << 8) + log2_table [(avalue << (9 - dbits)) & 0xff]; | ||
719 | } | ||
720 | else { | ||
721 | if (avalue < (1L << 16)) | ||
722 | dbits = nbits_table [avalue >> 8] + 8; | ||
723 | else if (avalue < (1L << 24)) | ||
724 | dbits = nbits_table [avalue >> 16] + 16; | ||
725 | else | ||
726 | dbits = nbits_table [avalue >> 24] + 24; | ||
727 | |||
728 | return (dbits << 8) + log2_table [(avalue >> (dbits - 9)) & 0xff]; | ||
729 | } | ||
730 | } | ||
731 | |||
732 | // This function returns the log2 for the specified 32-bit signed value. | ||
733 | // All input values are valid and the return values are in the range of | ||
734 | // +/- 8192. | ||
735 | |||
736 | int log2s (int32_t value) | ||
737 | { | ||
738 | return (value < 0) ? -mylog2 (-value) : mylog2 (value); | ||
739 | } | ||
740 | |||
741 | // This function returns the original integer represented by the supplied | ||
742 | // logarithm (at least within the provided accuracy). The log is signed, | ||
743 | // but since a full 32-bit value is returned this can be used for unsigned | ||
744 | // conversions as well (i.e. the input range is -8192 to +8447). | ||
745 | |||
746 | int32_t exp2s (int log) | ||
747 | { | ||
748 | uint32_t value; | ||
749 | |||
750 | if (log < 0) | ||
751 | return -exp2s (-log); | ||
752 | |||
753 | value = exp2_table [log & 0xff] | 0x100; | ||
754 | |||
755 | if ((log >>= 8) <= 9) | ||
756 | return value >> (9 - log); | ||
757 | else | ||
758 | return value << (log - 9); | ||
759 | } | ||
760 | |||
761 | // These two functions convert internal weights (which are normally +/-1024) | ||
762 | // to and from an 8-bit signed character version for storage in metadata. The | ||
763 | // weights are clipped here in the case that they are outside that range. | ||
764 | |||
765 | signed char store_weight (int weight) | ||
766 | { | ||
767 | if (weight > 1024) | ||
768 | weight = 1024; | ||
769 | else if (weight < -1024) | ||
770 | weight = -1024; | ||
771 | |||
772 | if (weight > 0) | ||
773 | weight -= (weight + 64) >> 7; | ||
774 | |||
775 | return (weight + 4) >> 3; | ||
776 | } | ||
777 | |||
778 | int restore_weight (signed char weight) | ||
779 | { | ||
780 | int result; | ||
781 | |||
782 | if ((result = (int) weight << 3) > 0) | ||
783 | result += (result + 64) >> 7; | ||
784 | |||
785 | return result; | ||
786 | } | ||
diff --git a/lib/rbcodec/codecs/libwavpack/wputils.c b/lib/rbcodec/codecs/libwavpack/wputils.c new file mode 100644 index 0000000000..b0ccd3ba83 --- /dev/null +++ b/lib/rbcodec/codecs/libwavpack/wputils.c | |||
@@ -0,0 +1,555 @@ | |||
1 | //////////////////////////////////////////////////////////////////////////// | ||
2 | // **** WAVPACK **** // | ||
3 | // Hybrid Lossless Wavefile Compressor // | ||
4 | // Copyright (c) 1998 - 2004 Conifer Software. // | ||
5 | // All Rights Reserved. // | ||
6 | // Distributed under the BSD Software License (see license.txt) // | ||
7 | //////////////////////////////////////////////////////////////////////////// | ||
8 | |||
9 | // wputils.c | ||
10 | |||
11 | // This module provides a high-level interface for decoding WavPack 4.0 audio | ||
12 | // streams and files. WavPack data is read with a stream reading callback. No | ||
13 | // direct seeking is provided for, but it is possible to start decoding | ||
14 | // anywhere in a WavPack stream. In this case, WavPack will be able to provide | ||
15 | // the sample-accurate position when it synchs with the data and begins | ||
16 | // decoding. | ||
17 | |||
18 | #include "wavpack.h" | ||
19 | |||
20 | #include <string.h> | ||
21 | |||
22 | static void strcpy_loc (char *dst, char *src) { while ((*dst++ = *src++) != 0); } | ||
23 | |||
24 | ///////////////////////////// local table storage //////////////////////////// | ||
25 | |||
26 | const uint32_t sample_rates [] = { 6000, 8000, 9600, 11025, 12000, 16000, 22050, | ||
27 | 24000, 32000, 44100, 48000, 64000, 88200, 96000, 192000 }; | ||
28 | |||
29 | ///////////////////////////// executable code //////////////////////////////// | ||
30 | |||
31 | static uint32_t read_next_header (read_stream infile, WavpackHeader *wphdr); | ||
32 | |||
33 | // This function reads data from the specified stream in search of a valid | ||
34 | // WavPack 4.0 audio block. If this fails in 1 megabyte (or an invalid or | ||
35 | // unsupported WavPack block is encountered) then an appropriate message is | ||
36 | // copied to "error" and NULL is returned, otherwise a pointer to a | ||
37 | // WavpackContext structure is returned (which is used to call all other | ||
38 | // functions in this module). This can be initiated at the beginning of a | ||
39 | // WavPack file, or anywhere inside a WavPack file. To determine the exact | ||
40 | // position within the file use WavpackGetSampleIndex(). For demonstration | ||
41 | // purposes this uses a single static copy of the WavpackContext structure, | ||
42 | // so obviously it cannot be used for more than one file at a time. Also, | ||
43 | // this function will not handle "correction" files, plays only the first | ||
44 | // two channels of multi-channel files, and is limited in resolution in some | ||
45 | // large integer or floating point files (but always provides at least 24 bits | ||
46 | // of resolution). | ||
47 | |||
48 | static WavpackContext wpc IBSS_ATTR; | ||
49 | |||
50 | WavpackContext *WavpackOpenFileInput (read_stream infile, char *error) | ||
51 | { | ||
52 | WavpackStream *wps = &wpc.stream; | ||
53 | uint32_t bcount; | ||
54 | |||
55 | CLEAR (wpc); | ||
56 | wpc.infile = infile; | ||
57 | wpc.total_samples = (uint32_t) -1; | ||
58 | wpc.norm_offset = 0; | ||
59 | wpc.open_flags = 0; | ||
60 | |||
61 | // open the source file for reading and store the size | ||
62 | |||
63 | while (!wps->wphdr.block_samples) { | ||
64 | |||
65 | bcount = read_next_header (wpc.infile, &wps->wphdr); | ||
66 | |||
67 | if (bcount == (uint32_t) -1) { | ||
68 | strcpy_loc (error, "invalid WavPack file!"); | ||
69 | return NULL; | ||
70 | } | ||
71 | |||
72 | wps->block_bytes_left = wps->wphdr.ckSize - 24; | ||
73 | |||
74 | if ((wps->wphdr.flags & UNKNOWN_FLAGS) || wps->wphdr.version < MIN_STREAM_VERS || | ||
75 | wps->wphdr.version > MAX_STREAM_VERS) { | ||
76 | strcpy_loc (error, "invalid WavPack file!"); | ||
77 | return NULL; | ||
78 | } | ||
79 | |||
80 | if (wps->wphdr.block_samples && wps->wphdr.total_samples != (uint32_t) -1) | ||
81 | wpc.total_samples = wps->wphdr.total_samples; | ||
82 | |||
83 | if (!unpack_init (&wpc)) { | ||
84 | strcpy_loc (error, wpc.error_message [0] ? wpc.error_message : | ||
85 | "invalid WavPack file!"); | ||
86 | |||
87 | return NULL; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | wpc.config.flags &= ~0xff; | ||
92 | wpc.config.flags |= wps->wphdr.flags & 0xff; | ||
93 | wpc.config.bytes_per_sample = (wps->wphdr.flags & BYTES_STORED) + 1; | ||
94 | wpc.config.float_norm_exp = wps->float_norm_exp; | ||
95 | |||
96 | wpc.config.bits_per_sample = (wpc.config.bytes_per_sample * 8) - | ||
97 | ((wps->wphdr.flags & SHIFT_MASK) >> SHIFT_LSB); | ||
98 | |||
99 | if (!wpc.config.sample_rate) { | ||
100 | if (!wps || !wps->wphdr.block_samples || (wps->wphdr.flags & SRATE_MASK) == SRATE_MASK) | ||
101 | wpc.config.sample_rate = 44100; | ||
102 | else | ||
103 | wpc.config.sample_rate = sample_rates [(wps->wphdr.flags & SRATE_MASK) >> SRATE_LSB]; | ||
104 | } | ||
105 | |||
106 | if (!wpc.config.num_channels) { | ||
107 | wpc.config.num_channels = (wps->wphdr.flags & MONO_FLAG) ? 1 : 2; | ||
108 | wpc.config.channel_mask = 0x5 - wpc.config.num_channels; | ||
109 | } | ||
110 | |||
111 | if (!(wps->wphdr.flags & FINAL_BLOCK)) | ||
112 | wpc.reduced_channels = (wps->wphdr.flags & MONO_FLAG) ? 1 : 2; | ||
113 | |||
114 | return &wpc; | ||
115 | } | ||
116 | |||
117 | // This function obtains general information about an open file and returns | ||
118 | // a mask with the following bit values: | ||
119 | |||
120 | // MODE_LOSSLESS: file is lossless (pure lossless only) | ||
121 | // MODE_HYBRID: file is hybrid mode (lossy part only) | ||
122 | // MODE_FLOAT: audio data is 32-bit ieee floating point | ||
123 | // MODE_HIGH: file was created in "high" mode (information only) | ||
124 | // MODE_FAST: file was created in "fast" mode (information only) | ||
125 | |||
126 | int WavpackGetMode (WavpackContext *wpc) | ||
127 | { | ||
128 | int mode = 0; | ||
129 | |||
130 | if (wpc) { | ||
131 | if (wpc->config.flags & CONFIG_HYBRID_FLAG) | ||
132 | mode |= MODE_HYBRID; | ||
133 | else if (!(wpc->config.flags & CONFIG_LOSSY_MODE)) | ||
134 | mode |= MODE_LOSSLESS; | ||
135 | |||
136 | if (wpc->lossy_blocks) | ||
137 | mode &= ~MODE_LOSSLESS; | ||
138 | |||
139 | if (wpc->config.flags & CONFIG_FLOAT_DATA) | ||
140 | mode |= MODE_FLOAT; | ||
141 | |||
142 | if (wpc->config.flags & CONFIG_HIGH_FLAG) | ||
143 | mode |= MODE_HIGH; | ||
144 | |||
145 | if (wpc->config.flags & CONFIG_FAST_FLAG) | ||
146 | mode |= MODE_FAST; | ||
147 | } | ||
148 | |||
149 | return mode; | ||
150 | } | ||
151 | |||
152 | // Unpack the specified number of samples from the current file position. | ||
153 | // Note that "samples" here refers to "complete" samples, which would be | ||
154 | // 2 int32_t's for stereo files. The audio data is returned right-justified in | ||
155 | // 32-bit int32_t's in the endian mode native to the executing processor. So, | ||
156 | // if the original data was 16-bit, then the values returned would be | ||
157 | // +/-32k. Floating point data can also be returned if the source was | ||
158 | // floating point data (and this is normalized to +/-1.0). The actual number | ||
159 | // of samples unpacked is returned, which should be equal to the number | ||
160 | // requested unless the end of fle is encountered or an error occurs. | ||
161 | |||
162 | uint32_t WavpackUnpackSamples (WavpackContext *wpc, int32_t *buffer, uint32_t samples) | ||
163 | { | ||
164 | WavpackStream *wps = &wpc->stream; | ||
165 | uint32_t bcount, samples_unpacked = 0, samples_to_unpack; | ||
166 | int num_channels = wpc->config.num_channels; | ||
167 | |||
168 | while (samples) { | ||
169 | if (!wps->wphdr.block_samples || !(wps->wphdr.flags & INITIAL_BLOCK) || | ||
170 | wps->sample_index >= wps->wphdr.block_index + wps->wphdr.block_samples) { | ||
171 | bcount = read_next_header (wpc->infile, &wps->wphdr); | ||
172 | |||
173 | if (bcount == (uint32_t) -1) | ||
174 | break; | ||
175 | |||
176 | wps->block_bytes_left = wps->wphdr.ckSize - 24; | ||
177 | |||
178 | if (wps->wphdr.version < MIN_STREAM_VERS || wps->wphdr.version > MAX_STREAM_VERS) { | ||
179 | strcpy_loc (wpc->error_message, "invalid WavPack file!"); | ||
180 | break; | ||
181 | } | ||
182 | |||
183 | if (!wps->wphdr.block_samples || wps->sample_index == wps->wphdr.block_index) | ||
184 | if (!unpack_init (wpc)) | ||
185 | break; | ||
186 | } | ||
187 | |||
188 | if (!wps->wphdr.block_samples || !(wps->wphdr.flags & INITIAL_BLOCK) || | ||
189 | wps->sample_index >= wps->wphdr.block_index + wps->wphdr.block_samples) | ||
190 | continue; | ||
191 | |||
192 | if (wps->sample_index < wps->wphdr.block_index) { | ||
193 | samples_to_unpack = wps->wphdr.block_index - wps->sample_index; | ||
194 | |||
195 | if (samples_to_unpack > samples) | ||
196 | samples_to_unpack = samples; | ||
197 | |||
198 | wps->sample_index += samples_to_unpack; | ||
199 | samples_unpacked += samples_to_unpack; | ||
200 | samples -= samples_to_unpack; | ||
201 | |||
202 | if (wpc->reduced_channels) | ||
203 | samples_to_unpack *= wpc->reduced_channels; | ||
204 | else | ||
205 | samples_to_unpack *= num_channels; | ||
206 | |||
207 | while (samples_to_unpack--) | ||
208 | *buffer++ = 0; | ||
209 | |||
210 | continue; | ||
211 | } | ||
212 | |||
213 | samples_to_unpack = wps->wphdr.block_index + wps->wphdr.block_samples - wps->sample_index; | ||
214 | |||
215 | if (samples_to_unpack > samples) | ||
216 | samples_to_unpack = samples; | ||
217 | |||
218 | unpack_samples (wpc, buffer, samples_to_unpack); | ||
219 | |||
220 | if (wpc->reduced_channels) | ||
221 | buffer += samples_to_unpack * wpc->reduced_channels; | ||
222 | else | ||
223 | buffer += samples_to_unpack * num_channels; | ||
224 | |||
225 | samples_unpacked += samples_to_unpack; | ||
226 | samples -= samples_to_unpack; | ||
227 | |||
228 | if (wps->sample_index == wps->wphdr.block_index + wps->wphdr.block_samples) { | ||
229 | if (check_crc_error (wpc)) | ||
230 | wpc->crc_errors++; | ||
231 | } | ||
232 | |||
233 | if (wps->sample_index == wpc->total_samples) | ||
234 | break; | ||
235 | } | ||
236 | |||
237 | return samples_unpacked; | ||
238 | } | ||
239 | |||
240 | // Get total number of samples contained in the WavPack file, or -1 if unknown | ||
241 | |||
242 | uint32_t WavpackGetNumSamples (WavpackContext *wpc) | ||
243 | { | ||
244 | return wpc ? wpc->total_samples : (uint32_t) -1; | ||
245 | } | ||
246 | |||
247 | // Get the current sample index position, or -1 if unknown | ||
248 | |||
249 | uint32_t WavpackGetSampleIndex (WavpackContext *wpc) | ||
250 | { | ||
251 | if (wpc) | ||
252 | return wpc->stream.sample_index; | ||
253 | |||
254 | return (uint32_t) -1; | ||
255 | } | ||
256 | |||
257 | // Get the number of errors encountered so far | ||
258 | |||
259 | int WavpackGetNumErrors (WavpackContext *wpc) | ||
260 | { | ||
261 | return wpc ? wpc->crc_errors : 0; | ||
262 | } | ||
263 | |||
264 | // return TRUE if any uncorrected lossy blocks were actually written or read | ||
265 | |||
266 | int WavpackLossyBlocks (WavpackContext *wpc) | ||
267 | { | ||
268 | return wpc ? wpc->lossy_blocks : 0; | ||
269 | } | ||
270 | |||
271 | // Returns the sample rate of the specified WavPack file | ||
272 | |||
273 | uint32_t WavpackGetSampleRate (WavpackContext *wpc) | ||
274 | { | ||
275 | return wpc ? wpc->config.sample_rate : 44100; | ||
276 | } | ||
277 | |||
278 | // Returns the number of channels of the specified WavPack file. Note that | ||
279 | // this is the actual number of channels contained in the file, but this | ||
280 | // version can only decode the first two. | ||
281 | |||
282 | int WavpackGetNumChannels (WavpackContext *wpc) | ||
283 | { | ||
284 | return wpc ? wpc->config.num_channels : 2; | ||
285 | } | ||
286 | |||
287 | // Returns the actual number of valid bits per sample contained in the | ||
288 | // original file, which may or may not be a multiple of 8. Floating data | ||
289 | // always has 32 bits, integers may be from 1 to 32 bits each. When this | ||
290 | // value is not a multiple of 8, then the "extra" bits are located in the | ||
291 | // LSBs of the results. That is, values are right justified when unpacked | ||
292 | // into int32_t's, but are left justified in the number of bytes used by the | ||
293 | // original data. | ||
294 | |||
295 | int WavpackGetBitsPerSample (WavpackContext *wpc) | ||
296 | { | ||
297 | return wpc ? wpc->config.bits_per_sample : 16; | ||
298 | } | ||
299 | |||
300 | // Returns the number of bytes used for each sample (1 to 4) in the original | ||
301 | // file. This is required information for the user of this module because the | ||
302 | // audio data is returned in the LOWER bytes of the int32_t buffer and must be | ||
303 | // left-shifted 8, 16, or 24 bits if normalized int32_t's are required. | ||
304 | |||
305 | int WavpackGetBytesPerSample (WavpackContext *wpc) | ||
306 | { | ||
307 | return wpc ? wpc->config.bytes_per_sample : 2; | ||
308 | } | ||
309 | |||
310 | // This function will return the actual number of channels decoded from the | ||
311 | // file (which may or may not be less than the actual number of channels, but | ||
312 | // will always be 1 or 2). Normally, this will be the front left and right | ||
313 | // channels of a multi-channel file. | ||
314 | |||
315 | int WavpackGetReducedChannels (WavpackContext *wpc) | ||
316 | { | ||
317 | if (wpc) | ||
318 | return wpc->reduced_channels ? wpc->reduced_channels : wpc->config.num_channels; | ||
319 | else | ||
320 | return 2; | ||
321 | } | ||
322 | |||
323 | // Read from current file position until a valid 32-byte WavPack 4.0 header is | ||
324 | // found and read into the specified pointer. The number of bytes skipped is | ||
325 | // returned. If no WavPack header is found within 1 meg, then a -1 is returned | ||
326 | // to indicate the error. No additional bytes are read past the header and it | ||
327 | // is returned in the processor's native endian mode. Seeking is not required. | ||
328 | |||
329 | static uint32_t read_next_header (read_stream infile, WavpackHeader *wphdr) | ||
330 | { | ||
331 | char buffer [sizeof (*wphdr)], *sp = buffer + sizeof (*wphdr), *ep = sp; | ||
332 | uint32_t bytes_skipped = 0; | ||
333 | int bleft; | ||
334 | |||
335 | while (1) { | ||
336 | if (sp < ep) { | ||
337 | bleft = ep - sp; | ||
338 | memcpy (buffer, sp, bleft); | ||
339 | } | ||
340 | else | ||
341 | bleft = 0; | ||
342 | |||
343 | if (infile (buffer + bleft, sizeof (*wphdr) - bleft) != (int32_t) sizeof (*wphdr) - bleft) | ||
344 | return -1; | ||
345 | |||
346 | sp = buffer; | ||
347 | |||
348 | if (*sp++ == 'w' && *sp == 'v' && *++sp == 'p' && *++sp == 'k' && | ||
349 | !(*++sp & 1) && sp [2] < 16 && !sp [3] && sp [5] == 4 && | ||
350 | sp [4] >= (MIN_STREAM_VERS & 0xff) && sp [4] <= (MAX_STREAM_VERS & 0xff)) { | ||
351 | memcpy (wphdr, buffer, sizeof (*wphdr)); | ||
352 | little_endian_to_native (wphdr, WavpackHeaderFormat); | ||
353 | return bytes_skipped; | ||
354 | } | ||
355 | |||
356 | while (sp < ep && *sp != 'w') | ||
357 | sp++; | ||
358 | |||
359 | if ((bytes_skipped += sp - buffer) > 1024 * 1024) | ||
360 | return -1; | ||
361 | } | ||
362 | } | ||
363 | |||
364 | // Open context for writing WavPack files. The returned context pointer is used | ||
365 | // in all following calls to the library. A return value of NULL indicates | ||
366 | // that memory could not be allocated for the context. | ||
367 | |||
368 | WavpackContext *WavpackOpenFileOutput (void) | ||
369 | { | ||
370 | CLEAR (wpc); | ||
371 | return &wpc; | ||
372 | } | ||
373 | |||
374 | // Set configuration for writing WavPack files. This must be done before | ||
375 | // sending any actual samples, however it is okay to send wrapper or other | ||
376 | // metadata before calling this. The "config" structure contains the following | ||
377 | // required information: | ||
378 | |||
379 | // config->bytes_per_sample see WavpackGetBytesPerSample() for info | ||
380 | // config->bits_per_sample see WavpackGetBitsPerSample() for info | ||
381 | // config->num_channels self evident | ||
382 | // config->sample_rate self evident | ||
383 | |||
384 | // In addition, the following fields and flags may be set: | ||
385 | |||
386 | // config->flags: | ||
387 | // -------------- | ||
388 | // o CONFIG_HYBRID_FLAG select hybrid mode (must set bitrate) | ||
389 | // o CONFIG_JOINT_STEREO select joint stereo (must set override also) | ||
390 | // o CONFIG_JOINT_OVERRIDE override default joint stereo selection | ||
391 | // o CONFIG_HYBRID_SHAPE select hybrid noise shaping (set override & | ||
392 | // shaping_weight != 0.0) | ||
393 | // o CONFIG_SHAPE_OVERRIDE override default hybrid noise shaping | ||
394 | // (set CONFIG_HYBRID_SHAPE and shaping_weight) | ||
395 | // o CONFIG_FAST_FLAG "fast" compression mode | ||
396 | // o CONFIG_HIGH_FLAG "high" compression mode | ||
397 | // o CONFIG_BITRATE_KBPS hybrid bitrate is kbps, not bits / sample | ||
398 | |||
399 | // config->bitrate hybrid bitrate in either bits/sample or kbps | ||
400 | // config->shaping_weight hybrid noise shaping coefficient override | ||
401 | // config->float_norm_exp select floating-point data (127 for +/-1.0) | ||
402 | |||
403 | // If the number of samples to be written is known then it should be passed | ||
404 | // here. If the duration is not known then pass -1. In the case that the size | ||
405 | // is not known (or the writing is terminated early) then it is suggested that | ||
406 | // the application retrieve the first block written and let the library update | ||
407 | // the total samples indication. A function is provided to do this update and | ||
408 | // it should be done to the "correction" file also. If this cannot be done | ||
409 | // (because a pipe is being used, for instance) then a valid WavPack will still | ||
410 | // be created, but when applications want to access that file they will have | ||
411 | // to seek all the way to the end to determine the actual duration. Also, if | ||
412 | // a RIFF header has been included then it should be updated as well or the | ||
413 | // WavPack file will not be directly unpackable to a valid wav file (although | ||
414 | // it will still be usable by itself). A return of FALSE indicates an error. | ||
415 | |||
416 | int WavpackSetConfiguration (WavpackContext *wpc, WavpackConfig *config, uint32_t total_samples) | ||
417 | { | ||
418 | WavpackStream *wps = &wpc->stream; | ||
419 | uint32_t flags = (config->bytes_per_sample - 1), shift = 0; | ||
420 | int num_chans = config->num_channels; | ||
421 | int i; | ||
422 | |||
423 | if ((wpc->config.flags & CONFIG_HYBRID_FLAG) || | ||
424 | wpc->config.float_norm_exp || | ||
425 | num_chans < 1 || num_chans > 2) | ||
426 | return FALSE; | ||
427 | |||
428 | wpc->total_samples = total_samples; | ||
429 | wpc->config.sample_rate = config->sample_rate; | ||
430 | wpc->config.num_channels = config->num_channels; | ||
431 | wpc->config.bits_per_sample = config->bits_per_sample; | ||
432 | wpc->config.bytes_per_sample = config->bytes_per_sample; | ||
433 | wpc->config.flags = config->flags; | ||
434 | |||
435 | shift = (config->bytes_per_sample * 8) - config->bits_per_sample; | ||
436 | |||
437 | for (i = 0; i < 15; ++i) | ||
438 | if (wpc->config.sample_rate == sample_rates [i]) | ||
439 | break; | ||
440 | |||
441 | flags |= i << SRATE_LSB; | ||
442 | flags |= shift << SHIFT_LSB; | ||
443 | flags |= CROSS_DECORR; | ||
444 | |||
445 | if (!(config->flags & CONFIG_JOINT_OVERRIDE) || (config->flags & CONFIG_JOINT_STEREO)) | ||
446 | flags |= JOINT_STEREO; | ||
447 | |||
448 | flags |= INITIAL_BLOCK | FINAL_BLOCK; | ||
449 | |||
450 | if (num_chans == 1) { | ||
451 | flags &= ~(JOINT_STEREO | CROSS_DECORR | HYBRID_BALANCE); | ||
452 | flags |= MONO_FLAG; | ||
453 | } | ||
454 | |||
455 | flags &= ~MAG_MASK; | ||
456 | flags += (1 << MAG_LSB) * ((flags & BYTES_STORED) * 8 + 7); | ||
457 | |||
458 | memcpy (wps->wphdr.ckID, "wvpk", 4); | ||
459 | wps->wphdr.ckSize = sizeof (WavpackHeader) - 8; | ||
460 | wps->wphdr.total_samples = wpc->total_samples; | ||
461 | wps->wphdr.version = CUR_STREAM_VERS; | ||
462 | wps->wphdr.flags = flags; | ||
463 | |||
464 | pack_init (wpc); | ||
465 | return TRUE; | ||
466 | } | ||
467 | |||
468 | // Add wrapper (currently RIFF only) to WavPack blocks. This should be called | ||
469 | // before sending any audio samples. If the exact contents of the RIFF header | ||
470 | // are not known because, for example, the file duration is uncertain or | ||
471 | // trailing chunks are possible, simply write a "dummy" header of the correct | ||
472 | // length. When all data has been written it will be possible to read the | ||
473 | // first block written and update the header directly. An example of this can | ||
474 | // be found in the Audition filter. | ||
475 | |||
476 | void WavpackAddWrapper (WavpackContext *wpc, void *data, uint32_t bcount) | ||
477 | { | ||
478 | wpc->wrapper_data = data; | ||
479 | wpc->wrapper_bytes = bcount; | ||
480 | } | ||
481 | |||
482 | // Start a WavPack block to be stored in the specified buffer. This must be | ||
483 | // called before calling WavpackPackSamples(). Note that writing CANNOT wrap | ||
484 | // in the buffer; the entire output block must fit in the buffer. | ||
485 | |||
486 | int WavpackStartBlock (WavpackContext *wpc, uchar *begin, uchar *end) | ||
487 | { | ||
488 | wpc->stream.blockbuff = begin; | ||
489 | wpc->stream.blockend = end; | ||
490 | return pack_start_block (wpc); | ||
491 | } | ||
492 | |||
493 | // Pack the specified samples. Samples must be stored in int32_ts in the native | ||
494 | // endian format of the executing processor. The number of samples specified | ||
495 | // indicates composite samples (sometimes called "frames"). So, the actual | ||
496 | // number of data points would be this "sample_count" times the number of | ||
497 | // channels. The caller must decide how many samples to place in each | ||
498 | // WavPack block (1/2 second is common), but this function may be called as | ||
499 | // many times as desired to build the final block (and performs the actual | ||
500 | // compression during the call). A return of FALSE indicates an error. | ||
501 | |||
502 | int WavpackPackSamples (WavpackContext *wpc, int32_t *sample_buffer, uint32_t sample_count) | ||
503 | { | ||
504 | if (!sample_count || pack_samples (wpc, sample_buffer, sample_count)) | ||
505 | return TRUE; | ||
506 | |||
507 | strcpy_loc (wpc->error_message, "output buffer overflowed!"); | ||
508 | return FALSE; | ||
509 | } | ||
510 | |||
511 | // Finish the WavPack block being built, returning the total size of the | ||
512 | // block in bytes. Note that the possible conversion of the WavPack header to | ||
513 | // little-endian takes place here. | ||
514 | |||
515 | uint32_t WavpackFinishBlock (WavpackContext *wpc) | ||
516 | { | ||
517 | WavpackStream *wps = &wpc->stream; | ||
518 | uint32_t bcount; | ||
519 | |||
520 | pack_finish_block (wpc); | ||
521 | bcount = ((WavpackHeader *) wps->blockbuff)->ckSize + 8; | ||
522 | native_to_little_endian ((WavpackHeader *) wps->blockbuff, WavpackHeaderFormat); | ||
523 | |||
524 | return bcount; | ||
525 | } | ||
526 | |||
527 | // Given the pointer to the first block written (to either a .wv or .wvc file), | ||
528 | // update the block with the actual number of samples written. This should | ||
529 | // be done if WavpackSetConfiguration() was called with an incorrect number | ||
530 | // of samples (or -1). It is the responsibility of the application to read and | ||
531 | // rewrite the block. An example of this can be found in the Audition filter. | ||
532 | |||
533 | void WavpackUpdateNumSamples (WavpackContext *wpc, void *first_block) | ||
534 | { | ||
535 | little_endian_to_native (wpc, WavpackHeaderFormat); | ||
536 | ((WavpackHeader *) first_block)->total_samples = WavpackGetSampleIndex (wpc); | ||
537 | native_to_little_endian (wpc, WavpackHeaderFormat); | ||
538 | } | ||
539 | |||
540 | // Given the pointer to the first block written to a WavPack file, this | ||
541 | // function returns the location of the stored RIFF header that was originally | ||
542 | // written with WavpackAddWrapper(). This would normally be used to update | ||
543 | // the wav header to indicate that a different number of samples was actually | ||
544 | // written or if additional RIFF chunks are written at the end of the file. | ||
545 | // It is the responsibility of the application to read and rewrite the block. | ||
546 | // An example of this can be found in the Audition filter. | ||
547 | |||
548 | void *WavpackGetWrapperLocation (void *first_block) | ||
549 | { | ||
550 | if (((uchar *) first_block) [32] == ID_RIFF_HEADER) | ||
551 | return ((uchar *) first_block) + 34; | ||
552 | else | ||
553 | return NULL; | ||
554 | } | ||
555 | |||