]> git.sesse.net Git - vlc/commitdiff
* simple.c: Extended the filter for mono output, and also converted it to the
authorChristophe Massiot <massiot@videolan.org>
Wed, 21 Nov 2007 19:04:49 +0000 (19:04 +0000)
committerChristophe Massiot <massiot@videolan.org>
Wed, 21 Nov 2007 19:04:49 +0000 (19:04 +0000)
   audio_filter2 architecture.

modules/audio_filter/channel_mixer/simple.c

index 7c9c448782708134ba03e1d625ff8c8cebb27405..8c36e36a3b162a035c4f2b27c0deb2fe7416699c 100644 (file)
 /*****************************************************************************
  * Preamble
  *****************************************************************************/
-
 #include <vlc/vlc.h>
 #include <vlc_aout.h>
+#include <vlc_filter.h>
+#include <vlc_block.h>
 
 /*****************************************************************************
  * Local prototypes
@@ -36,6 +37,9 @@ static int  Create    ( vlc_object_t * );
 static void DoWork    ( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
                         aout_buffer_t * );
 
+static int  OpenFilter ( vlc_object_t * );
+static block_t *Filter( filter_t *, block_t * );
+
 /*****************************************************************************
  * Module descriptor
  *****************************************************************************/
@@ -45,6 +49,11 @@ vlc_module_begin();
     set_category( CAT_AUDIO );
     set_subcategory( SUBCAT_AUDIO_MISC );
     set_callbacks( Create, NULL );
+
+    add_submodule();
+    set_description( _("audio filter for simple channel mixing") );
+    set_capability( "audio filter2", 10 );
+    set_callbacks( OpenFilter, NULL );
 vlc_module_end();
 
 /*****************************************************************************
@@ -65,24 +74,27 @@ static int Create( vlc_object_t *p_this )
         return -1;
     }
 
-    /* Only conversion to Stereo and 4.0 right now */
+    /* Only conversion to Mono, Stereo and 4.0 right now */
     if( p_filter->output.i_physical_channels !=
         (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT)
         && p_filter->output.i_physical_channels !=
         ( AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
-        AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT) )
-        {
-            return -1;
-        }
+        AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT)
+        && p_filter->output.i_physical_channels != AOUT_CHAN_CENTER )
+    {
+        return -1;
+    }
 
-    /* Only from 7/7.1/5/5.1 */
+    /* Only from 7/7.1/5/5.1/2.0 */
     if( (p_filter->input.i_physical_channels & ~AOUT_CHAN_LFE) !=
         (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
          AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT) &&
         (p_filter->input.i_physical_channels & ~AOUT_CHAN_LFE) !=
         (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
          AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT |
-         AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT) )
+         AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT) &&
+        p_filter->input.i_physical_channels !=
+        (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT) )
     {
         return -1;
     }
@@ -136,6 +148,37 @@ static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
             if( p_filter->input.i_physical_channels & AOUT_CHAN_LFE ) p_src++;
         }
     }
+    else if( p_filter->output.i_physical_channels == AOUT_CHAN_CENTER )
+    {
+        if( p_filter->input.i_physical_channels & AOUT_CHAN_MIDDLELEFT )
+        for( i = p_in_buf->i_nb_samples; i--; )
+        {
+            *p_dest = p_src[6] + p_src[0] / 4 + p_src[1] / 4 + p_src[2] / 8 + p_src[3] / 8 + p_src[4] / 8 + p_src[5] / 8;
+            p_dest++;
+
+            p_src += 7;
+
+            if( p_filter->input.i_physical_channels & AOUT_CHAN_LFE ) p_src++;
+        }
+        else if( p_filter->input.i_physical_channels & AOUT_CHAN_REARLEFT )
+        for( i = p_in_buf->i_nb_samples; i--; )
+        {
+            *p_dest = p_src[4] + p_src[0] / 4 + p_src[1] / 4 + p_src[2] / 6 + p_src[3] / 6;
+            p_dest++;
+
+            p_src += 5;
+
+            if( p_filter->input.i_physical_channels & AOUT_CHAN_LFE ) p_src++;
+        }
+        else
+        for( i = p_in_buf->i_nb_samples; i--; )
+        {
+            *p_dest = p_src[0] / 2 + p_src[1] / 2;
+            p_dest++;
+
+            p_src += 2;
+        }
+    }
     else
     {
         if( p_filter->input.i_physical_channels & AOUT_CHAN_MIDDLELEFT )
@@ -173,3 +216,108 @@ static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
 
     }
 }
