Skip to content

Commit

Permalink
Merge pull request #214 from Dn-Programming-Core-Management/fix-module
Browse files Browse the repository at this point in the history
Module interaction and state fixes
  • Loading branch information
Gumball2415 authored Jan 2, 2024
2 parents 6613efc + 254814e commit 3d77513
Show file tree
Hide file tree
Showing 15 changed files with 129 additions and 99 deletions.
12 changes: 6 additions & 6 deletions Source/APU/2A03.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,16 +198,16 @@ int C2A03::GetChannelLevelRange(int Channel) const
}


void C2A03::UpdateMixingAPU1(double v) {
void C2A03::UpdateMixingAPU1(double v, bool UseSurveyMix) {
// NSFPlay output waveform ranges from 0 - 8191
// should not affect legacy mixing
Synth2A03SS.volume(v, 8191);
// legacy mixing absolutely requires the range 10000
Synth2A03SS.volume(v, UseSurveyMix ? 8191 : 10000);
}

void C2A03::UpdateMixingAPU2(double v) {
void C2A03::UpdateMixingAPU2(double v, bool UseSurveyMix) {
// NSFPlay output waveform ranges from 0 - 8191
// should not affect legacy mixing
Synth2A03TND.volume(v, 8191);
// legacy mixing absolutely requires the range 10000
Synth2A03TND.volume(v, UseSurveyMix ? 8191 : 10000);
}

void C2A03::ClockSequence()
Expand Down
4 changes: 2 additions & 2 deletions Source/APU/2A03.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ class C2A03 : public CSoundChip2
int GetChannelLevelRange(int Channel) const override;

public:
void UpdateMixingAPU1(double v);
void UpdateMixingAPU2(double v);
void UpdateMixingAPU1(double v, bool UseSurveyMix = false);
void UpdateMixingAPU2(double v, bool UseSurveyMix = false);

void ClockSequence(); // // //

Expand Down
7 changes: 1 addition & 6 deletions Source/APU/FDS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,12 +232,7 @@ void CFDS::UpdateMixLevel(double v, bool UseSurveyMix)
// (m_SynthFDS: FdsAudio) used to generate output samples between [0..63] inclusive,
// but was changed to [0 .. 63*1152] inclusive to prevent quantization at low volumes.

if (UseSurveyMix)
m_SynthFDS.volume(v, 63 * 1152);
else
// The following mixing levels match nsfplay's FDS output,
// using 2A03 Pulse as a baseline.
m_SynthFDS.volume(v * 1.122f, 256 * 1152);
m_SynthFDS.volume(UseSurveyMix ? v : (v * 1.122f), UseSurveyMix ? (63 * 1152) : (256 * 1152));
}

/// Input:
Expand Down
27 changes: 11 additions & 16 deletions Source/APU/Mixer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ void CMixer::SetChipLevel(chip_level_t Chip, float Level)

float CMixer::GetAttenuation(bool UseSurveyMix) const
{
float Attenuation = 1.0f;
float ATTENUATION_2A03 = 1.0f;

if (!UseSurveyMix) {
const float ATTENUATION_VRC6 = 0.80f;
Expand All @@ -161,22 +161,17 @@ float CMixer::GetAttenuation(bool UseSurveyMix) const
// Increase headroom if some expansion chips are enabled

if (m_iExternalChip & SNDCHIP_VRC6)
Attenuation *= ATTENUATION_VRC6;

ATTENUATION_2A03 *= ATTENUATION_VRC6;
if (m_iExternalChip & SNDCHIP_VRC7)
Attenuation *= ATTENUATION_VRC7;

ATTENUATION_2A03 *= ATTENUATION_VRC7;
if (m_iExternalChip & SNDCHIP_FDS)
Attenuation *= ATTENUATION_FDS;

ATTENUATION_2A03 *= ATTENUATION_FDS;
if (m_iExternalChip & SNDCHIP_MMC5)
Attenuation *= ATTENUATION_MMC5;

ATTENUATION_2A03 *= ATTENUATION_MMC5;
if (m_iExternalChip & SNDCHIP_N163)
Attenuation *= ATTENUATION_N163;

ATTENUATION_2A03 *= ATTENUATION_N163;
if (m_iExternalChip & SNDCHIP_S5B) // // // 050B
Attenuation *= ATTENUATION_S5B;
ATTENUATION_2A03 *= ATTENUATION_S5B;
}
else {
// attenuation scaling is exponential based on total chips used
Expand All @@ -188,10 +183,10 @@ float CMixer::GetAttenuation(bool UseSurveyMix) const
if (m_iExternalChip & SNDCHIP_N163) TotalChipsUsed++;
if (m_iExternalChip & SNDCHIP_S5B) TotalChipsUsed++;

Attenuation *= static_cast<float>(1.0 / (float)TotalChipsUsed);
ATTENUATION_2A03 *= static_cast<float>(1.0 / (float)TotalChipsUsed);
}

return Attenuation;
return ATTENUATION_2A03;
}

void CMixer::RecomputeEmuMixState()
Expand Down Expand Up @@ -229,8 +224,8 @@ void CMixer::RecomputeEmuMixState()

// Maybe the range argument, as well as the constant factor in the volume,
// should be supplied by the CSoundChip2 subclass rather than CMixer.
chip2A03.UpdateMixingAPU1(Volume * m_fLevelAPU1);
chip2A03.UpdateMixingAPU2(Volume * m_fLevelAPU2);
chip2A03.UpdateMixingAPU1(Volume * m_fLevelAPU1, UseSurveyMixing);
chip2A03.UpdateMixingAPU2(Volume * m_fLevelAPU2, UseSurveyMixing);
chipFDS.UpdateMixLevel(Volume * m_fLevelFDS, UseSurveyMixing);
chipN163.UpdateMixLevel(Volume * m_fLevelN163, UseSurveyMixing);

Expand Down
2 changes: 1 addition & 1 deletion Source/APU/VRC7.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ void CVRC7::UpdateMixLevel(double v, bool UseSurveyMix)
SetDirectVolume(UseSurveyMix ? v : (v * AMPLIFY));

// emu2413's waveform output ranges from -4095...4095
m_SynthVRC7.volume(v, 8191);
m_SynthVRC7.volume(v, UseSurveyMix ? 8191 : 10000);
}

