mirror of
https://github.com/grumpycoders/pcsx-redux.git
synced 2024-05-16 19:11:04 -04:00
Dr. Hell noise generator
This commit is contained in:
parent
94e5216579
commit
ba04d30728
1
AUTHORS
1
AUTHORS
|
@ -75,5 +75,6 @@ smf
|
|||
iCatButler
|
||||
Neill Corlett
|
||||
Vincent "Yaz0r" Hamm
|
||||
Dokta Jigokusai / Dr. Hell
|
||||
|
||||
)"
|
||||
|
|
|
@ -125,8 +125,14 @@ typedef Protobuf::Field<Protobuf::Int32, TYPESTRING("cbVoiceInd"), 13> CBVoiceIn
|
|||
typedef Protobuf::Field<Protobuf::FixedBytes<1024 * 16 * 2>, TYPESTRING("CBLeft"), 14> CBCDLeft;
|
||||
typedef Protobuf::Field<Protobuf::FixedBytes<1024 * 16 * 2>, TYPESTRING("CBRight"), 15> CBCDRight;
|
||||
|
||||
// global noise generator
|
||||
typedef Protobuf::Field<Protobuf::UInt32, TYPESTRING("noiseClock"), 16> SPUNoiseClock;
|
||||
typedef Protobuf::Field<Protobuf::UInt32, TYPESTRING("noiseCount"), 17> SPUNoiseCount;
|
||||
typedef Protobuf::Field<Protobuf::UInt32, TYPESTRING("noiseVal"), 18> SPUNoiseVal;
|
||||
|
||||
typedef Protobuf::Message<TYPESTRING("SPU"), SPURam, SPUPorts, XAField, SPUIrq, SPUIrqPtr, Channels, SPUAddr, SPUCtrl,
|
||||
SPUStat, CBStartIndex, CBCurrIndex, CBEndIndex, CBVoiceIndex, CBCDLeft, CBCDRight>
|
||||
SPUStat, CBStartIndex, CBCurrIndex, CBEndIndex, CBVoiceIndex, CBCDLeft, CBCDRight,
|
||||
SPUNoiseClock, SPUNoiseCount, SPUNoiseVal>
|
||||
SPU;
|
||||
typedef Protobuf::MessageField<SPU, TYPESTRING("spu"), 6> SPUField;
|
||||
|
||||
|
|
|
@ -83,6 +83,10 @@ void PCSX::SPU::impl::save(SaveStates::SPU &spu) {
|
|||
spu.get<SaveStates::SPUCtrl>().value = spuCtrl;
|
||||
spu.get<SaveStates::SPUStat>().value = spuStat;
|
||||
|
||||
spu.get<SaveStates::SPUNoiseClock>().value = m_noiseClock;
|
||||
spu.get<SaveStates::SPUNoiseCount>().value = m_noiseCount;
|
||||
spu.get<SaveStates::SPUNoiseVal>().value = m_noiseVal;
|
||||
|
||||
SetupThread();
|
||||
}
|
||||
|
||||
|
@ -131,6 +135,10 @@ void PCSX::SPU::impl::load(const SaveStates::SPU &spu) {
|
|||
spuCtrl = spu.get<SaveStates::SPUCtrl>().value;
|
||||
spuStat = spu.get<SaveStates::SPUStat>().value;
|
||||
|
||||
m_noiseClock = spu.get<SaveStates::SPUNoiseClock>().value;
|
||||
m_noiseCount = spu.get<SaveStates::SPUNoiseCount>().value;
|
||||
m_noiseVal = spu.get<SaveStates::SPUNoiseVal>().value;
|
||||
|
||||
// repair some globals
|
||||
for (unsigned i = 0; i <= 62; i += 2) writeRegister(H_Reverb + i, regArea[(H_Reverb + i - 0xc00) >> 1]);
|
||||
writeRegister(H_SPUReverbAddr, regArea[(H_SPUReverbAddr - 0xc00) >> 1]);
|
||||
|
|
|
@ -138,6 +138,7 @@ class impl final : public SPUInterface {
|
|||
int iGetNoiseVal(SPUCHAN *pChannel);
|
||||
void StoreInterpolationVal(SPUCHAN *pChannel, int fa);
|
||||
int iGetInterpolationVal(SPUCHAN *pChannel);
|
||||
void NoiseClock();
|
||||
|
||||
// registers
|
||||
void SoundOn(int start, int end, uint16_t val);
|
||||
|
@ -199,7 +200,9 @@ class impl final : public SPUInterface {
|
|||
SPUCHAN s_chan[MAXCHAN + 1]; // channel + 1 infos (1 is security for fmod handling)
|
||||
REVERBInfo rvb;
|
||||
|
||||
uint32_t dwNoiseVal = 1; // global noise generator
|
||||
uint32_t m_noiseClock = 0; // global noise generator
|
||||
uint32_t m_noiseCount = 0; // global noise generator
|
||||
uint32_t m_noiseVal = 1; // global noise generator
|
||||
|
||||
uint16_t spuCtrl = 0; // some vars to store psx reg infos
|
||||
uint16_t spuStat = 0;
|
||||
|
|
|
@ -195,6 +195,7 @@ void PCSX::SPU::impl::writeRegister(uint32_t reg, uint16_t val) {
|
|||
|
||||
case H_SPUctrl:
|
||||
spuCtrl = val;
|
||||
m_noiseClock = (spuCtrl & (ControlFlags::NoiseShift | ControlFlags::NoiseStep)) >> 8;
|
||||
break;
|
||||
|
||||
case H_SPUstat:
|
||||
|
|
|
@ -291,23 +291,7 @@ inline void PCSX::SPU::impl::FModChangeFrequency(SPUCHAN *pChannel, int ns) {
|
|||
|
||||
inline int PCSX::SPU::impl::iGetNoiseVal(SPUCHAN *pChannel) {
|
||||
auto &SB = pChannel->data.get<PCSX::SPU::Chan::SB>().value;
|
||||
int fa;
|
||||
|
||||
if ((dwNoiseVal <<= 1) & 0x80000000L) {
|
||||
dwNoiseVal ^= 0x0040001L;
|
||||
fa = ((dwNoiseVal >> 2) & 0x7fff);
|
||||
fa = -fa;
|
||||
} else
|
||||
fa = (dwNoiseVal >> 2) & 0x7fff;
|
||||
|
||||
static constexpr uint16_t noiseMask = ControlFlags::NoiseShift | ControlFlags::NoiseStep;
|
||||
|
||||
// mmm... depending on the noise freq we allow bigger/smaller changes to the previous val
|
||||
fa = pChannel->data.get<PCSX::SPU::Chan::OldNoise>().value +
|
||||
((fa - pChannel->data.get<PCSX::SPU::Chan::OldNoise>().value) / ((0x001f - ((spuCtrl & noiseMask) >> 9)) + 1));
|
||||
if (fa > 32767L) fa = 32767L;
|
||||
if (fa < -32767L) fa = -32767L;
|
||||
pChannel->data.get<PCSX::SPU::Chan::OldNoise>().value = fa;
|
||||
const int fa = (int16_t)m_noiseVal;
|
||||
|
||||
if (settings.get<Interpolation>() < 2) // no gauss/cubic interpolation?
|
||||
SB[29].value = fa; // -> store noise val in "current sample" slot
|
||||
|
@ -316,6 +300,40 @@ inline int PCSX::SPU::impl::iGetNoiseVal(SPUCHAN *pChannel) {
|
|||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void PCSX::SPU::impl::NoiseClock() {
|
||||
// Noise Waveform - Dr. Hell (Xebra)
|
||||
static constexpr char NoiseWaveAdd[64] = {1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1,
|
||||
1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||
1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1};
|
||||
|
||||
static constexpr unsigned short NoiseFreqAdd[5] = {0, 84, 140, 180, 210};
|
||||
|
||||
unsigned int level;
|
||||
|
||||
level = 0x8000 >> (m_noiseClock >> 2);
|
||||
level <<= 16;
|
||||
|
||||
m_noiseCount += 0x10000;
|
||||
|
||||
// Dr. Hell - fraction
|
||||
m_noiseCount += NoiseFreqAdd[m_noiseClock & 3];
|
||||
if ((m_noiseCount & 0xffff) >= NoiseFreqAdd[4]) {
|
||||
m_noiseCount += 0x10000;
|
||||
m_noiseCount -= NoiseFreqAdd[m_noiseClock & 3];
|
||||
}
|
||||
|
||||
if (m_noiseCount >= level) {
|
||||
while (m_noiseCount >= level) {
|
||||
m_noiseCount -= level;
|
||||
}
|
||||
|
||||
// Dr. Hell - form
|
||||
m_noiseVal = (m_noiseVal << 1) | NoiseWaveAdd[(m_noiseVal >> 10) & 63];
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline void PCSX::SPU::impl::StoreInterpolationVal(SPUCHAN *pChannel, int fa) {
|
||||
auto &SB = pChannel->data.get<PCSX::SPU::Chan::SB>().value;
|
||||
if (pChannel->data.get<PCSX::SPU::Chan::FMod>().value == 2) // fmod freq channel
|
||||
|
@ -510,6 +528,8 @@ void PCSX::SPU::impl::MainThread() {
|
|||
|
||||
while (ns < NSSIZE) // loop until 1 ms of data is reached
|
||||
{
|
||||
NoiseClock();
|
||||
|
||||
if (pChannel->data.get<PCSX::SPU::Chan::FMod>().value == 1 && iFMod[ns]) // fmod freq channel
|
||||
FModChangeFrequency(pChannel, ns);
|
||||
|
||||
|
|
|
@ -124,12 +124,11 @@ typedef Protobuf::Field<Protobuf::Bool, TYPESTRING("noise"), 28> Noise;
|
|||
typedef Protobuf::Field<Protobuf::Int32, TYPESTRING("fmod"), 29> FMod;
|
||||
// another reverb helper
|
||||
typedef Protobuf::Field<Protobuf::Int32, TYPESTRING("rvb_num"), 30> RVBNum;
|
||||
// old noise val for this channel
|
||||
typedef Protobuf::Field<Protobuf::Int32, TYPESTRING("old_noise"), 31> OldNoise;
|
||||
// skip id 31
|
||||
typedef Protobuf::Message<TYPESTRING("ChannelData"), New, SBPos, spos, sinc, SB, sval, StartPtr, CurrPtr, LoopPtr, On,
|
||||
Stop, Reverb, ActFreq, UsedFreq, LeftVolume, LeftVolRaw, IgnoreLoop, Mute, RightVolume,
|
||||
RightVolRaw, RawPitch, IrqDone, s_1, s_2, RVBActive, RVBOffset, RVBRepeat, Noise, FMod,
|
||||
RVBNum, OldNoise>
|
||||
RVBNum>
|
||||
Data;
|
||||
} // namespace Chan
|
||||
|
||||
|
|
Loading…
Reference in a new issue