Implement Wiimote sound mixing in AXWii

This commit is contained in:
Pierre Bourdon 2013-01-20 15:32:55 +01:00
parent 35249a8576
commit 25419ed827
3 changed files with 94 additions and 27 deletions

View File

@ -161,15 +161,15 @@ struct PBDpopWii
struct PBDpopWM struct PBDpopWM
{ {
s16 aMain0; s16 main0;
s16 aMain1; s16 main1;
s16 aMain2; s16 main2;
s16 aMain3; s16 main3;
s16 aAux0; s16 aux0;
s16 aAux1; s16 aux1;
s16 aAux2; s16 aux2;
s16 aAux3; s16 aux3;
}; };
struct PBVolumeEnvelope struct PBVolumeEnvelope
@ -216,7 +216,7 @@ struct PBSampleRateConverter
struct PBSampleRateConverterWM struct PBSampleRateConverterWM
{ {
u16 currentAddressFrac; u16 cur_addr_frac;
u16 last_samples[4]; u16 last_samples[4];
}; };

View File

@ -228,7 +228,15 @@ void CUCode_AXWii::ProcessPBList(u32 pb_addr)
m_samples_auxB_surround, m_samples_auxB_surround,
m_samples_auxC_left, m_samples_auxC_left,
m_samples_auxC_right, m_samples_auxC_right,
m_samples_auxC_surround m_samples_auxC_surround,
m_samples_wm0,
m_samples_aux0,
m_samples_wm1,
m_samples_aux1,
m_samples_wm2,
m_samples_aux2,
m_samples_wm3,
m_samples_aux3
}}; }};
if (!ReadPB(pb_addr, pb)) if (!ReadPB(pb_addr, pb))

View File

