]> git.sesse.net Git - vlc/commitdiff
* adpcm.c: add adpcm decoding support (Now just ms and ima adpcm from
authorLaurent Aimar <fenrir@videolan.org>
Tue, 3 Dec 2002 17:00:16 +0000 (17:00 +0000)
committerLaurent Aimar <fenrir@videolan.org>
Tue, 3 Dec 2002 17:00:16 +0000 (17:00 +0000)
microfsoft, not yet ima4)
 * wav, asf, avi: fix fourcc creation for adpcm. (Nevertheless adpcm
could not work with asf because of asf audio scrambling unsupported in asf
demuxer). Seek will not work, because vlc send garbage and then break stream
alignment.(I will try to fix that).

configure.ac.in
include/codecs.h
modules/codec/Modules.am
modules/codec/adpcm.c [new file with mode: 0644]
modules/demux/asf/asf.c
modules/demux/avi/avi.c
modules/demux/wav/wav.c

index 863e745d30bcfc08130222430b9eca2cd6597361..5b52bcfafac02e5c7ad1919a3ea09fbcbf6ae6ff 100644 (file)
@@ -620,7 +620,7 @@ PLUGINS="${PLUGINS} aout_file"
 #PLUGINS="${PLUGINS} scope"
 PLUGINS="${PLUGINS} i420_rgb i420_yuy2 i422_yuy2 i420_ymga"
 PLUGINS="${PLUGINS} id3 m3u"
-PLUGINS="${PLUGINS} wav araw demuxdump demuxsub"
+PLUGINS="${PLUGINS} wav araw demuxdump demuxsub adpcm"
 
 dnl
 dnl  Network modules
index 44ffe49a2f69945447fda9e0b7ce201069caaeda..e6a65376ca9e67570caf5a689d9bdf010e7af982 100644 (file)
@@ -2,7 +2,7 @@
  * codecs.h: codec related structures needed by the demuxers and decoders
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: codecs.h,v 1.2 2002/11/07 19:31:07 gbazin Exp $
+ * $Id: codecs.h,v 1.3 2002/12/03 17:00:15 fenrir Exp $
  *
  * Authors: Gildas Bazin <gbazin@netcourrier.com>
  *
