[paranoia-dev] Pop-reduction code

Jason cdp at lunkwill.org
Thu Jun 28 23:29:56 PDT 2001



I mentioned this on the paranoia user list - I'm working on code
to filter out popping noises I've been getting which are usually 
just one or two errant samples long.  Here's what I've thrown together
as a first pass.  Very ugly, reads in a .wav from stdin and writes
it to stdout.  Reduces the pops somewhat, but it still misses the
quieter ones (or perhaps doesn't clean them out enough).  You 
probably don't care about this code.

An example sample with popping noises can be had at:
http://www.technoloqy.com/pop.wav

                                -J

/* Try to find and remove spikes in .wav files
   public domain
   Jason Holt 29 Jun 2001
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

// Only actually reads a few seconds worth of sound
#define READBUFLEN 2000000

// Too many "spikes" in a row are probably not really spikes
#define FAKEOUT_THRESH 6

// How much higher than the average inter-sample delta is a spike
#define SPIKE_FACTOR 6
// Plus some wiggle room
#define SPIKE_BIAS 50

main(){
  int i;
  int *avgdelta, *fakeout, *pops;
  int fakeoutl=0, fakeoutr=0, popsl=0, popsr=0;
  int avgdeltal = 0, avgdeltar = 0;
  char header[80];
  short int readbuf[READBUFLEN + 50];
  short int readbufcopy[READBUFLEN + 50];
  size_t readlen;

  // copy header
  fread(header, 44, 1, stdin);
  fwrite(header, 44, 1, stdout);

  readlen = fread(readbuf, sizeof(short int), READBUFLEN, stdin);
  memcpy(readbufcopy, readbuf, readlen * sizeof(short int));

  if(readlen < 14) { 
        fwrite(readbuf, sizeof(short int), readlen, stdout);
        return 1;
  }

  avgdeltal = (abs(readbuf[0] - readbuf[2]) +
                           abs(readbuf[2] - readbuf[4]) +
                           abs(readbuf[4] - readbuf[6]) +
                           abs(readbuf[6] - readbuf[8]) +
                           abs(readbuf[8] - readbuf[10])) / 5;
  
  avgdeltar = (abs(readbuf[1] - readbuf[3]) +
                           abs(readbuf[3] - readbuf[5]) +
                           abs(readbuf[5] - readbuf[7]) +
                           abs(readbuf[7] - readbuf[9]) +
                           abs(readbuf[9] - readbuf[11])) / 5;

  if(avgdeltal < 100) avgdeltal=100;
  if(avgdeltar < 100) avgdeltar=100;
  
  fprintf(stderr, "Read %d samples.\n", readlen);
  fprintf(stderr, "Left average: %d.  Right: %d\n", avgdeltal,
avgdeltar);

  for(i=12; i<readlen; i++) {
        pops = (i % 2) ? &popsr : &popsl;
        fakeout = (i % 2) ? &fakeoutr : &fakeoutl;
        avgdelta = (i % 2) ? &avgdeltar : &avgdeltal;
        
        if(!*fakeout && 
           (abs(readbuf[i] - readbuf[i-2]) > abs(*avgdelta * SPIKE_FACTOR +
SPIKE_BIAS))) {
          fprintf(stderr, "Pop removed at sample %d (%d > %d).\n", i,
readbuf[i]-readbuf[i-2], *avgdelta * 10 +100);

          // Should really interpolate, but what if the next sample is
          // a spike too?
          readbuf[i] = readbuf[i-2];
          (*pops)++;

          if(*pops == FAKEOUT_THRESH) {
                int j;

                for(j=0; j<FAKEOUT_THRESH; j++) {
                  readbuf[i-(j*2)] = readbufcopy[i-(j*2)];
                }

                fprintf(stderr, "Fakeout! Rewinding from %d to %d.\n", i,
i-FAKEOUT_THRESH*2-1);

                *fakeout = FAKEOUT_THRESH;
                i -= FAKEOUT_THRESH*2 - 1;
                if(i<12){ i += FAKEOUT_THRESH*2 -1; *fakeout = 0; }
          }
        } else {
          if(*fakeout) (*fakeout)--;
          *pops = 0;
          *avgdelta -= abs(readbuf[i-12] - readbuf[i-10]) / 5;
          *avgdelta += abs(readbuf[i] - readbuf[i-2]) / 5;
        }
  }
  fwrite(readbuf, sizeof(short int), readlen, stdout);
}

--- >8 ----
List archives:  http://www.xiph.org/archives/
Paranoia homepage: http://www.xiph.org/paranoia/
To unsubscribe from this list, send mail to 'paranoia-dev-request at xiph.org'
containing only the word 'unsubscribe' in the body.  No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.



More information about the Paranoia-dev mailing list