|
From: <sag...@us...> - 2014-08-01 18:57:14
|
Revision: 4200
http://sourceforge.net/p/modplug/code/4200
Author: saga-games
Date: 2014-08-01 18:56:58 +0000 (Fri, 01 Aug 2014)
Log Message:
-----------
[Fix] FT2 compatibility: Tentatively fix arpeggio after pitch slide behaviour (http://bugs.openmpt.org/view.php?id=542) - note that the current behaviour is not 100% correct because of the finetune weirdness in FT2's RelocateTon function. Test case: ArpSlide.xm
Modified Paths:
--------------
trunk/OpenMPT/soundlib/Snd_fx.cpp
trunk/OpenMPT/soundlib/Sndfile.h
trunk/OpenMPT/soundlib/Sndmix.cpp
Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Snd_fx.cpp 2014-07-31 11:32:15 UTC (rev 4199)
+++ trunk/OpenMPT/soundlib/Snd_fx.cpp 2014-08-01 18:56:58 UTC (rev 4200)
@@ -4899,8 +4899,9 @@
//////////////////////////////////////////////////////
// Note/Period/Frequency functions
-UINT CSoundFile::GetNoteFromPeriod(UINT period) const
-//---------------------------------------------------
+// Find lowest note which has same or lower period as a given period (i.e. the note has the same or higher frequency)
+UINT CSoundFile::GetNoteFromPeriod(UINT period, int nFineTune, UINT nC5Speed) const
+//---------------------------------------------------------------------------------
{
if (!period) return 0;
if (GetType() & (MOD_TYPE_MED|MOD_TYPE_MOD|MOD_TYPE_DIGI|MOD_TYPE_MTM|MOD_TYPE_669|MOD_TYPE_OKT|MOD_TYPE_AMF0))
@@ -4922,12 +4923,22 @@
return 6*12+36;
} else
{
- for (UINT i=NOTE_MIN; i<NOTE_MAX; i++)
+ // This essentially implements std::lower_bound, with the difference that we don't need an iterable container.
+ uint32 minNote = NOTE_MIN, maxNote = NOTE_MAX, count = maxNote - minNote + 1;
+ while(count > 0)
{
- LONG n = GetPeriodFromNote(i, 0, 0);
- if ((n > 0) && (n <= (LONG)period)) return i;
+ const uint32 step = count / 2, midNote = minNote + step;
+ uint32 n = GetPeriodFromNote(midNote, nFineTune, nC5Speed);
+ if(n > period || !n)
+ {
+ minNote = midNote + 1;
+ count -= step + 1;
+ } else
+ {
+ count = step;
+ }
}
- return NOTE_MAX;
+ return minNote;
}
}
Modified: trunk/OpenMPT/soundlib/Sndfile.h
===================================================================
--- trunk/OpenMPT/soundlib/Sndfile.h 2014-07-31 11:32:15 UTC (rev 4199)
+++ trunk/OpenMPT/soundlib/Sndfile.h 2014-08-01 18:56:58 UTC (rev 4200)
@@ -874,9 +874,9 @@
bool ReadSampleFromSong(SAMPLEINDEX targetSample, const CSoundFile &srcSong, SAMPLEINDEX sourceSample);
// Period/Note functions
- UINT GetNoteFromPeriod(UINT period) const;
+ UINT GetNoteFromPeriod(UINT period, int nFineTune = 0, UINT nC5Speed = 0) const;
UINT GetPeriodFromNote(UINT note, int nFineTune, UINT nC5Speed) const;
- UINT GetFreqFromPeriod(UINT period, UINT nC5Speed, int nPeriodFrac=0) const;
+ UINT GetFreqFromPeriod(UINT period, UINT nC5Speed, int nPeriodFrac = 0) const;
// Misc functions
ModSample &GetSample(SAMPLEINDEX sample) { ASSERT(sample <= m_nSamples && sample < CountOf(Samples)); return Samples[sample]; }
const ModSample &GetSample(SAMPLEINDEX sample) const { ASSERT(sample <= m_nSamples && sample < CountOf(Samples)); return Samples[sample]; }
Modified: trunk/OpenMPT/soundlib/Sndmix.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Sndmix.cpp 2014-07-31 11:32:15 UTC (rev 4199)
+++ trunk/OpenMPT/soundlib/Sndmix.cpp 2014-08-01 18:56:58 UTC (rev 4200)
@@ -1219,15 +1219,18 @@
}
} else if(IsCompatibleMode(TRK_FASTTRACKER2))
{
- uint8 note = pChn->nNote;
- int arpPos = 0;
-
+ // FastTracker 2: Swedish tracker logic (TM) arpeggio
if(!m_SongFlags[SONG_FIRSTTICK])
{
- arpPos = m_PlayState.m_nMusicSpeed - (m_PlayState.m_nTickCount % m_PlayState.m_nMusicSpeed);
+ // Arpeggio is added on top of current note, but cannot do it the IT way because of
+ // the behaviour in ArpeggioClamp.xm.
+ // Test case: ArpSlide.xm
+ uint8 note = GetNoteFromPeriod(period, pChn->nFineTune, pChn->nC5Speed);//pChn->nNote;
+
// The fact that arpeggio behaves in a totally fucked up way at 16 ticks/row or more is that the arpeggio offset LUT only has 16 entries in FT2.
// At more than 16 ticks/row, FT2 reads into the vibrato table, which is placed right after the arpeggio table.
// Test case: Arpeggio.xm
+ int arpPos = m_PlayState.m_nMusicSpeed - (m_PlayState.m_nTickCount % m_PlayState.m_nMusicSpeed);
if(arpPos > 16) arpPos = 2;
else if(arpPos == 16) arpPos = 0;
else arpPos %= 3;
@@ -1236,13 +1239,13 @@
case 1: note += (pChn->nArpeggio >> 4); break;
case 2: note += (pChn->nArpeggio & 0x0F); break;
}
- }
- // Test case: ArpeggioClamp.xm
- if(note > 108 + NOTE_MIN && arpPos != 0)
- note = 108 + NOTE_MIN; // FT2's note limit
+ // Test case: ArpeggioClamp.xm
+ if(note > 108 + NOTE_MIN && arpPos != 0)
+ note = 108 + NOTE_MIN; // FT2's note limit
- period = GetPeriodFromNote(note, pChn->nFineTune, pChn->nC5Speed);
+ period = GetPeriodFromNote(note, pChn->nFineTune, pChn->nC5Speed);
+ }
}
// Other trackers
else
@@ -2171,7 +2174,7 @@
{
ModCommand::NOTE realNote = note;
if(ModCommand::IsNote(note))
- realNote = pIns->NoteMap[note - 1];
+ realNote = pIns->NoteMap[note - NOTE_MIN];
pPlugin->MidiCommand(GetBestMidiChannel(nChn), pIns->nMidiProgram, pIns->wMidiBank, realNote, static_cast<uint16>(chn.nVolume), nChn);
} else if(hasVolCommand)
{
@@ -2195,7 +2198,7 @@
ModCommand::NOTE realNote = note;
if(ModCommand::IsNote(note))
- realNote = pIns->NoteMap[note - 1];
+ realNote = pIns->NoteMap[note - NOTE_MIN];
// Experimental VST panning
//ProcessMIDIMacro(nChn, false, m_MidiCfg.szMidiGlb[MIDIOUT_PAN], 0, nPlugin);
pPlugin->MidiCommand(GetBestMidiChannel(nChn), pIns->nMidiProgram, pIns->wMidiBank, realNote, velocity, nChn);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|