dsound: Clean up channels.
This commit is contained in:
parent
ab4ef6636d
commit
93a0ca7c6c
|
@ -104,6 +104,18 @@ static float getieee32(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD chann
|
|||
|
||||
const bitsgetfunc getbpp[5] = {get8, get16, get24, get32, getieee32};
|
||||
|
||||
float get_mono(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel)
|
||||
{
|
||||
DWORD channels = dsb->pwfx->nChannels;
|
||||
DWORD c;
|
||||
float val = 0;
|
||||
/* XXX: does Windows include LFE into the mix? */
|
||||
for (c = 0; c < channels; c++)
|
||||
val += dsb->get_aux(dsb, pos, c);
|
||||
val /= channels;
|
||||
return val;
|
||||
}
|
||||
|
||||
static void put8(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value)
|
||||
{
|
||||
BYTE* buf = dsb->device->tmp_buffer;
|
||||
|
@ -158,6 +170,12 @@ static void put32(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, f
|
|||
|
||||
const bitsputfunc putbpp[4] = {put8, put16, put24, put32};
|
||||
|
||||
void put_mono2stereo(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value)
|
||||
{
|
||||
dsb->put_aux(dsb, pos, 0, value);
|
||||
dsb->put_aux(dsb, pos, 1, value);
|
||||
}
|
||||
|
||||
static void mix8(signed char *src, INT *dst, unsigned len)
|
||||
{
|
||||
TRACE("%p - %p %d\n", src, dst, len);
|
||||
|
|
|
@ -193,12 +193,16 @@ struct IDirectSoundBufferImpl
|
|||
LONG ds3db_lVolume;
|
||||
BOOL ds3db_need_recalc;
|
||||
/* Used for bit depth conversion */
|
||||
bitsgetfunc get;
|
||||
bitsputfunc put;
|
||||
int mix_channels;
|
||||
bitsgetfunc get, get_aux;
|
||||
bitsputfunc put, put_aux;
|
||||
|
||||
struct list entry;
|
||||
};
|
||||
|
||||
float get_mono(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel) DECLSPEC_HIDDEN;
|
||||
void put_mono2stereo(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value) DECLSPEC_HIDDEN;
|
||||
|
||||
HRESULT IDirectSoundBufferImpl_Create(
|
||||
DirectSoundDevice *device,
|
||||
IDirectSoundBufferImpl **ppdsb,
|
||||
|
|
|
@ -178,6 +178,8 @@ static void DSOUND_RecalcFreqAcc(IDirectSoundBufferImpl *dsb)
|
|||
*/
|
||||
void DSOUND_RecalcFormat(IDirectSoundBufferImpl *dsb)
|
||||
{
|
||||
DWORD ichannels = dsb->pwfx->nChannels;
|
||||
DWORD ochannels = dsb->device->pwfx->nChannels;
|
||||
BOOL needremix = TRUE, needresample = (dsb->freq != dsb->device->pwfx->nSamplesPerSec);
|
||||
DWORD bAlign = dsb->pwfx->nBlockAlign, pAlign = dsb->device->pwfx->nBlockAlign;
|
||||
WAVEFORMATEXTENSIBLE *pwfxe;
|
||||
|
@ -200,8 +202,36 @@ void DSOUND_RecalcFormat(IDirectSoundBufferImpl *dsb)
|
|||
dsb->freqAcc = dsb->freqAccNext = 0;
|
||||
dsb->freqneeded = needresample;
|
||||
|
||||
dsb->get = ieee ? getbpp[4] : getbpp[dsb->pwfx->wBitsPerSample/8 - 1];
|
||||
dsb->put = putbpp[dsb->device->pwfx->wBitsPerSample/8 - 1];
|
||||
dsb->get_aux = ieee ? getbpp[4] : getbpp[dsb->pwfx->wBitsPerSample/8 - 1];
|
||||
dsb->put_aux = putbpp[dsb->device->pwfx->wBitsPerSample/8 - 1];
|
||||
|
||||
dsb->get = dsb->get_aux;
|
||||
dsb->put = dsb->put_aux;
|
||||
|
||||
if (ichannels == ochannels)
|
||||
{
|
||||
dsb->mix_channels = ichannels;
|
||||
if (ichannels > 32) {
|
||||
FIXME("Copying %u channels is unsupported, limiting to first 32\n", ichannels);
|
||||
dsb->mix_channels = 32;
|
||||
}
|
||||
}
|
||||
else if (ichannels == 1)
|
||||
{
|
||||
dsb->mix_channels = 1;
|
||||
dsb->put = put_mono2stereo;
|
||||
}
|
||||
else if (ochannels == 1)
|
||||
{
|
||||
dsb->mix_channels = 1;
|
||||
dsb->get = get_mono;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ichannels > 2)
|
||||
FIXME("Conversion from %u to %u channels is not implemented, falling back to stereo\n", ichannels, ochannels);
|
||||
dsb->mix_channels = 2;
|
||||
}
|
||||
|
||||
if (needremix)
|
||||
{
|
||||
|
@ -278,38 +308,13 @@ static inline void cp_fields(const IDirectSoundBufferImpl *dsb,
|
|||
DWORD ipos = dsb->sec_mixpos;
|
||||
UINT istride = dsb->pwfx->nBlockAlign;
|
||||
UINT adj = dsb->freqAdjust;
|
||||
DirectSoundDevice *device = dsb->device;
|
||||
float value;
|
||||
ULONG adv;
|
||||
DWORD opos = 0;
|
||||
|
||||
while (count-- > 0) {
|
||||
if (device->pwfx->nChannels == dsb->pwfx->nChannels ||
|
||||
(device->pwfx->nChannels == 2 && dsb->pwfx->nChannels == 6) ||
|
||||
(device->pwfx->nChannels == 8 && dsb->pwfx->nChannels == 2) ||
|
||||
(device->pwfx->nChannels == 6 && dsb->pwfx->nChannels == 2)) {
|
||||
value = dsb->get(dsb, ipos, 0);
|
||||
dsb->put(dsb, opos, 0, value);
|
||||
if (device->pwfx->nChannels == 2 || dsb->pwfx->nChannels == 2) {
|
||||
value = dsb->get(dsb, ipos, 1);
|
||||
dsb->put(dsb, opos, 1, value);
|
||||
}
|
||||
}
|
||||
|
||||
if (device->pwfx->nChannels == 1 && dsb->pwfx->nChannels == 2)
|
||||
{
|
||||
float val = (dsb->get(dsb, ipos, 0) + dsb->get(dsb, ipos, 1)) / 2.;
|
||||
|
||||
dsb->put(dsb, opos, 0, val);
|
||||
}
|
||||
|
||||
if (device->pwfx->nChannels == 2 && dsb->pwfx->nChannels == 1)
|
||||
{
|
||||
value = dsb->get(dsb, ipos, 0);
|
||||
dsb->put(dsb, opos, 0, value);
|
||||
dsb->put(dsb, opos, 1, value);
|
||||
}
|
||||
|
||||
DWORD channel;
|
||||
for (channel = 0; channel < dsb->mix_channels; channel++)
|
||||
dsb->put(dsb, opos, channel, dsb->get(dsb, ipos, channel));
|
||||
freqAcc += adj;
|
||||
adv = (freqAcc >> DSOUND_FREQSHIFT);
|
||||
freqAcc &= (1 << DSOUND_FREQSHIFT) - 1;
|
||||
|
@ -361,18 +366,6 @@ static void DSOUND_MixToTemporary(const IDirectSoundBufferImpl *dsb, DWORD tmp_l
|
|||
dsb->device->tmp_buffer = HeapAlloc(GetProcessHeap(), 0, tmp_len);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
cp_fields(dsb, oAdvance, size, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Mix in different sample rates */
|
||||
TRACE("(%p) Adjusting frequency: %d -> %d\n", dsb, dsb->freq, dsb->device->pwfx->nSamplesPerSec);
|
||||
|
||||
DSOUND_secpos_to_bufpos(dsb, dsb->sec_mixpos, dsb->sec_mixpos, &freqAcc);
|
||||
|
||||
/* FIXME: Small problem here when we're overwriting buf_mixpos, it then STILL uses old freqAcc, not sure if it matters or not */
|
||||
|
|
Loading…
Reference in New Issue