Support both versions of the mixer_control bitfield. Fixes Skies of Arcadia music being muted (and sounds being mixed only on the left audio channel), this time without a hack.
This commit is contained in:
parent
c8b2ba1bc6
commit
3541d33c25
|
@ -372,26 +372,6 @@ enum {
|
|||
SRCTYPE_NEAREST = 2,
|
||||
};
|
||||
|
||||
enum {
|
||||
MIX_L = 0x0001,
|
||||
MIX_R = 0x0002,
|
||||
MIX_S = 0x0004,
|
||||
MIX_RAMP = 0x0008,
|
||||
|
||||
MIX_AUXA_L = 0x0010,
|
||||
MIX_AUXA_R = 0x0020,
|
||||
MIX_AUXA_RAMPLR = 0x0040,
|
||||
MIX_AUXA_S = 0x0080,
|
||||
MIX_AUXA_RAMPS = 0x0100,
|
||||
|
||||
MIX_AUXB_L = 0x0200,
|
||||
MIX_AUXB_R = 0x0400,
|
||||
MIX_AUXB_RAMPLR = 0x0800,
|
||||
MIX_AUXB_S = 0x1000,
|
||||
MIX_AUXB_RAMPS = 0x2000,
|
||||
MIX_AUXB_DPL2 = 0x4000
|
||||
};
|
||||
|
||||
// Both may be used at once
|
||||
enum {
|
||||
FILTER_LOWPASS = 1,
|
||||
|
|
|
@ -230,7 +230,7 @@ inline void MixAddVoice(ParamBlockType &pb, const AXBuffers& buffers,
|
|||
int vol = pb.vol_env.cur_volume >> 9;
|
||||
sample = sample * vol >> 8;
|
||||
|
||||
if (pb.mixer_control & MIX_RAMP)
|
||||
if (pb.mixer_control & 8)
|
||||
{
|
||||
int x = pb.vol_env.cur_volume;
|
||||
x += pb.vol_env.cur_volume_delta; // I'm not sure about this, can anybody find a game
|
||||
|
|
|
@ -19,13 +19,12 @@
|
|||
#include "UCode_NewAX_Voice.h"
|
||||
#include "../../DSP.h"
|
||||
|
||||
#define MIXBUF_MAX_SAMPLES 16000 // 500ms of stereo audio
|
||||
|
||||
CUCode_NewAX::CUCode_NewAX(DSPHLE* dsp_hle, u32 crc)
|
||||
: IUCode(dsp_hle, crc)
|
||||
, m_cmdlist_size(0)
|
||||
, m_axthread(&SpawnAXThread, this)
|
||||
{
|
||||
WARN_LOG(DSPHLE, "Instantiating CUCode_NewAX: crc=%08x", crc);
|
||||
m_rMailHandler.PushMail(DSP_INIT);
|
||||
DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP);
|
||||
}
|
||||
|
@ -83,6 +82,11 @@ void CUCode_NewAX::HandleCommandList()
|
|||
|
||||
u32 pb_addr = 0;
|
||||
|
||||
// WARN_LOG(DSPHLE, "Command list:");
|
||||
// for (u32 i = 0; m_cmdlist[i] != CMD_END; ++i)
|
||||
// WARN_LOG(DSPHLE, "%04x", m_cmdlist[i]);
|
||||
// WARN_LOG(DSPHLE, "-------------");
|
||||
|
||||
u32 curr_idx = 0;
|
||||
bool end = false;
|
||||
while (!end)
|
||||
|
@ -193,6 +197,54 @@ static void ApplyUpdatesForMs(AXPB& pb, int curr_ms)
|
|||
}
|
||||
}
|
||||
|
||||
AXMixControl CUCode_NewAX::ConvertMixerControl(u32 mixer_control)
|
||||
{
|
||||
u32 ret = 0;
|
||||
|
||||
// TODO: find other UCode versions with different mixer_control values
|
||||
if (m_CRC == 0x4e8a8b21)
|
||||
{
|
||||
ret |= MIX_L | MIX_R;
|
||||
if (mixer_control & 0x0001) ret |= MIX_AUXA_L | MIX_AUXA_R;
|
||||
if (mixer_control & 0x0002) ret |= MIX_AUXB_L | MIX_AUXB_R;
|
||||
if (mixer_control & 0x0004)
|
||||
{
|
||||
ret |= MIX_S;
|
||||
if (ret & MIX_AUXA_L) ret |= MIX_AUXA_S;
|
||||
if (ret & MIX_AUXB_L) ret |= MIX_AUXB_S;
|
||||
}
|
||||
if (mixer_control & 0x0008)
|
||||
{
|
||||
ret |= MIX_L_RAMP | MIX_R_RAMP;
|
||||
if (ret & MIX_AUXA_L) ret |= MIX_AUXA_L_RAMP | MIX_AUXA_R_RAMP;
|
||||
if (ret & MIX_AUXB_L) ret |= MIX_AUXB_L_RAMP | MIX_AUXB_R_RAMP;
|
||||
if (ret & MIX_AUXA_S) ret |= MIX_AUXA_S_RAMP;
|
||||
if (ret & MIX_AUXB_S) ret |= MIX_AUXB_S_RAMP;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mixer_control & 0x0001) ret |= MIX_L;
|
||||
if (mixer_control & 0x0002) ret |= MIX_R;
|
||||
if (mixer_control & 0x0004) ret |= MIX_S;
|
||||
if (mixer_control & 0x0008) ret |= MIX_L_RAMP | MIX_R_RAMP | MIX_S_RAMP;
|
||||
if (mixer_control & 0x0010) ret |= MIX_AUXA_L;
|
||||
if (mixer_control & 0x0020) ret |= MIX_AUXA_R;
|
||||
if (mixer_control & 0x0040) ret |= MIX_AUXA_L_RAMP | MIX_AUXA_R_RAMP;
|
||||
if (mixer_control & 0x0080) ret |= MIX_AUXA_S;
|
||||
if (mixer_control & 0x0100) ret |= MIX_AUXA_S_RAMP;
|
||||
if (mixer_control & 0x0200) ret |= MIX_AUXB_L;
|
||||
if (mixer_control & 0x0400) ret |= MIX_AUXB_R;
|
||||
if (mixer_control & 0x0800) ret |= MIX_AUXB_L_RAMP | MIX_AUXB_R_RAMP;
|
||||
if (mixer_control & 0x1000) ret |= MIX_AUXB_S;
|
||||
if (mixer_control & 0x2000) ret |= MIX_AUXB_S_RAMP;
|
||||
|
||||
// TODO: 0x4000 is used for Dolby Pro 2 sound mixing
|
||||
}
|
||||
|
||||
return (AXMixControl)ret;
|
||||
}
|
||||
|
||||
void CUCode_NewAX::SetupProcessing(u32 init_addr)
|
||||
{
|
||||
u16 init_data[0x20];
|
||||
|
@ -263,7 +315,7 @@ void CUCode_NewAX::ProcessPBList(u32 pb_addr)
|
|||
{
|
||||
ApplyUpdatesForMs(pb, curr_ms);
|
||||
|
||||
Process1ms(pb, buffers);
|
||||
Process1ms(pb, buffers, ConvertMixerControl(pb.mixer_control));
|
||||
|
||||
// Forward the buffers
|
||||
for (u32 i = 0; i < sizeof (buffers.ptrs) / sizeof (buffers.ptrs[0]); ++i)
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "UCodes.h"
|
||||
#include "UCode_AXStructs.h"
|
||||
#include "UCode_NewAX_Voice.h"
|
||||
|
||||
class CUCode_NewAX : public IUCode
|
||||
{
|
||||
|
@ -99,6 +100,11 @@ private:
|
|||
// Copy a command list from memory to our temp buffer
|
||||
void CopyCmdList(u32 addr, u16 size);
|
||||
|
||||
// Convert a mixer_control bitfield to our internal representation for that
|
||||
// value. Required because that bitfield has a different meaning in some
|
||||
// versions of AX.
|
||||
AXMixControl ConvertMixerControl(u32 mixer_control);
|
||||
|
||||
// Send a notification to the AX thread to tell him a new cmdlist addr is
|
||||
// available for processing.
|
||||
void NotifyAXThread();
|
||||
|
|
|
@ -47,6 +47,33 @@ union AXBuffers
|
|||
int* ptrs[9];
|
||||
};
|
||||
|
||||
// We can't directly use the mixer_control field from the PB because it does
|
||||
// not mean the same in all AX versions. The AX UCode converts the
|
||||
// mixer_control value to an AXMixControl bitfield.
|
||||
enum AXMixControl
|
||||
{
|
||||
MIX_L = 0x00001,
|
||||
MIX_L_RAMP = 0x00002,
|
||||
MIX_R = 0x00004,
|
||||
MIX_R_RAMP = 0x00008,
|
||||
MIX_S = 0x00010,
|
||||
MIX_S_RAMP = 0x00020,
|
||||
|
||||
MIX_AUXA_L = 0x00040,
|
||||
MIX_AUXA_L_RAMP = 0x00080,
|
||||
MIX_AUXA_R = 0x00100,
|
||||
MIX_AUXA_R_RAMP = 0x00200,
|
||||
MIX_AUXA_S = 0x00400,
|
||||
MIX_AUXA_S_RAMP = 0x00800,
|
||||
|
||||
MIX_AUXB_L = 0x01000,
|
||||
MIX_AUXB_L_RAMP = 0x02000,
|
||||
MIX_AUXB_R = 0x04000,
|
||||
MIX_AUXB_R_RAMP = 0x08000,
|
||||
MIX_AUXB_S = 0x10000,
|
||||
MIX_AUXB_S_RAMP = 0x20000
|
||||
};
|
||||
|
||||
// Read a PB from MRAM/ARAM
|
||||
inline bool ReadPB(u32 addr, AXPB& pb)
|
||||
{
|
||||
|
@ -290,7 +317,7 @@ inline void MixAdd(int* out, const s16* input, u16* pvol, bool ramp)
|
|||
}
|
||||
|
||||
// Process 1ms of audio (32 samples) from a PB and mix it to the buffers.
|
||||
inline void Process1ms(AXPB& pb, const AXBuffers& buffers)
|
||||
inline void Process1ms(AXPB& pb, const AXBuffers& buffers, AXMixControl mctrl)
|
||||
{
|
||||
// If the voice is not running, nothing to do.
|
||||
if (!pb.running)
|
||||
|
@ -320,26 +347,26 @@ inline void Process1ms(AXPB& pb, const AXBuffers& buffers)
|
|||
// HACK: at the moment we don't mix surround into left and right, so always
|
||||
// mix left and right in order to have sound even if a game uses surround
|
||||
// only.
|
||||
//if (pb.mixer_control & MIX_L)
|
||||
MixAdd(buffers.left, samples, &pb.mixer.left, pb.mixer_control & MIX_RAMP);
|
||||
//if (pb.mixer_control & MIX_R)
|
||||
MixAdd(buffers.right, samples, &pb.mixer.right, pb.mixer_control & MIX_RAMP);
|
||||
if (pb.mixer_control & MIX_S)
|
||||
MixAdd(buffers.surround, samples, &pb.mixer.surround, pb.mixer_control & MIX_RAMP);
|
||||
if (mctrl & MIX_L)
|
||||
MixAdd(buffers.left, samples, &pb.mixer.left, mctrl & MIX_L_RAMP);
|
||||
if (mctrl & MIX_R)
|
||||
MixAdd(buffers.right, samples, &pb.mixer.right, mctrl & MIX_R_RAMP);
|
||||
if (mctrl & MIX_S)
|
||||
MixAdd(buffers.surround, samples, &pb.mixer.surround, mctrl & MIX_S_RAMP);
|
||||
|
||||
if (pb.mixer_control & MIX_AUXA_L)
|
||||
MixAdd(buffers.auxA_left, samples, &pb.mixer.auxA_left, pb.mixer_control & MIX_AUXA_RAMPLR);
|
||||
if (pb.mixer_control & MIX_AUXA_R)
|
||||
MixAdd(buffers.auxA_right, samples, &pb.mixer.auxA_right, pb.mixer_control & MIX_AUXA_RAMPLR);
|
||||
if (pb.mixer_control & MIX_AUXA_S)
|
||||
MixAdd(buffers.auxA_surround, samples, &pb.mixer.auxA_surround, pb.mixer_control & MIX_AUXA_RAMPS);
|
||||
if (mctrl & MIX_AUXA_L)
|
||||
MixAdd(buffers.auxA_left, samples, &pb.mixer.auxA_left, mctrl & MIX_AUXA_L_RAMP);
|
||||
if (mctrl & MIX_AUXA_R)
|
||||
MixAdd(buffers.auxA_right, samples, &pb.mixer.auxA_right, mctrl & MIX_AUXA_R_RAMP);
|
||||
if (mctrl & MIX_AUXA_S)
|
||||
MixAdd(buffers.auxA_surround, samples, &pb.mixer.auxA_surround, mctrl & MIX_AUXA_S_RAMP);
|
||||
|
||||
if (pb.mixer_control & MIX_AUXB_L)
|
||||
MixAdd(buffers.auxB_left, samples, &pb.mixer.auxB_left, pb.mixer_control & MIX_AUXB_RAMPLR);
|
||||
if (pb.mixer_control & MIX_AUXB_R)
|
||||
MixAdd(buffers.auxB_right, samples, &pb.mixer.auxB_right, pb.mixer_control & MIX_AUXB_RAMPLR);
|
||||
if (pb.mixer_control & MIX_AUXB_S)
|
||||
MixAdd(buffers.auxB_surround, samples, &pb.mixer.auxB_surround, pb.mixer_control & MIX_AUXB_RAMPS);
|
||||
if (mctrl & MIX_AUXB_L)
|
||||
MixAdd(buffers.auxB_left, samples, &pb.mixer.auxB_left, mctrl & MIX_AUXB_L_RAMP);
|
||||
if (mctrl & MIX_AUXB_R)
|
||||
MixAdd(buffers.auxB_right, samples, &pb.mixer.auxB_right, mctrl & MIX_AUXB_R_RAMP);
|
||||
if (mctrl & MIX_AUXB_S)
|
||||
MixAdd(buffers.auxB_surround, samples, &pb.mixer.auxB_surround, mctrl & MIX_AUXB_S_RAMP);
|
||||
|
||||
// Optionally, phase shift left or right channel to simulate 3D sound.
|
||||
if (pb.initial_time_delay.on)
|
||||
|
|
Loading…
Reference in New Issue