Implement Wiimote sound mixing in AXWii
This commit is contained in:
parent
35249a8576
commit
25419ed827
|
@ -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];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue