/src/libsndfile/src/nms_adpcm.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | ** Copyright (C) 1999-2014 Erik de Castro Lopo <erikd@mega-nerd.com> |
3 | | ** Copyright (C) 2017 Arthur Taylor <art@ified.ca> |
4 | | ** |
5 | | ** This program is free software; you can redistribute it and/or modify |
6 | | ** it under the terms of the GNU Lesser General Public License as published by |
7 | | ** the Free Software Foundation; either version 2.1 of the License, or |
8 | | ** (at your option) any later version. |
9 | | ** |
10 | | ** This program is distributed in the hope that it will be useful, |
11 | | ** but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | | ** GNU Lesser 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 program; if not, write to the Free Software |
17 | | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
18 | | */ |
19 | | |
20 | | /* |
21 | | ** This is a Natural MicroSystems ADPCM encoder/decoder. It converts 14 bit linear |
22 | | ** PCM to and from either a 2, 3, or 4 bit ADPCM. NMS-ADPCM does not have appeared |
23 | | ** to have ever been publicly documented, and appears to have debuted in the early |
24 | | ** 90s in the Natural Access suite of PC-based telephony products. Raw NMS ADPCM |
25 | | ** files usually have a .vce extension, although this does not encode what bitrate |
26 | | ** is used. |
27 | | ** |
28 | | ** NMS-ADPCM is an 'optimised variation' of the ITU G.726 ADPCM scheme. The dominant |
29 | | ** variation is that it removes the tone (modem) operation mode, and it's associated |
30 | | ** voice/modem transition detection. This simplifies the computation of the step |
31 | | ** size multiplier, as all operations on it remain in a log domain. |
32 | | */ |
33 | | |
34 | | #include "sfconfig.h" |
35 | | |
36 | | #include <math.h> |
37 | | |
38 | | #include "sndfile.h" |
39 | | #include "sfendian.h" |
40 | | #include "common.h" |
41 | | |
42 | | |
43 | 15.9M | #define NMS_SAMPLES_PER_BLOCK 160 |
44 | 41 | #define NMS_BLOCK_SHORTS_32 41 |
45 | 26 | #define NMS_BLOCK_SHORTS_24 31 |
46 | 226 | #define NMS_BLOCK_SHORTS_16 21 |
47 | | |
48 | | /* Variable names from ITU G.726 spec */ |
49 | | struct nms_adpcm_state |
50 | | { /* Log of the step size multiplier. Operated on by codewords. */ |
51 | | short yl ; |
52 | | |
53 | | /* Quantizer step size multiplier. Generated from yl. */ |
54 | | short y ; |
55 | | |
56 | | /* Coefficients of the pole predictor */ |
57 | | short a [2] ; |
58 | | |
59 | | /* Coefficients of the zero predictor */ |
60 | | short b [6] ; |
61 | | |
62 | | /* Previous quantized deltas (multiplied by 2^14) */ |
63 | | short d_q [7] ; |
64 | | |
65 | | /* d_q [x] + s_ez [x], used by the pole-predictor for signs only. */ |
66 | | short p [3] ; |
67 | | |
68 | | /* Previous reconstructed signal values. */ |
69 | | short s_r [2] ; |
70 | | |
71 | | /* Zero predictor components of the signal estimate. */ |
72 | | short s_ez ; |
73 | | |
74 | | /* Signal estimate, (including s_ez). */ |
75 | | short s_e ; |
76 | | |
77 | | /* The most recent codeword (enc:generated, dec:inputted) */ |
78 | | char Ik ; |
79 | | |
80 | | char parity ; |
81 | | |
82 | | /* |
83 | | ** Offset into code tables for the bitrate. |
84 | | ** 2-bit words: +0 |
85 | | ** 3-bit words: +8 |
86 | | ** 4-bit words: +16 |
87 | | */ |
88 | | int t_off ; |
89 | | } ; |
90 | | |
91 | | enum nms_enc_type |
92 | | { NMS16, |
93 | | NMS24, |
94 | | NMS32 |
95 | | } ; |
96 | | |
97 | | typedef struct |
98 | | { struct nms_adpcm_state state ; |
99 | | |
100 | | /* The encoding type */ |
101 | | enum nms_enc_type type ; |
102 | | |
103 | | int shortsperblock ; |
104 | | int blocks_total ; |
105 | | int block_curr, sample_curr ; |
106 | | |
107 | | unsigned short block [NMS_BLOCK_SHORTS_32] ; |
108 | | short samples [NMS_SAMPLES_PER_BLOCK] ; |
109 | | } NMS_ADPCM_PRIVATE ; |
110 | | |
111 | | /* Pre-computed exponential interval used in the antilog approximation. */ |
112 | | static unsigned short table_expn [] = |
113 | | { 0x4000, 0x4167, 0x42d5, 0x444c, 0x45cb, 0x4752, 0x48e2, 0x4a7a, |
114 | | 0x4c1b, 0x4dc7, 0x4f7a, 0x5138, 0x52ff, 0x54d1, 0x56ac, 0x5892, |
115 | | 0x5a82, 0x5c7e, 0x5e84, 0x6096, 0x62b4, 0x64dd, 0x6712, 0x6954, |
116 | | 0x6ba2, 0x6dfe, 0x7066, 0x72dc, 0x7560, 0x77f2, 0x7a93, 0x7d42, |
117 | | } ; |
118 | | |
119 | | /* Table mapping codewords to scale factor deltas. */ |
120 | | static short table_scale_factor_step [] = |
121 | | { 0x0, 0x0, 0x0, 0x0, 0x4b0, 0x0, 0x0, 0x0, /* 2-bit */ |
122 | | -0x3c, 0x0, 0x90, 0x0, 0x2ee, 0x0, 0x898, 0x0, /* 3-bit */ |
123 | | -0x30, 0x12, 0x6b, 0xc8, 0x188, 0x2e0, 0x551, 0x1150, /* 4-bit */ |
124 | | } ; |
125 | | |
126 | | /* Table mapping codewords to quantized delta interval steps. */ |
127 | | static unsigned short table_step [] = |
128 | | { 0x73F, 0, 0, 0, 0x1829, 0, 0, 0, /* 2-bit */ |
129 | | 0x3EB, 0, 0xC18, 0, 0x1581, 0, 0x226E, 0, /* 3-bit */ |
130 | | 0x20C, 0x635, 0xA83, 0xF12, 0x1418, 0x19E3, 0x211A, 0x2BBA, /* 4-bit */ |
131 | | } ; |
132 | | |
133 | | /* Binary search lookup table for quantizing using table_step. */ |
134 | | static short table_step_search [] = |
135 | | { 0, 0x1F6D, 0, -0x1F6D, 0, 0, 0, 0, /* 2-bit */ |
136 | | 0x1008, 0x1192, 0, -0x219A, 0x1656, -0x1656, 0, 0, /* 3-bit */ |
137 | | 0x872, 0x1277, -0x8E6, -0x232B, 0xD06, -0x17D7, -0x11D3, 0, /* 4-bit */ |
138 | | } ; |
139 | | |
140 | | |
141 | | /*============================================================================================ |
142 | | ** Static functions. |
143 | | */ |
144 | | |
145 | | static void nms_adpcm_update (struct nms_adpcm_state *s) ; |
146 | | static void nms_adpcm_codec_init (struct nms_adpcm_state *s, enum nms_enc_type type) ; |
147 | | |
148 | | static int16_t nms_adpcm_reconstruct_sample (struct nms_adpcm_state *s, uint8_t I) ; |
149 | | static uint8_t nms_adpcm_encode_sample (struct nms_adpcm_state *s, int16_t sl) ; |
150 | | static int16_t nms_adpcm_decode_sample (struct nms_adpcm_state *s, uint8_t code) ; |
151 | | |
152 | | static void nms_adpcm_block_pack_16 (const int16_t codewords [], uint16_t block [], int16_t rms) ; |
153 | | static void nms_adpcm_block_pack_24 (const int16_t codewords [], uint16_t block [], int16_t rms) ; |
154 | | static void nms_adpcm_block_pack_32 (const int16_t codewords [], uint16_t block [], int16_t rms) ; |
155 | | |
156 | | static void nms_adpcm_block_unpack_16 (const uint16_t block [], int16_t codewords [], int16_t *rms) ; |
157 | | static void nms_adpcm_block_unpack_24 (const uint16_t block [], int16_t codewords [], int16_t *rms) ; |
158 | | static void nms_adpcm_block_unpack_32 (const uint16_t block [], int16_t codewords [], int16_t *rms) ; |
159 | | |
160 | | static int nms_adpcm_decode_block (SF_PRIVATE *psf, NMS_ADPCM_PRIVATE *pnms, uint16_t block [], int16_t samples []) ; |
161 | | static int nms_adpcm_encode_block (SF_PRIVATE *psf, NMS_ADPCM_PRIVATE *pnms, int16_t samples [], uint16_t block []) ; |
162 | | |
163 | | static sf_count_t nms_adpcm_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; |
164 | | static sf_count_t nms_adpcm_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; |
165 | | static sf_count_t nms_adpcm_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; |
166 | | static sf_count_t nms_adpcm_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; |
167 | | |
168 | | static sf_count_t nms_adpcm_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; |
169 | | static sf_count_t nms_adpcm_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; |
170 | | static sf_count_t nms_adpcm_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; |
171 | | static sf_count_t nms_adpcm_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; |
172 | | |
173 | | static int nms_adpcm_close (SF_PRIVATE *psf) ; |
174 | | static sf_count_t nms_adpcm_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ; |
175 | | |
176 | | /* |
177 | | ** An exponential function (antilog) approximation. |
178 | | ** |
179 | | ** Maps [1,20480] to [1,1024] in an exponential relationship. This is |
180 | | ** approximately ret = b^exp where b = e^(ln(1024)/ln(20480)) ~= 1.0003385 |
181 | | */ |
182 | | static inline short |
183 | | nms_adpcm_antilog (short exp) |
184 | 12.4M | { int_fast32_t r ; |
185 | | |
186 | 12.4M | r = 0x1000 ; |
187 | 12.4M | r += (((int_fast32_t) (exp & 0x3f) * 0x166b) >> 12) ; |
188 | 12.4M | r *= table_expn [(exp & 0x7c0) >> 6] ; |
189 | 12.4M | r >>= (26 - (exp >> 11)) ; |
190 | | |
191 | 12.4M | return (short) r ; |
192 | 12.4M | } /* nms_adpcm_antilog */ |
193 | | |
194 | | static void |
195 | | nms_adpcm_update (struct nms_adpcm_state *s) |
196 | 12.4M | { /* Variable names from ITU G.726 spec */ |
197 | 12.4M | short a1ul, fa1 ; |
198 | 12.4M | int_fast32_t se ; |
199 | 12.4M | int i ; |
200 | | |
201 | | /* Decay and Modify the scale factor in the log domain based on the codeword. */ |
202 | 12.4M | s->yl = ((s->yl *0xf8) >> 8) + table_scale_factor_step [s->t_off + (s->Ik & 7)] ; |
203 | 12.4M | if (s->yl < 2171) |
204 | 1.64M | s->yl = 2171 ; |
205 | 10.7M | else if (s->yl > 20480) |
206 | 1.31M | s->yl = 20480 ; |
207 | 12.4M | s->y = nms_adpcm_antilog (s->yl) ; |
208 | | |
209 | | /* Update the zero predictor coefficients. */ |
210 | 86.9M | for (i = 0 ; i < 6 ; i++) |
211 | 74.5M | { s->b [i] = (s->b [i] * 0xff) >> 8 ; |
212 | 74.5M | if ((s->d_q [0] ^ s->d_q [i + 1]) >= 0) |
213 | 51.5M | s->b [i] += 128 ; |
214 | 23.0M | else |
215 | 23.0M | s->b [i] -= 128 ; |
216 | 74.5M | } |
217 | | |
218 | | /* Update the pole predictor coefficients. */ |
219 | 12.4M | fa1 = s->a [0] >> 5 ; |
220 | 12.4M | if (fa1 < -256) |
221 | 299k | fa1 = -256 ; |
222 | 12.1M | else if (fa1 > 256) |
223 | 7.99M | fa1 = 256 ; |
224 | | |
225 | 12.4M | s->a [0] = (s->a [0] * 0xff) >> 8 ; |
226 | 12.4M | if (s->p [0] != 0 && s->p [1] != 0 && ((s->p [0] ^ s->p [1]) < 0)) |
227 | 2.93M | s->a [0] -= 192 ; |
228 | 9.48M | else |
229 | 9.48M | { s->a [0] += 192 ; |
230 | 9.48M | fa1 = -fa1 ; |
231 | 9.48M | } |
232 | | |
233 | 12.4M | s->a [1] = fa1 + ((s->a [1] * 0xfe) >> 8) ; |
234 | 12.4M | if (s->p [0] != 0 && s->p [2] != 0 && ((s->p [0] ^ s->p [2]) < 0)) |
235 | 2.65M | s->a [1] -= 128 ; |
236 | 9.77M | else |
237 | 9.77M | s->a [1] += 128 ; |
238 | | |
239 | | /* Stability constraints. */ |
240 | 12.4M | if (s->a [1] < -12288) |
241 | 5.44M | s->a [1] = -12288 ; |
242 | 6.98M | else if (s->a [1] > 12288) |
243 | 29.3k | s->a [1] = 12288 ; |
244 | 12.4M | a1ul = 15360 - s->a [1] ; |
245 | 12.4M | if (s->a [0] >= a1ul) |
246 | 5.97M | s->a [0] = a1ul ; |
247 | 6.45M | else |
248 | 6.45M | { a1ul = -a1ul ; |
249 | 6.45M | if (s->a [0] < a1ul) |
250 | 190k | s->a [0] = a1ul ; |
251 | 6.45M | } ; |
252 | | |
253 | | /* Compute the zero predictor estimate and rotate past deltas. */ |
254 | 12.4M | se = 0 ; |
255 | 86.9M | for (i = 5 ; i >= 0 ; i--) |
256 | 74.5M | { se += (int_fast32_t) s->d_q [i] * s->b [i] ; |
257 | 74.5M | s->d_q [i + 1] = s->d_q [i] ; |
258 | 74.5M | } ; |
259 | 12.4M | s->s_ez = se >> 14 ; |
260 | | |
261 | | /* Complete the signal estimate. */ |
262 | 12.4M | se += (int_fast32_t) s->a [0] * s->s_r [0] ; |
263 | 12.4M | se += (int_fast32_t) s->a [1] * s->s_r [1] ; |
264 | 12.4M | s->s_e = se >> 14 ; |
265 | | |
266 | | /* Rotate members to prepare for next iteration. */ |
267 | 12.4M | s->s_r [1] = s->s_r [0] ; |
268 | 12.4M | s->p [2] = s->p [1] ; |
269 | 12.4M | s->p [1] = s->p [0] ; |
270 | 12.4M | } /* nms_adpcm_update */ |
271 | | |
272 | | |
273 | | static int16_t |
274 | | nms_adpcm_reconstruct_sample (struct nms_adpcm_state *s, uint8_t I) |
275 | 12.4M | { /* Variable names from ITU G.726 spec */ |
276 | 12.4M | int_fast32_t dqx ; |
277 | | |
278 | | /* |
279 | | ** The ordering of the 12-bit right-shift is a precision loss. It agrees |
280 | | ** with the output of a 16-bit NMSVCE.DLL, but disagrees with the output |
281 | | ** of a CG6565 board. |
282 | | */ |
283 | | |
284 | | /* Look up the delta, scale and sign it. */ |
285 | 12.4M | dqx = table_step [s->t_off + (I & 7)] * s->y ; |
286 | 12.4M | if (I & 8) |
287 | 4.43M | dqx = -dqx ; |
288 | | |
289 | | /* Take from delta scale to actual scale. */ |
290 | 12.4M | dqx >>= 12 ; |
291 | | |
292 | | /* Set variables used as input for the next predictor update. */ |
293 | 12.4M | s->d_q [0] = dqx ; |
294 | 12.4M | s->s_r [0] = s->s_e + dqx ; |
295 | 12.4M | s->Ik = I & 0xf ; |
296 | 12.4M | s->p [0] = s->s_ez + dqx ; |
297 | | |
298 | 12.4M | return s->s_r [0] ; |
299 | 12.4M | } /* nms_adpcm_reconstruct_sample */ |
300 | | |
301 | | static void |
302 | | nms_adpcm_codec_init (struct nms_adpcm_state *s, enum nms_enc_type type) |
303 | 293 | { memset (s, 0, sizeof (struct nms_adpcm_state)) ; |
304 | 293 | s->t_off = (type == NMS32) ? 16 : (type == NMS24) ? 8 : 0 ; |
305 | 293 | } /* nms_adpcm_codec_init */ |
306 | | |
307 | | /* |
308 | | ** nms_adpcm_encode_sample() |
309 | | ** |
310 | | ** Encode a linear 16-bit pcm sample into a 2, 3, or 4 bit NMS-ADPCM codeword |
311 | | ** using and updating the predictor state. |
312 | | */ |
313 | | static uint8_t |
314 | | nms_adpcm_encode_sample (struct nms_adpcm_state *s, int16_t sl) |
315 | 0 | { /* Variable names from ITU G.726 spec */ |
316 | 0 | int_fast32_t d ; |
317 | 0 | uint8_t I ; |
318 | | |
319 | | /* Down scale the sample from 16 => ~14 bits. */ |
320 | 0 | sl = ((int_fast32_t) sl * 0x1fdf) / 0x7fff ; |
321 | | |
322 | | /* Compute estimate, and delta from actual value */ |
323 | 0 | nms_adpcm_update (s) ; |
324 | 0 | d = sl - s->s_e ; |
325 | | |
326 | | /* |
327 | | ** Vary the input signal. Not sure why. It agrees with NMSVCE.DLL and |
328 | | ** a CG6565 board. |
329 | | */ |
330 | 0 | if (s->parity ^= 1) |
331 | 0 | d -= 2 ; |
332 | | |
333 | | /* Encode the delta signed-ness (Codeword bit 4) */ |
334 | 0 | if (d < 0) |
335 | 0 | { d = -d ; |
336 | 0 | I = 8 ; |
337 | 0 | } |
338 | 0 | else |
339 | 0 | I = 0 ; |
340 | | |
341 | | /* Increase magnitude to be in the range of the delta steps */ |
342 | 0 | d <<= 13 ; |
343 | | |
344 | | /* Quantize the delta using a binary search. */ |
345 | 0 | d += table_step_search [s->t_off + 3] * s->y ; |
346 | | /* Codeword bit 3 */ |
347 | 0 | if (d >= 0) |
348 | 0 | { d += table_step_search [s->t_off + 5] * s->y ; |
349 | | /* Codeword bit 2 */ |
350 | 0 | if (d >= 0) |
351 | 0 | { d += table_step_search [s->t_off + 6] * s->y ; |
352 | | /* Codeword bit 1 */ |
353 | 0 | if (d >= 0) |
354 | 0 | I |= 7 ; |
355 | 0 | else |
356 | 0 | I |= 6 ; |
357 | 0 | } |
358 | 0 | else |
359 | 0 | { d += table_step_search [s->t_off + 4] * s->y ; |
360 | | /* Codeword bit 1 */ |
361 | 0 | if (d >= 0) |
362 | 0 | I |= 5 ; |
363 | 0 | else |
364 | 0 | I |= 4 ; |
365 | 0 | } ; |
366 | 0 | } |
367 | 0 | else { |
368 | 0 | d += table_step_search [s->t_off + 1] * s->y ; |
369 | | /* Codeword bit 2 */ |
370 | 0 | if (d >= 0) |
371 | 0 | { d += table_step_search [s->t_off + 2] * s->y ; |
372 | | /* Codeword bit 1 */ |
373 | 0 | if (d >= 0) |
374 | 0 | I |= 3 ; |
375 | 0 | else |
376 | 0 | I |= 2 ; |
377 | 0 | } |
378 | 0 | else { |
379 | 0 | d += table_step_search [s->t_off + 0] * s->y ; |
380 | | /* Codeword bit 1 */ |
381 | 0 | if (d >= 0) |
382 | 0 | I |= 1 ; |
383 | 0 | else |
384 | 0 | I |= 0 ; |
385 | 0 | } ; |
386 | 0 | } ; |
387 | | /* What's left in d is actually our quantizer noise. */ |
388 | | |
389 | | /* Reduce the codeword size for the bitrate accordingly. */ |
390 | 0 | if (s->t_off == 8) |
391 | 0 | I &= 0xe ; |
392 | 0 | else if (s->t_off == 0) |
393 | 0 | I &= 0xc ; |
394 | | |
395 | | /* Call reconstruct for side effects preparing for the next update. */ |
396 | 0 | nms_adpcm_reconstruct_sample (s, I) ; |
397 | |
|
398 | 0 | return I ; |
399 | 0 | } /* nms_adpcm_encode_sample */ |
400 | | |
401 | | /* |
402 | | ** nms_adpcm_decode_sample() |
403 | | ** |
404 | | ** Given a 2,3 or 4-bit NMS-ADPCM codeword, decode the next 16-bit linear PCM |
405 | | ** sample using and updating the predictor state. |
406 | | */ |
407 | | static int16_t |
408 | | nms_adpcm_decode_sample (struct nms_adpcm_state *s, uint8_t I) |
409 | 12.4M | { int_fast32_t sl ; |
410 | | |
411 | 12.4M | nms_adpcm_update (s) ; |
412 | 12.4M | sl = nms_adpcm_reconstruct_sample (s, I) ; |
413 | | |
414 | | /* Clamp to [-0x1fdf, 0x1fdf] (just under 14 bits resolution) */ |
415 | 12.4M | if (sl < -0x1fdf) |
416 | 1.13M | sl = -0x1fdf ; |
417 | 11.2M | else if (sl > 0x1fdf) |
418 | 1.24M | sl = 0x1fdf ; |
419 | | |
420 | | /* Expand from 14 to 16 bits */ |
421 | 12.4M | sl = (sl * 0x7fff) / 0x1fdf ; |
422 | | |
423 | 12.4M | return (int16_t) sl ; |
424 | 12.4M | } /* nms_adpcm_decode_sample */ |
425 | | |
426 | | /** |
427 | | ** NMS ADPCM Codeword packing scheme. |
428 | | ** |
429 | | ** The serialized form of NMS-ADPCM operates on blocks of 160 mono samples |
430 | | ** (20ms at 8000Hz.) Blocks are 42, 62 and 82 bytes in size for the 2, 3, and |
431 | | ** 4 bit codeword sizes respectively. The data is treated as an array of |
432 | | ** little-endian 2-byte shorts, and the data is packed into the first 20, 30 |
433 | | ** or 40 shorts. The last short represents the block's root-mean-square |
434 | | ** average. This is apparently an optimization so that energy/silence |
435 | | ** detection processes can avoid decoding a block. |
436 | | ** |
437 | | ** All codewords are nibbles, with the least significant bits dropped as |
438 | | ** required for the 3 and 2 bit codeword sizes. |
439 | | ** |
440 | | ** Nibbles are packed into shorts in order of most significant to least. The |
441 | | ** 4-bit scheme is trivial. The three bit scheme reconstructs a fourth sample |
442 | | ** from the leftover bits of the proceeding three samples. The 2-bit scheme |
443 | | ** uses a two-pass, left two bit shift. |
444 | | */ |
445 | | |
446 | | /* |
447 | | ** Reads 21 shorts from block, unpacks 160 codewords of 2-bits each, writing |
448 | | ** each to its sequential array index of codewords. If rms is non-null, the |
449 | | ** read block rms is copied to its location. |
450 | | */ |
451 | | static void |
452 | | nms_adpcm_block_unpack_16 (const uint16_t block [], int16_t codewords [], int16_t *rms) |
453 | 66.5k | { int k ; |
454 | 66.5k | uint16_t w = 0 ; |
455 | | |
456 | 2.72M | for (k = 0 ; k < NMS_SAMPLES_PER_BLOCK ; ) |
457 | 2.66M | { /* |
458 | | ** k % 8 == [0-3]: Top 2-bits of a nibble |
459 | | ** k % 8 == [4-7]: Bottom 2-bits of a nibble |
460 | | */ |
461 | 2.66M | if ((k & 4) == 0) |
462 | 1.33M | w = *(block++) ; |
463 | 1.33M | else |
464 | 1.33M | w <<= 2 ; |
465 | 2.66M | codewords [k++] = (w >> 12) & 0xc ; |
466 | 2.66M | codewords [k++] = (w >> 8) & 0xc ; |
467 | 2.66M | codewords [k++] = (w >> 4) & 0xc ; |
468 | 2.66M | codewords [k++] = w & 0xc ; |
469 | 2.66M | } ; |
470 | | |
471 | | /* |
472 | | ** Every block ends with a short representing a RMS-approximation for the |
473 | | ** block. |
474 | | **/ |
475 | 66.5k | if (rms) |
476 | 0 | *rms = *block ; |
477 | 66.5k | } /* nms_adpcm_unpack_16 */ |
478 | | |
479 | | /* |
480 | | ** Reads 31 shorts from block, unpacks 160 codewords of 3-bits each, writing |
481 | | ** each to its sequential array index of codewords. If rms is non-null, the |
482 | | ** read block rms is copied to its location. |
483 | | */ |
484 | | static void |
485 | | nms_adpcm_block_unpack_24 (const uint16_t block [], int16_t codewords [], int16_t *rms) |
486 | 1.00k | { int k ; |
487 | 1.00k | uint16_t w = 0, residual = 0 ; |
488 | | |
489 | 41.2k | for (k = 0 ; k < NMS_SAMPLES_PER_BLOCK ; ) |
490 | 40.2k | { /* |
491 | | ** k % 16 == [0, 11]: Unpack new nibble, build residual |
492 | | ** k % 16 == [12, 15]: Unpack residual |
493 | | */ |
494 | 40.2k | if ((k & 12) != 12) |
495 | 30.1k | { w = *(block++) ; |
496 | 30.1k | residual = (residual << 1) | (w & 0x1111) ; |
497 | 30.1k | } |
498 | 10.0k | else |
499 | 10.0k | { w = residual << 1 ; |
500 | 10.0k | residual = 0 ; |
501 | 10.0k | } ; |
502 | 40.2k | codewords [k++] = (w >> 12) & 0xe ; |
503 | 40.2k | codewords [k++] = (w >> 8) & 0xe ; |
504 | 40.2k | codewords [k++] = (w >> 4) & 0xe ; |
505 | 40.2k | codewords [k++] = w & 0xe ; |
506 | 40.2k | } ; |
507 | | |
508 | | /* |
509 | | ** Every block ends with a short representing a RMS-approximation for the |
510 | | ** block. |
511 | | **/ |
512 | 1.00k | if (rms) |
513 | 0 | *rms = *block ; |
514 | 1.00k | } /* nms_adpcm_unpack_24 */ |
515 | | |
516 | | /* |
517 | | ** Reads 41 shorts from block, unpacks 160 codewords of 4-bits each, writing |
518 | | ** each to its sequential array index of codewords. If rms is non-null, the |
519 | | ** read block rms is copied to its location. |
520 | | */ |
521 | | static void |
522 | | nms_adpcm_block_unpack_32 (const uint16_t block [], int16_t codewords [], int16_t *rms) |
523 | 10.1k | { int k ; |
524 | 10.1k | uint16_t w = 0 ; |
525 | | |
526 | 415k | for (k = 0 ; k < NMS_SAMPLES_PER_BLOCK ; ) |
527 | 405k | { w = *(block++) ; |
528 | 405k | codewords [k++] = (w >> 12) & 0xf ; |
529 | 405k | codewords [k++] = (w >> 8) & 0xf ; |
530 | 405k | codewords [k++] = (w >> 4) & 0xf ; |
531 | 405k | codewords [k++] = w & 0xf ; |
532 | 405k | } ; |
533 | | /* |
534 | | ** Every block ends with a short representing a RMS-approximation for the |
535 | | ** block. |
536 | | **/ |
537 | 10.1k | if (rms) |
538 | 0 | *rms = *block ; |
539 | 10.1k | } /* nms_adpcm_unpack_32 */ |
540 | | |
541 | | /* |
542 | | ** Reads 160 indicies of codewords for one 2-bit codeword each, packing them |
543 | | ** into 20 shorts of block, and writes the short rms for a total of 42 bytes. |
544 | | */ |
545 | | static void |
546 | | nms_adpcm_block_pack_16 (const int16_t codewords [], uint16_t block [], int16_t rms) |
547 | 0 | { int k ; |
548 | 0 | uint16_t w ; |
549 | |
|
550 | 0 | for (k = 0 ; k < NMS_SAMPLES_PER_BLOCK ; ) |
551 | 0 | { w = codewords [k++] << 12 ; |
552 | 0 | w |= codewords [k++] << 8 ; |
553 | 0 | w |= codewords [k++] << 4 ; |
554 | 0 | w |= codewords [k++] ; |
555 | 0 | w |= codewords [k++] << 10 ; |
556 | 0 | w |= codewords [k++] << 6 ; |
557 | 0 | w |= codewords [k++] << 2 ; |
558 | 0 | w |= codewords [k++] >> 2 ; |
559 | |
|
560 | 0 | *(block++) = w ; |
561 | 0 | } ; |
562 | | |
563 | | /* Every block ends with a short representing the blocks RMS */ |
564 | 0 | *block = rms ; |
565 | 0 | } /* nms_adpcm_pack_16 */ |
566 | | |
567 | | /* |
568 | | ** Reads 160 indicies of codewords for one 3-bit codeword each, packing them |
569 | | ** into 30 shorts of block, and writes the short rms for a total of 62 bytes. |
570 | | */ |
571 | | static void |
572 | | nms_adpcm_block_pack_24 (const int16_t codewords [], uint16_t block [], int16_t rms) |
573 | 0 | { int k ; |
574 | 0 | uint16_t w [3] ; |
575 | 0 | uint16_t residual ; |
576 | |
|
577 | 0 | for (k = 0 ; k < NMS_SAMPLES_PER_BLOCK ; ) |
578 | 0 | { w [0] = codewords [k++] << 12 ; |
579 | 0 | w [0] |= codewords [k++] << 8 ; |
580 | 0 | w [0] |= codewords [k++] << 4 ; |
581 | 0 | w [0] |= codewords [k++] ; |
582 | |
|
583 | 0 | w [1] = codewords [k++] << 12 ; |
584 | 0 | w [1] |= codewords [k++] << 8 ; |
585 | 0 | w [1] |= codewords [k++] << 4 ; |
586 | 0 | w [1] |= codewords [k++] ; |
587 | |
|
588 | 0 | w [2] = codewords [k++] << 12 ; |
589 | 0 | w [2] |= codewords [k++] << 8 ; |
590 | 0 | w [2] |= codewords [k++] << 4 ; |
591 | 0 | w [2] |= codewords [k++] ; |
592 | |
|
593 | 0 | residual = codewords [k++] << 12 ; |
594 | 0 | residual |= codewords [k++] << 8 ; |
595 | 0 | residual |= codewords [k++] << 4 ; |
596 | 0 | residual |= codewords [k++] ; |
597 | |
|
598 | 0 | residual >>= 1 ; |
599 | 0 | w [2] |= (residual & 0x1111) ; |
600 | 0 | residual >>= 1 ; |
601 | 0 | w [1] |= (residual & 0x1111) ; |
602 | 0 | residual >>= 1 ; |
603 | 0 | w [0] |= (residual & 0x1111) ; |
604 | |
|
605 | 0 | *(block++) = w [0] ; |
606 | 0 | *(block++) = w [1] ; |
607 | 0 | *(block++) = w [2] ; |
608 | 0 | } ; |
609 | | |
610 | | /* Every block ends with a short representing the blocks RMS */ |
611 | 0 | *block = rms ; |
612 | 0 | } /* nms_adpcm_pack_24 */ |
613 | | |
614 | | /* |
615 | | ** Reads 160 indicies of codewords for one 4-bit codeword each, packing them |
616 | | ** into 40 shorts of block, and writes the short rms for a total of 82 bytes. |
617 | | */ |
618 | | static void |
619 | | nms_adpcm_block_pack_32 (const int16_t codewords [], uint16_t block [], int16_t rms) |
620 | 0 | { int k ; |
621 | 0 | uint16_t w ; |
622 | |
|
623 | 0 | for (k = 0 ; k < NMS_SAMPLES_PER_BLOCK ; ) |
624 | 0 | { w = codewords [k++] << 12 ; |
625 | 0 | w |= codewords [k++] << 8 ; |
626 | 0 | w |= codewords [k++] << 4 ; |
627 | 0 | w |= codewords [k++] ; |
628 | |
|
629 | 0 | *(block++) = w ; |
630 | 0 | } ; |
631 | | |
632 | | /* Every block ends with a short representing the blocks RMS */ |
633 | 0 | *block = rms ; |
634 | 0 | } /*nms_adpcm_block_pack_32 */ |
635 | | |
636 | | static int |
637 | | nms_adpcm_decode_block (SF_PRIVATE *psf, NMS_ADPCM_PRIVATE *pnms, uint16_t block [], int16_t samples []) |
638 | 77.6k | { int k ; |
639 | | |
640 | 77.6k | switch (pnms->type) |
641 | 77.6k | { case NMS16 : |
642 | 66.5k | nms_adpcm_block_unpack_16 (block, samples, NULL) ; |
643 | 66.5k | break ; |
644 | 1.00k | case NMS24 : |
645 | 1.00k | nms_adpcm_block_unpack_24 (block, samples, NULL) ; |
646 | 1.00k | break ; |
647 | 10.1k | case NMS32 : |
648 | 10.1k | nms_adpcm_block_unpack_32 (block, samples, NULL) ; |
649 | 10.1k | break ; |
650 | | |
651 | 0 | default : |
652 | 0 | psf_log_printf (psf, "*** Error : Unhandled NMS ADPCM type %d.\n", pnms->type) ; |
653 | 0 | return 0 ; |
654 | 77.6k | } ; |
655 | | |
656 | 12.5M | for (k = 0 ; k < NMS_SAMPLES_PER_BLOCK ; k++) |
657 | 12.4M | samples [k] = nms_adpcm_decode_sample (&pnms->state, samples [k]) ; |
658 | | |
659 | 77.6k | return NMS_SAMPLES_PER_BLOCK ; |
660 | 77.6k | } /* nms_adpcm_decode_block */ |
661 | | |
662 | | static int |
663 | | nms_adpcm_encode_block (SF_PRIVATE *psf, NMS_ADPCM_PRIVATE *pnms, int16_t samples [], uint16_t block []) |
664 | 0 | { int k ; |
665 | 0 | unsigned int rms = 0 ; |
666 | | |
667 | | /* |
668 | | ** The rms we write is a complete lie. Considering that the various |
669 | | ** other implementations I've tested don't completely agree, that this data |
670 | | ** is usually ignored, and except for some weird offloading of "energy |
671 | | ** detection", so long as we don't write zeros for non-zero data, I don't |
672 | | ** think it really matters. |
673 | | */ |
674 | |
|
675 | 0 | for (k = 0 ; k < NMS_SAMPLES_PER_BLOCK ; k++) |
676 | 0 | { rms += (samples [k] * samples [k]) >> 2 ; |
677 | 0 | samples [k] = nms_adpcm_encode_sample (&pnms->state, samples [k]) ; |
678 | 0 | } ; |
679 | |
|
680 | 0 | rms <<= 12 ; |
681 | 0 | switch (pnms->type) |
682 | 0 | { case NMS16 : |
683 | 0 | nms_adpcm_block_pack_16 (samples, block, rms) ; |
684 | 0 | break ; |
685 | 0 | case NMS24 : |
686 | 0 | nms_adpcm_block_pack_24 (samples, block, rms) ; |
687 | 0 | break ; |
688 | 0 | case NMS32 : |
689 | 0 | nms_adpcm_block_pack_32 (samples, block, rms) ; |
690 | 0 | break ; |
691 | | |
692 | 0 | default : |
693 | 0 | psf_log_printf (psf, "*** Error : Unhandled NMS ADPCM type %d.\n", pnms->type) ; |
694 | 0 | return 0 ; |
695 | 0 | } ; |
696 | |
|
697 | 0 | return NMS_SAMPLES_PER_BLOCK ; |
698 | 0 | } /* nms_adpcm_encode_block */ |
699 | | |
700 | | static int |
701 | | psf_nms_adpcm_decode_block (SF_PRIVATE *psf, NMS_ADPCM_PRIVATE *pnms) |
702 | 77.6k | { int k ; |
703 | | |
704 | 77.6k | if ((k = (int) psf_fread (pnms->block, sizeof (short), pnms->shortsperblock, psf)) != pnms->shortsperblock) |
705 | 515 | { psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pnms->shortsperblock) ; |
706 | 515 | memset (pnms->block + (k * sizeof (short)), 0, (pnms->shortsperblock - k) * sizeof (short)) ; |
707 | 515 | } ; |
708 | | |
709 | 77.6k | if (CPU_IS_BIG_ENDIAN) |
710 | 0 | endswap_short_array ((signed short *) pnms->block, pnms->shortsperblock) ; |
711 | | |
712 | 77.6k | nms_adpcm_decode_block (psf, pnms, pnms->block, pnms->samples) ; |
713 | | |
714 | 77.6k | return 1 ; |
715 | 77.6k | } /* nms_adpcm_decode_block */ |
716 | | |
717 | | static int |
718 | | nms_adpcm_read_block (SF_PRIVATE *psf, NMS_ADPCM_PRIVATE *pnms, short *ptr, int len) |
719 | 3.44k | { int count, indx = 0 ; |
720 | | |
721 | 84.1k | while (indx < len) |
722 | 80.7k | { if (pnms->sample_curr >= NMS_SAMPLES_PER_BLOCK) |
723 | 77.4k | { pnms->block_curr ++ ; |
724 | 77.4k | pnms->sample_curr = 0 ; |
725 | 77.4k | } ; |
726 | | |
727 | 80.7k | if (pnms->block_curr > pnms->blocks_total) |
728 | 93 | { memset (&(ptr [indx]), 0, (len - indx) * sizeof (short)) ; |
729 | 93 | return indx ; |
730 | 80.6k | } ; |
731 | | |
732 | 80.6k | if (pnms->sample_curr == 0) |
733 | 77.6k | psf_nms_adpcm_decode_block (psf, pnms) ; |
734 | | |
735 | 80.6k | count = NMS_SAMPLES_PER_BLOCK - pnms->sample_curr ; |
736 | 80.6k | if (len - indx < count) |
737 | 3.19k | count = len - indx ; |
738 | | |
739 | 80.6k | memcpy (&(ptr [indx]), &(pnms->samples [pnms->sample_curr]), count * sizeof (short)) ; |
740 | 80.6k | indx += count ; |
741 | 80.6k | pnms->sample_curr += count ; |
742 | 80.6k | } ; |
743 | | |
744 | 3.35k | return indx ; |
745 | 3.44k | } /* nms_adpcm_read_block */ |
746 | | |
747 | | static sf_count_t |
748 | | nms_adpcm_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) |
749 | 206 | { NMS_ADPCM_PRIVATE *pnms ; |
750 | 206 | int readcount, count ; |
751 | 206 | sf_count_t total = 0 ; |
752 | | |
753 | 206 | if (psf->codec_data == NULL) |
754 | 0 | return 0 ; |
755 | 206 | pnms = (NMS_ADPCM_PRIVATE*) psf->codec_data ; |
756 | | |
757 | 398 | while (len > 0) |
758 | 206 | { readcount = (len > 0x10000000) ? 0x10000000 : (int) len ; |
759 | | |
760 | 206 | count = nms_adpcm_read_block (psf, pnms, ptr, readcount) ; |
761 | | |
762 | 206 | total += count ; |
763 | 206 | len -= count ; |
764 | | |
765 | 206 | if (count != readcount) |
766 | 14 | break ; |
767 | 206 | } ; |
768 | | |
769 | 206 | return total ; |
770 | 206 | } /* nms_adpcm_read_s */ |
771 | | |
772 | | static sf_count_t |
773 | | nms_adpcm_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) |
774 | 330 | { BUF_UNION ubuf ; |
775 | 330 | NMS_ADPCM_PRIVATE *pnms ; |
776 | 330 | short *sptr ; |
777 | 330 | int k, bufferlen, readcount = 0, count ; |
778 | 330 | sf_count_t total = 0 ; |
779 | | |
780 | 330 | if (psf->codec_data == NULL) |
781 | 0 | return 0 ; |
782 | 330 | pnms = (NMS_ADPCM_PRIVATE *) psf->codec_data ; |
783 | | |
784 | 330 | sptr = ubuf.sbuf ; |
785 | 330 | bufferlen = SF_BUFFER_LEN / sizeof (short) ; |
786 | 1.16k | while (len > 0) |
787 | 872 | { readcount = (len >= bufferlen) ? bufferlen : (int) len ; |
788 | 872 | count = nms_adpcm_read_block (psf, pnms, sptr, readcount) ; |
789 | | |
790 | 2.47M | for (k = 0 ; k < readcount ; k++) |
791 | 2.47M | ptr [total + k] = arith_shift_left (sptr [k], 16) ; |
792 | | |
793 | 872 | total += count ; |
794 | 872 | len -= readcount ; |
795 | 872 | if (count != readcount) |
796 | 36 | break ; |
797 | 872 | } ; |
798 | | |
799 | 330 | return total ; |
800 | 330 | } /* nms_adpcm_read_i */ |
801 | | |
802 | | static sf_count_t |
803 | | nms_adpcm_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) |
804 | 0 | { BUF_UNION ubuf ; |
805 | 0 | NMS_ADPCM_PRIVATE *pnms ; |
806 | 0 | short *sptr ; |
807 | 0 | int k, bufferlen, readcount = 0, count ; |
808 | 0 | sf_count_t total = 0 ; |
809 | 0 | float normfact ; |
810 | |
|
811 | 0 | if (psf->codec_data == NULL) |
812 | 0 | return 0 ; |
813 | 0 | pnms = (NMS_ADPCM_PRIVATE*) psf->codec_data ; |
814 | |
|
815 | 0 | normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ; |
816 | |
|
817 | 0 | sptr = ubuf.sbuf ; |
818 | 0 | bufferlen = SF_BUFFER_LEN / sizeof (short) ; |
819 | 0 | while (len > 0) |
820 | 0 | { readcount = (len >= bufferlen) ? bufferlen : (int) len ; |
821 | 0 | count = nms_adpcm_read_block (psf, pnms, sptr, readcount) ; |
822 | 0 | for (k = 0 ; k < readcount ; k++) |
823 | 0 | ptr [total + k] = normfact * sptr [k] ; |
824 | |
|
825 | 0 | total += count ; |
826 | 0 | len -= readcount ; |
827 | 0 | if (count != readcount) |
828 | 0 | break ; |
829 | 0 | } ; |
830 | |
|
831 | 0 | return total ; |
832 | 0 | } /* nms_adpcm_read_f */ |
833 | | |
834 | | static sf_count_t |
835 | | nms_adpcm_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) |
836 | 398 | { BUF_UNION ubuf ; |
837 | 398 | NMS_ADPCM_PRIVATE *pnms ; |
838 | 398 | short *sptr ; |
839 | 398 | int k, bufferlen, readcount = 0, count ; |
840 | 398 | sf_count_t total = 0 ; |
841 | 398 | double normfact ; |
842 | | |
843 | 398 | if (psf->codec_data == NULL) |
844 | 0 | return 0 ; |
845 | 398 | pnms = (NMS_ADPCM_PRIVATE*) psf->codec_data ; |
846 | | |
847 | 398 | normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ; |
848 | | |
849 | 398 | sptr = ubuf.sbuf ; |
850 | 398 | bufferlen = SF_BUFFER_LEN / sizeof (short) ; |
851 | 2.72k | while (len > 0) |
852 | 2.36k | { readcount = (len >= bufferlen) ? bufferlen : (int) len ; |
853 | 2.36k | count = nms_adpcm_read_block (psf, pnms, sptr, readcount) ; |
854 | 8.44M | for (k = 0 ; k < readcount ; k++) |
855 | 8.43M | ptr [total + k] = normfact * (double) (sptr [k]) ; |
856 | | |
857 | 2.36k | total += count ; |
858 | 2.36k | len -= readcount ; |
859 | 2.36k | if (count != readcount) |
860 | 43 | break ; |
861 | 2.36k | } ; |
862 | | |
863 | 398 | return total ; |
864 | 398 | } /* nms_adpcm_read_d */ |
865 | | |
866 | | static int |
867 | | psf_nms_adpcm_encode_block (SF_PRIVATE *psf, NMS_ADPCM_PRIVATE *pnms) |
868 | 0 | { int k ; |
869 | | |
870 | | /* Encode the samples. */ |
871 | 0 | nms_adpcm_encode_block (psf, pnms, pnms->samples, pnms->block) ; |
872 | |
|
873 | 0 | if (CPU_IS_BIG_ENDIAN) |
874 | 0 | endswap_short_array ((signed short *) pnms->block, pnms->shortsperblock) ; |
875 | | |
876 | | /* Write the block to disk. */ |
877 | 0 | if ((k = (int) psf_fwrite (pnms->block, sizeof (short), pnms->shortsperblock, psf)) != pnms->shortsperblock) |
878 | 0 | psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pnms->shortsperblock) ; |
879 | |
|
880 | 0 | pnms->sample_curr = 0 ; |
881 | 0 | pnms->block_curr ++ ; |
882 | |
|
883 | 0 | return 1 ; |
884 | 0 | } /* psf_nms_adpcm_encode_block */ |
885 | | |
886 | | static int |
887 | | nms_adpcm_write_block (SF_PRIVATE *psf, NMS_ADPCM_PRIVATE *pnms, const short *ptr, int len) |
888 | 0 | { int count, total = 0, indx = 0 ; |
889 | |
|
890 | 0 | while (indx < len) |
891 | 0 | { count = NMS_SAMPLES_PER_BLOCK - pnms->sample_curr ; |
892 | |
|
893 | 0 | if (count > len - indx) |
894 | 0 | count = len - indx ; |
895 | |
|
896 | 0 | memcpy (&(pnms->samples [pnms->sample_curr]), &(ptr [indx]), count * sizeof (short)) ; |
897 | 0 | indx += count ; |
898 | 0 | pnms->sample_curr += count ; |
899 | 0 | total = indx ; |
900 | |
|
901 | 0 | if (pnms->sample_curr >= NMS_SAMPLES_PER_BLOCK) |
902 | 0 | psf_nms_adpcm_encode_block (psf, pnms) ; |
903 | 0 | } ; |
904 | |
|
905 | 0 | return total ; |
906 | 0 | } /* nms_adpcm_write_block */ |
907 | | |
908 | | static sf_count_t |
909 | | nms_adpcm_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) |
910 | 0 | { NMS_ADPCM_PRIVATE *pnms ; |
911 | 0 | int writecount, count ; |
912 | 0 | sf_count_t total = 0 ; |
913 | |
|
914 | 0 | if (psf->codec_data == NULL) |
915 | 0 | return 0 ; |
916 | 0 | pnms = (NMS_ADPCM_PRIVATE*) psf->codec_data ; |
917 | |
|
918 | 0 | while (len > 0) |
919 | 0 | { writecount = (len > 0x10000000) ? 0x10000000 : (int) len ; |
920 | |
|
921 | 0 | count = nms_adpcm_write_block (psf, pnms, ptr, writecount) ; |
922 | |
|
923 | 0 | total += count ; |
924 | 0 | len -= count ; |
925 | 0 | if (count != writecount) |
926 | 0 | break ; |
927 | 0 | } ; |
928 | |
|
929 | 0 | return total ; |
930 | 0 | } /* nms_adpcm_write_s */ |
931 | | |
932 | | static sf_count_t |
933 | | nms_adpcm_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) |
934 | 0 | { BUF_UNION ubuf ; |
935 | 0 | NMS_ADPCM_PRIVATE *pnms ; |
936 | 0 | short *sptr ; |
937 | 0 | int k, bufferlen, writecount = 0, count ; |
938 | 0 | sf_count_t total = 0 ; |
939 | |
|
940 | 0 | if (psf->codec_data == NULL) |
941 | 0 | return 0 ; |
942 | 0 | pnms = (NMS_ADPCM_PRIVATE*) psf->codec_data ; |
943 | |
|
944 | 0 | sptr = ubuf.sbuf ; |
945 | 0 | bufferlen = SF_BUFFER_LEN / sizeof (short) ; |
946 | 0 | while (len > 0) |
947 | 0 | { writecount = (len >= bufferlen) ? bufferlen : (int) len ; |
948 | 0 | for (k = 0 ; k < writecount ; k++) |
949 | 0 | sptr [k] = ptr [total + k] >> 16 ; |
950 | 0 | count = nms_adpcm_write_block (psf, pnms, sptr, writecount) ; |
951 | |
|
952 | 0 | total += count ; |
953 | 0 | len -= writecount ; |
954 | 0 | if (count != writecount) |
955 | 0 | break ; |
956 | 0 | } ; |
957 | 0 | return total ; |
958 | 0 | } /* nms_adpcm_write_i */ |
959 | | |
960 | | static sf_count_t |
961 | | nms_adpcm_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) |
962 | 0 | { BUF_UNION ubuf ; |
963 | 0 | NMS_ADPCM_PRIVATE *pnms ; |
964 | 0 | short *sptr ; |
965 | 0 | int k, bufferlen, writecount = 0, count ; |
966 | 0 | sf_count_t total = 0 ; |
967 | 0 | float normfact ; |
968 | |
|
969 | 0 | if (psf->codec_data == NULL) |
970 | 0 | return 0 ; |
971 | 0 | pnms = (NMS_ADPCM_PRIVATE*) psf->codec_data ; |
972 | |
|
973 | 0 | normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x8000) : 1.0 ; |
974 | |
|
975 | 0 | sptr = ubuf.sbuf ; |
976 | 0 | bufferlen = SF_BUFFER_LEN / sizeof (short) ; |
977 | 0 | while (len > 0) |
978 | 0 | { writecount = (len >= bufferlen) ? bufferlen : (int) len ; |
979 | 0 | for (k = 0 ; k < writecount ; k++) |
980 | 0 | sptr [k] = psf_lrintf (normfact * ptr [total + k]) ; |
981 | 0 | count = nms_adpcm_write_block (psf, pnms, sptr, writecount) ; |
982 | |
|
983 | 0 | total += count ; |
984 | 0 | len -= writecount ; |
985 | 0 | if (count != writecount) |
986 | 0 | break ; |
987 | 0 | } ; |
988 | |
|
989 | 0 | return total ; |
990 | 0 | } /* nms_adpcm_write_f */ |
991 | | |
992 | | static sf_count_t |
993 | | nms_adpcm_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) |
994 | 0 | { BUF_UNION ubuf ; |
995 | 0 | NMS_ADPCM_PRIVATE *pnms ; |
996 | 0 | short *sptr ; |
997 | 0 | int k, bufferlen, writecount = 0, count ; |
998 | 0 | sf_count_t total = 0 ; |
999 | 0 | double normfact ; |
1000 | |
|
1001 | 0 | if (psf->codec_data == NULL) |
1002 | 0 | return 0 ; |
1003 | 0 | pnms = (NMS_ADPCM_PRIVATE*) psf->codec_data ; |
1004 | |
|
1005 | 0 | normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x8000) : 1.0 ; |
1006 | |
|
1007 | 0 | sptr = ubuf.sbuf ; |
1008 | 0 | bufferlen = SF_BUFFER_LEN / sizeof (short) ; |
1009 | 0 | while (len > 0) |
1010 | 0 | { writecount = (len >= bufferlen) ? bufferlen : (int) len ; |
1011 | 0 | for (k = 0 ; k < writecount ; k++) |
1012 | 0 | sptr [k] = psf_lrint (normfact * ptr [total + k]) ; |
1013 | 0 | count = nms_adpcm_write_block (psf, pnms, sptr, writecount) ; |
1014 | |
|
1015 | 0 | total += count ; |
1016 | 0 | len -= writecount ; |
1017 | 0 | if (count != writecount) |
1018 | 0 | break ; |
1019 | 0 | } ; |
1020 | |
|
1021 | 0 | return total ; |
1022 | 0 | } /* nms_adpcm_write_d */ |
1023 | | |
1024 | | int |
1025 | | nms_adpcm_init (SF_PRIVATE *psf) |
1026 | 293 | { NMS_ADPCM_PRIVATE *pnms ; |
1027 | | |
1028 | 293 | if (psf->codec_data != NULL) |
1029 | 0 | { psf_log_printf (psf, "*** psf->codec_data is not NULL.\n") ; |
1030 | 0 | return SFE_INTERNAL ; |
1031 | 293 | } ; |
1032 | | |
1033 | 293 | psf->sf.seekable = SF_FALSE ; |
1034 | | |
1035 | 293 | if (psf->sf.channels != 1) |
1036 | 0 | return SFE_NMS_ADPCM_NOT_MONO ; |
1037 | | |
1038 | 293 | if ((pnms = calloc (1, sizeof (NMS_ADPCM_PRIVATE))) == NULL) |
1039 | 0 | return SFE_MALLOC_FAILED ; |
1040 | | |
1041 | 293 | psf->codec_data = (void*) pnms ; |
1042 | | |
1043 | 293 | pnms->block_curr = 0 ; |
1044 | 293 | pnms->sample_curr = 0 ; |
1045 | | |
1046 | 293 | switch (SF_CODEC (psf->sf.format)) |
1047 | 293 | { case SF_FORMAT_NMS_ADPCM_16 : |
1048 | 226 | pnms->type = NMS16 ; |
1049 | 226 | pnms->shortsperblock = NMS_BLOCK_SHORTS_16 ; |
1050 | 226 | break ; |
1051 | 26 | case SF_FORMAT_NMS_ADPCM_24 : |
1052 | 26 | pnms->type = NMS24 ; |
1053 | 26 | pnms->shortsperblock = NMS_BLOCK_SHORTS_24 ; |
1054 | 26 | break ; |
1055 | 41 | case SF_FORMAT_NMS_ADPCM_32 : |
1056 | 41 | pnms->type = NMS32 ; |
1057 | 41 | pnms->shortsperblock = NMS_BLOCK_SHORTS_32 ; |
1058 | 41 | break ; |
1059 | | |
1060 | 0 | default : return SFE_UNIMPLEMENTED ; |
1061 | 293 | } ; |
1062 | 293 | nms_adpcm_codec_init (&pnms->state, pnms->type) ; |
1063 | | |
1064 | 293 | psf->filelength = psf_get_filelen (psf) ; |
1065 | 293 | if (psf->filelength < psf->dataoffset) |
1066 | 0 | psf->filelength = psf->dataoffset ; |
1067 | | |
1068 | 293 | psf->datalength = psf->filelength - psf->dataoffset ; |
1069 | 293 | if (psf->dataend > 0) |
1070 | 31 | psf->datalength -= psf->filelength - psf->dataend ; |
1071 | | |
1072 | 293 | if (psf->file.mode == SFM_READ) |
1073 | 293 | { psf->read_short = nms_adpcm_read_s ; |
1074 | 293 | psf->read_int = nms_adpcm_read_i ; |
1075 | 293 | psf->read_float = nms_adpcm_read_f ; |
1076 | 293 | psf->read_double = nms_adpcm_read_d ; |
1077 | 293 | } |
1078 | 0 | else if (psf->file.mode == SFM_WRITE) |
1079 | 0 | { psf->write_short = nms_adpcm_write_s ; |
1080 | 0 | psf->write_int = nms_adpcm_write_i ; |
1081 | 0 | psf->write_float = nms_adpcm_write_f ; |
1082 | 0 | psf->write_double = nms_adpcm_write_d ; |
1083 | 0 | } ; |
1084 | | |
1085 | 293 | if (psf->datalength % (pnms->shortsperblock * sizeof (short))) |
1086 | 277 | { psf_log_printf (psf, "*** Odd psf->datalength (%D) should be a multiple of %d\n", |
1087 | 277 | psf->datalength, pnms->shortsperblock * sizeof (short)) ; |
1088 | 277 | pnms->blocks_total = (psf->datalength / (pnms->shortsperblock * sizeof (short))) + 1 ; |
1089 | 277 | } |
1090 | 16 | else |
1091 | 16 | pnms->blocks_total = psf->datalength / (pnms->shortsperblock * sizeof (short)) ; |
1092 | | |
1093 | 293 | psf->sf.frames = (sf_count_t) pnms->blocks_total * NMS_SAMPLES_PER_BLOCK ; |
1094 | 293 | psf->codec_close = nms_adpcm_close ; |
1095 | 293 | psf->seek = nms_adpcm_seek ; |
1096 | | |
1097 | 293 | return 0 ; |
1098 | 293 | } /* nms_adpcm_init */ |
1099 | | |
1100 | | static int |
1101 | | nms_adpcm_close (SF_PRIVATE *psf) |
1102 | 293 | { NMS_ADPCM_PRIVATE *pnms ; |
1103 | | |
1104 | 293 | pnms = (NMS_ADPCM_PRIVATE*) psf->codec_data ; |
1105 | | |
1106 | | /* |
1107 | | ** If a block has been partially assembled, write it out as the final |
1108 | | ** block. |
1109 | | */ |
1110 | 293 | if (psf->file.mode == SFM_WRITE) |
1111 | 0 | { if (pnms->sample_curr && pnms->sample_curr < NMS_SAMPLES_PER_BLOCK) |
1112 | 0 | { memset (pnms->samples + pnms->sample_curr, 0, (NMS_SAMPLES_PER_BLOCK - pnms->sample_curr) * sizeof (short)) ; |
1113 | 0 | psf_nms_adpcm_encode_block (psf, pnms) ; |
1114 | 0 | } |
1115 | |
|
1116 | 0 | if (psf->write_header) |
1117 | 0 | psf->write_header (psf, SF_FALSE) ; |
1118 | 0 | } |
1119 | | |
1120 | 293 | return 0 ; |
1121 | 293 | } /* nms_adpcm_close */ |
1122 | | |
1123 | | static sf_count_t |
1124 | | nms_adpcm_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) |
1125 | 0 | { NMS_ADPCM_PRIVATE *pnms ; |
1126 | |
|
1127 | 0 | pnms = (NMS_ADPCM_PRIVATE *) psf->codec_data ; |
1128 | | |
1129 | | /* |
1130 | | ** NMS ADPCM is symmetric, so transitioning from reading and writing is |
1131 | | ** possible, but unimplemented, as it would require syncing partial blocks. |
1132 | | */ |
1133 | 0 | if (mode != psf->file.mode) |
1134 | 0 | { psf->error = SFE_BAD_SEEK ; |
1135 | 0 | return PSF_SEEK_ERROR ; |
1136 | 0 | } ; |
1137 | | |
1138 | | /* |
1139 | | ** NMS ADPCM cannot be seek'ed, as codec state depends on previous samples, |
1140 | | ** so only a seek to 0 is supported. |
1141 | | */ |
1142 | 0 | if (offset != 0) |
1143 | 0 | { psf->error = SFE_BAD_SEEK ; |
1144 | 0 | return PSF_SEEK_ERROR ; |
1145 | 0 | } ; |
1146 | |
|
1147 | 0 | if (psf_fseek (psf, psf->dataoffset, SEEK_SET) == PSF_SEEK_ERROR) |
1148 | 0 | return PSF_SEEK_ERROR ; |
1149 | | |
1150 | 0 | nms_adpcm_codec_init (&pnms->state, pnms->type) ; |
1151 | 0 | pnms->block_curr = 0 ; |
1152 | 0 | pnms->sample_curr = 0 ; |
1153 | 0 | return 0 ; |
1154 | 0 | } /* nms_adpcm_seek */ |
1155 | | |