comparison minijss/jssplr.c @ 2586:9807ae37ad69

Require stdbool.h, we require C11 now.
author Matti Hamalainen <ccr@tnsp.org>
date Thu, 08 Dec 2022 15:59:22 +0200
parents 69a5af2eb1ea
children
comparison
equal deleted inserted replaced
2585:ef6c826c5b7a 2586:9807ae37ad69
116 chn->volume = dmClamp(volume, mpMinVol, mpMaxVol); 116 chn->volume = dmClamp(volume, mpMinVol, mpMaxVol);
117 JMPSETNDFLAGS(cdfNewVolume); 117 JMPSETNDFLAGS(cdfNewVolume);
118 } 118 }
119 119
120 120
121 static BOOL jmpExecEnvelope(JSSEnvelope *env, JSSPlayerEnvelope *pe, BOOL keyOff) 121 static bool jmpExecEnvelope(JSSEnvelope *env, JSSPlayerEnvelope *pe, bool keyOff)
122 { 122 {
123 int point; 123 int point;
124 124
125 if (!pe->exec) 125 if (!pe->exec)
126 return FALSE; 126 return false;
127 127
128 // Find current point, if not last point 128 // Find current point, if not last point
129 for (point = 0; point < env->npoints - 1; point++) 129 for (point = 0; point < env->npoints - 1; point++)
130 { 130 {
131 if (pe->frame < env->points[point + 1].frame) 131 if (pe->frame < env->points[point + 1].frame)
141 141
142 // Check for last point 142 // Check for last point
143 if (pe->frame >= env->points[env->npoints - 1].frame) 143 if (pe->frame >= env->points[env->npoints - 1].frame)
144 { 144 {
145 point = env->npoints - 1; 145 point = env->npoints - 1;
146 pe->exec = FALSE; 146 pe->exec = false;
147 pe->value = env->points[point].value; 147 pe->value = env->points[point].value;
148 } 148 }
149 else 149 else
150 { 150 {
151 // Linearly interpolate the value between current and next point 151 // Linearly interpolate the value between current and next point
170 pe->frame++; 170 pe->frame++;
171 } else 171 } else
172 pe->frame++; 172 pe->frame++;
173 } 173 }
174 174
175 return TRUE; 175 return true;
176 } 176 }
177 177
178 178
179 static void jmpProcessExtInstrument(JSSPlayerChannel *chn, int channel) 179 static void jmpProcessExtInstrument(JSSPlayerChannel *chn, int channel)
180 { 180 {
278 /* Reset the envelopes for given channel. 278 /* Reset the envelopes for given channel.
279 */ 279 */
280 static void jmpResetEnvelope(JSSPlayerEnvelope *env) 280 static void jmpResetEnvelope(JSSPlayerEnvelope *env)
281 { 281 {
282 env->frame = env->value = 0; 282 env->frame = env->value = 0;
283 env->exec = TRUE; 283 env->exec = true;
284 } 284 }
285 285
286 286
287 /* Clear module player structure 287 /* Clear module player structure
288 */ 288 */
303 assert(mp != NULL); 303 assert(mp != NULL);
304 JSS_LOCK(mp); 304 JSS_LOCK(mp);
305 305
306 // Initialize general variables 306 // Initialize general variables
307 mp->patternDelay = 0; 307 mp->patternDelay = 0;
308 mp->newRowSet = FALSE; 308 mp->newRowSet = false;
309 mp->newOrderSet = FALSE; 309 mp->newOrderSet = false;
310 mp->tick = jsetNotSet; 310 mp->tick = jsetNotSet;
311 mp->row = 0; 311 mp->row = 0;
312 mp->lastPatLoopRow = 0; 312 mp->lastPatLoopRow = 0;
313 313
314 // Initialize channel data 314 // Initialize channel data
343 JSS_LOCK(mp); 343 JSS_LOCK(mp);
344 344
345 if (mp->isPlaying) 345 if (mp->isPlaying)
346 { 346 {
347 jvmRemoveCallback(mp->device); 347 jvmRemoveCallback(mp->device);
348 mp->isPlaying = FALSE; 348 mp->isPlaying = false;
349 } 349 }
350 350
351 JSS_UNLOCK(mp); 351 JSS_UNLOCK(mp);
352 } 352 }
353 353
363 { 363 {
364 int result = jvmSetCallback(mp->device, jmpExec, (void *) mp); 364 int result = jvmSetCallback(mp->device, jmpExec, (void *) mp);
365 if (result != DMERR_OK) 365 if (result != DMERR_OK)
366 JSSERROR(result,, "Could not initialize callback for player.\n"); 366 JSSERROR(result,, "Could not initialize callback for player.\n");
367 367
368 mp->isPlaying = TRUE; 368 mp->isPlaying = true;
369 } 369 }
370 370
371 JSS_UNLOCK(mp); 371 JSS_UNLOCK(mp);
372 } 372 }
373 373
376 * Jumps over skip-points and invalid values, loops 376 * Jumps over skip-points and invalid values, loops
377 * to first order if enabled. 377 * to first order if enabled.
378 */ 378 */
379 static void jmpSetNewOrder(JSSPlayer * mp, int order) 379 static void jmpSetNewOrder(JSSPlayer * mp, int order)
380 { 380 {
381 BOOL orderOK; 381 bool orderOK;
382 mp->order = jsetNotSet; 382 mp->order = jsetNotSet;
383 orderOK = FALSE; 383 orderOK = false;
384 384
385 while (!orderOK) 385 while (!orderOK)
386 { 386 {
387 if (order < 0 || order >= mp->module->norders) 387 if (order < 0 || order >= mp->module->norders)
388 { 388 {
389 jmpStop(mp); 389 jmpStop(mp);
390 orderOK = TRUE; 390 orderOK = true;
391 } 391 }
392 else 392 else
393 { 393 {
394 int pattern = mp->module->orderList[order]; 394 int pattern = mp->module->orderList[order];
395 if (pattern == jsetOrderSkip) 395 if (pattern == jsetOrderSkip)
398 } 398 }
399 else 399 else
400 if (pattern >= mp->module->npatterns || pattern == jsetOrderEnd) 400 if (pattern >= mp->module->npatterns || pattern == jsetOrderEnd)
401 { 401 {
402 jmpStop(mp); 402 jmpStop(mp);
403 orderOK = TRUE; 403 orderOK = true;
404 } 404 }
405 else 405 else
406 { 406 {
407 // All OK 407 // All OK
408 orderOK = TRUE; 408 orderOK = true;
409 mp->pattern = mp->module->patterns[pattern]; 409 mp->pattern = mp->module->patterns[pattern];
410 mp->npattern = pattern; 410 mp->npattern = pattern;
411 mp->order = order; 411 mp->order = order;
412 } 412 }
413 } 413 }
460 if (result != DMERR_OK) 460 if (result != DMERR_OK)
461 { 461 {
462 JSSERROR(result, result, "Could not initialize callback for player.\n"); 462 JSSERROR(result, result, "Could not initialize callback for player.\n");
463 } 463 }
464 464
465 mp->isPlaying = TRUE; 465 mp->isPlaying = true;
466 return DMERR_OK; 466 return DMERR_OK;
467 } 467 }
468 468
469 469
470 int jmpChangeOrder(JSSPlayer *mp, int order) 470 int jmpChangeOrder(JSSPlayer *mp, int order)
702 jmpChangeVolume(chn, channel, paramX); 702 jmpChangeVolume(chn, channel, paramX);
703 if (paramX == 0) 703 if (paramX == 0)
704 jmpChangeVolume(chn, channel, -paramY); 704 jmpChangeVolume(chn, channel, -paramY);
705 } 705 }
706 706
707 static void jmpTriggerNote(JSSPlayer * mp, JSSPlayerChannel *chn, BOOL newExtInstrument); 707 static void jmpTriggerNote(JSSPlayer * mp, JSSPlayerChannel *chn, bool newExtInstrument);
708 708
709 709
710 static void jmpDoMultiRetrigNote(JSSPlayer *mp, JSSPlayerChannel *chn, int channel) 710 static void jmpDoMultiRetrigNote(JSSPlayer *mp, JSSPlayerChannel *chn, int channel)
711 { 711 {
712 if (chn->lastMultiRetrigParamY != 0 && 712 if (chn->lastMultiRetrigParamY != 0 &&
713 (mp->tick % chn->lastMultiRetrigParamY) == 0) 713 (mp->tick % chn->lastMultiRetrigParamY) == 0)
714 { 714 {
715 BOOL change = TRUE; 715 bool change = true;
716 int volume = chn->volume; 716 int volume = chn->volume;
717 switch (chn->lastMultiRetrigParamX) 717 switch (chn->lastMultiRetrigParamX)
718 { 718 {
719 case 0x1: volume -= 1; break; 719 case 0x1: volume -= 1; break;
720 case 0x2: volume -= 2; break; 720 case 0x2: volume -= 2; break;
729 case 0xB: volume += 4; break; 729 case 0xB: volume += 4; break;
730 case 0xC: volume += 8; break; 730 case 0xC: volume += 8; break;
731 case 0xD: volume += 16; break; 731 case 0xD: volume += 16; break;
732 case 0xE: volume = (volume * 3) / 2; break; 732 case 0xE: volume = (volume * 3) / 2; break;
733 case 0xF: volume *= 2; break; 733 case 0xF: volume *= 2; break;
734 default: change = FALSE; 734 default: change = false;
735 } 735 }
736 jmpTriggerNote(mp, chn, FALSE); 736 jmpTriggerNote(mp, chn, false);
737 if (change) 737 if (change)
738 jmpSetVolume(chn, channel, volume); 738 jmpSetVolume(chn, channel, volume);
739 } 739 }
740 } 740 }
741 741
764 chn->iPatLoopCount = paramY + 1; 764 chn->iPatLoopCount = paramY + 1;
765 765
766 // Loop to specified row 766 // Loop to specified row
767 chn->iPatLoopCount--; 767 chn->iPatLoopCount--;
768 mp->newRow = chn->iPatLoopRow; 768 mp->newRow = chn->iPatLoopRow;
769 mp->newRowSet = TRUE; 769 mp->newRowSet = true;
770 } 770 }
771 } 771 }
772 else 772 else
773 { 773 {
774 // SB0/E60 sets the loop start point 774 // SB0/E60 sets the loop start point
811 811
812 /* Trigger a new note on the given channel. 812 /* Trigger a new note on the given channel.
813 * Separate function used from various places where note 813 * Separate function used from various places where note
814 * triggering is needed (retrig, multi-retrig, etc.) 814 * triggering is needed (retrig, multi-retrig, etc.)
815 */ 815 */
816 static void jmpTriggerNote(JSSPlayer * mp, JSSPlayerChannel *chn, BOOL newExtInstrument) 816 static void jmpTriggerNote(JSSPlayer * mp, JSSPlayerChannel *chn, bool newExtInstrument)
817 { 817 {
818 if (chn->nextInstrument >= 0 && 818 if (chn->nextInstrument >= 0 &&
819 chn->nextInstrument < mp->module->nextInstruments && 819 chn->nextInstrument < mp->module->nextInstruments &&
820 mp->module->extInstruments[chn->nextInstrument] != NULL) 820 mp->module->extInstruments[chn->nextInstrument] != NULL)
821 { 821 {
880 * Process a new pattern row 880 * Process a new pattern row
881 */ 881 */
882 static void jmpProcessNewRow(JSSPlayer * mp, int channel) 882 static void jmpProcessNewRow(JSSPlayer * mp, int channel)
883 { 883 {
884 JSSNote *currNote; 884 JSSNote *currNote;
885 BOOL newNote = FALSE, newExtInstrument = FALSE, volumePortaSet = FALSE; 885 bool newNote = false, newExtInstrument = false, volumePortaSet = false;
886 char effect; 886 char effect;
887 int param, paramX, paramY; 887 int param, paramX, paramY;
888 JSSPlayerChannel *chn = &(mp->channels[channel]); 888 JSSPlayerChannel *chn = &(mp->channels[channel]);
889 889
890 JMPGETNOTE(currNote, mp->row, channel); 890 JMPGETNOTE(currNote, mp->row, channel);
891 891
892 // Check for a new note/keyoff here 892 // Check for a new note/keyoff here
893 if (currNote->note == jsetNoteOff) 893 if (currNote->note == jsetNoteOff)
894 chn->keyOff = TRUE; 894 chn->keyOff = true;
895 else 895 else
896 if (currNote->note >= 0 && currNote->note <= 96) 896 if (currNote->note >= 0 && currNote->note <= 96)
897 { 897 {
898 newNote = TRUE; 898 newNote = true;
899 chn->oldNote = chn->note; 899 chn->oldNote = chn->note;
900 chn->note = currNote->note; 900 chn->note = currNote->note;
901 chn->keyOff = FALSE; 901 chn->keyOff = false;
902 } 902 }
903 903
904 // Check for new instrument 904 // Check for new instrument
905 if (currNote->instrument != jsetNotSet) 905 if (currNote->instrument != jsetNotSet)
906 { 906 {
907 /* Envelopes and ext.instrument fadeout are initialized always if 907 /* Envelopes and ext.instrument fadeout are initialized always if
908 * new instrument is set, even if the instrument does not exist. 908 * new instrument is set, even if the instrument does not exist.
909 */ 909 */
910 jmpResetEnvelope(&chn->volumeEnv); 910 jmpResetEnvelope(&chn->volumeEnv);
911 jmpResetEnvelope(&chn->panningEnv); 911 jmpResetEnvelope(&chn->panningEnv);
912 chn->keyOff = FALSE; 912 chn->keyOff = false;
913 chn->fadeOutVol = mpMaxFadeoutVol; 913 chn->fadeOutVol = mpMaxFadeoutVol;
914 914
915 JMPSETNDFLAGS(cdfNewPanPos | cdfPlay | cdfNewVolume); 915 JMPSETNDFLAGS(cdfNewPanPos | cdfPlay | cdfNewVolume);
916 916
917 // We save the instrument number here for later use 917 // We save the instrument number here for later use
918 chn->nextInstrument = currNote->instrument; 918 chn->nextInstrument = currNote->instrument;
919 newExtInstrument = TRUE; 919 newExtInstrument = true;
920 } 920 }
921 921
922 if (newNote) 922 if (newNote)
923 { 923 {
924 jmpTriggerNote(mp, chn, newExtInstrument); 924 jmpTriggerNote(mp, chn, newExtInstrument);
963 chn->lastPortaToNoteNote = chn->note; 963 chn->lastPortaToNoteNote = chn->note;
964 chn->iLastPortaToNotePitch = chn->pitch; 964 chn->iLastPortaToNotePitch = chn->pitch;
965 chn->pitch = chn->oldPitch; 965 chn->pitch = chn->oldPitch;
966 chn->note = chn->oldNote; 966 chn->note = chn->oldNote;
967 JMPUNSETNDFLAGS(cdfNewPitch | cdfPlay); 967 JMPUNSETNDFLAGS(cdfNewPitch | cdfPlay);
968 volumePortaSet = TRUE; 968 volumePortaSet = true;
969 } 969 }
970 break; 970 break;
971 } 971 }
972 972
973 // ...And finally process the Normal effects 973 // ...And finally process the Normal effects
1070 chn->iLastVolSlideParam = param; 1070 chn->iLastVolSlideParam = param;
1071 break; 1071 break;
1072 1072
1073 case 'B': // Bxx = Pattern Jump : IMPL.VERIFIED 1073 case 'B': // Bxx = Pattern Jump : IMPL.VERIFIED
1074 mp->newOrder = param; 1074 mp->newOrder = param;
1075 mp->newOrderSet = TRUE; 1075 mp->newOrderSet = true;
1076 mp->jumpFlag = TRUE; 1076 mp->jumpFlag = true;
1077 mp->lastPatLoopRow = 0; 1077 mp->lastPatLoopRow = 0;
1078 break; 1078 break;
1079 1079
1080 case 'C': // Cxx = Set Volume : IMPL.VERIFIED 1080 case 'C': // Cxx = Set Volume : IMPL.VERIFIED
1081 jmpSetVolume(chn, channel, param); 1081 jmpSetVolume(chn, channel, param);
1085 // Compute the new row 1085 // Compute the new row
1086 mp->newRow = (paramX * 10) + paramY; 1086 mp->newRow = (paramX * 10) + paramY;
1087 if (mp->newRow >= mp->pattern->nrows) 1087 if (mp->newRow >= mp->pattern->nrows)
1088 mp->newRow = 0; 1088 mp->newRow = 0;
1089 1089
1090 mp->newRowSet = TRUE; 1090 mp->newRowSet = true;
1091 1091
1092 // Now we do some tricky tests 1092 // Now we do some tricky tests
1093 if (!mp->breakFlag && !mp->jumpFlag) 1093 if (!mp->breakFlag && !mp->jumpFlag)
1094 { 1094 {
1095 mp->newOrder = mp->order + 1; 1095 mp->newOrder = mp->order + 1;
1096 mp->newOrderSet = TRUE; 1096 mp->newOrderSet = true;
1097 } 1097 }
1098 1098
1099 mp->breakFlag = TRUE; 1099 mp->breakFlag = true;
1100 break; 1100 break;
1101 1101
1102 case 'E': // Exy = Special Effects 1102 case 'E': // Exy = Special Effects
1103 switch (paramX) 1103 switch (paramX)
1104 { 1104 {
1144 JMPSETNDFLAGS(cdfNewPanPos); 1144 JMPSETNDFLAGS(cdfNewPanPos);
1145 break; 1145 break;
1146 1146
1147 case 0x09: // E9x - Retrig note 1147 case 0x09: // E9x - Retrig note
1148 if (mp->tick == paramY) 1148 if (mp->tick == paramY)
1149 jmpTriggerNote(mp, chn, FALSE); 1149 jmpTriggerNote(mp, chn, false);
1150 break; 1150 break;
1151 1151
1152 case 0x0a: // EAx - Fine Volumeslide Up 1152 case 0x0a: // EAx - Fine Volumeslide Up
1153 if (paramY) 1153 if (paramY)
1154 chn->iCLastFineVolumeslideUpParam = paramY; 1154 chn->iCLastFineVolumeslideUpParam = paramY;
1207 case 'H': // Hxx = Global Volume Slide 1207 case 'H': // Hxx = Global Volume Slide
1208 JMPDEBUG("Global Volume Slide used, UNIMPLEMENTED"); 1208 JMPDEBUG("Global Volume Slide used, UNIMPLEMENTED");
1209 break; 1209 break;
1210 1210
1211 case 'K': // Kxx = Key-off (Same as key-off note) 1211 case 'K': // Kxx = Key-off (Same as key-off note)
1212 chn->keyOff = TRUE; 1212 chn->keyOff = true;
1213 break; 1213 break;
1214 1214
1215 case 'L': // Lxx = Set Envelope Position 1215 case 'L': // Lxx = Set Envelope Position
1216 JMPDEBUG("Set Envelope Position used, NOT verified with FT2"); 1216 JMPDEBUG("Set Envelope Position used, NOT verified with FT2");
1217 chn->panningEnv.frame = param; 1217 chn->panningEnv.frame = param;
1218 chn->volumeEnv.frame = param; 1218 chn->volumeEnv.frame = param;
1219 chn->panningEnv.exec = TRUE; 1219 chn->panningEnv.exec = true;
1220 chn->volumeEnv.exec = TRUE; 1220 chn->volumeEnv.exec = true;
1221 break; 1221 break;
1222 1222
1223 case 'R': // Rxy = Multi Retrig note 1223 case 'R': // Rxy = Multi Retrig note
1224 if (paramX != 0) 1224 if (paramX != 0)
1225 chn->lastMultiRetrigParamX = paramX; 1225 chn->lastMultiRetrigParamX = paramX;
1345 case 'E': // Exy = Special Effects 1345 case 'E': // Exy = Special Effects
1346 switch (paramX) 1346 switch (paramX)
1347 { 1347 {
1348 case 0x09: // E9x - Retrig note 1348 case 0x09: // E9x - Retrig note
1349 if (mp->tick == paramY) 1349 if (mp->tick == paramY)
1350 jmpTriggerNote(mp, chn, FALSE); 1350 jmpTriggerNote(mp, chn, false);
1351 break; 1351 break;
1352 1352
1353 case 0x0c: // ECx - Set Note Cut 1353 case 0x0c: // ECx - Set Note Cut
1354 if (mp->tick == paramY) 1354 if (mp->tick == paramY)
1355 jmpSetVolume(chn, channel, jsetMinVol); 1355 jmpSetVolume(chn, channel, jsetMinVol);
1401 // Check if we are playing 1401 // Check if we are playing
1402 if (!mp->isPlaying) 1402 if (!mp->isPlaying)
1403 goto out; 1403 goto out;
1404 1404
1405 // Clear channel new data flags 1405 // Clear channel new data flags
1406 mp->jumpFlag = FALSE; 1406 mp->jumpFlag = false;
1407 mp->breakFlag = FALSE; 1407 mp->breakFlag = false;
1408 1408
1409 for (int channel = 0; channel < jsetNChannels; channel++) 1409 for (int channel = 0; channel < jsetNChannels; channel++)
1410 mp->channels[channel].newDataFlags = 0; 1410 mp->channels[channel].newDataFlags = 0;
1411 1411
1412 //fprintf(stderr, "1: tick=%d, order=%d, iPattern=%d, row=%d\n", mp->tick, mp->order, mp->npattern, mp->row); 1412 //fprintf(stderr, "1: tick=%d, order=%d, iPattern=%d, row=%d\n", mp->tick, mp->order, mp->npattern, mp->row);
1414 // Check for init-tick 1414 // Check for init-tick
1415 if (mp->tick == jsetNotSet) 1415 if (mp->tick == jsetNotSet)
1416 { 1416 {
1417 // Initialize pattern 1417 // Initialize pattern
1418 mp->newRow = 0; 1418 mp->newRow = 0;
1419 mp->newRowSet = TRUE; 1419 mp->newRowSet = true;
1420 mp->tick = mp->speed; 1420 mp->tick = mp->speed;
1421 mp->patternDelay = 0; 1421 mp->patternDelay = 0;
1422 } 1422 }
1423 1423
1424 //fprintf(stderr, "2: tick=%d, order=%d, iPattern=%d, row=%d\n", mp->tick, mp->order, mp->npattern, mp->row); 1424 //fprintf(stderr, "2: tick=%d, order=%d, iPattern=%d, row=%d\n", mp->tick, mp->order, mp->npattern, mp->row);
1443 { 1443 {
1444 // New pattern row 1444 // New pattern row
1445 if (mp->newRowSet) 1445 if (mp->newRowSet)
1446 { 1446 {
1447 mp->row = mp->newRow; 1447 mp->row = mp->newRow;
1448 mp->newRowSet = FALSE; 1448 mp->newRowSet = false;
1449 } else 1449 } else
1450 mp->row++; 1450 mp->row++;
1451 1451
1452 // Check for end of pattern 1452 // Check for end of pattern
1453 if (mp->row >= mp->pattern->nrows) 1453 if (mp->row >= mp->pattern->nrows)
1454 { 1454 {
1455 // Go to next order 1455 // Go to next order
1456 if (mp->order != jsetNotSet) 1456 if (mp->order != jsetNotSet)
1457 jmpSetNewOrder(mp, mp->order + 1); 1457 jmpSetNewOrder(mp, mp->order + 1);
1458 else 1458 else
1459 mp->isPlaying = FALSE; 1459 mp->isPlaying = false;
1460 1460
1461 // Check for FT2 quirks 1461 // Check for FT2 quirks
1462 if (JMPGETMODFLAGS(mp, jmdfFT2Replay)) 1462 if (JMPGETMODFLAGS(mp, jmdfFT2Replay))
1463 mp->row = mp->lastPatLoopRow; 1463 mp->row = mp->lastPatLoopRow;
1464 else 1464 else
1470 1470
1471 // Check current order 1471 // Check current order
1472 if (mp->newOrderSet) 1472 if (mp->newOrderSet)
1473 { 1473 {
1474 jmpSetNewOrder(mp, mp->newOrder); 1474 jmpSetNewOrder(mp, mp->newOrder);
1475 mp->newOrderSet = FALSE; 1475 mp->newOrderSet = false;
1476 } 1476 }
1477 1477
1478 //fprintf(stderr, "3: tick=%d, order=%d, iPattern=%d, row=%d\n", mp->tick, mp->order, mp->npattern, mp->row); 1478 //fprintf(stderr, "3: tick=%d, order=%d, iPattern=%d, row=%d\n", mp->tick, mp->order, mp->npattern, mp->row);
1479 1479
1480 if (!mp->isPlaying) 1480 if (!mp->isPlaying)
1549 if (flags & cdfNewPos) 1549 if (flags & cdfNewPos)
1550 jvmSetPos(mp->device, channel, chn->position); 1550 jvmSetPos(mp->device, channel, chn->position);
1551 1551
1552 if (flags & cdfNewVolume) 1552 if (flags & cdfNewVolume)
1553 { 1553 {
1554 BOOL init = flags & (cdfNewInstr | cdfPlay); 1554 bool init = flags & (cdfNewInstr | cdfPlay);
1555 jvmSetVolumeRamp(mp->device, channel, 1555 jvmSetVolumeRamp(mp->device, channel,
1556 init ? 0 : jvmGetVolume(mp->device, channel), 1556 init ? 0 : jvmGetVolume(mp->device, channel),
1557 (chn->fadeOutVol * chn->volumeEnv.value * chn->volume) / (16 * 65536), 1557 (chn->fadeOutVol * chn->volumeEnv.value * chn->volume) / (16 * 65536),
1558 init ? 5 : 0); 1558 init ? 5 : 0);
1559 } 1559 }