/src/wavpack/src/decorr_utils.c
Line | Count | Source |
1 | | //////////////////////////////////////////////////////////////////////////// |
2 | | // **** WAVPACK **** // |
3 | | // Hybrid Lossless Wavefile Compressor // |
4 | | // Copyright (c) 1998 - 2013 Conifer Software. // |
5 | | // All Rights Reserved. // |
6 | | // Distributed under the BSD Software License (see license.txt) // |
7 | | //////////////////////////////////////////////////////////////////////////// |
8 | | |
9 | | // decorr_utils.c |
10 | | |
11 | | // This module contains the functions that process metadata blocks that are |
12 | | // specific to the decorrelator. These would be called any time a WavPack |
13 | | // block was parsed. These are in a module separate from the actual unpack |
14 | | // decorrelation code (unpack.c) so that if an application just wants to get |
15 | | // information from WavPack files (rather than actually decoding audio) then |
16 | | // less code needs to be linked. |
17 | | |
18 | | #include <stdlib.h> |
19 | | #include <string.h> |
20 | | |
21 | | #include "wavpack_local.h" |
22 | | |
23 | | ///////////////////////////// executable code //////////////////////////////// |
24 | | |
25 | | // Read decorrelation terms from specified metadata block into the |
26 | | // decorr_passes array. The terms range from -3 to 8, plus 17 & 18; |
27 | | // other values are reserved and generate errors for now. The delta |
28 | | // ranges from 0 to 7 with all values valid. Note that the terms are |
29 | | // stored in the opposite order in the decorr_passes array compared |
30 | | // to packing. |
31 | | |
32 | | int read_decorr_terms (WavpackStream *wps, WavpackMetadata *wpmd) |
33 | 5.23k | { |
34 | 5.23k | int termcnt = wpmd->byte_length; |
35 | 5.23k | unsigned char *byteptr = (unsigned char *)wpmd->data; |
36 | 5.23k | struct decorr_pass *dpp; |
37 | | |
38 | 5.23k | if (termcnt > MAX_NTERMS) |
39 | 222 | return FALSE; |
40 | | |
41 | 5.01k | wps->num_terms = termcnt; |
42 | | |
43 | 16.3k | for (dpp = wps->decorr_passes + termcnt - 1; termcnt--; dpp--) { |
44 | 12.5k | dpp->term = (int)(*byteptr & 0x1f) - 5; |
45 | 12.5k | dpp->delta = (*byteptr++ >> 5) & 0x7; |
46 | | |
47 | 12.5k | if (!dpp->term || dpp->term < -3 || (dpp->term > MAX_TERM && dpp->term < 17) || dpp->term > 18 || |
48 | 12.5k | ((wps->wphdr.flags & MONO_DATA) && dpp->term < 0)) |
49 | 1.18k | return FALSE; |
50 | 12.5k | } |
51 | | |
52 | 3.82k | return TRUE; |
53 | 5.01k | } |
54 | | |
55 | | // Read decorrelation weights from specified metadata block into the |
56 | | // decorr_passes array. The weights range +/-1024, but are rounded and |
57 | | // truncated to fit in signed chars for metadata storage. Weights are |
58 | | // separate for the two channels and are specified from the "last" term |
59 | | // (first during encode). Unspecified weights are set to zero. |
60 | | |
61 | | int read_decorr_weights (WavpackStream *wps, WavpackMetadata *wpmd) |
62 | 1.97k | { |
63 | 1.97k | int termcnt = wpmd->byte_length, tcount; |
64 | 1.97k | char *byteptr = (char *)wpmd->data; |
65 | 1.97k | struct decorr_pass *dpp; |
66 | | |
67 | 1.97k | if (!(wps->wphdr.flags & MONO_DATA)) |
68 | 968 | termcnt /= 2; |
69 | | |
70 | 1.97k | if (termcnt > wps->num_terms) |
71 | 241 | return FALSE; |
72 | | |
73 | 6.99k | for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) |
74 | 5.26k | dpp->weight_A = dpp->weight_B = 0; |
75 | | |
76 | 5.67k | while (--dpp >= wps->decorr_passes && termcnt--) { |
77 | 3.94k | dpp->weight_A = restore_weight (*byteptr++); |
78 | | |
79 | 3.94k | if (!(wps->wphdr.flags & MONO_DATA)) |
80 | 2.47k | dpp->weight_B = restore_weight (*byteptr++); |
81 | 3.94k | } |
82 | | |
83 | 1.73k | return TRUE; |
84 | 1.97k | } |
85 | | |
86 | | // Read decorrelation samples from specified metadata block into the |
87 | | // decorr_passes array. The samples are signed 32-bit values, but are |
88 | | // converted to signed log2 values for storage in metadata. Values are |
89 | | // stored for both channels and are specified from the "last" term |
90 | | // (first during encode) with unspecified samples set to zero. The |
91 | | // number of samples stored varies with the actual term value, so |
92 | | // those must obviously come first in the metadata. |
93 | | |
94 | | int read_decorr_samples (WavpackStream *wps, WavpackMetadata *wpmd) |
95 | 3.65k | { |
96 | 3.65k | unsigned char *byteptr = (unsigned char *)wpmd->data; |
97 | 3.65k | unsigned char *endptr = byteptr + wpmd->byte_length; |
98 | 3.65k | struct decorr_pass *dpp; |
99 | 3.65k | int tcount; |
100 | | |
101 | 12.5k | for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) { |
102 | 8.90k | CLEAR (dpp->samples_A); |
103 | 8.90k | CLEAR (dpp->samples_B); |
104 | 8.90k | } |
105 | | |
106 | 3.65k | if (wps->wphdr.version == 0x402 && (wps->wphdr.flags & HYBRID_FLAG)) { |
107 | 678 | if (byteptr + (wps->wphdr.flags & MONO_DATA ? 2 : 4) > endptr) |
108 | 196 | return FALSE; |
109 | | |
110 | 482 | wps->dc.error [0] = wp_exp2s ((int16_t)(byteptr [0] + (byteptr [1] << 8))); |
111 | 482 | byteptr += 2; |
112 | | |
113 | 482 | if (!(wps->wphdr.flags & MONO_DATA)) { |
114 | 208 | wps->dc.error [1] = wp_exp2s ((int16_t)(byteptr [0] + (byteptr [1] << 8))); |
115 | 208 | byteptr += 2; |
116 | 208 | } |
117 | 482 | } |
118 | | |
119 | 5.68k | while (dpp-- > wps->decorr_passes && byteptr < endptr) |
120 | 3.49k | if (dpp->term > MAX_TERM) { |
121 | 1.29k | if (byteptr + (wps->wphdr.flags & MONO_DATA ? 4 : 8) > endptr) |
122 | 353 | return FALSE; |
123 | | |
124 | 945 | dpp->samples_A [0] = wp_exp2s ((int16_t)(byteptr [0] + (byteptr [1] << 8))); |
125 | 945 | dpp->samples_A [1] = wp_exp2s ((int16_t)(byteptr [2] + (byteptr [3] << 8))); |
126 | 945 | byteptr += 4; |
127 | | |
128 | 945 | if (!(wps->wphdr.flags & MONO_DATA)) { |
129 | 396 | dpp->samples_B [0] = wp_exp2s ((int16_t)(byteptr [0] + (byteptr [1] << 8))); |
130 | 396 | dpp->samples_B [1] = wp_exp2s ((int16_t)(byteptr [2] + (byteptr [3] << 8))); |
131 | 396 | byteptr += 4; |
132 | 396 | } |
133 | 945 | } |
134 | 2.19k | else if (dpp->term < 0) { |
135 | 869 | if (byteptr + 4 > endptr) |
136 | 509 | return FALSE; |
137 | | |
138 | 360 | dpp->samples_A [0] = wp_exp2s ((int16_t)(byteptr [0] + (byteptr [1] << 8))); |
139 | 360 | dpp->samples_B [0] = wp_exp2s ((int16_t)(byteptr [2] + (byteptr [3] << 8))); |
140 | 360 | byteptr += 4; |
141 | 360 | } |
142 | 1.32k | else { |
143 | 1.32k | int m = 0, cnt = dpp->term; |
144 | | |
145 | 3.12k | while (cnt--) { |
146 | 2.20k | if (byteptr + (wps->wphdr.flags & MONO_DATA ? 2 : 4) > endptr) |
147 | 400 | return FALSE; |
148 | | |
149 | 1.80k | dpp->samples_A [m] = wp_exp2s ((int16_t)(byteptr [0] + (byteptr [1] << 8))); |
150 | 1.80k | byteptr += 2; |
151 | | |
152 | 1.80k | if (!(wps->wphdr.flags & MONO_DATA)) { |
153 | 753 | dpp->samples_B [m] = wp_exp2s ((int16_t)(byteptr [0] + (byteptr [1] << 8))); |
154 | 753 | byteptr += 2; |
155 | 753 | } |
156 | | |
157 | 1.80k | m++; |
158 | 1.80k | } |
159 | 1.32k | } |
160 | | |
161 | 2.19k | return byteptr == endptr; |
162 | 3.45k | } |
163 | | |
164 | | // Read the shaping weights from specified metadata block into the |
165 | | // WavpackStream structure. Note that there must be two values (even |
166 | | // for mono streams) and that the values are stored in the same |
167 | | // manner as decorrelation weights. These would normally be read from |
168 | | // the "correction" file and are used for lossless reconstruction of |
169 | | // hybrid data. |
170 | | |
171 | | int read_shaping_info (WavpackStream *wps, WavpackMetadata *wpmd) |
172 | 1.24k | { |
173 | 1.24k | if (wpmd->byte_length == 2) { |
174 | 223 | char *byteptr = (char *)wpmd->data; |
175 | | |
176 | 223 | wps->dc.shaping_acc [0] = (uint32_t) restore_weight (*byteptr++) << 16; |
177 | 223 | wps->dc.shaping_acc [1] = (uint32_t) restore_weight (*byteptr++) << 16; |
178 | 223 | return TRUE; |
179 | 223 | } |
180 | 1.02k | else if (wpmd->byte_length >= (wps->wphdr.flags & MONO_DATA ? 4 : 8)) { |
181 | 820 | unsigned char *byteptr = (unsigned char *)wpmd->data; |
182 | | |
183 | 820 | wps->dc.error [0] = wp_exp2s ((int16_t)(byteptr [0] + (byteptr [1] << 8))); |
184 | 820 | wps->dc.shaping_acc [0] = wp_exp2s ((int16_t)(byteptr [2] + (byteptr [3] << 8))); |
185 | 820 | byteptr += 4; |
186 | | |
187 | 820 | if (!(wps->wphdr.flags & MONO_DATA)) { |
188 | 335 | wps->dc.error [1] = wp_exp2s ((int16_t)(byteptr [0] + (byteptr [1] << 8))); |
189 | 335 | wps->dc.shaping_acc [1] = wp_exp2s ((int16_t)(byteptr [2] + (byteptr [3] << 8))); |
190 | 335 | byteptr += 4; |
191 | 335 | } |
192 | | |
193 | 820 | if (wpmd->byte_length == (wps->wphdr.flags & MONO_DATA ? 6 : 12)) { |
194 | 539 | wps->dc.shaping_delta [0] = wp_exp2s ((int16_t)(byteptr [0] + (byteptr [1] << 8))); |
195 | | |
196 | 539 | if (!(wps->wphdr.flags & MONO_DATA)) |
197 | 292 | wps->dc.shaping_delta [1] = wp_exp2s ((int16_t)(byteptr [2] + (byteptr [3] << 8))); |
198 | 539 | } |
199 | | |
200 | 820 | return TRUE; |
201 | 820 | } |
202 | | |
203 | 200 | return FALSE; |
204 | 1.24k | } |