Overclocking: Fix sound pitch for expansion audio when APU overclocking is disabled

This commit is contained in:
Souryo 2016-06-12 19:11:11 -04:00
parent 9d1f5f61ba
commit 84b4190f8b
12 changed files with 177 additions and 87 deletions

32
Core/BaseExpansionAudio.h Normal file
View 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--;
}
}
}
};

View file

@ -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" />

View file

@ -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">

View file

@ -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) {

View file

@ -170,7 +170,7 @@ private:
_ppuInFrame = false;
}
_audio.ProcessCpuClock();
_audio.Clock();
}
virtual void NotifyVRAMAddressChange(uint16_t addr)

View file

@ -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) {

View file

@ -103,7 +103,7 @@ protected:
}
if(_variant == NamcoVariant::Namco163) {
_audio.ProcessCpuClock();
_audio.Clock();
}
}

View file

@ -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) {

View file

@ -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) {

View file

@ -55,7 +55,7 @@ protected:
}
}
_audio.ProcessCpuClock();
_audio.Clock();
}
void UpdateWorkRam()

View file

@ -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
View 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;
}
}
};