[Mplayer-cvslog] CVS: main/libaf af_comp.c,NONE,1.1 af_gate.c,NONE,1.1 af_pan.c,NONE,1.1 af_resample.h,NONE,1.1 af_tools.c,NONE,1.1 Makefile,1.6,1.7 af.c,1.19,1.20 af.h,1.12,1.13 af_channels.c,1.8,1.9 af_delay.c,1.8,1.9 af_equalizer.c,1.2,1.3 af_format.c,1.9,1.10 af_resample.c,1.15,1.16 af_volume.c,1.5,1.6 control.h,1.3,1.4

Anders Johansson CVS anders at mplayerhq.hu
Sat Dec 28 14:59:56 CET 2002


Update of /cvsroot/mplayer/main/libaf
In directory mail:/var/tmp.root/cvs-serv18447

Modified Files:
	Makefile af.c af.h af_channels.c af_delay.c af_equalizer.c 
	af_format.c af_resample.c af_volume.c control.h 
Added Files:
	af_comp.c af_gate.c af_pan.c af_resample.h af_tools.c 
Log Message:
Changes includes:
- Improved runtime control system 
- 3 New filter panning, compressor/limiter and a noise gate
  - The compressor/limiter and the noise gate are not yet finished
  - The panning filter does combined mixing and channel routing and
    can be used to down-mix from stereo to mono (for example)
- Improvements to volume and channel
  - volume now has a very good soft clipping using sin()
  - channel can handle generic routing of audio data 
- Conversion of all filters to handle floating point data
- Cleanup of message printing
- Fix for the sig 11 bug reported by Denes


--- NEW FILE ---
/*=============================================================================
//	
//  This software has been released under the terms of the GNU Public
//  license. See http://www.gnu.org/copyleft/gpl.html for details.
//
//  Copyright 2002 Anders Johansson ajh at atri.curtin.edu.au
//
//=============================================================================
*/

#include <stdio.h>
#include <stdlib.h>

#include <unistd.h>
#include <inttypes.h>
#include <math.h>
#include <limits.h>

#include "af.h"

// Data for specific instances of this filter
typedef struct af_comp_s
{
  int   enable[AF_NCH];		// Enable/disable / channel
  float time[AF_NCH];		// Forgetting factor for power estimate
  float	pow[AF_NCH];		// Estimated power level [dB]
  float	tresh[AF_NCH];		// Threshold [dB]
  float	attack[AF_NCH];		// Attack time [ms]
  float	release[AF_NCH];	// Release time [ms]
  float	ratio[AF_NCH];		// Compression ratio
}af_comp_t;

// Initialization and runtime control
static int control(struct af_instance_s* af, int cmd, void* arg)
{
  af_comp_t* s   = (af_comp_t*)af->setup; 
  int i;

  switch(cmd){
  case AF_CONTROL_REINIT:
    // Sanity check
    if(!arg) return AF_ERROR;
    
    af->data->rate   = ((af_data_t*)arg)->rate;
    af->data->nch    = ((af_data_t*)arg)->nch;
    af->data->format = AF_FORMAT_F | AF_FORMAT_NE;
    af->data->bps    = 4;

    // Time constant set to 0.1s
    //    s->alpha = (1.0/0.2)/(2.0*M_PI*(float)((af_data_t*)arg)->rate); 
    return af_test_output(af,(af_data_t*)arg);
  case AF_CONTROL_COMMAND_LINE:{
/*     float v=-10.0; */
/*     float vol[AF_NCH]; */
/*     float s=0.0; */
/*     float clipp[AF_NCH]; */
/*     int i; */
/*     sscanf((char*)arg,"%f:%f", &v, &s); */
/*     for(i=0;i<AF_NCH;i++){ */
/*       vol[i]=v; */
/*       clipp[i]=s; */
/*     } */
/*     if(AF_OK != control(af,AF_CONTROL_VOLUME_SOFTCLIP | AF_CONTROL_SET, clipp)) */
/*       return AF_ERROR; */
/*     return control(af,AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_SET, vol); */
  }
  case AF_CONTROL_COMP_ON_OFF | AF_CONTROL_SET:
    memcpy(s->enable,(int*)arg,AF_NCH*sizeof(int));
    return AF_OK; 
  case AF_CONTROL_COMP_ON_OFF | AF_CONTROL_GET:
    memcpy((int*)arg,s->enable,AF_NCH*sizeof(int));
    return AF_OK; 
  case AF_CONTROL_COMP_THRESH | AF_CONTROL_SET:
    return af_from_dB(AF_NCH,(float*)arg,s->tresh,20.0,-60.0,-1.0);
  case AF_CONTROL_COMP_THRESH | AF_CONTROL_GET:
    return af_to_dB(AF_NCH,s->tresh,(float*)arg,10.0);
  case AF_CONTROL_COMP_ATTACK | AF_CONTROL_SET:
    return af_from_ms(AF_NCH,(float*)arg,s->attack,af->data->rate,500.0,0.1);
  case AF_CONTROL_COMP_ATTACK | AF_CONTROL_GET:
    return af_to_ms(AF_NCH,s->attack,(float*)arg,af->data->rate);
  case AF_CONTROL_COMP_RELEASE | AF_CONTROL_SET:
    return af_from_ms(AF_NCH,(float*)arg,s->release,af->data->rate,3000.0,10.0);
  case AF_CONTROL_COMP_RELEASE | AF_CONTROL_GET:
    return af_to_ms(AF_NCH,s->release,(float*)arg,af->data->rate);
  case AF_CONTROL_COMP_RATIO | AF_CONTROL_SET:
    for(i=0;i<AF_NCH;i++) 
      s->ratio[i] = clamp(((float*)arg)[i],1.0,10.0);
    return AF_OK;
  case AF_CONTROL_COMP_RATIO | AF_CONTROL_GET:
    for(i=0;i<AF_NCH;i++) 
      ((float*)arg)[i] = s->ratio[i];
    return AF_OK; 
  }
  return AF_UNKNOWN;
}

// Deallocate memory 
static void uninit(struct af_instance_s* af)
{
  if(af->data)
    free(af->data);
  if(af->setup)
    free(af->setup);
}

// Filter data through filter
static af_data_t* play(struct af_instance_s* af, af_data_t* data)
{
  af_data_t*    c   = data;			// Current working data
  af_comp_t*  	s   = (af_comp_t*)af->setup; 	// Setup for this instance
  float*   	a   = (float*)c->audio;		// Audio data
  int       	len = c->len/4;			// Number of samples
  int           ch  = 0;			// Channel counter
  register int	nch = c->nch;			// Number of channels	
  register int  i   = 0;

  // Compress/expand
  for(ch = 0; ch < nch ; ch++){
    if(s->enable[ch]){
      float	t   = 1.0 - s->time[ch];
      for(i=ch;i<len;i+=nch){
	register float x 	= a[i];
	register float pow 	= x*x;	
	s->pow[ch] = t*s->pow[ch] + 
	  pow*s->time[ch]; // LP filter
	if(pow < s->pow[ch]){
	  ;
	}
	else{
	  ;
	}
	a[i] = x;
      }
    }
  }
  return c;
}

// Allocate memory and set function pointers
static int open(af_instance_t* af){
  af->control=control;
  af->uninit=uninit;
  af->play=play;
  af->mul.n=1;
  af->mul.d=1;
  af->data=calloc(1,sizeof(af_data_t));
  af->setup=calloc(1,sizeof(af_comp_t));
  if(af->data == NULL || af->setup == NULL)
    return AF_ERROR;
  return AF_OK;
}

// Description of this filter
af_info_t af_info_comp = {
    "Compressor/expander audio filter",
    "comp",
    "Anders",
    "",
    AF_FLAGS_NOT_REENTRANT,
    open
};

--- NEW FILE ---
/*=============================================================================
//	
//  This software has been released under the terms of the GNU Public
//  license. See http://www.gnu.org/copyleft/gpl.html for details.
//
//  Copyright 2002 Anders Johansson ajh at atri.curtin.edu.au
//
//=============================================================================
*/

#include <stdio.h>
#include <stdlib.h>

#include <unistd.h>
#include <inttypes.h>
#include <math.h>
#include <limits.h>

#include "af.h"

// Data for specific instances of this filter
typedef struct af_gate_s
{
  int   enable[AF_NCH];		// Enable/disable / channel
  float time[AF_NCH];		// Forgetting factor for power estimate
  float	pow[AF_NCH];		// Estimated power level [dB]
  float	tresh[AF_NCH];		// Threshold [dB]
  float	attack[AF_NCH];		// Attack time [ms]
  float	release[AF_NCH];	// Release time [ms]
  float	range[AF_NCH];		// Range level [dB]
}af_gate_t;

// Initialization and runtime control
static int control(struct af_instance_s* af, int cmd, void* arg)
{
  af_gate_t* s   = (af_gate_t*)af->setup; 
  switch(cmd){
  case AF_CONTROL_REINIT:
    // Sanity check
    if(!arg) return AF_ERROR;
    
    af->data->rate   = ((af_data_t*)arg)->rate;
    af->data->nch    = ((af_data_t*)arg)->nch;
    af->data->format = AF_FORMAT_F | AF_FORMAT_NE;
    af->data->bps    = 4;

    // Time constant set to 0.1s
    //    s->alpha = (1.0/0.2)/(2.0*M_PI*(float)((af_data_t*)arg)->rate); 
    return af_test_output(af,(af_data_t*)arg);
  case AF_CONTROL_COMMAND_LINE:{
/*     float v=-10.0; */
/*     float vol[AF_NCH]; */
/*     float s=0.0; */
/*     float clipp[AF_NCH]; */
/*     int i; */
/*     sscanf((char*)arg,"%f:%f", &v, &s); */
/*     for(i=0;i<AF_NCH;i++){ */
/*       vol[i]=v; */
/*       clipp[i]=s; */
/*     } */
/*     if(AF_OK != control(af,AF_CONTROL_VOLUME_SOFTCLIP | AF_CONTROL_SET, clipp)) */
/*       return AF_ERROR; */
/*     return control(af,AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_SET, vol); */
  }

  case AF_CONTROL_GATE_ON_OFF | AF_CONTROL_SET:
    memcpy(s->enable,(int*)arg,AF_NCH*sizeof(int));
    return AF_OK; 
  case AF_CONTROL_GATE_ON_OFF | AF_CONTROL_GET:
    memcpy((int*)arg,s->enable,AF_NCH*sizeof(int));
    return AF_OK; 
  case AF_CONTROL_GATE_THRESH | AF_CONTROL_SET:
    return af_from_dB(AF_NCH,(float*)arg,s->tresh,20.0,-60.0,-1.0);
  case AF_CONTROL_GATE_THRESH | AF_CONTROL_GET:
    return af_to_dB(AF_NCH,s->tresh,(float*)arg,10.0);
  case AF_CONTROL_GATE_ATTACK | AF_CONTROL_SET:
    return af_from_ms(AF_NCH,(float*)arg,s->attack,af->data->rate,500.0,0.1);
  case AF_CONTROL_GATE_ATTACK | AF_CONTROL_GET:
    return af_to_ms(AF_NCH,s->attack,(float*)arg,af->data->rate);
  case AF_CONTROL_GATE_RELEASE | AF_CONTROL_SET:
    return af_from_ms(AF_NCH,(float*)arg,s->release,af->data->rate,3000.0,10.0);
  case AF_CONTROL_GATE_RELEASE | AF_CONTROL_GET:
    return af_to_ms(AF_NCH,s->release,(float*)arg,af->data->rate);
  case AF_CONTROL_GATE_RANGE | AF_CONTROL_SET:
    return af_from_dB(AF_NCH,(float*)arg,s->range,20.0,100.0,0.0);
  case AF_CONTROL_GATE_RANGE | AF_CONTROL_GET:
    return af_to_dB(AF_NCH,s->range,(float*)arg,10.0);
  }
  return AF_UNKNOWN;
}

// Deallocate memory 
static void uninit(struct af_instance_s* af)
{
  if(af->data)
    free(af->data);
  if(af->setup)
    free(af->setup);
}

// Filter data through filter
static af_data_t* play(struct af_instance_s* af, af_data_t* data)
{
  af_data_t*    c   = data;			// Current working data
  af_gate_t*  	s   = (af_gate_t*)af->setup; 	// Setup for this instance
  float*   	a   = (float*)c->audio;		// Audio data
  int       	len = c->len/4;			// Number of samples
  int           ch  = 0;			// Channel counter
  register int	nch = c->nch;			// Number of channels	
  register int  i   = 0;


  // Noise gate
  for(ch = 0; ch < nch ; ch++){
    if(s->enable[ch]){
      float	t   = 1.0 - s->time[ch];
      for(i=ch;i<len;i+=nch){
	register float x 	= a[i];
	register float pow 	= x*x;	
	s->pow[ch] = t*s->pow[ch] + 
	  pow*s->time[ch]; // LP filter
	if(pow < s->pow[ch]){
	  ;
	}
	else{
	  ;
	}
	a[i] = x;
      }
    }
  }
  return c;
}

