[PATCH 4/4] dsound: Clean up channels
Alexander E. Patrakov
patrakov at gmail.com
Tue May 1 10:46:11 CDT 2012
The infrastructure set up in the "Replace convert() functions with
get() and put()" also allows to convert the number of channels more
elegantly. See how much deeply-nested code and complex conditions was
removed from cp_fields() :)
The old code supported (secondary -> primary):
n -> n
6 -> 2
2 -> 8 (hack, first 2 only)
2 -> 6 (hack, first 2 only)
2 -> 1
1 -> 2
silence (catchall)
While the new code supports:
n -> n
1 -> 2
n -> 1
n -> m (catchall, hack, first 2 only)
--
Alexander E. Patrakov
-------------- next part --------------
>From b421c12f35a1374b13275cec53be0467e52515e1 Mon Sep 17 00:00:00 2001
From: "Alexander E. Patrakov" <patrakov at gmail.com>
Date: Mon, 12 Dec 2011 14:07:49 -0600
Subject: [PATCH 4/7] dsound: Clean up channels
---
dlls/dsound/dsound_convert.c | 18 ++++++++++
dlls/dsound/dsound_private.h | 8 +++-
dlls/dsound/mixer.c | 77 +++++++++++++++++++-----------------------
3 files changed, 59 insertions(+), 44 deletions(-)
diff --git a/dlls/dsound/dsound_convert.c b/dlls/dsound/dsound_convert.c
index b670c04..63f1eb0 100644
--- a/dlls/dsound/dsound_convert.c
+++ b/dlls/dsound/dsound_convert.c
@@ -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);
diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h
index 9f30bff..5d1d62a 100644
--- a/dlls/dsound/dsound_private.h
+++ b/dlls/dsound/dsound_private.h
@@ -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,
diff --git a/dlls/dsound/mixer.c b/dlls/dsound/mixer.c
index 4f73831..5fa15b2 100644
--- a/dlls/dsound/mixer.c
+++ b/dlls/dsound/mixer.c
@@ -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 */
--
1.7.8.6
More information about the wine-patches
mailing list