From dd307445755a834dd9a06b7a94a33b7e334c8c20 Mon Sep 17 00:00:00 2001 From: jpd002 Date: Fri, 8 Aug 2008 21:52:31 +0000 Subject: [PATCH] git-svn-id: http://svn.purei.org/purei/trunk@358 b36208d7-6611-0410-8bec-b1987f11c4a2 --- tools/PsfPlayer2/Source/Main.cpp | 3 +- tools/PsfPlayer2/Source/Spu.cpp | 116 ++++++++++++++++++++++++- tools/PsfPlayer2/Source/Spu.h | 10 ++- tools/PsfPlayer2/Source/SpuRegView.cpp | 27 +++++- tools/PsfPlayer2/Tester.vcproj | 8 +- 5 files changed, 152 insertions(+), 12 deletions(-) diff --git a/tools/PsfPlayer2/Source/Main.cpp b/tools/PsfPlayer2/Source/Main.cpp index 3f8ccc70..5868094d 100644 --- a/tools/PsfPlayer2/Source/Main.cpp +++ b/tools/PsfPlayer2/Source/Main.cpp @@ -6,7 +6,8 @@ using namespace Framework; using namespace Psx; -int main(int argc, char** argv) +//int main(int argc, char** argv) +int WINAPI WinMain(HINSTANCE, HINSTANCE, char*, int) { CPsxVm virtualMachine; diff --git a/tools/PsfPlayer2/Source/Spu.cpp b/tools/PsfPlayer2/Source/Spu.cpp index 40681f01..27a7e7c4 100644 --- a/tools/PsfPlayer2/Source/Spu.cpp +++ b/tools/PsfPlayer2/Source/Spu.cpp @@ -135,6 +135,7 @@ void CSpu::Render(int16* samples, unsigned int sampleCount, unsigned int sampleR { reader.SetParams(m_ram + (channel.address * 8), m_ram + (channel.repeat * 8)); channel.status = ATTACK; + channel.adsrVolume = 0; } reader.SetPitch(channel.pitch); reader.GetSamples(bufferTemp, ticks, sampleRate); @@ -143,11 +144,13 @@ void CSpu::Render(int16* samples, unsigned int sampleCount, unsigned int sampleR for(unsigned int j = 0; j < ticks; j++) { if(channel.status == STOPPED) break; - if(channel.status == RELEASE) - { - channel.status = STOPPED; - } + UpdateAdsr(channel); int32 inputSample = static_cast(bufferTemp[j]); + //Mix adsrVolume + { + int64 result = (static_cast(inputSample) * static_cast(channel.adsrVolume)) / static_cast(MAX_ADSR_VOLUME); + inputSample = static_cast(result); + } struct SampleMixer { void operator() (int32 inputSample, const CHANNEL_VOLUME& volume, int16*& output) const @@ -386,6 +389,111 @@ void CSpu::DisassembleWrite(uint32 address, uint16 value) } } +uint32 CSpu::GetAdsrDelta(unsigned int index) const +{ + return m_adsrLogTable[index + 32]; +} + +void CSpu::UpdateAdsr(CHANNEL& channel) +{ + static unsigned int logIndex[8] = { 0, 4, 6, 8, 9, 10, 11, 12 }; + int64 currentAdsrLevel = channel.adsrVolume; + if(channel.status == ATTACK) + { + if(channel.adsrLevel.attackMode == 0) + { + //Linear mode + currentAdsrLevel += GetAdsrDelta((channel.adsrLevel.attackRate ^ 0x7F) - 0x10); + } + else + { + if(currentAdsrLevel < 0x60000000) + { + currentAdsrLevel += GetAdsrDelta((channel.adsrLevel.attackRate ^ 0x7F) - 0x10); + } + else + { + currentAdsrLevel += GetAdsrDelta((channel.adsrLevel.attackRate ^ 0x7F) - 0x18); + } + } + //Terminasion condition + if(currentAdsrLevel >= MAX_ADSR_VOLUME) + { + channel.status = DECAY; + } + } + else if(channel.status == DECAY) + { + unsigned int decayType = (static_cast(currentAdsrLevel) >> 28) & 0x7; + currentAdsrLevel -= GetAdsrDelta((4 * (channel.adsrLevel.decayRate ^ 0x1F)) - 0x18 + logIndex[decayType]); + //Terminasion condition + if(((currentAdsrLevel >> 27) & 0xF) <= channel.adsrLevel.sustainLevel) + { + channel.status = SUSTAIN; + } + } + else if(channel.status == SUSTAIN) + { + if(channel.adsrRate.sustainDirection == 0) + { + //Increment + if(channel.adsrRate.sustainMode == 0) + { + currentAdsrLevel += GetAdsrDelta((channel.adsrRate.sustainRate ^ 0x7F) - 0x10); + } + else + { + if(currentAdsrLevel < 0x60000000) + { + currentAdsrLevel += GetAdsrDelta((channel.adsrRate.sustainRate ^ 0x7F) - 0x10); + } + else + { + currentAdsrLevel += GetAdsrDelta((channel.adsrRate.sustainRate ^ 0x7F) - 0x18); + } + } + } + else + { + //Decrement + if(channel.adsrRate.sustainMode == 0) + { + //Linear + currentAdsrLevel -= GetAdsrDelta((channel.adsrRate.sustainRate ^ 0x7F) - 0x0F); + } + else + { + unsigned int sustainType = (static_cast(currentAdsrLevel) >> 28) & 0x7; + currentAdsrLevel -= GetAdsrDelta((channel.adsrRate.sustainRate ^ 0x7F) - 0x1B + logIndex[sustainType]); + } + } + } + else if(channel.status == RELEASE) + { + if(channel.adsrRate.releaseMode == 0) + { + //Linear + currentAdsrLevel -= GetAdsrDelta((4 * (channel.adsrRate.releaseRate ^ 0x1F)) - 0x0C); + } + else + { + unsigned int releaseType = (static_cast(currentAdsrLevel) >> 28) & 0x7; + currentAdsrLevel -= GetAdsrDelta((4 * (channel.adsrRate.releaseRate ^ 0x1F)) - 0x18 + logIndex[releaseType]); + } + + if(currentAdsrLevel <= 0) + { + channel.status = STOPPED; + } + } + currentAdsrLevel = min(currentAdsrLevel, MAX_ADSR_VOLUME); + currentAdsrLevel = max(currentAdsrLevel, 0); + channel.adsrVolume = static_cast(currentAdsrLevel); +} + +/////////////////////////////////////////////////////// +// CSampleReader +/////////////////////////////////////////////////////// CSpu::CSampleReader::CSampleReader() : m_nextSample(NULL) diff --git a/tools/PsfPlayer2/Source/Spu.h b/tools/PsfPlayer2/Source/Spu.h index 1b886643..7106e35c 100644 --- a/tools/PsfPlayer2/Source/Spu.h +++ b/tools/PsfPlayer2/Source/Spu.h @@ -64,7 +64,7 @@ public: uint16 address; ADSR_LEVEL adsrLevel; ADSR_RATE adsrRate; - int32 adsrVolume; + uint32 adsrVolume; uint16 repeat; uint16 status; }; @@ -225,12 +225,20 @@ private: RAMSIZE = 0x80000 }; + enum + { + MAX_ADSR_VOLUME = 0x7FFFFFFF, + }; + void SendKeyOn(uint32); void SendKeyOff(uint32); void DisassembleRead(uint32); void DisassembleWrite(uint32, uint16); + void UpdateAdsr(CHANNEL&); + uint32 GetAdsrDelta(unsigned int) const; + uint32 m_bufferAddr; uint16 m_ctrl; uint16 m_status0; diff --git a/tools/PsfPlayer2/Source/SpuRegView.cpp b/tools/PsfPlayer2/Source/SpuRegView.cpp index 378fac63..2fbfb6ef 100644 --- a/tools/PsfPlayer2/Source/SpuRegView.cpp +++ b/tools/PsfPlayer2/Source/SpuRegView.cpp @@ -17,13 +17,14 @@ CSpuRegView::~CSpuRegView() void CSpuRegView::Render() { string text; + char channelStatus[CSpu::MAX_CHANNEL + 1]; //Header text += " VLEFT VRIGH PITCH ADDRE ADSRL ADSRR ADSRV REPEA\r\n"; text += "\r\n"; //Channel detail - for(unsigned int i = 0; i < 24; i++) + for(unsigned int i = 0; i < CSpu::MAX_CHANNEL; i++) { CSpu::CHANNEL& channel(m_spu.GetChannel(i)); uint32 address = CSpu::CH0_BASE + (i * 0x10); @@ -39,11 +40,33 @@ void CSpuRegView::Render() channel.adsrVolume >> 16, channel.repeat); text += temp; + + char status = '0'; + switch(channel.status) + { + case CSpu::ATTACK: + case CSpu::KEY_ON: + status = 'A'; + break; + case CSpu::DECAY: + status = 'D'; + break; + case CSpu::SUSTAIN: + status = 'S'; + break; + case CSpu::RELEASE: + status = 'R'; + break; + } + + channelStatus[i] = status; } + channelStatus[CSpu::MAX_CHANNEL] = 0; + text += "\r\n"; char temp[256]; - sprintf(temp, "CH_ON: 0x%0.8X VO_ON 0x%0.8X\r\n", m_spu.GetChannelOn(), m_spu.GetVoiceOn()); + sprintf(temp, "CH_ON: 0x%0.8X CH_STAT: %s\r\n", m_spu.GetChannelOn(), channelStatus); text += temp; SetDisplayText(text.c_str()); diff --git a/tools/PsfPlayer2/Tester.vcproj b/tools/PsfPlayer2/Tester.vcproj index 33af0c5f..8bf7ff58 100644 --- a/tools/PsfPlayer2/Tester.vcproj +++ b/tools/PsfPlayer2/Tester.vcproj @@ -41,7 +41,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories=""C:\Program Files\OpenAL 1.1 SDK\include";C:\Projects\Rawr\Source;C:\Projects\zlib;C:\Components\boost_1_35_0\boost\tr1\tr1;C:\Components\boost_1_35_0;C:\Projects\Framework\include;C:\Projects\Rawr\tools\PsfPlayer\Source" - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_MSVC" + PreprocessorDefinitions="WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;_MSVC" MinimalRebuild="true" BasicRuntimeChecks="3" RuntimeLibrary="3" @@ -65,7 +65,7 @@ LinkIncremental="2" AdditionalLibraryDirectories=""C:\Program Files\OpenAL 1.1 SDK\libs\Win32";C:\Components\boost_1_35_0\stage\lib" GenerateDebugInformation="true" - SubSystem="1" + SubSystem="2" TargetMachine="1" />