+
+/*****************************************************************************
+ * OpenFilter:
+ *****************************************************************************/
+static int OpenFilter( vlc_object_t *p_this )
+{
+    filter_t *p_filter = (filter_t *)p_this;
+
+    if ( (p_filter->fmt_in.audio.i_physical_channels
+           == p_filter->fmt_out.audio.i_physical_channels
+           && p_filter->fmt_in.audio.i_original_channels
+               == p_filter->fmt_out.audio.i_original_channels)
+          || p_filter->fmt_in.i_codec != p_filter->fmt_out.i_codec
+          || p_filter->fmt_in.audio.i_rate != p_filter->fmt_out.audio.i_rate
+          || p_filter->fmt_in.i_codec != VLC_FOURCC('f','l','3','2') )
+    {
+        return -1;
+    }
+
+    /* Only conversion to Mono, Stereo and 4.0 right now */
+    if( p_filter->fmt_out.audio.i_physical_channels !=
+        (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT)
+        && p_filter->fmt_out.audio.i_physical_channels !=
+        ( AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
+        AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT)
+        && p_filter->fmt_out.audio.i_physical_channels != AOUT_CHAN_CENTER )
+    {
+        return -1;
+    }
+
+    /* Only from 7/7.1/5/5.1/2.0 */
+    if( (p_filter->fmt_in.audio.i_physical_channels & ~AOUT_CHAN_LFE) !=
+        (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
+         AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT) &&
+        (p_filter->fmt_in.audio.i_physical_channels & ~AOUT_CHAN_LFE) !=
+        (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
+         AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT |
+         AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT) &&
+        p_filter->fmt_in.audio.i_physical_channels !=
+        (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT) )
+    {
+        return -1;
+    }
+
+    p_filter->pf_audio_filter = Filter;
+
+    return 0;
+}
+
+/*****************************************************************************
+ * Filter:
+ *****************************************************************************/
+static block_t *Filter( filter_t *p_filter, block_t *p_block )
+{
+    aout_filter_t aout_filter;
+    aout_buffer_t in_buf, out_buf;
+    block_t *p_out;
+    int i_out_size;
+
+    if( !p_block || !p_block->i_samples )
+    {
+        if( p_block ) p_block->pf_release( p_block );
+        return NULL;
+    }
+
+    i_out_size = p_block->i_samples *
+      p_filter->fmt_out.audio.i_bitspersample *
+        p_filter->fmt_out.audio.i_channels / 8;
+
+    p_out = p_filter->pf_audio_buffer_new( p_filter, i_out_size );
+    if( !p_out )
+    {
+        msg_Warn( p_filter, "can't get output buffer" );
+        p_block->pf_release( p_block );
+        return NULL;
+    }
+
+    p_out->i_samples = p_block->i_samples;
+    p_out->i_dts = p_block->i_dts;
+    p_out->i_pts = p_block->i_pts;
+    p_out->i_length = p_block->i_length;
+
+    aout_filter.p_sys = (struct aout_filter_sys_t *)p_filter->p_sys;
+    aout_filter.input = p_filter->fmt_in.audio;
+    aout_filter.input.i_format = p_filter->fmt_in.i_codec;
+    aout_filter.output = p_filter->fmt_out.audio;
+    aout_filter.output.i_format = p_filter->fmt_out.i_codec;
+
+    in_buf.p_buffer = p_block->p_buffer;
+    in_buf.i_nb_bytes = p_block->i_buffer;
+    in_buf.i_nb_samples = p_block->i_samples;
+    out_buf.p_buffer = p_out->p_buffer;
+    out_buf.i_nb_bytes = p_out->i_buffer;
+    out_buf.i_nb_samples = p_out->i_samples;
+
+    DoWork( (aout_instance_t *)p_filter, &aout_filter, &in_buf, &out_buf );
+
+    p_block->pf_release( p_block );
+
+    p_out->i_buffer = out_buf.i_nb_bytes;
+    p_out->i_samples = out_buf.i_nb_samples;
+
+    return p_out;
+}
+