Overclocking: Fix sound pitch for expansion audio when APU overclocking is disabled
This commit is contained in:
parent
9d1f5f61ba
commit
84b4190f8b
12 changed files with 177 additions and 87 deletions
32
Core/BaseExpansionAudio.h
Normal file
32
Core/BaseExpansionAudio.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "Snapshotable.h"
|
||||
#include "EmulationSettings.h"
|
||||
|
||||
class BaseExpansionAudio : public Snapshotable
|
||||
{
|
||||
private:
|
||||
double _clocksNeeded = 0;
|
||||
|
||||
protected:
|
||||
virtual void ClockAudio() = 0;
|
||||
|
||||
void StreamState(bool saving)
|
||||
{
|
||||
Stream(_clocksNeeded);
|
||||
}
|
||||
|
||||
public:
|
||||
void Clock()
|
||||
{
|
||||
if(EmulationSettings::GetOverclockRate() == 100 || !EmulationSettings::GetOverclockAdjustApu()) {
|
||||
ClockAudio();
|
||||
} else {
|
||||
_clocksNeeded += 1.0 / ((double)EmulationSettings::GetOverclockRate() / 100);
|
||||
while(_clocksNeeded >= 1.0) {
|
||||
ClockAudio();
|
||||
_clocksNeeded--;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
|
@ -386,6 +386,7 @@
|
|||
<ClInclude Include="ArkanoidController.h" />
|
||||
<ClInclude Include="AutoRomTest.h" />
|
||||
<ClInclude Include="Bandai74161_7432.h" />
|
||||
<ClInclude Include="BaseExpansionAudio.h" />
|
||||
<ClInclude Include="BaseFdsChannel.h" />
|
||||
<ClInclude Include="BaseMapper.h" />
|
||||
<ClInclude Include="BaseSoundFilter.h" />
|
||||
|
@ -553,6 +554,7 @@
|
|||
<ClInclude Include="VRC2_4.h" />
|
||||
<ClInclude Include="VRC3.h" />
|
||||
<ClInclude Include="VRC6.h" />
|
||||
<ClInclude Include="Vrc6Audio.h" />
|
||||
<ClInclude Include="Vrc6Pulse.h" />
|
||||
<ClInclude Include="Vrc6Saw.h" />
|
||||
<ClInclude Include="VRC7.h" />
|
||||
|
|
|
@ -613,6 +613,12 @@
|
|||
<ClInclude Include="MMC5Audio.h">
|
||||
<Filter>Nes\Mappers\MMC</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="BaseExpansionAudio.h">
|
||||
<Filter>Nes\Mappers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Vrc6Audio.h">
|
||||
<Filter>Nes\Mappers\VRC</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
|
|
|
@ -6,8 +6,9 @@
|
|||
#include "BaseFdsChannel.h"
|
||||
#include "ModChannel.h"
|
||||
#include <algorithm>
|
||||
#include "BaseExpansionAudio.h"
|
||||
|
||||
class FdsAudio : public Snapshotable
|
||||
class FdsAudio : public BaseExpansionAudio
|
||||
{
|
||||
private:
|
||||
const uint32_t WaveVolumeTable[4] = { 36, 24, 17, 14 };
|
||||
|
@ -34,6 +35,8 @@ private:
|
|||
protected:
|
||||
void StreamState(bool saving)
|
||||
{
|
||||
BaseExpansionAudio::StreamState(saving);
|
||||
|
||||
ArrayInfo<uint8_t> waveTable = { _waveTable, 64 };
|
||||
SnapshotInfo volume{ &_volume };
|
||||
SnapshotInfo mod{ &_mod };
|
||||
|
@ -41,8 +44,7 @@ protected:
|
|||
Stream(volume, mod, _waveWriteEnabled, _disableEnvelopes, _haltWaveform, _masterVolume, _waveOverflowCounter, _wavePitch, _wavePosition, _lastOutput, waveTable);
|
||||
}
|
||||
|
||||
public:
|
||||
void Clock()
|
||||
void ClockAudio()
|
||||
{
|
||||
//"The envelopes are not ticked while the waveform is halted."
|
||||
_volume.TickEnvelope(_disableEnvelopes || _haltWaveform);
|
||||
|
@ -79,6 +81,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
public:
|
||||
uint8_t ReadRegister(uint16_t addr)
|
||||
{
|
||||
if(addr <= 0x407F) {
|
||||
|
|
|
@ -170,7 +170,7 @@ private:
|
|||
_ppuInFrame = false;
|
||||
}
|
||||
|
||||
_audio.ProcessCpuClock();
|
||||
_audio.Clock();
|
||||
}
|
||||
|
||||
virtual void NotifyVRAMAddressChange(uint16_t addr)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "SquareChannel.h"
|
||||
#include "BaseExpansionAudio.h"
|
||||
|
||||
class MMC5Square : public SquareChannel
|
||||
{
|
||||
|
@ -40,7 +41,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class MMC5Audio : public Snapshotable
|
||||
class MMC5Audio : public BaseExpansionAudio
|
||||
{
|
||||
private:
|
||||
MMC5Square _square1;
|
||||
|
@ -55,29 +56,21 @@ private:
|
|||
protected:
|
||||
void StreamState(bool saving)
|
||||
{
|
||||
BaseExpansionAudio::StreamState(saving);
|
||||
|
||||
SnapshotInfo square1{ &_square1 };
|
||||
SnapshotInfo square2{ &_square2 };
|
||||
Stream(square1, square2, _audioCounter, _lastOutput, _pcmReadMode, _pcmIrqEnabled, _pcmOutput);
|
||||
}
|
||||
|
||||
public:
|
||||
MMC5Audio()
|
||||
{
|
||||
_audioCounter = 0;
|
||||
_lastOutput = 0;
|
||||
_pcmReadMode = false;
|
||||
_pcmIrqEnabled = false;
|
||||
_pcmOutput = 0;
|
||||
}
|
||||
|
||||
void ProcessCpuClock()
|
||||
void ClockAudio()
|
||||
{
|
||||
_audioCounter--;
|
||||
_square1.Run();
|
||||
_square2.Run();
|
||||
if(_audioCounter <= 0) {
|
||||
//~240hz envelope/length counter
|
||||
_audioCounter = CPU::GetClockRate(EmulationSettings::GetNesModel()) / 240;
|
||||
_audioCounter = CPU::GetClockRate(EmulationSettings::GetNesModel(), false) / 240;
|
||||
_square1.TickLengthCounter();
|
||||
_square1.TickEnvelope();
|
||||
_square2.TickLengthCounter();
|
||||
|
@ -92,6 +85,16 @@ public:
|
|||
_square2.ReloadCounter();
|
||||
}
|
||||
|
||||
public:
|
||||
MMC5Audio()
|
||||
{
|
||||
_audioCounter = 0;
|
||||
_lastOutput = 0;
|
||||
_pcmReadMode = false;
|
||||
_pcmIrqEnabled = false;
|
||||
_pcmOutput = 0;
|
||||
}
|
||||
|
||||
uint8_t ReadRegister(uint16_t addr)
|
||||
{
|
||||
switch(addr) {
|
||||
|
|
|
@ -103,7 +103,7 @@ protected:
|
|||
}
|
||||
|
||||
if(_variant == NamcoVariant::Namco163) {
|
||||
_audio.ProcessCpuClock();
|
||||
_audio.Clock();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
#include "stdafx.h"
|
||||
#include "Snapshotable.h"
|
||||
#include "APU.h"
|
||||
#include "BaseExpansionAudio.h"
|
||||
|
||||
class Namco163Audio : public Snapshotable
|
||||
class Namco163Audio : public BaseExpansionAudio
|
||||
{
|
||||
private:
|
||||
uint8_t _internalRam[0x80];
|
||||
|
@ -113,25 +114,14 @@ private:
|
|||
protected:
|
||||
void StreamState(bool saving)
|
||||
{
|
||||
BaseExpansionAudio::StreamState(saving);
|
||||
|
||||
ArrayInfo<uint8_t> internalRam{ _internalRam, 0x80 };
|
||||
ArrayInfo<int16_t> channelOutput{ _channelOutput, 8 };
|
||||
Stream(internalRam, channelOutput, _ramPosition, _autoIncrement, _updateCounter, _currentChannel, _lastOutput);
|
||||
}
|
||||
|
||||
public:
|
||||
Namco163Audio()
|
||||
{
|
||||
memset(_internalRam, 0, sizeof(_internalRam));
|
||||
memset(_channelOutput, 0, sizeof(_channelOutput));
|
||||
_ramPosition = 0;
|
||||
_autoIncrement = false;
|
||||
_updateCounter = 0;
|
||||
_currentChannel = 7;
|
||||
_lastOutput = 0;
|
||||
_disableSound = false;
|
||||
}
|
||||
|
||||
void ProcessCpuClock()
|
||||
void ClockAudio()
|
||||
{
|
||||
if(!_disableSound && GetNumberOfChannels()) {
|
||||
_updateCounter++;
|
||||
|
@ -147,6 +137,19 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
public:
|
||||
Namco163Audio()
|
||||
{
|
||||
memset(_internalRam, 0, sizeof(_internalRam));
|
||||
memset(_channelOutput, 0, sizeof(_channelOutput));
|
||||
_ramPosition = 0;
|
||||
_autoIncrement = false;
|
||||
_updateCounter = 0;
|
||||
_currentChannel = 7;
|
||||
_lastOutput = 0;
|
||||
_disableSound = false;
|
||||
}
|
||||
|
||||
void WriteRegister(uint16_t addr, uint8_t value)
|
||||
{
|
||||
switch(addr & 0xF800) {
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
#include "stdafx.h"
|
||||
#include "Snapshotable.h"
|
||||
#include "APU.h"
|
||||
#include "BaseExpansionAudio.h"
|
||||
|
||||
class Sunsoft5bAudio : public Snapshotable
|
||||
class Sunsoft5bAudio : public BaseExpansionAudio
|
||||
{
|
||||
private:
|
||||
uint8_t _volumeLut[0x10];
|
||||
|
@ -74,12 +75,25 @@ private:
|
|||
protected:
|
||||
void StreamState(bool saving)
|
||||
{
|
||||
BaseExpansionAudio::StreamState(saving);
|
||||
|
||||
ArrayInfo<uint16_t> timer{ _timer, 3 };
|
||||
ArrayInfo<uint8_t> registers{ _registers, 0x10 };
|
||||
ArrayInfo<uint8_t> toneStep{ _toneStep, 3 };
|
||||
Stream(timer, registers, toneStep, _currentRegister, _lastOutput, _processTick);
|
||||
}
|
||||
|
||||
void ClockAudio()
|
||||
{
|
||||
if(_processTick) {
|
||||
for(int i = 0; i < 3; i++) {
|
||||
UpdateChannel(i);
|
||||
}
|
||||
UpdateOutputLevel();
|
||||
}
|
||||
_processTick = !_processTick;
|
||||
}
|
||||
|
||||
public:
|
||||
Sunsoft5bAudio()
|
||||
{
|
||||
|
@ -101,17 +115,6 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void ProcessCpuClock()
|
||||
{
|
||||
if(_processTick) {
|
||||
for(int i = 0; i < 3; i++) {
|
||||
UpdateChannel(i);
|
||||
}
|
||||
UpdateOutputLevel();
|
||||
}
|
||||
_processTick = !_processTick;
|
||||
}
|
||||
|
||||
void WriteRegister(uint16_t addr, uint8_t value)
|
||||
{
|
||||
switch(addr & 0xE000) {
|
||||
|
|
|
@ -55,7 +55,7 @@ protected:
|
|||
}
|
||||
}
|
||||
|
||||
_audio.ProcessCpuClock();
|
||||
_audio.Clock();
|
||||
}
|
||||
|
||||
void UpdateWorkRam()
|
||||
|
|
50
Core/VRC6.h
50
Core/VRC6.h
|
@ -2,8 +2,7 @@
|
|||
#include "stdafx.h"
|
||||
#include "BaseMapper.h"
|
||||
#include "VrcIrq.h"
|
||||
#include "Vrc6Pulse.h"
|
||||
#include "Vrc6Saw.h"
|
||||
#include "Vrc6Audio.h"
|
||||
|
||||
enum class VRCVariant;
|
||||
|
||||
|
@ -12,17 +11,12 @@ class VRC6 : public BaseMapper
|
|||
{
|
||||
private:
|
||||
VrcIrq _irq;
|
||||
Vrc6Pulse _pulse1;
|
||||
Vrc6Pulse _pulse2;
|
||||
Vrc6Saw _saw;
|
||||
Vrc6Audio _audio;
|
||||
|
||||
VRCVariant _model;
|
||||
uint8_t _bankingMode;
|
||||
uint8_t _chrRegisters[8];
|
||||
int32_t _lastOutput;
|
||||
|
||||
bool _haltAudio;
|
||||
|
||||
|
||||
void UpdatePrgRamAccess()
|
||||
{
|
||||
SetCpuMemoryMapping(0x6000, 0x7FFF, 0, HasBattery() ? PrgMemoryType::SaveRam : PrgMemoryType::WorkRam, (_bankingMode & 0x80) ? MemoryAccessType::ReadWrite : MemoryAccessType::NoAccess);
|
||||
|
@ -35,9 +29,7 @@ protected:
|
|||
void InitMapper()
|
||||
{
|
||||
_irq.Reset();
|
||||
_lastOutput = 0;
|
||||
_bankingMode = 0;
|
||||
_haltAudio = false;
|
||||
_audio.Reset();
|
||||
memset(_chrRegisters, 0, sizeof(_chrRegisters));
|
||||
SelectPRGPage(3, -1);
|
||||
}
|
||||
|
@ -47,11 +39,9 @@ protected:
|
|||
BaseMapper::StreamState(saving);
|
||||
ArrayInfo<uint8_t> chrRegisters = { _chrRegisters, 8 };
|
||||
SnapshotInfo irq{ &_irq };
|
||||
SnapshotInfo pulse1{ &_pulse1 };
|
||||
SnapshotInfo pulse2{ &_pulse2 };
|
||||
SnapshotInfo saw{ &_saw };
|
||||
SnapshotInfo audio{ &_audio };
|
||||
|
||||
Stream(_bankingMode, chrRegisters, _lastOutput, _haltAudio, irq, pulse1, pulse2, saw);
|
||||
Stream(_bankingMode, chrRegisters, irq, audio);
|
||||
|
||||
if(!saving) {
|
||||
UpdatePrgRamAccess();
|
||||
|
@ -61,15 +51,7 @@ protected:
|
|||
void ProcessCpuClock()
|
||||
{
|
||||
_irq.ProcessCpuClock();
|
||||
if(!_haltAudio) {
|
||||
_pulse1.Clock();
|
||||
_pulse2.Clock();
|
||||
_saw.Clock();
|
||||
}
|
||||
|
||||
int32_t outputLevel = _pulse1.GetVolume() + _pulse2.GetVolume() + _saw.GetVolume();
|
||||
APU::AddExpansionAudioDelta(AudioChannel::VRC6, outputLevel - _lastOutput);
|
||||
_lastOutput = outputLevel;
|
||||
_audio.Clock();
|
||||
}
|
||||
|
||||
void UpdatePpuBanking()
|
||||
|
@ -126,24 +108,10 @@ protected:
|
|||
break;
|
||||
|
||||
case 0x9000: case 0x9001: case 0x9002:
|
||||
_pulse1.WriteReg(addr, value);
|
||||
break;
|
||||
|
||||
case 0x9003: {
|
||||
_haltAudio = (value & 0x01) == 0x01;
|
||||
uint8_t frequencyShift = (value & 0x04) == 0x04 ? 8 : ((value & 0x02) == 0x02 ? 4 : 0);
|
||||
_pulse1.SetFrequencyShift(frequencyShift);
|
||||
_pulse2.SetFrequencyShift(frequencyShift);
|
||||
_saw.SetFrequencyShift(frequencyShift);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x9003:
|
||||
case 0xA000: case 0xA001: case 0xA002:
|
||||
_pulse2.WriteReg(addr, value);
|
||||
break;
|
||||
|
||||
case 0xB000: case 0xB001: case 0xB002:
|
||||
_saw.WriteReg(addr, value);
|
||||
_audio.WriteRegister(addr, value);
|
||||
break;
|
||||
|
||||
case 0xB003:
|
||||
|
|
70
Core/Vrc6Audio.h
Normal file
70
Core/Vrc6Audio.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
#pragma once
|
||||
#include "BaseExpansionAudio.h"
|
||||
#include "Vrc6Pulse.h"
|
||||
#include "Vrc6Saw.h"
|
||||
|
||||
class Vrc6Audio : public BaseExpansionAudio
|
||||
{
|
||||
private:
|
||||
Vrc6Pulse _pulse1;
|
||||
Vrc6Pulse _pulse2;
|
||||
Vrc6Saw _saw;
|
||||
bool _haltAudio;
|
||||
int32_t _lastOutput;
|
||||
|
||||
protected:
|
||||
void StreamState(bool saving)
|
||||
{
|
||||
SnapshotInfo pulse1{ &_pulse1 };
|
||||
SnapshotInfo pulse2{ &_pulse2 };
|
||||
SnapshotInfo saw{ &_saw };
|
||||
|
||||
Stream(_lastOutput, _haltAudio, pulse1, pulse2, saw);
|
||||
}
|
||||
|
||||
void ClockAudio()
|
||||
{
|
||||
if(!_haltAudio) {
|
||||
_pulse1.Clock();
|
||||
_pulse2.Clock();
|
||||
_saw.Clock();
|
||||
}
|
||||
|
||||
int32_t outputLevel = _pulse1.GetVolume() + _pulse2.GetVolume() + _saw.GetVolume();
|
||||
APU::AddExpansionAudioDelta(AudioChannel::VRC6, outputLevel - _lastOutput);
|
||||
_lastOutput = outputLevel;
|
||||
}
|
||||
|
||||
public:
|
||||
void Reset()
|
||||
{
|
||||
_lastOutput = 0;
|
||||
_haltAudio = false;
|
||||
}
|
||||
|
||||
void WriteRegister(uint16_t addr, uint8_t value)
|
||||
{
|
||||
switch(addr) {
|
||||
case 0x9000: case 0x9001: case 0x9002:
|
||||
_pulse1.WriteReg(addr, value);
|
||||
break;
|
||||
|
||||
case 0x9003: {
|
||||
_haltAudio = (value & 0x01) == 0x01;
|
||||
uint8_t frequencyShift = (value & 0x04) == 0x04 ? 8 : ((value & 0x02) == 0x02 ? 4 : 0);
|
||||
_pulse1.SetFrequencyShift(frequencyShift);
|
||||
_pulse2.SetFrequencyShift(frequencyShift);
|
||||
_saw.SetFrequencyShift(frequencyShift);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xA000: case 0xA001: case 0xA002:
|
||||
_pulse2.WriteReg(addr, value);
|
||||
break;
|
||||
|
||||
case 0xB000: case 0xB001: case 0xB002:
|
||||
_saw.WriteReg(addr, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
Loading…
Add table
Reference in a new issue