/** * Mix some frames from the given secondary buffer "dsb" into the device * primary buffer. * * dsb = the secondary buffer * playpos = the current play position in the device buffer (primary buffer) * writepos = the current safe-to-write position in the device buffer * mixlen = the maximum number of bytes in the primary buffer to mix, from the * current writepos. * * Returns: the number of bytes beyond the writepos that were mixed. */ static DWORD DSOUND_MixOne(IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD mixlen) { DWORD primary_done = 0; TRACE("(%p,%d,%d)\n",dsb,writepos,mixlen); TRACE("writepos=%d, mixlen=%d\n", writepos, mixlen); TRACE("looping=%d, leadin=%d\n", dsb->playflags, dsb->leadin); /* If leading in, only mix about 20 ms, and 'skip' mixing the rest, for more fluid pointer advancement */ /* FIXME: Is this needed? */ if (dsb->leadin && dsb->state == STATE_STARTING) { if (mixlen > 2 * dsb->device->fraglen) { primary_done = mixlen - 2 * dsb->device->fraglen; mixlen = 2 * dsb->device->fraglen; writepos += primary_done; dsb->sec_mixpos += (primary_done / dsb->device->pwfx->nBlockAlign) * dsb->pwfx->nBlockAlign * dsb->freqAdjust; } } dsb->leadin = FALSE; TRACE("mixlen (primary) = %i\n", mixlen); /* First try to mix to the end of the buffer if possible * Theoretically it would allow for better optimization */ primary_done += DSOUND_MixInBuffer(dsb, writepos, mixlen); TRACE("total mixed data=%d\n", primary_done); /* Report back the total prebuffered amount for this buffer */ return primary_done; }
/** * Mix some frames from the given secondary buffer "dsb" into the device * primary buffer. * * dsb = the secondary buffer * playpos = the current play position in the device buffer (primary buffer) * writepos = the current safe-to-write position in the device buffer * mixlen = the maximum number of bytes in the primary buffer to mix, from the * current writepos. * * Returns: the number of bytes beyond the writepos that were mixed. */ static DWORD DSOUND_MixOne(IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD mixlen) { /* The buffer's primary_mixpos may be before or after the device * buffer's mixpos, but both must be ahead of writepos. */ DWORD primary_done; TRACE("(%p,%d,%d)\n",dsb,writepos,mixlen); TRACE("writepos=%d, primary_mixpos=%d, mixlen=%d\n", writepos, dsb->primary_mixpos, mixlen); TRACE("looping=%d, leadin=%d\n", dsb->playflags, dsb->leadin); /* If leading in, only mix about 20 ms, and 'skip' mixing the rest, for more fluid pointer advancement */ if (dsb->leadin && dsb->state == STATE_STARTING) { if (mixlen > 2 * dsb->device->fraglen) { dsb->primary_mixpos += mixlen - 2 * dsb->device->fraglen; dsb->primary_mixpos %= dsb->device->buflen; } } dsb->leadin = FALSE; /* calculate how much pre-buffering has already been done for this buffer */ primary_done = DSOUND_BufPtrDiff(dsb->device->buflen, dsb->primary_mixpos, writepos); /* sanity */ if(mixlen < primary_done) { /* Should *NEVER* happen */ ERR("Fatal error. Under/Overflow? primary_done=%d, mixpos=%d/%d, primary_mixpos=%d, writepos=%d, mixlen=%d\n", primary_done,dsb->sec_mixpos, dsb->buflen, dsb->primary_mixpos, writepos, mixlen); dsb->primary_mixpos = writepos + mixlen; dsb->primary_mixpos %= dsb->device->buflen; return mixlen; } /* take into account already mixed data */ mixlen -= primary_done; TRACE("primary_done=%d, mixlen (primary) = %i\n", primary_done, mixlen); if (!mixlen) return primary_done; /* First try to mix to the end of the buffer if possible * Theoretically it would allow for better optimization */ DSOUND_MixInBuffer(dsb, dsb->primary_mixpos, mixlen); /* re-calculate the primary done */ primary_done = DSOUND_BufPtrDiff(dsb->device->buflen, dsb->primary_mixpos, writepos); TRACE("new primary_mixpos=%d, total mixed data=%d\n", dsb->primary_mixpos, primary_done); /* Report back the total prebuffered amount for this buffer */ return primary_done; }