]> git.sesse.net Git - vlc/blobdiff - modules/demux/voc.c
Removes trailing spaces. Removes tabs.
[vlc] / modules / demux / voc.c
index 97a13dc407bd69dca1af57c1b38ce8d3af42d1f3..af211f0a737ce09df9806205157b7e3f86092b5f 100644 (file)
@@ -1,10 +1,10 @@
 /*****************************************************************************
  * voc.c : Creative Voice File (.VOC) demux module for vlc
  *****************************************************************************
- * Copyright (C) 2005 VideoLAN
+ * Copyright (C) 2005 Rémi Denis-Courmont
  * $Id$
  *
- * Authors: Remi Denis-Courmont <rem # videolan.org>
+ * Authors: Rémi Denis-Courmont <rem # videolan.org>
  *
  * 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
  *
  * 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.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
 /*****************************************************************************
  * Preamble
  *****************************************************************************/
-#include <stdlib.h>                                      /* malloc(), free() */
 
 #include <vlc/vlc.h>
-#include <vlc/input.h>
-#include <vlc/aout.h>
+#include <vlc_demux.h>
+#include <vlc_aout.h>
 
-#include <codecs.h>
+#include <vlc_codecs.h>
 
 /*****************************************************************************
  * Module descriptor
@@ -76,7 +75,7 @@ static int Open( vlc_object_t * p_this )
 {
     demux_t     *p_demux = (demux_t*)p_this;
     demux_sys_t *p_sys;
-    uint8_t     *p_buf;
+    const uint8_t *p_buf;
     uint16_t    i_data_offset, i_version;
 
     if( stream_Peek( p_demux->s, &p_buf, 26 ) < 26 )
@@ -156,7 +155,6 @@ static unsigned int fix_voc_sr( unsigned int sr )
     }
     return sr;
 }
-        
 
 static int ReadBlockHeader( demux_t *p_demux )
 {
@@ -189,7 +187,7 @@ static int ReadBlockHeader( demux_t *p_demux )
 
             if( buf[1] )
             {
-                msg_Err( p_demux, "Unsupported compression" );
+                msg_Err( p_demux, "unsupported compression" );
                 return VLC_EGENERIC;
             }
 
@@ -251,12 +249,57 @@ static int ReadBlockHeader( demux_t *p_demux )
             }
             break;
 
-        /* FIXME: support block type 8 properly */
         case 8:
-            msg_Err( p_demux, "Unimplemented block type 8" );
-            return VLC_EGENERIC;
+            /*
+             * Block 8 is a big kludge to add stereo support to block 1 :
+             * A block of type 8 is always followed by a block of type 1
+             * and specifies the number of channels in that 1-block
+             * (normally block 1 are always mono). In practice, block type 9
+             * is used for stereo rather than 8
+             */
+            if( ( i_block_size != 4 )
+             || ( stream_Read( p_demux->s, buf, 4 ) < 4 ) )
+                goto corrupt;
+
+            if( buf[2] )
+            {
+                msg_Err( p_demux, "unsupported compression" );
+                return VLC_EGENERIC;
+            }
+
+            new_fmt.i_codec = VLC_FOURCC('u','8',' ',' ');
+            new_fmt.audio.i_channels = buf[3] + 1; /* can't be nul */
+            new_fmt.audio.i_rate = 256000000L /
+                          ((65536L - GetWLE(buf)) * new_fmt.audio.i_channels);
+            new_fmt.audio.i_bytes_per_frame = new_fmt.audio.i_channels;
+            new_fmt.audio.i_frame_length = 1;
+            new_fmt.audio.i_blockalign = new_fmt.audio.i_bytes_per_frame;
+            new_fmt.audio.i_bitspersample = 8 * new_fmt.audio.i_bytes_per_frame;
+            new_fmt.i_bitrate = new_fmt.audio.i_rate * 8;
+
+            /* read subsequent block 1 */
+            if( stream_Read( p_demux->s, buf, 4 ) < 4 )
+                return VLC_EGENERIC; /* EOF */
+            i_block_size = GetDWLE( buf ) >> 8;
+            msg_Dbg( p_demux, "new block: type: %u, size: %u",
+                    (unsigned)*buf, i_block_size );
+            if( i_block_size < 2 )
+                goto corrupt;
+            i_block_size -= 2;
+
+            if( stream_Read( p_demux->s, buf, 2 ) < 2 )
+                goto corrupt;
+
+            if( buf[1] )
+            {
+                msg_Err( p_demux, "unsupported compression" );
+                return VLC_EGENERIC;
+            }
+
+            break;
 
-        case 9:
+        case 9: /* newer data block with channel number and bits resolution */
             if( i_block_size < 12 )
                 goto corrupt;
             i_block_size -= 12;
@@ -283,7 +326,7 @@ static int ReadBlockHeader( demux_t *p_demux )
                             break;
 
                         default:
-                            msg_Err( p_demux, "Unsupported bit res.: %u bits",
+                            msg_Err( p_demux, "unsupported bit res.: %u bits",
                                      new_fmt.audio.i_bitspersample );
                             return VLC_EGENERIC;
                     }
@@ -301,14 +344,14 @@ static int ReadBlockHeader( demux_t *p_demux )
                             break;
 
                         default:
-                            msg_Err( p_demux, "Unsupported bit res.: %u bits",
+                            msg_Err( p_demux, "unsupported bit res.: %u bits",
                                      new_fmt.audio.i_bitspersample );
                             return VLC_EGENERIC;
                     }
                     break;
 
-                default: 
-                    msg_Err( p_demux, "Unsupported compression" );
+                default:
+                    msg_Err( p_demux, "unsupported compression" );
                     return VLC_EGENERIC;
             }
 
@@ -321,7 +364,7 @@ static int ReadBlockHeader( demux_t *p_demux )
             break;
 
         default:
-            msg_Dbg( p_demux, "Unknown block type %u - skipping block",
+            msg_Dbg( p_demux, "unknown block type %u - skipping block",
                      (unsigned)*buf);
         case 4: /* blocks of non-audio types can be skipped */
         case 5:
@@ -371,6 +414,7 @@ corrupt:
  *****************************************************************************
  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
  *****************************************************************************/
+#define SAMPLES_BUFFER 1000
 static int Demux( demux_t *p_demux )
 {
     demux_sys_t *p_sys = p_demux->p_sys;
@@ -388,8 +432,8 @@ static int Demux( demux_t *p_demux )
     {
         i = ( p_sys->i_block_end - i_offset )
             / p_sys->fmt.audio.i_bytes_per_frame;
-        if( i > 100)
-            i = 100;
+        if( i > SAMPLES_BUFFER )
+            i = SAMPLES_BUFFER;
 
         p_block = stream_Block( p_demux->s,
                                 p_sys->fmt.audio.i_bytes_per_frame * i );
@@ -402,8 +446,8 @@ static int Demux( demux_t *p_demux )
     else
     {   /* emulates silence from the stream */
         i = p_sys->i_silence_countdown;
-        if (i > 100 )
-            i = 100;
+        if( i > SAMPLES_BUFFER )
+            i = SAMPLES_BUFFER;
 
         p_block = block_New( p_demux, i );
         if( p_block == NULL )