1 /* adpcm.c  codex functions for MS_ADPCM data
2  *          (hopefully) provides interoperability with
3  *          Microsoft's ADPCM format, but, as usual,
4  *          see LACK-OF-WARRANTY information below.
5  *
6  *      Copyright (C) 1999 Stanley J. Brooks <stabro@megsinet.net>
7  *
8  * This library is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation; either version 2.1 of the License, or (at
11  * your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this library; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23 
24 /*
25  * November 22, 1999
26  *  specs I've seen are unclear about ADPCM supporting more than 2 channels,
27  *  but these routines support more channels in a manner which looks (IMHO)
28  *  like the most natural extension.
29  *
30  *  Remark: code still turbulent, encoding very new.
31  *
32  */
33 
34 #include "sox_i.h"
35 #include "adpcm.h"
36 
37 #include <sys/types.h>
38 #include <stdio.h>
39 
40 typedef struct {
41         sox_sample_t  step;      /* step size */
42         short coef[2];
43 } MsState_t;
44 
45 #define lsbshortldi(x,p) { (x)=((short)((int)(p)[0] + ((int)(p)[1]<<8))); (p) += 2; }
46 
47 /*
48  * Lookup tables for MS ADPCM format
49  */
50 
51 /* these are step-size adjust factors, where
52  * 1.0 is scaled to 0x100
53  */
54 static const
55 sox_sample_t stepAdjustTable[] = {
56         230, 230, 230, 230, 307, 409, 512, 614,
57         768, 614, 512, 409, 307, 230, 230, 230
58 };
59 
60 /* TODO : The first 7 lsx_ms_adpcm_i_coef sets are always hardcoded and must
61    appear in the actual WAVE file.  They should be read in
62    in case a sound program added extras to the list. */
63 
64 const short lsx_ms_adpcm_i_coef[7][2] = {
65                         { 256,   0},
66                         { 512,-256},
67                         {   0,   0},
68                         { 192,  64},
69                         { 240,   0},
70                         { 460,-208},
71                         { 392,-232}
72 };
73 
lsx_ms_adpcm_alloc(unsigned chans)74 extern void *lsx_ms_adpcm_alloc(unsigned chans)
75 {
76         return lsx_malloc(chans * sizeof(MsState_t));
77 }
78 
AdpcmDecode(sox_sample_t c,MsState_t * state,sox_sample_t sample1,sox_sample_t sample2)79 static inline sox_sample_t AdpcmDecode(sox_sample_t c, MsState_t *state,
80                                sox_sample_t sample1, sox_sample_t sample2)
81 {
82         sox_sample_t vlin;
83         sox_sample_t sample;
84         sox_sample_t step;
85 
86         /** Compute next step value **/
87         step = state->step;
88         {
89                 sox_sample_t nstep;
90                 nstep = (stepAdjustTable[c] * step) >> 8;
91                 state->step = (nstep < 16)? 16:nstep;
92         }
93 
94         /** make linear prediction for next sample **/
95         vlin =
96                         ((sample1 * state->coef[0]) +
97                          (sample2 * state->coef[1])) >> 8;
98         /** then add the code*step adjustment **/
99         c -= (c & 0x08) << 1;
100         sample = (c * step) + vlin;
101 
102         if (sample > 0x7fff) sample = 0x7fff;
103         else if (sample < -0x8000) sample = -0x8000;
104 
105         return (sample);
106 }
107 
108 /* lsx_ms_adpcm_block_expand_i() outputs interleaved samples into one output buffer */
lsx_ms_adpcm_block_expand_i(void * priv,unsigned chans,int nCoef,const short * coef,const unsigned char * ibuff,SAMPL * obuff,int n)109 const char *lsx_ms_adpcm_block_expand_i(
110         void *priv,
111         unsigned chans,          /* total channels             */
112         int nCoef,
113         const short *coef,
114         const unsigned char *ibuff,/* input buffer[blockAlign]   */
115         SAMPL *obuff,       /* output samples, n*chans    */
116         int n               /* samples to decode PER channel */
117 )
118 {
119   const unsigned char *ip;
120   unsigned ch;
121   const char *errmsg = NULL;
122   MsState_t *state = priv;  /* One decompressor state for each channel */
123 
124   /* Read the four-byte header for each channel */
125   ip = ibuff;
126   for (ch = 0; ch < chans; ch++) {
127     unsigned char bpred = *ip++;
128     if (bpred >= nCoef) {
129       errmsg = "MSADPCM bpred >= nCoef, arbitrarily using 0\n";
130       bpred = 0;
131     }
132     state[ch].coef[0] = coef[(int)bpred*2+0];
133     state[ch].coef[1] = coef[(int)bpred*2+1];
134   }
135 
136   for (ch = 0; ch < chans; ch++)
137     lsbshortldi(state[ch].step, ip);
138 
139   /* sample1's directly into obuff */
140   for (ch = 0; ch < chans; ch++)
141     lsbshortldi(obuff[chans+ch], ip);
142 
143   /* sample2's directly into obuff */
144   for (ch = 0; ch < chans; ch++)
145     lsbshortldi(obuff[ch], ip);
146 
147   {
148     unsigned ch2;
149     unsigned char b;
150     short *op, *top, *tmp;
151 
152     /* already have 1st 2 samples from block-header */
153     op = obuff + 2*chans;
154     top = obuff + n*chans;
155 
156     ch2 = 0;
157     while (op < top) { /*** N.B. Without int casts, crashes on 64-bit arch ***/
158       b = *ip++;
159       tmp = op;
160       *op++ = AdpcmDecode(b >> 4, state+ch2, tmp[-(int)chans], tmp[-(int)(2*chans)]);
161       if (++ch2 == chans) ch2 = 0;
162       tmp = op;
163       *op++ = AdpcmDecode(b&0x0f, state+ch2, tmp[-(int)chans], tmp[-(int)(2*chans)]);
164       if (++ch2 == chans) ch2 = 0;
165     }
166   }
167   return errmsg;
168 }
169 
AdpcmMashS(unsigned ch,unsigned chans,SAMPL v[2],const short coef[2],const SAMPL * ibuff,int n,int * iostep,unsigned char * obuff)170 static int AdpcmMashS(
171         unsigned ch,              /* channel number to encode, REQUIRE 0 <= ch < chans  */
172         unsigned chans,           /* total channels */
173         SAMPL v[2],          /* values to use as starting 2 */
174         const short coef[2],/* lin predictor coeffs */
175         const SAMPL *ibuff,  /* ibuff[] is interleaved input samples */
176         int n,               /* samples to encode PER channel */
177         int *iostep,         /* input/output step, REQUIRE 16 <= *st <= 0x7fff */
178         unsigned char *obuff /* output buffer[blockAlign], or NULL for no output  */
179 )
180 {
181         const SAMPL *ip, *itop;
182         unsigned char *op;
183         int ox = 0;      /*  */
184         int d, v0, v1, step;
185         double d2;       /* long long is okay also, speed abt the same */
186 
187         ip = ibuff + ch;       /* point ip to 1st input sample for this channel */
188         itop = ibuff + n*chans;
189         v0 = v[0];
190         v1 = v[1];
191         d = *ip - v1; ip += chans; /* 1st input sample for this channel */
192         d2 = d*d;  /* d2 will be sum of squares of errors, given input v0 and *st */
193         d = *ip - v0; ip += chans; /* 2nd input sample for this channel */
194         d2 += d*d;
195 
196         step = *iostep;
197 
198         op = obuff;            /* output pointer (or NULL) */
199         if (op) {              /* NULL means don't output, just compute the rms error */
200                 op += chans;         /* skip bpred indices */
201                 op += 2*ch;          /* channel's stepsize */
202                 op[0] = step; op[1] = step>>8;
203                 op += 2*chans;       /* skip to v0 */
204                 op[0] = v0; op[1] = v0>>8;
205                 op += 2*chans;       /* skip to v1 */
206                 op[0] = v1; op[1] = v1>>8;
207                 op = obuff+7*chans;  /* point to base of output nibbles */
208                 ox = 4*ch;
209         }
210         for (; ip < itop; ip+=chans) {
211                 int vlin,d3,dp,c;
212 
213           /* make linear prediction for next sample */
214                 vlin = (v0 * coef[0] + v1 * coef[1]) >> 8;
215                 d3 = *ip - vlin;  /* difference between linear prediction and current sample */
216                 dp = d3 + (step<<3) + (step>>1);
217                 c = 0;
218                 if (dp>0) {
219                         c = dp/step;
220                         if (c>15) c = 15;
221                 }
222                 c -= 8;
223                 dp = c * step;   /* quantized estimate of samp - vlin */
224                 c &= 0x0f;       /* mask to 4 bits */
225 
226                 v1 = v0; /* shift history */
227                 v0 = vlin + dp;
228                 if (v0<-0x8000) v0 = -0x8000;
229                 else if (v0>0x7fff) v0 = 0x7fff;
230 
231                 d3 = *ip - v0;
232                 d2 += d3*d3; /* update square-error */
233 
234                 if (op) {   /* if we want output, put it in proper place */
235                         op[ox>>3] |= (ox&4)? c:(c<<4);
236                         ox += 4*chans;
237                         lsx_debug_more("%.1x",c);
238 
239                 }
240 
241                 /* Update the step for the next sample */
242                 step = (stepAdjustTable[c] * step) >> 8;
243                 if (step < 16) step = 16;
244 
245         }
246         if (op) lsx_debug_more("\n");
247         d2 /= n; /* be sure it's non-negative */
248         lsx_debug_more("ch%d: st %d->%d, d %.1f\n", ch, *iostep, step, sqrt(d2));
249         *iostep = step;
250         return (int) sqrt(d2);
251 }
252 
AdpcmMashChannel(unsigned ch,unsigned chans,const SAMPL * ip,int n,int * st,unsigned char * obuff)253 static inline void AdpcmMashChannel(
254         unsigned ch,             /* channel number to encode, REQUIRE 0 <= ch < chans  */
255         unsigned chans,          /* total channels */
256         const SAMPL *ip,    /* ip[] is interleaved input samples */
257         int n,              /* samples to encode PER channel, REQUIRE */
258         int *st,            /* input/output steps, 16<=st[i] */
259         unsigned char *obuff /* output buffer[blockAlign] */
260 )
261 {
262         SAMPL v[2];
263         int n0,s0,s1,ss,smin;
264         int dmin,k,kmin;
265 
266         n0 = n/2; if (n0>32) n0=32;
267         if (*st<16) *st = 16;
268         v[1] = ip[ch];
269         v[0] = ip[ch+chans];
270 
271         dmin = 0; kmin = 0; smin = 0;
272         /* for each of 7 standard coeff sets, we try compression
273          * beginning with last step-value, and with slightly
274          * forward-adjusted step-value, taking best of the 14
275          */
276         for (k=0; k<7; k++) {
277                 int d0,d1;
278                 ss = s0 = *st;
279                 d0=AdpcmMashS(ch, chans, v, lsx_ms_adpcm_i_coef[k], ip, n, &ss, NULL); /* with step s0 */
280 
281                 s1 = s0;
282                 AdpcmMashS(ch, chans, v, lsx_ms_adpcm_i_coef[k], ip, n0, &s1, NULL);
283                 lsx_debug_more(" s32 %d\n",s1);
284                 ss = s1 = (3*s0+s1)/4;
285                 d1=AdpcmMashS(ch, chans, v, lsx_ms_adpcm_i_coef[k], ip, n, &ss, NULL); /* with step s1 */
286                 if (!k || d0<dmin || d1<dmin) {
287                         kmin = k;
288                         if (d0<=d1) {
289                                 dmin = d0;
290                                 smin = s0;
291                         }else{
292                                 dmin = d1;
293                                 smin = s1;
294                         }
295                 }
296         }
297         *st = smin;
298         lsx_debug_more("kmin %d, smin %5d, ",kmin,smin);
299         AdpcmMashS(ch, chans, v, lsx_ms_adpcm_i_coef[kmin], ip, n, st, obuff);
300         obuff[ch] = kmin;
301 }
302 
lsx_ms_adpcm_block_mash_i(unsigned chans,const SAMPL * ip,int n,int * st,unsigned char * obuff,int blockAlign)303 void lsx_ms_adpcm_block_mash_i(
304         unsigned chans,          /* total channels */
305         const SAMPL *ip,    /* ip[n*chans] is interleaved input samples */
306         int n,              /* samples to encode PER channel */
307         int *st,            /* input/output steps, 16<=st[i] */
308         unsigned char *obuff,      /* output buffer[blockAlign]     */
309         int blockAlign      /* >= 7*chans + chans*(n-2)/2.0    */
310 )
311 {
312         unsigned ch;
313         unsigned char *p;
314 
315         lsx_debug_more("AdpcmMashI(chans %d, ip %p, n %d, st %p, obuff %p, bA %d)\n",
316             chans, (void *)ip, n, (void *)st, obuff, blockAlign);
317 
318         for (p=obuff+7*chans; p<obuff+blockAlign; p++) *p=0;
319 
320         for (ch=0; ch<chans; ch++)
321                 AdpcmMashChannel(ch, chans, ip, n, st+ch, obuff);
322 }
323 
324 /*
325  * lsx_ms_adpcm_samples_in(dataLen, chans, blockAlign, samplesPerBlock)
326  *  returns the number of samples/channel which would be
327  *  in the dataLen, given the other parameters ...
328  *  if input samplesPerBlock is 0, then returns the max
329  *  samplesPerBlock which would go into a block of size blockAlign
330  *  Yes, it is confusing usage.
331  */
lsx_ms_adpcm_samples_in(size_t dataLen,size_t chans,size_t blockAlign,size_t samplesPerBlock)332 size_t lsx_ms_adpcm_samples_in(
333         size_t dataLen,
334         size_t chans,
335         size_t blockAlign,
336         size_t samplesPerBlock
337 ){
338         size_t m, n;
339 
340         if (samplesPerBlock) {
341                 n = (dataLen / blockAlign) * samplesPerBlock;
342                 m = (dataLen % blockAlign);
343         } else {
344                 n = 0;
345                 m = blockAlign;
346         }
347         if (m >= (size_t)(7*chans)) {
348                 m -= 7*chans;          /* bytes beyond block-header */
349                 m = (2*m)/chans + 2;   /* nibbles/chans + 2 in header */
350                 if (samplesPerBlock && m > samplesPerBlock) m = samplesPerBlock;
351                 n += m;
352         }
353         return n;
354 }
355 
lsx_ms_adpcm_bytes_per_block(size_t chans,size_t samplesPerBlock)356 size_t lsx_ms_adpcm_bytes_per_block(
357         size_t chans,
358         size_t samplesPerBlock
359 )
360 {
361         size_t n;
362         n = 7*chans;  /* header */
363         if (samplesPerBlock > 2)
364                 n += (((size_t)samplesPerBlock-2)*chans + 1)/2;
365         return n;
366 }
367 
368