Coverage Report

Created: 2023-06-07 06:30

/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
}