@ -32,11 +32,9 @@
#ifdef AX_GC #ifdef AX_GC
# define PB_TYPE AXPB # define PB_TYPE AXPB
# define MS_PER_FRAME 1
# define SAMPLES_PER_FRAME 32 # define SAMPLES_PER_FRAME 32
#else #else
# define PB_TYPE AXPBWii # define PB_TYPE AXPBWii
# define MS_PER_FRAME 3
# define SAMPLES_PER_FRAME 96 # define SAMPLES_PER_FRAME 96
#endif #endif
@ -69,13 +67,22 @@ union AXBuffers
int* auxC_left; int* auxC_left;
int* auxC_right; int* auxC_right;
int* auxC_surround; int* auxC_surround;
int* wm_main0;
int* wm_aux0;
int* wm_main1;
int* wm_aux1;
int* wm_main2;
int* wm_aux2;
int* wm_main3;
int* wm_aux3;
#endif #endif
}; };
#ifdef AX_GC #ifdef AX_GC
int* ptrs[9]; int* ptrs[9];
#else #else
int* ptrs[12]; int* ptrs[20];
#endif #endif
}; };
@ -309,7 +316,7 @@ void GetInputSamples(PB_TYPE& pb, s16* samples)
} }
// Add samples to an output buffer, with optional volume ramping. // Add samples to an output buffer, with optional volume ramping.
void MixAdd(int* out, const s16* input, u16* pvol, s16* dpop, bool ramp) void MixAdd(int* out, const s16* input, u32 count, u16* pvol, s16* dpop, bool ramp)
{ {
u16& volume = pvol[0]; u16& volume = pvol[0];
u16 volume_delta = pvol[1]; u16 volume_delta = pvol[1];
@ -320,7 +327,7 @@ void MixAdd(int* out, const s16* input, u16* pvol, s16* dpop, bool ramp)
if (!ramp) if (!ramp)
volume_delta = 0; volume_delta = 0;
for (u32 i = 0; i < SAMPLES_PER_FRAME; ++i) for (u32 i = 0; i < count; ++i)
{ {
s64 sample = input[i]; s64 sample = input[i];
sample *= volume; sample *= volume;
@ -363,33 +370,33 @@ void ProcessVoice(PB_TYPE& pb, const AXBuffers& buffers, AXMixControl mctrl)
// TODO: Handle DPL2 on AUXB. // TODO: Handle DPL2 on AUXB.
if (mctrl & MIX_L) if (mctrl & MIX_L)
MixAdd(buffers.left, samples, &pb.mixer.left, &pb.dpop.left, mctrl & MIX_L_RAMP); MixAdd(buffers.left, samples, SAMPLES_PER_FRAME, &pb.mixer.left, &pb.dpop.left, mctrl & MIX_L_RAMP);
if (mctrl & MIX_R) if (mctrl & MIX_R)
MixAdd(buffers.right, samples, &pb.mixer.right, &pb.dpop.right, mctrl & MIX_R_RAMP); MixAdd(buffers.right, samples, SAMPLES_PER_FRAME, &pb.mixer.right, &pb.dpop.right, mctrl & MIX_R_RAMP);
if (mctrl & MIX_S) if (mctrl & MIX_S)
MixAdd(buffers.surround, samples, &pb.mixer.surround, &pb.dpop.surround, mctrl & MIX_S_RAMP); MixAdd(buffers.surround, samples, SAMPLES_PER_FRAME, &pb.mixer.surround, &pb.dpop.surround, mctrl & MIX_S_RAMP);
if (mctrl & MIX_AUXA_L) if (mctrl & MIX_AUXA_L)
MixAdd(buffers.auxA_left, samples, &pb.mixer.auxA_left, &pb.dpop.auxA_left, mctrl & MIX_AUXA_L_RAMP); MixAdd(buffers.auxA_left, samples, SAMPLES_PER_FRAME, &pb.mixer.auxA_left, &pb.dpop.auxA_left, mctrl & MIX_AUXA_L_RAMP);
if (mctrl & MIX_AUXA_R) if (mctrl & MIX_AUXA_R)
MixAdd(buffers.auxA_right, samples, &pb.mixer.auxA_right, &pb.dpop.auxA_right, mctrl & MIX_AUXA_R_RAMP); MixAdd(buffers.auxA_right, samples, SAMPLES_PER_FRAME, &pb.mixer.auxA_right, &pb.dpop.auxA_right, mctrl & MIX_AUXA_R_RAMP);
if (mctrl & MIX_AUXA_S) if (mctrl & MIX_AUXA_S)
MixAdd(buffers.auxA_surround, samples, &pb.mixer.auxA_surround, &pb.dpop.auxA_surround, mctrl & MIX_AUXA_S_RAMP); MixAdd(buffers.auxA_surround, samples, SAMPLES_PER_FRAME, &pb.mixer.auxA_surround, &pb.dpop.auxA_surround, mctrl & MIX_AUXA_S_RAMP);
if (mctrl & MIX_AUXB_L) if (mctrl & MIX_AUXB_L)
MixAdd(buffers.auxB_left, samples, &pb.mixer.auxB_left, &pb.dpop.auxB_left, mctrl & MIX_AUXB_L_RAMP); MixAdd(buffers.auxB_left, samples, SAMPLES_PER_FRAME, &pb.mixer.auxB_left, &pb.dpop.auxB_left, mctrl & MIX_AUXB_L_RAMP);
if (mctrl & MIX_AUXB_R) if (mctrl & MIX_AUXB_R)
MixAdd(buffers.auxB_right, samples, &pb.mixer.auxB_right, &pb.dpop.auxB_right, mctrl & MIX_AUXB_R_RAMP); MixAdd(buffers.auxB_right, samples, SAMPLES_PER_FRAME, &pb.mixer.auxB_right, &pb.dpop.auxB_right, mctrl & MIX_AUXB_R_RAMP);
if (mctrl & MIX_AUXB_S) if (mctrl & MIX_AUXB_S)
MixAdd(buffers.auxB_surround, samples, &pb.mixer.auxB_surround, &pb.dpop.auxB_surround, mctrl & MIX_AUXB_S_RAMP); MixAdd(buffers.auxB_surround, samples, SAMPLES_PER_FRAME, &pb.mixer.auxB_surround, &pb.dpop.auxB_surround, mctrl & MIX_AUXB_S_RAMP);
#ifdef AX_WII #ifdef AX_WII
if (mctrl & MIX_AUXC_L) if (mctrl & MIX_AUXC_L)
MixAdd(buffers.auxC_left, samples, &pb.mixer.auxC_left, &pb.dpop.auxC_left, mctrl & MIX_AUXC_L_RAMP); MixAdd(buffers.auxC_left, samples, SAMPLES_PER_FRAME, &pb.mixer.auxC_left, &pb.dpop.auxC_left, mctrl & MIX_AUXC_L_RAMP);
if (mctrl & MIX_AUXC_R) if (mctrl & MIX_AUXC_R)
MixAdd(buffers.auxC_right, samples, &pb.mixer.auxC_right, &pb.dpop.auxC_right, mctrl & MIX_AUXC_R_RAMP); MixAdd(buffers.auxC_right, samples, SAMPLES_PER_FRAME, &pb.mixer.auxC_right, &pb.dpop.auxC_right, mctrl & MIX_AUXC_R_RAMP);
if (mctrl & MIX_AUXC_S) if (mctrl & MIX_AUXC_S)
MixAdd(buffers.auxC_surround, samples, &pb.mixer.auxC_surround, &pb.dpop.auxC_surround, mctrl & MIX_AUXC_S_RAMP); MixAdd(buffers.auxC_surround, samples, SAMPLES_PER_FRAME, &pb.mixer.auxC_surround, &pb.dpop.auxC_surround, mctrl & MIX_AUXC_S_RAMP);
#endif #endif
// Optionally, phase shift left or right channel to simulate 3D sound. // Optionally, phase shift left or right channel to simulate 3D sound.
@ -397,6 +404,58 @@ void ProcessVoice(PB_TYPE& pb, const AXBuffers& buffers, AXMixControl mctrl)
{ {
// TODO // TODO
} }
#ifdef AX_WII
// Wiimote mixing.
if (pb.remote)
{
// Interpolate 18 samples from the 96 samples we read before. The real
// DSP code does it using a polyphase interpolation, we just use a
// linear interpolation here.
s16 wm_samples[18];
s16 curr0 = pb.remote_src.last_samples[2];
s16 curr1 = pb.remote_src.last_samples[3];
u32 ratio = 0x55555; // about 96/18 = 5.33333
u32 curr_pos = pb.remote_src.cur_addr_frac;
for (u32 i = 0; i < 18; ++i)
{
s32 curr_frac_pos = curr_pos & 0xFFFF;
s16 sample = curr0 + (s16)(((curr1 - curr0) * (s32)curr_frac_pos) >> 16);
wm_samples[i] = sample;
curr_pos += ratio;
curr0 = curr1;
curr1 = samples[curr_pos >> 16];
}
pb.remote_src.last_samples[2] = curr0;
pb.remote_src.last_samples[3] = curr1;
pb.src.cur_addr_frac = curr_pos & 0xFFFF;
// Mix to main[0-3] and aux[0-3]
#define WMCHAN_MIX_ON(n) ((pb.remote_mixer_control >> (2 * n)) & 3)
#define WMCHAN_MIX_RAMP(n) ((pb.remote_mixer_control >> (2 * n)) & 2)
if (WMCHAN_MIX_ON(0))
MixAdd(buffers.wm_main0, wm_samples, 18, &pb.remote_mixer.main0, &pb.remote_dpop.main0, WMCHAN_MIX_RAMP(0));
if (WMCHAN_MIX_ON(1))
MixAdd(buffers.wm_aux0, wm_samples, 18, &pb.remote_mixer.aux0, &pb.remote_dpop.aux0, WMCHAN_MIX_RAMP(1));
if (WMCHAN_MIX_ON(2))
MixAdd(buffers.wm_main1, wm_samples, 18, &pb.remote_mixer.main1, &pb.remote_dpop.main1, WMCHAN_MIX_RAMP(2));
if (WMCHAN_MIX_ON(3))
MixAdd(buffers.wm_aux1, wm_samples, 18, &pb.remote_mixer.aux1, &pb.remote_dpop.aux1, WMCHAN_MIX_RAMP(3));
if (WMCHAN_MIX_ON(4))
MixAdd(buffers.wm_main2, wm_samples, 18, &pb.remote_mixer.main2, &pb.remote_dpop.main2, WMCHAN_MIX_RAMP(4));
if (WMCHAN_MIX_ON(5))
MixAdd(buffers.wm_aux2, wm_samples, 18, &pb.remote_mixer.aux2, &pb.remote_dpop.aux2, WMCHAN_MIX_RAMP(5));
if (WMCHAN_MIX_ON(6))
MixAdd(buffers.wm_main3, wm_samples, 18, &pb.remote_mixer.main3, &pb.remote_dpop.main3, WMCHAN_MIX_RAMP(6));
if (WMCHAN_MIX_ON(7))
MixAdd(buffers.wm_aux3, wm_samples, 18, &pb.remote_mixer.aux3, &pb.remote_dpop.aux3, WMCHAN_MIX_RAMP(7));
}
#endif
} }
} // namespace } // namespace