implement tremolo in command stream player

This commit is contained in:
tildearrow 2026-01-10 03:44:58 -05:00
parent 5037e90906
commit ef11c2bf97
2 changed files with 35 additions and 6 deletions

View file

@ -172,6 +172,7 @@ bool DivCSPlayer::tick() {
case 0xc8: // vol slide
chan[i].volSpeed=(short)(bigEndian?stream.readS_BE():stream.readS());
chan[i].volSpeedTarget=-1;
chan[i].tremoloDepth=0;
break;
case 0xc9: // porta
chan[i].portaTarget=(int)((unsigned char)stream.readC())-60;
@ -195,11 +196,18 @@ bool DivCSPlayer::tick() {
chan[i].volSpeedTarget=arg0==0 ? -1 : arg1;
break;
}
case 0xcc: // tremolo (TODO)
stream.readC();
case 0xcc: // tremolo
unsigned char param=stream.readC();
chan[i].tremoloDepth=param&15;
chan[i].tremoloRate=param>>4;
chan[i].volSpeed=0;
chan[i].volSpeedTarget=-1;
sendVolume=true;
break;
case 0xcd: // panbrello (TODO)
stream.readC();
case 0xcd: // panbrello
unsigned char param=stream.readC();
chan[i].panbrelloDepth=param&15;
chan[i].panbrelloRate=param>>4;
break;
case 0xce: // pan slide (TODO)
stream.readC();
@ -554,7 +562,7 @@ bool DivCSPlayer::tick() {
if (mustTell) chan[i].readPos=stream.tell();
}
if (sendVolume || chan[i].volSpeed!=0) {
if (sendVolume || chan[i].volSpeed!=0 || chan[i].tremoloDepth!=0) {
int preSpeedVol=chan[i].volume;
chan[i].volume+=chan[i].volSpeed;
if (chan[i].volSpeedTarget!=-1) {
@ -578,13 +586,20 @@ bool DivCSPlayer::tick() {
chan[i].volSpeedTarget=-1;
}
}
if (chan[i].volume<0) {
chan[i].volume=0;
}
if (chan[i].volume>chan[i].volMax) {
chan[i].volume=chan[i].volMax;
}
e->dispatchCmd(DivCommand(DIV_CMD_VOLUME,i,chan[i].volume>>8));
if (chan[i].tremoloDepth>0) {
chan[i].tremoloPos+=chan[i].tremoloRate;
chan[i].tremoloPos&=127;
dispatchCmd(DivCommand(DIV_CMD_VOLUME,i,MAX(0,chan[i].volume-(tremTable[chan[i].tremoloPos]*chan[i].tremoloDepth))>>8));
} else {
e->dispatchCmd(DivCommand(DIV_CMD_VOLUME,i,chan[i].volume>>8));
}
}
if (sendPitch || chan[i].vibratoDepth!=0) {
@ -716,6 +731,9 @@ bool DivCSPlayer::init() {
for (int i=0; i<64; i++) {
vibTable[i]=127*sin(((double)i/64.0)*(2*M_PI));
}
for (int i=0; i<128; i++) {
tremTable[i]=255*0.5*(1.0-cos(((double)i/128.0)*(2*M_PI)));
}
arpSpeed=1;
bAccessTS=new unsigned short[bLen];

View file

@ -37,6 +37,8 @@ struct DivCSChannelState {
int note, pitch;
int volume, volMax, volSpeed, volSpeedTarget;
int vibratoDepth, vibratoRate, vibratoPos, vibratoRange, vibratoShape;
int tremoloDepth, tremoloRate, tremoloPos;
int panbrelloDepth, panbrelloRate, panbrelloPos;
int portaTarget, portaSpeed;
unsigned char arp, arpStage, arpTicks;
@ -61,6 +63,14 @@ struct DivCSChannelState {
vibratoDepth(0),
vibratoRate(0),
vibratoPos(0),
vibratoRange(15),
vibratoShape(0),
tremoloDepth(0),
tremoloRate(0),
tremoloPos(0),
panbrelloDepth(0),
panbrelloRate(0),
panbrelloPos(0),
portaTarget(0),
portaSpeed(0),
arp(0),
@ -93,6 +103,7 @@ class DivCSPlayer {
bool bigEndian;
short vibTable[64];
short tremTable[128];
public:
unsigned char* getData();
unsigned short* getDataAccess();