// Allocate memory and set function pointers
static int open(af_instance_t* af){
  af->control=control;
  af->uninit=uninit;
  af->play=play;
  af->mul.n=1;
  af->mul.d=1;
  af->data=calloc(1,sizeof(af_data_t));
  af->setup=calloc(1,sizeof(af_gate_t));
  if(af->data == NULL || af->setup == NULL)
    return AF_ERROR;
  return AF_OK;
}

// Description of this filter
af_info_t af_info_gate = {
    "Noise gate audio filter",
    "gate",
    "Anders",
    "",
    AF_FLAGS_NOT_REENTRANT,
    open
};

--- NEW FILE ---
/*=============================================================================
//	
//  This software has been released under the terms of the GNU Public
//  license. See http://www.gnu.org/copyleft/gpl.html for details.
//
//  Copyright 2002 Anders Johansson ajh at atri.curtin.edu.au
//
//=============================================================================
*/

/* */

#include <stdio.h>
#include <stdlib.h>

#include <unistd.h>
#include <inttypes.h>
#include <math.h>
#include <limits.h>

#include "af.h"

// Data for specific instances of this filter
typedef struct af_pan_s
{
  float level[AF_NCH][AF_NCH];	// Gain level for each channel
}af_pan_t;

// Initialization and runtime control
static int control(struct af_instance_s* af, int cmd, void* arg)
{
  af_pan_t* s = af->setup; 

  switch(cmd){
  case AF_CONTROL_REINIT:
    // Sanity check
    if(!arg) return AF_ERROR;

    af->data->rate   = ((af_data_t*)arg)->rate;
    af->data->format = AF_FORMAT_F | AF_FORMAT_NE;
    af->data->bps    = 4;
    af->mul.n        = af->data->nch;
    af->mul.d	     = ((af_data_t*)arg)->nch;

    if((af->data->format != ((af_data_t*)arg)->format) || 
       (af->data->bps != ((af_data_t*)arg)->bps)){
      ((af_data_t*)arg)->format = af->data->format;
      ((af_data_t*)arg)->bps = af->data->bps;
      return AF_FALSE;
    }
    return control(af,AF_CONTROL_PAN_NOUT | AF_CONTROL_SET, &af->data->nch);
  case AF_CONTROL_COMMAND_LINE:{
    int   nch = 0;
    int   n = 0;
    char* cp = NULL;
    int   j,k;
    // Read number of outputs
    sscanf((char*)arg,"%i%n", &nch,&n);
    if(AF_OK != control(af,AF_CONTROL_PAN_NOUT | AF_CONTROL_SET, &nch))
      return AF_ERROR;

    // Read pan values
    cp = &((char*)arg)[n];
    j = 0; k = 0;
    while((*cp == ':') && (k < AF_NCH)){
      sscanf(cp, ":%f%n" , &s->level[k][j], &n);
      s->level[k][j] = clamp(s->level[k][j],0.0,1.0);
      af_msg(AF_MSG_VERBOSE,"[pan] Pan level from channel %i to" 
	     " channel %i = %f\n",j,k,s->level[k][j]);
      cp =&cp[n];
      j++;
      if(j>=nch){
	j = 0; 
	k++;
      }
    }
    return AF_OK;
  }
  case AF_CONTROL_PAN_LEVEL | AF_CONTROL_SET:{
    int    i;
    int    ch = ((af_control_ext_t*)arg)->ch;
    float* level = ((af_control_ext_t*)arg)->arg;
    for(i=0;i<AF_NCH;i++)
      s->level[ch][i] = clamp(level[i],0.0,1.0);
    return AF_OK;
  }
  case AF_CONTROL_PAN_LEVEL | AF_CONTROL_GET:{
    int    i;
    int ch = ((af_control_ext_t*)arg)->ch;
    float* level = ((af_control_ext_t*)arg)->arg;
    for(i=0;i<AF_NCH;i++)
      level[i] = s->level[ch][i];
    return AF_OK;
  }
  case AF_CONTROL_PAN_NOUT | AF_CONTROL_SET:
    // Reinit must be called after this function has been called

    // Sanity check
    if(((int*)arg)[0] <= 0 || ((int*)arg)[0] > 6){
      af_msg(AF_MSG_ERROR,"[pan] The number of output channels must be" 
	     " between 1 and %i. Current value is %i\n",AF_NCH,((int*)arg)[0]);
      return AF_ERROR;
    }
    af->data->nch=((int*)arg)[0];
    return AF_OK;
  case AF_CONTROL_PAN_NOUT | AF_CONTROL_GET:
    *(int*)arg = af->data->nch;
    return AF_OK;
  }
  return AF_UNKNOWN;
}

// Deallocate memory 
static void uninit(struct af_instance_s* af)
{
  if(af->data)
    free(af->data);
  if(af->setup)
    free(af->setup);
}

// Filter data through filter
static af_data_t* play(struct af_instance_s* af, af_data_t* data)
{
  af_data_t*    c    = data;		// Current working data
  af_data_t*	l    = af->data;	// Local data
  af_pan_t*  	s    = af->setup; 	// Setup for this instance
  float*   	in   = c->audio;	// Input audio data
  float*   	out  = NULL;		// Output audio data
  float*	end  = in+c->len/4; 	// End of loop
  int		nchi = c->nch;		// Number of input channels
  int		ncho = l->nch;		// Number of output channels
  register int  j,k;

  if(AF_OK != RESIZE_LOCAL_BUFFER(af,data))
    return NULL;

  out = l->audio;
  // Execute panning 
  // FIXME: Too slow
  while(in < end){
    for(j=0;j<ncho;j++){
      register float  x   = 0.0;
      register float* tin = in;
      for(k=0;k<nchi;k++)
	x += tin[k] * s->level[j][k];
      out[j] = x;
    }
    out+= ncho;
    in+= nchi;
  }

  // Set output data
  c->audio = l->audio;
  c->len   = (c->len*af->mul.n)/af->mul.d;
  c->nch   = l->nch;

  return c;
}

// Allocate memory and set function pointers
static int open(af_instance_t* af){
  af->control=control;
  af->uninit=uninit;
  af->play=play;
  af->mul.n=1;
  af->mul.d=1;
  af->data=calloc(1,sizeof(af_data_t));
  af->setup=calloc(1,sizeof(af_pan_t));
  if(af->data == NULL || af->setup == NULL)
    return AF_ERROR;
  // Set initial pan to pass-through.
  return AF_OK;
}

// Description of this filter
af_info_t af_info_pan = {
    "Panning audio filter",
    "pan",
    "Anders",
    "",
    AF_FLAGS_NOT_REENTRANT,
    open
};

--- NEW FILE ---
/*=============================================================================
//	
//  This software has been released under the terms of the GNU Public
//  license. See http://www.gnu.org/copyleft/gpl.html for details.
//
//  Copyright 2002 Anders Johansson ajh at atri.curtin.edu.au
//
//=============================================================================
*/

/* This file contains the resampling engine, the sample format is
   controlled by the FORMAT parameter, the filter length by the L
   parameter and the resampling type by UP and DN. This file should
   only be included by af_resample.c 
*/ 

#undef L
#undef SHIFT
#undef FORMAT
#undef FIR
#undef ADDQUE

/* The lenght Lxx definition selects the length of each poly phase
   component. Valid definitions are L8 and L16 where the number
   defines the nuber of taps. This definition affects the
   computational complexity, the performance and the memory usage.
*/

/* The FORMAT_x parameter selects the sample format type currently
   float and int16 are supported. Thes two formats are selected by
   defining eiter FORMAT_F or FORMAT_I. The advantage of using float
   is that the amplitude and therefore the SNR isn't affected by the
   filtering, the disadvantage is that it is a lot slower.
*/

#if defined(FORMAT_I)
#define SHIFT >>16
#define FORMAT int16_t
#else 
#define SHIFT
#define FORMAT float
#endif

// Short filter
#if defined(L8) 

#define L   	8	// Filter length
// Unrolled loop to speed up execution 
#define FIR(x,w,y) \
  (y[0])  = ( w[0]*x[0]+w[1]*x[1]+w[2]*x[2]+w[3]*x[3] \
            + w[4]*x[4]+w[5]*x[5]+w[6]*x[6]+w[7]*x[7] ) SHIFT



#else  /* L8/L16 */

#define L   	16
// Unrolled loop to speed up execution 
#define FIR(x,w,y) \
  y[0] = ( w[0] *x[0] +w[1] *x[1] +w[2] *x[2] +w[3] *x[3] \
         + w[4] *x[4] +w[5] *x[5] +w[6] *x[6] +w[7] *x[7] \
         + w[8] *x[8] +w[9] *x[9] +w[10]*x[10]+w[11]*x[11] \
         + w[12]*x[12]+w[13]*x[13]+w[14]*x[14]+w[15]*x[15] ) SHIFT

#endif /* L8/L16 */

// Macro to add data to circular que 
#define ADDQUE(xi,xq,in)\
  xq[xi]=xq[xi+L]=(*in);\
  xi=(xi-1)&(L-1);

#if defined(UP)

  uint32_t		ci    = l->nch; 	// Index for channels
  uint32_t		nch   = l->nch;   	// Number of channels
  uint32_t		inc   = s->up/s->dn; 
  uint32_t		level = s->up%s->dn; 
  uint32_t		up    = s->up;
  uint32_t		dn    = s->dn;
  uint32_t		ns    = c->len/l->bps;
  register FORMAT*	w     = s->w;

  register uint32_t	wi    = 0;
  register uint32_t	xi    = 0; 

  // Index current channel
  while(ci--){
    // Temporary pointers
    register FORMAT*	x     = s->xq[ci];
    register FORMAT*	in    = ((FORMAT*)c->audio)+ci;
    register FORMAT*	out   = ((FORMAT*)l->audio)+ci;
    FORMAT* 		end   = in+ns; // Block loop end
    wi = s->wi; xi = s->xi;

    while(in < end){
      register uint32_t	i = inc;
      if(wi<level) i++;

      ADDQUE(xi,x,in);
      in+=nch;
      while(i--){
	// Run the FIR filter
	FIR((&x[xi]),(&w[wi*L]),out);
	len++; out+=nch;
	// Update wi to point at the correct polyphase component
	wi=(wi+dn)%up;
      }
    }

  }
  // Save values that needs to be kept for next time
  s->wi = wi;
  s->xi = xi;
#endif /* UP */

#if defined(DN) /* DN */
  uint32_t		ci    = l->nch; 	// Index for channels
  uint32_t		nch   = l->nch;   	// Number of channels
  uint32_t		inc   = s->dn/s->up; 
  uint32_t		level = s->dn%s->up; 
  uint32_t		up    = s->up;
  uint32_t		dn    = s->dn;
  uint32_t		ns    = c->len/l->bps;
  FORMAT*		w     = s->w;

  register int32_t	i     = 0;
  register uint32_t	wi    = 0;
  register uint32_t	xi    = 0;
  
  // Index current channel
  while(ci--){
    // Temporary pointers
    register FORMAT*	x     = s->xq[ci];
    register FORMAT*	in    = ((FORMAT*)c->audio)+ci;
    register FORMAT*	out   = ((FORMAT*)l->audio)+ci;
    register FORMAT* 	end   = in+ns;    // Block loop end
    i = s->i; wi = s->wi; xi = s->xi;

    while(in < end){

      ADDQUE(xi,x,in);
      in+=nch;
      if((--i)<=0){
	// Run the FIR filter
	FIR((&x[xi]),(&w[wi*L]),out);
	len++;	out+=nch;

	// Update wi to point at the correct polyphase component
	wi=(wi+dn)%up;  

	// Insert i number of new samples in queue
	i = inc;
	if(wi<level) i++;
      }
    }
  }
  // Save values that needs to be kept for next time
  s->wi = wi;
  s->xi = xi;
  s->i = i;
#endif /* DN */

--- NEW FILE ---
#include <math.h>
#include <af.h>

/* Convert to gain value from dB. Returns AF_OK if of and AF_ERROR if
   fail */
inline int af_from_dB(int n, float* in, float* out, float k, float mi, float ma)
{
  int i = 0; 
  // Sanity check
  if(!in || !out) 
    return AF_ERROR;

  for(i=0;i<n;i++){
    if(in[i]<=-200)
      out[i]=0.0;
    else
      out[i]=pow(10.0,clamp(in[i],mi,ma)/k);
  }
  return AF_OK;
}

/* Convert from gain value to dB. Returns AF_OK if of and AF_ERROR if
   fail */
