OK.. having found a load of mp3's that sound bad when I conveted the sample 
rate from 44100 -> 16000 (the artifacts were like scratches and clicks... not 
nice) I' took a look at the way lame is downsampling.

In fill_buffer_resample() it's basically interpolating using either a linear 
or cubic polynomial, this is fine for going from a low frequency to a high 
frequency. Of course... I could b completely mistaken - feel free to call me 
an idiot if that's not what's happening.  Anyway - the problem with this is 
that the algorithm is reflecting high frequencies into the audible spectrum, 
if you downsample using interpolation then you need to do the lowpass filter 
*before* you resample, since you can't remove the reflected frequencies once 
they've been bounced into the Low frequency regime.

OK.. I'm too lazy to do this... so here';s my quick hack which sounds a lot 
better - but will probably have teh DSP people up in arms at how stupid it is.

Fr upsampling I still use the interpolation routing, but for downsampling I 
use a binning routine - add this to lame.c

/* gfp->resample_ratio >1 implies downsampling..... */
/* this rather ugly binning based convertor is a hack by scott manley */
/* It completley ignores signal processing thory but sound better */
/* for downsampling */
int fill_buffer_downsample(lame_global_flags *gfp,short int *outbuf,int 
desired_len, short int *inbuf,int len,int *num_used,int ch) {
  static float t_step,part_sam[2],s_time[2];
  static int init[2]={0,0};
  int i,j;
  if (gfp->frameNum==0 && !init[ch]) {
    init[ch]=1;
    s_time[ch]=0;
    part_sam[ch]=0;
    /* this may get initialised twice but they should be the same */
    t_step=1.0/gfp->resample_ratio;
    fprintf(stderr,"Using scott's downsampling hack\n");
  }
  j=0;
  i=0;
  while((j<desired_len)&&(i<len)){
    s_time[ch]+=t_step;
    if(s_time[ch]<1){
      part_sam[ch]+=inbuf[i]*t_step;
    } else {
      s_time[ch]-=1.0;
      part_sam[ch]+=inbuf[i]*(t_step-s_time[ch]);
      outbuf[j]=part_sam[ch];
      part_sam[ch]=inbuf[i]*s_time[ch];
      j++;
    }
    i++;
  }
  *num_used=i;
  return j;
}


then rename fill_buffer_resample() to fill_buffer_upsample() 

Finally modify lame_encode_buffer() to differentiate between the up and 
downsampling..

   /* copy in new samples */
    for (ch=0; ch<gfp->stereo; ch++) {
      if (gfp->resample_ratio<1)  {
        n_out=fill_buffer_upsample(gfp,&mfbuf[ch][mf_size],gfp->framesize,
                                          in_buffer[ch],nsamples,&n_in,ch);
      } else if (gfp->resample_ratio>1)  {
        n_out=fill_buffer_downsample(gfp,&mfbuf[ch][mf_size],gfp->framesize,
                                   in_buffer[ch],nsamples,&n_in,ch);
      } else {
        n_out=fill_buffer(gfp,&mfbuf[ch][mf_size],gfp->framesize,in_buffer[ch],nsample
s);
        n_in = n_out;
      }
      in_buffer[ch] += n_in;
    }




I have a couple of good examples ... but the best example is a remix of a 
track by Aqua.... not something I want to be heard in public ;-)



Scott Manley (aka Szyzyg)                           /------ _@/ Mail -----\
 ___         _   _     __  __           _           |  Armagh Observatory |
/ __| __ ___| |_| |_  |  \/  |__ _ _ _ | |___ _  _  |  Armagh             |
\__ \/ _/ _ \  _|  _| | |\/| / _` | ' \| / -_) || | |  Northern Ireland   |
|___/\__\___/\__|\__| |_|  |_\__,_|_||_|_\___|\_, | |  BT61 9DG.          |
http://star.arm.ac.uk/~spm/welcome.html       |__/  \=====================/


--
MP3 ENCODER mailing list ( http://geek.rcc.se/mp3encoder/ )

Reply via email to