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/ )