inline int af_to_dB(int n, float* in, float* out, float k)
{
  int i = 0; 
  // Sanity check
  if(!in || !out) 
    return AF_ERROR;

  for(i=0;i<AF_NCH;i++){
    if(in[i] == 0.0)
      out[i]=-200.0;
    else
      out[i]=k*log10(in[i]);
  }
  return AF_OK;
}

/* Convert from ms to sample time*/
inline int af_from_ms(int n, float* in, float* out, int rate, float mi, float ma)
{
  int i = 0; 
  // Sanity check
  if(!in || !out) 
    return AF_ERROR;

  for(i=0;i<AF_NCH;i++)
    out[i]=clamp(in[i],ma,mi);

  return AF_OK;
}

/* Convert from sample time to ms */
inline int af_to_ms(int n, float* in, float* out, int rate)
{
  int i = 0; 
  // Sanity check
  if(!in || !out) 
    return AF_ERROR;

  for(i=0;i<AF_NCH;i++)
    out[i]=in[i];
  
  return AF_OK;
}

/* Helper function for testing the output format */
inline int af_test_output(struct af_instance_s* af, af_data_t* out)
{
  if((af->data->format != out->format) || 
     (af->data->bps    != out->bps)    ||
     (af->data->rate   != out->rate)   ||
     (af->data->nch    != out->nch)){
    memcpy(out,af->data,sizeof(af_data_t));
    return AF_FALSE;
  }
  return AF_OK;
}

Index: Makefile
===================================================================
RCS file: /cvsroot/mplayer/main/libaf/Makefile,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- Makefile	25 Nov 2002 02:19:27 -0000	1.6
+++ Makefile	28 Dec 2002 13:59:53 -0000	1.7
@@ -2,7 +2,7 @@
 
 LIBNAME = libaf.a
 
-SRCS=af.c af_mp.c af_dummy.c af_delay.c af_channels.c af_format.c af_resample.c window.c filter.c af_volume.c af_equalizer.c 
+SRCS=af.c af_mp.c af_dummy.c af_delay.c af_channels.c af_format.c af_resample.c window.c filter.c af_volume.c af_equalizer.c af_tools.c af_comp.c af_gate.c af_pan.c
 
 OBJS=$(SRCS:.c=.o)
 

Index: af.c
===================================================================
RCS file: /cvsroot/mplayer/main/libaf/af.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- af.c	12 Nov 2002 12:33:54 -0000	1.19
+++ af.c	28 Dec 2002 13:59:53 -0000	1.20
@@ -16,6 +16,9 @@
 extern af_info_t af_info_resample;
 extern af_info_t af_info_volume;
 extern af_info_t af_info_equalizer;
+extern af_info_t af_info_gate;
+extern af_info_t af_info_comp;
+extern af_info_t af_info_pan;
 
 static af_info_t* filter_list[]={ \
    &af_info_dummy,\
@@ -25,6 +28,9 @@
    &af_info_resample,\
    &af_info_volume,\
    &af_info_equalizer,\
+   &af_info_gate,\
+   &af_info_comp,\
+   &af_info_pan,\
    NULL \
 };
 
@@ -72,7 +78,7 @@
   // Allocate space for the new filter and reset all pointers
   af_instance_t* new=malloc(sizeof(af_instance_t));
   if(!new){
-    af_msg(AF_MSG_ERROR,"Could not allocate memory\n");
+    af_msg(AF_MSG_ERROR,"[libaf] Could not allocate memory\n");
     return NULL;
   }  
   memset(new,0,sizeof(af_instance_t));
@@ -88,13 +94,14 @@
      non-reentrant */
   if(new->info->flags & AF_FLAGS_NOT_REENTRANT){
     if(af_get(s,name)){
-      af_msg(AF_MSG_ERROR,"There can only be one instance of the filter '%s' in each stream\n",name);  
+      af_msg(AF_MSG_ERROR,"[libaf] There can only be one instance of" 
+	     " the filter '%s' in each stream\n",name);  
       free(new);
       return NULL;
     }
   }
   
-  af_msg(AF_MSG_VERBOSE,"Adding filter %s \n",name);
+  af_msg(AF_MSG_VERBOSE,"[libaf] Adding filter %s \n",name);
   
   // Initialize the new filter
   if(AF_OK == new->info->open(new) && 
@@ -108,7 +115,8 @@
   }
   
   free(new);
-  af_msg(AF_MSG_ERROR,"Couldn't create or open audio filter '%s'\n",name);  
+  af_msg(AF_MSG_ERROR,"[libaf] Couldn't create or open audio filter '%s'\n",
+	 name);  
   return NULL;
 }
 
@@ -165,6 +173,9 @@
 {
   if(!af) return;
 
+  // Print friendly message 
+  af_msg(AF_MSG_VERBOSE,"[libaf] Removing filter %s \n",af->info->name); 
+
   // Notify filter before changing anything
   af->control(af,AF_CONTROL_PRE_DESTROY,0);
 
@@ -234,8 +245,9 @@
 	  // Create format filter
 	  if(NULL == (new = af_prepend(s,af,"format")))
 	    return AF_ERROR;
-	  // Set output format
-	  if(AF_OK != (rv = new->control(new,AF_CONTROL_FORMAT,&in)))
+	  // Set output bits per sample
+	  if(AF_OK != (rv = new->control(new,AF_CONTROL_FORMAT_BPS,&in.bps)) || 
+	     AF_OK != (rv = new->control(new,AF_CONTROL_FORMAT_FMT,&in.format)))
 	    return rv;
 	  // Initialize format filter
 	  if(!new->prev) 
@@ -245,8 +257,11 @@
 	  if(AF_OK != (rv = new->control(new,AF_CONTROL_REINIT,&in)))
 	    return rv;
 	}
-	if(!new) // Should _never_ happen
+	if(!new){ // Should _never_ happen
+	  af_msg(AF_MSG_ERROR,"[libaf] Unable to correct audio format. " 
+		 "This error should never uccur, please send bugreport.\n");
 	  return AF_ERROR;
+	}
 	af=new;
       }
       break;
@@ -264,10 +279,17 @@
       break;
     }
     default:
-      af_msg(AF_MSG_ERROR,"Reinitialization did not work, audio filter '%s' returned error code %i\n",af->info->name,rv);
+      af_msg(AF_MSG_ERROR,"[libaf] Reinitialization did not work, audio" 
+	     " filter '%s' returned error code %i\n",af->info->name,rv);
       return AF_ERROR;
     }
-    af=af->next;
+    // Check if there are any filters left in the list
+    if(NULL == af){
+      if(!af_append(s,s->first,"dummy")) 
+	return -1; 
+    }
+    else
+      af=af->next;
   }while(af);
   return AF_OK;
 }
@@ -315,7 +337,7 @@
       }
     }
   }
-  
+
   // Init filters 
   if(AF_OK != af_reinit(s,s->first))
     return -1;
@@ -340,7 +362,8 @@
 	}
       }
       // Init the new filter
-      if(!af || (AF_OK != af->control(af,AF_CONTROL_RESAMPLE,&(s->output.rate))))
+      if(!af || (AF_OK != af->control(af,AF_CONTROL_RESAMPLE_RATE,
+				      &(s->output.rate))))
 	return -1;
       if(AF_OK != af_reinit(s,af))
       	return -1;
@@ -368,7 +391,8 @@
       else
 	af = s->last;
       // Init the new filter
-      if(!af ||(AF_OK != af->control(af,AF_CONTROL_FORMAT,&(s->output))))
+      if(!af ||(AF_OK != af->control(af,AF_CONTROL_FORMAT_BPS,&(s->output.bps))) 
+	 || (AF_OK != af->control(af,AF_CONTROL_FORMAT_FMT,&(s->output.format))))
 	return -1;
       if(AF_OK != af_reinit(s,af))
 	return -1;
@@ -383,7 +407,8 @@
        (s->last->data->nch    != s->output.nch)    || 
        (s->last->data->rate   != s->output.rate))  {
       // Something is stuffed audio out will not work 
-      af_msg(AF_MSG_ERROR,"Unable to setup filter system can not meet sound-card demands, please report this error on MPlayer development mailing list. \n");
+      af_msg(AF_MSG_ERROR,"[libaf] Unable to setup filter system can not" 
+	     " meet sound-card demands, please send bugreport. \n");
       af_uninit(s);
       return -1;
     }
@@ -493,6 +518,10 @@
     mul.d *= af->mul.d;
     af=af->next;
   }while(af);
+  // Sanity check 
+  if(!mul.n || !mul.d) 
+    return -1;
+
   in = t * (((len/t) * mul.d - 1)/mul.n);
   
   if(in>max_insize) in=t*(max_insize/t);
