mirror of
https://github.com/libretro/Play-.git
synced 2025-02-25 14:10:50 +00:00
SPU: Added support for linear volume sweeping.
git-svn-id: http://svn.purei.org/purei/trunk@1041 b36208d7-6611-0410-8bec-b1987f11c4a2
This commit is contained in:
parent
5d91889dc4
commit
7c8db60731
@ -290,6 +290,12 @@ uint32 CCore::ReadRegisterChannel(unsigned int channelId, uint32 address, uint32
|
||||
case VP_ENVX:
|
||||
result = (channel.adsrVolume >> 16);
|
||||
break;
|
||||
case VP_VOLXL:
|
||||
result = (channel.volumeLeftAbs >> 16);
|
||||
break;
|
||||
case VP_VOLXR:
|
||||
result = (channel.volumeRightAbs >> 16);
|
||||
break;
|
||||
case VA_SSA_HI:
|
||||
result = GetAddressHi(channel.address);
|
||||
break;
|
||||
@ -320,9 +326,17 @@ uint32 CCore::WriteRegisterChannel(unsigned int channelId, uint32 address, uint3
|
||||
{
|
||||
case VP_VOLL:
|
||||
channel.volumeLeft <<= static_cast<uint16>(value);
|
||||
if(channel.volumeLeft.mode.mode == 0)
|
||||
{
|
||||
channel.volumeLeftAbs = channel.volumeLeft.volume.volume << 17;
|
||||
}
|
||||
break;
|
||||
case VP_VOLR:
|
||||
channel.volumeRight <<= static_cast<uint16>(value);
|
||||
if(channel.volumeRight.mode.mode == 0)
|
||||
{
|
||||
channel.volumeRightAbs = channel.volumeRight.volume.volume << 17;
|
||||
}
|
||||
break;
|
||||
case VP_PITCH:
|
||||
channel.pitch = static_cast<uint16>(value);
|
||||
@ -336,12 +350,6 @@ uint32 CCore::WriteRegisterChannel(unsigned int channelId, uint32 address, uint3
|
||||
case VP_ENVX:
|
||||
channel.adsrVolume = static_cast<uint16>(value);
|
||||
break;
|
||||
case VP_VOLXL:
|
||||
// channel.volxLeft = static_cast<uint16>(value);
|
||||
break;
|
||||
case VP_VOLXR:
|
||||
// channel.volxRight = static_cast<uint16>(value);
|
||||
break;
|
||||
case VA_SSA_HI:
|
||||
channel.address = SetAddressHi(channel.address, static_cast<uint16>(value));
|
||||
break;
|
||||
@ -472,6 +480,14 @@ void CCore::LogChannelRead(unsigned int channelId, uint32 address, uint32 result
|
||||
CLog::GetInstance().Print(logName, "ch%0.2i: = VP_ENVX = 0x%0.4X.\r\n",
|
||||
channelId, result);
|
||||
break;
|
||||
case VP_VOLXL:
|
||||
CLog::GetInstance().Print(logName, "ch%0.2i: = VP_VOLXL = 0x%0.4X.\r\n",
|
||||
channelId, result);
|
||||
break;
|
||||
case VP_VOLXR:
|
||||
CLog::GetInstance().Print(logName, "ch%0.2i: = VP_VOLXR = 0x%0.4X.\r\n",
|
||||
channelId, result);
|
||||
break;
|
||||
case VA_SSA_HI:
|
||||
CLog::GetInstance().Print(logName, "ch%0.2i: = VA_SSA_HI = %0.4X.\r\n",
|
||||
channelId, result);
|
||||
|
@ -45,6 +45,46 @@ bool CSpuBase::g_reverbParamIsAddress[REVERB_PARAM_COUNT] =
|
||||
false
|
||||
};
|
||||
|
||||
const uint32 CSpuBase::g_linearIncreaseSweepDeltas[0x80] =
|
||||
{
|
||||
0x3A0CC55E, 0x305FF9CE, 0x2976D61E, 0x203FFBDE, 0x1D0662AF, 0x182FFCE7, 0x1359971F, 0x101FFDEF,
|
||||
0x0DD2475F, 0x0C17FE73, 0x0A0233AF, 0x080FFEF7, 0x07144A05, 0x060BFF39, 0x050119D7, 0x03F9DC6C,
|
||||
0x037F3A27, 0x02FE04E5, 0x026B32E3, 0x01EF5BE9, 0x01B514DD, 0x018712AA, 0x01430F6B, 0x0100385E,
|
||||
0x00E129C7, 0x00BE85CF, 0x00A187B5, 0x00801C2F, 0x007094E3, 0x00607F9E, 0x004FE588, 0x003DEB7D,
|
||||
0x00392824, 0x00318930, 0x00271B77, 0x00204E57, 0x001B851B, 0x0017F80F, 0x00141506, 0x0010272B,
|
||||
0x000E0504, 0x000BFC07, 0x000A0A83, 0x0007FD5A, 0x0006C140, 0x00063126, 0x0004F41E, 0x0003E925,
|
||||
0x000389CC, 0x0002F8DF, 0x00027A0F, 0x0002021A, 0x0001C4E6, 0x00017C6F, 0x00014267, 0x0001010D,
|
||||
0x0000DFC9, 0x0000C023, 0x00009E83, 0x00007ECF, 0x00006FE4, 0x00005F1B, 0x00004F41, 0x00003F67,
|
||||
0x000037F2, 0x00002F8D, 0x000027A0, 0x0000203D, 0x00001BF9, 0x00001814, 0x00001405, 0x00000FD9,
|
||||
0x00000D96, 0x00000BE3, 0x00000A02, 0x000007EC, 0x0000070B, 0x000005F1, 0x00000501, 0x000003F6,
|
||||
0x00000385, 0x00000304, 0x00000280, 0x00000200, 0x000001BE, 0x0000017F, 0x00000140, 0x00000100,
|
||||
0x000000DF, 0x000000BF, 0x000000A0, 0x00000080, 0x0000006F, 0x0000005F, 0x00000050, 0x00000040,
|
||||
0x00000037, 0x0000002F, 0x00000028, 0x00000020, 0x0000001B, 0x00000017, 0x00000014, 0x00000010,
|
||||
0x0000000D, 0x0000000B, 0x0000000A, 0x00000008, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
|
||||
};
|
||||
|
||||
const uint32 CSpuBase::g_linearDecreaseSweepDeltas[0x80] =
|
||||
{
|
||||
0x488FF6B5, 0x3A0CC55E, 0x305FF9CE, 0x2976D61E, 0x203FFBDE, 0x1D0662AF, 0x182FFCE7, 0x1359971F,
|
||||
0x101FFDEF, 0x0DD2475F, 0x0C17FE73, 0x0A0233AF, 0x080FFEF7, 0x07144A05, 0x060BFF39, 0x050119D7,
|
||||
0x03F9DC6C, 0x037F3A27, 0x02FE04E5, 0x026B32E3, 0x01EF5BE9, 0x01B514DD, 0x018712AA, 0x01430F6B,
|
||||
0x0100385E, 0x00E129C7, 0x00BE85CF, 0x00A187B5, 0x00801C2F, 0x007094E3, 0x00607F9E, 0x004FE588,
|
||||
0x003DEB7D, 0x00392824, 0x00318930, 0x00271B77, 0x00204E57, 0x001B851B, 0x0017F80F, 0x00141506,
|
||||
0x0010272B, 0x000E0504, 0x000BFC07, 0x000A0A83, 0x0007FD5A, 0x0006C140, 0x00063126, 0x0004F41E,
|
||||
0x0003E925, 0x000389CC, 0x0002F8DF, 0x00027A0F, 0x0002021A, 0x0001C4E6, 0x00017C6F, 0x00014267,
|
||||
0x0001010D, 0x0000DFC9, 0x0000C023, 0x00009E83, 0x00007ECF, 0x00006FE4, 0x00005F1B, 0x00004F41,
|
||||
0x00003F67, 0x000037F2, 0x00002F8D, 0x000027A0, 0x0000203D, 0x00001BF9, 0x00001814, 0x00001405,
|
||||
0x00000FD9, 0x00000D96, 0x00000BE3, 0x00000A02, 0x000007EC, 0x0000070B, 0x000005F1, 0x00000501,
|
||||
0x000003F6, 0x00000385, 0x00000304, 0x00000280, 0x00000200, 0x000001BE, 0x0000017F, 0x00000140,
|
||||
0x00000100, 0x000000DF, 0x000000BF, 0x000000A0, 0x00000080, 0x0000006F, 0x0000005F, 0x00000050,
|
||||
0x00000040, 0x00000037, 0x0000002F, 0x00000028, 0x00000020, 0x0000001B, 0x00000017, 0x00000014,
|
||||
0x00000010, 0x0000000D, 0x0000000B, 0x0000000A, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
|
||||
};
|
||||
|
||||
CSpuBase::CSpuBase(uint8* ram, uint32 ramSize)
|
||||
: m_ram(ram)
|
||||
, m_ramSize(ramSize)
|
||||
@ -313,7 +353,7 @@ void CSpuBase::WriteWord(uint16 value)
|
||||
m_bufferAddr += 2;
|
||||
}
|
||||
|
||||
int32 CSpuBase::ComputeChannelVolume(const CHANNEL_VOLUME& volume)
|
||||
int32 CSpuBase::ComputeChannelVolume(const CHANNEL_VOLUME& volume, int32 currentVolume)
|
||||
{
|
||||
int32 volumeLevel = 0;
|
||||
if(!volume.mode.mode)
|
||||
@ -326,18 +366,31 @@ int32 CSpuBase::ComputeChannelVolume(const CHANNEL_VOLUME& volume)
|
||||
{
|
||||
volumeLevel = volume.volume.volume;
|
||||
}
|
||||
volumeLevel <<= 17;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0);
|
||||
assert(volume.sweep.phase == 0);
|
||||
assert(volume.sweep.slope == 0);
|
||||
if(volume.sweep.decrease)
|
||||
{
|
||||
uint32 sweepDelta = g_linearDecreaseSweepDeltas[volume.sweep.volume];
|
||||
volumeLevel = currentVolume - sweepDelta;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 sweepDelta = g_linearIncreaseSweepDeltas[volume.sweep.volume];
|
||||
volumeLevel = currentVolume + sweepDelta;
|
||||
}
|
||||
volumeLevel = std::max<int32>(volumeLevel, 0x00000000);
|
||||
volumeLevel = std::min<int32>(volumeLevel, 0x7FFFFFFF);
|
||||
}
|
||||
volumeLevel = std::min<int32>(0x3FFF, static_cast<int32>(static_cast<float>(volumeLevel) * m_volumeAdjust));
|
||||
return volumeLevel;
|
||||
}
|
||||
|
||||
void CSpuBase::MixSamples(int32 inputSample, int32 volumeLevel, int16* output)
|
||||
{
|
||||
inputSample = (inputSample * volumeLevel) / 0x3FFF;
|
||||
inputSample = (inputSample * volumeLevel) / 0x7FFF;
|
||||
int32 resultSample = inputSample + static_cast<int32>(*output);
|
||||
resultSample = std::max<int32>(resultSample, SHRT_MIN);
|
||||
resultSample = std::min<int32>(resultSample, SHRT_MAX);
|
||||
@ -351,14 +404,6 @@ void CSpuBase::Render(int16* samples, unsigned int sampleCount, unsigned int sam
|
||||
unsigned int ticks = sampleCount / 2;
|
||||
memset(samples, 0, sizeof(int16) * sampleCount);
|
||||
|
||||
//Precompute volume values
|
||||
for(unsigned int i = 0; i < 24; i++)
|
||||
{
|
||||
CHANNEL& channel(m_channel[i]);
|
||||
channel.volumeLeftAbs = ComputeChannelVolume(channel.volumeLeft);
|
||||
channel.volumeRightAbs = ComputeChannelVolume(channel.volumeRight);
|
||||
}
|
||||
|
||||
for(unsigned int j = 0; j < ticks; j++)
|
||||
{
|
||||
int16 reverbSample[2] = { 0, 0 };
|
||||
@ -401,13 +446,19 @@ void CSpuBase::Render(int16* samples, unsigned int sampleCount, unsigned int sam
|
||||
{
|
||||
inputSample = (inputSample * static_cast<int32>(channel.adsrVolume >> 16)) / static_cast<int32>(MAX_ADSR_VOLUME >> 16);
|
||||
}
|
||||
MixSamples(inputSample, channel.volumeLeftAbs, samples + 0);
|
||||
MixSamples(inputSample, channel.volumeRightAbs, samples + 1);
|
||||
|
||||
channel.volumeLeftAbs = ComputeChannelVolume(channel.volumeLeft, channel.volumeLeftAbs);
|
||||
channel.volumeRightAbs = ComputeChannelVolume(channel.volumeRight, channel.volumeRightAbs);
|
||||
|
||||
int32 adjustedLeftVolume = std::min<int32>(0x7FFF, static_cast<int32>(static_cast<float>(channel.volumeLeftAbs >> 16) * m_volumeAdjust));
|
||||
int32 adjustedRightVolume = std::min<int32>(0x7FFF, static_cast<int32>(static_cast<float>(channel.volumeRightAbs >> 16) * m_volumeAdjust));
|
||||
MixSamples(inputSample, adjustedLeftVolume, samples + 0);
|
||||
MixSamples(inputSample, adjustedRightVolume, samples + 1);
|
||||
//Mix in reverb if enabled for this channel
|
||||
if(m_reverbEnabled && (m_channelReverb.f & (1 << i)))
|
||||
{
|
||||
MixSamples(inputSample, channel.volumeLeftAbs, reverbSample + 0);
|
||||
MixSamples(inputSample, channel.volumeRightAbs, reverbSample + 1);
|
||||
MixSamples(inputSample, adjustedLeftVolume, reverbSample + 0);
|
||||
MixSamples(inputSample, adjustedRightVolume, reverbSample + 1);
|
||||
}
|
||||
}
|
||||
//Update reverb
|
||||
|
@ -252,7 +252,10 @@ namespace Iop
|
||||
float GetReverbCoef(unsigned int) const;
|
||||
|
||||
static void MixSamples(int32, int32, int16*);
|
||||
int32 ComputeChannelVolume(const CHANNEL_VOLUME&);
|
||||
int32 ComputeChannelVolume(const CHANNEL_VOLUME&, int32);
|
||||
|
||||
static const uint32 g_linearIncreaseSweepDeltas[0x80];
|
||||
static const uint32 g_linearDecreaseSweepDeltas[0x80];
|
||||
|
||||
uint8* m_ram;
|
||||
uint32 m_ramSize;
|
||||
|
Loading…
x
Reference in New Issue
Block a user