/** * Mix at most the given amount of data into the allocated temporary buffer * of the given secondary buffer, starting from the dsb's first currently * unsampled frame (writepos), translating frequency (pitch), stereo/mono * and bits-per-sample so that it is ideal for the primary buffer. * Doesn't perform any mixing - this is a straight copy/convert operation. * * dsb = the secondary buffer * writepos = Starting position of changed buffer * len = number of bytes to resample from writepos * * NOTE: writepos + len <= buflen. When called by mixer, MixOne makes sure of this. */ static void DSOUND_MixToTemporary(IDirectSoundBufferImpl *dsb, DWORD frames) { UINT size_bytes = frames * sizeof(float) * dsb->device->pwfx->nChannels; if (dsb->device->tmp_buffer_len < size_bytes || !dsb->device->tmp_buffer) { dsb->device->tmp_buffer_len = size_bytes; if (dsb->device->tmp_buffer) dsb->device->tmp_buffer = HeapReAlloc(GetProcessHeap(), 0, dsb->device->tmp_buffer, size_bytes); else dsb->device->tmp_buffer = HeapAlloc(GetProcessHeap(), 0, size_bytes); } cp_fields(dsb, frames, &dsb->freqAcc); }
/** * Mix at most the given amount of data into the allocated temporary buffer * of the given secondary buffer, starting from the dsb's first currently * unsampled frame (writepos), translating frequency (pitch), stereo/mono * and bits-per-sample so that it is ideal for the primary buffer. * Doesn't perform any mixing - this is a straight copy/convert operation. * * dsb = the secondary buffer * writepos = Starting position of changed buffer * len = number of bytes to resample from writepos * * NOTE: writepos + len <= buflen. When called by mixer, MixOne makes sure of this. */ static void DSOUND_MixToTemporary(IDirectSoundBufferImpl *dsb, DWORD tmp_len) { INT oAdvance = dsb->device->pwfx->nBlockAlign; INT size = tmp_len / oAdvance; if (dsb->device->tmp_buffer_len < tmp_len || !dsb->device->tmp_buffer) { dsb->device->tmp_buffer_len = tmp_len; if (dsb->device->tmp_buffer) dsb->device->tmp_buffer = HeapReAlloc(GetProcessHeap(), 0, dsb->device->tmp_buffer, tmp_len); else dsb->device->tmp_buffer = HeapAlloc(GetProcessHeap(), 0, tmp_len); } cp_fields(dsb, oAdvance, size, &dsb->freqAcc); }
/** * Mix at most the given amount of data into the allocated temporary buffer * of the given secondary buffer, starting from the dsb's first currently * unsampled frame (writepos), translating frequency (pitch), stereo/mono * and bits-per-sample so that it is ideal for the primary buffer. * Doesn't perform any mixing - this is a straight copy/convert operation. * * dsb = the secondary buffer * writepos = Starting position of changed buffer * len = number of bytes to resample from writepos * * NOTE: writepos + len <= buflen. When called by mixer, MixOne makes sure of this. */ void DSOUND_MixToTemporary(const IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD len, BOOL inmixer) { INT size; BYTE *ibp, *obp, *obp_begin; INT iAdvance = dsb->pwfx->nBlockAlign; INT oAdvance = dsb->device->pwfx->nBlockAlign; DWORD freqAcc, target_writepos = 0, overshot, maxlen; /* We resample only when needed */ if ((dsb->tmp_buffer && inmixer) || (!dsb->tmp_buffer && !inmixer) || dsb->resampleinmixer != inmixer) return; assert(writepos + len <= dsb->buflen); if (inmixer && writepos + len < dsb->buflen) len += dsb->pwfx->nBlockAlign; maxlen = DSOUND_secpos_to_bufpos(dsb, len, 0, NULL); ibp = dsb->buffer->memory + writepos; if (!inmixer) obp_begin = dsb->tmp_buffer; else if (dsb->device->tmp_buffer_len < maxlen || !dsb->device->tmp_buffer) { dsb->device->tmp_buffer_len = maxlen; if (dsb->device->tmp_buffer) dsb->device->tmp_buffer = HeapReAlloc(GetProcessHeap(), 0, dsb->device->tmp_buffer, maxlen); else dsb->device->tmp_buffer = HeapAlloc(GetProcessHeap(), 0, maxlen); obp_begin = dsb->device->tmp_buffer; } else obp_begin = dsb->device->tmp_buffer; TRACE("(%p, %p)\n", dsb, ibp); size = len / iAdvance; /* Check for same sample rate */ if (dsb->freq == dsb->device->pwfx->nSamplesPerSec) { TRACE("(%p) Same sample rate %d = primary %d\n", dsb, dsb->freq, dsb->device->pwfx->nSamplesPerSec); obp = obp_begin; if (!inmixer) obp += writepos/iAdvance*oAdvance; cp_fields(dsb, ibp, obp, iAdvance, oAdvance, size, 0, 1 << DSOUND_FREQSHIFT); return; } /* Mix in different sample rates */ TRACE("(%p) Adjusting frequency: %d -> %d\n", dsb, dsb->freq, dsb->device->pwfx->nSamplesPerSec); target_writepos = DSOUND_secpos_to_bufpos(dsb, writepos, dsb->sec_mixpos, &freqAcc); overshot = freqAcc >> DSOUND_FREQSHIFT; if (overshot) { if (overshot >= size) return; size -= overshot; writepos += overshot * iAdvance; if (writepos >= dsb->buflen) return; ibp = dsb->buffer->memory + writepos; freqAcc &= (1 << DSOUND_FREQSHIFT) - 1; TRACE("Overshot: %d, freqAcc: %04x\n", overshot, freqAcc); } if (!inmixer) obp = obp_begin + target_writepos; else obp = obp_begin; /* FIXME: Small problem here when we're overwriting buf_mixpos, it then STILL uses old freqAcc, not sure if it matters or not */ cp_fields(dsb, ibp, obp, iAdvance, oAdvance, size, freqAcc, dsb->freqAdjust); }