@@ -531,14 +560,15 @@
 {
   // Calculate new length
   register int len = af_lencalc(af->mul,data);
-  af_msg(AF_MSG_VERBOSE,"Reallocating memory in module %s, old len = %i, new len = %i\n",af->info->name,af->data->len,len);
+  af_msg(AF_MSG_VERBOSE,"[libaf] Reallocating memory in module %s, " 
+	 "old len = %i, new len = %i\n",af->info->name,af->data->len,len);
   // If there is a buffer free it
   if(af->data->audio) 
     free(af->data->audio);
   // Create new buffer and check that it is OK
   af->data->audio = malloc(len);
   if(!af->data->audio){
-    af_msg(AF_MSG_FATAL,"Could not allocate memory \n");
+    af_msg(AF_MSG_FATAL,"[libaf] Could not allocate memory \n");
     return AF_ERROR;
   }
   af->data->len=len;

Index: af.h
===================================================================
RCS file: /cvsroot/mplayer/main/libaf/af.h,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- af.h	13 Nov 2002 09:09:50 -0000	1.12
+++ af.h	28 Dec 2002 13:59:53 -0000	1.13
@@ -180,6 +180,19 @@
    needed */
 int af_lencalc(frac_t mul, af_data_t* data);
 
+/* Helper function used to convert to gain value from dB. Returns
+   AF_OK if of and AF_ERROR if fail */
+int af_from_dB(int n, float* in, float* out, float k, float mi, float ma);
+/* Helper function used to convert from gain value to dB. Returns
+   AF_OK if of and AF_ERROR if fail */
+int af_to_dB(int n, float* in, float* out, float k);
+/* Helper function used to convert from ms to sample time*/
+int af_from_ms(int n, float* in, float* out, int rate, float mi, float ma);
+/* Helper function used to convert from sample time to ms */
+int af_to_ms(int n, float* in, float* out, int rate); 
+/* Helper function for testing the output format */
+int af_test_output(struct af_instance_s* af, af_data_t* out);
+
 /* Memory reallocation macro: if a local buffer is used (i.e. if the
    filter doesn't operate on the incoming buffer this macro must be
    called to ensure the buffer is big enough. */

Index: af_channels.c
===================================================================
RCS file: /cvsroot/mplayer/main/libaf/af_channels.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- af_channels.c	12 Nov 2002 12:33:54 -0000	1.8
+++ af_channels.c	28 Dec 2002 13:59:53 -0000	1.9
@@ -10,6 +10,15 @@
 
 #include "af.h"
 
+#define FR 0
+#define TO 1
+
+typedef struct af_channels_s{
+  int route[AF_NCH][2];
+  int nr;
+  int router;
+}af_channels_t;
+
 // Local function for copying data
 void copy(void* in, void* out, int ins, int inos,int outs, int outos, int len, int bps)
 {
@@ -67,41 +76,140 @@
     break;
   }
   default:
-    af_msg(AF_MSG_ERROR,"[channels] Unsupported number of bytes/sample: %i please report this error on the MPlayer mailing list. \n",bps);
+    af_msg(AF_MSG_ERROR,"[channels] Unsupported number of bytes/sample: %i" 
+	   " please report this error on the MPlayer mailing list. \n",bps);
+  }
+}
+
+// Make sure the routes are sane
+static int check_routes(af_channels_t* s, int nin, int nout)
+{
+  int i;
+  if((s->nr < 1) || (s->nr > AF_NCH)){
+    af_msg(AF_MSG_ERROR,"[channels] The number of routing pairs musst be" 
+	   " between 1 and %i. Current value is %i\n",AF_NCH,s->nr);
+    return AF_ERROR;
+  }
+	
+  for(i=0;i<s->nr;i++){
+    if((s->route[i][FR] >= nin) || (s->route[i][TO] >= nout)){
+      af_msg(AF_MSG_ERROR,"[channels] Invalid routing in pair nr. %i.\n", i);
+      return AF_ERROR;
+    }
   }
+  return AF_OK;
 }
 
 // Initialization and runtime control
 static int control(struct af_instance_s* af, int cmd, void* arg)
 {
+  af_channels_t* s = af->setup;
   switch(cmd){
   case AF_CONTROL_REINIT:
-    // Make sure this filter isn't redundant 
-    if(af->data->nch == ((af_data_t*)arg)->nch)
-      return AF_DETACH;
+
+    // Set default channel assignment
+    if(!s->router){
+      int i;
+      // Make sure this filter isn't redundant 
+      if(af->data->nch == ((af_data_t*)arg)->nch)
+	return AF_DETACH;
+
+      // If mono: fake stereo
+      if(((af_data_t*)arg)->nch == 1){
+	s->nr = min(af->data->nch,2);
+	for(i=0;i<s->nr;i++){
+	  s->route[i][FR] = 0;
+	  s->route[i][TO] = i;
+	}
+      }
+      else{
+	s->nr = min(af->data->nch, ((af_data_t*)arg)->nch);
+	for(i=0;i<s->nr;i++){
+	  s->route[i][FR] = i;
+	  s->route[i][TO] = i;
+	}
+      }
+    }
 
     af->data->rate   = ((af_data_t*)arg)->rate;
     af->data->format = ((af_data_t*)arg)->format;
     af->data->bps    = ((af_data_t*)arg)->bps;
     af->mul.n        = af->data->nch;
     af->mul.d	     = ((af_data_t*)arg)->nch;
-    return AF_OK;
+    return check_routes(s,((af_data_t*)arg)->nch,af->data->nch);
   case AF_CONTROL_COMMAND_LINE:{
     int nch = 0;
-    sscanf((char*)arg,"%i",&nch);
-    return af->control(af,AF_CONTROL_CHANNELS,&nch);
-  }  
-  case AF_CONTROL_CHANNELS: 
+    int n = 0;
+    // Check number of channels and number of routing pairs
+    sscanf(arg, "%i:%i%n", &nch, &s->nr, &n);
+
+    // If router scan commandline for routing pairs
+    if(s->nr){
+      char* cp = &((char*)arg)[n];
+      int ch = 0;
+      // Sanity check
+      if((s->nr < 1) || (s->nr > AF_NCH)){
+	af_msg(AF_MSG_ERROR,"[channels] The number of routing pairs musst be" 
+	     " between 1 and %i. Current value is %i\n",AF_NCH,s->nr);
+      }	
+      s->router = 1;
+      // Scan for pairs on commandline
+      while((*cp == ':') && (ch < s->nr)){
+	sscanf(cp, ":%i:%i%n" ,&s->route[ch][FR], &s->route[ch][TO], &n);
+	af_msg(AF_MSG_DEBUG0,"[channels] Routing from channel %i to" 
+	       " channel %i\n",s->route[ch][FR],s->route[ch][TO]);
+	cp = &cp[n];
+	ch++;
+      }
+    }
+
+    if(AF_OK != af->control(af,AF_CONTROL_CHANNELS | AF_CONTROL_SET ,&nch))
+      return AF_ERROR;
+    return AF_OK;
+  }    
+  case AF_CONTROL_CHANNELS | AF_CONTROL_SET: 
     // Reinit must be called after this function has been called
     
     // Sanity check
     if(((int*)arg)[0] <= 0 || ((int*)arg)[0] > 6){
-      af_msg(AF_MSG_ERROR,"[channels] The number of output channels must be between 1 and 6. Current value is%i \n",((int*)arg)[0]);
+      af_msg(AF_MSG_ERROR,"[channels] The number of output channels must be" 
+	     " between 1 and %i. Current value is %i\n",AF_NCH,((int*)arg)[0]);
       return AF_ERROR;
     }
 
     af->data->nch=((int*)arg)[0]; 
-    af_msg(AF_MSG_VERBOSE,"[channels] Changing number of channels to %i\n",af->data->nch);
+    if(!s->router)
+      af_msg(AF_MSG_VERBOSE,"[channels] Changing number of channels" 
+	     " to %i\n",af->data->nch);
+    return AF_OK;
+  case AF_CONTROL_CHANNELS | AF_CONTROL_GET:
+    *(int*)arg = af->data->nch;
+    return AF_OK;
+  case AF_CONTROL_CHANNELS_ROUTING | AF_CONTROL_SET:{
+    int ch = ((af_control_ext_t*)arg)->ch;
+    int* route = ((af_control_ext_t*)arg)->arg;
+    s->route[ch][FR] = route[FR];
+    s->route[ch][TO] = route[TO];
+    return AF_OK;
+  }
+  case AF_CONTROL_CHANNELS_ROUTING | AF_CONTROL_GET:{
+    int ch = ((af_control_ext_t*)arg)->ch;
+    int* route = ((af_control_ext_t*)arg)->arg;
+    route[FR] = s->route[ch][FR];
+    route[TO] = s->route[ch][TO];
+    return AF_OK;
+  }
+  case AF_CONTROL_CHANNELS_NR | AF_CONTROL_SET:
+    s->nr = *(int*)arg;
+    return AF_OK;
+  case AF_CONTROL_CHANNELS_NR | AF_CONTROL_GET:
+    *(int*)arg = s->nr;
+    return AF_OK;
+  case AF_CONTROL_CHANNELS_ROUTER | AF_CONTROL_SET:
+    s->router = *(int*)arg;
+    return AF_OK;
+  case AF_CONTROL_CHANNELS_ROUTER | AF_CONTROL_GET:
+    *(int*)arg = s->router;
     return AF_OK;
   }
   return AF_UNKNOWN;
@@ -110,6 +218,8 @@
 // Deallocate memory 
 static void uninit(struct af_instance_s* af)
 {
+  if(af->setup)
+    free(af->setup);
   if(af->data)
     free(af->data);
 }
@@ -117,32 +227,21 @@
 // Filter data through filter
 static af_data_t* play(struct af_instance_s* af, af_data_t* data)
 {
-  af_data_t*   c = data;			// Current working data
-  af_data_t*   l = af->data;	 		// Local data
-
+  af_data_t*   	 c = data;			// Current working data
+  af_data_t*   	 l = af->data;	 		// Local data
+  af_channels_t* s = af->setup;
+  int 		 i;
+  
   if(AF_OK != RESIZE_LOCAL_BUFFER(af,data))
     return NULL;
 
-  // Reset unused channels if nch in < nch out
-  if(af->mul.n > af->mul.d)
-    memset(l->audio,0,(c->len*af->mul.n)/af->mul.d);
+  // Reset unused channels
+  memset(l->audio,0,(c->len*af->mul.n)/af->mul.d);
   
-  // Special case always output L & R
-  if(c->nch == 1){
-    copy(c->audio,l->audio,1,0,l->nch,0,c->len,c->bps);
-    copy(c->audio,l->audio,1,0,l->nch,1,c->len,c->bps);
-  }
-  else{
-    int i;
-    if(l->nch < c->nch){ 
-      for(i=0;i<l->nch;i++) // Truncates R if l->nch == 1 not good need mixing
-	copy(c->audio,l->audio,c->nch,i,l->nch,i,c->len,c->bps);	
-    }
-    else{
-      for(i=0;i<c->nch;i++)
-	copy(c->audio,l->audio,c->nch,i,l->nch,i,c->len,c->bps);	
-    }
-  }
+  if(AF_OK == check_routes(s,c->nch,l->nch))
+    for(i=0;i<s->nr;i++)
+      copy(c->audio,l->audio,c->nch,s->route[i][FR],
+	   l->nch,s->route[i][TO],c->len,c->bps);
   
   // Set output data
   c->audio = l->audio;
@@ -160,7 +259,8 @@
   af->mul.n=1;
   af->mul.d=1;
   af->data=calloc(1,sizeof(af_data_t));
-  if(af->data == NULL)
+  af->setup=calloc(1,sizeof(af_channels_t));
+  if((af->data == NULL) || (af->setup == NULL))
     return AF_ERROR;
   return AF_OK;
 }

Index: af_delay.c
===================================================================
RCS file: /cvsroot/mplayer/main/libaf/af_delay.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- af_delay.c	4 Dec 2002 21:48:15 -0000	1.8
+++ af_delay.c	28 Dec 2002 13:59:53 -0000	1.9
@@ -27,14 +27,15 @@
     af->data->format = ((af_data_t*)arg)->format;
     af->data->bps    = ((af_data_t*)arg)->bps;
     
-    return af->control(af,AF_CONTROL_DELAY_SET_LEN,&((af_delay_t*)af->setup)->tlen);
+    return af->control(af,AF_CONTROL_DELAY_LEN | AF_CONTROL_SET,
+		       &((af_delay_t*)af->setup)->tlen);
   }
   case AF_CONTROL_COMMAND_LINE:{
     float d = 0;
     sscanf((char*)arg,"%f",&d);
-    return af->control(af,AF_CONTROL_DELAY_SET_LEN,&d);
+    return af->control(af,AF_CONTROL_DELAY_LEN | AF_CONTROL_SET,&d);
   }  
-  case AF_CONTROL_DELAY_SET_LEN:{
+  case AF_CONTROL_DELAY_LEN | AF_CONTROL_SET:{
     af_delay_t* s  = (af_delay_t*)af->setup;
     void*       bt = s->buf; // Old buffer
     int         lt = s->len; // Old len
@@ -50,8 +51,7 @@
     // Set new len and allocate new buffer
     s->tlen = *((float*)arg);
     af->delay = s->tlen * 1000.0;
-//    s->len  = af->data->rate*af->data->bps*af->data->nch*(int)s->tlen;
-    s->len  = ((int)(af->data->rate*s->tlen))*af->data->bps*af->data->nch;
+    s->len  = af->data->rate*af->data->bps*af->data->nch*(int)s->tlen;
     s->buf  = malloc(s->len);
     af_msg(AF_MSG_DEBUG0,"[delay] Delaying audio output by %0.2fs\n",s->tlen);
     af_msg(AF_MSG_DEBUG1,"[delay] Delaying audio output by %i bytes\n",s->len);
@@ -74,6 +74,9 @@
     }
     return AF_OK;
   }
+  case AF_CONTROL_DELAY_LEN | AF_CONTROL_GET:
+    *((float*)arg) = ((af_delay_t*)af->setup)->tlen;
+    return AF_OK;
   }
   return AF_UNKNOWN;
 }

Index: af_equalizer.c
===================================================================
RCS file: /cvsroot/mplayer/main/libaf/af_equalizer.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- af_equalizer.c	12 Nov 2002 12:33:54 -0000	1.2
+++ af_equalizer.c	28 Dec 2002 13:59:53 -0000	1.3
@@ -22,16 +22,27 @@
 #include <math.h>
 
 #include "af.h"
-#include "equalizer.h"
 
-#define NCH	AF_NCH // Number of channels
 #define L   	2      // Storage for filter taps
 #define KM  	10     // Max number of bands 
 
 #define Q   1.2247449 /* Q value for band-pass filters 1.2247=(3/2)^(1/2)
 			 gives 4dB suppression @ Fc*2 and Fc/2 */
 
-// Center frequencies for band-pass filters
+/* Center frequencies for band-pass filters
+   The different frequency bands are:	
+   nr.    	center frequency
+   0  	31.25 Hz
+   1 	62.50 Hz
+   2	125.0 Hz
+   3	250.0 Hz
+   4	500.0 Hz
+   5	1.000 kHz
+   6	2.000 kHz
+   7	4.000 kHz
+   8	8.000 kHz
+   9 	16.00 kHz
+*/
 #define CF  	{31.25,62.5,125,250,500,1000,2000,4000,8000,16000}
 
 // Maximum and minimum gain for the bands
@@ -41,12 +52,12 @@
 // Data for specific instances of this filter
 typedef struct af_equalizer_s
 {
-  float   a[KM][L];        // A weights
-  float   b[KM][L];        // B weights
-  float   wq[NCH][KM][L];  // Circular buffer for W data
-  float   g[NCH][KM];      // Gain factor for each channel and band
-  int     K; 		   // Number of used eq bands
-  int     channels;        // Number of channels
+  float   a[KM][L];        	// A weights
+  float   b[KM][L];	     	// B weights
+  float   wq[AF_NCH][KM][L];  	// Circular buffer for W data
+  float   g[AF_NCH][KM];      	// Gain factor for each channel and band
+  int     K; 		   	// Number of used eq bands
+  int     channels;        	// Number of channels
 } af_equalizer_t;
 
 // 2nd order Band-pass Filter design
@@ -76,8 +87,8 @@
     
     af->data->rate   = ((af_data_t*)arg)->rate;
     af->data->nch    = ((af_data_t*)arg)->nch;
-    af->data->format = AF_FORMAT_NE | AF_FORMAT_SI;
-    af->data->bps    = 2;
+    af->data->format = AF_FORMAT_NE | AF_FORMAT_F;
+    af->data->bps    = 4;
     
     // Calculate number of active filters
     s->K=KM;
@@ -85,7 +96,8 @@
       s->K--;
     
     if(s->K != KM)
