pulling trunk
[ardour.git] / libs / libsndfile / src / vox_adpcm.c
1 /*
2 ** Copyright (C) 2002-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 /*
20 **      This is the OKI / Dialogic ADPCM encoder/decoder. It converts from
21 **      12 bit linear sample data to a 4 bit ADPCM.
22 **
23 **      Implemented from the description found here:
24 **
25 **              http://www.comptek.ru:8100/telephony/tnotes/tt1-13.html
26 **
27 **      and compared against the encoder/decoder found here:
28 **
29 **              http://ibiblio.org/pub/linux/apps/sound/convert/vox.tar.gz
30 */
31
32 #include        "sfconfig.h"
33
34 #include        <stdio.h>
35 #include        <stdlib.h>
36 #include        <string.h>
37
38 #include        "sndfile.h"
39 #include        "sfendian.h"
40 #include        "float_cast.h"
41 #include        "common.h"
42
43 #define         VOX_DATA_LEN    2048
44 #define         PCM_DATA_LEN    (VOX_DATA_LEN *2)
45
46 typedef struct
47 {       short last ;
48         short step_index ;
49
50         int             vox_bytes, pcm_samples ;
51
52         unsigned char   vox_data [VOX_DATA_LEN] ;
53         short                   pcm_data [PCM_DATA_LEN] ;
54 } VOX_ADPCM_PRIVATE ;
55
56 static int vox_adpcm_encode_block (VOX_ADPCM_PRIVATE *pvox) ;
57 static int vox_adpcm_decode_block (VOX_ADPCM_PRIVATE *pvox) ;
58
59 static short vox_adpcm_decode (char code, VOX_ADPCM_PRIVATE *pvox) ;
60 static char vox_adpcm_encode (short samp, VOX_ADPCM_PRIVATE *pvox) ;
61
62 static sf_count_t vox_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
63 static sf_count_t vox_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
64 static sf_count_t vox_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
65 static sf_count_t vox_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
66
67 static sf_count_t vox_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
68 static sf_count_t vox_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
69 static sf_count_t vox_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
70 static sf_count_t vox_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
71
72 static int vox_read_block (SF_PRIVATE *psf, VOX_ADPCM_PRIVATE *pvox, short *ptr, int len) ;
73
74 /*============================================================================================
75 ** Predefined OKI ADPCM encoder/decoder tables.
76 */
77
78 static short step_size_table [49] =
79 {       16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60,
80         66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209,
81         230, 253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658,
82         724, 796, 876, 963, 1060, 1166, 1282, 1408, 1552
83 } ; /* step_size_table */
84
85 static short step_adjust_table [8] =
86 {       -1, -1, -1, -1, 2, 4, 6, 8
87 } ; /* step_adjust_table */
88
89 /*------------------------------------------------------------------------------
90 */
91
92 int
93 vox_adpcm_init (SF_PRIVATE *psf)
94 {       VOX_ADPCM_PRIVATE *pvox = NULL ;
95
96         if (psf->mode == SFM_RDWR)
97                 return SFE_BAD_MODE_RW ;
98
99         if (psf->mode == SFM_WRITE && psf->sf.channels != 1)
100                 return SFE_CHANNEL_COUNT ;
101
102         if ((pvox = malloc (sizeof (VOX_ADPCM_PRIVATE))) == NULL)
103                 return SFE_MALLOC_FAILED ;
104
105         psf->fdata = (void*) pvox ;
106         memset (pvox, 0, sizeof (VOX_ADPCM_PRIVATE)) ;
107
108         if (psf->mode == SFM_WRITE)
109         {       psf->write_short        = vox_write_s ;
110                 psf->write_int          = vox_write_i ;
111                 psf->write_float        = vox_write_f ;
112                 psf->write_double       = vox_write_d ;
113                 }
114         else
115         {       psf_log_printf (psf, "Header-less OKI Dialogic ADPCM encoded file.\n") ;
116                 psf_log_printf (psf, "Setting up for 8kHz, mono, Vox ADPCM.\n") ;
117
118                 psf->read_short         = vox_read_s ;
119                 psf->read_int           = vox_read_i ;
120                 psf->read_float         = vox_read_f ;
121                 psf->read_double        = vox_read_d ;
122                 } ;
123
124         /* Standard sample rate chennels etc. */
125         if (psf->sf.samplerate < 1)
126                 psf->sf.samplerate      = 8000 ;
127         psf->sf.channels        = 1 ;
128
129         psf->sf.frames = psf->filelength * 2 ;
130
131         psf->sf.seekable = SF_FALSE ;
132
133         /* Seek back to start of data. */
134         if (psf_fseek (psf, 0 , SEEK_SET) == -1)
135                 return SFE_BAD_SEEK ;
136
137         return 0 ;
138 } /* vox_adpcm_init */
139
140 /*------------------------------------------------------------------------------
141 */
142
143 static char
144 vox_adpcm_encode (short samp, VOX_ADPCM_PRIVATE *pvox)
145 {       short code ;
146         short diff, error, stepsize ;
147
148         stepsize = step_size_table [pvox->step_index] ;
149         code = 0 ;
150
151         diff = samp - pvox->last ;
152         if (diff < 0)
153         {       code = 0x08 ;
154                 error = -diff ;
155                 }
156         else
157                 error = diff ;
158
159         if (error >= stepsize)
160         {       code = code | 0x04 ;
161                 error -= stepsize ;
162                 } ;
163
164         if (error >= stepsize / 2)
165         {       code = code | 0x02 ;
166                 error -= stepsize / 2 ;
167                 } ;
168
169         if (error >= stepsize / 4)
170                 code = code | 0x01 ;
171
172         /*
173         ** To close the feedback loop, the deocder is used to set the
174         ** estimate of last sample and in doing so, also set the step_index.
175         */
176         pvox->last = vox_adpcm_decode (code, pvox) ;
177
178         return code ;
179 } /* vox_adpcm_encode */
180
181 static short
182 vox_adpcm_decode (char code, VOX_ADPCM_PRIVATE *pvox)
183 {       short diff, error, stepsize, samp ;
184
185         stepsize = step_size_table [pvox->step_index] ;
186
187         error = stepsize / 8 ;
188
189         if (code & 0x01)
190                 error += stepsize / 4 ;
191
192         if (code & 0x02)
193                 error += stepsize / 2 ;
194
195         if (code & 0x04)
196                 error += stepsize ;
197
198         diff = (code & 0x08) ? -error : error ;
199         samp = pvox->last + diff ;
200
201         /*
202         **  Apply clipping.
203         */
204         if (samp > 2048)
205                 samp = 2048 ;
206         if (samp < -2048)
207                 samp = -2048 ;
208
209         pvox->last = samp ;
210         pvox->step_index += step_adjust_table [code & 0x7] ;
211
212         if (pvox->step_index < 0)
213                 pvox->step_index = 0 ;
214         if (pvox->step_index > 48)
215                 pvox->step_index = 48 ;
216
217         return samp ;
218 } /* vox_adpcm_decode */
219
220 static int
221 vox_adpcm_encode_block (VOX_ADPCM_PRIVATE *pvox)
222 {       unsigned char code ;
223         int j, k ;
224
225         /* If data_count is odd, add an extra zero valued sample. */
226         if (pvox->pcm_samples & 1)
227                 pvox->pcm_data [pvox->pcm_samples++] = 0 ;
228
229         for (j = k = 0 ; k < pvox->pcm_samples ; j++)
230         {       code = vox_adpcm_encode (pvox->pcm_data [k++] / 16, pvox) << 4 ;
231                 code |= vox_adpcm_encode (pvox->pcm_data [k++] / 16, pvox) ;
232                 pvox->vox_data [j] = code ;
233                 } ;
234
235         pvox->vox_bytes = j ;
236
237         return 0 ;
238 } /* vox_adpcm_encode_block */
239
240 static int
241 vox_adpcm_decode_block (VOX_ADPCM_PRIVATE *pvox)
242 {       unsigned char code ;
243         int j, k ;
244
245         for (j = k = 0 ; j < pvox->vox_bytes ; j++)
246         {       code = pvox->vox_data [j] ;
247                 pvox->pcm_data [k++] = 16 * vox_adpcm_decode ((code >> 4) & 0x0f, pvox) ;
248                 pvox->pcm_data [k++] = 16 * vox_adpcm_decode (code & 0x0f, pvox) ;
249                 } ;
250
251         pvox->pcm_samples = k ;
252
253         return 0 ;
254 } /* vox_adpcm_decode_block */
255
256 /*==============================================================================
257 */
258
259 static int
260 vox_read_block (SF_PRIVATE *psf, VOX_ADPCM_PRIVATE *pvox, short *ptr, int len)
261 {       int     indx = 0, k ;
262
263         while (indx < len)
264         {       pvox->vox_bytes = (len - indx > PCM_DATA_LEN) ? VOX_DATA_LEN : (len - indx + 1) / 2 ;
265
266                 if ((k = psf_fread (pvox->vox_data, 1, pvox->vox_bytes, psf)) != pvox->vox_bytes)
267                 {       if (psf_ftell (psf) + k != psf->filelength)
268                                 psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pvox->vox_bytes) ;
269                         if (k == 0)
270                                 break ;
271                         } ;
272
273                 pvox->vox_bytes = k ;
274
275                 vox_adpcm_decode_block (pvox) ;
276
277                 memcpy (&(ptr [indx]), pvox->pcm_data, pvox->pcm_samples * sizeof (short)) ;
278                 indx += pvox->pcm_samples ;
279                 } ;
280
281         return indx ;
282 } /* vox_read_block */
283
284
285 static sf_count_t
286 vox_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
287 {       VOX_ADPCM_PRIVATE       *pvox ;
288         int                     readcount, count ;
289         sf_count_t      total = 0 ;
290
291         if (! psf->fdata)
292                 return 0 ;
293         pvox = (VOX_ADPCM_PRIVATE*) psf->fdata ;
294
295         while (len > 0)
296         {       readcount = (len > 0x10000000) ? 0x10000000 : (int) len ;
297
298                 count = vox_read_block (psf, pvox, ptr, readcount) ;
299
300                 total += count ;
301                 len -= count ;
302                 if (count != readcount)
303                         break ;
304                 } ;
305
306         return total ;
307 } /* vox_read_s */
308
309 static sf_count_t
310 vox_read_i      (SF_PRIVATE *psf, int *ptr, sf_count_t len)
311 {       VOX_ADPCM_PRIVATE *pvox ;
312         short           *sptr ;
313         int                     k, bufferlen, readcount, count ;
314         sf_count_t      total = 0 ;
315
316         if (! psf->fdata)
317                 return 0 ;
318         pvox = (VOX_ADPCM_PRIVATE*) psf->fdata ;
319
320         sptr = psf->u.sbuf ;
321         bufferlen = ARRAY_LEN (psf->u.sbuf) ;
322         while (len > 0)
323         {       readcount = (len >= bufferlen) ? bufferlen : (int) len ;
324                 count = vox_read_block (psf, pvox, sptr, readcount) ;
325                 for (k = 0 ; k < readcount ; k++)
326                         ptr [total + k] = ((int) sptr [k]) << 16 ;
327                 total += count ;
328                 len -= readcount ;
329                 if (count != readcount)
330                         break ;
331                 } ;
332
333         return total ;
334 } /* vox_read_i */
335
336 static sf_count_t
337 vox_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
338 {       VOX_ADPCM_PRIVATE *pvox ;
339         short           *sptr ;
340         int                     k, bufferlen, readcount, count ;
341         sf_count_t      total = 0 ;
342         float           normfact ;
343
344         if (! psf->fdata)
345                 return 0 ;
346         pvox = (VOX_ADPCM_PRIVATE*) psf->fdata ;
347
348         normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ;
349
350         sptr = psf->u.sbuf ;
351         bufferlen = ARRAY_LEN (psf->u.sbuf) ;
352         while (len > 0)
353         {       readcount = (len >= bufferlen) ? bufferlen : (int) len ;
354                 count = vox_read_block (psf, pvox, sptr, readcount) ;
355                 for (k = 0 ; k < readcount ; k++)
356                         ptr [total + k] = normfact * (float) (sptr [k]) ;
357                 total += count ;
358                 len -= readcount ;
359                 if (count != readcount)
360                         break ;
361                 } ;
362
363         return total ;
364 } /* vox_read_f */
365
366 static sf_count_t
367 vox_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
368 {       VOX_ADPCM_PRIVATE *pvox ;
369         short           *sptr ;
370         int                     k, bufferlen, readcount, count ;
371         sf_count_t      total = 0 ;
372         double          normfact ;
373
374         if (! psf->fdata)
375                 return 0 ;
376         pvox = (VOX_ADPCM_PRIVATE*) psf->fdata ;
377
378         normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ;
379
380         sptr = psf->u.sbuf ;
381         bufferlen = ARRAY_LEN (psf->u.sbuf) ;
382         while (len > 0)
383         {       readcount = (len >= bufferlen) ? bufferlen : (int) len ;
384                 count = vox_read_block (psf, pvox, sptr, readcount) ;
385                 for (k = 0 ; k < readcount ; k++)
386                         ptr [total + k] = normfact * (double) (sptr [k]) ;
387                 total += count ;
388                 len -= readcount ;
389                 if (count != readcount)
390                         break ;
391                 } ;
392
393         return total ;
394 } /* vox_read_d */
395
396 /*------------------------------------------------------------------------------
397 */
398
399 static int
400 vox_write_block (SF_PRIVATE *psf, VOX_ADPCM_PRIVATE *pvox, const short *ptr, int len)
401 {       int     indx = 0, k ;
402
403         while (indx < len)
404         {       pvox->pcm_samples = (len - indx > PCM_DATA_LEN) ? PCM_DATA_LEN : len - indx ;
405
406                 memcpy (pvox->pcm_data, &(ptr [indx]), pvox->pcm_samples * sizeof (short)) ;
407
408                 vox_adpcm_encode_block (pvox) ;
409
410                 if ((k = psf_fwrite (pvox->vox_data, 1, pvox->vox_bytes, psf)) != pvox->vox_bytes)
411                         psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pvox->vox_bytes) ;
412
413                 indx += pvox->pcm_samples ;
414                 } ;
415
416         return indx ;
417 } /* vox_write_block */
418
419 static sf_count_t
420 vox_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
421 {       VOX_ADPCM_PRIVATE       *pvox ;
422         int                     writecount, count ;
423         sf_count_t      total = 0 ;
424
425         if (! psf->fdata)
426                 return 0 ;
427         pvox = (VOX_ADPCM_PRIVATE*) psf->fdata ;
428
429         while (len)
430         {       writecount = (len > 0x10000000) ? 0x10000000 : (int) len ;
431
432                 count = vox_write_block (psf, pvox, ptr, writecount) ;
433
434                 total += count ;
435                 len -= count ;
436                 if (count != writecount)
437                         break ;
438                 } ;
439
440         return total ;
441 } /* vox_write_s */
442
443 static sf_count_t
444 vox_write_i     (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
445 {       VOX_ADPCM_PRIVATE *pvox ;
446         short           *sptr ;
447         int                     k, bufferlen, writecount, count ;
448         sf_count_t      total = 0 ;
449
450         if (! psf->fdata)
451                 return 0 ;
452         pvox = (VOX_ADPCM_PRIVATE*) psf->fdata ;
453
454         sptr = psf->u.sbuf ;
455         bufferlen = ARRAY_LEN (psf->u.sbuf) ;
456         while (len > 0)
457         {       writecount = (len >= bufferlen) ? bufferlen : (int) len ;
458                 for (k = 0 ; k < writecount ; k++)
459                         sptr [k] = ptr [total + k] >> 16 ;
460                 count = vox_write_block (psf, pvox, sptr, writecount) ;
461                 total += count ;
462                 len -= writecount ;
463                 if (count != writecount)
464                         break ;
465                 } ;
466
467         return total ;
468 } /* vox_write_i */
469
470 static sf_count_t
471 vox_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
472 {       VOX_ADPCM_PRIVATE *pvox ;
473         short           *sptr ;
474         int                     k, bufferlen, writecount, count ;
475         sf_count_t      total = 0 ;
476         float           normfact ;
477
478         if (! psf->fdata)
479                 return 0 ;
480         pvox = (VOX_ADPCM_PRIVATE*) psf->fdata ;
481
482         normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ;
483
484         sptr = psf->u.sbuf ;
485         bufferlen = ARRAY_LEN (psf->u.sbuf) ;
486         while (len > 0)
487         {       writecount = (len >= bufferlen) ? bufferlen : (int) len ;
488                 for (k = 0 ; k < writecount ; k++)
489                         sptr [k] = lrintf (normfact * ptr [total + k]) ;
490                 count = vox_write_block (psf, pvox, sptr, writecount) ;
491                 total += count ;
492                 len -= writecount ;
493                 if (count != writecount)
494                         break ;
495                 } ;
496
497         return total ;
498 } /* vox_write_f */
499
500 static sf_count_t
501 vox_write_d     (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
502 {       VOX_ADPCM_PRIVATE *pvox ;
503         short           *sptr ;
504         int                     k, bufferlen, writecount, count ;
505         sf_count_t      total = 0 ;
506         double          normfact ;
507
508         if (! psf->fdata)
509                 return 0 ;
510         pvox = (VOX_ADPCM_PRIVATE*) psf->fdata ;
511
512         normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ;
513
514         sptr = psf->u.sbuf ;
515         bufferlen = ARRAY_LEN (psf->u.sbuf) ;
516         while (len > 0)
517         {       writecount = (len >= bufferlen) ? bufferlen : (int) len ;
518                 for (k = 0 ; k < writecount ; k++)
519                         sptr [k] = lrint (normfact * ptr [total + k]) ;
520                 count = vox_write_block (psf, pvox, sptr, writecount) ;
521                 total += count ;
522                 len -= writecount ;
523                 if (count != writecount)
524                         break ;
525                 } ;
526
527         return total ;
528 } /* vox_write_d */
529
530
531 /*
532 ** Do not edit or modify anything in this comment block.
533 ** The arch-tag line is a file identity tag for the GNU Arch 
534 ** revision control system.
535 **
536 ** arch-tag: e15e97fe-ff9d-4b46-a489-7059fb2d0b1e
537 */