[vlc-commits] [Git][videolan/vlc][master] 5 commits: codec: adpcm: fix ADPCM_IMA_QT samplesperblock

François Cartegnie (@fcartegnie) gitlab at videolan.org
Fri Jul 24 11:02:01 UTC 2026



François Cartegnie pushed to branch master at VideoLAN / VLC


Commits:
f400deaf by François Cartegnie at 2026-07-24T12:38:12+02:00
codec: adpcm: fix ADPCM_IMA_QT samplesperblock

refs #29971
Reported-by: HE WEI (ギカク) <skyexpoc at gmail.com>

- - - - -
44a3ca9e by François Cartegnie at 2026-07-24T12:38:12+02:00
codec: adpcm: fix DK3 samplesperblock

- - - - -
16a4358b by François Cartegnie at 2026-07-24T12:38:12+02:00
codec: adpcm: fix EA ADPCM decoded samples boundary

limited by block aligned allocs

- - - - -
bdcb6522 by François Cartegnie at 2026-07-24T12:38:12+02:00
codec: adpcm: fix IMA WAV samplesperblock

- - - - -
9a8f0a76 by François Cartegnie at 2026-07-24T12:38:12+02:00
codec: adpcm: add some more codec description

- - - - -


1 changed file:

- modules/codec/adpcm.c


Changes:

