Back to home page

DOS ain't dead

Forum index page

Log in | Register

Back to the forum
Board view  Mix view

SBEMU dirty hotfix for playback speed on SB Audigy (Live) (Announce)

posted by Japheth Homepage, Germany (South), 25.01.2025, 02:00

> 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!

 

Complete thread:

Back to the forum
Board view  Mix view
22287 Postings in 2062 Threads, 399 registered users, 187 users online (0 registered, 187 guests)
DOS ain't dead | Admin contact
RSS Feed
powered by my little forum