Unified · Split
| @@ -22,7 +22,7 @@ · 21 unmodified lines | ||
| 22 | 22 | #include "pt2_scopes.h" |
| 23 | 23 | #include "pt2_sync.h" |
| 24 | 24 | |
| 25 | −static bool posJumpAssert, pBreakFlag, updateUIPositions, modHasBeenPlayed; | |
| 25 | +static bool posJumpAssert, pBreakFlag, modRenderDone; | |
| 26 | 26 | static int8_t pBreakPosition, oldRow, modPattern; |
| 27 | 27 | static uint8_t pattDelTime, lowMask = 0xFF, pattDelTime2; |
| 28 | 28 | static int16_t modOrder, oldPattern, oldOrder; |
| @@ -909,8 +909,38 @@ static void playVoice(moduleChannel_t *ch) · 880 unmodified lines | ||
| 909 | 909 | } |
| 910 | 910 | } |
| 911 | 911 | |
| 912 | +static bool firstNextPos = true; | |
| 913 | + | |
| 914 | +static void updateUIPositions(void) | |
| 915 | +{ | |
| 916 | + // don't update UI under MOD2WAV/PAT2SMP rendering | |
| 917 | + if (editor.isWAVRendering || editor.isSMPRendering) | |
| 918 | + return; | |
| 919 | + | |
| 920 | + song->currRow = song->row; | |
| 921 | + song->currOrder = modOrder; | |
| 922 | + song->currPattern = modPattern; | |
| 923 | + | |
| 924 | + uint16_t *currPatPtr = &song->header.order[modOrder]; | |
| 925 | + editor.currPatternDisp = currPatPtr; | |
| 926 | + editor.currPosEdPattDisp = currPatPtr; | |
| 927 | + editor.currPatternDisp = currPatPtr; | |
| 928 | + editor.currPosEdPattDisp = currPatPtr; | |
| 929 | + | |
| 930 | + ui.updateSongPos = true; | |
| 931 | + ui.updateSongPattern = true; | |
| 932 | + ui.updateCurrPattText = true; | |
| 933 | + ui.updatePatternData = true; | |
| 934 | + | |
| 935 | + if (ui.posEdScreenShown) | |
| 936 | + ui.updatePosEd = true; | |
| 937 | +} | |
| 938 | + | |
| 912 | 939 | static void nextPosition(void) |
| 913 | 940 | { |
| 941 | + if (editor.isSMPRendering) | |
| 942 | + modRenderDone = true; | |
| 943 | + | |
| 914 | 944 | song->row = pBreakPosition; |
| 915 | 945 | pBreakPosition = 0; |
| 916 | 946 | posJumpAssert = false; |
| @@ -925,9 +955,7 @@ static void nextPosition(void) · 8 unmodified lines | ||
| 925 | 955 | editor.stepPlayEnabled = false; |
| 926 | 956 | editor.stepPlayBackwards = false; |
| 927 | 957 | |
| 928 | − if (!editor.isWAVRendering && !editor.isSMPRendering) | |
| 929 | − song->currRow = song->row; | |
| 930 | − | |
| 958 | + song->currRow = song->row; | |
| 931 | 959 | return; |
| 932 | 960 | } |
| 933 | 961 | |
| @@ -935,96 +963,101 @@ static void nextPosition(void) · 1 unmodified line | ||
| 935 | 963 | if (modOrder >= song->header.numOrders) |
| 936 | 964 | { |
| 937 | 965 | modOrder = 0; |
| 938 | − modHasBeenPlayed = true; | |
| 939 | 966 | |
| 940 | 967 | if (config.compoMode) // stop song for music competitions playing |
| 941 | 968 | { |
| 942 | 969 | doStopIt(true); |
| 943 | 970 | turnOffVoices(); |
| 944 | 971 | |
| 945 | − song->currOrder = 0; | |
| 946 | − song->currRow = song->row = 0; | |
| 947 | − song->currPattern = modPattern = (int8_t)song->header.order[0]; | |
| 972 | + modOrder = 0; | |
| 973 | + modPattern = (int8_t)song->header.order[modOrder]; | |
| 974 | + song->row = 0; | |
| 948 | 975 | |
| 949 | − editor.currPatternDisp = &song->currPattern; | |
| 950 | − editor.currPosEdPattDisp = &song->currPattern; | |
| 951 | − editor.currPatternDisp = &song->currPattern; | |
| 952 | − editor.currPosEdPattDisp = &song->currPattern; | |
| 953 | − | |
| 954 | − if (ui.posEdScreenShown) | |
| 955 | − ui.updatePosEd = true; | |
| 956 | − | |
| 957 | − ui.updateSongPos = true; | |
| 958 | − ui.updateSongPattern = true; | |
| 959 | − ui.updateCurrPattText = true; | |
| 976 | + updateUIPositions(); | |
| 960 | 977 | } |
| 978 | + | |
| 979 | + if (editor.isWAVRendering) | |
| 980 | + modRenderDone = true; | |
| 961 | 981 | } |
| 962 | 982 | |
| 963 | 983 | modPattern = (int8_t)song->header.order[modOrder]; |
| 964 | 984 | if (modPattern > MAX_PATTERNS-1) |
| 965 | 985 | modPattern = MAX_PATTERNS-1; |
| 966 | − | |
| 967 | − updateUIPositions = true; | |
| 968 | 986 | } |
| 987 | + | |
| 988 | + firstNextPos = false; | |
| 969 | 989 | } |
| 970 | 990 | |
| 971 | −bool intMusic(void) | |
| 991 | +static void increasePlaybackTimer(void) | |
| 972 | 992 | { |
| 973 | − uint8_t i; | |
| 974 | − uint16_t *patt; | |
| 975 | − moduleChannel_t *c; | |
| 993 | + // the timer is not counting in "play pattern" mode | |
| 994 | + if (editor.playMode != PLAY_MODE_PATTERN && modBPM >= 32 && modBPM <= 255) | |
| 995 | + editor.musicTime64 += musicTimeTab64[modBPM-32]; | |
| 996 | +} | |
| 976 | 997 | |
| 977 | − // Quirk: CIA uses newly set timer values on the next interrupt, so handle BPM change now (ciaSetBPM was set on previous interrupt) | |
| 978 | − if (ciaSetBPM != -1) | |
| 979 | − { | |
| 980 | − modSetTempo(ciaSetBPM, false); | |
| 981 | − ciaSetBPM = -1; | |
| 982 | − } | |
| 998 | +static void setCurrRowToVisited(void) // for MOD2WAV | |
| 999 | +{ | |
| 1000 | + if (editor.isWAVRendering) | |
| 1001 | + editor.rowVisitTable[(modOrder * MOD_ROWS) + song->row] = true; | |
| 1002 | +} | |
| 983 | 1003 | |
| 984 | − if (editor.playMode != PLAY_MODE_PATTERN && modBPM >= 32 && modBPM <= 255) | |
| 985 | − editor.musicTime64 += musicTimeTab64[modBPM-32]; // for playback counter (don't increase in "play/rec pattern" mode) | |
| 1004 | +static bool renderEndCheck(void) // for MOD2WAV/PAT2SMP | |
| 1005 | +{ | |
| 1006 | + if (!editor.isWAVRendering && !editor.isSMPRendering) | |
| 1007 | + return true; // we're not doing MOD2WAV/PAT2SMP | |
| 986 | 1008 | |
| 987 | − if (updateUIPositions) | |
| 1009 | + bool noPatternDelay = pattDelTime2 == 0; | |
| 1010 | + if (noPatternDelay && song->tick == song->speed-1) | |
| 988 | 1011 | { |
| 989 | − updateUIPositions = false; | |
| 990 | − | |
| 991 | − if (!editor.isWAVRendering && !editor.isSMPRendering) | |
| 1012 | + if (editor.isSMPRendering) | |
| 992 | 1013 | { |
| 993 | − if (editor.playMode != PLAY_MODE_PATTERN) | |
| 994 | − { | |
| 995 | − song->currOrder = modOrder; | |
| 996 | − song->currPattern = modPattern; | |
| 997 | − | |
| 998 | − patt = &song->header.order[modOrder]; | |
| 999 | − editor.currPatternDisp = patt; | |
| 1000 | − editor.currPosEdPattDisp = patt; | |
| 1001 | − editor.currPatternDisp = patt; | |
| 1002 | − editor.currPosEdPattDisp = patt; | |
| 1014 | + if (modRenderDone) | |
| 1015 | + return false; // we're done rendering | |
| 1016 | + } | |
| 1017 | + | |
| 1018 | + if (editor.isWAVRendering) | |
| 1019 | + { | |
| 1020 | + bool rowVisited = editor.rowVisitTable[(modOrder * MOD_ROWS) + song->row]; | |
| 1021 | + if (rowVisited || modRenderDone) | |
| 1022 | + return false; // we're done rendering | |
| 1023 | + } | |
| 1024 | + } | |
| 1003 | 1025 | |
| 1004 | − if (ui.posEdScreenShown) | |
| 1005 | − ui.updatePosEd = true; | |
| 1026 | + return true; | |
| 1027 | +} | |
| 1006 | 1028 | |
| 1007 | − ui.updateSongPos = true; | |
| 1008 | − ui.updateSongPattern = true; | |
| 1009 | − ui.updateCurrPattText = true; | |
| 1010 | − } | |
| 1011 | − } | |
| 1029 | +bool intMusic(void) // replayer ticker | |
| 1030 | +{ | |
| 1031 | + // quirk: CIA BPM changes are delayed by one tick in PT, so handle previous tick's BPM change now | |
| 1032 | + if (ciaSetBPM != -1) | |
| 1033 | + { | |
| 1034 | + const int32_t newBPM = ciaSetBPM; | |
| 1035 | + modSetTempo(newBPM, false); | |
| 1036 | + ciaSetBPM = -1; | |
| 1012 | 1037 | } |
| 1013 | 1038 | |
| 1014 | − if (editor.isWAVRendering && song->tick == 0) | |
| 1015 | − editor.rowVisitTable[(modOrder * MOD_ROWS) + song->row] = true; | |
| 1039 | + increasePlaybackTimer(); | |
| 1016 | 1040 | |
| 1017 | 1041 | if (!editor.stepPlayEnabled) |
| 1018 | 1042 | song->tick++; |
| 1019 | 1043 | |
| 1020 | − if ((uint32_t)song->tick >= (uint32_t)song->speed || editor.stepPlayEnabled) | |
| 1044 | + bool readNewNote = false; | |
| 1045 | + if ((unsigned)song->tick >= (unsigned)song->speed) | |
| 1021 | 1046 | { |
| 1022 | 1047 | song->tick = 0; |
| 1048 | + readNewNote = true; | |
| 1049 | + } | |
| 1023 | 1050 | |
| 1024 | − if (pattDelTime2 == 0) | |
| 1051 | + if (readNewNote || editor.stepPlayEnabled) // tick 0 | |
| 1052 | + { | |
| 1053 | + if (pattDelTime2 == 0) // no pattern delay, time to read note data | |
| 1025 | 1054 | { |
| 1026 | − c = song->channels; | |
| 1027 | − for (i = 0; i < AMIGA_VOICES; i++, c++) | |
| 1055 | + setCurrRowToVisited(); // for MOD2WAV/PAT2SMP | |
| 1056 | + updateUIPositions(); // update current song positions in UI | |
| 1057 | + | |
| 1058 | + // read note data and trigger voices | |
| 1059 | + moduleChannel_t *c = song->channels; | |
| 1060 | + for (int32_t i = 0; i < AMIGA_VOICES; i++, c++) | |
| 1028 | 1061 | { |
| 1029 | 1062 | playVoice(c); |
| 1030 | 1063 | paulaSetVolume(i, c->n_volume); |
| @@ -1034,23 +1067,18 @@ bool intMusic(void) · 3 unmodified lines | ||
| 1034 | 1067 | paulaSetLength(i, c->n_replen); |
| 1035 | 1068 | } |
| 1036 | 1069 | } |
| 1037 | − else | |
| 1070 | + else // pattern delay is on-going | |
| 1038 | 1071 | { |
| 1039 | − c = song->channels; | |
| 1040 | − for (i = 0; i < AMIGA_VOICES; i++, c++) | |
| 1072 | + moduleChannel_t *c = song->channels; | |
| 1073 | + for (int32_t i = 0; i < AMIGA_VOICES; i++, c++) | |
| 1041 | 1074 | checkEffects(c); |
| 1042 | 1075 | } |
| 1043 | 1076 | |
| 1044 | − if (!editor.isWAVRendering && !editor.isSMPRendering) | |
| 1045 | − { | |
| 1046 | − song->currRow = song->row; | |
| 1047 | − ui.updatePatternData = true; | |
| 1048 | − } | |
| 1049 | − | |
| 1077 | + // increase row | |
| 1050 | 1078 | if (!editor.stepPlayBackwards) |
| 1051 | 1079 | { |
| 1052 | 1080 | song->row++; |
| 1053 | − song->rowsCounter++; | |
| 1081 | + song->rowsCounter++; // for MOD2WAV's progress bar | |
| 1054 | 1082 | } |
| 1055 | 1083 | |
| 1056 | 1084 | if (pattDelTime > 0) |
| @@ -1059,10 +1087,15 @@ bool intMusic(void) · 2 unmodified lines | ||
| 1059 | 1087 | pattDelTime = 0; |
| 1060 | 1088 | } |
| 1061 | 1089 | |
| 1090 | + // undo row increase if pattern delay is on-going | |
| 1062 | 1091 | if (pattDelTime2 > 0) |
| 1063 | 1092 | { |
| 1064 | − if (--pattDelTime2 > 0) | |
| 1093 | + pattDelTime2--; | |
| 1094 | + if (pattDelTime2 > 0) | |
| 1095 | + { | |
| 1065 | 1096 | song->row--; |
| 1097 | + song->rowsCounter--; // for MOD2WAV's progress bar | |
| 1098 | + } | |
| 1066 | 1099 | } |
| 1067 | 1100 | |
| 1068 | 1101 | if (pBreakFlag) |
| @@ -1072,51 +1105,37 @@ bool intMusic(void) · 3 unmodified lines | ||
| 1072 | 1105 | pBreakFlag = false; |
| 1073 | 1106 | } |
| 1074 | 1107 | |
| 1075 | − if (editor.blockMarkFlag) | |
| 1076 | − ui.updateStatusText = true; | |
| 1077 | − | |
| 1108 | + // step-play handling | |
| 1078 | 1109 | if (editor.stepPlayEnabled) |
| 1079 | 1110 | { |
| 1080 | 1111 | doStopIt(true); |
| 1081 | 1112 | |
| 1082 | 1113 | song->currRow = song->row & 0x3F; |
| 1083 | − ui.updatePatternData = true; | |
| 1084 | − | |
| 1085 | 1114 | editor.stepPlayEnabled = false; |
| 1086 | 1115 | editor.stepPlayBackwards = false; |
| 1087 | − ui.updatePatternData = true; | |
| 1088 | 1116 | |
| 1117 | + ui.updatePatternData = true; | |
| 1089 | 1118 | return true; |
| 1090 | 1119 | } |
| 1091 | 1120 | |
| 1092 | 1121 | if (song->row >= MOD_ROWS || posJumpAssert) |
| 1093 | − { | |
| 1094 | − if (editor.isSMPRendering) | |
| 1095 | − modHasBeenPlayed = true; | |
| 1096 | − | |
| 1097 | 1122 | nextPosition(); |
| 1098 | − } | |
| 1099 | 1123 | |
| 1100 | − if (editor.isWAVRendering && !pattDelTime2 && editor.rowVisitTable[(modOrder * MOD_ROWS) + song->row]) | |
| 1101 | − modHasBeenPlayed = true; | |
| 1124 | + // for pattern block mark feature | |
| 1125 | + if (editor.blockMarkFlag) | |
| 1126 | + ui.updateStatusText = true; | |
| 1102 | 1127 | } |
| 1103 | − else | |
| 1128 | + else // tick > 0 (handle effects) | |
| 1104 | 1129 | { |
| 1105 | − c = song->channels; | |
| 1106 | − for (i = 0; i < AMIGA_VOICES; i++, c++) | |
| 1130 | + moduleChannel_t *c = song->channels; | |
| 1131 | + for (int32_t i = 0; i < AMIGA_VOICES; i++, c++) | |
| 1107 | 1132 | checkEffects(c); |
| 1108 | 1133 | |
| 1109 | 1134 | if (posJumpAssert) |
| 1110 | 1135 | nextPosition(); |
| 1111 | 1136 | } |
| 1112 | 1137 | |
| 1113 | − if ((editor.isSMPRendering || editor.isWAVRendering) && modHasBeenPlayed && song->tick == song->speed-1) | |
| 1114 | − { | |
| 1115 | − modHasBeenPlayed = false; | |
| 1116 | − return false; | |
| 1117 | − } | |
| 1118 | − | |
| 1119 | − return true; | |
| 1138 | + return renderEndCheck(); // MOD2WAV/PAT2SMP listens to the return value (true = not done yet) | |
| 1120 | 1139 | } |
| 1121 | 1140 | |
| 1122 | 1141 | void modSetPattern(uint8_t pattern) |
| @@ -1179,7 +1198,7 @@ void modSetPos(int16_t order, int16_t row) · 56 unmodified lines | ||
| 1179 | 1198 | |
| 1180 | 1199 | void modSetTempo(int32_t bpm, bool doLockAudio) |
| 1181 | 1200 | { |
| 1182 | − if (bpm < 32) | |
| 1201 | + if (bpm < 32 || bpm > 255) | |
| 1183 | 1202 | return; |
| 1184 | 1203 | |
| 1185 | 1204 | const bool audioWasntLocked = !audio.locked; |
| @@ -1195,20 +1214,20 @@ void modSetTempo(int32_t bpm, bool doLockAudio) · 9 unmodified lines | ||
| 1195 | 1214 | |
| 1196 | 1215 | bpm -= 32; // 32..255 -> 0..223 |
| 1197 | 1216 | |
| 1198 | − double dSamplesPerTick; | |
| 1217 | + int64_t samplesPerTick64; | |
| 1199 | 1218 | if (editor.isSMPRendering) |
| 1200 | − dSamplesPerTick = editor.pat2SmpHQ ? audio.bpmTable28kHz[bpm] : audio.bpmTable22kHz[bpm]; | |
| 1219 | + samplesPerTick64 = editor.pat2SmpHQ ? audio.bpmTable28kHz[bpm] : audio.bpmTable22kHz[bpm]; | |
| 1201 | 1220 | else if (editor.isWAVRendering) |
| 1202 | − dSamplesPerTick = audio.bpmTableMod2Wav[bpm]; | |
| 1221 | + samplesPerTick64 = audio.bpmTableMod2Wav[bpm]; | |
| 1203 | 1222 | else |
| 1204 | − dSamplesPerTick = audio.bpmTable[bpm]; | |
| 1223 | + samplesPerTick64 = audio.bpmTable[bpm]; | |
| 1205 | 1224 | |
| 1206 | − audio.dSamplesPerTick = dSamplesPerTick; | |
| 1225 | + audio.samplesPerTick64 = samplesPerTick64; | |
| 1207 | 1226 | |
| 1208 | 1227 | // calculate tick time length for audio/video sync timestamp |
| 1209 | 1228 | const uint64_t tickTimeLen64 = audio.tickLengthTable[bpm]; |
| 1210 | 1229 | const uint32_t tickTimeLen = tickTimeLen64 >> 32; |
| 1211 | − const uint32_t tickTimeLenFrac = tickTimeLen64 & 0xFFFFFFFF; | |
| 1230 | + const uint32_t tickTimeLenFrac = (uint32_t)tickTimeLen64; | |
| 1212 | 1231 | |
| 1213 | 1232 | setSyncTickTimeLen(tickTimeLen, tickTimeLenFrac); |
| 1214 | 1233 | |
| @@ -1238,7 +1257,7 @@ void modStop(void) · 23 unmodified lines | ||
| 1238 | 1257 | pattDelTime2 = 0; |
| 1239 | 1258 | pBreakPosition = 0; |
| 1240 | 1259 | posJumpAssert = false; |
| 1241 | − modHasBeenPlayed = true; | |
| 1260 | + modRenderDone = true; | |
| 1242 | 1261 | } |
| 1243 | 1262 | |
| 1244 | 1263 | void playPattern(int8_t startRow) |
| @@ -1246,7 +1265,7 @@ void playPattern(int8_t startRow) · 1 unmodified line | ||
| 1246 | 1265 | if (!editor.stepPlayEnabled) |
| 1247 | 1266 | pointerSetMode(POINTER_MODE_PLAY, DO_CARRY); |
| 1248 | 1267 | |
| 1249 | − audio.dTickSampleCounter = 0.0; // zero tick sample counter so that it will instantly initiate a tick | |
| 1268 | + audio.tickSampleCounter64 = 0; // zero tick sample counter so that it will instantly initiate a tick | |
| 1250 | 1269 | song->currRow = song->row = startRow & 0x3F; |
| 1251 | 1270 | song->tick = song->speed; |
| 1252 | 1271 | ciaSetBPM = -1; |
| @@ -1291,7 +1310,7 @@ void modPlay(int16_t patt, int16_t order, int8_t row) · 38 unmodified lines | ||
| 1291 | 1310 | |
| 1292 | 1311 | doStopIt(false); |
| 1293 | 1312 | turnOffVoices(); |
| 1294 | − audio.dTickSampleCounter = 0.0; // zero tick sample counter so that it will instantly initiate a tick | |
| 1313 | + audio.tickSampleCounter64 = 0; // zero tick sample counter so that it will instantly initiate a tick | |
| 1295 | 1314 | ciaSetBPM = -1; |
| 1296 | 1315 | |
| 1297 | 1316 | if (row != -1) |
| @@ -1343,8 +1362,8 @@ void modPlay(int16_t patt, int16_t order, int8_t row) · 45 unmodified lines | ||
| 1343 | 1362 | editor.playMode = oldPlayMode; |
| 1344 | 1363 | editor.currMode = oldMode; |
| 1345 | 1364 | |
| 1346 | − song->tick = song->speed; | |
| 1347 | − modHasBeenPlayed = false; | |
| 1365 | + song->tick = song->speed-1; | |
| 1366 | + modRenderDone = false; | |
| 1348 | 1367 | editor.songPlaying = true; |
| 1349 | 1368 | editor.didQuantize = false; |
| 1350 | 1369 | |
| @@ -1569,6 +1588,6 @@ void resetSong(void) // only call this after storeTempVariables() has been calle · 218 unmodified lines | ||
| 1569 | 1588 | doStopIt(true); |
| 1570 | 1589 | |
| 1571 | 1590 | song->tick = 0; |
| 1572 | − modHasBeenPlayed = false; | |
| 1591 | + modRenderDone = false; | |
| 1573 | 1592 | audio.forceMixerOff = false; |
| 1574 | 1593 | } |