Skip to content

Commit 1bcdfb3

Browse files
yumasansansanWohlstand
authored andcommitted
GENS: the phase a channel update works with wraps as well
The patch that made Fcnt unsigned left the int that GET_CURRENT_PHASE() copies it into, on the grounds that the phase is only shifted and masked there. That is true of the phase as it arrives, but not of what the channel update does with it: modulation adds one operator's output to the next one's phase, and that addition overflows the same way the counter did. src/chips/gens/Ym2612.cpp:1424:5: runtime error: signed integer overflow: -2146769536 + -2312044 cannot be represented in type 'int' The four in0..in3 of T_Update_Chan(), T_Update_Chan_LFO(), T_Update_Chan_Int() and T_Update_Chan_LFO_Int() are that phase, and they are unsigned now, as Fcnt is. Every use of them is the same as before: they are set from Fcnt, added to in DO_FEEDBACK() and in the algorithm macros, and read as (in >> SIN_LBITS) & SIN_MASK, which takes bits 14 to 25 -- the bits an arithmetic shift and a logical shift agree on, since the mask is twelve bits wide. Copying Fcnt into an int was also a conversion that the standard leaves to the implementation once the counter had gone past INT_MAX, and that goes away too. A fuzz target of ADLplug-Next found it, one that plays MIDI through the real-time API with the chip settings a saved project can hold: the emulator GENS, two chips, the LFO on, and a note of 104 at velocity 11, which the daily run came upon in a quarter of an hour.
1 parent be1b2fe commit 1bcdfb3

1 file changed

Lines changed: 4 additions & 4 deletions

File tree

‎src/chips/gens/Ym2612.cpp‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1195,7 +1195,7 @@ inline void Ym2612Private::T_Update_Chan(channel_t *CH, int32_t *bufL, int32_t *
11951195
// "Algo %d len = %d", algo, length);
11961196

11971197
for (int i = 0; i < length; i++) {
1198-
int in0, in1, in2, in3; // current phase calculation
1198+
unsigned int in0, in1, in2, in3; // current phase calculation
11991199
int en0, en1, en2, en3; // current envelope calculation
12001200

12011201
GET_CURRENT_PHASE();
@@ -1263,7 +1263,7 @@ inline void Ym2612Private::T_Update_Chan_LFO(channel_t *CH, int32_t *bufL, int32
12631263
// "Algo %d LFO len = %d", algo, length);
12641264

12651265
for (int i = 0; i < length; i++) {
1266-
int in0, in1, in2, in3; // current phase calculation
1266+
unsigned int in0, in1, in2, in3; // current phase calculation
12671267
int en0, en1, en2, en3; // current envelope calculation
12681268

12691269
GET_CURRENT_PHASE();
@@ -1335,7 +1335,7 @@ inline void Ym2612Private::T_Update_Chan_Int(channel_t *CH, int32_t *bufL, int32
13351335
int_cnt = state.Inter_Cnt;
13361336

13371337
for (int i = 0; i < length; i++) {
1338-
int in0, in1, in2, in3; // current phase calculation
1338+
unsigned int in0, in1, in2, in3; // current phase calculation
13391339
int en0, en1, en2, en3; // current envelope calculation
13401340

13411341
GET_CURRENT_PHASE();
@@ -1404,7 +1404,7 @@ inline void Ym2612Private::T_Update_Chan_LFO_Int(channel_t *CH, int32_t *bufL, i
14041404
// "Algo %d LFO Int len = %d", algo, length);
14051405

14061406
for (int i = 0; i < length; i++) {
1407-
int in0, in1, in2, in3; // current phase calculation
1407+
unsigned int in0, in1, in2, in3; // current phase calculation
14081408
int en0, en1, en2, en3; // current envelope calculation
14091409

14101410
GET_CURRENT_PHASE();

0 commit comments

Comments
 (0)