Aid VSU performance
This commit is contained in:
parent
e97b52e944
commit
bc864644f7
|
@ -64,7 +64,9 @@ typedef struct {
|
|||
} wave;
|
||||
|
||||
/* Other state */
|
||||
uint32_t clocks; /* Clocks until next sample */
|
||||
uint32_t clocks; /* Clocks until next wave or noise sample */
|
||||
uint8_t freqmod; /* Frequency modifications are active */
|
||||
uint32_t until; /* Clocks until channel component update */
|
||||
} Channel;
|
||||
|
||||
/* Simulation state */
|
||||
|
|
183
core/vsu.c
183
core/vsu.c
|
@ -74,100 +74,57 @@ static void vsuNextFreqMod(VB *sim, Channel *chan) {
|
|||
}
|
||||
|
||||
/* Process one channel */
|
||||
static void vsuEmulateChannel(VB *sim, int index, uint32_t clocks) {
|
||||
uint32_t bit; /* Pseudorandom bit */
|
||||
Channel *chan; /* Channel handle */
|
||||
int freqmod; /* Frequency modifications enabled */
|
||||
uint32_t until; /* Clocks to process sub-channel components */
|
||||
static void vsuEmulateChannel(VB *sim, Channel *chan, uint32_t clocks) {
|
||||
uint32_t bit; /* Pseudorandom bit */
|
||||
|
||||
/* Select channel */
|
||||
chan = &sim->vsu.channels[index];
|
||||
|
||||
/* Channel is disabled */
|
||||
if (!chan->int_.enb)
|
||||
/* Automatic shutoff */
|
||||
if (chan->int_.auto_ && chan->int_.clocks == 0) {
|
||||
chan->int_.enb = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Frequency modifications are active */
|
||||
freqmod =
|
||||
index == 4 && /* Channel 5 */
|
||||
sim->vsu.freqmod.enb && /* Modifications enabled */
|
||||
sim->vsu.freqmod.interval != 0 /* Modifications valid */
|
||||
;
|
||||
/* Next input sample */
|
||||
if (chan->clocks == 0) {
|
||||
|
||||
/* Process all clocks */
|
||||
do {
|
||||
/* Wave */
|
||||
if (chan != &sim->vsu.channels[5]) {
|
||||
chan->clocks = 4 * (2048 - (uint32_t) chan->freq.current);
|
||||
chan->wave.sample = (chan->wave.sample + 1) & 31;
|
||||
}
|
||||
|
||||
/* Clocks until next state change */
|
||||
until = clocks;
|
||||
if (chan->clocks < until)
|
||||
until = chan->clocks;
|
||||
if (chan->env.enb && chan->env.clocks < until)
|
||||
until = chan->env.clocks;
|
||||
if (chan->int_.auto_ && chan->int_.clocks < until)
|
||||
until = chan->int_.clocks;
|
||||
if (freqmod && sim->vsu.freqmod.clocks < until)
|
||||
until = sim->vsu.freqmod.clocks;
|
||||
/* Noise */
|
||||
else {
|
||||
chan->clocks = 40 * (2048 - (uint32_t) chan->freq.current);
|
||||
bit = ((
|
||||
sim->vsu.noise.register_ >> NOISE_TAPS[sim->vsu.noise.tap]^
|
||||
sim->vsu.noise.register_ >> 7
|
||||
) & 1) ^ 1;
|
||||
sim->vsu.noise.register_ = bit |
|
||||
(sim->vsu.noise.register_ << 1 & 0x7FFE);
|
||||
}
|
||||
|
||||
/* Manage clocks */
|
||||
clocks -= until;
|
||||
chan->clocks -= until;
|
||||
if (chan->env.enb)
|
||||
chan->env.clocks -= until;
|
||||
if (chan->int_.auto_)
|
||||
chan->int_.clocks -= until;
|
||||
if (freqmod)
|
||||
sim->vsu.freqmod.clocks -= until;
|
||||
}
|
||||
|
||||
/* Automatic shutoff */
|
||||
if (chan->int_.auto_ && chan->int_.clocks == 0) {
|
||||
chan->int_.enb = 0;
|
||||
/* Envelope modification */
|
||||
if (chan->env.enb && chan->env.clocks == 0) {
|
||||
if (chan->env.dir == 0 && chan->env.value != 0)
|
||||
chan->env.value--;
|
||||
else if (chan->env.dir == 1 && chan->env.value != 15)
|
||||
chan->env.value++;
|
||||
else if (chan->env.rep)
|
||||
chan->env.value = chan->env.reload;
|
||||
chan->env.clocks = ((uint32_t) chan->env.interval + 1) * 307220;
|
||||
}
|
||||
|
||||
/* Frequency modification */
|
||||
if (chan->freqmod && sim->vsu.freqmod.clocks == 0) {
|
||||
chan->freq.current = sim->vsu.freqmod.next;
|
||||
vsuNextFreqMod(sim, chan);
|
||||
if (!chan->int_.enb)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Next sample */
|
||||
if (chan->clocks == 0) {
|
||||
|
||||
/* Wave */
|
||||
if (index != 5) {
|
||||
chan->clocks = 4 * (2048 - (uint32_t) chan->freq.current);
|
||||
chan->wave.sample = (chan->wave.sample + 1) & 31;
|
||||
}
|
||||
|
||||
/* Noise */
|
||||
else {
|
||||
chan->clocks = 40 * (2048 - (uint32_t) chan->freq.current);
|
||||
bit = ((
|
||||
sim->vsu.noise.register_ >> NOISE_TAPS[sim->vsu.noise.tap]^
|
||||
sim->vsu.noise.register_ >> 7
|
||||
) & 1) ^ 1;
|
||||
sim->vsu.noise.register_ = bit |
|
||||
(sim->vsu.noise.register_ << 1 & 0x7FFE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Envelope modification */
|
||||
if (chan->env.enb && chan->env.clocks == 0) {
|
||||
if (chan->env.dir == 0 && chan->env.value != 0)
|
||||
chan->env.value--;
|
||||
else if (chan->env.dir == 1 && chan->env.value != 15)
|
||||
chan->env.value++;
|
||||
else if (chan->env.rep)
|
||||
chan->env.value = chan->env.reload;
|
||||
chan->env.clocks = ((uint32_t) chan->env.interval + 1) * 307220;
|
||||
}
|
||||
|
||||
/* Frequency modification */
|
||||
if (freqmod && sim->vsu.freqmod.clocks == 0) {
|
||||
chan->freq.current = sim->vsu.freqmod.next;
|
||||
vsuNextFreqMod(sim, chan);
|
||||
if (!chan->int_.enb)
|
||||
return;
|
||||
sim->vsu.freqmod.clocks = (uint32_t) sim->vsu.freqmod.interval *
|
||||
(sim->vsu.freqmod.clk == 0 ? 19200 : 153600);
|
||||
}
|
||||
|
||||
} while (clocks != 0);
|
||||
sim->vsu.freqmod.clocks = (uint32_t) sim->vsu.freqmod.interval *
|
||||
(sim->vsu.freqmod.clk == 0 ? 19200 : 153600);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -230,6 +187,8 @@ static void vsuWriteEV1(VB *sim, int index, uint8_t value) {
|
|||
sim->vsu.freqmod.func = value >> 4 & 1;
|
||||
sim->vsu.freqmod.rep = value >> 5 & 1;
|
||||
vsuNextFreqMod(sim, chan);
|
||||
chan->freqmod =
|
||||
sim->vsu.freqmod.enb && sim->vsu.freqmod.interval != 0;
|
||||
break;
|
||||
|
||||
case 5: /* Channel 6 */
|
||||
|
@ -313,6 +272,8 @@ static void vsuWriteSWP(VB *sim, uint8_t value) {
|
|||
(sim->vsu.freqmod.clk == 0 ? 19200 : 153600);
|
||||
if (clocks < sim->vsu.freqmod.clocks)
|
||||
sim->vsu.freqmod.clocks = clocks;
|
||||
sim->vsu.channels[4].freqmod =
|
||||
sim->vsu.freqmod.enb && sim->vsu.freqmod.interval != 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -321,6 +282,8 @@ static void vsuWriteSWP(VB *sim, uint8_t value) {
|
|||
|
||||
/* Process component */
|
||||
static void vsuEmulate(VB *sim, uint32_t clocks) {
|
||||
Channel *chan; /* Input channel */
|
||||
uint32_t chantil; /* Clocks until next channel state update */
|
||||
float i0; /* Current analog input sample */
|
||||
float o0; /* Current analog output sample */
|
||||
uint16_t output[2]; /* Digital output samples */
|
||||
|
@ -340,8 +303,50 @@ static void vsuEmulate(VB *sim, uint32_t clocks) {
|
|||
sim->vsu.clocks -= until;
|
||||
|
||||
/* Process all channels */
|
||||
for (x = 0; x < 6; x++)
|
||||
vsuEmulateChannel(sim, x, until);
|
||||
for (x = 0; x < 6; x++) {
|
||||
chan = &sim->vsu.channels[x];
|
||||
chantil = until;
|
||||
|
||||
/* Process all clocks */
|
||||
while (chan->int_.enb && chantil != 0) {
|
||||
|
||||
/* Determine when the next state change will occur */
|
||||
if (chan->until == 0) {
|
||||
|
||||
/* Clocks until next state change */
|
||||
chan->until = chan->clocks;
|
||||
if (chan->env.enb && chan->env.clocks < chan->until)
|
||||
chan->until = chan->env.clocks;
|
||||
if (chan->int_.auto_ && chan->int_.clocks < chan->until)
|
||||
chan->until = chan->int_.clocks;
|
||||
if (chan->freqmod && sim->vsu.freqmod.clocks < chan->until)
|
||||
chan->until = sim->vsu.freqmod.clocks;
|
||||
|
||||
/* Manage clocks */
|
||||
chan->clocks -= chan->until;
|
||||
if (chan->env.enb)
|
||||
chan->env.clocks -= chan->until;
|
||||
if (chan->int_.auto_)
|
||||
chan->int_.clocks -= chan->until;
|
||||
if (chan->freqmod)
|
||||
sim->vsu.freqmod.clocks -= chan->until;
|
||||
}
|
||||
|
||||
/* Manage clocks */
|
||||
if (chan->until > chantil) {
|
||||
chan->until -= chantil;
|
||||
chantil = 0;
|
||||
} else {
|
||||
chantil -= chan->until;
|
||||
chan->until = 0;
|
||||
}
|
||||
|
||||
/* Update channel state */
|
||||
if (chan->until == 0)
|
||||
vsuEmulateChannel(sim, chan, chan->until);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Wait for the current sample to finish */
|
||||
if (sim->vsu.clocks != 0)
|
||||
|
@ -416,6 +421,8 @@ static void vsuReset(VB *sim) {
|
|||
for (x = 0; x < 6; x++) {
|
||||
chan = &sim->vsu.channels[x];
|
||||
chan->clocks = 0;
|
||||
chan->freqmod = 0;
|
||||
chan->until = 0;
|
||||
chan->env.clocks = 0;
|
||||
chan->env.enb = 0;
|
||||
chan->env.dir = 0;
|
||||
|
|
Loading…
Reference in New Issue