-      af_msg(AF_MSG_INFO,"Limiting the number of filters to %i due to low sample rate.\n",s->K);
+      af_msg(AF_MSG_INFO,"[equalizer] Limiting the number of filters to" 
+	     " %i due to low sample rate.\n",s->K);
 
     // Generate filter taps
     for(k=0;k<s->K;k++)
@@ -94,18 +106,14 @@
     // Calculate how much this plugin adds to the overall time delay
     af->delay += 2000.0/((float)af->data->rate);
 
-    // Only signed 16 bit little endian is supported 
-    if(af->data->format != ((af_data_t*)arg)->format || 
-       af->data->bps != ((af_data_t*)arg)->bps)
-      return AF_FALSE;
-    return AF_OK;
+    return af_test_output(af,arg);
   }
   case AF_CONTROL_COMMAND_LINE:{
     float g[10]={0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0};
     int i,j;
     sscanf((char*)arg,"%f:%f:%f:%f:%f:%f:%f:%f:%f:%f", &g[0], &g[1], 
 	   &g[2], &g[3], &g[4], &g[5], &g[6], &g[7], &g[8] ,&g[9]);
-    for(i=0;i<NCH;i++){
+    for(i=0;i<AF_NCH;i++){
       for(j=0;j<KM;j++){
 	((af_equalizer_t*)af->setup)->g[i][j] = 
 	  pow(10.0,clamp(g[j],G_MIN,G_MAX)/20.0)-1.0;
@@ -113,23 +121,28 @@
     }
     return AF_OK;
   }
-  case AF_CONTROL_EQUALIZER_SET_GAIN:{
-    float gain = ((equalizer_t*)arg)->gain;
-    int   ch   = ((equalizer_t*)arg)->channel;
-    int   band = ((equalizer_t*)arg)->band;
-    if(ch > NCH || ch < 0 || band > KM || band < 0)
+  case AF_CONTROL_EQUALIZER_GAIN | AF_CONTROL_SET:{
+    float* gain = ((af_control_ext_t*)arg)->arg;
+    int    ch   = ((af_control_ext_t*)arg)->ch;
+    int    k;
+    if(ch > AF_NCH || ch < 0)
       return AF_ERROR;
-    
-    s->g[ch][band] = pow(10.0,clamp(gain,G_MIN,G_MAX)/20.0)-1.0;
+
+    for(k = 0 ; k<KM ; k++)
+      s->g[ch][k] = pow(10.0,clamp(gain[k],G_MIN,G_MAX)/20.0)-1.0;
+
     return AF_OK;
   }
-  case AF_CONTROL_EQUALIZER_GET_GAIN:{
-    int ch     =((equalizer_t*)arg)->channel;
-    int band   =((equalizer_t*)arg)->band;
-    if(ch > NCH || ch < 0 || band > KM || band < 0)
+  case AF_CONTROL_EQUALIZER_GAIN | AF_CONTROL_GET:{
+    float* gain = ((af_control_ext_t*)arg)->arg;
+    int    ch   = ((af_control_ext_t*)arg)->ch;
+    int    k;
+    if(ch > AF_NCH || ch < 0)
       return AF_ERROR;
-    
-    ((equalizer_t*)arg)->gain = log10(s->g[ch][band]+1.0) * 20.0;
+
+    for(k = 0 ; k<KM ; k++)
+      gain[k] = log10(s->g[ch][k]+1.0) * 20.0;
+
     return AF_OK;
   }
   }
@@ -155,13 +168,13 @@
 
   while(ci--){
     float*	g   = s->g[ci];      // Gain factor 
-    int16_t*	in  = ((int16_t*)c->audio)+ci;
-    int16_t*	out = ((int16_t*)c->audio)+ci;
-    int16_t* 	end = in + c->len/2; // Block loop end
+    float*	in  = ((float*)c->audio)+ci;
+    float*	out = ((float*)c->audio)+ci;
+    float* 	end = in + c->len/4; // Block loop end
 
     while(in < end){
-      register uint32_t	k  = 0;   	   // Frequency band index
-      register float 	yt = (float)(*in); // Current input sample
+      register uint32_t	k  = 0;		// Frequency band index
+      register float 	yt = *in; 	// Current input sample
       in+=nch;
       
       // Run the filters
@@ -177,7 +190,7 @@
 	wq[0] = w;
       }
       // Calculate output 
-      *out=(int16_t)(yt/(4.0*10.0));
+      *out=yt/(4.0*10.0);
       out+=nch;
     }
   }

Index: af_format.c
===================================================================
RCS file: /cvsroot/mplayer/main/libaf/af_format.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- af_format.c	14 Nov 2002 09:47:46 -0000	1.9
+++ af_format.c	28 Dec 2002 13:59:53 -0000	1.10
@@ -126,26 +126,32 @@
   return str;
 }
 
-// Helper function to check sanity for input arguments
-int check_sanity(af_data_t* data)
+// Helper functions to check sanity for input arguments
+
+// Sanity check for bytes per sample
+int check_bps(int bps)
 {
-  char buf[256];
-  // Sanity check for bytes per sample
-  if(data->bps != 4 && data->bps != 2 && data->bps != 1){
-    af_msg(AF_MSG_ERROR,"[format] The number of bytes per sample must be 1, 2 or 4. Current value is %i \n",data->bps);
+  if(bps != 4 && bps != 2 && bps != 1){
+    af_msg(AF_MSG_ERROR,"[format] The number of bytes per sample" 
+	   " must be 1, 2 or 4. Current value is %i \n",bps);
     return AF_ERROR;
   }
+  return AF_OK;
+}
 
-  // Check for unsupported formats
-  switch(data->format & AF_FORMAT_SPECIAL_MASK){
+// Check for unsupported formats
+int check_format(int format)
+{
+  char buf[256];
+  switch(format & AF_FORMAT_SPECIAL_MASK){
   case(AF_FORMAT_MPEG2): 
   case(AF_FORMAT_AC3):
     af_msg(AF_MSG_ERROR,"[format] Sample format %s not yet supported \n",
-	 fmt2str(data->format,buf,255)); 
+	 fmt2str(format,buf,255)); 
     return AF_ERROR;
   }
   return AF_OK;
-}	
+}
 
 // Initialization and runtime control
 static int control(struct af_instance_s* af, int cmd, void* arg)
@@ -158,10 +164,12 @@
     if(af->data->format == ((af_data_t*)arg)->format && 
        af->data->bps == ((af_data_t*)arg)->bps)
       return AF_DETACH;
-    
+
     // Check for errors in configuraton
-    if(AF_OK != check_sanity((af_data_t*)arg) || 
-       AF_OK != check_sanity(af->data))
+    if((AF_OK != check_bps(((af_data_t*)arg)->bps)) ||
+       (AF_OK != check_format(((af_data_t*)arg)->format)) ||
+       (AF_OK != check_bps(af->data->bps)) ||
+       (AF_OK != check_format(af->data->format)))
       return AF_ERROR;
 
     af_msg(AF_MSG_VERBOSE,"[format] Changing sample format from %ibit %sto %ibit %s \n",
@@ -175,35 +183,47 @@
     return AF_OK;
   }
   case AF_CONTROL_COMMAND_LINE:{
-    af_data_t d={NULL,0,0,0,0,2};
+    int bps = 2;
+    int format = AF_FORMAT_NE;
     char str[256];
     str[0] = '\0';
-    sscanf((char*)arg,"%i:%s",&(d.bps),str);
+    sscanf((char*)arg,"%i:%s",&bps,str);
     // Convert string to format
-    d.format = str2fmt(str);
+    format = str2fmt(str);
     
     // Automatic correction of errors
-    switch(d.format & AF_FORMAT_SPECIAL_MASK){
+    switch(format & AF_FORMAT_SPECIAL_MASK){
     case(AF_FORMAT_A_LAW):
     case(AF_FORMAT_MU_LAW): 
-      d.bps=1; break;
+      bps=1; break;
     case(AF_FORMAT_AC3):
-      d.bps=4; break; // I think
+      bps=4; break; // I think
     }
-    if(AF_FORMAT_F == (d.format & AF_FORMAT_POINT_MASK))
-      d.bps=4;
-
-    return af->control(af,AF_CONTROL_FORMAT,&d);
+    if(AF_FORMAT_F == (format & AF_FORMAT_POINT_MASK))
+      bps=4;
+    
+    if((AF_OK != af->control(af,AF_CONTROL_FORMAT_BPS | AF_CONTROL_SET,&bps)) ||
+       (AF_OK != af->control(af,AF_CONTROL_FORMAT_FMT | AF_CONTROL_SET,&format)))
+      return AF_ERROR;
+    return AF_OK;
   }
-  case AF_CONTROL_FORMAT:
+  case AF_CONTROL_FORMAT_BPS | AF_CONTROL_SET:
     // Reinit must be called after this function has been called
     
     // Check for errors in configuraton
-    if(AF_OK != check_sanity((af_data_t*)arg))
+    if(AF_OK != check_bps(*(int*)arg))
+      return AF_ERROR;
+
+    af->data->bps = *(int*)arg;
+    return AF_OK;
+  case AF_CONTROL_FORMAT_FMT | AF_CONTROL_SET:
+    // Reinit must be called after this function has been called
+
+    // Check for errors in configuraton
+    if(AF_OK != check_format(*(int*)arg))
       return AF_ERROR;
 
-    af->data->format = ((af_data_t*)arg)->format;
-    af->data->bps=((af_data_t*)arg)->bps; 
+    af->data->format = *(int*)arg;
     return AF_OK;
   }
   return AF_UNKNOWN;

Index: af_resample.c
===================================================================
RCS file: /cvsroot/mplayer/main/libaf/af_resample.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- af_resample.c	14 Dec 2002 17:55:38 -0000	1.15
+++ af_resample.c	28 Dec 2002 13:59:53 -0000	1.16
@@ -25,45 +25,36 @@
    slow and to 16 if the machine is fast and has MMX.  
 */
 
-#if !defined(HAVE_SSE) && !defined(HAVE_3DNOW) // This machine is slow
-
-#define L   	8	// Filter length
-// Unrolled loop to speed up execution 
-#define FIR(x,w,y) \
-  (y[0])  = ( w[0]*x[0]+w[1]*x[1]+w[2]*x[2]+w[3]*x[3] \
-            + w[4]*x[4]+w[5]*x[5]+w[6]*x[6]+w[7]*x[7] ) >> 16
-
-#else  /* Fast machine */
-
-#define L   	16
-// Unrolled loop to speed up execution 
-#define FIR(x,w,y) \
-  y[0] = ( w[0] *x[0] +w[1] *x[1] +w[2] *x[2] +w[3] *x[3] \
-         + w[4] *x[4] +w[5] *x[5] +w[6] *x[6] +w[7] *x[7] \
-         + w[8] *x[8] +w[9] *x[9] +w[10]*x[10]+w[11]*x[11] \
-         + w[12]*x[12]+w[13]*x[13]+w[14]*x[14]+w[15]*x[15] ) >> 16
-
-#endif /* Fast machine */
-
-// Macro to add data to circular que 
-#define ADDQUE(xi,xq,in)\
-  xq[xi]=xq[xi+L]=(*in);\
-  xi=(xi-1)&(L-1);
-
+#if !defined(HAVE_MMX) // This machine is slow
+#define L8 
+#else
+#define L16
+#endif
+
+#include "af_resample.h"
+
+// Filtering types
+#define TYPE_LIN   0	// Linear interpolation
+#define TYPE_INT   1   	// 16 bit integer 
+#define TYPE_FLOAT 2	// 32 bit floating point
 
+// Accuracy for linear interpolation
+#define STEPACCURACY 32
 
 // local data
 typedef struct af_resample_s
 {
-  int16_t*  	w;	// Current filter weights
-  int16_t** 	xq; 	// Circular buffers
+  void*  	w;	// Current filter weights
+  void** 	xq; 	// Circular buffers
   uint32_t	xi; 	// Index for circular buffers
   uint32_t	wi;	// Index for w
-  uint32_t	i; 	// Number of new samples to put in x queue
+  uint32_t	i; 	// Number of new samples to put in x queue 
   uint32_t  	dn;     // Down sampling factor
   uint32_t	up;	// Up sampling factor 
+  uint64_t	step;	// Step size for linear interpolation
+  uint64_t	pt;	// Pointer remainder for linear interpolation
   int		sloppy;	// Enable sloppy resampling to reduce memory usage
-  int		fast;	// Enable linear interpolation instead of filtering
+  int		type;	// Filter type 
 } af_resample_t;
 
 // Euclids algorithm for calculating Greatest Common Divisor GCD(a,b)
@@ -82,96 +73,50 @@
   return b;
 }
 
