Vibrato optimizations (#530)

Optimize vibrato to even exceed vanilla's implementation, all without restricting usability from the current implementation. This should save up to about 1ms of audio runtime.
This commit is contained in:
Gregory Heskett
2023-01-20 17:45:53 -05:00
committed by GitHub
parent 65d29dc337
commit dc71aef024
6 changed files with 68 additions and 30 deletions

View File

@@ -226,7 +226,7 @@ chan_end
.delay_interrupt: .delay_interrupt:
chan_setpanmix 127 chan_setpanmix 127
chan_setvolscale 127 chan_setvolscale 127
chan_setvibratoextent 0 chan_setvibratoextent 0xff // 0xff represents disabled value
chan_ioreadval 1 // IO slots 0-3 are reset to -1 when read; restore the value chan_ioreadval 1 // IO slots 0-3 are reset to -1 when read; restore the value
chan_iowriteval 0 chan_iowriteval 0
chan_break // break out of the loop chan_break // break out of the loop
@@ -1147,6 +1147,9 @@ chan_setbank 4
chan_setinstr 14 chan_setinstr 14
chan_setdecayrelease 12 chan_setdecayrelease 12
chan_setvibratoextent 10 chan_setvibratoextent 10
chan_setval 0x7f
chan_call .delay
chan_setvibratoextent 0xff
chan_end chan_end
.layer_68F: .layer_68F:
@@ -1317,7 +1320,7 @@ chan_setlayer 0, .layer_79D
chan_setlayer 1, .layer_79B chan_setlayer 1, .layer_79B
chan_setval 36 chan_setval 36
chan_call .delay chan_call .delay
chan_setvibratoextent 0 chan_setvibratoextent 0xff
chan_end chan_end
.layer_79B: .layer_79B:
@@ -3025,6 +3028,9 @@ chan_setvibratorate 60
chan_setval 25 chan_setval 25
chan_call .set_reverb chan_call .set_reverb
chan_setlayer 0, .layer_11E4 chan_setlayer 0, .layer_11E4
chan_setval 0x45
chan_call .delay
chan_setvibratoextent 0xff
chan_end chan_end
.layer_11E4: .layer_11E4:
@@ -3070,7 +3076,7 @@ chan_setbank 4
chan_setinstr 6 chan_setinstr 6
chan_setval 49 chan_setval 49
chan_call .delay chan_call .delay
chan_setvibratoextent 0 chan_setvibratoextent 0xff
chan_end chan_end
.layer_1242: .layer_1242:
@@ -4389,7 +4395,7 @@ chan_setlayer 0, .layer_1AEB
chan_setlayer 1, .layer_1AE9 chan_setlayer 1, .layer_1AE9
chan_setval 35 chan_setval 35
chan_call .delay chan_call .delay
chan_setvibratoextent 0 chan_setvibratoextent 0xff
chan_end chan_end
.layer_1AE9: .layer_1AE9:
@@ -6055,7 +6061,7 @@ chan_setvibratorate 60
chan_setlayer 0, .layer_259B chan_setlayer 0, .layer_259B
chan_setval 30 chan_setval 30
chan_call .delay chan_call .delay
chan_setvibratoextent 0 chan_setvibratoextent 0xff
chan_end chan_end
.layer_259B: .layer_259B:
@@ -6189,7 +6195,7 @@ chan_setvibratorate 5
chan_setlayer 0, .layer_2684 chan_setlayer 0, .layer_2684
chan_setval 88 chan_setval 88
chan_call .delay chan_call .delay
chan_setvibratoextent 0 chan_setvibratoextent 0xff
chan_end chan_end
.layer_2684: .layer_2684:
@@ -6360,7 +6366,7 @@ chan_setlayer 0, .layer_27B7
chan_setlayer 1, .layer_27B5 chan_setlayer 1, .layer_27B5
chan_setval 56 chan_setval 56
chan_call .delay chan_call .delay
chan_setvibratoextent 0 chan_setvibratoextent 0xff
chan_end chan_end
.layer_27B5: .layer_27B5:
@@ -7067,6 +7073,9 @@ chan_setenvelope .envelope_3444
chan_setvibratorate 1 chan_setvibratorate 1
chan_setvibratoextent 100 chan_setvibratoextent 100
chan_setlayer 0, .layer_2CA0 chan_setlayer 0, .layer_2CA0
chan_setval 0x12
chan_call .delay
chan_setvibratoextent 0xff
chan_end chan_end
.layer_2CA0: .layer_2CA0:
@@ -7094,7 +7103,7 @@ chan_call .delay
chan_setvibratoextent 80 chan_setvibratoextent 80
chan_setval 67 chan_setval 67
chan_call .delay chan_call .delay
chan_setvibratoextent 0 chan_setvibratoextent 0xff
chan_end chan_end
.layer_2CD6: .layer_2CD6:
@@ -7292,6 +7301,13 @@ chan_setval 70
chan_call .delay chan_call .delay
chan_setbank 10 chan_setbank 10
chan_setinstr 8 chan_setinstr 8
chan_setval 0x7f
chan_call .delay
chan_setval 0x7f
chan_call .delay
chan_setval 0x4
chan_call .delay
chan_setvibratoextent 0xff
chan_end chan_end
.layer_2E28: .layer_2E28:

View File

@@ -189,23 +189,33 @@ s32 get_vibrato_pitch_change(struct VibratoState *vib) {
#endif #endif
f32 get_vibrato_freq_scale(struct VibratoState *vib) { f32 get_vibrato_freq_scale(struct VibratoState *vib) {
s32 vibratoExtentTarget;
if (vib->delay != 0) { if (vib->delay != 0) {
vib->delay--; vib->delay--;
return 1; return 1;
} }
// This needs to be set locally because changing the original value to 0 overrides the whole channel,
// effectively negating the ability to disable vibrato and bypass this function in the first place.
// This function isn't huge but it otherwise would get called many thousands of times per second.
vibratoExtentTarget = vib->seqChannel->vibratoExtentTarget;
if (vibratoExtentTarget >= VIBRATO_DISABLED_VALUE) {
vibratoExtentTarget = 0;
}
if (vib->extentChangeTimer) { if (vib->extentChangeTimer) {
if (vib->extentChangeTimer == 1) { if (vib->extentChangeTimer == 1) {
vib->extent = (s32) vib->seqChannel->vibratoExtentTarget; vib->extent = vibratoExtentTarget;
} else { } else {
vib->extent += vib->extent +=
((s32) vib->seqChannel->vibratoExtentTarget - vib->extent) / (s32) vib->extentChangeTimer; (vibratoExtentTarget - vib->extent) / (s32) vib->extentChangeTimer;
} }
vib->extentChangeTimer--; vib->extentChangeTimer--;
} else if (vib->seqChannel->vibratoExtentTarget != (s32) vib->extent) { } else if (vibratoExtentTarget != (s32) vib->extent) {
if ((vib->extentChangeTimer = vib->seqChannel->vibratoExtentChangeDelay) == 0) { if ((vib->extentChangeTimer = vib->seqChannel->vibratoExtentChangeDelay) == 0) {
vib->extent = (s32) vib->seqChannel->vibratoExtentTarget; vib->extent = vibratoExtentTarget;
} }
} }
@@ -246,11 +256,11 @@ void note_vibrato_update(struct Note *note) {
note->vibratoFreqScale = get_vibrato_freq_scale(&note->vibratoState); note->vibratoFreqScale = get_vibrato_freq_scale(&note->vibratoState);
} }
#else #else
if (note->vibratoState.active) { if (note->vibratoState.activeFlags & VIBMODE_PORTAMENTO) {
note->portamentoFreqScale = get_portamento_freq_scale(&note->portamento); note->portamentoFreqScale = get_portamento_freq_scale(&note->portamento);
if (note->parentLayer != NO_LAYER) { }
note->vibratoFreqScale = get_vibrato_freq_scale(&note->vibratoState); if ((note->vibratoState.activeFlags & VIBMODE_VIBRATO) && note->parentLayer != NO_LAYER) {
} note->vibratoFreqScale = get_vibrato_freq_scale(&note->vibratoState);
} }
#endif #endif
} }
@@ -265,18 +275,23 @@ void note_vibrato_init(struct Note *note) {
struct VibratoState *vib = &note->vibratoState; struct VibratoState *vib = &note->vibratoState;
/* This code was probably removed from EU and SH for a reason; probably because it's dumb and makes vibrato harder to use well.
#if defined(VERSION_JP) || defined(VERSION_US) #if defined(VERSION_JP) || defined(VERSION_US)
if (note->parentLayer->seqChannel->vibratoExtentStart == 0 vib->activeFlags = VIBMODE_NONE;
&& note->parentLayer->seqChannel->vibratoExtentTarget == 0 if (note->parentLayer->portamento.mode != 0) {
&& note->parentLayer->portamento.mode == 0) { vib->activeFlags |= VIBMODE_PORTAMENTO;
vib->active = FALSE; note->portamento = note->parentLayer->portamento;
}
if (!(note->parentLayer->seqChannel->vibratoExtentStart == 0
&& note->parentLayer->seqChannel->vibratoExtentTarget >= VIBRATO_DISABLED_VALUE)) {
vib->activeFlags |= VIBMODE_VIBRATO;
} else {
return; return;
} }
#endif #else
*/
vib->active = TRUE; vib->active = TRUE;
#endif
vib->time = 0; vib->time = 0;
#if defined(VERSION_EU) || defined(VERSION_SH) #if defined(VERSION_EU) || defined(VERSION_SH)
@@ -313,8 +328,6 @@ void note_vibrato_init(struct Note *note) {
vib->rate = seqChannel->vibratoRateStart; vib->rate = seqChannel->vibratoRateStart;
} }
vib->delay = seqChannel->vibratoDelay; vib->delay = seqChannel->vibratoDelay;
note->portamento = note->parentLayer->portamento;
#endif #endif
} }

