Пример #1
0
Файл: mixer.c Проект: behda/wine
/**
 * 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);
}
Пример #2
0
/**
 * 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);
}
Пример #3
0
/**
 * 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);
}