]> git.sesse.net Git - vlc/blob - modules/codec/adpcm.c
Improvements to preferences
[vlc] / modules / codec / adpcm.c
1 /*****************************************************************************
2  * adpcm.c : adpcm variant audio decoder
3  *****************************************************************************
4  * Copyright (C) 2001, 2002 VideoLAN
5  * $Id$
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *
27  * Documentation: http://www.pcisys.net/~melanson/codecs/adpcm.txt
28  *****************************************************************************/
29 #include <vlc/vlc.h>
30 #include <vlc/decoder.h>
31
32 /*****************************************************************************
33  * Module descriptor
34  *****************************************************************************/
35 static int  OpenDecoder( vlc_object_t * );
36 static void CloseDecoder( vlc_object_t * );
37
38 static aout_buffer_t *DecodeBlock( decoder_t *, block_t ** );
39
40 vlc_module_begin();
41     set_description( _("ADPCM audio decoder") );
42     set_capability( "decoder", 50 );
43     set_category( CAT_INPUT );
44     set_subcategory( SUBCAT_INPUT_ACODEC );
45     set_callbacks( OpenDecoder, CloseDecoder );
46 vlc_module_end();
47
48 /*****************************************************************************
49  * Local prototypes
50  *****************************************************************************/
51 enum adpcm_codec_e
52 {
53     ADPCM_IMA_QT,
54     ADPCM_IMA_WAV,
55     ADPCM_MS,
56     ADPCM_DK3,
57     ADPCM_DK4
58 };
59
60 struct decoder_sys_t
61 {
62     enum adpcm_codec_e codec;
63
64     int                 i_block;
65     int                 i_samplesperblock;
66
67     audio_date_t        end_date;
68 };
69
70 static void DecodeAdpcmMs    ( decoder_t *, int16_t *, uint8_t * );
71 static void DecodeAdpcmImaWav( decoder_t *, int16_t *, uint8_t * );
72 static void DecodeAdpcmImaQT ( decoder_t *, int16_t *, uint8_t * );
73 static void DecodeAdpcmDk4   ( decoder_t *, int16_t *, uint8_t * );
74 static void DecodeAdpcmDk3   ( decoder_t *, int16_t *, uint8_t * );
75
76 static int pi_channels_maps[6] =
77 {
78     0,
79     AOUT_CHAN_CENTER,
80     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
81     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER,
82     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARLEFT,
83     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
84      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARLEFT
85 };
86
87 /* Various table from http://www.pcisys.net/~melanson/codecs/adpcm.txt */
88 static int i_index_table[16] =
89 {
90     -1, -1, -1, -1, 2, 4, 6, 8,
91     -1, -1, -1, -1, 2, 4, 6, 8
92 };
93
94 static int i_step_table[89] =
95 {
96     7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
97     19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
98     50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
99     130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
100     337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
101     876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
102     2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
103     5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
104     15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
105 };
106
107 static int i_adaptation_table[16] =
108 {
109     230, 230, 230, 230, 307, 409, 512, 614,
110     768, 614, 512, 409, 307, 230, 230, 230
111 };
112
113 static int i_adaptation_coeff1[7] =
114 {
115     256, 512, 0, 192, 240, 460, 392
116 };
117
118 static int i_adaptation_coeff2[7] =
119 {
120     0, -256, 0, 64, 0, -208, -232
121 };
122
123 /*****************************************************************************
124  * OpenDecoder: probe the decoder and return score
125  *****************************************************************************/
126 static int OpenDecoder( vlc_object_t *p_this )
127 {
128     decoder_t *p_dec = (decoder_t*)p_this;
129     decoder_sys_t *p_sys;
130
131     switch( p_dec->fmt_in.i_codec )
132     {
133         case VLC_FOURCC('i','m','a', '4'): /* IMA ADPCM */
134         case VLC_FOURCC('m','s',0x00,0x02): /* MS ADPCM */
135         case VLC_FOURCC('m','s',0x00,0x11): /* IMA ADPCM */
136         case VLC_FOURCC('m','s',0x00,0x61): /* Duck DK4 ADPCM */
137         case VLC_FOURCC('m','s',0x00,0x62): /* Duck DK3 ADPCM */
138             break;
139         default:
140             return VLC_EGENERIC;
141     }
142
143     /* Allocate the memory needed to store the decoder's structure */
144     if( ( p_dec->p_sys = p_sys =
145           (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
146     {
147         msg_Err( p_dec, "out of memory" );
148         return VLC_EGENERIC;
149     }
150
151     if( p_dec->fmt_in.audio.i_channels <= 0 ||
152         p_dec->fmt_in.audio.i_channels > 5 )
153     {
154         msg_Err( p_dec, "bad channels count(1-5)" );
155         return VLC_EGENERIC;
156     }
157
158     if( p_dec->fmt_in.audio.i_rate <= 0 )
159     {
160         msg_Err( p_dec, "bad samplerate" );
161         return VLC_EGENERIC;
162     }
163
164     switch( p_dec->fmt_in.i_codec )
165     {
166         case VLC_FOURCC('i','m','a', '4'): /* IMA ADPCM */
167             p_sys->codec = ADPCM_IMA_QT;
168             break;
169         case VLC_FOURCC('m','s',0x00,0x11): /* IMA ADPCM */
170             p_sys->codec = ADPCM_IMA_WAV;
171             break;
172         case VLC_FOURCC('m','s',0x00,0x02): /* MS ADPCM */
173             p_sys->codec = ADPCM_MS;
174             break;
175         case VLC_FOURCC('m','s',0x00,0x61): /* Duck DK4 ADPCM */
176             p_sys->codec = ADPCM_DK4;
177             break;
178         case VLC_FOURCC('m','s',0x00,0x62): /* Duck DK3 ADPCM */
179             p_sys->codec = ADPCM_DK3;
180             break;
181     }
182
183     if( p_dec->fmt_in.audio.i_blockalign <= 0 )
184     {
185         p_sys->i_block = (p_sys->codec == ADPCM_IMA_QT) ?
186             34 * p_dec->fmt_in.audio.i_channels : 1024;
187         msg_Warn( p_dec, "block size undefined, using %d", p_sys->i_block );
188     }
189     else
190     {
191         p_sys->i_block = p_dec->fmt_in.audio.i_blockalign;
192     }
193
194     /* calculate samples per block */
195     switch( p_sys->codec )
196     {
197     case ADPCM_IMA_QT:
198         p_sys->i_samplesperblock = 64;
199         break;
200     case ADPCM_IMA_WAV:
201         p_sys->i_samplesperblock =
202             2 * ( p_sys->i_block - 4 * p_dec->fmt_in.audio.i_channels ) /
203             p_dec->fmt_in.audio.i_channels;
204         break;
205     case ADPCM_MS:
206         p_sys->i_samplesperblock =
207             2 * (p_sys->i_block - 7 * p_dec->fmt_in.audio.i_channels) /
208             p_dec->fmt_in.audio.i_channels + 2;
209         break;
210     case ADPCM_DK4:
211         p_sys->i_samplesperblock =
212             2 * (p_sys->i_block - 4 * p_dec->fmt_in.audio.i_channels) /
213             p_dec->fmt_in.audio.i_channels + 1;
214         break;
215     case ADPCM_DK3:
216         p_dec->fmt_in.audio.i_channels = 2;
217         p_sys->i_samplesperblock = ( 4 * ( p_sys->i_block - 16 ) + 2 )/ 3;
218         break;
219     }
220
221     msg_Dbg( p_dec, "format: samplerate:%dHz channels:%d bits/sample:%d "
222              "blockalign:%d samplesperblock:%d",
223              p_dec->fmt_in.audio.i_rate, p_dec->fmt_in.audio.i_channels,
224              p_dec->fmt_in.audio.i_bitspersample, p_sys->i_block,
225              p_sys->i_samplesperblock );
226
227     p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE;
228     p_dec->fmt_out.audio.i_rate = p_dec->fmt_in.audio.i_rate;
229     p_dec->fmt_out.audio.i_channels = p_dec->fmt_in.audio.i_channels;
230     p_dec->fmt_out.audio.i_physical_channels =
231         p_dec->fmt_out.audio.i_original_channels =
232             pi_channels_maps[p_dec->fmt_in.audio.i_channels];
233
234     aout_DateInit( &p_sys->end_date, p_dec->fmt_out.audio.i_rate );
235     aout_DateSet( &p_sys->end_date, 0 );
236
237     p_dec->pf_decode_audio = DecodeBlock;
238
239     return VLC_SUCCESS;
240 }
241
242 /*****************************************************************************
243  * DecodeBlock:
244  *****************************************************************************/
245 static aout_buffer_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
246 {
247     decoder_sys_t *p_sys  = p_dec->p_sys;
248     block_t *p_block;
249
250     if( !pp_block || !*pp_block ) return NULL;
251
252     p_block = *pp_block;
253
254     if( p_block->i_pts != 0 &&
255         p_block->i_pts != aout_DateGet( &p_sys->end_date ) )
256     {
257         aout_DateSet( &p_sys->end_date, p_block->i_pts );
258     }
259     else if( !aout_DateGet( &p_sys->end_date ) )
260     {
261         /* We've just started the stream, wait for the first PTS. */
262         block_Release( p_block );
263         return NULL;
264     }
265
266     /* Don't re-use the same pts twice */
267     p_block->i_pts = 0;
268
269     if( p_block->i_buffer >= p_sys->i_block )
270     {
271         aout_buffer_t *p_out;
272
273         p_out = p_dec->pf_aout_buffer_new( p_dec, p_sys->i_samplesperblock );
274         if( p_out == NULL )
275         {
276             block_Release( p_block );
277             return NULL;
278         }
279
280         p_out->start_date = aout_DateGet( &p_sys->end_date );
281         p_out->end_date =
282             aout_DateIncrement( &p_sys->end_date, p_sys->i_samplesperblock );
283
284         switch( p_sys->codec )
285         {
286         case ADPCM_IMA_QT:
287             DecodeAdpcmImaQT( p_dec, (int16_t*)p_out->p_buffer,
288                               p_block->p_buffer );
289             break;
290         case ADPCM_IMA_WAV:
291             DecodeAdpcmImaWav( p_dec, (int16_t*)p_out->p_buffer,
292                                p_block->p_buffer );
293             break;
294         case ADPCM_MS:
295             DecodeAdpcmMs( p_dec, (int16_t*)p_out->p_buffer,
296                            p_block->p_buffer );
297             break;
298         case ADPCM_DK4:
299             DecodeAdpcmDk4( p_dec, (int16_t*)p_out->p_buffer,
300                             p_block->p_buffer );
301             break;
302         case ADPCM_DK3:
303             DecodeAdpcmDk3( p_dec, (int16_t*)p_out->p_buffer,
304                             p_block->p_buffer );
305             break;
306         default:
307             break;
308         }
309
310         p_block->p_buffer += p_sys->i_block;
311         p_block->i_buffer -= p_sys->i_block;
312         return p_out;
313     }
314
315     block_Release( p_block );
316     return NULL;
317 }
318
319 /*****************************************************************************
320  * CloseDecoder:
321  *****************************************************************************/
322 static void CloseDecoder( vlc_object_t *p_this )
323 {
324     decoder_t *p_dec = (decoder_t *)p_this;
325     decoder_sys_t *p_sys = p_dec->p_sys;
326
327     free( p_sys );
328 }
329
330 /*****************************************************************************
331  * Local functions
332  *****************************************************************************/
333 #define CLAMP( v, min, max ) \
334     if( (v) < (min) ) (v) = (min); \
335     if( (v) > (max) ) (v) = (max)
336
337 #define GetByte( v ) \
338     (v) = *p_buffer; p_buffer++;
339
340 #define GetWord( v ) \
341     (v) = *p_buffer; p_buffer++; \
342     (v) |= ( *p_buffer ) << 8; p_buffer++; \
343     if( (v)&0x8000 ) (v) -= 0x010000;
344
345 /*
346  * MS
347  */
348 typedef struct adpcm_ms_channel_s
349 {
350     int i_idelta;
351     int i_sample1, i_sample2;
352     int i_coeff1, i_coeff2;
353
354 } adpcm_ms_channel_t;
355
356
357 static int AdpcmMsExpandNibble(adpcm_ms_channel_t *p_channel,
358                                int i_nibble )
359 {
360     int i_predictor;
361     int i_snibble;
362     /* expand sign */
363
364     i_snibble = i_nibble - ( i_nibble&0x08 ? 0x10 : 0 );
365
366     i_predictor = ( p_channel->i_sample1 * p_channel->i_coeff1 +
367                     p_channel->i_sample2 * p_channel->i_coeff2 ) / 256 +
368                   i_snibble * p_channel->i_idelta;
369
370     CLAMP( i_predictor, -32768, 32767 );
371
372     p_channel->i_sample2 = p_channel->i_sample1;
373     p_channel->i_sample1 = i_predictor;
374
375     p_channel->i_idelta = ( i_adaptation_table[i_nibble] *
376                             p_channel->i_idelta ) / 256;
377     if( p_channel->i_idelta < 16 )
378     {
379         p_channel->i_idelta = 16;
380     }
381     return( i_predictor );
382 }
383
384 static void DecodeAdpcmMs( decoder_t *p_dec, int16_t *p_sample,
385                            uint8_t *p_buffer )
386 {
387     decoder_sys_t *p_sys  = p_dec->p_sys;
388     adpcm_ms_channel_t channel[2];
389     int i_nibbles;
390     int b_stereo;
391     int i_block_predictor;
392
393     b_stereo = p_dec->fmt_in.audio.i_channels == 2 ? 1 : 0;
394
395     GetByte( i_block_predictor );
396     CLAMP( i_block_predictor, 0, 6 );
397     channel[0].i_coeff1 = i_adaptation_coeff1[i_block_predictor];
398     channel[0].i_coeff2 = i_adaptation_coeff2[i_block_predictor];
399
400     if( b_stereo )
401     {
402         GetByte( i_block_predictor );
403         CLAMP( i_block_predictor, 0, 6 );
404         channel[1].i_coeff1 = i_adaptation_coeff1[i_block_predictor];
405         channel[1].i_coeff2 = i_adaptation_coeff2[i_block_predictor];
406     }
407     GetWord( channel[0].i_idelta );
408     if( b_stereo )
409     {
410         GetWord( channel[1].i_idelta );
411     }
412
413     GetWord( channel[0].i_sample1 );
414     if( b_stereo )
415     {
416         GetWord( channel[1].i_sample1 );
417     }
418
419     GetWord( channel[0].i_sample2 );
420     if( b_stereo )
421     {
422         GetWord( channel[1].i_sample2 );
423     }
424
425     if( b_stereo )
426     {
427         *p_sample++ = channel[0].i_sample2;
428         *p_sample++ = channel[1].i_sample2;
429         *p_sample++ = channel[0].i_sample1;
430         *p_sample++ = channel[1].i_sample1;
431     }
432     else
433     {
434         *p_sample++ = channel[0].i_sample2;
435         *p_sample++ = channel[0].i_sample1;
436     }
437
438     for( i_nibbles = 2 * (p_sys->i_block - 7 * p_dec->fmt_in.audio.i_channels);
439          i_nibbles > 0; i_nibbles -= 2, p_buffer++ )
440     {
441         *p_sample++ = AdpcmMsExpandNibble( &channel[0], (*p_buffer) >> 4);
442         *p_sample++ = AdpcmMsExpandNibble( &channel[b_stereo ? 1 : 0],
443                                            (*p_buffer)&0x0f);
444     }
445 }
446
447 /*
448  * IMA-WAV
449  */
450 typedef struct adpcm_ima_wav_channel_s
451 {
452     int i_predictor;
453     int i_step_index;
454
455 } adpcm_ima_wav_channel_t;
456
457 static int AdpcmImaWavExpandNibble(adpcm_ima_wav_channel_t *p_channel,
458                                    int i_nibble )
459 {
460     int i_diff;
461
462     i_diff = i_step_table[p_channel->i_step_index] >> 3;
463     if( i_nibble&0x04 ) i_diff += i_step_table[p_channel->i_step_index];
464     if( i_nibble&0x02 ) i_diff += i_step_table[p_channel->i_step_index]>>1;
465     if( i_nibble&0x01 ) i_diff += i_step_table[p_channel->i_step_index]>>2;
466     if( i_nibble&0x08 )
467         p_channel->i_predictor -= i_diff;
468     else
469         p_channel->i_predictor += i_diff;
470
471     CLAMP( p_channel->i_predictor, -32768, 32767 );
472
473     p_channel->i_step_index += i_index_table[i_nibble];
474
475     CLAMP( p_channel->i_step_index, 0, 88 );
476
477     return( p_channel->i_predictor );
478 }
479
480 static void DecodeAdpcmImaWav( decoder_t *p_dec, int16_t *p_sample,
481                                uint8_t *p_buffer )
482 {
483     decoder_sys_t *p_sys  = p_dec->p_sys;
484     adpcm_ima_wav_channel_t channel[2];
485     int                     i_nibbles;
486     int                     b_stereo;
487
488     b_stereo = p_dec->fmt_in.audio.i_channels == 2 ? 1 : 0;
489
490     GetWord( channel[0].i_predictor );
491     GetByte( channel[0].i_step_index );
492     CLAMP( channel[0].i_step_index, 0, 88 );
493     p_buffer++;
494
495     if( b_stereo )
496     {
497         GetWord( channel[1].i_predictor );
498         GetByte( channel[1].i_step_index );
499         CLAMP( channel[1].i_step_index, 0, 88 );
500         p_buffer++;
501     }
502
503     if( b_stereo )
504     {
505         for( i_nibbles = 2 * (p_sys->i_block - 8);
506              i_nibbles > 0;
507              i_nibbles -= 16 )
508         {
509             int i;
510
511             for( i = 0; i < 4; i++ )
512             {
513                 p_sample[i * 4] =
514                     AdpcmImaWavExpandNibble(&channel[0],p_buffer[i]&0x0f);
515                 p_sample[i * 4 + 2] =
516                     AdpcmImaWavExpandNibble(&channel[0],p_buffer[i] >> 4);
517             }
518             p_buffer += 4;
519
520             for( i = 0; i < 4; i++ )
521             {
522                 p_sample[i * 4 + 1] =
523                     AdpcmImaWavExpandNibble(&channel[1],p_buffer[i]&0x0f);
524                 p_sample[i * 4 + 3] =
525                     AdpcmImaWavExpandNibble(&channel[1],p_buffer[i] >> 4);
526             }
527             p_buffer += 4;
528             p_sample += 16;
529
530         }
531
532
533     }
534     else
535     {
536         for( i_nibbles = 2 * (p_sys->i_block - 4);
537              i_nibbles > 0;
538              i_nibbles -= 2, p_buffer++ )
539         {
540             *p_sample++ =AdpcmImaWavExpandNibble( &channel[0], (*p_buffer)&0x0f );
541             *p_sample++ =AdpcmImaWavExpandNibble( &channel[0], (*p_buffer) >> 4 );
542         }
543     }
544 }
545
546 /*
547  * Ima4 in QT file
548  */
549 static void DecodeAdpcmImaQT( decoder_t *p_dec, int16_t *p_sample,
550                               uint8_t *p_buffer )
551 {
552     adpcm_ima_wav_channel_t channel[2];
553     int                     i_nibbles;
554     int                     i_ch;
555     int                     i_step;
556
557     i_step = p_dec->fmt_in.audio.i_channels;
558
559     for( i_ch = 0; i_ch < p_dec->fmt_in.audio.i_channels; i_ch++ )
560     {
561         /* load preambule */
562         channel[i_ch].i_predictor  = (int16_t)((( ( p_buffer[0] << 1 )|(  p_buffer[1] >> 7 ) ))<<7);
563         channel[i_ch].i_step_index = p_buffer[1]&0x7f;
564
565         CLAMP( channel[i_ch].i_step_index, 0, 88 );
566         p_buffer += 2;
567
568         for( i_nibbles = 0; i_nibbles < 64; i_nibbles +=2 )
569         {
570             *p_sample = AdpcmImaWavExpandNibble( &channel[i_ch], (*p_buffer)&0x0f);
571             p_sample += i_step;
572
573             *p_sample = AdpcmImaWavExpandNibble( &channel[i_ch], (*p_buffer >> 4)&0x0f);
574             p_sample += i_step;
575
576             p_buffer++;
577         }
578
579         /* Next channel */
580         p_sample += 1 - 64 * i_step;
581     }
582 }
583
584 /*
585  * Dk4
586  */
587 static void DecodeAdpcmDk4( decoder_t *p_dec, int16_t *p_sample,
588                             uint8_t *p_buffer )
589 {
590     decoder_sys_t *p_sys  = p_dec->p_sys;
591     adpcm_ima_wav_channel_t channel[2];
592     int                     i_nibbles;
593     int                     b_stereo;
594
595     b_stereo = p_dec->fmt_in.audio.i_channels == 2 ? 1 : 0;
596
597     GetWord( channel[0].i_predictor );
598     GetByte( channel[0].i_step_index );
599     CLAMP( channel[0].i_step_index, 0, 88 );
600     p_buffer++;
601
602     if( b_stereo )
603     {
604         GetWord( channel[1].i_predictor );
605         GetByte( channel[1].i_step_index );
606         CLAMP( channel[1].i_step_index, 0, 88 );
607         p_buffer++;
608     }
609
610     /* first output predictor */
611     *p_sample++ = channel[0].i_predictor;
612     if( b_stereo )
613     {
614         *p_sample++ = channel[1].i_predictor;
615     }
616
617     for( i_nibbles = 0;
618          i_nibbles < p_sys->i_block - 4 * (b_stereo ? 2:1 );
619          i_nibbles++ )
620     {
621         *p_sample++ = AdpcmImaWavExpandNibble( &channel[0],
622                                               (*p_buffer) >> 4);
623         *p_sample++ = AdpcmImaWavExpandNibble( &channel[b_stereo ? 1 : 0],
624                                                (*p_buffer)&0x0f);
625
626         p_buffer++;
627     }
628 }
629
630 /*
631  * Dk3
632  */
633 static void DecodeAdpcmDk3( decoder_t *p_dec, int16_t *p_sample,
634                             uint8_t *p_buffer )
635 {
636     decoder_sys_t *p_sys  = p_dec->p_sys;
637     uint8_t                 *p_end = &p_buffer[p_sys->i_block];
638     adpcm_ima_wav_channel_t sum;
639     adpcm_ima_wav_channel_t diff;
640     int                     i_diff_value;
641
642     p_buffer += 10;
643
644     GetWord( sum.i_predictor );
645     GetWord( diff.i_predictor );
646     GetByte( sum.i_step_index );
647     GetByte( diff.i_step_index );
648
649     i_diff_value = diff.i_predictor;
650     /* we process 6 nibbles at once */
651     while( p_buffer + 1 <= p_end )
652     {
653         /* first 3 nibbles */
654         AdpcmImaWavExpandNibble( &sum,
655                                  (*p_buffer)&0x0f);
656
657         AdpcmImaWavExpandNibble( &diff,
658                                  (*p_buffer) >> 4 );
659
660         i_diff_value = ( i_diff_value + diff.i_predictor ) / 2;
661
662         *p_sample++ = sum.i_predictor + i_diff_value;
663         *p_sample++ = sum.i_predictor - i_diff_value;
664
665         p_buffer++;
666
667         AdpcmImaWavExpandNibble( &sum,
668                                  (*p_buffer)&0x0f);
669
670         *p_sample++ = sum.i_predictor + i_diff_value;
671         *p_sample++ = sum.i_predictor - i_diff_value;
672
673         /* now last 3 nibbles */
674         AdpcmImaWavExpandNibble( &sum,
675                                  (*p_buffer)>>4);
676         p_buffer++;
677         if( p_buffer < p_end )
678         {
679             AdpcmImaWavExpandNibble( &diff,
680                                      (*p_buffer)&0x0f );
681
682             i_diff_value = ( i_diff_value + diff.i_predictor ) / 2;
683
684             *p_sample++ = sum.i_predictor + i_diff_value;
685             *p_sample++ = sum.i_predictor - i_diff_value;
686
687             AdpcmImaWavExpandNibble( &sum,
688                                      (*p_buffer)>>4);
689             p_buffer++;
690
691             *p_sample++ = sum.i_predictor + i_diff_value;
692             *p_sample++ = sum.i_predictor - i_diff_value;
693         }
694     }
695 }