Coverage Report

Created: 2025-07-18 06:14

/src/libsndfile/src/ALAC/ag_enc.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2011 Apple Inc. All rights reserved.
3
 * Copyright (C) 2013-2014 Erik de Castro Lopo <erikd@mega-nerd.com>
4
 *
5
 * @APPLE_APACHE_LICENSE_HEADER_START@
6
 *
7
 * Licensed under the Apache License, Version 2.0 (the "License") ;
8
 * you may not use this file except in compliance with the License.
9
 * You may obtain a copy of the License at
10
 *
11
 *   http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 * Unless required by applicable law or agreed to in writing, software
14
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 * See the License for the specific language governing permissions and
17
 * limitations under the License.
18
 *
19
 * @APPLE_APACHE_LICENSE_HEADER_END@
20
 */
21
22
/*
23
  File:   ag_enc.c
24
25
  Contains:   Adaptive Golomb encode routines.
26
27
  Copyright:  (c) 2001-2011 Apple, Inc.
28
*/
29
30
#include "config.h"
31
32
#include "aglib.h"
33
#include "ALACBitUtilities.h"
34
#include "EndianPortable.h"
35
#include "ALACAudioTypes.h"
36
37
#include <math.h>
38
#include <stdio.h>
39
#include <stdlib.h>
40
#include <string.h>
41
42
#define CODE_TO_LONG_MAXBITS  32
43
0
#define N_MAX_MEAN_CLAMP    0xffff
44
0
#define N_MEAN_CLAMP_VAL    0xffff
45
#define REPORT_VAL        40
46
47
#if __GNUC__
48
#define ALWAYS_INLINE   __attribute__ ((always_inline))
49
#elif defined _MSC_VER
50
#define ALWAYS_INLINE   __forceinline
51
#else
52
#define ALWAYS_INLINE
53
#endif
54
55
56
/*  And on the subject of the CodeWarrior x86 compiler and inlining, I reworked a lot of this
57
  to help the compiler out.   In many cases this required manual inlining or a macro.  Sorry
58
  if it is ugly but the performance gains are well worth it.
59
  - WSK 5/19/04
60
*/
61
62
// note: implementing this with some kind of "count leading zeros" assembly is a big performance win
63
static inline int32_t lead (int32_t m)
64
0
{
65
0
  long j ;
66
0
  unsigned long c = (1ul << 31) ;
67
68
0
  for (j = 0 ; j < 32 ; j++)
69
0
  {
70
0
    if ((c & m) != 0)
71
0
      break ;
72
0
    c >>= 1 ;
73
0
  }
74
0
  return j ;
75
0
}
76
77
#define arithmin (a, b) ((a) < (b) ? (a) : (b))
78
79
static inline int32_t ALWAYS_INLINE lg3a (int32_t x)
80
0
{
81
0
  int32_t result ;
82
83
0
  x += 3 ;
84
0
  result = lead (x) ;
85
86
0
  return 31 - result ;
87
0
}
88
89
static inline int32_t ALWAYS_INLINE abs_func (int32_t a)
90
0
{
91
  // note: the CW PPC intrinsic __abs () turns into these instructions so no need to try and use it
92
0
  int32_t isneg = a >> 31 ;
93
0
  int32_t xorval = a ^ isneg ;
94
0
  int32_t result = xorval-isneg ;
95
96
0
  return result ;
97
0
}
98
99
#if PRAGMA_MARK
100
#pragma mark -
101
#endif
102
103
static inline int32_t dyn_code (int32_t m, int32_t k, int32_t n, uint32_t *outNumBits)
104
0
{
105
0
  uint32_t  divx, mod, de ;
106
0
  uint32_t  numBits ;
107
0
  uint32_t  value ;
108
109
  // Assert (n >= 0) ;
110
111
0
  divx = n / m ;
112
113
0
  if (divx >= MAX_PREFIX_16)
114
0
  {
115
0
    numBits = MAX_PREFIX_16 + MAX_DATATYPE_BITS_16 ;
116
0
    value = (((1 << MAX_PREFIX_16) - 1) << MAX_DATATYPE_BITS_16) + n ;
117
0
  }
118
0
  else
119
0
  {
120
0
    mod = n%m ;
121
0
    de = (mod == 0) ;
122
0
    numBits = divx + k + 1 - de ;
123
0
    value = (((1 << divx) - 1) << (numBits - divx)) + mod + 1 - de ;
124
125
    // if coding this way is bigger than doing escape, then do escape
126
0
    if (numBits > MAX_PREFIX_16 + MAX_DATATYPE_BITS_16)
127
0
    {
128
0
      numBits = MAX_PREFIX_16 + MAX_DATATYPE_BITS_16 ;
129
0
      value = (((1 << MAX_PREFIX_16) - 1) << MAX_DATATYPE_BITS_16) + n ;
130
0
    }
131
0
  }
132
133
0
  *outNumBits = numBits ;
134
135
0
  return (int32_t) value ;
136
0
}
137
138
139
static inline int32_t dyn_code_32bit (int32_t maxbits, uint32_t m, uint32_t k, uint32_t n, uint32_t *outNumBits, uint32_t *outValue, uint32_t *overflow, uint32_t *overflowbits)
140
0
{
141
0
  uint32_t  divx, mod, de ;
142
0
  uint32_t  numBits ;
143
0
  uint32_t  value ;
144
0
  int32_t     didOverflow = 0 ;
145
146
0
  divx = n / m ;
147
148
0
  if (divx < MAX_PREFIX_32)
149
0
  {
150
0
    mod = n - (m * divx) ;
151
152
0
    de = (mod == 0) ;
153
0
    numBits = divx + k + 1 - de ;
154
0
    value = (((1 << divx) - 1) << (numBits - divx)) + mod + 1 - de ;
155
0
    if (numBits > 25)
156
0
      goto codeasescape ;
157
0
  }
158
0
  else
159
0
  {
160
0
codeasescape:
161
0
    numBits = MAX_PREFIX_32 ;
162
0
    value = (((1 << MAX_PREFIX_32) - 1)) ;
163
0
    *overflow = n ;
164
0
    *overflowbits = maxbits ;
165
0
    didOverflow = 1 ;
166
0
  }
167
168
0
  *outNumBits = numBits ;
169
0
  *outValue = value ;
170
171
0
  return didOverflow ;
172
0
}
173
174
175
static inline void ALWAYS_INLINE dyn_jam_noDeref (unsigned char *out, uint32_t bitPos, uint32_t numBits, uint32_t value)
176
0
{
177
0
  uint32_t  mask ;
178
0
  uint32_t  curr ;
179
0
  uint32_t  shift ;
180
181
  //Assert (numBits <= 32) ;
182
183
0
  curr = psf_get_be32 (out, bitPos >> 3) ;
184
185
0
  shift = 32 - (bitPos & 7) - numBits ;
186
187
0
  mask = ~0u >> (32 - numBits) ;    // mask must be created in two steps to avoid compiler sequencing ambiguity
188
0
  mask <<= shift ;
189
190
0
  value = (value << shift) & mask ;
191
0
  value |= curr & ~mask ;
192
193
0
  psf_put_be32 (out, bitPos >> 3, value) ;
194
0
}
195
196
197
static inline void ALWAYS_INLINE dyn_jam_noDeref_large (unsigned char *out, uint32_t bitPos, uint32_t numBits, uint32_t value)
198
0
{
199
0
  uint32_t  w ;
200
0
  uint32_t  curr ;
201
0
  uint32_t  mask ;
202
0
  int32_t   shiftvalue = (32 - (bitPos & 7) - numBits) ;
203
204
  //Assert (numBits <= 32) ;
205
206
0
  curr = psf_get_be32 (out, bitPos >> 3) ;
207
208
0
  if (shiftvalue < 0)
209
0
  {
210
0
    uint8_t   tailbyte ;
211
0
    uint8_t   *tailptr ;
212
213
0
    w = value >> -shiftvalue ;
214
0
    mask = ~0u >> -shiftvalue ;
215
0
    w |= (curr & ~mask) ;
216
217
0
    tailptr = out + (bitPos >> 3) + 4 ;
218
0
    tailbyte = (value << ((8+shiftvalue))) & 0xff ;
219
0
    *tailptr = (uint8_t) tailbyte ;
220
0
  }
221
0
  else
222
0
  {
223
0
    mask = ~0u >> (32 - numBits) ;
224
0
    mask <<= shiftvalue ;     // mask must be created in two steps to avoid compiler sequencing ambiguity
225
226
0
    w = (value << shiftvalue) & mask ;
227
0
    w |= curr & ~mask ;
228
0
  }
229
230
0
  psf_put_be32 (out, bitPos >> 3, w) ;
231
0
}
232
233
234
int32_t dyn_comp (AGParamRecPtr params, int32_t * pc, BitBuffer * bitstream, int32_t numSamples, int32_t bitSize, uint32_t * outNumBits)
235
0
{
236
0
  unsigned char *   out ;
237
0
  uint32_t    bitPos, startPos ;
238
0
  uint32_t      m, k, n, c, mz, nz ;
239
0
  uint32_t    numBits ;
240
0
  uint32_t      value ;
241
0
  int32_t       del, zmode ;
242
0
  uint32_t    overflow, overflowbits ;
243
0
  int32_t         status ;
244
245
  // shadow the variables in params so there's not the dereferencing overhead
246
0
  uint32_t    mb, pb, kb, wb ;
247
0
  int32_t         rowPos = 0 ;
248
0
  int32_t         rowSize = params->sw ;
249
0
  int32_t         rowJump = (params->fw) - rowSize ;
250
0
  int32_t *     inPtr = pc ;
251
252
0
  *outNumBits = 0 ;
253
0
  RequireAction ((bitSize >= 1) && (bitSize <= 32), return kALAC_ParamError ;) ;
254
255
0
  out = bitstream->cur ;
256
0
  startPos = bitstream->bitIndex ;
257
0
  bitPos = startPos ;
258
259
0
  mb = params->mb = params->mb0 ;
260
0
  pb = params->pb ;
261
0
  kb = params->kb ;
262
0
  wb = params->wb ;
263
0
  zmode = 0 ;
264
265
0
  c = 0 ;
266
0
  status = ALAC_noErr ;
267
268
0
  while (c < (uint32_t) numSamples)
269
0
  {
270
0
    m = mb >> QBSHIFT ;
271
0
    k = lg3a (m) ;
272
0
    if (k > kb)
273
0
    {
274
0
      k = kb ;
275
0
    }
276
0
    m = (1 << k) - 1 ;
277
278
0
    del = *inPtr++ ;
279
0
    rowPos++ ;
280
281
0
    n = (abs_func (del) << 1) - ((del >> 31) & 1) - zmode ;
282
    //Assert (32-lead (n) <= bitSize) ;
283
284
0
    if (dyn_code_32bit (bitSize, m, k, n, &numBits, &value, &overflow, &overflowbits))
285
0
    {
286
0
      dyn_jam_noDeref (out, bitPos, numBits, value) ;
287
0
      bitPos += numBits ;
288
0
      dyn_jam_noDeref_large (out, bitPos, overflowbits, overflow) ;
289
0
      bitPos += overflowbits ;
290
0
    }
291
0
    else
292
0
    {
293
0
      dyn_jam_noDeref (out, bitPos, numBits, value) ;
294
0
      bitPos += numBits ;
295
0
    }
296
297
0
    c++ ;
298
0
    if (rowPos >= rowSize)
299
0
    {
300
0
      rowPos = 0 ;
301
0
      inPtr += rowJump ;
302
0
    }
303
304
0
    mb = pb * (n + zmode) + mb - ((pb * mb) >> QBSHIFT) ;
305
306
    // update mean tracking if it's overflowed
307
0
    if (n > N_MAX_MEAN_CLAMP)
308
0
      mb = N_MEAN_CLAMP_VAL ;
309
310
0
    zmode = 0 ;
311
312
0
    RequireAction (c <= (uint32_t) numSamples, status = kALAC_ParamError ; goto Exit ;) ;
313
314
0
    if (((mb << MMULSHIFT) < QB) && (c < (uint32_t) numSamples))
315
0
    {
316
0
      zmode = 1 ;
317
0
      nz = 0 ;
318
319
0
      while (c < (uint32_t) numSamples && *inPtr == 0)
320
0
      {
321
        /* Take care of wrap-around globals. */
322
0
        ++inPtr ;
323
0
        ++nz ;
324
0
        ++c ;
325
0
        if (++rowPos >= rowSize)
326
0
        {
327
0
          rowPos = 0 ;
328
0
          inPtr += rowJump ;
329
0
        }
330
331
0
        if (nz >= 65535)
332
0
        {
333
0
          zmode = 0 ;
334
0
          break ;
335
0
        }
336
0
      }
337
338
0
      k = lead (mb) - BITOFF + ((mb + MOFF) >> MDENSHIFT) ;
339
0
      mz = ((1 << k) - 1) & wb ;
340
341
0
      value = dyn_code (mz, k, nz, &numBits) ;
342
0
      dyn_jam_noDeref (out, bitPos, numBits, value) ;
343
0
      bitPos += numBits ;
344
345
0
      mb = 0 ;
346
0
    }
347
0
  }
348
349
0
  *outNumBits = (bitPos - startPos) ;
350
0
  BitBufferAdvance (bitstream, *outNumBits) ;
351
352
0
Exit:
353
0
  return status ;
354
0
}