-static int upsample(af_data_t* c,af_data_t* l, af_resample_t* s)
-{
-  uint32_t		ci    = l->nch; 	// Index for channels
-  uint32_t		len   = 0; 		// Number of input samples
-  uint32_t		nch   = l->nch;   	// Number of channels
-  uint32_t		inc   = s->up/s->dn; 
-  uint32_t		level = s->up%s->dn; 
-  uint32_t		up    = s->up;
-  uint32_t		dn    = s->dn;
-
-  register int16_t*	w     = s->w;
-  register uint32_t	wi    = 0;
-  register uint32_t	xi    = 0; 
-
-  // Index current channel
-  while(ci--){
-    // Temporary pointers
-    register int16_t*	x     = s->xq[ci];
-    register int16_t*	in    = ((int16_t*)c->audio)+ci;
-    register int16_t*	out   = ((int16_t*)l->audio)+ci;
-    int16_t* 		end   = in+c->len/2; // Block loop end
-    wi = s->wi; xi = s->xi;
-
-    while(in < end){
-      register uint32_t	i = inc;
-      if(wi<level) i++;
-
-      ADDQUE(xi,x,in);
-      in+=nch;
-      while(i--){
-	// Run the FIR filter
-	FIR((&x[xi]),(&w[wi*L]),out);
-	len++; out+=nch;
-	// Update wi to point at the correct polyphase component
-	wi=(wi+dn)%up;
-      }
-    }
-  }
-  // Save values that needs to be kept for next time
-  s->wi = wi;
-  s->xi = xi;
-  return len;
-}
-
-static int downsample(af_data_t* c,af_data_t* l, af_resample_t* s)
+// Fast linear interpolation resample with modest audio quality
+static int linint(af_data_t* c,af_data_t* l, af_resample_t* s)
 {
-  uint32_t		ci    = l->nch; 	// Index for channels
-  uint32_t		len   = 0; 		// Number of output samples
-  uint32_t		nch   = l->nch;   	// Number of channels
-  uint32_t		inc   = s->dn/s->up; 
-  uint32_t		level = s->dn%s->up; 
-  uint32_t		up    = s->up;
-  uint32_t		dn    = s->dn;
-
-  register int32_t	i     = 0;
-  register uint32_t	wi    = 0;
-  register uint32_t	xi    = 0;
+  uint32_t	len   = 0; 		// Number of input samples
+  uint32_t	nch   = l->nch;   	// Words pre transfer
+  uint64_t	step  = s->step; 
+  int16_t*	in16  = ((int16_t*)c->audio);
+  int16_t*	out16 = ((int16_t*)l->audio);
+  int32_t*	in32  = ((int32_t*)c->audio);
+  int32_t*	out32 = ((int32_t*)l->audio);
+  uint64_t 	end   = ((((uint64_t)c->len)/2LL)<<STEPACCURACY);
+  uint64_t	pt    = s->pt;
+  uint16_t 	tmp;
   
-  // Index current channel
-  while(ci--){
-    // Temporary pointers
-    register int16_t*	x     = s->xq[ci];
-    register int16_t*	in    = ((int16_t*)c->audio)+ci;
-    register int16_t*	out   = ((int16_t*)l->audio)+ci;
-    register int16_t* 	end   = in+c->len/2;    // Block loop end
-    i = s->i; wi = s->wi; xi = s->xi;
-
-    while(in < end){
-
-      ADDQUE(xi,x,in);
-      in+=nch;
-      if((--i)<=0){
-	// Run the FIR filter
-	FIR((&x[xi]),(&s->w[wi*L]),out);
-	len++;	out+=nch;
-
-	// Update wi to point at the correct polyphase component
-	wi=(wi+dn)%up;  
-
-	// Insert i number of new samples in queue
-	i = inc;
-	if(wi<level) i++;
-      }
+  switch (nch){
+  case 1:
+    while(pt < end){
+      out16[len++]=in16[pt>>STEPACCURACY];    	    
+      pt+=step;
+    }
+    s->pt=pt & ((1LL<<STEPACCURACY)-1);
+    break;		
+  case 2:
+    end/=2;
+    while(pt < end){
+      out32[len++]=in32[pt>>STEPACCURACY];    	    
+      pt+=step;
     }
+    len=(len<<1);
+    s->pt=pt & ((1LL<<STEPACCURACY)-1);
+    break;
+  default:	
+    end /=nch;
+    while(pt < end){
+      tmp=nch;
+      do {	 
+	tmp--;   
+	out16[len+tmp]=in16[tmp+(pt>>STEPACCURACY)*nch];    	    
+      } while (tmp);
+      len+=nch;
+      pt+=step;
+    }	
+    s->pt=pt & ((1LL<<STEPACCURACY)-1);
   }
-  // Save values that needs to be kept for next time
-  s->wi = wi;
-  s->xi = xi;
-  s->i = i;
-
   return len;
 }
 
@@ -184,13 +129,24 @@
     af_data_t* 	   n   = (af_data_t*)arg; // New configureation
     int            i,d = 0;
     int 	   rv  = AF_OK;
+    size_t 	   tsz = (s->type==TYPE_INT) ? sizeof(int16_t) : sizeof(float);
 
     // Make sure this filter isn't redundant 
     if(af->data->rate == n->rate)
       return AF_DETACH;
 
+    // If linear interpolation 
+    if(s->type == TYPE_LIN){
+      s->pt=0LL;
+      s->step=((uint64_t)n->rate<<STEPACCURACY)/(uint64_t)af->data->rate+1LL;
+      af_msg(AF_MSG_VERBOSE,"[resample] Linear interpolation step: 0x%016X.\n",
+	     s->step);
+      af->mul.n = af->data->rate;
+      af->mul.d = n->rate;
+    }
+
     // Create space for circular bufers (if nesessary)
-    if(af->data->nch != n->nch){
+    if((af->data->nch != n->nch) && (s->type != TYPE_LIN)){
       // First free the old ones
       if(s->xq){
 	for(i=1;i<af->data->nch;i++)
@@ -199,20 +155,30 @@
 	free(s->xq);
       }
       // ... then create new
-      s->xq = malloc(n->nch*sizeof(int16_t*));
+      s->xq = malloc(n->nch*sizeof(void*));
       for(i=0;i<n->nch;i++)
-	s->xq[i] = malloc(2*L*sizeof(int16_t));
+	s->xq[i] = malloc(2*L*tsz);
       s->xi = 0;
     }
 
     // Set parameters
     af->data->nch    = n->nch;
-    af->data->format = AF_FORMAT_NE | AF_FORMAT_SI;
-    af->data->bps    = 2;
+    if(s->type == TYPE_INT || s->type == TYPE_LIN){
+      af->data->format = AF_FORMAT_NE | AF_FORMAT_SI;
+      af->data->bps    = 2;
+    }
+    else{
+      af->data->format = AF_FORMAT_NE | AF_FORMAT_F;
+      af->data->bps    = 4;
+    }
     if(af->data->format != n->format || af->data->bps != n->bps)
       rv = AF_FALSE;
-    n->format = AF_FORMAT_NE | AF_FORMAT_SI;
-    n->bps = 2;
+    n->format = af->data->format;
+    n->bps = af->data->bps;
+
+    // If linear interpolation is used the setup is done.
+    if(s->type == TYPE_LIN)
+      return rv;
 
     // Calculate up and down sampling factors
     d=gcd(af->data->rate,n->rate);
@@ -244,7 +210,7 @@
       w = malloc(sizeof(float) * s->up *L);
       if(NULL != s->w)
 	free(s->w);
-      s->w = malloc(L*s->up*sizeof(int16_t));
+      s->w = malloc(L*s->up*tsz);
 
       // Design prototype filter type using Kaiser window with beta = 10
       if(NULL == w || NULL == s->w || 
@@ -256,13 +222,18 @@
       wt=w;
       for(j=0;j<L;j++){//Columns
 	for(i=0;i<s->up;i++){//Rows
-	  float t=(float)s->up*32767.0*(*wt);
-	  s->w[i*L+j] = (int16_t)((t>=0.0)?(t+0.5):(t-0.5));
+	  if(s->type == TYPE_INT){
+	    float t=(float)s->up*32767.0*(*wt);
+	    ((int16_t*)s->w)[i*L+j] = (int16_t)((t>=0.0)?(t+0.5):(t-0.5));
+	  }
+	  else
+	    ((float*)s->w)[i*L+j] = (float)s->up*(*wt);
 	  wt++;
 	}
       }
       free(w);
-      af_msg(AF_MSG_VERBOSE,"[resample] New filter designed up: %i down: %i\n", s->up, s->dn);
+      af_msg(AF_MSG_VERBOSE,"[resample] New filter designed up: %i "
+	     "down: %i\n", s->up, s->dn);
     }
 
     // Set multiplier and delay
@@ -274,20 +245,30 @@
   case AF_CONTROL_COMMAND_LINE:{
     af_resample_t* s   = (af_resample_t*)af->setup; 
     int rate=0;
-    sscanf((char*)arg,"%i:%i:%i",&rate,&(s->sloppy), &(s->fast));
-    return af->control(af,AF_CONTROL_RESAMPLE,&rate);
+    int lin=0;
+    sscanf((char*)arg,"%i:%i:%i", &rate, &(s->sloppy), &lin);
+    if(lin)
+      s->type = TYPE_LIN;
+    return af->control(af,AF_CONTROL_RESAMPLE_RATE | AF_CONTROL_SET, &rate);
   }
-  case AF_CONTROL_RESAMPLE: 
+  case AF_CONTROL_POST_CREATE:	
+    ((af_resample_t*)af->setup)->type = 
+      ((af_cfg_t*)arg)->force  == AF_INIT_SLOW ? TYPE_INT : TYPE_FLOAT;
+    return AF_OK;
+  case AF_CONTROL_RESAMPLE_RATE | AF_CONTROL_SET: 
     // Reinit must be called after this function has been called
     
     // Sanity check
     if(((int*)arg)[0] < 8000 || ((int*)arg)[0] > 192000){
-      af_msg(AF_MSG_ERROR,"[resample] The output sample frequency must be between 8kHz and 192kHz. Current value is %i \n",((int*)arg)[0]);
+      af_msg(AF_MSG_ERROR,"[resample] The output sample frequency " 
+	     "must be between 8kHz and 192kHz. Current value is %i \n",
+	     ((int*)arg)[0]);
       return AF_ERROR;
     }
 
     af->data->rate=((int*)arg)[0]; 
-    af_msg(AF_MSG_VERBOSE,"[resample] Changing sample rate to %iHz\n",af->data->rate);
+    af_msg(AF_MSG_VERBOSE,"[resample] Changing sample rate "  
+	   "to %iHz\n",af->data->rate);
     return AF_OK;
   }
   return AF_UNKNOWN;
@@ -312,14 +293,42 @@
     return NULL;
 
   // Run resampling
-  if(s->up>s->dn)
-    len = upsample(c,l,s);
-  else
-    len = downsample(c,l,s);
+  switch(s->type){
+  case(TYPE_INT):
+# define FORMAT_I 1
+    if(s->up>s->dn){
+#     define UP
+#     include "af_resample.h"
+#     undef UP 
+    }
+    else{
+#     define DN
+#     include "af_resample.h"
+#     undef DN
+    }
+    break;
+  case(TYPE_FLOAT):
+# undef FORMAT_I
+# define FORMAT_F 1
+    if(s->up>s->dn){
+#     define UP
+#     include "af_resample.h"
+#     undef UP 
+    }
+    else{
+#     define DN
+#     include "af_resample.h"
+#     undef DN
+    }
+    break;
+  case(TYPE_LIN):
+    len = linint(c, l, s);
+    break;
+  }
 
   // Set output data
   c->audio = l->audio;
-  c->len   = len*2;
+  c->len   = len*l->bps;
   c->rate  = l->rate;
   
   return c;

Index: af_volume.c
===================================================================
RCS file: /cvsroot/mplayer/main/libaf/af_volume.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- af_volume.c	14 Nov 2002 09:49:06 -0000	1.5
+++ af_volume.c	28 Dec 2002 13:59:53 -0000	1.6
@@ -1,19 +1,27 @@
+/*=============================================================================
+//	
+//  This software has been released under the terms of the GNU Public
+//  license. See http://www.gnu.org/copyleft/gpl.html for details.
+//
+//  Copyright 2002 Anders Johansson ajh at atri.curtin.edu.au
+//
+//=============================================================================
+*/
+
 /* This audio filter changes the volume of the sound, and can be used
-   when the mixer doesn't support the PCM channel. It can handel
+   when the mixer doesn't support the PCM channel. It can handle
    between 1 and 6 channels. The volume can be adjusted between -60dB
-   to +20dB and is set on a per channels basis. The volume can be
-   written ad read by AF_CONTROL_VOLUME_SET and AF_CONTROL_VOLUME_GET
-   respectivly.
+   to +20dB and is set on a per channels basis. The is accessed through
+   AF_CONTROL_VOLUME_LEVEL.
 
-   The plugin has support for softclipping, it is enabled by
+   The filter has support for soft-clipping, it is enabled by
    AF_CONTROL_VOLUME_SOFTCLIPP. It has also a probing feature which
    can be used to measure the power in the audio stream, both an
-   instantanious value and the maximum value can be probed. The
+   instantaneous value and the maximum value can be probed. The
    probing is enable by AF_CONTROL_VOLUME_PROBE_ON_OFF and is done on a
    per channel basis. The result from the probing is obtained using
    AF_CONTROL_VOLUME_PROBE_GET and AF_CONTROL_VOLUME_PROBE_GET_MAX. The
-   probed values are calculated in dB. The control of the volume can
-   be turned off by the AF_CONTROL_VOLUME_ON_OFF switch.
+   probed values are calculated in dB. 
 */
 
 #include <stdio.h>
@@ -22,66 +30,22 @@
 #include <unistd.h>
 #include <inttypes.h>
 #include <math.h>
+#include <limits.h>
 
 #include "af.h"
 
-// Some limits
-#define NCH	AF_NCH // Number of channels
-
-#define MIN_S16 -32650
-#define MAX_S16  32650
-
-#define MAX_VOL +40.0
-#define MIN_VOL	-200.0
-
 // Data for specific instances of this filter
 typedef struct af_volume_s
 {
-  float volume[NCH];	// Volume for each channel
-  float power[NCH];	// Instantaneous power in each channel
-  float maxpower[NCH];	// Maximum power in each channel
-  float alpha;		// Forgetting factor for power estimate
-  int softclip;		// Soft clippng on/off
-  int probe;		// Probing on/off
-  int onoff;		// Volume control on/off
+  int   enable[AF_NCH];		// Enable/disable / channel
+  float	pow[AF_NCH];		// Estimated power level [dB]
+  float	max[AF_NCH];		// Max Power level [dB]
+  float level[AF_NCH];		// Gain level for each channel
+  float time;			// Forgetting factor for power estimate
+  int soft;			// Enable/disable soft clipping
+  int fast;			// Use fix-point volume control
 }af_volume_t;
 
-/* Convert to gain value from dB. Returns AF_OK if of and AF_ERROR if
-   fail */
-inline int from_dB(float* in, float* out, float k) 
-{
-  int i = 0; 
-  // Sanity check
-  if(!in || !out) 
-    return AF_ERROR;
-
-  for(i=0;i<NCH;i++){
-    if(in[i]<MIN_VOL)
-      out[i]=0.0;
-    else
-      out[i]=pow(10.0,clamp(in[i],MIN_VOL,MAX_VOL)/k);
-  }
-  return AF_OK;
-}
-
-/* Convert from gain value to dB. Returns AF_OK if of and AF_ERROR if
-   fail */
-inline int to_dB(float* in, float* out, float k) 
-{
-  int i = 0; 
-  // Sanity check
-  if(!in || !out) 
-    return AF_ERROR;
-
-  for(i=0;i<NCH;i++){
-    if(in[i] == 0.0)
-      out[i]=MIN_VOL;
-    else
-      out[i]=k*log10(clamp(in[i],MIN_VOL,MAX_VOL));
-  }
-  return AF_OK;
-}
-
 // Initialization and runtime control
 static int control(struct af_instance_s* af, int cmd, void* arg)
 {
@@ -94,48 +58,57 @@
     
     af->data->rate   = ((af_data_t*)arg)->rate;
     af->data->nch    = ((af_data_t*)arg)->nch;
-    af->data->format = AF_FORMAT_SI | AF_FORMAT_LE;
-    af->data->bps    = 2;
     
-    // Time constant set to 0.1s
-    s->alpha = (1.0/0.2)/(2.0*M_PI*(float)((af_data_t*)arg)->rate); 
-
-    // Only AFMT_S16_LE is supported for now
-    if(af->data->format != ((af_data_t*)arg)->format || 
-       af->data->bps != ((af_data_t*)arg)->bps)
-      return AF_FALSE;
-    return AF_OK;
+    if(s->fast){
+      af->data->format = AF_FORMAT_SI | AF_FORMAT_NE;
+      af->data->bps    = 2;
+    }
+    else{
+      // Cutoff set to 10Hz for forgetting factor
+      float x = 2.0*M_PI*15.0/(float)af->data->rate;
+      float t = 2.0-cos(x);
+      s->time = 1.0 - (t - sqrt(t*t - 1));
+      af_msg(AF_MSG_DEBUG0,"[volume] Forgetting factor = %0.5f\n",s->time);
+      af->data->format = AF_FORMAT_F | AF_FORMAT_NE;
+      af->data->bps    = 4;
+    }
+    return af_test_output(af,(af_data_t*)arg);
   case AF_CONTROL_COMMAND_LINE:{
     float v=-10.0;
-    float vol[6];
-    int i;
-    sscanf((char*)arg,"%f:%i:%i:%i", &v,
-	   &(s->softclip), &(s->probe), &(s->onoff));
-    for(i=0;i<NCH;i++) vol[i]=v;
-    return from_dB(vol,s->volume,20.0);
-  }
-  case AF_CONTROL_VOLUME_SET:
-    return from_dB((float*)arg,s->volume,20.0);
-  case AF_CONTROL_VOLUME_GET:
-    return to_dB(s->volume,(float*)arg,20.0);
-  case AF_CONTROL_VOLUME_PROBE_GET:
-    return to_dB(s->power,(float*)arg,10.0);
-  case AF_CONTROL_VOLUME_PROBE_GET_MAX:
-    return to_dB(s->maxpower,(float*)arg,10.0);
-  case AF_CONTROL_VOLUME_SOFTCLIP:
-    s->softclip = (int)arg;
-    return AF_OK;
-  case AF_CONTROL_VOLUME_PROBE_ON_OFF:
-    s->probe = (int)arg;
-    return AF_OK;
-  case AF_CONTROL_VOLUME_ON_OFF:
-    s->onoff = (int)arg;
+    float vol[AF_NCH];
+    int   i;
+    sscanf((char*)arg,"%f:%i", &v, &s->soft);
+    for(i=0;i<AF_NCH;i++) vol[i]=v;
+    return control(af,AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_SET, vol);
+  }
+  case AF_CONTROL_POST_CREATE:	
+    s->fast = ((af_cfg_t*)arg)->force  == AF_INIT_SLOW ? 1 : 0;
     return AF_OK;
+  case AF_CONTROL_VOLUME_ON_OFF | AF_CONTROL_SET:
+    memcpy(s->enable,(int*)arg,AF_NCH*sizeof(int));
+    return AF_OK; 
+  case AF_CONTROL_VOLUME_ON_OFF | AF_CONTROL_GET:
+    memcpy((int*)arg,s->enable,AF_NCH*sizeof(int));
+    return AF_OK; 
+  case AF_CONTROL_VOLUME_SOFTCLIP | AF_CONTROL_SET:
+    s->soft = *(int*)arg;
+    return AF_OK; 
+  case AF_CONTROL_VOLUME_SOFTCLIP | AF_CONTROL_GET:
+    *(int*)arg = s->soft;
+    return AF_OK; 
+  case AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_SET:
+    return af_from_dB(AF_NCH,(float*)arg,s->level,20.0,-200.0,60.0);
+  case AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_GET:
+    return af_to_dB(AF_NCH,s->level,(float*)arg,20.0);
+  case AF_CONTROL_VOLUME_PROBE | AF_CONTROL_GET:
+    return af_to_dB(AF_NCH,s->pow,(float*)arg,10.0);
+  case AF_CONTROL_VOLUME_PROBE_MAX | AF_CONTROL_GET:
+    return af_to_dB(AF_NCH,s->max,(float*)arg,10.0);
   case AF_CONTROL_PRE_DESTROY:{
     float m = 0.0;
     int i;
-    for(i=0;i<NCH;i++)
-      m=max(m,s->maxpower[i]);
+    for(i=0;i<AF_NCH;i++)
+      m=max(m,s->max[i]);
     af_msg(AF_MSG_INFO,"The maximum volume was %0.2fdB \n",10*log10(m));
     return AF_OK;
   }
@@ -155,57 +128,66 @@
 // Filter data through filter
 static af_data_t* play(struct af_instance_s* af, af_data_t* data)
 {
-  af_data_t*     c = data;			// Current working data
-  af_volume_t*   s = (af_volume_t*)af->setup; 	// Setup for this instance
-  int16_t*       a = (int16_t*)c->audio;	// Audio data
-  int          len = c->len/2;			// Number of samples
-  int           ch = 0;				// Channel counter
-  register int nch = c->nch;			// Number of channels	
-  register int   i = 0;
-  
-  // Probe the data stream 
-  if(s->probe){
+  af_data_t*    c   = data;			// Current working data
+  af_volume_t*  s   = (af_volume_t*)af->setup; 	// Setup for this instance
+  int           ch  = 0;			// Channel counter
+  register int	nch = c->nch;			// Number of channels	
+  register int  i   = 0;
+
+  // Basic operation volume control only (used on slow machines)
+  if(af->data->format == (AF_FORMAT_SI | AF_FORMAT_NE)){
+    int16_t*    a   = (int16_t*)c->audio;	// Audio data
+    int         len = c->len/2;			// Number of samples
     for(ch = 0; ch < nch ; ch++){
-      float alpha  = s->alpha;
-      float beta   = 1 - alpha;
-      float pow    = s->power[ch];
-      float maxpow = s->maxpower[ch];
-      register float t = 0;
-      for(i=ch;i<len;i+=nch){
-	t = ((float)a[i])/32768.0;
-	t *= t;
-	// Check maximum power value
-	if(t>maxpow) 
-	  maxpow=t;
-	// Power estimate made using first order AR model
-	if(t>pow)
-	  pow=t;
-	else
-	  pow = beta*pow+alpha*t;
+      if(s->enable[ch]){
+	register int vol = (int)(255.0 * s->level[ch]); 
+	for(i=ch;i<len;i+=nch){
+	  register int x = (a[i] * vol) >> 8;
+	  a[i]=clamp(x,SHRT_MIN,SHRT_MAX);
+	}
       }
-      s->power[ch]    = pow;
-      s->maxpower[ch] = maxpow;
     }
   }
-
-  // Change the volume.
-  if(s->onoff){
-    register int sc  = s->softclip;
+  // Machine is fast and data is floating point
+  else if(af->data->format == (AF_FORMAT_F | AF_FORMAT_NE)){ 
+    float*   	a   	= (float*)c->audio;	// Audio data
+    int       	len 	= c->len/4;		// Number of samples
     for(ch = 0; ch < nch ; ch++){
-      register int vol = (int)(255.0 * s->volume[ch]); 
-      for(i=ch;i<len;i+=nch){
-	register int x;
-	x=(a[i] * vol) >> 8;
-	if(sc){
-	  int64_t t=x*x;
-	  t=(t*x) >> 30;
-	  x = (3*x - (int)t) >> 1;
+      // Volume control (fader)
+      if(s->enable[ch]){
+	float	t   = 1.0 - s->time;
+	for(i=ch;i<len;i+=nch){
+	  register float x 	= a[i];
+	  register float pow 	= x*x;	
+	  // Check maximum power value
+	  if(pow > s->max[ch])
+	    s->max[ch] = pow;
+	  // Set volume
+	  x *= s->level[ch];
+	  // Peak meter
+	  pow 	= x*x;
+	  if(pow > s->pow[ch])
+	    s->pow[ch] = pow;
+	  else
+	    s->pow[ch] = t*s->pow[ch] + pow*s->time; // LP filter
+	  /* Soft clipping, the sound of a dream, thanks to Jon Wattes
+	     post to Musicdsp.org */
+	  if(s->soft){
+	    if (x >=  M_PI/2)
+	      x = 1.0;
+	    else if(x <= -M_PI/2)
+	      x = -1.0;
+	    else
+	      x = sin(x);
+	  }
+	  // Hard clipping
+	  else
+	    x=clamp(x,-1.0,1.0);
+	  a[i] = x;
 	}
-	a[i]=clamp(x,MIN_S16,MAX_S16);
       }
     }
   }
-
   return c;
 }
 
@@ -222,13 +204,13 @@
   if(af->data == NULL || af->setup == NULL)
     return AF_ERROR;
   /* Enable volume control and set initial volume to 0.1 this is a
-     safety mesure to ensure that the user doesn't blow his
+     safety measure to ensure that the user doesn't blow his
      speakers. If the user isn't happy with this he can use the
-     commandline parameters to set the initial volume */
-  ((af_volume_t*)af->setup)->onoff = 1;
-  for(i=0;i<NCH;i++)
-    ((af_volume_t*)af->setup)->volume[i]=0.1;
-
+     command-line parameters to set the initial volume */
+  for(i=0;i<AF_NCH;i++){
+    ((af_volume_t*)af->setup)->enable[i] = 1;
+    ((af_volume_t*)af->setup)->level[i]  = 0.1;
+  }
   return AF_OK;
 }
 

Index: control.h
===================================================================
RCS file: /cvsroot/mplayer/main/libaf/control.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- control.h	3 Nov 2002 09:51:02 -0000	1.3
+++ control.h	28 Dec 2002 13:59:53 -0000	1.4
@@ -2,6 +2,57 @@
 #define __af_control_h
 
 /*********************************************
+// Control info struct. 
+//
+// This struct is the argument in a info call to a filter.
+*/
+
+// Argument types 
+#define AF_CONTROL_TYPE_BOOL	(0x0<<0)
+#define AF_CONTROL_TYPE_CHAR	(0x1<<0)
+#define AF_CONTROL_TYPE_INT	(0x2<<0)
+#define AF_CONTROL_TYPE_FLOAT	(0x3<<0)
+#define AF_CONTROL_TYPE_STRUCT	(0x4<<0)
+#define AF_CONTROL_TYPE_SPECIAL	(0x5<<0) // a pointer to a function for example
+#define AF_CONTROL_TYPE_MASK	(0x7<<0)
+// Argument geometry
+#define AF_CONTROL_GEOM_SCALAR	(0x0<<3)
+#define AF_CONTROL_GEOM_ARRAY	(0x1<<3)
+#define AF_CONTROL_GEOM_MATRIX	(0x2<<3)
+#define AF_CONTROL_GEOM_MASK	(0x3<<3)
+// Argument properties
+#define AF_CONTROL_PROP_READ	(0x0<<5) // The argument can be read
+#define AF_CONTROL_PROP_WRITE	(0x1<<5) // The argument can be written
+#define AF_CONTROL_PROP_SAVE	(0x2<<5) // Can be saved
+#define AF_CONTROL_PROP_RUNTIME	(0x4<<5) // Acessable during execution
+#define AF_CONTROL_PROP_CHANNEL (0x8<<5) // Argument is set per channel
+#define AF_CONTROL_PROP_MASK	(0xF<<5)
+
+typedef struct af_control_info_s{
+  int	 def;	// Control enumrification
+  char*	 name; 	// Name of argument
+  char*	 info;	// Description of what it does
+  int 	 flags;	// Flags as defined above	
+  float	 max;	// Max and min value 
+  float	 min;	// (only aplicable on float and int) 
+  int	 xdim;	// 1st dimension
+  int	 ydim;	// 2nd dimension (=0 for everything except matrix)
+  size_t sz;	// Size of argument in bytes
+  int	 ch;	// Channel number (for future use)
+  void*  arg;	// Data (for future use)
+}af_control_info_t;
+
+
+/*********************************************
+// Extended control used with arguments that operates on only one
+// channel at the time
+*/
+typedef struct af_control_ext_s{
+  void* arg;	// Argument
+  int	ch;	// Chanel number
+}af_control_ext_t;
+
+/*********************************************
 // Control parameters 
 */
 
@@ -11,9 +62,9 @@
    filter specific calls - applies only to some filters
 */
 
-#define AF_CONTROL_MANDATORY_BASE	0
-#define AF_CONTROL_OPTIONAL_BASE	100
-#define AF_CONTROL_FILTER_SPECIFIC_BASE	200
+#define AF_CONTROL_MANDATORY		0x10000000
+#define AF_CONTROL_OPTIONAL		0x20000000
+#define AF_CONTROL_FILTER_SPECIFIC	0x40000000
 
 // MANDATORY CALLS
 
@@ -23,66 +74,136 @@
    should be returned. If the incoming and outgoing data streams are
    identical the filter can return AF_DETACH. This will remove the
    filter. */
-#define AF_CONTROL_REINIT  		01 + AF_CONTROL_MANDATORY_BASE
+#define AF_CONTROL_REINIT  		0x00000100 | AF_CONTROL_MANDATORY
 
 // OPTIONAL CALLS
 
 /* Called just after creation with the af_cfg for the stream in which
    the filter resides as input parameter this call can be used by the
    filter to initialize itself */
-#define AF_CONTROL_POST_CREATE 		1 + AF_CONTROL_OPTIONAL_BASE
+#define AF_CONTROL_POST_CREATE 		0x00000100 | AF_CONTROL_OPTIONAL
 
 // Called just before destruction of a filter
-#define AF_CONTROL_PRE_DESTROY 		2 + AF_CONTROL_OPTIONAL_BASE
+#define AF_CONTROL_PRE_DESTROY 		0x00000200 | AF_CONTROL_OPTIONAL
 
 /* Commandline parameters. If there were any commandline parameters
    for this specific filter, they will be given as a char* in the
    argument */
-#define AF_CONTROL_COMMAND_LINE		3 + AF_CONTROL_OPTIONAL_BASE
+#define AF_CONTROL_COMMAND_LINE		0x00000300 | AF_CONTROL_OPTIONAL
 
 
 // FILTER SPECIFIC CALLS
 
+// Basic operations: These can be ored with any of the below calls
+// Set argument 
+#define AF_CONTROL_SET			0x00000000
+// Get argument
+#define AF_CONTROL_GET			0x00000001
+// Get info about the control, i.e fill in everything except argument
+#define AF_CONTROL_INFO			0x00000002  
+
+// Resample
+
 // Set output rate in resample
-#define AF_CONTROL_RESAMPLE		1 + AF_CONTROL_FILTER_SPECIFIC_BASE
+#define AF_CONTROL_RESAMPLE_RATE	0x00000100 | AF_CONTROL_FILTER_SPECIFIC
+
+// Enable sloppy resampling
+#define AF_CONTROL_RESAMPLE_SLOPPY	0x00000200 | AF_CONTROL_FILTER_SPECIFIC
+
+// Set resampling accuracy
+#define AF_CONTROL_RESAMPLE_ACCURACY	0x00000300 | AF_CONTROL_FILTER_SPECIFIC
 
-// Set output format in format
-#define AF_CONTROL_FORMAT		2 + AF_CONTROL_FILTER_SPECIFIC_BASE
+// Format 
+
+// Set output format bits per sample
+#define AF_CONTROL_FORMAT_BPS		0x00000400 | AF_CONTROL_FILTER_SPECIFIC
+
+// Set output format sample format
+#define AF_CONTROL_FORMAT_FMT		0x00000500 | AF_CONTROL_FILTER_SPECIFIC
+
+// Channels
 
 // Set number of output channels in channels
-#define AF_CONTROL_CHANNELS		3 + AF_CONTROL_FILTER_SPECIFIC_BASE
+#define AF_CONTROL_CHANNELS		0x00000600 | AF_CONTROL_FILTER_SPECIFIC
+
+// Set number of channel routes
+#define AF_CONTROL_CHANNELS_ROUTES	0x00000700 | AF_CONTROL_FILTER_SPECIFIC
 
-// Set delay length in delay
-#define AF_CONTROL_DELAY_SET_LEN	4 + AF_CONTROL_FILTER_SPECIFIC_BASE
+// Set channel routing pair, arg is int[2] and ch is used
+#define AF_CONTROL_CHANNELS_ROUTING	0x00000800 | AF_CONTROL_FILTER_SPECIFIC
 
+// Set nuber of channel routing pairs, arg is int*
+#define AF_CONTROL_CHANNELS_NR		0x00000900 | AF_CONTROL_FILTER_SPECIFIC
+
+// Set make af_channels into a router
+#define AF_CONTROL_CHANNELS_ROUTER	0x00000A00 | AF_CONTROL_FILTER_SPECIFIC
+	
 // Volume 
 
+// Turn volume control on and off, arg is int*
+#define AF_CONTROL_VOLUME_ON_OFF	0x00000B00 | AF_CONTROL_FILTER_SPECIFIC
+
+// Turn soft clipping of the volume on and off, arg is binary
+#define AF_CONTROL_VOLUME_SOFTCLIP	0x00000C00 | AF_CONTROL_FILTER_SPECIFIC
+
 // Set volume level, arg is a float* with the volume for all the channels
-#define AF_CONTROL_VOLUME_SET		5 + AF_CONTROL_FILTER_SPECIFIC_BASE
+#define AF_CONTROL_VOLUME_LEVEL		0x00000D00 | AF_CONTROL_FILTER_SPECIFIC
 
-/* Get volume level for all channels, arg is a float* that will
-   contain the volume for all the channels */
-#define AF_CONTROL_VOLUME_GET		6 + AF_CONTROL_FILTER_SPECIFIC_BASE
+// Probed power level for all channels, arg is a float* 
+#define AF_CONTROL_VOLUME_PROBE		0x00000E00 | AF_CONTROL_FILTER_SPECIFIC
 
-// Turn volume control on and off, arg is binary
-#define AF_CONTROL_VOLUME_ON_OFF	7 + AF_CONTROL_FILTER_SPECIFIC_BASE
+// Maximum probed power level for all channels, arg is a float* 
+#define AF_CONTROL_VOLUME_PROBE_MAX	0x00000F00 | AF_CONTROL_FILTER_SPECIFIC
 
-// Turn soft clipping of the volume on and off, arg is binary
-#define AF_CONTROL_VOLUME_SOFTCLIP	8 + AF_CONTROL_FILTER_SPECIFIC_BASE
+// Compressor/expander
+
+// Turn compressor/expander on and off
+#define AF_CONTROL_COMP_ON_OFF	 	0x00001000 | AF_CONTROL_FILTER_SPECIFIC
+
+// Compression/expansion threshold [dB]
+#define AF_CONTROL_COMP_THRESH	 	0x00001100 | AF_CONTROL_FILTER_SPECIFIC
+
+// Compression/expansion attack time [ms]
+#define AF_CONTROL_COMP_ATTACK	 	0x00001200 | AF_CONTROL_FILTER_SPECIFIC
+
+// Compression/expansion release time [ms]
+#define AF_CONTROL_COMP_RELEASE 	0x00001300 | AF_CONTROL_FILTER_SPECIFIC
+
+// Compression/expansion gain level [dB]
+#define AF_CONTROL_COMP_RATIO	 	0x00001400 | AF_CONTROL_FILTER_SPECIFIC
+
+// Noise gate
+
+// Turn noise gate on an off
+#define AF_CONTROL_GATE_ON_OFF	 	0x00001500 | AF_CONTROL_FILTER_SPECIFIC
+
+// Noise gate threshold [dB] 
+#define AF_CONTROL_GATE_THRESH	 	0x00001600 | AF_CONTROL_FILTER_SPECIFIC
+
+// Noise gate attack time [ms]
+#define AF_CONTROL_GATE_ATTACK	 	0x00001700 | AF_CONTROL_FILTER_SPECIFIC
+
+// Noise gate release time [ms] 
+#define AF_CONTROL_GATE_RELEASE 	0x00001800 | AF_CONTROL_FILTER_SPECIFIC
+
+// Noise gate release range level [dB]
+#define AF_CONTROL_GATE_RANGE	 	0x00001900 | AF_CONTROL_FILTER_SPECIFIC
+
+// Pan
+
+// Pan levels, arg is a control_ext with a float* 
+#define AF_CONTROL_PAN_LEVEL	 	0x00001A00 | AF_CONTROL_FILTER_SPECIFIC
 
-// Get the probed power level for all channels, arg is a float* 
-#define AF_CONTROL_VOLUME_PROBE_GET	9 + AF_CONTROL_FILTER_SPECIFIC_BASE
+// Number of outputs from pan, arg is int*
+#define AF_CONTROL_PAN_NOUT	 	0x00001B00 | AF_CONTROL_FILTER_SPECIFIC
+ 
 
-// Get the maximum probed power level for all channels, arg is a float* 
-#define AF_CONTROL_VOLUME_PROBE_GET_MAX	10 + AF_CONTROL_FILTER_SPECIFIC_BASE
+// Set equalizer gain, arg is a control_ext with a float* 
+#define AF_CONTROL_EQUALIZER_GAIN 	0x00001C00 | AF_CONTROL_FILTER_SPECIFIC
 
-// Turn probing on and off, arg is binary
-#define AF_CONTROL_VOLUME_PROBE_ON_OFF 	11 + AF_CONTROL_FILTER_SPECIFIC_BASE
 
-// Set equalizer gain, arg is an equalizer_t* 
-#define AF_CONTROL_EQUALIZER_SET_GAIN 	12 + AF_CONTROL_FILTER_SPECIFIC_BASE
+// Set delay length in seconds
+#define AF_CONTROL_DELAY_LEN		0x00001D00 | AF_CONTROL_FILTER_SPECIFIC
 
-// Get equalizer gain, arg is an equalizer_t* 
-#define AF_CONTROL_EQUALIZER_GET_GAIN 	13 + AF_CONTROL_FILTER_SPECIFIC_BASE
 
 #endif /*__af_control_h */




More information about the MPlayer-cvslog mailing list