=====================================
modules/codec/adpcm.c
=====================================
@@ -211,16 +211,26 @@ static int OpenDecoder( vlc_object_t *p_this )
     switch( p_sys->codec )
     {
     case ADPCM_IMA_QT:
-        p_sys->i_samplesperblock = 64;
+        if( p_sys->i_block >= 34 * i_channels )
+            p_sys->i_samplesperblock = (p_sys->i_block / (34 * i_channels) ) * 64;
         break;
     case ADPCM_IMA_WAV:
-        if( p_sys->i_block >= 4 * i_channels )
+        /* 4 bytes block/channel preamble */
+        /* samples: 4 bytes aligned nibble per channel. 2 samples per byte */
+        if( i_channels == 2 && p_sys->i_block >= ((4+4) * 2) )
+        {
+            size_t padding = p_sys->i_block % 8;
+            p_sys->i_samplesperblock = 2 * ( p_sys->i_block - 4 * i_channels - padding )
+                                     / i_channels;
+        }
+        else if( i_channels == 1 && p_sys->i_block > 4 )
         {
-            p_sys->i_samplesperblock = 2 * ( p_sys->i_block - 4 * i_channels )
+            p_sys->i_samplesperblock = 2 * ( p_sys->i_block - 4 )
                                      / i_channels;
         }
         break;
     case ADPCM_MS:
+        /* 7 bytes block/channel preamble outputs 2 samples */
         if( p_sys->i_block >= 7 * i_channels )
         {
             p_sys->i_samplesperblock =
@@ -228,6 +238,7 @@ static int OpenDecoder( vlc_object_t *p_this )
         }
         break;
     case ADPCM_DK4:
+        /* 4 bytes block/channel preamble outputs 1 sample */
         if( p_sys->i_block >= 4 * i_channels )
         {
             p_sys->i_samplesperblock =
@@ -235,12 +246,19 @@ static int OpenDecoder( vlc_object_t *p_this )
         }
         break;
     case ADPCM_DK3:
+        /* 16 bytes block (2 channels) preamble outputs 1 sample */
+        /* 3 ADPCM nibbles decodes to 4 16-bit PCM samples. Only stereo */
         i_channels = 2;
-        if( p_sys->i_block >= 16 )
-            p_sys->i_samplesperblock = ( 4 * ( p_sys->i_block - 16 ) + 2 )/ 3;
+        if( p_sys->i_block > 16 )
+        {
+            size_t i_payload = p_sys->i_block - 16;
+            p_sys->i_samplesperblock = 4 * ( i_payload / 3 );
+            if( i_payload % 3 == 2 )
+                p_sys->i_samplesperblock += 2;
+        }
         break;
     case ADPCM_EA:
-        if( p_sys->i_block >= i_channels )
+        if( p_sys->i_block > i_channels )
         {
             p_sys->i_samplesperblock =
                 2 * (p_sys->i_block - i_channels) / i_channels;
@@ -571,7 +589,7 @@ static void DecodeAdpcmImaWav( decoder_t *p_dec, int16_t *p_sample,
     if( b_stereo )
     {
         for( i_nibbles = 2 * (p_sys->i_block - 8);
-             i_nibbles > 0;
+             i_nibbles > 15;
              i_nibbles -= 16 )
         {
             int i;
@@ -617,35 +635,38 @@ static void DecodeAdpcmImaWav( decoder_t *p_dec, int16_t *p_sample,
 static void DecodeAdpcmImaQT( decoder_t *p_dec, int16_t *p_sample,
                               uint8_t *p_buffer )
 {
+    decoder_sys_t *p_sys  = p_dec->p_sys;
     adpcm_ima_wav_channel_t channel[2];
     int                     i_nibbles;
     int                     i_ch;
-    int                     i_step;
+    int                     i_chans = p_dec->fmt_out.audio.i_channels;
 
-    i_step = p_dec->fmt_out.audio.i_channels;
-
-    for( i_ch = 0; i_ch < p_dec->fmt_out.audio.i_channels; i_ch++ )
+    for( unsigned i=0; i<p_sys->i_block/(34 * i_chans); i++)
     {
-        /* load preamble */
-        channel[i_ch].i_predictor  = (int16_t)((( ( p_buffer[0] << 1 )|(  p_buffer[1] >> 7 ) ))<<7);
-        channel[i_ch].i_step_index = p_buffer[1]&0x7f;
+        for( i_ch = 0; i_ch < p_dec->fmt_out.audio.i_channels; i_ch++ )
+        {
+            int16_t *p_out = &p_sample[i_ch];
 
-        CLAMP( channel[i_ch].i_step_index, 0, 88 );
-        p_buffer += 2;
+            /* load preamble */
+            channel[i_ch].i_predictor  = (int16_t)((( ( p_buffer[0] << 1 )|(  p_buffer[1] >> 7 ) ))<<7);
+            channel[i_ch].i_step_index = p_buffer[1]&0x7f;
 
-        for( i_nibbles = 0; i_nibbles < 64; i_nibbles +=2 )
-        {
-            *p_sample = AdpcmImaWavExpandNibble( &channel[i_ch], (*p_buffer)&0x0f);
-            p_sample += i_step;
+            CLAMP( channel[i_ch].i_step_index, 0, 88 );
+            p_buffer += 2;
+
+            for( i_nibbles = 0; i_nibbles < 64; i_nibbles +=2 )
+            {
+                *p_out = AdpcmImaWavExpandNibble( &channel[i_ch], (*p_buffer)&0x0f);
+                p_out += i_chans;
 
-            *p_sample = AdpcmImaWavExpandNibble( &channel[i_ch], (*p_buffer >> 4)&0x0f);
-            p_sample += i_step;
+                *p_out = AdpcmImaWavExpandNibble( &channel[i_ch], (*p_buffer >> 4)&0x0f);
+                p_out += i_chans;
 
-            p_buffer++;
+                p_buffer++;
+            }
         }
 
-        /* Next channel */
-        p_sample += 1 - 64 * i_step;
+        p_sample += 64 * i_chans;
     }
 }
 
@@ -714,9 +735,12 @@ static void DecodeAdpcmDk3( decoder_t *p_dec, int16_t *p_sample,
     GetByte( sum.i_step_index );
     GetByte( diff.i_step_index );
 
+    CLAMP( sum.i_step_index, 0, 88 );
+    CLAMP( diff.i_step_index, 0, 88 );
+
     i_diff_value = diff.i_predictor;
     /* we process 6 nibbles at once */
-    while( p_buffer + 1 <= p_end )
+    while( p_buffer + 1 < p_end )
     {
         /* first 3 nibbles */
         AdpcmImaWavExpandNibble( &sum,
@@ -794,7 +818,7 @@ static void DecodeAdpcmEA( decoder_t *p_dec, int16_t *p_sample,
         d[c] = (input & 0xf) + 8;
     }
 
-    for (p_buffer += chans; p_buffer < p_end; p_buffer += chans)
+    for (p_buffer += chans; p_buffer + chans <= p_end; p_buffer += chans)
     {
         union { uint32_t u; int32_t i; } spl;
 



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/b8105da78375c2c7e7d221e4ace091488a6dcd44...9a8f0a76ad639247188821ba3fc7395abde1850a

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/b8105da78375c2c7e7d221e4ace091488a6dcd44...9a8f0a76ad639247188821ba3fc7395abde1850a
You're receiving this email because of your account on code.videolan.org. Manage all notifications: https://code.videolan.org/-/profile/notifications | Help: https://code.videolan.org/help




More information about the vlc-commits mailing list