21
21
*/
22
22
package de .quippy .javamod .multimedia .mod ;
23
23
24
+ import java .time .LocalDate ;
25
+ import java .time .format .DateTimeFormatter ;
26
+
24
27
/**
25
28
* @author Daniel Becker
26
29
* @since 02.08.2020
@@ -84,9 +87,12 @@ public ModConstants()
84
87
0xB0 , 0xB4 , 0xB8 , 0xBC , // 24-31
85
88
};
86
89
87
- // Panning values for old ProTracker and STMs
90
+ // Panning values for old ProTracker and STMs / S3Ms
88
91
public static final int OLD_PANNING_LEFT = 0 ; // 0: full left, 64: quarter left
89
92
public static final int OLD_PANNING_RIGHT = 256 - OLD_PANNING_LEFT ;
93
+ // Special panning values for S3M and IT
94
+ public static final int CHANNEL_IS_MUTED = 0x80 <<2 ; // IT and S3M use this
95
+ public static final int CHANNEL_IS_SURROUND = 100 <<2 ; // IT uses this (YES, not hex!)
90
96
91
97
// Volume constants
92
98
public static final int MAXGLOBALVOLUME = 128 ; // the maximum global volume at mod loading
@@ -133,19 +139,18 @@ public ModConstants()
133
139
public static enum PanBits { Pan4Bit , Pan6Bit , Pan8Bit }
134
140
135
141
// Constants for different supported samples
136
- public static final int SM_PCMS = 0x00 ; // PCM 8 Bit Signed
137
- public static final int SM_PCMU = 0x01 ; // PCM 8 Bit unsigned
138
- public static final int SM_PCMD = 0x02 ; // PCM 8 Bit delta values
139
- public static final int SM_16BIT = 0x04 ; // 16 BIT
140
- public static final int SM_STEREO = 0x08 ; // STEREO
141
- public static final int SM_PCM16D = SM_PCMD | SM_16BIT ; // PCM 16 Bit delta values
142
+ public static final int SM_PCMS = 0x0001 ; // PCM 8 Bit Signed
143
+ public static final int SM_PCMU = 0x0002 ; // PCM 8 Bit unsigned
144
+ public static final int SM_PCMD = 0x0004 ; // PCM 8 Bit delta values
145
+ public static final int SM_16BIT = 0x0008 ; // 16 BIT
146
+ public static final int SM_BigEndian = 0x0010 ; // 16 Bit in BigEndian order
147
+ public static final int SM_STEREO = 0x0020 ; // STEREO
142
148
// IT Packed (>2.14)
143
- public static final int SM_IT2148 = 0x10 ; // IT 2.14 8Bit compressed - can have stereo set
144
- public static final int SM_IT21416 = SM_IT2148 | SM_16BIT ; // IT 2.14 16Bit compressed - can have stereo set
145
- public static final int SM_IT2158 = 0x12 ; // IT 2.15 8Bit compressed - can have stereo set
146
- public static final int SM_IT21516 = SM_IT2158 | SM_16BIT ; // IT 2.15 16Bit compressed - can have stereo set
149
+ public static final int SM_IT214 = 0x0040 ; // IT 2.14 compressed
150
+ public static final int SM_IT215 = 0x0080 ; // IT 2.15 compressed
151
+ public static final int SM_PTM8Dto16 = 0x0100 ; // IT PTM8to16
147
152
// XM ADPCM ModPlug
148
- public static final int SM_ADPCM = 0x20 ; // ModPlug ADPCM
153
+ public static final int SM_ADPCM = 0x0200 ; // ModPlug ADPCM
149
154
150
155
// Loop Types
151
156
public static final int LOOP_ON = 0x01 ;
@@ -201,6 +206,12 @@ public static enum PanBits { Pan4Bit, Pan6Bit, Pan8Bit }
201
206
public static final int SONG_AMIGALIMITS = 0x00040 ;
202
207
public static final int SONG_ISSTEREO = 0x00080 ;
203
208
public static final int SONG_USEINSTRUMENTS = 0x00100 ;
209
+ public static final int SONG_ST2VIBRATO = 0x00200 ;
210
+ public static final int SONG_ST2TEMPO = 0x00400 ;
211
+ public static final int SONG_AMIGASLIDES = 0x00800 ;
212
+ public static final int SONG_VOL0MIXOPTI = 0x01000 ;
213
+ public static final int SONG_USEMIDIPITCH = 0x02000 ;
214
+ public static final int SONG_S3M_GUS = 0x80000 ;
204
215
205
216
// Player flags
206
217
public static final int PLAYER_LOOP_DEACTIVATED = 0x00 ;
@@ -1018,12 +1029,30 @@ public static String getAsHex(final int value, final int digits)
1018
1029
for (int shift =(digits -1 )<<2 ; shift >=0 ; shift -=4 )
1019
1030
result .append (numbers [(value >>shift )&0xF ]);
1020
1031
return result .toString ();
1032
+ }
1033
+ /**
1034
+ * Displays a value as a hex-value, using #digits. If the digits are not
1035
+ * sufficient, the number is cut!
1036
+ * @param value
1037
+ * @param digits
1038
+ * @return
1039
+ */
1040
+ public static String getAsHex (final long value , final int digits )
1041
+ {
1042
+ StringBuilder result = new StringBuilder ();
1043
+ for (int shift =(digits -1 )<<2 ; shift >=0 ; shift -=4 )
1044
+ result .append (numbers [(int )(value >>shift )&0xF ]);
1045
+ return result .toString ();
1021
1046
// Old standard way, much slower, much more fail safe.
1022
1047
// final String hex = Integer.toHexString(value).toUpperCase();
1023
1048
// final int zeros = digits - hex.length();
1024
1049
// for (int i=0; i<zeros; i++) result.append('0');
1025
1050
// return (result.append(hex)).toString();
1026
1051
}
1052
+ /**
1053
+ * Our standard Date formatter
1054
+ */
1055
+ public static final DateTimeFormatter DATE_FORMATER = DateTimeFormatter .ofPattern ("yyyy-MM-dd" );
1027
1056
/**
1028
1057
* convert the ModPlug version information to a readable string
1029
1058
* @param version
@@ -1032,10 +1061,68 @@ public static String getAsHex(final int value, final int digits)
1032
1061
public static String getModPlugVersionString (final int version )
1033
1062
{
1034
1063
if (version ==0 ) return "Unknown" ;
1035
- if ((version &0xFFFF )==0 ) return getAsHex ((version >>24 )&0xFF , 2 ) + '.' + getAsHex ((version >>16 )&0xFF , 2 );
1036
- final String versionString = getAsHex ((version >>24 )&0xFF , 2 ) + '.' + getAsHex ((version >>16 )&0xFF , 2 ) + '.' + getAsHex ((version >>8 )&0xFF , 2 ) + '.' + getAsHex (version &0xFF , 2 );
1037
- if (versionString .charAt (0 )=='0' ) return versionString .substring (1 ); else return versionString ;
1064
+ if ((version &0xFFFF )==0 ) return String .format ("%x.%02x" , Integer .valueOf ((version >>24 )&0xFF ), Integer .valueOf ((version >>16 )&0xFF ));
1065
+ return String .format ("%x.%02x.%02x.%02x" , Integer .valueOf ((version >>24 )&0xFF ), Integer .valueOf ((version >>16 )&0xFF ), Integer .valueOf ((version >>8 )&0xFF ), Integer .valueOf (version &0xFF ));
1038
1066
}
1067
+ /**
1068
+ * convert the Schism version information to a readable string
1069
+ * @since 19.07.2024
1070
+ * @param version
1071
+ * @return
1072
+ */
1073
+ public static String getSchismVersionString (final int version )
1074
+ {
1075
+ final int cwtv = (version >>16 ) & 0xFFF ;
1076
+ final int extVersion = version &0xFFFF ;
1077
+ if (cwtv >0x50 )
1078
+ {
1079
+ // version is days from 2009-10-31
1080
+ LocalDate d = LocalDate .of (2009 , 10 , 31 );
1081
+ if (cwtv <0xFFF )
1082
+ d = d .plusDays (cwtv -0x50 );
1083
+ else
1084
+ d = d .plusDays (extVersion );
1085
+ return DATE_FORMATER .format (d );
1086
+ }
1087
+ return String .format ("0.%x" , Integer .valueOf (cwtv ));
1088
+ }
1089
+ // private static final int ST2TempoFactor[] = { 140, 50, 25, 15, 10, 7, 6, 4, 3, 3, 2, 2, 2, 2, 1, 1 };
1090
+ // private static final int st2MixingRate = 23863; // Highest possible setting in ST2
1091
+ // public static int convertST2tempo(final int tempo)
1092
+ // {
1093
+ // // This underflows at tempo 06...0F, and the resulting tick lengths depend on the mixing rate.
1094
+ // // Note: ST2.3 uses the constant 50 below, earlier versions use 49 but they also play samples at a different speed.
1095
+ // int samplesPerTick = st2MixingRate / (50 - ((ST2TempoFactor[tempo >> 4] * (tempo & 0x0F)) >> 4));
1096
+ // if(samplesPerTick <= 0)
1097
+ // samplesPerTick += 65536;
1098
+ // return (st2MixingRate<<5)/(samplesPerTick<<2);
1099
+ // }
1100
+ private static final int st2_tempo_table [][] =
1101
+ {
1102
+ { 125 , 117 , 110 , 102 , 95 , 87 , 80 , 72 , 62 , 55 , 47 , 40 , 32 , 25 , 17 , 10 , },
1103
+ { 125 , 122 , 117 , 115 , 110 , 107 , 102 , 100 , 95 , 90 , 87 , 82 , 80 , 75 , 72 , 67 , },
1104
+ { 125 , 125 , 122 , 120 , 117 , 115 , 112 , 110 , 107 , 105 , 102 , 100 , 97 , 95 , 92 , 90 , },
1105
+ { 125 , 125 , 122 , 122 , 120 , 117 , 117 , 115 , 112 , 112 , 110 , 110 , 107 , 105 , 105 , 102 , },
1106
+ { 125 , 125 , 125 , 122 , 122 , 120 , 120 , 117 , 117 , 117 , 115 , 115 , 112 , 112 , 110 , 110 , },
1107
+ { 125 , 125 , 125 , 122 , 122 , 122 , 120 , 120 , 117 , 117 , 117 , 115 , 115 , 115 , 112 , 112 , },
1108
+ { 125 , 125 , 125 , 125 , 122 , 122 , 122 , 122 , 120 , 120 , 120 , 120 , 117 , 117 , 117 , 117 , },
1109
+ { 125 , 125 , 125 , 125 , 125 , 125 , 122 , 122 , 122 , 122 , 122 , 120 , 120 , 120 , 120 , 120 , },
1110
+ { 125 , 125 , 125 , 125 , 125 , 125 , 122 , 122 , 122 , 122 , 122 , 120 , 120 , 120 , 120 , 120 , },
1111
+ { 125 , 125 , 125 , 125 , 125 , 125 , 125 , 125 , 122 , 122 , 122 , 122 , 122 , 122 , 122 , 122 , },
1112
+ { 125 , 125 , 125 , 125 , 125 , 125 , 125 , 125 , 122 , 122 , 122 , 122 , 122 , 122 , 122 , 122 , },
1113
+ { 125 , 125 , 125 , 125 , 125 , 125 , 125 , 125 , 122 , 122 , 122 , 122 , 122 , 122 , 122 , 122 , },
1114
+ { 125 , 125 , 125 , 125 , 125 , 125 , 125 , 125 , 122 , 122 , 122 , 122 , 122 , 122 , 122 , 122 , },
1115
+ { 125 , 125 , 125 , 125 , 125 , 125 , 125 , 125 , 125 , 125 , 125 , 125 , 125 , 125 , 125 , 125 , },
1116
+ { 125 , 125 , 125 , 125 , 125 , 125 , 125 , 125 , 125 , 125 , 125 , 125 , 125 , 125 , 125 , 125 , },
1117
+ };
1118
+ public static int convertST2tempo (final int tempo )
1119
+ {
1120
+ final int tpr = ((tempo >>4 )!=0 )?(tempo >>4 ):1 ;
1121
+ final int scale = tempo &0xF ;
1122
+ return st2_tempo_table [tpr -1 ][scale ];
1123
+ }
1124
+
1125
+
1039
1126
// Conversions for read bytes! *********************************************
1040
1127
// /**
1041
1128
// * Converts an Intel like stored word to an integer
0 commit comments