Coverage Report

Created: 2025-11-11 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libsndfile/src/ima_oki_adpcm.c
Line
Count
Source
1
/*
2
** Copyright (C) 2007-2014 Erik de Castro Lopo <erikd@mega-nerd.com>
3
** Copyright (c) 2007 <robs@users.sourceforge.net>
4
**
5
** This library is free software; you can redistribute it and/or modify it
6
** under the terms of the GNU Lesser General Public License as published by
7
** the Free Software Foundation; either version 2 of the License, or (at
8
** your option) any later version.
9
**
10
** This library is distributed in the hope that it will be useful, but
11
** WITHOUT ANY WARRANTY; without even the implied warranty of
12
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
13
** General Public License for more details.
14
**
15
** You should have received a copy of the GNU Lesser General Public License
16
** along with this library.  If not, write to the Free Software Foundation,
17
** Fifth Floor, 51 Franklin Street, Boston, MA 02111-1301, USA.
18
*/
19
20
/* ADPCM: IMA, OKI <==> 16-bit PCM. */
21
22
#include "sfconfig.h"
23
24
#include <string.h>
25
26
/* Set up for libsndfile environment: */
27
#include "common.h"
28
29
#include "ima_oki_adpcm.h"
30
31
0
#define MIN_SAMPLE  -0x8000
32
0
#define MAX_SAMPLE  0x7fff
33
34
static int const ima_steps [] = /* ~16-bit precision */
35
{ 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
36
  50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230,
37
  253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963,
38
  1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327,
39
  3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493, 10442,
40
  11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794,
41
  32767
42
} ;
43
44
static int const oki_steps [] = /* ~12-bit precision */
45
{ 256, 272, 304, 336, 368, 400, 448, 496, 544, 592, 656, 720, 800, 880, 960,
46
  1056, 1168, 1280, 1408, 1552, 1712, 1888, 2080, 2288, 2512, 2768, 3040, 3344,
47
  3680, 4048, 4464, 4912, 5392, 5936, 6528, 7184, 7904, 8704, 9568, 10528,
48
  11584, 12736, 14016, 15408, 16960, 18656, 20512, 22576, 24832
49
} ;
50
51
static int const step_changes [] = { -1, -1, -1, -1, 2, 4, 6, 8 } ;
52
53
void
54
ima_oki_adpcm_init (IMA_OKI_ADPCM * state, IMA_OKI_ADPCM_TYPE type)
55
0
{
56
0
  memset (state, 0, sizeof (*state)) ;
57
58
0
  if (type == IMA_OKI_ADPCM_TYPE_IMA)
59
0
  { state->max_step_index = ARRAY_LEN (ima_steps) - 1 ;
60
0
    state->steps = ima_steps ;
61
0
    state->mask = (~0) ;
62
0
    }
63
0
  else
64
0
  { state->max_step_index = ARRAY_LEN (oki_steps) - 1 ;
65
0
    state->steps = oki_steps ;
66
0
    state->mask = arith_shift_left (~0, 4) ;
67
0
    } ;
68
69
0
} /* ima_oki_adpcm_init */
70
71
72
int
73
adpcm_decode (IMA_OKI_ADPCM * state, int code)
74
0
{ int s ;
75
76
0
  s = ((code & 7) << 1) | 1 ;
77
0
  s = ((state->steps [state->step_index] * s) >> 3) & state->mask ;
78
79
0
  if (code & 8)
80
0
    s = -s ;
81
0
  s += state->last_output ;
82
83
0
  if (s < MIN_SAMPLE || s > MAX_SAMPLE)
84
0
  { int grace ;
85
86
0
    grace = (state->steps [state->step_index] >> 3) & state->mask ;
87
88
0
    if (s < MIN_SAMPLE - grace || s > MAX_SAMPLE + grace)
89
0
      state->errors ++ ;
90
91
0
    s = s < MIN_SAMPLE ? MIN_SAMPLE : MAX_SAMPLE ;
92
0
    } ;
93
94
0
  state->step_index += step_changes [code & 7] ;
95
0
  state->step_index = SF_MIN (SF_MAX (state->step_index, 0), state->max_step_index) ;
96
0
  state->last_output = s ;
97
98
0
  return s ;
99
0
} /* adpcm_decode */
100
101
int
102
adpcm_encode (IMA_OKI_ADPCM * state, int sample)
103
0
{ int delta, sign = 0, code ;
104
105
0
  delta = sample - state->last_output ;
106
107
0
  if (delta < 0)
108
0
  { sign = 8 ;
109
0
    delta = -delta ;
110
0
    } ;
111
112
0
  code = 4 * delta / state->steps [state->step_index] ;
113
0
  code = sign | SF_MIN (code, 7) ;
114
0
  adpcm_decode (state, code) ; /* Update encoder state */
115
116
0
  return code ;
117
0
} /* adpcm_encode */
118
119
120
void
121
ima_oki_adpcm_decode_block  (IMA_OKI_ADPCM * state)
122
0
{ unsigned char code ;
123
0
  int k ;
124
125
0
  for (k = 0 ; k < state->code_count ; k++)
126
0
  { code = state->codes [k] ;
127
0
    state->pcm [2 * k] = adpcm_decode (state, code >> 4) ;
128
0
    state->pcm [2 * k + 1] = adpcm_decode (state, code) ;
129
0
    } ;
130
131
0
  state->pcm_count = 2 * k ;
132
0
} /* ima_oki_adpcm_decode_block */
133
134
135
void
136
ima_oki_adpcm_encode_block (IMA_OKI_ADPCM * state)
137
0
{ unsigned char code ;
138
0
  int k ;
139
140
  /*
141
  **  The codec expects an even number of input samples.
142
  **
143
  **  Samples should always be passed in even length blocks. If the last block to
144
  **  be encoded is odd length, extend that block by one zero valued sample.
145
  */
146
0
  if (state->pcm_count % 2 == 1)
147
0
    state->pcm [state->pcm_count ++] = 0 ;
148
149
0
  for (k = 0 ; k < state->pcm_count / 2 ; k++)
150
0
  { code = adpcm_encode (state, state->pcm [2 * k]) << 4 ;
151
0
    code |= adpcm_encode (state, state->pcm [2 * k + 1]) ;
152
0
    state->codes [k] = code ;
153
0
    } ;
154
155
0
  state->code_count = k ;
156
0
} /* ima_oki_adpcm_encode_block */
157
158
159
#ifdef TEST
160
161
static const unsigned char test_codes [] =
162
{ 0x08, 0x08, 0x04, 0x7f, 0x72, 0xf7, 0x9f, 0x7c, 0xd7, 0xbc, 0x7a, 0xa7, 0xb8,
163
  0x4b, 0x0b, 0x38, 0xf6, 0x9d, 0x7a, 0xd7, 0xbc, 0x7a, 0xd7, 0xa8, 0x6c, 0x81,
164
  0x98, 0xe4, 0x0e, 0x7a, 0xd7, 0x9e, 0x7b, 0xc7, 0xab, 0x7a, 0x85, 0xc0, 0xb3,
165
  0x8f, 0x58, 0xd7, 0xad, 0x7a, 0xd7, 0xad, 0x7a, 0x87, 0xd0, 0x2b, 0x0e, 0x48,
166
  0xd7, 0xad, 0x78, 0xf7, 0xbc, 0x7a, 0xb7, 0xa8, 0x4b, 0x88, 0x18, 0xd5, 0x8d,
167
  0x6a, 0xa4, 0x98, 0x08, 0x00, 0x80, 0x88,
168
} ;
169
170
static const short test_pcm [] =
171
{ 32, 0, 32, 0, 32, 320, 880, -336, 2304, 4192, -992, 10128, 5360, -16352,
172
  30208, 2272, -31872, 14688, -7040, -32432, 14128, -1392, -15488, 22960,
173
  1232, -1584, 21488, -240, 2576, -15360, 960, -1152, -30032, 10320, 1008,
174
  -30032, 16528, 1008, -30032, 16528, -5200, -30592, 15968, 448, -30592,
175
  15968, 448, -2368, 30960, 3024, -80, 8384, 704, -1616, -29168, -1232, 1872,
176
  -32768, 13792, -1728, -32768, 13792, 4480, -32192, 14368, -7360, -32752,
177
  13808, -1712, -21456, 16992, 1472, -1344, 26848, -1088, 2016, -17728, 208,
178
  -2112, -32768, 1376, -1728, -32768, 13792, -1728, -32768, 13792, -1728,
179
  -32768, 13792, -1728, -32768, 13792, -1728, -4544, 32767, -1377, 1727,
180
  15823, -2113, 207, -27345, 591, -2513, -32768, 13792, -1728, -32768, 13792,
181
  10688, -31632, 14928, -6800, -32192, 14368, -1152, -20896, 17552, 2032,
182
  -784, 22288, 560, -2256, -4816, 2176, 64, -21120, 9920, 6816, -24224, 16128,
183
  608, -13488, 9584, 272, -2544, 16, -2304, -192, 1728, -16, 1568, 128, -1184,
184
} ;
185
186
187
static void
188
test_oki_adpcm (void)
189
{
190
  IMA_OKI_ADPCM adpcm ;
191
  unsigned char code ;
192
  int i, j ;
193
194
  printf ("    Testing encoder          : ") ;
195
  fflush (stdout) ;
196
197
  ima_oki_adpcm_init (&adpcm, IMA_OKI_ADPCM_TYPE_OKI) ;
198
  for (i = 0 ; i < ARRAY_LEN (test_codes) ; i++)
199
    for (j = 0, code = test_codes [i] ; j < 2 ; j++, code <<= 4)
200
      if (adpcm_decode (&adpcm, code >> 4) != test_pcm [2 * i + j])
201
      { printf ("\n\nFail at i = %d, j = %d.\n\n", i, j) ;
202
        exit (1) ;
203
        } ;
204
205
  puts ("ok") ;
206
207
  printf ("    Testing decoder          : ") ;
208
  fflush (stdout) ;
209
210
  ima_oki_adpcm_init (&adpcm, IMA_OKI_ADPCM_TYPE_OKI) ;
211
  for (i = 0 ; i < ARRAY_LEN (test_pcm) ; i += j)
212
  { code = adpcm_encode (&adpcm, test_pcm [i]) ;
213
    code = (code << 4) | adpcm_encode (&adpcm, test_pcm [i + 1]) ;
214
    if (code != test_codes [i / 2])
215
      { printf ("\n\nFail at i = %d, %d should be %d\n\n", i, code, test_codes [i / 2]) ;
216
        exit (1) ;
217
        } ;
218
    } ;
219
220
  puts ("ok") ;
221
} /* test_oki_adpcm */
222
223
static void
224
test_oki_adpcm_block (void)
225
{
226
  IMA_OKI_ADPCM adpcm ;
227
  int k ;
228
229
  if (ARRAY_LEN (adpcm.pcm) < ARRAY_LEN (test_pcm))
230
  { printf ("\n\nLine %d : ARRAY_LEN (adpcm->pcm) > ARRAY_LEN (test_pcm) (%d > %d).\n\n", __LINE__, ARRAY_LEN (adpcm.pcm), ARRAY_LEN (test_pcm)) ;
231
    exit (1) ;
232
    } ;
233
234
  if (ARRAY_LEN (adpcm.codes) < ARRAY_LEN (test_codes))
235
  { printf ("\n\nLine %d : ARRAY_LEN (adcodes->codes) > ARRAY_LEN (test_codes).n", __LINE__) ;
236
    exit (1) ;
237
    } ;
238
239
  printf ("    Testing block encoder    : ") ;
240
  fflush (stdout) ;
241
242
  ima_oki_adpcm_init (&adpcm, IMA_OKI_ADPCM_TYPE_OKI) ;
243
244
  memcpy (adpcm.pcm, test_pcm, sizeof (adpcm.pcm [0]) * ARRAY_LEN (test_pcm)) ;
245
  adpcm.pcm_count = ARRAY_LEN (test_pcm) ;
246
  adpcm.code_count = 13 ;
247
248
  ima_oki_adpcm_encode_block (&adpcm) ;
249
250
  if (adpcm.code_count * 2 != ARRAY_LEN (test_pcm))
251
  { printf ("\n\nLine %d : %d * 2 != %d\n\n", __LINE__, adpcm.code_count * 2, ARRAY_LEN (test_pcm)) ;
252
    exit (1) ;
253
    } ;
254
255
  for (k = 0 ; k < ARRAY_LEN (test_codes) ; k++)
256
    if (adpcm.codes [k] != test_codes [k])
257
    { printf ("\n\nLine %d : Fail at k = %d, %d should be %d\n\n", __LINE__, k, adpcm.codes [k], test_codes [k]) ;
258
      exit (1) ;
259
      } ;
260
261
  puts ("ok") ;
262
263
  printf ("    Testing block decoder    : ") ;
264
  fflush (stdout) ;
265
266
  ima_oki_adpcm_init (&adpcm, IMA_OKI_ADPCM_TYPE_OKI) ;
267
268
  memcpy (adpcm.codes, test_codes, sizeof (adpcm.codes [0]) * ARRAY_LEN (test_codes)) ;
269
  adpcm.code_count = ARRAY_LEN (test_codes) ;
270
  adpcm.pcm_count = 13 ;
271
272
  ima_oki_adpcm_decode_block (&adpcm) ;
273
274
  if (adpcm.pcm_count != 2 * ARRAY_LEN (test_codes))
275
  { printf ("\n\nLine %d : %d * 2 != %d\n\n", __LINE__, adpcm.pcm_count, 2 * ARRAY_LEN (test_codes)) ;
276
    exit (1) ;
277
    } ;
278
279
  for (k = 0 ; k < ARRAY_LEN (test_pcm) ; k++)
280
    if (adpcm.pcm [k] != test_pcm [k])
281
    { printf ("\n\nLine %d : Fail at i = %d, %d should be %d.\n\n", __LINE__, k, adpcm.pcm [k], test_pcm [k]) ;
282
      exit (1) ;
283
      } ;
284
285
  puts ("ok") ;
286
} /* test_oki_adpcm_block */
287
288
int
289
main (void)
290
{
291
  test_oki_adpcm () ;
292
  test_oki_adpcm_block () ;
293
294
  return 0 ;
295
} /* main */
296
297
#endif