[MEncoder-users] Re: Negatively delay audio?

James Lee jlee23 at umbc.edu
Fri Mar 4 09:10:21 CET 2005


Well after learning that there was NO way to get negative delays, I hacked up
the delay af into a new af called advance.  It works for my needs, but it
doesn't allow separate values for each channel like the delay af (but I think a
good lot of the code for seperate channels is there for some other more
experienced dev if they want to fix it) and for some reason it only works with
"-mc 0".  It's a good start I think.

af_advance.c:

/* This audio filter advances the output signal for the different
   channels and can be used for simple position panning. Extension for
   this filter would be a reverb.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>

#include "af.h"

// Data for specific instances of this filter
typedef struct af_advance_s
{
  int   sa[AF_NCH];     // Advance [samples]
  int   d[AF_NCH];      // Amount disposed
  float a[AF_NCH];      // Advance [ms]
}af_advance_t;

// Initialization and runtime control
static int control(struct af_instance_s* af, int cmd, void* arg)
{
  af_advance_t* s = af->setup;
  switch(cmd){
  case AF_CONTROL_REINIT:{
    af->data->rate   = ((af_data_t*)arg)->rate;
    af->data->nch    = ((af_data_t*)arg)->nch;
    af->data->format = ((af_data_t*)arg)->format;
    af->data->bps    = ((af_data_t*)arg)->bps;

    return control(af,AF_CONTROL_DELAY_LEN | AF_CONTROL_SET,s->a);
  }
  case AF_CONTROL_COMMAND_LINE:{
    int i = 0;
    char* cl = arg;
    float a;
    sscanf(cl,"%f",&a);
    while(i < AF_NCH){
      s->d[i] = 0;
      s->a[i] = a;
      i++;
    }
    return AF_OK;
  }
  case AF_CONTROL_DELAY_LEN | AF_CONTROL_SET:{
    int i;
    if(AF_OK != af_from_ms(AF_NCH, arg, s->sa, af->data->rate, 0.0, 1000.0))
      return AF_ERROR;
    for(i=0;i<AF_NCH;i++){
      af_msg(AF_MSG_DEBUG0,"[advance] Channel %i advanced by %0.3fms\n",
             i,clamp(s->a[i],0.0,1000.0));
      af_msg(AF_MSG_DEBUG1,"[advance] Channel %i advanced by %i samples\n",
             i,s->sa[i]);
    }
    return AF_OK;
  }
  case AF_CONTROL_DELAY_LEN | AF_CONTROL_GET:{
    return af_to_ms(AF_NCH, s->sa, arg, af->data->rate);
  }
  }
  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_advance_t* s   = af->setup; // Setup for this instance
  int           nch = c->nch;    // Number of channels
  int           len = c->len/c->bps; // Number of sample in data chunk
  int           ch,i,iorig;
  int           size = 0;
  for(ch=0;ch<nch;ch++){
    switch(c->bps){
    case 1:{
      int8_t* a = c->audio;
      int sa = s->sa[ch];
      for (i=ch;i<len&&s->d[ch]<sa;i+=nch,s->d[ch]++);
      for(iorig=ch;i<len;iorig+=nch,i+=nch){
        a[iorig] = a[i];
        size++;
      }
      break;
    }
    case 2:{
      int16_t* a = c->audio;
      int sa = s->sa[ch];
      for (i=ch;i<len&&s->d[ch]<sa;i+=nch,s->d[ch]++);
      for(iorig=ch;i<len;iorig+=nch,i+=nch){
        a[iorig] = a[i];
        size++;
      }
      break;
    }
    case 4:{
      int32_t* a = c->audio;
      int sa = s->sa[ch];
      for (i=ch;i<len&&s->d[ch]<sa;i+=nch,s->d[ch]++);
      for(iorig=ch;i<len;iorig+=nch,i+=nch){
        a[iorig] = a[i];
        size++;
      }
      break;
    }
    }
  }
  c->len = size*c->bps;
  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_advance_t));
  if(af->data == NULL || af->setup == NULL)
    return AF_ERROR;
  return AF_OK;
}

// Description of this filter
af_info_t af_info_advance = {
    "Advance audio filter",
    "advance",
    "Anders",
    "",
    AF_FLAGS_REENTRANT,
    open
};






More information about the MEncoder-users mailing list