1 #ifndef _WDL_ADPCM_DECODE_H_
2 #define _WDL_ADPCM_DECODE_H_
7 #define IMAADPCM_TYPE 0x11
8 #define CADPCM2_TYPE 0xac0c
10 class WDL_adpcm_decoder
14 int cf1
,cf2
,deltas
,spl1
,spl2
;
15 } WDL_adpcm_decode_chanctx
;
18 enum { MSADPCM_PREAMBLELEN
=7, IMA_PREAMBLELEN
=4 };
19 static INT64
sampleLengthFromBytes(INT64 nbytes
, int blockalign
, int nch
, int type
, int bps
)
21 if (!bps
||type
!=CADPCM2_TYPE
) bps
=4;
22 // remove overhead of headers
23 INT64 nblocks
=((nbytes
+blockalign
-1)/blockalign
);
26 if (type
==IMAADPCM_TYPE
||type
==CADPCM2_TYPE
) nbytes
-= nblocks
*IMA_PREAMBLELEN
*nch
;
27 else nbytes
-= nblocks
*MSADPCM_PREAMBLELEN
*nch
;
29 // scale from bytes to samples
30 nbytes
= (nbytes
*8)/(nch
*bps
);
32 if (type
==IMAADPCM_TYPE
||type
==CADPCM2_TYPE
) nbytes
++; // IMA has just one initial sample
33 else nbytes
+=2; // msadpcm has 2 initial sample values
38 WDL_adpcm_decoder(int blockalign
,int nch
, int type
, int bps
)
46 setParameters(blockalign
,nch
,type
,bps
);
57 if (m_chans
) memset(m_chans
,0,m_nch
*sizeof(WDL_adpcm_decode_chanctx
));
63 void setParameters(int ba
, int nch
, int type
, int bps
)
65 if (m_blockalign
!= ba
||nch
!= m_nch
||type
!=m_type
||bps
!= m_bps
)
73 m_srcbuf
=(unsigned char*)malloc(ba
);
74 m_chans
=(WDL_adpcm_decode_chanctx
*)malloc(sizeof(WDL_adpcm_decode_chanctx
)*nch
);
80 int blockAlign() { return m_blockalign
; }
84 if (m_type
==IMAADPCM_TYPE
||m_type
==CADPCM2_TYPE
)
86 if (m_bps
== 2) return (m_blockalign
/m_nch
- IMA_PREAMBLELEN
)*4 + 1;
87 return (m_blockalign
/m_nch
- IMA_PREAMBLELEN
)*2 + 1; //4 bit
89 return (m_blockalign
/m_nch
- MSADPCM_PREAMBLELEN
)*2 + 2; // 4 bit
92 INT64
samplesToSourceBytes(INT64 outlen_samples
) // length in samplepairs
94 outlen_samples
-= samplesOut
.Available()/m_nch
;
95 if (outlen_samples
<1) return 0; // no data required
97 int spls_block
= samplesPerBlock();
98 if (spls_block
<1) return 0;
99 INT64 nblocks
= (outlen_samples
+spls_block
-1)/spls_block
;
100 INT64 v
=nblocks
* m_blockalign
;
107 void AddInput(void *buf
, int len
, short *parm_cotab
=NULL
)
109 unsigned char *rdbuf
= (unsigned char *)buf
;
112 int v
=m_blockalign
-m_srcbuf_valid
;
115 memcpy(m_srcbuf
+m_srcbuf_valid
,rdbuf
,v
);
118 if ((m_srcbuf_valid
+=v
)>=m_blockalign
)
120 DecodeBlock(m_srcbuf
,parm_cotab
);
125 while (len
>= m_blockalign
)
127 DecodeBlock(rdbuf
,parm_cotab
);
131 if (len
>0) memcpy(m_srcbuf
,rdbuf
,m_srcbuf_valid
=len
);
135 int sourceBytesQueued() { return m_srcbuf_valid
; }
136 WDL_TypedQueue
<short> samplesOut
;
139 static int getwordsigned(unsigned char **rdptr
)
141 int s
= (*rdptr
)[0] + ((*rdptr
)[1]<<8);
143 if (s
& 0x8000) s
-= 0x10000;
147 bool DecodeBlockIMA(unsigned char *buf
)
149 int samples_block
= samplesPerBlock();
153 short *outptr
= samplesOut
.Add(NULL
,samples_block
* nch
);
155 for (ch
=0;ch
<nch
;ch
++)
157 m_chans
[ch
].spl1
= getwordsigned(&buf
);
158 m_chans
[ch
].cf1
= buf
[0] | (buf
[1]<<8);
162 for (ch
=0;ch
<nch
;ch
++) *outptr
++ = m_chans
[ch
].spl1
;
165 unsigned char lastbyte
=0;
168 static signed char index_table
[8] = { -1, -1, -1, -1, 2, 4, 6, 8 };
169 static short step_table
[89] = {
170 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
171 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
172 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
173 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
174 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
175 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
176 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
177 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
178 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
182 int splcnt
= (samples_block
-1)*nch
;
188 const int chunksize
= bps
== 2 ? 16 : 8;
190 for (x
=0; x
< splcnt
; x
++)
198 case 0: nib
=(lastbyte
=*buf
++)<<2; break;
199 case 1: nib
=lastbyte
; break;
200 case 2: nib
=lastbyte
>>2; break;
201 default: nib
=lastbyte
>>4; bstate
=0; break;
207 if ((bstate
^=1)) nib
=(lastbyte
=*buf
++)&0xf;
208 else nib
=lastbyte
>>4;
211 int step_index
=m_chans
[ch
].cf1
;
212 if (step_index
<0)step_index
=0;
213 else if (step_index
>88)step_index
=88;
215 int step
=step_table
[step_index
];
217 int diff
= ((nib
&7)*step
)/4 + step
/8;
219 int v
=m_chans
[ch
].spl1
+ ((nib
&8) ? -diff
: diff
);
221 if (v
<-32768)v
=-32768;
222 else if (v
>32767)v
=32767;
224 outptr
[wrpos
]=(short)v
;
229 m_chans
[ch
].cf1
=step_index
+ index_table
[nib
&7];
232 // advance channelcounts
233 if (++cnt
==chunksize
)
238 outptr
+= chunksize
*nch
;
248 bool DecodeBlock(unsigned char *buf
, short *parm_cotab
=NULL
)
250 if (m_type
==IMAADPCM_TYPE
||m_type
==CADPCM2_TYPE
) return DecodeBlockIMA(buf
);
251 static short cotab
[14] = { 256,0, 512,-256, 0,0, 192,64, 240, 0,460, -208, 392, -232 };
252 static short adtab
[16] = { 230, 230, 230, 230, 307, 409, 512, 614, 768, 614, 512, 409, 307, 230, 230, 230 };
254 short *use_cotab
= parm_cotab
? parm_cotab
: cotab
;
257 for(ch
=0;ch
<nch
;ch
++)
259 unsigned char c
=*buf
++;
260 if (c
> 6) return false;
262 m_chans
[ch
].cf1
= use_cotab
[c
];
263 m_chans
[ch
].cf2
= use_cotab
[c
+1];
265 for(ch
=0;ch
<nch
;ch
++) m_chans
[ch
].deltas
= getwordsigned(&buf
);
266 for(ch
=0;ch
<nch
;ch
++) m_chans
[ch
].spl1
= getwordsigned(&buf
);
267 for(ch
=0;ch
<nch
;ch
++) m_chans
[ch
].spl2
= getwordsigned(&buf
);
269 int samples_block
= samplesPerBlock();
271 short *outptr
= samplesOut
.Add(NULL
,samples_block
* nch
);
273 for(ch
=0;ch
<nch
;ch
++) *outptr
++ = m_chans
[ch
].spl2
;
274 for(ch
=0;ch
<nch
;ch
++) *outptr
++ = m_chans
[ch
].spl1
;
278 unsigned char lastbyte
;
279 for (x
=2; x
< samples_block
; x
++)
281 for(ch
=0;ch
<nch
;ch
++)
284 if ((bstate
^=1)) nib
=(lastbyte
=*buf
++)>>4;
285 else nib
=lastbyte
&0xf;
288 if (sn
& 8) sn
-= 16;
290 int pred
= ( ((m_chans
[ch
].spl1
* m_chans
[ch
].cf1
) +
291 (m_chans
[ch
].spl2
* m_chans
[ch
].cf2
)) / 256) +
292 (sn
* m_chans
[ch
].deltas
);
294 m_chans
[ch
].spl2
= m_chans
[ch
].spl1
;
296 if (pred
< -32768) pred
=-32768;
297 else if (pred
> 32767) pred
=32767;
299 *outptr
++ = m_chans
[ch
].spl1
= pred
;
301 int i
= (adtab
[nib
] * m_chans
[ch
].deltas
) / 256;
302 if (i
<= 16) m_chans
[ch
].deltas
=16;
303 else m_chans
[ch
].deltas
= i
;
309 WDL_adpcm_decode_chanctx
*m_chans
;
310 unsigned char *m_srcbuf
;
313 int m_blockalign
,m_nch
,m_type
,m_bps
;