Skip to content

Commit

Permalink
3.9.2 Preview BugFix
Browse files Browse the repository at this point in the history
  • Loading branch information
quippy-git committed Jun 21, 2024
1 parent 28fd497 commit b3552d9
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 73 deletions.
17 changes: 10 additions & 7 deletions source/de/quippy/javamod/main/gui/MainForm.java
Original file line number Diff line number Diff line change
Expand Up @@ -2792,22 +2792,25 @@ private void doCheckUpdate(final boolean beSilent)
{
public void run()
{
String serverVersion = Helpers.getCurrentServerVersion();
int compareResult = Helpers.compareVersions(Helpers.VERSION, serverVersion);
// first update last check date...
lastUpdateCheck = LocalDate.now();

final String serverVersion = Helpers.getCurrentServerVersion();
final int compareResult = Helpers.compareVersions(Helpers.VERSION, serverVersion);
if (compareResult<0)
{
File f = new File(".");
String programmDestination = f.getAbsolutePath();
final File f = new File(".");
final String programmDestination = f.getAbsolutePath();
// Show Version History
int resultHistory = JOptionPane.showConfirmDialog(MainForm.this, "There is a new version available!\n\nYour version: "+Helpers.VERSION+" - online verison: " + serverVersion + "\n\nWatch version history?\n\n", "New Version", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
final int resultHistory = JOptionPane.showConfirmDialog(MainForm.this, "There is a new version available!\n\nYour version: "+Helpers.VERSION+" - online verison: " + serverVersion + "\n\nWatch version history?\n\n", "New Version", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
if (resultHistory == JOptionPane.YES_OPTION)
{
SimpleTextViewerDialog dialog = getSimpleTextViewerDialog();
dialog.setDisplayTextFromURL(Helpers.VERSION_URL);
dialog.setVisible(true);
}
// Ask for download
int result = JOptionPane.showConfirmDialog(MainForm.this, "Your version: "+Helpers.VERSION+" - online verison: " + serverVersion + "\n\nShould I start the download?\n\n", "New Version", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
final int result = JOptionPane.showConfirmDialog(MainForm.this, "Your version: "+Helpers.VERSION+" - online verison: " + serverVersion + "\n\nShould I start the download?\n\n", "New Version", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
if (result == JOptionPane.YES_OPTION)
{
JFileChooser chooser = new JFileChooser();
Expand Down Expand Up @@ -2839,7 +2842,7 @@ public void run()
getDownloadDialog().setLocation(Helpers.getFrameCenteredLocation(getDownloadDialog(), MainForm.this));
getDownloadDialog().setCurrentFileName(Helpers.JAVAMOD_URL);
getDownloadDialog().setVisible(true);
int copied = Helpers.downloadJavaMod(destination, getDownloadDialog());
final int copied = Helpers.downloadJavaMod(destination, getDownloadDialog());
getDownloadDialog().setVisible(false);
if (copied==-1)
JOptionPane.showMessageDialog(MainForm.this, "Download failed!\n"+destination, "Failed", JOptionPane.ERROR_MESSAGE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public int updatePosition(final ChannelMemory aktMemo, final int currentTick, fi
{
int tick = currentTick + 1;

if (xm_style) // XM does this way more complicated + sustain is only one point (start==end) + FT not only has ticks but stores the position as well
if (xm_style) // XM does this way more complicated + sustain is only one point (start==end) + FT2 not only has ticks but stores the position as well
{
if (loop && tick==positions[loopEndPoint] && (!sustain || tick!=positions[sustainStartPoint] || !aktMemo.keyOff))
{
Expand Down Expand Up @@ -167,13 +167,31 @@ public int getInitPosition()
{
return (xm_style)?-1:0;
}
// public int getXMResetPosition(final int tick)
// {
// int index = endPoint;
// for (int i=0; i<index; i++)
// if (positions[i]>=tick) index = i; // results in a break
// return positions[index] - 1;
// }
/**
* XMs reset the envelope to the previous point position at
* a key off event
* As we do not store the current position, we need to derive
* that from the current tick position
* @since 20.06.2024
* @param tick
* @return
*/
public int getXMResetPosition(final int tick)
{
// This does not work as intended...
// if (endPoint!=-1)
// {
// int index = 0;
// while (index<endPoint && tick>=positions[index]) index++;
// if (tick<positions[index])
// {
// index--;
// if (index<0) index = 0;
// }
// return positions[index] - 1;
// }
return tick;
}
/**
* Sets the boolean values corresponding to the flag value
* XM-Version
Expand Down
154 changes: 101 additions & 53 deletions source/de/quippy/javamod/multimedia/mod/mixer/BasicModMixer.java
Original file line number Diff line number Diff line change
Expand Up @@ -1100,6 +1100,13 @@ private void doResonance(final ChannelMemory aktMemo, final long buffer[])
* @return
*/
protected abstract boolean isSampleOffsetEffekt(final int effekt);
/**
* Returns true, if the Effekt and EffektOp indicate a Note Off effect
* @param effekt
* @param effektOp
* @return
*/
protected abstract boolean isKeyOffEffekt(final int effekt, final int effektParam);
/**
* Returns true, if an NNA-Effekt is set. Than, no default instrument NNA
* should be processed.
Expand Down Expand Up @@ -1350,41 +1357,22 @@ protected void processEnvelopes(ChannelMemory aktMemo)
}
}

if (aktMemo.keyOff) // Key Off without volume envelope or looping envelope:
{
if (isXM)
{
if (volumeEnv==null || !volumeEnv.on) // XMs do hard note cut, if no volumeEnv or not enabled
{
currentVolume = aktMemo.currentInstrumentVolume = aktMemo.currentVolume = aktMemo.fadeOutVolume = 0;
aktMemo.doFastVolRamp = aktMemo.instrumentFinished = true;
}
// else
// {
// aktMemo.volEnvPos = volumeEnv.getXMResetPosition(aktMemo.volEnvPos);
// }
// if (panningEnv!=null && panningEnv.on)
// {
// aktMemo.panEnvPos = panningEnv.getXMResetPosition(aktMemo.panEnvPos);
// }
}

initNoteFade(aktMemo);
}
if (aktMemo.keyOff) initNoteFade(aktMemo);

// Do the note fade
// we are either from IT, which have this effect directly
// or volume envelopes finished
if (aktMemo.noteFade && currentInstrument!=null)
if (aktMemo.noteFade)
{
aktMemo.fadeOutVolume -= (currentInstrument.volumeFadeOut<<1);
if (aktMemo.fadeOutVolume<0)
if (currentInstrument!=null/* && currentInstrument.volumeFadeOut>0*/)
{
aktMemo.fadeOutVolume = 0;
aktMemo.noteFade = false;
aktMemo.fadeOutVolume -= (currentInstrument.volumeFadeOut<<1);
if (aktMemo.fadeOutVolume<0) aktMemo.fadeOutVolume = 0;
currentVolume = (currentVolume * aktMemo.fadeOutVolume) >> ModConstants.MAXFADEOUTVOLSHIFT;
}
currentVolume = (currentVolume * aktMemo.fadeOutVolume) >> ModConstants.MAXFADEOUTVOLSHIFT;

else
currentVolume = aktMemo.fadeOutVolume = 0;

// With IT a finished noteFade also sets the instrument as finished
if (isIT && aktMemo.fadeOutVolume<=0 && isChannelActive(aktMemo))
{
Expand Down Expand Up @@ -1978,18 +1966,18 @@ protected void resetAutoVibrato(final ChannelMemory aktMemo, final Sample sample
{
if (isXM)
{
if (sample.vibratoDepth > 0)
if (sample.vibratoDepth>0)
{
aktMemo.autoVibratoTablePos = 0;

if (aktMemo.autoVibratoSweep > 0)
if (aktMemo.autoVibratoSweep>0)
{
aktMemo.autoVibratoAmplitude = 0;
aktMemo.autoVibratoSweep = (sample.vibratoDepth << 8) / sample.vibratoSweep;
aktMemo.autoVibratoAmplitude=0;
aktMemo.autoVibratoSweep = (sample.vibratoDepth<<8) / sample.vibratoSweep;
}
else
{
aktMemo.autoVibratoAmplitude = sample.vibratoDepth << 8;
aktMemo.autoVibratoAmplitude = sample.vibratoDepth<<8;
aktMemo.autoVibratoSweep = 0;
}
}
Expand Down Expand Up @@ -2078,6 +2066,34 @@ protected boolean setFilterAndRandomVariations(final ChannelMemory aktMemo, fina

return useFilter;
}
/**
* @since 20.06.2024
* @param aktMemo
*/
protected void doKeyOff(final ChannelMemory aktMemo)
{
aktMemo.keyOff = true;
if (isXM)
{
// XM has a certain tick reset with key off and existing envelopes - tick is reset to the previous start position
final Instrument currentInstrument = aktMemo.assignedInstrument;
final Envelope volumeEnv = (currentInstrument!=null)?currentInstrument.volumeEnvelope:null;
if (volumeEnv!=null && volumeEnv.on)
{
aktMemo.volEnvPos = volumeEnv.getXMResetPosition(aktMemo.volEnvPos);
}
else
{
aktMemo.currentVolume = 0;
aktMemo.doFastVolRamp = true;
}
final Envelope panningEnv = (currentInstrument!=null)?currentInstrument.panningEnvelope:null;
if (panningEnv!=null && !panningEnv.on) // another FT2 Bug
{
aktMemo.panEnvPos = panningEnv.getXMResetPosition(aktMemo.panEnvPos);
}
}
}
/**
* @since 11.06.2006
* @param aktMemo
Expand All @@ -2098,14 +2114,45 @@ protected void setNewInstrumentAndPeriod(final ChannelMemory aktMemo)
{
doNNAAutoInstrument(aktMemo);
}

// copy last seen values from pattern
aktMemo.assignedNotePeriod = aktMemo.currentAssignedNotePeriod;
aktMemo.assignedNoteIndex = aktMemo.currentAssignedNoteIndex;

// copy last seen values from pattern - only effect values first
aktMemo.assignedEffekt = aktMemo.currentAssignedEffekt;
aktMemo.assignedEffektParam = aktMemo.currentAssignedEffektParam;
aktMemo.assignedVolumeEffekt = aktMemo.currentAssignedVolumeEffekt;
aktMemo.assignedVolumeEffektOp = aktMemo.currentAssignedVolumeEffektOp;

// special K00/KeyOff handling of XMs - instrument and note are "invisible" with K00
final boolean isXMK00 = isKeyOffEffekt(aktMemo.currentAssignedEffekt, aktMemo.currentAssignedEffektParam) && aktMemo.currentAssignedEffektParam==0;
if (isXM && (isKeyOff || isXMK00)
)
{
aktMemo.currentAssignedNotePeriod = aktMemo.assignedNotePeriod;
aktMemo.currentAssignedNoteIndex = aktMemo.assignedNoteIndex;
aktMemo.currentAssignedInstrumentIndex = aktMemo.assignedInstrumentIndex;
aktMemo.currentAssignedInstrument = aktMemo.assignedInstrument;

doKeyOff(aktMemo);

if (isNoteDelay)
{
if (element.getInstrument()>0)
{
resetVolumeAndPanning(aktMemo, aktMemo.assignedInstrument, aktMemo.assignedSample);
resetAutoVibrato(aktMemo, aktMemo.assignedSample);
resetTablePositions(aktMemo);
}
resetEnvelopes(aktMemo, aktMemo.currentAssignedInstrument);
aktMemo.noteCut = aktMemo.keyOff = aktMemo.noteFade = false;
}
else
if (element.getInstrument()>0) resetVolumeAndPanning(aktMemo, aktMemo.assignedInstrument, aktMemo.assignedSample);

return;
}

// copy last seen values from pattern - now note and instrument
aktMemo.assignedNotePeriod = aktMemo.currentAssignedNotePeriod;
aktMemo.assignedNoteIndex = aktMemo.currentAssignedNoteIndex;
// what Sample would be assigned? Get the correct sample from the mapping table, if there is an instrument set
aktMemo.assignedSample = (aktMemo.currentAssignedInstrument!=null)?
((aktMemo.assignedNoteIndex>0)? // but only if we also have a note index, if not, ignore it!
Expand All @@ -2115,12 +2162,11 @@ protected void setNewInstrumentAndPeriod(final ChannelMemory aktMemo)

boolean hasInstrument = element.getInstrument()>0 && aktMemo.assignedSample!=null;

// At this point we reset volume and panning for XMs and Fastracker family (IT, STM, S3M)
if (hasInstrument)
if (hasInstrument) // At this point we reset volume and panning for XMs and Fastracker family (IT, STM, S3M)
{
if (isXM)
{
if (isPortaToNoteEffect) // PortaToNote: ignore new instrument completely but reset old one
if (isPortaToNoteEffect || !isNewNote) // PortaToNote or no note: ignore new instrument completely but reset old one
{
aktMemo.currentAssignedInstrumentIndex = aktMemo.assignedInstrumentIndex;
aktMemo.currentAssignedInstrument = aktMemo.assignedInstrument;
Expand Down Expand Up @@ -2180,7 +2226,7 @@ protected void setNewInstrumentAndPeriod(final ChannelMemory aktMemo)
}
}

// Now safe those instruments for later re-use - except: XM ignores these samples completely
// Now safe those instruments for later re-use
aktMemo.assignedInstrumentIndex = aktMemo.currentAssignedInstrumentIndex;
aktMemo.assignedInstrument = aktMemo.currentAssignedInstrument;

Expand All @@ -2190,19 +2236,12 @@ protected void setNewInstrumentAndPeriod(final ChannelMemory aktMemo)
if (isXM && isNoteDelay)
{
isPortaToNoteEffect=!(hasInstrument=isNewNote=true);
// we could have a key_off here, which will make that fake above not work
// so we need to reset volume and envelope ourself here
if (isKeyOff)
{
resetVolumeAndPanning(aktMemo, aktMemo.assignedInstrument, aktMemo.currentSample);
resetEnvelopes(aktMemo);
}
}

// Key Off, Note Cut or Period / noteIndex to set?
// Key Off, Note Cut, Note Fade or Period / noteIndex to set?
if (isKeyOff)
{
aktMemo.keyOff = true;
doKeyOff(aktMemo);
}
else
if (element.getPeriod()==ModConstants.NOTE_CUT || element.getNoteIndex()==ModConstants.NOTE_CUT)
Expand Down Expand Up @@ -2293,6 +2332,7 @@ protected void setNewInstrumentAndPeriod(final ChannelMemory aktMemo)
{
resetInstrumentPointers(aktMemo);
resetEnvelopes(aktMemo);
resetAutoVibrato(aktMemo, aktMemo.currentSample);
if (isMOD) resetTablePositions(aktMemo); // with MODs we reset vibrato/tremolo here
}
// With XMs reset the finetune with a new note. A finetune effect might change that later
Expand Down Expand Up @@ -2487,12 +2527,20 @@ protected void doRowEvents()
aktMemo.assignedEffektParam = retEffektOp;
}
}
// With FastTracker, globalVolume is applied when it occurs.
// That is, the envelopes are processed in this loop, not afterwards
// in a whole, as seen below with Non-FastTracker
if (isXM) processEnvelopes(channelMemory[c]);
}
// with Row Effects, first all rows effect parameter need to be
// processed - then we can do the envelopes and volume effects
// Otherwise global (volume) effects would not be considered...
for (int c=0; c<maxChannels; c++)
processEnvelopes(channelMemory[c]);
// Otherwise global (volume) effects would not be considered correctly.
// Except for FastTracker - there it is different (see above)
if (!isXM)
{
for (int c=0; c<maxChannels; c++)
processEnvelopes(channelMemory[c]);
}
}
/**
* when stepping to a new Pattern - Position needs new set...
Expand Down
21 changes: 16 additions & 5 deletions source/de/quippy/javamod/multimedia/mod/mixer/ProTrackerMixer.java
Original file line number Diff line number Diff line change
Expand Up @@ -492,8 +492,8 @@ protected void doRowEffects(final ChannelMemory aktMemo)
aktMemo.keyOffCounter = aktMemo.assignedEffektParam;
break;
case 0x15: // Set envelope position
aktMemo.volEnvPos = aktMemo.assignedEffektParam;
aktMemo.panEnvPos = aktMemo.assignedEffektParam;
aktMemo.volEnvPos = aktMemo.assignedEffektParam - 1;
aktMemo.panEnvPos = aktMemo.assignedEffektParam - 1;
break;
case 0x19: // Panning slide
if ((aktMemo.assignedEffektParam>>4)!=0)
Expand Down Expand Up @@ -729,7 +729,7 @@ protected void preparePortaToNoteEffect(final ChannelMemory aktMemo)
final boolean isKeyOff = (element.getPeriod()==ModConstants.KEY_OFF || element.getNoteIndex()==ModConstants.KEY_OFF);
if (isKeyOff)
{
aktMemo.keyOff = true;
doKeyOff(aktMemo);
}
else
if (hasNewNote(element)) // KeyOff is not a note...
Expand Down Expand Up @@ -895,7 +895,7 @@ protected void doAutoVibratoEffekt(final ChannelMemory aktMemo, final Sample cur
case 3: periodAdd = ((0x40 - (aktMemo.autoVibratoTablePos>>1)) & 0x7F) - 0x40; // Ramp Down
break;
}
periodAdd = ((periodAdd<<ModConstants.PERIOD_SHIFT) * autoVibAmp) >> (6+8); // copy from FT2 source code
periodAdd = ((periodAdd<<ModConstants.PERIOD_SHIFT) * autoVibAmp) >> (6+8+2); // copy from FT2 source code plus our PERIOD_SHIFT is 4, not 2

int newPeriod = currentPeriod + periodAdd;
if (newPeriod>=(32000<<ModConstants.PERIOD_SHIFT))
Expand Down Expand Up @@ -1340,7 +1340,7 @@ protected void doTickEffekts(final ChannelMemory aktMemo)
if (aktMemo.keyOffCounter<=0)
{
aktMemo.keyOffCounter = -1;
aktMemo.keyOff = true;
doKeyOff(aktMemo);
}
}
break;
Expand Down Expand Up @@ -1561,6 +1561,17 @@ protected boolean isSampleOffsetEffekt(final int effekt)
{
return effekt==0x09;
}
/**
* @param effekt
* @param effektParam
* @return
* @see de.quippy.javamod.multimedia.mod.mixer.BasicModMixer#isKeyOffEffekt(int, int)
*/
@Override
protected boolean isKeyOffEffekt(int effekt, int effektParam)
{
return effekt==0x14;
}
/**
* @param aktMemo
* @return
Expand Down
Loading

0 comments on commit b3552d9

Please sign in to comment.