Merged with trunk revision 600
[ardour.git] / libs / libsndfile / src / ima_adpcm.c
1 /*
2 ** Copyright (C) 1999-2005 Erik de Castro Lopo <erikd@mega-nerd.com>
3 **
4 ** This program is free software; you can redistribute it and/or modify
5 ** it under the terms of the GNU Lesser General Public License as published by
6 ** the Free Software Foundation; either version 2.1 of the License, or
7 ** (at your option) any later version.
8 **
9 ** This program is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 ** GNU Lesser General Public License for more details.
13 **
14 ** You should have received a copy of the GNU Lesser General Public License
15 ** along with this program; if not, write to the Free Software
16 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 #include        "sfconfig.h"
20
21 #include        <stdio.h>
22 #include        <stdlib.h>
23 #include        <string.h>
24
25 #include        "sndfile.h"
26 #include        "sfendian.h"
27 #include        "float_cast.h"
28 #include        "common.h"
29
30 typedef struct IMA_ADPCM_PRIVATE_tag
31 {       int                     (*decode_block) (SF_PRIVATE *psf, struct IMA_ADPCM_PRIVATE_tag *pima) ;
32         int                     (*encode_block) (SF_PRIVATE *psf, struct IMA_ADPCM_PRIVATE_tag *pima) ;
33
34         int                             channels, blocksize, samplesperblock, blocks ;
35         int                             blockcount, samplecount ;
36         int                             previous [2] ;
37         int                             stepindx [2] ;
38         unsigned char   *block ;
39         short                   *samples ;
40 #if HAVE_FLEXIBLE_ARRAY
41         short                   data    [] ; /* ISO C99 struct flexible array. */
42 #else
43         short                   data    [0] ; /* This is a hack and might not work. */
44 #endif
45 } IMA_ADPCM_PRIVATE ;
46
47 /*============================================================================================
48 ** Predefined IMA ADPCM data.
49 */
50
51 static int ima_indx_adjust [16] =
52 {       -1, -1, -1, -1,         /* +0 - +3, decrease the step size */
53      2,  4,  6,  8,     /* +4 - +7, increase the step size */
54     -1, -1, -1, -1,             /* -0 - -3, decrease the step size */
55      2,  4,  6,  8,             /* -4 - -7, increase the step size */
56 } ;
57
58 static int ima_step_size [89] =
59 {       7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
60         50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230,
61         253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963,
62         1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327,
63         3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493, 10442,
64         11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794,
65         32767
66 } ;
67
68 static int ima_reader_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) ;
69 static int ima_writer_init (SF_PRIVATE *psf, int blockalign) ;
70
71 static int ima_read_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima, short *ptr, int len) ;
72 static int ima_write_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima, const short *ptr, int len) ;
73
74 static sf_count_t ima_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
75 static sf_count_t ima_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
76 static sf_count_t ima_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
77 static sf_count_t ima_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
78
79 static sf_count_t ima_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
80 static sf_count_t ima_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
81 static sf_count_t ima_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
82 static sf_count_t ima_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
83
84 static sf_count_t       ima_seek        (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
85
86 static int      ima_close       (SF_PRIVATE *psf) ;
87
88 static int wav_w64_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) ;
89 static int wav_w64_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) ;
90
91 /*-static int aiff_ima_reader_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) ;-*/
92 static int aiff_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) ;
93 static int aiff_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) ;
94
95
96 /*============================================================================================
97 ** IMA ADPCM Reader initialisation function.
98 */
99
100 int
101 wav_w64_ima_init (SF_PRIVATE *psf, int blockalign, int samplesperblock)
102 {       int error ;
103
104         if (psf->fdata != NULL)
105         {       psf_log_printf (psf, "*** psf->fdata is not NULL.\n") ;
106                 return SFE_INTERNAL ;
107                 } ;
108
109         if (psf->mode == SFM_RDWR)
110                 return SFE_BAD_MODE_RW ;
111
112         if (psf->mode == SFM_READ)
113                 if ((error = ima_reader_init (psf, blockalign, samplesperblock)))
114                         return error ;
115
116         if (psf->mode == SFM_WRITE)
117                 if ((error = ima_writer_init (psf, blockalign)))
118                         return error ;
119
120         psf->codec_close = ima_close ;
121         psf->seek = ima_seek ;
122
123         return 0 ;
124 } /* wav_w64_ima_init */
125
126 int
127 aiff_ima_init (SF_PRIVATE *psf, int blockalign, int samplesperblock)
128 {       int error ;
129
130         if (psf->mode == SFM_RDWR)
131                 return SFE_BAD_MODE_RW ;
132
133         if (psf->mode == SFM_READ)
134                 if ((error = ima_reader_init (psf, blockalign, samplesperblock)))
135                         return error ;
136
137         if (psf->mode == SFM_WRITE)
138                 if ((error = ima_writer_init (psf, blockalign)))
139                         return error ;
140
141         psf->codec_close = ima_close ;
142
143         return 0 ;
144 } /* aiff_ima_init */
145
146 static int
147 ima_close       (SF_PRIVATE *psf)
148 {       IMA_ADPCM_PRIVATE *pima ;
149
150         pima = (IMA_ADPCM_PRIVATE*) psf->fdata ;
151
152         if (psf->mode == SFM_WRITE)
153         {       /*      If a block has been partially assembled, write it out
154                 **      as the final block.
155                 */
156                 if (pima->samplecount && pima->samplecount < pima->samplesperblock)
157                         pima->encode_block (psf, pima) ;
158
159                 psf->sf.frames = pima->samplesperblock * pima->blockcount / psf->sf.channels ;
160                 } ;
161
162         return 0 ;
163 } /* ima_close */
164
165 /*============================================================================================
166 ** IMA ADPCM Read Functions.
167 */
168
169 static int
170 ima_reader_init (SF_PRIVATE *psf, int blockalign, int samplesperblock)
171 {       IMA_ADPCM_PRIVATE       *pima ;
172         int             pimasize, count ;
173
174         if (psf->mode != SFM_READ)
175                 return SFE_BAD_MODE_RW ;
176
177         pimasize = sizeof (IMA_ADPCM_PRIVATE) + blockalign * psf->sf.channels + 3 * psf->sf.channels * samplesperblock ;
178
179         if (! (pima = malloc (pimasize)))
180                 return SFE_MALLOC_FAILED ;
181
182         psf->fdata = (void*) pima ;
183
184         memset (pima, 0, pimasize) ;
185
186         pima->samples   = pima->data ;
187         pima->block             = (unsigned char*) (pima->data + samplesperblock * psf->sf.channels) ;
188
189         pima->channels                  = psf->sf.channels ;
190         pima->blocksize                 = blockalign ;
191         pima->samplesperblock   = samplesperblock ;
192
193         psf->filelength = psf_get_filelen (psf) ;
194         psf->datalength = (psf->dataend) ? psf->dataend - psf->dataoffset :
195                                                         psf->filelength - psf->dataoffset ;
196
197         if (psf->datalength % pima->blocksize)
198                 pima->blocks = psf->datalength / pima->blocksize + 1 ;
199         else
200                 pima->blocks = psf->datalength / pima->blocksize ;
201
202         switch (psf->sf.format & SF_FORMAT_TYPEMASK)
203         {       case SF_FORMAT_WAV :
204                 case SF_FORMAT_W64 :
205                                 count = 2 * (pima->blocksize - 4 * pima->channels) / pima->channels + 1 ;
206
207                                 if (pima->samplesperblock != count)
208                                         psf_log_printf (psf, "*** Warning : samplesperblock should be %d.\n", count) ;
209
210                                 pima->decode_block = wav_w64_ima_decode_block ;
211
212                                 psf->sf.frames = pima->samplesperblock * pima->blocks ;
213                                 break ;
214
215                 case SF_FORMAT_AIFF :
216                                 psf_log_printf (psf, "still need to check block count\n") ;
217                                 pima->decode_block = aiff_ima_decode_block ;
218                                 psf->sf.frames = pima->samplesperblock * pima->blocks / pima->channels ;
219                                 break ;
220
221                 default :
222                                 psf_log_printf (psf, "ima_reader_init: bad psf->sf.format\n") ;
223                                 return SFE_INTERNAL ;
224                                 break ;
225                 } ;
226
227         pima->decode_block (psf, pima) ;        /* Read first block. */
228
229         psf->read_short         = ima_read_s ;
230         psf->read_int           = ima_read_i ;
231         psf->read_float         = ima_read_f ;
232         psf->read_double        = ima_read_d ;
233
234         return 0 ;
235 } /* ima_reader_init */
236
237 static int
238 aiff_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima)
239 {       unsigned char *blockdata ;
240         int             chan, k, diff, bytecode ;
241         short   step, stepindx, predictor, *sampledata ;
242
243 static int count = 0 ;
244 count ++ ;
245
246         pima->blockcount += pima->channels ;
247         pima->samplecount = 0 ;
248
249         if (pima->blockcount > pima->blocks)
250         {       memset (pima->samples, 0, pima->samplesperblock * pima->channels * sizeof (short)) ;
251                 return 1 ;
252                 } ;
253
254         if ((k = psf_fread (pima->block, 1, pima->blocksize * pima->channels, psf)) != pima->blocksize * pima->channels)
255                 psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pima->blocksize) ;
256
257         /* Read and check the block header. */
258         for (chan = 0 ; chan < pima->channels ; chan++)
259         {       blockdata = pima->block + chan * 34 ;
260                 sampledata = pima->samples + chan ;
261
262                 predictor = (blockdata [0] << 8) | (blockdata [1] & 0x80) ;
263                 stepindx = blockdata [1] & 0x7F ;
264
265 {
266 if (count < 5)
267 printf ("\nchan: %d    predictor: %d    stepindx: %d (%d)\n",
268         chan, predictor, stepindx, ima_step_size [stepindx]) ;
269 }
270                 /* FIXME : Do this a better way. */
271                 if (stepindx < 0) stepindx = 0 ;
272                 else if (stepindx > 88) stepindx = 88 ;
273
274                 /*
275                 **      Pull apart the packed 4 bit samples and store them in their
276                 **      correct sample positions.
277                 */
278                 for (k = 0 ; k < pima->blocksize - 2 ; k++)
279                 {       bytecode = blockdata [k + 2] ;
280                         sampledata [pima->channels * (2 * k + 0)] = bytecode & 0xF ;
281                         sampledata [pima->channels * (2 * k + 1)] = (bytecode >> 4) & 0xF ;
282                         } ;
283
284                 /* Decode the encoded 4 bit samples. */
285                 for (k = 0 ; k < pima->samplesperblock ; k ++)
286                 {       step = ima_step_size [stepindx] ;
287
288                         bytecode = pima->samples [pima->channels * k + chan] ;
289
290                         stepindx += ima_indx_adjust [bytecode] ;
291
292                         if (stepindx < 0) stepindx = 0 ;
293                         else if (stepindx > 88) stepindx = 88 ;
294
295                         diff = step >> 3 ;
296                         if (bytecode & 1)       diff += step >> 2 ;
297                         if (bytecode & 2)       diff += step >> 1 ;
298                         if (bytecode & 4)       diff += step ;
299                         if (bytecode & 8)       diff = -diff ;
300
301                         predictor += diff ;
302
303                         pima->samples [pima->channels * k + chan] = predictor ;
304                         } ;
305                 } ;
306
307 if (count < 5)
308 {
309         for (k = 0 ; k < 10 ; k++)
310                 printf ("% 7d,", pima->samples [k]) ;
311         puts ("") ;
312 }
313
314         return 1 ;
315 } /* aiff_ima_decode_block */
316
317 static int
318 aiff_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima)
319 {       int             chan, k, step, diff, vpdiff, blockindx, indx ;
320         short   bytecode, mask ;
321
322 static int count = 0 ;
323 if (0 && count == 0)
324 {       pima->samples [0] = 0 ;
325         printf ("blocksize : %d\n", pima->blocksize) ;
326         printf ("pima->stepindx [0] : %d\n", pima->stepindx [0]) ;
327         }
328 count ++ ;
329
330         /* Encode the block header. */
331         for (chan = 0 ; chan < pima->channels ; chan ++)
332         {       blockindx = chan * pima->blocksize ;
333
334                 pima->block [blockindx] = (pima->samples [chan] >> 8) & 0xFF ;
335                 pima->block [blockindx + 1] = (pima->samples [chan] & 0x80) + (pima->stepindx [chan] & 0x7F) ;
336
337                 pima->previous [chan] = pima->samples [chan] ;
338                 } ;
339
340         /* Encode second and later samples for every block as a 4 bit value. */
341         for (k = pima->channels ; k < (pima->samplesperblock * pima->channels) ; k ++)
342         {       chan = (pima->channels > 1) ? (k % 2) : 0 ;
343
344                 diff = pima->samples [k] - pima->previous [chan] ;
345
346                 bytecode = 0 ;
347                 step = ima_step_size [pima->stepindx [chan]] ;
348                 vpdiff = step >> 3 ;
349                 if (diff < 0)
350                 {       bytecode = 8 ;
351                         diff = -diff ;
352                         } ;
353                 mask = 4 ;
354                 while (mask)
355                 {       if (diff >= step)
356                         {       bytecode |= mask ;
357                                 diff -= step ;
358                                 vpdiff += step ;
359                                 } ;
360                         step >>= 1 ;
361                         mask >>= 1 ;
362                         } ;
363
364                 if (bytecode & 8)
365                         pima->previous [chan] -= vpdiff ;
366                 else
367                         pima->previous [chan] += vpdiff ;
368
369                 if (pima->previous [chan] > 32767)
370                         pima->previous [chan] = 32767 ;
371                 else if (pima->previous [chan] < -32768)
372                         pima->previous [chan] = -32768 ;
373
374                 pima->stepindx [chan] += ima_indx_adjust [bytecode] ;
375                 if (pima->stepindx [chan] < 0)
376                         pima->stepindx [chan] = 0 ;
377                 else if (pima->stepindx [chan] > 88)
378                         pima->stepindx [chan] = 88 ;
379
380                 pima->samples [k] = bytecode ;
381                 } ;
382
383         /* Pack the 4 bit encoded samples. */
384
385         for (chan = 0 ; chan < pima->channels ; chan ++)
386         {       for (indx = pima->channels ; indx < pima->channels * pima->samplesperblock ; indx += 2 * pima->channels)
387                 {       blockindx = chan * pima->blocksize + 2 + indx / 2 ;
388
389 if (0 && count ++ < 5)
390         printf ("chan: %d    blockindx: %3d    indx: %3d\n", chan, blockindx, indx) ;
391
392                         pima->block [blockindx] = pima->samples [indx] & 0x0F ;
393                         pima->block [blockindx] |= (pima->samples [indx + pima->channels] << 4) & 0xF0 ;
394                         } ;
395                 } ;
396
397         /* Write the block to disk. */
398
399         if ((k = psf_fwrite (pima->block, 1, pima->channels * pima->blocksize, psf)) != pima->channels * pima->blocksize)
400                 psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pima->channels * pima->blocksize) ;
401
402         memset (pima->samples, 0, pima->channels * pima->samplesperblock * sizeof (short)) ;
403         pima->samplecount = 0 ;
404         pima->blockcount ++ ;
405
406         return 1 ;
407 } /* aiff_ima_encode_block */
408
409 static int
410 wav_w64_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima)
411 {       int             chan, k, current, blockindx, indx, indxstart, diff ;
412         short   step, bytecode, stepindx [2] ;
413
414         pima->blockcount ++ ;
415         pima->samplecount = 0 ;
416
417         if (pima->blockcount > pima->blocks)
418         {       memset (pima->samples, 0, pima->samplesperblock * pima->channels * sizeof (short)) ;
419                 return 1 ;
420                 } ;
421
422         if ((k = psf_fread (pima->block, 1, pima->blocksize, psf)) != pima->blocksize)
423                 psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pima->blocksize) ;
424
425         /* Read and check the block header. */
426
427         for (chan = 0 ; chan < pima->channels ; chan++)
428         {       current = pima->block [chan*4] | (pima->block [chan*4+1] << 8) ;
429                 if (current & 0x8000)
430                         current -= 0x10000 ;
431
432                 stepindx [chan] = pima->block [chan*4+2] ;
433                 if (stepindx [chan] < 0)
434                         stepindx [chan] = 0 ;
435                 else if (stepindx [chan] > 88)
436                         stepindx [chan] = 88 ;
437
438                 if (pima->block [chan*4+3] != 0)
439                         psf_log_printf (psf, "IMA ADPCM synchronisation error.\n") ;
440
441                 pima->samples [chan] = current ;
442                 } ;
443
444         /*
445         **      Pull apart the packed 4 bit samples and store them in their
446         **      correct sample positions.
447         */
448
449         blockindx = 4 * pima->channels ;
450
451         indxstart = pima->channels ;
452         while (blockindx < pima->blocksize)
453         {       for (chan = 0 ; chan < pima->channels ; chan++)
454                 {       indx = indxstart + chan ;
455                         for (k = 0 ; k < 4 ; k++)
456                         {       bytecode = pima->block [blockindx++] ;
457                                 pima->samples [indx] = bytecode & 0x0F ;
458                                 indx += pima->channels ;
459                                 pima->samples [indx] = (bytecode >> 4) & 0x0F ;
460                                 indx += pima->channels ;
461                                 } ;
462                         } ;
463                 indxstart += 8 * pima->channels ;
464                 } ;
465
466         /* Decode the encoded 4 bit samples. */
467
468         for (k = pima->channels ; k < (pima->samplesperblock * pima->channels) ; k ++)
469         {       chan = (pima->channels > 1) ? (k % 2) : 0 ;
470
471                 bytecode = pima->samples [k] & 0xF ;
472
473                 step = ima_step_size [stepindx [chan]] ;
474                 current = pima->samples [k - pima->channels] ;
475
476                 diff = step >> 3 ;
477                 if (bytecode & 1)
478                         diff += step >> 2 ;
479                 if (bytecode & 2)
480                         diff += step >> 1 ;
481                 if (bytecode & 4)
482                         diff += step ;
483                 if (bytecode & 8)
484                         diff = -diff ;
485
486                 current += diff ;
487
488                 if (current > 32767)
489                         current = 32767 ;
490                 else if (current < -32768)
491                         current = -32768 ;
492
493                 stepindx [chan] += ima_indx_adjust [bytecode] ;
494
495                 if (stepindx [chan] < 0)
496                         stepindx [chan] = 0 ;
497                 else if (stepindx [chan] > 88)
498                         stepindx [chan] = 88 ;
499
500                 pima->samples [k] = current ;
501                 } ;
502
503         return 1 ;
504 } /* wav_w64_ima_decode_block */
505
506 static int
507 wav_w64_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima)
508 {       int             chan, k, step, diff, vpdiff, blockindx, indx, indxstart ;
509         short   bytecode, mask ;
510
511         /* Encode the block header. */
512         for (chan = 0 ; chan < pima->channels ; chan++)
513         {       pima->block [chan*4]    = pima->samples [chan] & 0xFF ;
514                 pima->block [chan*4+1]  = (pima->samples [chan] >> 8) & 0xFF ;
515
516                 pima->block [chan*4+2] = pima->stepindx [chan] ;
517                 pima->block [chan*4+3] = 0 ;
518
519                 pima->previous [chan] = pima->samples [chan] ;
520                 } ;
521
522         /* Encode the samples as 4 bit. */
523
524         for (k = pima->channels ; k < (pima->samplesperblock * pima->channels) ; k ++)
525         {       chan = (pima->channels > 1) ? (k % 2) : 0 ;
526
527                 diff = pima->samples [k] - pima->previous [chan] ;
528
529                 bytecode = 0 ;
530                 step = ima_step_size [pima->stepindx [chan]] ;
531                 vpdiff = step >> 3 ;
532                 if (diff < 0)
533                 {       bytecode = 8 ;
534                         diff = -diff ;
535                         } ;
536                 mask = 4 ;
537                 while (mask)
538                 {       if (diff >= step)
539                         {       bytecode |= mask ;
540                                 diff -= step ;
541                                 vpdiff += step ;
542                                 } ;
543                         step >>= 1 ;
544                         mask >>= 1 ;
545                         } ;
546
547                 if (bytecode & 8)
548                         pima->previous [chan] -= vpdiff ;
549                 else
550                         pima->previous [chan] += vpdiff ;
551
552                 if (pima->previous [chan] > 32767)
553                         pima->previous [chan] = 32767 ;
554                 else if (pima->previous [chan] < -32768)
555                         pima->previous [chan] = -32768 ;
556
557                 pima->stepindx [chan] += ima_indx_adjust [bytecode] ;
558                 if (pima->stepindx [chan] < 0)
559                         pima->stepindx [chan] = 0 ;
560                 else if (pima->stepindx [chan] > 88)
561                         pima->stepindx [chan] = 88 ;
562
563                 pima->samples [k] = bytecode ;
564                 } ;
565
566         /* Pack the 4 bit encoded samples. */
567
568         blockindx = 4 * pima->channels ;
569
570         indxstart = pima->channels ;
571         while (blockindx < pima->blocksize)
572         {       for (chan = 0 ; chan < pima->channels ; chan++)
573                 {       indx = indxstart + chan ;
574                         for (k = 0 ; k < 4 ; k++)
575                         {       pima->block [blockindx] = pima->samples [indx] & 0x0F ;
576                                 indx += pima->channels ;
577                                 pima->block [blockindx] |= (pima->samples [indx] << 4) & 0xF0 ;
578                                 indx += pima->channels ;
579                                 blockindx ++ ;
580                                 } ;
581                         } ;
582                 indxstart += 8 * pima->channels ;
583                 } ;
584
585         /* Write the block to disk. */
586
587         if ((k = psf_fwrite (pima->block, 1, pima->blocksize, psf)) != pima->blocksize)
588                 psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pima->blocksize) ;
589
590         memset (pima->samples, 0, pima->samplesperblock * sizeof (short)) ;
591         pima->samplecount = 0 ;
592         pima->blockcount ++ ;
593
594         return 1 ;
595 } /* wav_w64_ima_encode_block */
596
597 static int
598 ima_read_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima, short *ptr, int len)
599 {       int             count, total = 0, indx = 0 ;
600
601         while (indx < len)
602         {       if (pima->blockcount >= pima->blocks && pima->samplecount >= pima->samplesperblock)
603                 {       memset (&(ptr [indx]), 0, (size_t) ((len - indx) * sizeof (short))) ;
604                         return total ;
605                         } ;
606
607                 if (pima->samplecount >= pima->samplesperblock)
608                         pima->decode_block (psf, pima) ;
609
610                 count = (pima->samplesperblock - pima->samplecount) * pima->channels ;
611                 count = (len - indx > count) ? count : len - indx ;
612
613                 memcpy (&(ptr [indx]), &(pima->samples [pima->samplecount * pima->channels]), count * sizeof (short)) ;
614                 indx += count ;
615                 pima->samplecount += count / pima->channels ;
616                 total = indx ;
617                 } ;
618
619         return total ;
620 } /* ima_read_block */
621
622 static sf_count_t
623 ima_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
624 {       IMA_ADPCM_PRIVATE       *pima ;
625         int                     readcount, count ;
626         sf_count_t      total = 0 ;
627
628         if (! psf->fdata)
629                 return 0 ;
630         pima = (IMA_ADPCM_PRIVATE*) psf->fdata ;
631
632         while (len > 0)
633         {       readcount = (len > 0x10000000) ? 0x10000000 : (int) len ;
634
635                 count = ima_read_block (psf, pima, ptr, readcount) ;
636
637                 total += count ;
638                 len -= count ;
639                 if (count != readcount)
640                         break ;
641                 } ;
642
643         return total ;
644 } /* ima_read_s */
645
646 static sf_count_t
647 ima_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
648 {       IMA_ADPCM_PRIVATE *pima ;
649         short           *sptr ;
650         int                     k, bufferlen, readcount, count ;
651         sf_count_t      total = 0 ;
652
653         if (! psf->fdata)
654                 return 0 ;
655         pima = (IMA_ADPCM_PRIVATE*) psf->fdata ;
656
657         sptr = psf->u.sbuf ;
658         bufferlen = ARRAY_LEN (psf->u.sbuf) ;
659         while (len > 0)
660         {       readcount = (len >= bufferlen) ? bufferlen : (int) len ;
661                 count = ima_read_block (psf, pima, sptr, readcount) ;
662                 for (k = 0 ; k < readcount ; k++)
663                         ptr [total + k] = ((int) sptr [k]) << 16 ;
664                 total += count ;
665                 len -= readcount ;
666                 if (count != readcount)
667                         break ;
668                 } ;
669
670         return total ;
671 } /* ima_read_i */
672
673 static sf_count_t
674 ima_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
675 {       IMA_ADPCM_PRIVATE *pima ;
676         short           *sptr ;
677         int                     k, bufferlen, readcount, count ;
678         sf_count_t      total = 0 ;
679         float           normfact ;
680
681         if (! psf->fdata)
682                 return 0 ;
683         pima = (IMA_ADPCM_PRIVATE*) psf->fdata ;
684
685         normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ;
686
687         sptr = psf->u.sbuf ;
688         bufferlen = ARRAY_LEN (psf->u.sbuf) ;
689         while (len > 0)
690         {       readcount = (len >= bufferlen) ? bufferlen : (int) len ;
691                 count = ima_read_block (psf, pima, sptr, readcount) ;
692                 for (k = 0 ; k < readcount ; k++)
693                         ptr [total + k] = normfact * (float) (sptr [k]) ;
694                 total += count ;
695                 len -= readcount ;
696                 if (count != readcount)
697                         break ;
698                 } ;
699
700         return total ;
701 } /* ima_read_f */
702
703 static sf_count_t
704 ima_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
705 {       IMA_ADPCM_PRIVATE *pima ;
706         short           *sptr ;
707         int                     k, bufferlen, readcount, count ;
708         sf_count_t      total = 0 ;
709         double          normfact ;
710
711         if (! psf->fdata)
712                 return 0 ;
713         pima = (IMA_ADPCM_PRIVATE*) psf->fdata ;
714
715         normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ;
716
717         sptr = psf->u.sbuf ;
718         bufferlen = ARRAY_LEN (psf->u.sbuf) ;
719         while (len > 0)
720         {       readcount = (len >= bufferlen) ? bufferlen : (int) len ;
721                 count = ima_read_block (psf, pima, sptr, readcount) ;
722                 for (k = 0 ; k < readcount ; k++)
723                         ptr [total + k] = normfact * (double) (sptr [k]) ;
724                 total += count ;
725                 len -= readcount ;
726                 if (count != readcount)
727                         break ;
728                 } ;
729
730         return total ;
731 } /* ima_read_d */
732
733 static sf_count_t
734 ima_seek (SF_PRIVATE *psf, int mode, sf_count_t offset)
735 {       IMA_ADPCM_PRIVATE *pima ;
736         int                     newblock, newsample ;
737
738         if (! psf->fdata)
739                 return 0 ;
740         pima = (IMA_ADPCM_PRIVATE*) psf->fdata ;
741
742         if (psf->datalength < 0 || psf->dataoffset < 0)
743         {       psf->error = SFE_BAD_SEEK ;
744                 return PSF_SEEK_ERROR ;
745                 } ;
746
747         if (offset == 0)
748         {       psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
749                 pima->blockcount = 0 ;
750                 pima->decode_block (psf, pima) ;
751                 pima->samplecount = 0 ;
752                 return 0 ;
753                 } ;
754
755         if (offset < 0 || offset > pima->blocks * pima->samplesperblock)
756         {       psf->error = SFE_BAD_SEEK ;
757                 return  PSF_SEEK_ERROR ;
758                 } ;
759
760         newblock        = offset / pima->samplesperblock ;
761         newsample       = offset % pima->samplesperblock ;
762
763         if (mode == SFM_READ)
764         {       psf_fseek (psf, psf->dataoffset + newblock * pima->blocksize, SEEK_SET) ;
765                 pima->blockcount = newblock ;
766                 pima->decode_block (psf, pima) ;
767                 pima->samplecount = newsample ;
768                 }
769         else
770         {       /* What to do about write??? */
771                 psf->error = SFE_BAD_SEEK ;
772                 return  PSF_SEEK_ERROR ;
773                 } ;
774
775         return newblock * pima->samplesperblock + newsample ;
776 } /* ima_seek */
777
778 /*==========================================================================================
779 ** IMA ADPCM Write Functions.
780 */
781
782 static int
783 ima_writer_init (SF_PRIVATE *psf, int blockalign)
784 {       IMA_ADPCM_PRIVATE       *pima ;
785         int                                     samplesperblock ;
786         unsigned int            pimasize ;
787
788         if (psf->mode != SFM_WRITE)
789                 return SFE_BAD_MODE_RW ;
790
791         samplesperblock = 2 * (blockalign - 4 * psf->sf.channels) / psf->sf.channels + 1 ;
792
793         pimasize = sizeof (IMA_ADPCM_PRIVATE) + blockalign + 3 * psf->sf.channels * samplesperblock ;
794
795         if ((pima = calloc (1, pimasize)) == NULL)
796                 return SFE_MALLOC_FAILED ;
797
798         psf->fdata = (void*) pima ;
799
800         pima->channels                  = psf->sf.channels ;
801         pima->blocksize                 = blockalign ;
802         pima->samplesperblock   = samplesperblock ;
803
804         pima->block             = (unsigned char*) pima->data ;
805         pima->samples   = (short*) (pima->data + blockalign) ;
806
807         pima->samplecount = 0 ;
808
809         switch (psf->sf.format & SF_FORMAT_TYPEMASK)
810         {       case SF_FORMAT_WAV :
811                 case SF_FORMAT_W64 :
812                                 pima->encode_block = wav_w64_ima_encode_block ;
813                                 break ;
814
815                 case SF_FORMAT_AIFF :
816                                 pima->encode_block = aiff_ima_encode_block ;
817                                 break ;
818
819                 default :
820                                 psf_log_printf (psf, "ima_reader_init: bad psf->sf.format\n") ;
821                                 return SFE_INTERNAL ;
822                                 break ;
823                 } ;
824
825         psf->write_short        = ima_write_s ;
826         psf->write_int          = ima_write_i ;
827         psf->write_float        = ima_write_f ;
828         psf->write_double       = ima_write_d ;
829
830         return 0 ;
831 } /* ima_writer_init */
832
833 /*==========================================================================================
834 */
835
836 static int
837 ima_write_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima, const short *ptr, int len)
838 {       int             count, total = 0, indx = 0 ;
839
840         while (indx < len)
841         {       count = (pima->samplesperblock - pima->samplecount) * pima->channels ;
842
843                 if (count > len - indx)
844                         count = len - indx ;
845
846                 memcpy (&(pima->samples [pima->samplecount * pima->channels]), &(ptr [total]), count * sizeof (short)) ;
847                 indx += count ;
848                 pima->samplecount += count / pima->channels ;
849                 total = indx ;
850
851                 if (pima->samplecount >= pima->samplesperblock)
852                         pima->encode_block (psf, pima) ;
853                 } ;
854
855         return total ;
856 } /* ima_write_block */
857
858 static sf_count_t
859 ima_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
860 {       IMA_ADPCM_PRIVATE       *pima ;
861         int                     writecount, count ;
862         sf_count_t      total = 0 ;
863
864         if (! psf->fdata)
865                 return 0 ;
866         pima = (IMA_ADPCM_PRIVATE*) psf->fdata ;
867
868         while (len)
869         {       writecount = (len > 0x10000000) ? 0x10000000 : (int) len ;
870
871                 count = ima_write_block (psf, pima, ptr, writecount) ;
872
873                 total += count ;
874                 len -= count ;
875                 if (count != writecount)
876                         break ;
877                 } ;
878
879         return total ;
880 } /* ima_write_s */
881
882 static sf_count_t
883 ima_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
884 {       IMA_ADPCM_PRIVATE *pima ;
885         short           *sptr ;
886         int                     k, bufferlen, writecount, count ;
887         sf_count_t      total = 0 ;
888
889         if (! psf->fdata)
890                 return 0 ;
891         pima = (IMA_ADPCM_PRIVATE*) psf->fdata ;
892
893         sptr = psf->u.sbuf ;
894         bufferlen = ARRAY_LEN (psf->u.sbuf) ;
895         while (len > 0)
896         {       writecount = (len >= bufferlen) ? bufferlen : (int) len ;
897                 for (k = 0 ; k < writecount ; k++)
898                         sptr [k] = ptr [total + k] >> 16 ;
899                 count = ima_write_block (psf, pima, sptr, writecount) ;
900                 total += count ;
901                 len -= writecount ;
902                 if (count != writecount)
903                         break ;
904                 } ;
905
906         return total ;
907 } /* ima_write_i */
908
909 static sf_count_t
910 ima_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
911 {       IMA_ADPCM_PRIVATE *pima ;
912         short           *sptr ;
913         int                     k, bufferlen, writecount, count ;
914         sf_count_t      total = 0 ;
915         float           normfact ;
916
917         if (! psf->fdata)
918                 return 0 ;
919         pima = (IMA_ADPCM_PRIVATE*) psf->fdata ;
920
921         normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ;
922
923         sptr = psf->u.sbuf ;
924         bufferlen = ARRAY_LEN (psf->u.sbuf) ;
925         while (len > 0)
926         {       writecount = (len >= bufferlen) ? bufferlen : (int) len ;
927                 for (k = 0 ; k < writecount ; k++)
928                         sptr [k] = lrintf (normfact * ptr [total + k]) ;
929                 count = ima_write_block (psf, pima, sptr, writecount) ;
930                 total += count ;
931                 len -= writecount ;
932                 if (count != writecount)
933                         break ;
934                 } ;
935
936         return total ;
937 } /* ima_write_f */
938
939 static sf_count_t
940 ima_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
941 {       IMA_ADPCM_PRIVATE *pima ;
942         short           *sptr ;
943         int                     k, bufferlen, writecount, count ;
944         sf_count_t      total = 0 ;
945         double          normfact ;
946
947         if (! psf->fdata)
948                 return 0 ;
949         pima = (IMA_ADPCM_PRIVATE*) psf->fdata ;
950
951         normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ;
952
953         sptr = psf->u.sbuf ;
954         bufferlen = ARRAY_LEN (psf->u.sbuf) ;
955         while (len > 0)
956         {       writecount = (len >= bufferlen) ? bufferlen : (int) len ;
957                 for (k = 0 ; k < writecount ; k++)
958                         sptr [k] = lrint (normfact * ptr [total + k]) ;
959                 count = ima_write_block (psf, pima, sptr, writecount) ;
960                 total += count ;
961                 len -= writecount ;
962                 if (count != writecount)
963                         break ;
964                 } ;
965
966         return total ;
967 } /* ima_write_d */
968
969
970 /*
971 ** Do not edit or modify anything in this comment block.
972 ** The arch-tag line is a file identity tag for the GNU Arch 
973 ** revision control system.
974 **
975 ** arch-tag: 75a54b82-ad18-4758-9933-64e00a7f24e0
976 */