]> git.sesse.net Git - vlc/blob - modules/codec/adpcm.c
50e51f3ad57760d98f8bc393e92e593fdf322c82
[vlc] / modules / codec / adpcm.c
1 /*****************************************************************************
2  * adpcm.c : adpcm variant audio decoder
3  *****************************************************************************
4  * Copyright (C) 2001, 2002 VideoLAN
5  * $Id: adpcm.c,v 1.6 2003/01/13 17:39:05 fenrir Exp $
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/aout.h>
31 #include <vlc/decoder.h>
32 #include <vlc/input.h>
33
34 #include <stdlib.h>                                      /* malloc(), free() */
35 #include <string.h>                                              /* strdup() */
36 #include "codecs.h"
37 /*****************************************************************************
38  * Local prototypes
39  *****************************************************************************/
40
41 #define ADPCM_IMA_QT    1
42 #define ADPCM_IMA_WAV   2
43 #define ADPCM_MS        3
44
45 typedef struct adec_thread_s
46 {
47     int i_codec;
48
49     WAVEFORMATEX    *p_wf;
50
51     int                 i_block;
52     uint8_t             *p_block;
53     int                 i_samplesperblock;
54
55     uint8_t             *p_buffer;      /* buffer for gather pes */  \
56     int                 i_buffer;       /* bytes present in p_buffer */
57
58     /* Input properties */
59     decoder_fifo_t *p_fifo;
60
61     /* Output properties */
62     aout_instance_t *   p_aout;       /* opaque */
63     aout_input_t *      p_aout_input; /* opaque */
64     audio_sample_format_t output_format;
65
66     audio_date_t        date;
67     mtime_t             pts;
68
69 } adec_thread_t;
70
71 static int  OpenDecoder    ( vlc_object_t * );
72
73 static int  RunDecoder     ( decoder_fifo_t * );
74 static int  InitThread     ( adec_thread_t * );
75 static void DecodeThread   ( adec_thread_t * );
76 static void EndThread      ( adec_thread_t * );
77
78
79 static void DecodeAdpcmMs( adec_thread_t *, aout_buffer_t * );
80 static void DecodeAdpcmImaWav( adec_thread_t *, aout_buffer_t * );
81
82 /*****************************************************************************
83  * Module descriptor
84  *****************************************************************************/
85
86 vlc_module_begin();
87     set_description( _("ADPCM audio deocder") );
88     set_capability( "decoder", 50 );
89     set_callbacks( OpenDecoder, NULL );
90 vlc_module_end();
91
92
93 static int pi_channels_maps[6] =
94 {
95     0,
96     AOUT_CHAN_CENTER,
97     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
98     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER,
99     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARLEFT,
100     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
101      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARLEFT 
102 };
103
104 /* Various table from http://www.pcisys.net/~melanson/codecs/adpcm.txt */
105 static int i_index_table[16] =
106 {
107     -1, -1, -1, -1, 2, 4, 6, 8,
108     -1, -1, -1, -1, 2, 4, 6, 8
109 };
110
111 static int i_step_table[89] =
112 {
113     7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
114     19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
115     50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
116     130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
117     337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
118     876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
119     2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
120     5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
121     15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
122 };
123
124 static int i_adaptation_table[16] =
125 {
126     230, 230, 230, 230, 307, 409, 512, 614,
127     768, 614, 512, 409, 307, 230, 230, 230
128 };
129
130 static int i_adaptation_coeff1[7] =
131 {
132     256, 512, 0, 192, 240, 460, 392
133 };
134
135 static int i_adaptation_coeff2[7] =
136 {
137     0, -256, 0, 64, 0, -208, -232
138 };
139
140
141 /*****************************************************************************
142  * OpenDecoder: probe the decoder and return score
143  *****************************************************************************
144  * Tries to launch a decoder and return score so that the interface is able
145  * to choose.
146  *****************************************************************************/
147 static int OpenDecoder( vlc_object_t *p_this )
148 {
149     decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
150     
151     switch( p_fifo->i_fourcc )
152     {   
153 //        case VLC_FOURCC('i','m','a', '4'): /* IMA ADPCM */
154         case VLC_FOURCC('m','s',0x00,0x02): /* MS ADPCM */
155         case VLC_FOURCC('m','s',0x00,0x11): /* IMA ADPCM */
156 //        case VLC_FOURCC('m','s',0x00,0x61): /* Duck DK4 ADPCM */
157 //        case VLC_FOURCC('m','s',0x00,0x62): /* Duck DK3 ADPCM */
158
159             p_fifo->pf_run = RunDecoder;
160             return VLC_SUCCESS;
161             
162         default:
163             return VLC_EGENERIC;
164     }
165
166 }
167
168 /*****************************************************************************
169  * RunDecoder: this function is called just after the thread is created
170  *****************************************************************************/
171 static int RunDecoder( decoder_fifo_t *p_fifo )
172 {
173     adec_thread_t *p_adec;
174     int b_error;
175
176     if( !( p_adec = malloc( sizeof( adec_thread_t ) ) ) )
177     {
178         msg_Err( p_fifo, "out of memory" );
179         DecoderError( p_fifo );
180         return( -1 );
181     }
182     memset( p_adec, 0, sizeof( adec_thread_t ) );
183     
184     p_adec->p_fifo = p_fifo;
185
186     if( InitThread( p_adec ) != 0 )
187     {
188         DecoderError( p_fifo );
189         return( -1 );
190     }
191
192     while( ( !p_adec->p_fifo->b_die )&&( !p_adec->p_fifo->b_error ) )
193     {
194         DecodeThread( p_adec );
195     }
196
197
198     if( ( b_error = p_adec->p_fifo->b_error ) )
199     {
200         DecoderError( p_adec->p_fifo );
201     }
202
203     EndThread( p_adec );
204     if( b_error )
205     {
206         return( -1 );
207     }
208
209     return( 0 );
210 }
211
212
213 #define FREE( p ) if( p ) free( p ); p = NULL
214 #define GetWLE( p ) \
215     ( *(u8*)(p) + ( *((u8*)(p)+1) << 8 ) )
216
217 #define GetDWLE( p ) \
218     (  *(u8*)(p) + ( *((u8*)(p)+1) << 8 ) + \
219         ( *((u8*)(p)+2) << 16 ) + ( *((u8*)(p)+3) << 24 ) )
220
221 /*****************************************************************************
222  * InitThread: initialize data before entering main loop
223  *****************************************************************************/
224
225 static int InitThread( adec_thread_t * p_adec )
226 {
227     if( ( p_adec->p_wf = (WAVEFORMATEX*)p_adec->p_fifo->p_waveformatex ) == NULL )
228     {
229         msg_Err( p_adec->p_fifo, "missing format" );
230         return( -1 );
231     }
232     /* fourcc to codec */
233     switch( p_adec->p_fifo->i_fourcc )
234     {
235         case VLC_FOURCC('i','m','a', '4'): /* IMA ADPCM */
236             p_adec->i_codec = ADPCM_IMA_QT;
237             break;
238         case VLC_FOURCC('m','s',0x00,0x11): /* IMA ADPCM */
239             p_adec->i_codec = ADPCM_IMA_WAV;
240             break;
241         case VLC_FOURCC('m','s',0x00,0x02): /* MS ADPCM */
242             p_adec->i_codec = ADPCM_MS;
243             break;
244         case VLC_FOURCC('m','s',0x00,0x61): /* Duck DK4 ADPCM */
245         case VLC_FOURCC('m','s',0x00,0x62): /* Duck DK3 ADPCM */
246             p_adec->i_codec = 0;
247             break;
248     }
249
250     if( p_adec->p_wf->nChannels < 1 || 
251             p_adec->p_wf->nChannels > 2 )
252     {
253         msg_Err( p_adec->p_fifo, "bad channels count(1-2)" );
254         return( -1 );
255     }
256     if( !( p_adec->i_block = p_adec->p_wf->nBlockAlign ) )
257     {
258         if( p_adec->i_codec == ADPCM_IMA_QT )
259         {
260             p_adec->i_block = 34;
261         }
262         else
263         {
264             p_adec->i_block = 1024; // XXX FIXME
265         }
266         msg_Err( p_adec->p_fifo,
267                  "block size undefined, using %d default", 
268                  p_adec->i_block );
269     }
270     p_adec->p_block = NULL;
271
272     /* calculate samples per block */
273     switch( p_adec->i_codec )
274     {
275         case ADPCM_IMA_QT:
276             p_adec->i_samplesperblock = 64;
277             break;
278         case ADPCM_IMA_WAV:
279             p_adec->i_samplesperblock = 
280                  2 * ( p_adec->i_block - 4 * p_adec->p_wf->nChannels )/
281                  p_adec->p_wf->nChannels;
282                  break;
283         case ADPCM_MS:
284             p_adec->i_samplesperblock = 
285                 2 * ( p_adec->i_block - 7 * p_adec->p_wf->nChannels ) / 
286                 p_adec->p_wf->nChannels + 2;
287             break;
288         default:
289             p_adec->i_samplesperblock = 0;
290     }
291    
292     msg_Dbg( p_adec->p_fifo,
293              "format: samplerate:%dHz channels:%d bits/sample:%d blockalign:%d samplesperblock %d",
294              p_adec->p_wf->nSamplesPerSec,
295              p_adec->p_wf->nChannels,
296              p_adec->p_wf->wBitsPerSample, 
297              p_adec->p_wf->nBlockAlign,
298              p_adec->i_samplesperblock );
299     
300     //p_adec->output_format.i_format = VLC_FOURCC('s','1','6','l');
301     /* FIXME good way ? */
302     p_adec->output_format.i_format = AOUT_FMT_S16_NE;
303     p_adec->output_format.i_rate = p_adec->p_wf->nSamplesPerSec;
304
305
306     p_adec->output_format.i_physical_channels = 
307         p_adec->output_format.i_original_channels =
308             pi_channels_maps[p_adec->p_wf->nChannels];
309     p_adec->p_aout = NULL;
310     p_adec->p_aout_input = NULL;
311
312     /* **** Create a new audio output **** */
313     aout_DateInit( &p_adec->date, p_adec->output_format.i_rate );
314     p_adec->p_aout_input = aout_DecNew( p_adec->p_fifo,
315                                         &p_adec->p_aout,
316                                         &p_adec->output_format );
317     if( !p_adec->p_aout_input )
318     {
319         msg_Err( p_adec->p_fifo, "cannot create aout" );
320         return( -1 );
321     }
322
323     /* Init the BitStream */
324 //    InitBitstream( &p_adec->bit_stream, p_adec->p_fifo,
325 //                   NULL, NULL );
326
327     return( 0 );
328 }
329
330
331 static void GetPESData( uint8_t *p_buf, int i_max, pes_packet_t *p_pes )
332 {
333     int i_copy;
334     int i_count;
335
336     data_packet_t   *p_data;
337
338     i_count = 0;
339     p_data = p_pes->p_first;
340     while( p_data != NULL && i_count < i_max )
341     {
342
343         i_copy = __MIN( p_data->p_payload_end - p_data->p_payload_start,
344                         i_max - i_count );
345
346         if( i_copy > 0 )
347         {
348             memcpy( p_buf,
349                     p_data->p_payload_start,
350                     i_copy );
351         }
352
353         p_data = p_data->p_next;
354         i_count += i_copy;
355         p_buf   += i_copy;
356     }
357
358     if( i_count < i_max )
359     {
360         memset( p_buf, 0, i_max - i_count );
361     }
362 }
363
364 /*****************************************************************************
365  * DecodeThread: decodes a frame
366  *****************************************************************************/
367 static void DecodeThread( adec_thread_t *p_adec )
368 {
369     aout_buffer_t   *p_aout_buffer;
370     pes_packet_t    *p_pes;
371
372     int             i_frame_size;
373
374     /* **** Get a new frames from streams **** */
375     do
376     {
377         input_ExtractPES( p_adec->p_fifo, &p_pes );
378         if( !p_pes )
379         {
380             p_adec->p_fifo->b_error = 1;
381             return;
382         }
383         if( p_pes->i_pts != 0 )
384         {
385             p_adec->pts = p_pes->i_pts;
386         }
387         i_frame_size = p_pes->i_pes_size;
388
389         if( i_frame_size > 0 )
390         {
391             if( p_adec->i_buffer < i_frame_size + 16 )
392             {
393                 FREE( p_adec->p_buffer );
394                 p_adec->p_buffer = malloc( i_frame_size + 16 );
395                 p_adec->i_buffer = i_frame_size + 16;
396             }
397
398             GetPESData( p_adec->p_buffer, p_adec->i_buffer, p_pes );
399         }
400         input_DeletePES( p_adec->p_fifo->p_packets_mgt, p_pes );
401
402     } while( i_frame_size <= 0 );
403
404     for( p_adec->p_block = p_adec->p_buffer;
405          i_frame_size >= p_adec->i_block;
406          p_adec->p_block += p_adec->i_block, i_frame_size -= p_adec->i_block  )
407     {
408         /* get output buffer */
409         if( p_adec->pts != 0 && p_adec->pts != aout_DateGet( &p_adec->date ) )
410         {
411             aout_DateSet( &p_adec->date, p_adec->pts );
412         }
413         else if( !aout_DateGet( &p_adec->date ) )
414         {
415             return;
416         }
417         p_adec->pts = 0;
418
419         p_aout_buffer = aout_DecNewBuffer( p_adec->p_aout,
420                                            p_adec->p_aout_input,
421                                            p_adec->i_samplesperblock );
422         if( !p_aout_buffer )
423         {
424             msg_Err( p_adec->p_fifo, "cannot get aout buffer" );
425             p_adec->p_fifo->b_error = 1;
426             return;
427         }
428
429         p_aout_buffer->start_date = aout_DateGet( &p_adec->date );
430         p_aout_buffer->end_date = aout_DateIncrement( &p_adec->date,
431                                                       p_adec->i_samplesperblock );
432
433         /* decode */
434
435         switch( p_adec->i_codec )
436         {
437             case ADPCM_IMA_QT:
438                 break;
439             case ADPCM_IMA_WAV:
440                 DecodeAdpcmImaWav( p_adec, p_aout_buffer );
441                 break;
442             case ADPCM_MS:
443                 DecodeAdpcmMs( p_adec, p_aout_buffer );
444                 break;
445             default:
446                 break;
447         }
448
449
450         /* **** Now we can output these samples **** */
451         aout_DecPlay( p_adec->p_aout, p_adec->p_aout_input, p_aout_buffer );
452     }
453 }
454
455
456 /*****************************************************************************
457  * EndThread : faad decoder thread destruction
458  *****************************************************************************/
459 static void EndThread (adec_thread_t *p_adec)
460 {
461     if( p_adec->p_aout_input )
462     {
463         aout_DecDelete( p_adec->p_aout, p_adec->p_aout_input );
464     }
465
466     msg_Dbg( p_adec->p_fifo, "adpcm audio decoder closed" );
467
468     FREE( p_adec->p_buffer );
469     free( p_adec );
470 }
471 #define CLAMP( v, min, max ) \
472     if( (v) < (min) ) (v) = (min); \
473     if( (v) > (max) ) (v) = (max)
474
475 #define GetByte( v ) \
476     (v) = *p_buffer; p_buffer++;
477
478 #define GetWord( v ) \
479     (v) = *p_buffer; p_buffer++; \
480     (v) |= ( *p_buffer ) << 8; p_buffer++; \
481     if( (v)&0x8000 ) (v) -= 0x010000;
482
483 typedef struct adpcm_ms_channel_s
484 {
485     int i_idelta; 
486     int i_sample1, i_sample2;
487     int i_coeff1, i_coeff2;
488
489 } adpcm_ms_channel_t;
490
491
492 static int AdpcmMsExpandNibble(adpcm_ms_channel_t *p_channel,
493                                int i_nibble )
494 {
495     int i_predictor;
496     int i_snibble;
497     /* expand sign */
498
499     i_snibble = i_nibble - ( i_nibble&0x08 ? 0x10 : 0 );
500     
501     i_predictor = ( p_channel->i_sample1 * p_channel->i_coeff1 + 
502                     p_channel->i_sample2 * p_channel->i_coeff2 ) / 256 +
503                   i_snibble * p_channel->i_idelta;
504
505     CLAMP( i_predictor, -32768, 32767 );
506
507     p_channel->i_sample2 = p_channel->i_sample1;
508     p_channel->i_sample1 = i_predictor;
509
510     p_channel->i_idelta = ( i_adaptation_table[i_nibble] * 
511                             p_channel->i_idelta ) / 256;
512     if( p_channel->i_idelta < 16 )
513     {
514         p_channel->i_idelta = 16;
515     }
516     return( i_predictor );
517 }
518     
519 static void DecodeAdpcmMs( adec_thread_t *p_adec,  
520                            aout_buffer_t *p_aout_buffer)
521 {
522     uint8_t            *p_buffer;
523     adpcm_ms_channel_t channel[2];
524     int i_nibbles;
525     uint16_t           *p_sample;
526     int b_stereo;
527     int i_block_predictor;
528     
529     p_buffer = p_adec->p_block;
530     b_stereo = p_adec->p_wf->nChannels == 2 ? 1 : 0;
531
532     GetByte( i_block_predictor );
533     CLAMP( i_block_predictor, 0, 6 );
534     channel[0].i_coeff1 = i_adaptation_coeff1[i_block_predictor];
535     channel[0].i_coeff2 = i_adaptation_coeff2[i_block_predictor];
536
537     if( b_stereo )
538     {
539         GetByte( i_block_predictor );
540         CLAMP( i_block_predictor, 0, 6 );
541         channel[1].i_coeff1 = i_adaptation_coeff1[i_block_predictor];
542         channel[1].i_coeff2 = i_adaptation_coeff2[i_block_predictor];
543     }
544     GetWord( channel[0].i_idelta );
545     if( b_stereo )
546     {
547         GetWord( channel[1].i_idelta );
548     }
549     
550     GetWord( channel[0].i_sample1 );
551     if( b_stereo )
552     {
553         GetWord( channel[1].i_sample1 );
554     }
555
556     GetWord( channel[0].i_sample2 );
557     if( b_stereo )
558     {
559         GetWord( channel[1].i_sample2 );
560     }
561
562     p_sample = (int16_t*)p_aout_buffer->p_buffer;
563
564     if( b_stereo )
565     {
566         *p_sample = channel[0].i_sample2; p_sample++;
567         *p_sample = channel[1].i_sample2; p_sample++;
568         *p_sample = channel[0].i_sample1; p_sample++;
569         *p_sample = channel[1].i_sample1; p_sample++;
570     }
571     else
572     {
573         *p_sample = channel[0].i_sample2; p_sample++;
574         *p_sample = channel[0].i_sample1; p_sample++;
575     }
576
577     for( i_nibbles =  2 *( p_adec->i_block - 7 * p_adec->p_wf->nChannels );
578          i_nibbles > 0; i_nibbles -= 2,p_buffer++ )
579     {
580         *p_sample = AdpcmMsExpandNibble( &channel[0], (*p_buffer) >> 4);
581         p_sample++;
582         
583         *p_sample = AdpcmMsExpandNibble( &channel[b_stereo ? 1 : 0], 
584                                          (*p_buffer)&0x0f);
585         p_sample++;
586     }
587
588     
589 }
590
591 typedef struct adpcm_ima_wav_channel_s
592 {
593     int i_predictor;
594     int i_step_index;
595
596 } adpcm_ima_wav_channel_t;
597
598 static int AdpcmImaWavExpandNibble(adpcm_ima_wav_channel_t *p_channel,
599                                    int i_nibble )
600 {
601     int i_diff;
602
603     i_diff = i_step_table[p_channel->i_step_index] >> 3;
604     if( i_nibble&0x04 ) i_diff += i_step_table[p_channel->i_step_index];
605     if( i_nibble&0x02 ) i_diff += i_step_table[p_channel->i_step_index]>>1;
606     if( i_nibble&0x01 ) i_diff += i_step_table[p_channel->i_step_index]>>2;
607     if( i_nibble&0x08 )
608         p_channel->i_predictor -= i_diff;
609     else
610         p_channel->i_predictor += i_diff;
611
612     CLAMP( p_channel->i_predictor, -32768, 32767 );
613
614     p_channel->i_step_index += i_index_table[i_nibble];
615
616     CLAMP( p_channel->i_step_index, 0, 88 );
617
618     return( p_channel->i_predictor );
619 }
620
621 static void DecodeAdpcmImaWav( adec_thread_t *p_adec,  
622                                aout_buffer_t *p_aout_buffer)
623 {
624     uint8_t                 *p_buffer;
625     adpcm_ima_wav_channel_t channel[2];
626     int                     i_nibbles;
627     uint16_t                *p_sample;
628     int                     b_stereo;
629     
630     p_buffer = p_adec->p_block;
631     b_stereo = p_adec->p_wf->nChannels == 2 ? 1 : 0;
632
633     GetWord( channel[0].i_predictor );
634     GetByte( channel[0].i_step_index );
635     CLAMP( channel[0].i_step_index, 0, 88 );
636     p_buffer++;
637
638     if( b_stereo )
639     {
640         GetWord( channel[1].i_predictor );
641         GetByte( channel[1].i_step_index );
642         CLAMP( channel[1].i_step_index, 0, 88 );
643         p_buffer++;
644     }
645     
646     p_sample = (int16_t*)p_aout_buffer->p_buffer;
647     if( b_stereo )
648     {
649         for( i_nibbles = 2 * (p_adec->i_block - 8); 
650              i_nibbles > 0; 
651              i_nibbles -= 16 )
652         {
653             int i;
654
655             for( i = 0; i < 4; i++ )
656             {
657                 p_sample[i * 4] = 
658                     AdpcmImaWavExpandNibble(&channel[0],p_buffer[i]&0x0f);
659                 p_sample[i * 4 + 2] =
660                     AdpcmImaWavExpandNibble(&channel[0],p_buffer[i] >> 4);
661             }
662             p_buffer += 4;
663             
664             for( i = 0; i < 4; i++ )
665             {
666                 p_sample[i * 4 + 1] = 
667                     AdpcmImaWavExpandNibble(&channel[1],p_buffer[i]&0x0f);
668                 p_sample[i * 4 + 3] =
669                     AdpcmImaWavExpandNibble(&channel[1],p_buffer[i] >> 4);
670             }
671             p_buffer += 4;
672             p_sample += 16;
673
674         }
675
676
677     }
678     else
679     {
680         for( i_nibbles = 2 * (p_adec->i_block - 4); 
681              i_nibbles > 0; 
682              i_nibbles -= 2, p_buffer++ )
683         {
684             *p_sample =AdpcmImaWavExpandNibble( &channel[0], (*p_buffer)&0x0f );
685             p_sample++;
686             *p_sample =AdpcmImaWavExpandNibble( &channel[0], (*p_buffer) >> 4 );
687             p_sample++;
688         }
689     }
690 }
691
692
693
694