DSPHLE: add support for dynamic range compression
The CPU-side AX library enables it by default and uses hardcoded parameters. CMD_COMPRESSOR_TABLE_ADDR (0x0A) was incorrect. It's always a nop on the GameCube and was probably confused with the Wii version.
This commit is contained in:
parent
cba4b6ca32
commit
09faf0987d
|
@ -23,7 +23,8 @@
|
||||||
|
|
||||||
namespace DSP::HLE
|
namespace DSP::HLE
|
||||||
{
|
{
|
||||||
AXUCode::AXUCode(DSPHLE* dsphle, u32 crc) : UCodeInterface(dsphle, crc), m_cmdlist_size(0)
|
AXUCode::AXUCode(DSPHLE* dsphle, u32 crc)
|
||||||
|
: UCodeInterface(dsphle, crc), m_cmdlist_size(0), m_compressor_pos(0)
|
||||||
{
|
{
|
||||||
INFO_LOG_FMT(DSPHLE, "Instantiating AXUCode: crc={:08x}", crc);
|
INFO_LOG_FMT(DSPHLE, "Instantiating AXUCode: crc={:08x}", crc);
|
||||||
}
|
}
|
||||||
|
@ -181,13 +182,11 @@ void AXUCode::HandleCommandList()
|
||||||
MixAUXSamples(1, 0, HILO_TO_32(addr));
|
MixAUXSamples(1, 0, HILO_TO_32(addr));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_COMPRESSOR_TABLE_ADDR:
|
case CMD_UNK_0A:
|
||||||
curr_idx += 2;
|
|
||||||
break;
|
|
||||||
case CMD_UNK_0B:
|
case CMD_UNK_0B:
|
||||||
break; // TODO: check other versions
|
|
||||||
case CMD_UNK_0C:
|
case CMD_UNK_0C:
|
||||||
break; // TODO: check other versions
|
// nop in all 6 known ucodes we handle here
|
||||||
|
break;
|
||||||
|
|
||||||
case CMD_MORE:
|
case CMD_MORE:
|
||||||
addr_hi = m_cmdlist[curr_idx++];
|
addr_hi = m_cmdlist[curr_idx++];
|
||||||
|
@ -224,16 +223,16 @@ void AXUCode::HandleCommandList()
|
||||||
SetOppositeLR(HILO_TO_32(addr));
|
SetOppositeLR(HILO_TO_32(addr));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_UNK_12:
|
case CMD_COMPRESSOR:
|
||||||
{
|
{
|
||||||
u16 samp_val = m_cmdlist[curr_idx++];
|
// 0x4e8a8b21 doesn't have this command, but it doesn't range-check
|
||||||
u16 idx = m_cmdlist[curr_idx++];
|
// the value properly and ends up jumping into a mixer function
|
||||||
|
ASSERT(m_crc != 0x4e8a8b21);
|
||||||
|
u16 threshold = m_cmdlist[curr_idx++];
|
||||||
|
u16 frames = m_cmdlist[curr_idx++];
|
||||||
addr_hi = m_cmdlist[curr_idx++];
|
addr_hi = m_cmdlist[curr_idx++];
|
||||||
addr_lo = m_cmdlist[curr_idx++];
|
addr_lo = m_cmdlist[curr_idx++];
|
||||||
// TODO
|
RunCompressor(threshold, frames, HILO_TO_32(addr), 5);
|
||||||
// suppress warnings:
|
|
||||||
(void)samp_val;
|
|
||||||
(void)idx;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -508,6 +507,52 @@ void AXUCode::SetMainLR(u32 src_addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AXUCode::RunCompressor(u16 threshold, u16 release_frames, u32 table_addr, u32 millis)
|
||||||
|
{
|
||||||
|
// check for L/R samples exceeding the threshold
|
||||||
|
bool triggered = false;
|
||||||
|
for (u32 i = 0; i < 32 * millis; ++i)
|
||||||
|
{
|
||||||
|
if (std::abs(m_samples_left[i]) > int(threshold) ||
|
||||||
|
std::abs(m_samples_right[i]) > int(threshold))
|
||||||
|
{
|
||||||
|
triggered = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const u32 frame_byte_size = 32 * millis * sizeof(s16);
|
||||||
|
u32 table_offset = 0;
|
||||||
|
if (triggered)
|
||||||
|
{
|
||||||
|
// one attack frame based on previous frame
|
||||||
|
table_offset = m_compressor_pos * frame_byte_size;
|
||||||
|
// next frame will start release
|
||||||
|
m_compressor_pos = release_frames;
|
||||||
|
}
|
||||||
|
else if (m_compressor_pos)
|
||||||
|
{
|
||||||
|
// release
|
||||||
|
--m_compressor_pos;
|
||||||
|
// the release ramps are located after the attack ramps
|
||||||
|
constexpr u32 ATTACK_ENTRY_COUNT = 11;
|
||||||
|
table_offset = (ATTACK_ENTRY_COUNT + m_compressor_pos) * frame_byte_size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// apply the selected ramp
|
||||||
|
u16* ramp = (u16*)HLEMemory_Get_Pointer(table_addr + table_offset);
|
||||||
|
for (u32 i = 0; i < 32 * millis; ++i)
|
||||||
|
{
|
||||||
|
u16 coef = Common::swap16(*ramp++);
|
||||||
|
m_samples_left[i] = (s64(m_samples_left[i]) * coef) >> 15;
|
||||||
|
m_samples_right[i] = (s64(m_samples_right[i]) * coef) >> 15;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AXUCode::OutputSamples(u32 lr_addr, u32 surround_addr)
|
void AXUCode::OutputSamples(u32 lr_addr, u32 surround_addr)
|
||||||
{
|
{
|
||||||
int surround_buffer[5 * 32];
|
int surround_buffer[5 * 32];
|
||||||
|
|
|
@ -98,6 +98,8 @@ protected:
|
||||||
bool m_coeffs_available;
|
bool m_coeffs_available;
|
||||||
s16 m_coeffs[0x800];
|
s16 m_coeffs[0x800];
|
||||||
|
|
||||||
|
u16 m_compressor_pos;
|
||||||
|
|
||||||
void LoadResamplingCoefficients();
|
void LoadResamplingCoefficients();
|
||||||
|
|
||||||
// Copy a command list from memory to our temp buffer
|
// Copy a command list from memory to our temp buffer
|
||||||
|
@ -138,6 +140,7 @@ protected:
|
||||||
void MixAUXSamples(int aux_id, u32 write_addr, u32 read_addr);
|
void MixAUXSamples(int aux_id, u32 write_addr, u32 read_addr);
|
||||||
void UploadLRS(u32 dst_addr);
|
void UploadLRS(u32 dst_addr);
|
||||||
void SetMainLR(u32 src_addr);
|
void SetMainLR(u32 src_addr);
|
||||||
|
void RunCompressor(u16 threshold, u16 release_stages, u32 table_addr, u32 millis);
|
||||||
void OutputSamples(u32 out_addr, u32 surround_addr);
|
void OutputSamples(u32 out_addr, u32 surround_addr);
|
||||||
void MixAUXBLR(u32 ul_addr, u32 dl_addr);
|
void MixAUXBLR(u32 ul_addr, u32 dl_addr);
|
||||||
void SetOppositeLR(u32 src_addr);
|
void SetOppositeLR(u32 src_addr);
|
||||||
|
@ -160,7 +163,7 @@ private:
|
||||||
CMD_SET_LR = 0x07,
|
CMD_SET_LR = 0x07,
|
||||||
CMD_UNK_08 = 0x08,
|
CMD_UNK_08 = 0x08,
|
||||||
CMD_MIX_AUXB_NOWRITE = 0x09,
|
CMD_MIX_AUXB_NOWRITE = 0x09,
|
||||||
CMD_COMPRESSOR_TABLE_ADDR = 0x0A,
|
CMD_UNK_0A = 0x0A,
|
||||||
CMD_UNK_0B = 0x0B,
|
CMD_UNK_0B = 0x0B,
|
||||||
CMD_UNK_0C = 0x0C,
|
CMD_UNK_0C = 0x0C,
|
||||||
CMD_MORE = 0x0D,
|
CMD_MORE = 0x0D,
|
||||||
|
@ -168,7 +171,7 @@ private:
|
||||||
CMD_END = 0x0F,
|
CMD_END = 0x0F,
|
||||||
CMD_MIX_AUXB_LR = 0x10,
|
CMD_MIX_AUXB_LR = 0x10,
|
||||||
CMD_SET_OPPOSITE_LR = 0x11,
|
CMD_SET_OPPOSITE_LR = 0x11,
|
||||||
CMD_UNK_12 = 0x12,
|
CMD_COMPRESSOR = 0x12,
|
||||||
CMD_SEND_AUX_AND_MIX = 0x13,
|
CMD_SEND_AUX_AND_MIX = 0x13,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -113,11 +113,15 @@ void AXWiiUCode::HandleCommandList()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(delroth): figure this one out, it's used by almost every
|
case CMD_COMPRESSOR_OLD:
|
||||||
// game I've tested so far.
|
{
|
||||||
case CMD_UNK_0B_OLD:
|
u16 threshold = m_cmdlist[curr_idx++];
|
||||||
curr_idx += 4;
|
u16 frames = m_cmdlist[curr_idx++];
|
||||||
|
addr_hi = m_cmdlist[curr_idx++];
|
||||||
|
addr_lo = m_cmdlist[curr_idx++];
|
||||||
|
RunCompressor(threshold, frames, HILO_TO_32(addr), 3);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case CMD_OUTPUT_OLD:
|
case CMD_OUTPUT_OLD:
|
||||||
case CMD_OUTPUT_DPL2_OLD:
|
case CMD_OUTPUT_DPL2_OLD:
|
||||||
|
@ -206,11 +210,15 @@ void AXWiiUCode::HandleCommandList()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(delroth): figure this one out, it's used by almost every
|
case CMD_COMPRESSOR:
|
||||||
// game I've tested so far.
|
{
|
||||||
case CMD_UNK_0A:
|
u16 threshold = m_cmdlist[curr_idx++];
|
||||||
curr_idx += 4;
|
u16 frames = m_cmdlist[curr_idx++];
|
||||||
|
addr_hi = m_cmdlist[curr_idx++];
|
||||||
|
addr_lo = m_cmdlist[curr_idx++];
|
||||||
|
RunCompressor(threshold, frames, HILO_TO_32(addr), 3);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case CMD_OUTPUT:
|
case CMD_OUTPUT:
|
||||||
case CMD_OUTPUT_DPL2:
|
case CMD_OUTPUT_DPL2:
|
||||||
|
|
|
@ -82,7 +82,7 @@ private:
|
||||||
CMD_MIX_AUXC = 0x07,
|
CMD_MIX_AUXC = 0x07,
|
||||||
CMD_UPL_AUXA_MIX_LRSC = 0x08,
|
CMD_UPL_AUXA_MIX_LRSC = 0x08,
|
||||||
CMD_UPL_AUXB_MIX_LRSC = 0x09,
|
CMD_UPL_AUXB_MIX_LRSC = 0x09,
|
||||||
CMD_UNK_0A = 0x0A,
|
CMD_COMPRESSOR = 0x0A,
|
||||||
CMD_OUTPUT = 0x0B,
|
CMD_OUTPUT = 0x0B,
|
||||||
CMD_OUTPUT_DPL2 = 0x0C,
|
CMD_OUTPUT_DPL2 = 0x0C,
|
||||||
CMD_WM_OUTPUT = 0x0D,
|
CMD_WM_OUTPUT = 0x0D,
|
||||||
|
@ -105,7 +105,7 @@ private:
|
||||||
CMD_MIX_AUXC_OLD = 0x08,
|
CMD_MIX_AUXC_OLD = 0x08,
|
||||||
CMD_UPL_AUXA_MIX_LRSC_OLD = 0x09,
|
CMD_UPL_AUXA_MIX_LRSC_OLD = 0x09,
|
||||||
CMD_UPL_AUXB_MIX_LRSC_OLD = 0x0a,
|
CMD_UPL_AUXB_MIX_LRSC_OLD = 0x0a,
|
||||||
CMD_UNK_0B_OLD = 0x0B,
|
CMD_COMPRESSOR_OLD = 0x0B,
|
||||||
CMD_OUTPUT_OLD = 0x0C, // no volume!
|
CMD_OUTPUT_OLD = 0x0C, // no volume!
|
||||||
CMD_OUTPUT_DPL2_OLD = 0x0D,
|
CMD_OUTPUT_DPL2_OLD = 0x0D,
|
||||||
CMD_WM_OUTPUT_OLD = 0x0E,
|
CMD_WM_OUTPUT_OLD = 0x0E,
|
||||||
|
|
Loading…
Reference in New Issue