> I suspect the code in au_base.c function mixer_speed_lq() that has
> something to do with interpolation of emulated fs to real sound device fs.
Correct. AFAIR it's the 2. of 3 conversions. The HW sound device is feeded with 16-bit, stereo, 22050 or 44100 Hz:
1. convert bitness (8 to 16-bit)
2. convert frequency
3. convert channel (mono to stereo)
In VSBHDA, it's in sndisr.c, func cv_rate():
static unsigned int cv_rate( PCM_CV_TYPE_S *pcmsrc, unsigned int samplenum, unsigned int channels, unsigned int srcrate, unsigned int dstrate)
{
/* todo: what algorithm for instep is best? */
//const unsigned int instep = ((srcrate / dstrate) << 12) | (((4096 * (srcrate % dstrate) - 1) / (dstrate - 1)) & 0xFFF);
const unsigned int instep = ((srcrate / dstrate) << 12) | (((4096 * (srcrate % dstrate) + dstrate - 1 ) / dstrate) & 0xFFF);
const unsigned int inend = (samplenum / channels) << 12;
PCM_CV_TYPE_S *pcmdst;
unsigned long ipi;
unsigned int inpos = 0;//(srcrate < dstrate) ? instep/2 : 0;
int total;
#if MALLOCSTATIC
static int maxsample = 0;
static PCM_CV_TYPE_S* buff = NULL;
#else
PCM_CV_TYPE_S* buff;
#endif
if(!samplenum)
return 0;
#if MALLOCSTATIC
if ( samplenum > maxsample ) {
if ( buff )
free( buff );
buff = (PCM_CV_TYPE_S*)malloc(samplenum * sizeof(PCM_CV_TYPE_S));
maxsample = samplenum;
}
#else
buff = (PCM_CV_TYPE_S*)malloc(samplenum * sizeof(PCM_CV_TYPE_S));
#endif
memcpy( buff, pcmsrc, samplenum * sizeof(PCM_CV_TYPE_S) );
pcmdst = pcmsrc;
total = samplenum / channels;
do{
int m1,m2;
unsigned int ipi,ch;
PCM_CV_TYPE_S *intmp1,*intmp2;
ipi = inpos >> 12;
m2 = inpos & 0xFFF;
m1 = 4096 - m2;
ch = channels;
ipi *= ch;
intmp1 = buff + ipi;
intmp2 = ipi < total - ch ? intmp1 + ch : intmp1;
do{
*pcmdst++= ((*intmp1++) * m1 + (*intmp2++) * m2) / 4096;// >> 12; //don't use shift, signed right shift impl defined, maybe logical shift
}while (--ch);
inpos += instep;
}while( inpos < inend );
//dbgprintf(("cv_rate(src/dst rates=%u/%u chn=%u smpl=%u step=%x end=%x)=%u\n", srcrate, dstrate, channels, samplenum, instep, inend, pcmdst - pcmsrc ));
#if !MALLOCSTATIC
free(buff);
#endif
return pcmdst - pcmsrc;
}
It has been optimized to reduce malloc/free calls. And I guess interpolation between the last sample and the first one of the next block is missing. --- MS-DOS forever! |