@@ -70,6 +70,7 @@ typedef struct {
 #define  WAVE_FORMAT_ALAW               0x0006 /* Microsoft Corporation */
 #define  WAVE_FORMAT_MULAW              0x0007 /* Microsoft Corporation */
 #define  WAVE_FORMAT_DTS                0x0008 /* Microsoft Corporation */
+#define  WAVE_FORMAT_IMA_ADPCM          0x0011
 #define  WAVE_FORMAT_MPEG               0x0050 /* Microsoft Corporation */
 #define  WAVE_FORMAT_MPEGLAYER3         0x0055 /* ISO/MPEG Layer3 Format Tag */
 #define  WAVE_FORMAT_DOLBY_AC3_SPDIF    0x0092 /* Sonic Foundry */
@@ -78,6 +79,7 @@ typedef struct {
 #define WAVE_FORMAT_A52             0x2000
 #define WAVE_FORMAT_WMA1            0x0160
 #define WAVE_FORMAT_WMA2            0x0161
+#define WAVE_FORMAT_WMA3            0x0162
 
 #if !defined(WAVE_FORMAT_EXTENSIBLE)
 #define  WAVE_FORMAT_EXTENSIBLE                 0xFFFE /* Microsoft */
index 602bb1b6bd16b9b0314f2aa265a3473bb3a1b108..10a6575bd9c55157212fdca6f59c39a624660b31 100644 (file)
@@ -7,3 +7,4 @@ SOURCES_theora = modules/codec/theora.c
 SOURCES_tremor = modules/codec/vorbis.c
 SOURCES_dv = modules/codec/dv.c
 SOURCES_xvid = modules/codec/xvid.c
+SOURCES_adpcm = modules/codec/adpcm.c
diff --git a/modules/codec/adpcm.c b/modules/codec/adpcm.c
new file mode 100644 (file)
index 0000000..856dc6a
--- /dev/null
@@ -0,0 +1,627 @@
+/*****************************************************************************
+ * adpcm.c : adpcm variant audio decoder
+ *****************************************************************************
+ * Copyright (C) 2001, 2002 VideoLAN
+ * $Id: adpcm.c,v 1.1 2002/12/03 17:00:16 fenrir Exp $
+ *
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *      
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *
+ * Documentation: http://www.pcisys.net/~melanson/codecs/adpcm.txt
+ *****************************************************************************/
+#include <vlc/vlc.h>
+#include <vlc/aout.h>
+#include <vlc/decoder.h>
+#include <vlc/input.h>
+
+#include <stdlib.h>                                      /* malloc(), free() */
+#include <string.h>                                              /* strdup() */
+#include "codecs.h"
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+
+#define ADPCM_IMA_QT    1
+#define ADPCM_IMA_WAV   2
+#define ADPCM_MS        3
+
+typedef struct adec_thread_s
+{
+    int i_codec;
+
+    WAVEFORMATEX    *p_wf;
+    
+    /* The bit stream structure handles the PES stream at the bit level */
+    bit_stream_t        bit_stream;
+    int                 i_block;
+    uint8_t             *p_block;
+    int                 i_samplesperblock;
+    
+    /* Input properties */
+    decoder_fifo_t *p_fifo;
+    
+    /* Output properties */
+    aout_instance_t *   p_aout;       /* opaque */
+    aout_input_t *      p_aout_input; /* opaque */
+    audio_sample_format_t output_format;
+
+    audio_date_t        date;
+    mtime_t             pts;
+
+} adec_thread_t;
+
+static int  OpenDecoder    ( vlc_object_t * );
+
+static int  RunDecoder     ( decoder_fifo_t * );
+static int  InitThread     ( adec_thread_t * );
+static void DecodeThread   ( adec_thread_t * );
+static void EndThread      ( adec_thread_t * );
+
+
+static void DecodeAdpcmMs( adec_thread_t *, aout_buffer_t * );
+static void DecodeAdpcmImaWav( adec_thread_t *, aout_buffer_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+
+vlc_module_begin();
+    set_description( _("ADPCM audio deocder") );
+    set_capability( "decoder", 50 );
+    set_callbacks( OpenDecoder, NULL );
+vlc_module_end();
+
+
+static int pi_channels_maps[6] =
+{
+    0,
+    AOUT_CHAN_CENTER,
+    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
+    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER,
+    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARLEFT,
+    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
+     | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARLEFT 
+};
+
+/* Various table from http://www.pcisys.net/~melanson/codecs/adpcm.txt */
+static int i_index_table[16] =
+{
+    -1, -1, -1, -1, 2, 4, 6, 8,
+    -1, -1, -1, -1, 2, 4, 6, 8
+};
+
+static int i_step_table[89] =
+{
+    7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
+    19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
+    50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
+    130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
+    337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
+    876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
+    2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
+    5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
+    15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
+};
+
+static int i_adaptation_table[16] =
+{
+    230, 230, 230, 230, 307, 409, 512, 614,
+    768, 614, 512, 409, 307, 230, 230, 230
+};
+
+static int i_adaptation_coeff1[7] =
+{
+    256, 512, 0, 192, 240, 460, 392
+};
+
+static int i_adaptation_coeff2[7] =
+{
+    0, -256, 0, 64, 0, -208, -232
+};
+
+
+/*****************************************************************************
+ * OpenDecoder: probe the decoder and return score
+ *****************************************************************************
+ * Tries to launch a decoder and return score so that the interface is able
+ * to choose.
+ *****************************************************************************/
+static int OpenDecoder( vlc_object_t *p_this )
+{
+    decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
+    
+    switch( p_fifo->i_fourcc )
+    {   
+//        case VLC_FOURCC('i','m','a', '4'): /* IMA ADPCM */
+        case VLC_FOURCC('m','s',0x00,0x02): /* MS ADPCM */
+        case VLC_FOURCC('m','s',0x00,0x11): /* IMA ADPCM */
+//        case VLC_FOURCC('m','s',0x00,0x61): /* Duck DK4 ADPCM */
+//        case VLC_FOURCC('m','s',0x00,0x62): /* Duck DK3 ADPCM */
+
+            p_fifo->pf_run = RunDecoder;
+            return VLC_SUCCESS;
+            
+        default:
+            return VLC_EGENERIC;
+    }
+
+}
+
+/*****************************************************************************
+ * RunDecoder: this function is called just after the thread is created
+ *****************************************************************************/
+static int RunDecoder( decoder_fifo_t *p_fifo )
+{
+    adec_thread_t *p_adec;
+    int b_error;
+
+    if( !( p_adec = malloc( sizeof( adec_thread_t ) ) ) )
+    {
+        msg_Err( p_fifo, "out of memory" );
+        DecoderError( p_fifo );
+        return( -1 );
+    }
+    memset( p_adec, 0, sizeof( adec_thread_t ) );
+    
+    p_adec->p_fifo = p_fifo;
+
+    if( InitThread( p_adec ) != 0 )
+    {
+        DecoderError( p_fifo );
+        return( -1 );
+    }
+
+    while( ( !p_adec->p_fifo->b_die )&&( !p_adec->p_fifo->b_error ) )
+    {
+        DecodeThread( p_adec );
+    }
+
+
+    if( ( b_error = p_adec->p_fifo->b_error ) )
+    {
+        DecoderError( p_adec->p_fifo );
+    }
+
+    EndThread( p_adec );
+    if( b_error )
+    {
+        return( -1 );
+    }
+
+    return( 0 );
+}
+
+
+#define FREE( p ) if( p ) free( p ); p = NULL
+#define GetWLE( p ) \
+    ( *(u8*)(p) + ( *((u8*)(p)+1) << 8 ) )
+
+#define GetDWLE( p ) \
+    (  *(u8*)(p) + ( *((u8*)(p)+1) << 8 ) + \
+        ( *((u8*)(p)+2) << 16 ) + ( *((u8*)(p)+3) << 24 ) )
+
+/*****************************************************************************
+ * InitThread: initialize data before entering main loop
+ *****************************************************************************/
+
+static int InitThread( adec_thread_t * p_adec )
+{
+    if( !( p_adec->p_wf = (WAVEFORMATEX*)p_adec->p_fifo->p_demux_data ) )
+    {
+        msg_Err( p_adec->p_fifo, "missing format" );
+        return( -1 );
+    }
+    /* fourcc to codec */
+    switch( p_adec->p_fifo->i_fourcc )
+    {
+        case VLC_FOURCC('i','m','a', '4'): /* IMA ADPCM */
+            p_adec->i_codec = ADPCM_IMA_QT;
+            break;
+        case VLC_FOURCC('m','s',0x00,0x11): /* IMA ADPCM */
+            p_adec->i_codec = ADPCM_IMA_WAV;
+            break;
+        case VLC_FOURCC('m','s',0x00,0x02): /* MS ADPCM */
+            p_adec->i_codec = ADPCM_MS;
+            break;
+        case VLC_FOURCC('m','s',0x00,0x61): /* Duck DK4 ADPCM */
+        case VLC_FOURCC('m','s',0x00,0x62): /* Duck DK3 ADPCM */
+            p_adec->i_codec = 0;
+            break;
+    }
+
+    if( p_adec->p_wf->nChannels < 1 || 
+            p_adec->p_wf->nChannels > 2 )
+    {
+        msg_Err( p_adec->p_fifo, "bad channels count(1-2)" );
+        return( -1 );
+    }
+    if( !( p_adec->i_block = p_adec->p_wf->nBlockAlign ) )
+    {
+        if( p_adec->i_codec == ADPCM_IMA_QT )
+        {
+            p_adec->i_block = 34;
+        }
+        else
+        {
+            p_adec->i_block = 1024; // XXX FIXME
+        }
+        msg_Err( p_adec->p_fifo,
+                 "block size undefined, using %d default", 
+                 p_adec->i_block );
+    }
+    p_adec->p_block = malloc( p_adec->i_block );
+
+    /* calculate samples per block */
+    switch( p_adec->i_codec )
+    {
+        case ADPCM_IMA_QT:
+            p_adec->i_samplesperblock = 64;
+            break;
+        case ADPCM_IMA_WAV:
+            p_adec->i_samplesperblock = 
+                 2 * ( p_adec->i_block - 4 * p_adec->p_wf->nChannels )/
+                 p_adec->p_wf->nChannels;
+                 break;
+        case ADPCM_MS:
+            p_adec->i_samplesperblock = 
+                2 * ( p_adec->i_block - 7 * p_adec->p_wf->nChannels ) / 
+                p_adec->p_wf->nChannels + 2;
+            break;
+        default:
+            p_adec->i_samplesperblock = 0;
+    }
+   
+    msg_Dbg( p_adec->p_fifo,
+             "format: samplerate:%dHz channels:%d bits/sample:%d blockalign:%d samplesperblock %d",
+             p_adec->p_wf->nSamplesPerSec,
+             p_adec->p_wf->nChannels,
+             p_adec->p_wf->wBitsPerSample, 
+             p_adec->p_wf->nBlockAlign,
+             p_adec->i_samplesperblock );
+    
+    //p_adec->output_format.i_format = VLC_FOURCC('s','1','6','l');
+    /* FIXME good way ? */
+    p_adec->output_format.i_format = AOUT_FMT_S16_NE;
+    p_adec->output_format.i_rate = p_adec->p_wf->nSamplesPerSec;
+
+
+    p_adec->output_format.i_physical_channels = 
+        p_adec->output_format.i_original_channels =
+            pi_channels_maps[p_adec->p_wf->nChannels];
+    p_adec->p_aout = NULL;
+    p_adec->p_aout_input = NULL;
+
+    /* **** Create a new audio output **** */
+    aout_DateInit( &p_adec->date, p_adec->output_format.i_rate );
+    p_adec->p_aout_input = aout_DecNew( p_adec->p_fifo,
+                                        &p_adec->p_aout,
+                                        &p_adec->output_format );
+    if( !p_adec->p_aout_input )
+    {
+        msg_Err( p_adec->p_fifo, "cannot create aout" );
+        return( -1 );
+    }
+
+    /* Init the BitStream */
+    InitBitstream( &p_adec->bit_stream, p_adec->p_fifo,
+                   NULL, NULL );
+
+    return( 0 );
+}
+
+
+/*****************************************************************************
+ * DecodeThread: decodes a frame
+ *****************************************************************************/
+static void DecodeThread( adec_thread_t *p_adec )
+{
+    aout_buffer_t   *p_aout_buffer;
+
+    /* get pts */
+    CurrentPTS( &p_adec->bit_stream, &p_adec->pts, NULL );
+    /* gather block */
+    GetChunk( &p_adec->bit_stream,
+              p_adec->p_block,
+              p_adec->i_block );
+
+    /* get output buffer */
+    if( p_adec->pts != 0 && p_adec->pts != aout_DateGet( &p_adec->date ) )
+    {
+        aout_DateSet( &p_adec->date, p_adec->pts );
+    }
+    else if( !aout_DateGet( &p_adec->date ) )
+    {
+        return;
+    }
+
+    p_aout_buffer = aout_DecNewBuffer( p_adec->p_aout, 
+                                       p_adec->p_aout_input,
+                                       p_adec->i_samplesperblock );
+    if( !p_aout_buffer )
+    {
+        msg_Err( p_adec->p_fifo, "cannot get aout buffer" );
+        p_adec->p_fifo->b_error = 1;
+        return;
+    }
+    
+    p_aout_buffer->start_date = aout_DateGet( &p_adec->date );
+    p_aout_buffer->end_date = aout_DateIncrement( &p_adec->date,
+                                                  p_adec->i_samplesperblock );
+
+    /* decode */
+    
+    switch( p_adec->i_codec )
+    {
+        case ADPCM_IMA_QT:
+            break;
+        case ADPCM_IMA_WAV:
+            DecodeAdpcmImaWav( p_adec, p_aout_buffer );
+            break;
+        case ADPCM_MS:
+            DecodeAdpcmMs( p_adec, p_aout_buffer );
+            break;
+        default:
+    }
+
+
+    /* **** Now we can output these samples **** */
+    aout_DecPlay( p_adec->p_aout, p_adec->p_aout_input, p_aout_buffer );
+}
+
+
+/*****************************************************************************
+ * EndThread : faad decoder thread destruction
+ *****************************************************************************/
+static void EndThread (adec_thread_t *p_adec)
+{
+    if( p_adec->p_aout_input )
+    {
+        aout_DecDelete( p_adec->p_aout, p_adec->p_aout_input );
+    }
+
+    msg_Dbg( p_adec->p_fifo, "adpcm audio decoder closed" );
+        
+    free( p_adec->p_block );
+    free( p_adec );
+}
+#define CLAMP( v, min, max ) \
+    if( (v) < (min) ) (v) = (min); \
+    if( (v) > (max) ) (v) = (max)
+
+#define GetByte( v ) \
+    (v) = *p_buffer; p_buffer++;
+
+#define GetWord( v ) \
+    (v) = *p_buffer; p_buffer++; \
+    (v) |= ( *p_buffer ) << 8; p_buffer++; \
+    if( (v)&0x8000 ) (v) -= 0x010000;
+
+typedef struct adpcm_ms_channel_s
+{
+    int i_idelta; 
+    int i_sample1, i_sample2;
+    int i_coeff1, i_coeff2;
+
+} adpcm_ms_channel_t;
+
+
+static int AdpcmMsExpandNibble(adpcm_ms_channel_t *p_channel,
+                               int i_nibble )
+{
+    int i_predictor;
+    int i_snibble;
+    /* expand sign */
+
+    i_snibble = i_nibble - ( i_nibble&0x08 ? 0x10 : 0 );
+    
+    i_predictor = ( p_channel->i_sample1 * p_channel->i_coeff1 + 
+                    p_channel->i_sample2 * p_channel->i_coeff2 ) / 256 +
+                  i_snibble * p_channel->i_idelta;
+
+    CLAMP( i_predictor, -32768, 32767 );
+
+    p_channel->i_sample2 = p_channel->i_sample1;
+    p_channel->i_sample1 = i_predictor;
+
+    p_channel->i_idelta = ( i_adaptation_table[i_nibble] * 
+                            p_channel->i_idelta ) / 256;
+    if( p_channel->i_idelta < 16 )
+    {
+        p_channel->i_idelta = 16;
+    }
+    return( i_predictor );
+}
+    
+static void DecodeAdpcmMs( adec_thread_t *p_adec,  
+                           aout_buffer_t *p_aout_buffer)
+{
+    uint8_t            *p_buffer;
+    adpcm_ms_channel_t channel[2];
+    int i_nibbles;
+    uint16_t           *p_sample;
+    int b_stereo;
+    int i_block_predictor;
+    
+    p_buffer = p_adec->p_block;
+    b_stereo = p_adec->p_wf->nChannels == 2 ? 1 : 0;
+
+    GetByte( i_block_predictor );
+    CLAMP( i_block_predictor, 0, 6 );
+    channel[0].i_coeff1 = i_adaptation_coeff1[i_block_predictor];
+    channel[0].i_coeff2 = i_adaptation_coeff2[i_block_predictor];
+
+    if( b_stereo )
+    {
+        GetByte( i_block_predictor );
+        CLAMP( i_block_predictor, 0, 6 );
+        channel[1].i_coeff1 = i_adaptation_coeff1[i_block_predictor];
+        channel[1].i_coeff2 = i_adaptation_coeff2[i_block_predictor];
+    }
+    GetWord( channel[0].i_idelta );
+    if( b_stereo )
+    {
+        GetWord( channel[1].i_idelta );
+    }
+    
+    GetWord( channel[0].i_sample1 );
+    if( b_stereo )
+    {
+        GetWord( channel[1].i_sample1 );
+    }
+
+    GetWord( channel[0].i_sample2 );
+    if( b_stereo )
+    {
+        GetWord( channel[1].i_sample2 );
+    }
+
+    p_sample = (int16_t*)p_aout_buffer->p_buffer;
+
+    if( b_stereo )
+    {
+        *p_sample = channel[0].i_sample2; p_sample++;
+        *p_sample = channel[1].i_sample2; p_sample++;
+        *p_sample = channel[0].i_sample1; p_sample++;
+        *p_sample = channel[1].i_sample1; p_sample++;
+    }
+    else
+    {
+        *p_sample = channel[0].i_sample2; p_sample++;
+        *p_sample = channel[0].i_sample1; p_sample++;
+    }
+
+    for( i_nibbles =  2 *( p_adec->i_block - 7 * p_adec->p_wf->nChannels );
+         i_nibbles > 0; i_nibbles -= 2,p_buffer++ )
+    {
+        *p_sample = AdpcmMsExpandNibble( &channel[0], (*p_buffer) >> 4);
+        p_sample++;
+        
+        *p_sample = AdpcmMsExpandNibble( &channel[b_stereo ? 1 : 0], 
+                                         (*p_buffer)&0x0f);
+        p_sample++;
+    }
+
+    
+}
+
+typedef struct adpcm_ima_wav_channel_s
+{
+    int i_predictor;
+    int i_step_index;
+
+} adpcm_ima_wav_channel_t;
+
+static int AdpcmImaWavExpandNibble(adpcm_ima_wav_channel_t *p_channel,
+                                   int i_nibble )
+{
+    int i_diff;
+
+    i_diff = i_step_table[p_channel->i_step_index] >> 3;
+    if( i_nibble&0x04 ) i_diff += i_step_table[p_channel->i_step_index];
+    if( i_nibble&0x02 ) i_diff += i_step_table[p_channel->i_step_index]>>1;
+    if( i_nibble&0x01 ) i_diff += i_step_table[p_channel->i_step_index]>>2;
+    if( i_nibble&0x08 )
+        p_channel->i_predictor -= i_diff;
+    else
+        p_channel->i_predictor += i_diff;
+
+    CLAMP( p_channel->i_predictor, -32768, 32767 );
+
+    p_channel->i_step_index += i_index_table[i_nibble];
+
+    CLAMP( p_channel->i_step_index, 0, 88 );
+
+    return( p_channel->i_predictor );
+}
+
+static void DecodeAdpcmImaWav( adec_thread_t *p_adec,  
+                               aout_buffer_t *p_aout_buffer)
+{
+    uint8_t                 *p_buffer;
+    adpcm_ima_wav_channel_t channel[2];
+    int                     i_nibbles;
+    uint16_t                *p_sample;
+    int                     b_stereo;
+    
+    p_buffer = p_adec->p_block;
+    b_stereo = p_adec->p_wf->nChannels == 2 ? 1 : 0;
+
+    GetWord( channel[0].i_predictor );
+    GetByte( channel[0].i_step_index );
+    CLAMP( channel[0].i_step_index, 0, 88 );
+    p_buffer++;
+
+    if( b_stereo )
+    {
+        GetWord( channel[1].i_predictor );
+        GetByte( channel[1].i_step_index );
+        CLAMP( channel[1].i_step_index, 0, 88 );
+        p_buffer++;
+    }
+    
+    p_sample = (int16_t*)p_aout_buffer->p_buffer;
+    if( b_stereo )
+    {
+        for( i_nibbles = 2 * (p_adec->i_block - 8); 
+             i_nibbles > 0; 
+             i_nibbles -= 16 )
+        {
+            int i;
+
+            for( i = 0; i < 4; i++ )
+            {
+                p_sample[i * 4] = 
+                    AdpcmImaWavExpandNibble(&channel[0],p_buffer[i]&0x0f);
+                p_sample[i * 4 + 2] =
+                    AdpcmImaWavExpandNibble(&channel[0],p_buffer[i] >> 4);
+            }
+            p_buffer += 4;
+            
+            for( i = 0; i < 4; i++ )
+            {
+                p_sample[i * 4 + 1] = 
+                    AdpcmImaWavExpandNibble(&channel[1],p_buffer[i]&0x0f);
+                p_sample[i * 4 + 3] =
+                    AdpcmImaWavExpandNibble(&channel[1],p_buffer[i] >> 4);
+            }
+            p_buffer += 4;
+            p_sample += 16;
+
+        }
+
+
+    }
+    else
+    {
+        for( i_nibbles = 2 * (p_adec->i_block - 4); 
+             i_nibbles > 0; 
+             i_nibbles -= 2, p_buffer++ )
+        {
+            *p_sample =AdpcmImaWavExpandNibble( &channel[0], (*p_buffer)&0x0f );
+            p_sample++;
+            *p_sample =AdpcmImaWavExpandNibble( &channel[0], (*p_buffer) >> 4 );
+            p_sample++;
+        }
+    }
+}
+
+
+
+
index 7bbda92a3f9af6fd294832a969d51fc08cbadb0a..1e3eb475caeee6f4e6232a071743b1a359a2a5c8 100644 (file)
@@ -2,7 +2,7 @@
  * asf.c : ASFv01 file input module for vlc
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: asf.c,v 1.10 2002/11/28 18:35:19 fenrir Exp $
+ * $Id: asf.c,v 1.11 2002/12/03 17:00:16 fenrir Exp $
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  * 
  * This program is free software; you can redistribute it and/or modify
@@ -235,7 +235,7 @@ static int Activate( vlc_object_t * p_this )
                     break;
                 default:
                     p_stream->p_es->i_fourcc = 
-                        VLC_FOURCC( 'u','n','d','f' );
+                        VLC_FOURCC( 'm','s',(i_codec >> 8)&0xff,i_codec&0xff );
             }
             if( p_sp->i_type_specific_data_length > 0 )
             {
index 9a08dc5ec89eea0cf6988255285fd09e76f0109f..fc0a675655f7ed6a37e1fc4fddcec35c170ff278 100644 (file)
@@ -2,7 +2,7 @@
  * avi.c : AVI file Stream input module for vlc
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: avi.c,v 1.14 2002/11/17 06:46:56 fenrir Exp $
+ * $Id: avi.c,v 1.15 2002/12/03 17:00:16 fenrir Exp $
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  * 
  * This program is free software; you can redistribute it and/or modify
@@ -228,8 +228,7 @@ vlc_fourcc_t AVI_FourccGetCodec( int i_cat, vlc_fourcc_t i_codec )
                     return VLC_FOURCC( 'w', 'm', 'a', '2' );
                 default:
                     return VLC_FOURCC( 'm', 's', 
-                                       ((uint8_t *)&i_codec)[2],
-                                       ((uint8_t *)&i_codec)[3] );
+                                       ( i_codec >> 8 )&0xff, i_codec&0xff );
             }
         case VIDEO_ES:
             // XXX DIV1 <- msmpeg4v1, DIV2 <- msmpeg4v2, DIV3 <- msmpeg4v3, mp4v for mpeg4 
index a915e6cea08997088f616a18d39fe060227776b2..65607dbaa42d1f5d744066564e90309cb4d6ed4c 100644 (file)
@@ -2,7 +2,7 @@
  * wav.c : wav file input module for vlc
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: wav.c,v 1.4 2002/11/28 16:32:29 fenrir Exp $
+ * $Id: wav.c,v 1.5 2002/12/03 17:00:16 fenrir Exp $
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  * 
  * This program is free software; you can redistribute it and/or modify
@@ -98,7 +98,7 @@ static int SeekAbsolute( input_thread_t *p_input,
 
     if( i_pos >= p_input->stream.p_selected_area->i_size )
     {
-        return( 0 );
+    //    return( 0 );
     }
             
     i_filepos = TellAbsolute( p_input );
@@ -296,6 +296,40 @@ static int PCM_GetFrame( input_thread_t *p_input,
     return( ReadPES( p_input, pp_pes, i_bytes ) );
 }
 
+static int MS_ADPCM_GetFrame( input_thread_t *p_input,
+                              WAVEFORMATEX   *p_wf,
+                              pes_packet_t   **pp_pes,
+                              mtime_t        *pi_length )
+{
+    int i_samples;
+
+    i_samples = 2 + 2 * ( p_wf->nBlockAlign - 
+                                7 * p_wf->nChannels ) / p_wf->nChannels;
+    
+    *pi_length = (mtime_t)1000000 *
+                 (mtime_t)i_samples /
+                 (mtime_t)p_wf->nSamplesPerSec;
+
+    return( ReadPES( p_input, pp_pes, p_wf->nBlockAlign ) );
+}
+
+static int IMA_ADPCM_GetFrame( input_thread_t *p_input,
+                               WAVEFORMATEX   *p_wf,
+                               pes_packet_t   **pp_pes,
+                               mtime_t        *pi_length )
+{
+    int i_samples;
+
+    i_samples = 2 * ( p_wf->nBlockAlign - 
+                        4 * p_wf->nChannels ) / p_wf->nChannels;
+    
+    *pi_length = (mtime_t)1000000 *
+                 (mtime_t)i_samples /
+                 (mtime_t)p_wf->nSamplesPerSec;
+
+    return( ReadPES( p_input, pp_pes, p_wf->nBlockAlign ) );
+}
+
 /*****************************************************************************
  * WAVInit: check file and initializes structures
  *****************************************************************************/
@@ -385,25 +419,37 @@ static int WAVInit( vlc_object_t * p_this )
     /* XXX p_demux->psz_demux shouldn't be NULL ! */
     switch( p_demux->p_wf->wFormatTag )
     {
-        case( 0x01 ):
+        case( WAVE_FORMAT_PCM ):
             msg_Dbg( p_input,"found raw pcm audio format" );
             p_demux->i_fourcc = VLC_FOURCC( 'a', 'r', 'a', 'w' );
             p_demux->GetFrame = PCM_GetFrame;
             p_demux->psz_demux = strdup( "" );
             break;
-        case( 0x50 ):
-        case( 0x55 ):
+        case( WAVE_FORMAT_MPEG ):
+        case( WAVE_FORMAT_MPEGLAYER3 ):
             msg_Dbg( p_input, "found mpeg audio format" );
             p_demux->i_fourcc = VLC_FOURCC( 'm', 'p', 'g', 'a' );
             p_demux->GetFrame = NULL;
             p_demux->psz_demux = strdup( "mpegaudio" );
             break;
-        case( 0x2000 ):
+        case( WAVE_FORMAT_A52 ):
             msg_Dbg( p_input,"found a52 audio format" );
             p_demux->i_fourcc = VLC_FOURCC( 'a', '5', '2', ' ' );
             p_demux->GetFrame = NULL;
             p_demux->psz_demux = strdup( "a52" );
             break;
+        case( WAVE_FORMAT_ADPCM ):
+            msg_Dbg( p_input, "found ms adpcm audio format" );
+            p_demux->i_fourcc = VLC_FOURCC( 'm', 's', 0x00, 0x02 );
+            p_demux->GetFrame = MS_ADPCM_GetFrame;
+            p_demux->psz_demux = strdup( "" );
+            break;
+        case( WAVE_FORMAT_IMA_ADPCM ):
+            msg_Dbg( p_input, "found ima adpcm audio format" );
+            p_demux->i_fourcc = VLC_FOURCC( 'm', 's', 0x00, 0x11 );
+            p_demux->GetFrame = IMA_ADPCM_GetFrame;
+            p_demux->psz_demux = strdup( "" );
+            break;
         default:
             msg_Warn( p_input,"unrecognize audio format(0x%x)", 
                       p_demux->p_wf->wFormatTag );
@@ -544,15 +590,14 @@ static int WAVDemux( input_thread_t *p_input )
         i_offset = TellAbsolute( p_input ) - p_demux->i_data_pos;
         if( i_offset < 0 )
         {
-            SeekAbsolute( p_input, p_demux->i_data_pos );
+            i_offset = 0;
         }
-        else
         if( p_demux->p_wf->nBlockAlign != 0 )
         {
-            
-            i_offset = i_offset - i_offset % p_demux->p_wf->nBlockAlign;
-            SeekAbsolute( p_input, p_demux->i_data_pos + i_offset );
+            i_offset += p_demux->p_wf->nBlockAlign - 
+                                i_offset % p_demux->p_wf->nBlockAlign;
         }
+        SeekAbsolute( p_input, p_demux->i_data_pos + i_offset );
     }
     
     input_ClockManageRef( p_input,