View File

@@ -31,6 +31,12 @@ enum ADSRDelays {
ADSR_RESTART = -3, ADSR_RESTART = -3,
}; };
enum VibratoModes {
VIBMODE_NONE = 0,
VIBMODE_VIBRATO = (1 << 0),
VIBMODE_PORTAMENTO = (1 << 1),
};
// Envelopes are always stored as big endian, to match sequence files which are // Envelopes are always stored as big endian, to match sequence files which are
// byte blobs and can embed envelopes. Hence this byteswapping macro. // byte blobs and can embed envelopes. Hence this byteswapping macro.
#if IS_BIG_ENDIAN #if IS_BIG_ENDIAN

View File

@@ -27,6 +27,8 @@
#endif #endif
#endif // EXPAND_AUDIO_HEAP #endif // EXPAND_AUDIO_HEAP
#define VIBRATO_DISABLED_VALUE (0xFF * 8)
#define NO_LAYER ((struct SequenceChannelLayer *)(-1)) #define NO_LAYER ((struct SequenceChannelLayer *)(-1))
enum MuteBehaviors { enum MuteBehaviors {
@@ -139,7 +141,7 @@ struct VibratoState {
/* , 0x14*/ u8 active; /* , 0x14*/ u8 active;
#else #else
/*0x08, */ s8 *curve; /*0x08, */ s8 *curve;
/*0x0C, */ u8 active; /*0x0C, */ u8 activeFlags;
/*0x0E, */ u16 rate; /*0x0E, */ u16 rate;
/*0x10, */ u16 extent; /*0x10, */ u16 extent;
#endif #endif

View File

@@ -1423,6 +1423,7 @@ void note_init_all(void) {
note->prevParentLayer = NO_LAYER; note->prevParentLayer = NO_LAYER;
#if defined(VERSION_EU) || defined(VERSION_SH) #if defined(VERSION_EU) || defined(VERSION_SH)
note->waveId = 0; note->waveId = 0;
note->vibratoState.active = FALSE;
#else #else
note->reverbVol = 0; note->reverbVol = 0;
note->usesHeadsetPanEffects = FALSE; note->usesHeadsetPanEffects = FALSE;
@@ -1432,12 +1433,12 @@ void note_init_all(void) {
note->targetVolRight = 0; note->targetVolRight = 0;
note->frequency = 0.0f; note->frequency = 0.0f;
note->unused1 = 0x3f; note->unused1 = 0x3f;
note->vibratoState.activeFlags = VIBMODE_NONE;
#endif #endif
note->attributes.velocity = 0.0f; note->attributes.velocity = 0.0f;
note->adsrVolScale = 0; note->adsrVolScale = 0;
note->adsr.state = ADSR_STATE_DISABLED; note->adsr.state = ADSR_STATE_DISABLED;
note->adsr.action = 0; note->adsr.action = 0;
note->vibratoState.active = FALSE;
note->portamento.cur = 0.0f; note->portamento.cur = 0.0f;
note->portamento.speed = 0.0f; note->portamento.speed = 0.0f;
#if defined(VERSION_SH) #if defined(VERSION_SH)

View File

@@ -64,7 +64,7 @@ void sequence_channel_init(struct SequenceChannel *seqChannel) {
#endif #endif
seqChannel->vibratoRateTarget = 0x800; seqChannel->vibratoRateTarget = 0x800;
seqChannel->vibratoRateStart = 0x800; seqChannel->vibratoRateStart = 0x800;
seqChannel->vibratoExtentTarget = 0; seqChannel->vibratoExtentTarget = VIBRATO_DISABLED_VALUE;
seqChannel->vibratoExtentStart = 0; seqChannel->vibratoExtentStart = 0;
seqChannel->vibratoRateChangeDelay = 0; seqChannel->vibratoRateChangeDelay = 0;
seqChannel->vibratoExtentChangeDelay = 0; seqChannel->vibratoExtentChangeDelay = 0;
@@ -1942,7 +1942,7 @@ void sequence_channel_process_script(struct SequenceChannel *seqChannel) {
break; break;
case 0xec: case 0xec:
seqChannel->vibratoExtentTarget = 0; seqChannel->vibratoExtentTarget = VIBRATO_DISABLED_VALUE;
seqChannel->vibratoExtentStart = 0; seqChannel->vibratoExtentStart = 0;
seqChannel->vibratoExtentChangeDelay = 0; seqChannel->vibratoExtentChangeDelay = 0;
seqChannel->vibratoRateTarget = 0; seqChannel->vibratoRateTarget = 0;