From 5be1e7a4cc879c20d0bcb744014d35f13a823fd0 Mon Sep 17 00:00:00 2001 From: Persune Date: Sun, 5 Jan 2025 12:51:28 +0800 Subject: [PATCH] Refactor instrument loading --- Source/FamiTrackerDoc.cpp | 6 ++-- Source/Instrument2A03.cpp | 60 +++++++++++++++++++++------------------ Source/InstrumentFDS.cpp | 32 ++++++++++++++++----- Source/InstrumentN163.cpp | 5 ++-- Source/InstrumentVRC7.cpp | 2 +- 5 files changed, 66 insertions(+), 39 deletions(-) diff --git a/Source/FamiTrackerDoc.cpp b/Source/FamiTrackerDoc.cpp index 6eea9e94..91cdc198 100644 --- a/Source/FamiTrackerDoc.cpp +++ b/Source/FamiTrackerDoc.cpp @@ -1812,7 +1812,7 @@ void CFamiTrackerDoc::ReadBlock_Parameters(CDocumentFile *pDocFile, const int Ve switch (m_iPlaybackRateType) { case 1: // workaround for now - m_iEngineSpeed = static_cast(1000000. / m_iPlaybackRate + .5); + m_iEngineSpeed = static_cast(1000000. / m_iPlaybackRate + .5); break; case 0: case 2: default: @@ -1949,7 +1949,9 @@ void CFamiTrackerDoc::ReadBlock_Header(CDocumentFile *pDocFile, const int Versio for (unsigned int i = 0; i < m_iTrackCount; ++i) { int First = static_cast(pDocFile->GetBlockChar()); int Second = static_cast(pDocFile->GetBlockChar()); - if (!i) { + + // we don't have per-track row highlights yet, just use the first track + if (i == 0) { m_vHighlight.First = First; m_vHighlight.Second = Second; } diff --git a/Source/Instrument2A03.cpp b/Source/Instrument2A03.cpp index 0dea05b5..4c33a48d 100644 --- a/Source/Instrument2A03.cpp +++ b/Source/Instrument2A03.cpp @@ -67,7 +67,7 @@ void CInstrument2A03::Store(CDocumentFile *pDocFile) { CSeqInstrument::Store(pDocFile); // // // - int Version = 6; + int Version = pDocFile->GetBlockVersion(); int Octaves = Version >= 2 ? OCTAVE_RANGE : 6; if (Version >= 7) // // // 050B @@ -76,7 +76,7 @@ void CInstrument2A03::Store(CDocumentFile *pDocFile) for (int j = 0; j < NOTE_RANGE; ++j) { if (Version >= 7) { // // // 050B if (!GetSampleIndex(i, j)) continue; - pDocFile->WriteBlockChar(i * NOTE_RANGE + j); + pDocFile->WriteBlockChar(MIDI_NOTE(i, j)+1); } pDocFile->WriteBlockChar(GetSampleIndex(i, j)); pDocFile->WriteBlockChar(GetSamplePitch(i, j)); @@ -95,11 +95,12 @@ bool CInstrument2A03::Load(CDocumentFile *pDocFile) const auto ReadAssignment = [&] (int Octave, int Note) { try { - int Index = CModuleException::AssertRangeFmt( + char Sample = CModuleException::AssertRangeFmt( pDocFile->GetBlockChar(), 0, MAX_DSAMPLES, "DPCM sample assignment index", "%i"); - if (Index > MAX_DSAMPLES) - Index = 0; - SetSampleIndex(Octave, Note, Index); + if (Sample > MAX_DSAMPLES) + Sample = 0; + + SetSampleIndex(Octave, Note, Sample); char Pitch = pDocFile->GetBlockChar(); CModuleException::AssertRangeFmt(Pitch & 0x7F, 0, 0xF, "DPCM sample pitch", "%i"); SetSamplePitch(Octave, Note, Pitch & 0x8F); @@ -122,7 +123,7 @@ bool CInstrument2A03::Load(CDocumentFile *pDocFile) for (int i = 0; i < Count; ++i) { int Note = CModuleException::AssertRangeFmt( pDocFile->GetBlockChar(), 0, NOTE_COUNT - 1, "DPCM sample assignment note index", "%i"); - ReadAssignment(GET_OCTAVE(Note), GET_NOTE(Note) - 1); + ReadAssignment(GET_OCTAVE(Note - 1), GET_NOTE(Note - 1)); } } else @@ -155,10 +156,10 @@ void CInstrument2A03::SaveFile(CInstrumentFile *pFile) memset(UsedSamples, 0, sizeof(bool) * MAX_DSAMPLES); int UsedCount = 0; - for (int i = 0; i < OCTAVE_RANGE; ++i) { // octaves - for (int j = 0; j < NOTE_RANGE; ++j) { // notes + for (int i = 0; i < OCTAVE_RANGE; ++i) { + for (int j = 0; j < NOTE_RANGE; ++j) { if (unsigned char Sample = GetSampleIndex(i, j)) { - unsigned char Index = i * NOTE_RANGE + j; + unsigned char Index = MIDI_NOTE(i, j) + 1; pFile->WriteChar(Index); pFile->WriteChar(Sample); pFile->WriteChar(GetSamplePitch(i, j)); @@ -189,28 +190,28 @@ void CInstrument2A03::SaveFile(CInstrumentFile *pFile) bool CInstrument2A03::LoadFile(CInstrumentFile *pFile, int iVersion) { - char SampleNames[MAX_DSAMPLES][256]; - if (!CSeqInstrument::LoadFile(pFile, iVersion)) // // // return false; - unsigned int Count; - pFile->Read(&Count, sizeof(int)); - CModuleException::AssertRangeFmt(Count, 0U, static_cast(NOTE_COUNT), "DPCM assignment count", "%u"); + unsigned int Count = CModuleException::AssertRangeFmt(pFile->ReadInt(), 0U, static_cast(NOTE_COUNT), "DPCM assignment count", "%u"); // DPCM instruments for (unsigned int i = 0; i < Count; ++i) { - unsigned char InstNote = pFile->ReadChar(); - int Octave = InstNote / NOTE_RANGE; - int Note = InstNote % NOTE_RANGE; + unsigned char InstNote = CModuleException::AssertRangeFmt( + pFile->ReadChar(), 0, NOTE_COUNT - 1, "DPCM sample assignment note index", "%i"); + int Octave = GET_OCTAVE(InstNote - 1); + int Note = GET_NOTE(InstNote - 1); try { - unsigned char Sample = CModuleException::AssertRangeFmt(pFile->ReadChar(), 0U, 0x7FU, "DPCM sample assignment index", "%u"); + char Sample = CModuleException::AssertRangeFmt(pFile->ReadChar(), 0, MAX_DSAMPLES, "DPCM sample assignment index", "%u"); if (Sample > MAX_DSAMPLES) Sample = 0; - unsigned char Pitch = pFile->ReadChar(); - CModuleException::AssertRangeFmt(Pitch & 0x7FU, 0U, 0xFU, "DPCM sample pitch", "%u"); - SetSamplePitch(Octave, Note, Pitch); SetSampleIndex(Octave, Note, Sample); + + char Pitch = pFile->ReadChar(); + CModuleException::AssertRangeFmt(Pitch & 0x7F, 0, 0xF, "DPCM sample pitch", "%i"); + + SetSamplePitch(Octave, Note, Pitch); + SetSampleDeltaValue(Octave, Note, CModuleException::AssertRangeFmt( static_cast(iVersion >= 24 ? pFile->ReadChar() : -1), -1, 0x7F, "DPCM sample delta value", "%i")); } @@ -229,12 +230,16 @@ bool CInstrument2A03::LoadFile(CInstrumentFile *pFile, int iVersion) unsigned int SampleCount = pFile->ReadInt(); for (unsigned int i = 0; i < SampleCount; ++i) { + int Index = CModuleException::AssertRangeFmt( pFile->ReadInt(), 0U, static_cast(MAX_DSAMPLES - 1), "DPCM sample index", "%u"); + int Len = CModuleException::AssertRangeFmt( pFile->ReadInt(), 0U, static_cast(CDSample::MAX_NAME_SIZE - 1), "DPCM sample name length", "%u"); - pFile->Read(SampleNames[Index], Len); - SampleNames[Index][Len] = 0; + + char SampleName[256]{}; + pFile->Read(SampleName, Len); + int Size = pFile->ReadInt(); char *SampleData = new char[Size]; pFile->Read(SampleData, Size); @@ -242,7 +247,7 @@ bool CInstrument2A03::LoadFile(CInstrumentFile *pFile, int iVersion) for (int j = 0; j < MAX_DSAMPLES; ++j) if (const CDSample *pSample = m_pInstManager->GetDSample(j)) { // // // // Compare size and name to see if identical sample exists if (pSample->GetSize() == Size && !memcmp(pSample->GetData(), SampleData, Size) && // // // - !strcmp(pSample->GetName(), SampleNames[Index])) { + !strcmp(pSample->GetName(), SampleName)) { Found = true; // Assign sample for (int o = 0; o < OCTAVE_RANGE; ++o) { @@ -270,9 +275,9 @@ bool CInstrument2A03::LoadFile(CInstrumentFile *pFile, int iVersion) e->Raise(); } CDSample *pSample = new CDSample(); // // // - pSample->SetName(SampleNames[Index]); + pSample->SetName(SampleName); pSample->SetData(Size, SampleData); - int FreeSample = m_pInstManager->AddDSample(pSample); + int FreeSample = m_pInstManager->AddDSample(pSample); // not off-by-one if (FreeSample == -1) { SAFE_RELEASE(pSample); CModuleException *e = new CModuleException(); @@ -332,6 +337,7 @@ char CInstrument2A03::GetSampleDeltaValue(int Octave, int Note) const void CInstrument2A03::SetSampleIndex(int Octave, int Note, char Sample) { + // Sample is off by one; 0 means there is no index assigned to a note m_cSamples[Octave][Note] = Sample; InstrumentChanged(); } diff --git a/Source/InstrumentFDS.cpp b/Source/InstrumentFDS.cpp index 0faa2ea3..3a9b62e4 100644 --- a/Source/InstrumentFDS.cpp +++ b/Source/InstrumentFDS.cpp @@ -193,6 +193,7 @@ void CInstrumentFDS::Store(CDocumentFile *pDocFile) bool CInstrumentFDS::Load(CDocumentFile *pDocFile) { + const int Version = pDocFile->GetBlockVersion(); for (int i = 0; i < WAVE_SIZE; ++i) { SetSample(i, pDocFile->GetBlockChar()); } @@ -205,8 +206,25 @@ bool CInstrumentFDS::Load(CDocumentFile *pDocFile) SetModulationDepth(pDocFile->GetBlockInt()); SetModulationDelay(pDocFile->GetBlockInt()); - // hack to fix earlier saved files (remove this eventually) + for (int i = 0; i < SEQUENCE_COUNT; ++i) { + if (Version > 2) + SetSequence(i, LoadSequence(pDocFile)); + else + if (i < SEQ_PITCH) + // version 2 apparently does not have Pitch sequences + SetSequence(i, LoadSequence(pDocFile)); + } + + // Older files was 0-15, new is 0-31 + if (Version <= 3) DoubleVolume(); + + return true; + + // ancient code preserved for analysis + /* + // hack to fix earlier saved files (remove this eventually) + if (pDocFile->GetBlockVersion() > 2) { LoadSequence(pDocFile, GetSequence(SEQ_VOLUME)); LoadSequence(pDocFile, GetSequence(SEQ_ARPEGGIO)); @@ -215,10 +233,14 @@ bool CInstrumentFDS::Load(CDocumentFile *pDocFile) } else { */ + +/* + TODO: investigate Instrument block v2 and FDS + - perhaps an release interstice bug fix? + unsigned int a = pDocFile->GetBlockInt(); unsigned int b = pDocFile->GetBlockInt(); - // TODO: investigate why loading FDS instruments uses RollbackPointer() pDocFile->RollbackPointer(8); if (a < 256 && (b & 0xFF) != 0x00) { @@ -234,13 +256,9 @@ bool CInstrumentFDS::Load(CDocumentFile *pDocFile) if (pDocFile->GetBlockVersion() > 2) SetSequence(SEQ_PITCH, LoadSequence(pDocFile)); } +*/ // } - - // Older files was 0-15, new is 0-31 - if (pDocFile->GetBlockVersion() <= 3) DoubleVolume(); - - return true; } void CInstrumentFDS::SaveFile(CInstrumentFile *pFile) diff --git a/Source/InstrumentN163.cpp b/Source/InstrumentN163.cpp index 874331e2..8b92e3bf 100644 --- a/Source/InstrumentN163.cpp +++ b/Source/InstrumentN163.cpp @@ -78,7 +78,8 @@ void CInstrumentN163::Store(CDocumentFile *pDocFile) // Store wave pDocFile->WriteBlockInt(m_iWaveSize); pDocFile->WriteBlockInt(m_iWavePos); - //pDocFile->WriteBlockInt(m_bAutoWavePos ? 1 : 0); +// if (pDocFile->GetBlockVersion() >= 8) // // // 050B +// pDocFile->WriteBlockInt(m_bAutoWavePos ? 1 : 0); pDocFile->WriteBlockInt(m_iWaveCount); for (int i = 0; i < m_iWaveCount; ++i) { @@ -95,7 +96,7 @@ bool CInstrumentN163::Load(CDocumentFile *pDocFile) m_iWaveSize = CModuleException::AssertRangeFmt(pDocFile->GetBlockInt(), 4, MAX_WAVE_SIZE, "N163 wave size", "%i"); m_iWavePos = CModuleException::AssertRangeFmt(pDocFile->GetBlockInt(), 0, MAX_WAVE_SIZE - 1, "N163 wave position", "%i"); if (pDocFile->GetBlockVersion() >= 8) { // // // 050B - bool AutoPosition = pDocFile->GetBlockInt() != 0; + m_bAutoWavePos = pDocFile->GetBlockInt() != 0; } m_iWaveCount = CModuleException::AssertRangeFmt(pDocFile->GetBlockInt(), 1, MAX_WAVE_COUNT, "N163 wave count", "%i"); diff --git a/Source/InstrumentVRC7.cpp b/Source/InstrumentVRC7.cpp index 5be10185..0ecb7fcd 100644 --- a/Source/InstrumentVRC7.cpp +++ b/Source/InstrumentVRC7.cpp @@ -87,7 +87,7 @@ void CInstrumentVRC7::SaveFile(CInstrumentFile *pFile) bool CInstrumentVRC7::LoadFile(CInstrumentFile *pFile, int iVersion) { - m_iPatch = pFile->ReadInt(); + m_iPatch = CModuleException::AssertRangeFmt(pFile->ReadInt(), 0U, 0xFU, "VRC7 patch number", "%i"); for (int i = 0; i < 8; ++i) SetCustomReg(i, pFile->ReadChar());