void CVRC7::UpdatePatchSet(int PatchSelection, bool UseExternalOPLLChip, uint8_t* PatchSet)
Expand Down
4 changes: 2 additions & 2 deletions Source/Compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1482,7 +1482,7 @@ void CCompiler::CreateHeader(stNSFHeader *pHeader, int MachineType, unsigned int
// If speed is default, write correct NTSC/PAL speed periods
// else, set the same custom speed for both
SpeedNTSC = (Speed == 0) ? 1000000 / CAPU::FRAME_RATE_NTSC : 1000000 / Speed;
SpeedPAL = (Speed == 0) ? 1000000 / CAPU::FRAME_RATE_NTSC : 1000000 / Speed;
SpeedPAL = (Speed == 0) ? 1000000 / CAPU::FRAME_RATE_PAL : 1000000 / Speed;

memset(pHeader, 0, 0x80);

Expand Down Expand Up @@ -1564,7 +1564,7 @@ void CCompiler::CreateNSFeHeader(stNSFeHeader *pHeader, int MachineType) // //
unsigned int SpeedPAL, SpeedNTSC, Speed;
Speed = m_pDocument->GetEngineSpeed();
SpeedNTSC = (Speed == 0) ? 1000000 / CAPU::FRAME_RATE_NTSC : 1000000 / Speed;
SpeedPAL = (Speed == 0) ? 1000000 / CAPU::FRAME_RATE_NTSC : 1000000 / Speed;
SpeedPAL = (Speed == 0) ? 1000000 / CAPU::FRAME_RATE_PAL : 1000000 / Speed;

pHeader->InfoSize = 12;
pHeader->BankSize = 8;
Expand Down
32 changes: 25 additions & 7 deletions Source/DetuneTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ double CDetuneTable::PeriodToFrequency(unsigned int Period, int Octave, int Namc
return 0.0;
}

// https://www.nesdev.org/wiki/APU_Pulse#Sequencer_behavior
// no compensation is done for triangle
CDetuneNTSC::CDetuneNTSC(double A440_Note) :
CDetuneTable(DETUNE_NTSC, 0, 0x7FF, A440_Note)
{
Expand All @@ -126,16 +128,19 @@ CDetuneNTSC::CDetuneNTSC(double A440_Note) :
GenerateRegisters();
}

// period = CPU_clk / (16 * frequency) - 1
unsigned int CDetuneNTSC::FrequencyToPeriod(double Freq, int Octave, int NamcoChannels) const
{
return std::lround((CAPU::BASE_FREQ_NTSC / (Freq * 16.0)) - 1.0);
}

// frequency = CPU_clk / 16 * (period + 1)
double CDetuneNTSC::PeriodToFrequency(unsigned int Period, int Octave, int NamcoChannels) const
{
return CAPU::BASE_FREQ_NTSC / (16.0 * (Period + 1.0));
return CAPU::BASE_FREQ_NTSC / (16.0 * ((double)Period + 1.0));
}

// same as CDetuneNTSC, but with different clock frequency
CDetunePAL::CDetunePAL(double A440_Note) :
CDetuneTable(DETUNE_PAL, 0, 0x7FF, A440_Note)
{
Expand All @@ -151,9 +156,10 @@ unsigned int CDetunePAL::FrequencyToPeriod(double Freq, int Octave, int NamcoCha

double CDetunePAL::PeriodToFrequency(unsigned int Period, int Octave, int NamcoChannels) const
{
return CAPU::BASE_FREQ_PAL / (16.0 * (Period + 1.0));
return CAPU::BASE_FREQ_PAL / (16.0 * ((double)Period + 1.0));
}

// https://www.nesdev.org/wiki/VRC6_audio#Sawtooth_Channel
CDetuneSaw::CDetuneSaw(double A440_Note) :
CDetuneTable(DETUNE_SAW, 0, 0xFFF, A440_Note)
{
Expand All @@ -162,16 +168,19 @@ CDetuneSaw::CDetuneSaw(double A440_Note) :
GenerateRegisters();
}

// period = (CPU_clk / (14 * frequency)) - 1
unsigned int CDetuneSaw::FrequencyToPeriod(double Freq, int Octave, int NamcoChannels) const
{
return std::lround((CAPU::BASE_FREQ_NTSC / (Freq * 14.0)) - 1.0);
}

// frequency = CPU_clk / (14 * (period + 1))
double CDetuneSaw::PeriodToFrequency(unsigned int Period, int Octave, int NamcoChannels) const
{
return CAPU::BASE_FREQ_NTSC / (14.0 * (Period + 1.0));
return CAPU::BASE_FREQ_NTSC / (14.0 * ((double)Period + 1.0));
}

// https://www.nesdev.org/wiki/VRC7_audio#Channels
CDetuneVRC7::CDetuneVRC7(double A440_Note) :
CDetuneTable(DETUNE_VRC7, 0, 0x1FF, A440_Note)
{
Expand All @@ -186,9 +195,10 @@ unsigned int CDetuneVRC7::FrequencyToPeriod(double Freq, int Octave, int NamcoCh
return std::lround((Freq * std::pow(2, (19 - Octave))) / (CAPU::BASE_FREQ_VRC7 / 72.0));
}

// frequency = (VRC7_Xclock / 72 * period) / 2^(19 - octave - 1)
double CDetuneVRC7::PeriodToFrequency(unsigned int Period, int Octave, int NamcoChannels) const
{
return ((CAPU::BASE_FREQ_VRC7 / 72.0) * Period) / std::pow(2, (19 - Octave - 1));
return ((CAPU::BASE_FREQ_VRC7 / 72.0) * (double)Period) / std::pow(2, (19 - Octave - 1));
}

CDetuneFDS::CDetuneFDS(double A440_Note) :
Expand All @@ -209,6 +219,7 @@ double CDetuneFDS::PeriodToFrequency(unsigned int Period, int Octave, int NamcoC
return (CAPU::BASE_FREQ_NTSC * (double)Period) / (65536.0);
}

// https://www.nesdev.org/wiki/Namco_163_audio#Frequency
CDetuneN163::CDetuneN163(double A440_Note) :
CDetuneTable(DETUNE_N163, 0, 0xFFFF, A440_Note),
m_iChannelCount(1)
Expand All @@ -218,21 +229,24 @@ CDetuneN163::CDetuneN163(double A440_Note) :
GenerateRegisters();
}

// period = (frequency * 15 * (65536 * 4) * channel_count) / CPU_clk
unsigned int CDetuneN163::FrequencyToPeriod(double Freq, int Octave, int NamcoChannels) const
{
return std::lround((Freq * 15.0 * 65536.0 * 4.0 * NamcoChannels) / (CAPU::BASE_FREQ_NTSC));
return std::lround((Freq * 15.0 * 262144.0 * NamcoChannels) / CAPU::BASE_FREQ_NTSC);
}

// frequency = (CPU_clk * period) / (15 * (65536 * 4) * channel_count)
double CDetuneN163::PeriodToFrequency(unsigned int Period, int Octave, int NamcoChannels) const
{
return std::lround((Period * 15.0 * 65536.0 * 4.0 * NamcoChannels) / (CAPU::BASE_FREQ_NTSC));
return std::lround((CAPU::BASE_FREQ_NTSC * (double)Period) / (15.0 * 262144.0 * NamcoChannels));
}

void CDetuneN163::SetChannelCount(unsigned Count) // special
{
m_iChannelCount = Count;
}

// https://www.nesdev.org/wiki/Sunsoft_5B_audio#Sound
CDetuneS5B::CDetuneS5B(double A440_Note) :
CDetuneTable(DETUNE_S5B, 0, 0xFFF, A440_Note)
{
Expand All @@ -241,12 +255,16 @@ CDetuneS5B::CDetuneS5B(double A440_Note) :
GenerateRegisters();
}

// in the driver, S5B's note LUT uses the regular NTSC note LUT +- 1, since it's off-by-one
// so for compatibility, the frequency is doubled
// period = CPU_clk / (frequency * 16)
unsigned int CDetuneS5B::FrequencyToPeriod(double Freq, int Octave, int NamcoChannels) const
{
return std::lround(CAPU::BASE_FREQ_NTSC / (Freq * 16.0));
}

// frequency = CPU_clk / (16 * period)
double CDetuneS5B::PeriodToFrequency(unsigned int Period, int Octave, int NamcoChannels) const
{
return CAPU::BASE_FREQ_NTSC / (16.0 * (Period));
return CAPU::BASE_FREQ_NTSC / (16.0 * ((double)Period));
}
10 changes: 7 additions & 3 deletions Source/ExportDialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,14 @@ BOOL CExportDialog::OnInitDialog()

// Add selections for each custom plugin name
CStringArray names;
theApp.GetCustomExporters()->GetNames( names );
CCustomExporters* pExporters = theApp.GetCustomExporters();

for( int i = 0; i < names.GetCount(); ++i )
pTypeBox->AddString( names[ i ] );
if (pExporters) {
pExporters->GetNames(names);

for (int i = 0; i < names.GetCount(); ++i)
pTypeBox->AddString(names[i]);
}

// Set default selection
pTypeBox->SetCurSel(m_iExportOption);
Expand Down
10 changes: 7 additions & 3 deletions Source/FamiTracker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,11 @@ BOOL CFamiTrackerApp::InitInstance()
GetModuleFileName(NULL, pathToPlugins, MAX_PATH);
PathRemoveFileSpec(pathToPlugins);
PathAppend(pathToPlugins, _T("\\Plugins"));
m_customExporters = new CCustomExporters( pathToPlugins );

// https://github.com/eatscrayon/Dn-FamiTracker-dll-hijack
// custom exporters are disabled until a better method is found.
// this is a huge security risk!
//m_customExporters = new CCustomExporters( pathToPlugins );

// Load custom accelerator
m_pAccel = new CAccelerator();
Expand Down Expand Up @@ -455,11 +459,11 @@ void CFamiTrackerApp::OnRecentFilesClear() // // //

void CFamiTrackerApp::OnUpdateRecentFiles(CCmdUI *pCmdUI) // // //
{
// https://www.codeguru.com/cpp/controls/menu/miscellaneous/article.php/c167
// https://web.archive.org/web/20190906190854/https://www.codeguru.com/cpp/controls/menu/miscellaneous/article.php/c167/MRU-list-in-a-submenu-the-MFC-bug-and-how-to-correct-it.htm
// updating a submenu?
if (pCmdUI->m_pSubMenu != NULL) return;

m_pRecentFileList->UpdateMenu(pCmdUI);
CWinApp::OnUpdateRecentFileMenu(pCmdUI);
}

void CFamiTrackerApp::ShutDownSynth()
Expand Down
11 changes: 6 additions & 5 deletions Source/FamiTrackerDoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -391,8 +391,7 @@ BOOL CFamiTrackerDoc::OnSaveDocument(LPCTSTR lpszPathName)
// TODO: Dn-FamiTracker compatibility modes

// to avoid conflicts with FamiTracker beta 0.5.0 modules, set as Dn-FT module
if (m_iFileVersion >= 0x450U)
m_bFileDnModule = true;
m_bFileDnModule = true;
if (!SaveDocument(lpszPathName))
return FALSE;

Expand Down Expand Up @@ -816,7 +815,7 @@ bool CFamiTrackerDoc::WriteBlocks(CDocumentFile *pDocFile) const
// internal
6, // Parameters
1, // Song Info
1, // Tuning
0, // Tuning
3, // Header
6, // Instruments
6, // Sequences
Expand All @@ -827,6 +826,7 @@ bool CFamiTrackerDoc::WriteBlocks(CDocumentFile *pDocFile) const
#else
6, // Parameters
1, // Song Info
0, // Tuning
3, // Header
6, // Instruments
6, // Sequences
Expand Down Expand Up @@ -872,8 +872,9 @@ bool CFamiTrackerDoc::WriteBlocks(CDocumentFile *pDocFile) const
};

for (size_t i = 0; i < sizeof(FTM_WRITE_FUNC) / sizeof(*FTM_WRITE_FUNC); ++i) {
if (!CALL_MEMBER_FN(this, FTM_WRITE_FUNC[i])(pDocFile, DEFAULT_BLOCK_VERSION[i]))
return false;
if (DEFAULT_BLOCK_VERSION[i] != 0) // !! !! check if block version is nonzero
if (!CALL_MEMBER_FN(this, FTM_WRITE_FUNC[i])(pDocFile, DEFAULT_BLOCK_VERSION[i]))
return false;
}
return true;
}
Expand Down
13 changes: 7 additions & 6 deletions Source/FamiTrackerView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1778,21 +1778,21 @@ void CFamiTrackerView::MoveCursorPrevChannel()

void CFamiTrackerView::SelectFrame(unsigned int Frame)
{
ASSERT(Frame < MAX_FRAMES);
ASSERT(static_cast<int>(Frame) < MAX_FRAMES); // avoid comparing against UINT32_MAX
m_pPatternEditor->MoveToFrame(Frame);
InvalidateCursor();
}

void CFamiTrackerView::SelectRow(unsigned int Row)
{
ASSERT(Row < MAX_PATTERN_LENGTH);
ASSERT(static_cast<int>(Row) < MAX_PATTERN_LENGTH); // avoid comparing against UINT32_MAX
m_pPatternEditor->MoveToRow(Row);
InvalidateCursor();
}

void CFamiTrackerView::SelectChannel(unsigned int Channel)
{
ASSERT(Channel < MAX_CHANNELS);
ASSERT(static_cast<int>(Channel) < MAX_CHANNELS); // avoid comparing against UINT32_MAX
m_pPatternEditor->MoveToChannel(Channel);
InvalidateCursor();
}
Expand Down Expand Up @@ -2973,9 +2973,6 @@ bool CFamiTrackerView::EditEffNumberColumn(stChanNote &Note, Input input, int Ef
bStepDown = true;
return true;
}

if (key >= VK_NUMPAD0 && key <= VK_NUMPAD9)
key = '0' + (key - VK_NUMPAD0);
}

CFamiTrackerDoc* pDoc = GetDocument();
Expand All @@ -2990,6 +2987,10 @@ bool CFamiTrackerView::EditEffNumberColumn(stChanNote &Note, Input input, int Ef

if (auto p = get_if<Keycode>(&input)) {
auto key = *p;

if (key >= VK_NUMPAD0 && key <= VK_NUMPAD9)
key = '0' + (key - VK_NUMPAD0);

if (!isAlphanumeric(key)) {
return false;
}
Expand Down
Loading

0 comments on commit 3d77513

Please sign in to comment.