@@ -774,37 +774,12 @@ protected void calculateGlobalTuning()
774
774
* @param aktMemo
775
775
* @param period or noteIndex
776
776
* @return
777
+ * @since 28.06.2024 moved to the respective Mixers (ProTrackerMixher and ScreamTrackerMixer)
777
778
*/
778
779
protected int getFineTunePeriod (final ChannelMemory aktMemo , final int period )
779
780
{
780
- final int noteIndex = period - 1 ; // Period is only a note index now. No period - easier lookup
781
- switch (frequencyTableType )
782
- {
783
- case ModConstants .STM_S3M_TABLE :
784
- case ModConstants .IT_AMIGA_TABLE :
785
- final int s3mNote =ModConstants .FreqS3MTable [noteIndex %12 ];
786
- final int s3mOctave =noteIndex /12 ;
787
- return (int )((long )ModConstants .BASEFREQUENCY * ((long )s3mNote <<7 ) / ((long )aktMemo .currentFinetuneFrequency <<s3mOctave ));
788
-
789
- case ModConstants .IT_LINEAR_TABLE :
790
- return (ModConstants .FreqS3MTable [noteIndex %12 ]<<7 )>>(noteIndex /12 );
791
-
792
- case ModConstants .AMIGA_TABLE :
793
- final int lookUpFineTune = (aktMemo .currentFineTune <0 )?aktMemo .currentFineTune +16 :aktMemo .currentFineTune ;
794
- final int proTrackerIndex = noteIndex - 36 ; // our lookup table has three more octaves
795
- return ModConstants .periodTable [(lookUpFineTune *37 ) + proTrackerIndex ]<<ModConstants .PERIOD_SHIFT ;
796
-
797
- case ModConstants .XM_AMIGA_TABLE :
798
- final int amigaIndex = (noteIndex <<4 ) + ((aktMemo .currentFineTune >>3 ) + 16 ); // 0..1920
799
- return ModConstants .FT2_amigaPeriods [amigaIndex ]<<(ModConstants .PERIOD_SHIFT -2 ); // table values are already shifted by 2
800
-
801
- case ModConstants .XM_LINEAR_TABLE :
802
- final int linearIndex = (noteIndex <<4 ) + ((aktMemo .currentFineTune >>3 ) + 16 ); // 0..1920
803
- return ModConstants .FT2_linearPeriods [linearIndex ]<<(ModConstants .PERIOD_SHIFT -2 ); // table values are already shifted by 2
804
-
805
- default : // Period is not a noteindex - this will never happen, but I once used it with protracker mods
806
- return (int )((long )ModConstants .BASEFREQUENCY * (long )period / (long )aktMemo .currentFinetuneFrequency );
807
- }
781
+ // Period is not a noteindex - this will never happen, but I once used it with protracker mods
782
+ return (int )((long )ModConstants .BASEFREQUENCY * (long )period / (long )aktMemo .currentFinetuneFrequency );
808
783
}
809
784
/**
810
785
* Calls getFineTunePeriod(ChannelMemory, int Period) with the actual Period assigned.
@@ -830,6 +805,7 @@ protected int getFineTunePeriod(final ChannelMemory aktMemo)
830
805
* MAKE SHURE that newPeriod is already the "getFineTunePeriod" value.
831
806
* @param aktMemo
832
807
* @param newPeriod
808
+ * @since 28.06.2024 moved to the respective Mixers (ProTrackerMixher and ScreamTrackerMixer)
833
809
*/
834
810
protected void setNewPlayerTuningFor (final ChannelMemory aktMemo , final int newPeriod )
835
811
{
@@ -842,35 +818,7 @@ protected void setNewPlayerTuningFor(final ChannelMemory aktMemo, final int newP
842
818
}
843
819
844
820
final int clampedPeriod = (newPeriod >aktMemo .portaStepDownEnd )?aktMemo .portaStepDownEnd :(newPeriod <aktMemo .portaStepUpEnd )?aktMemo .portaStepUpEnd :newPeriod ;
845
-
846
- switch (frequencyTableType )
847
- {
848
- case ModConstants .AMIGA_TABLE :
849
- aktMemo .currentTuning = globalTuning / (aktMemo .currentNotePeriodSet = clampedPeriod );
850
- return ;
851
- case ModConstants .XM_LINEAR_TABLE :
852
- // We have a different LUT table as original FT2 - to avoid the doubles used there
853
- // So we need some adoption to the algorithm used in FT2 but stay as close as possible to the coding there:
854
- final int period = (newPeriod >>(ModConstants .PERIOD_SHIFT -2 )) & 0xFFFF ;
855
- final int invPeriod = ((12 * 192 * 4 ) + 767 - period ) & 0xFFFF ; // 12 octaves * (12 * 16 * 4) LUT entries = 9216, add 767 for rounding
856
- final int quotient = invPeriod / (12 * 16 * 4 );
857
- final int remainder = period % (12 * 16 * 4 );
858
- final int newFrequency = ModConstants .lintab [remainder ] >> (((14 - quotient ) & 0x1F )-2 ); // values are 4 times bigger in FT2
859
- aktMemo .currentTuning = (int )(((long )newFrequency <<ModConstants .SHIFT ) / (long )sampleRate );
860
- return ;
861
- case ModConstants .IT_LINEAR_TABLE :
862
- final long itTuning = (((((long )ModConstants .BASEPERIOD )<<ModConstants .PERIOD_SHIFT ) * (long )aktMemo .currentFinetuneFrequency )<<ModConstants .SHIFT ) / (long )sampleRate ;
863
- aktMemo .currentTuning = (int )(itTuning / (long )newPeriod );
864
- return ;
865
- case ModConstants .STM_S3M_TABLE :
866
- aktMemo .currentTuning = globalTuning / clampedPeriod ; // in globalTuning, all constant values are already calculated. (see above)
867
- return ;
868
- case ModConstants .XM_AMIGA_TABLE :
869
- case ModConstants .IT_AMIGA_TABLE :
870
- default :
871
- aktMemo .currentTuning = globalTuning / clampedPeriod ; // in globalTuning, all constant values are already calculated. (see above)
872
- return ;
873
- }
821
+ aktMemo .currentTuning = globalTuning / clampedPeriod ;
874
822
}
875
823
/**
876
824
* Set the current tuning for the player
@@ -1901,9 +1849,12 @@ protected void resetInstrumentPointers(final ChannelMemory aktMemo)
1901
1849
*/
1902
1850
protected void resetFineTune (final ChannelMemory aktMemo , final Sample currentSample )
1903
1851
{
1904
- aktMemo .currentFinetuneFrequency = currentSample .baseFrequency ;
1905
- aktMemo .currentFineTune = currentSample .fineTune ;
1906
- aktMemo .currentTranspose = currentSample .transpose ;
1852
+ if (currentSample !=null )
1853
+ {
1854
+ aktMemo .currentFinetuneFrequency = currentSample .baseFrequency ;
1855
+ aktMemo .currentFineTune = currentSample .fineTune ;
1856
+ aktMemo .currentTranspose = currentSample .transpose ;
1857
+ }
1907
1858
aktMemo .prevSampleOffset =0 ;
1908
1859
}
1909
1860
/**
@@ -1964,7 +1915,7 @@ protected void resetTablePositions(final ChannelMemory aktMemo)
1964
1915
*/
1965
1916
protected void resetAutoVibrato (final ChannelMemory aktMemo , final Sample sample )
1966
1917
{
1967
- if (isXM )
1918
+ if (isXM && sample != null )
1968
1919
{
1969
1920
if (sample .vibratoDepth >0 )
1970
1921
{
@@ -2161,6 +2112,22 @@ protected void setNewInstrumentAndPeriod(final ChannelMemory aktMemo)
2161
2112
:mod .getInstrumentContainer ().getSample (aktMemo .currentAssignedInstrumentIndex -1 );
2162
2113
2163
2114
boolean hasInstrument = element .getInstrument ()>0 && aktMemo .assignedSample !=null ;
2115
+ // do certain range checks with XMs.
2116
+ // With XMs the playback will skip some things when the noteIndex is out of range
2117
+ // i.e. do not reset volume and panning, do not set finetune of instrument, do not set tuning
2118
+ // we also do not set a sample offset (not implemented!) or retrigger the sample pointer
2119
+ // but if the note is zero, we only do not set the tuning
2120
+ // We simulate that here now - except for the sample offset...
2121
+ boolean isXMIllegalNote = false ;
2122
+ boolean isXMZeroNote = false ;
2123
+ if (isXM )
2124
+ {
2125
+ int note = aktMemo .assignedNoteIndex ;
2126
+ if (note >96 ) note = aktMemo .assignedNoteIndex = 96 ;
2127
+ if (aktMemo .assignedSample !=null ) note += aktMemo .assignedSample .transpose ;
2128
+ if (note <0 || note >=10 *12 ) isXMIllegalNote = true ; // this is an uint8 compare
2129
+ if (note ==0 ) isXMZeroNote = true ;
2130
+ }
2164
2131
2165
2132
if (hasInstrument ) // At this point we reset volume and panning for XMs and Fastracker family (IT, STM, S3M)
2166
2133
{
@@ -2173,7 +2140,7 @@ protected void setNewInstrumentAndPeriod(final ChannelMemory aktMemo)
2173
2140
if (aktMemo .currentSample !=null ) aktMemo .assignedSample = aktMemo .currentSample ;
2174
2141
}
2175
2142
// reset for new Instrument
2176
- resetVolumeAndPanning (aktMemo , aktMemo .currentAssignedInstrument , aktMemo .assignedSample );
2143
+ if (! isXMIllegalNote ) resetVolumeAndPanning (aktMemo , aktMemo .currentAssignedInstrument , aktMemo .assignedSample );
2177
2144
resetEnvelopes (aktMemo , aktMemo .currentAssignedInstrument );
2178
2145
resetAutoVibrato (aktMemo , aktMemo .assignedSample );
2179
2146
resetTablePositions (aktMemo );
@@ -2326,18 +2293,15 @@ protected void setNewInstrumentAndPeriod(final ChannelMemory aktMemo)
2326
2293
}
2327
2294
else // isFastTrackerFamily: reset to last known note period if instrument is set without note (or current, which is set anyways)
2328
2295
{
2329
- resetAllEffects (aktMemo , element ); // Reset Tremolo and such things... Forced! because of a new note
2330
- aktMemo .noteCut = aktMemo .keyOff = aktMemo .noteFade = false ;
2331
- if (!(isXM && isNewNote && !hasInstrument )) // with XMs a single note without instrument set does not retrigger anything
2332
- {
2333
- resetInstrumentPointers (aktMemo );
2334
- resetEnvelopes (aktMemo );
2335
- resetAutoVibrato (aktMemo , aktMemo .currentSample );
2336
- if (isMOD ) resetTablePositions (aktMemo ); // with MODs we reset vibrato/tremolo here
2337
- }
2296
+ resetAllEffects (aktMemo , element ); // Reset Tremolo and such things...
2297
+ //aktMemo.noteCut = aktMemo.keyOff = aktMemo.noteFade = false;
2298
+ if (!isXMIllegalNote ) resetInstrumentPointers (aktMemo );
2299
+ resetEnvelopes (aktMemo );
2300
+ resetAutoVibrato (aktMemo , aktMemo .currentSample );
2301
+ if (isMOD ) resetTablePositions (aktMemo ); // with MODs we reset vibrato/tremolo here
2338
2302
// With XMs reset the finetune with a new note. A finetune effect might change that later
2339
- if (isXM ) resetFineTune (aktMemo , aktMemo .currentSample );
2340
- setNewPlayerTuningFor (aktMemo , aktMemo .currentNotePeriod = getFineTunePeriod (aktMemo ));
2303
+ if (isXM && ! isXMIllegalNote ) resetFineTune (aktMemo , aktMemo .currentSample );
2304
+ if (! isXMIllegalNote && ! isXMZeroNote ) setNewPlayerTuningFor (aktMemo , aktMemo .currentNotePeriod = getFineTunePeriod (aktMemo ));
2341
2305
// With XMs we are also here in a note delay, even if it is a porta2Note effect - so do not reset portaTarget in that case
2342
2306
if (!isMOD && !isNoteDelay ) aktMemo .portaTargetNotePeriod = aktMemo .currentNotePeriod ; // do not reset with MODs
2343
2307
}
@@ -3019,7 +2983,7 @@ public int mixIntoBuffer(final long[] leftBuffer, final long[] rightBuffer, fina
3019
2983
for (int c =0 ; c <maxChannels ; c ++)
3020
2984
{
3021
2985
final ChannelMemory aktMemo = channelMemory [c ];
3022
- if (!aktMemo .instrumentFinished ) fillRampDataIntoBuffers (interweaveBufferLeft , interweaveBufferRight , aktMemo );
2986
+ if (!aktMemo .instrumentFinished && aktMemo . currentSample != null ) fillRampDataIntoBuffers (interweaveBufferLeft , interweaveBufferRight , aktMemo );
3023
2987
}
3024
2988
interweaveStartIndex =0 ; interweave = true ;
3025
2989
// now do the events
0 commit comments