ref: ba9a38b8266fd42f2bc327b7e6e60866812cbb92
parent: 462b3d46f1cb6d0e26539d4f8d5de7a85afeb430
author: Olav Sørensen <olav.sorensen@live.no>
date: Wed Jun 7 13:08:12 EDT 2023
A couple of minor changes to the visuals
--- a/src/pt2_edit.c
+++ b/src/pt2_edit.c
@@ -793,6 +793,7 @@
gotoNextMulti();
}
+ // PT quirk: spectrum analyzer is still handled here even if channel is muted
updateSpectrumAnalyzer(s->volume, tempPeriod);
}
else if (noteVal == -2)
--- a/src/pt2_header.h
+++ b/src/pt2_header.h
@@ -14,7 +14,7 @@
#include "pt2_unicode.h"
#include "pt2_palette.h"
-#define PROG_VER_STR "1.58"
+#define PROG_VER_STR "1.59"
#ifdef _WIN32
#define DIR_DELIMITER '\\'
--- a/src/pt2_keyboard.c
+++ b/src/pt2_keyboard.c
@@ -3467,10 +3467,10 @@
break;
}
- keyb.repeatFrac += keyb.repeatDelta; // 32.32 fixed-point counter
- if (keyb.repeatFrac > UINT32_MAX)
+ keyb.repeatFrac += video.amigaVblankDelta; // 0.52 fixed-point
+ if (keyb.repeatFrac > 1ULL<<52)
{
- keyb.repeatFrac &= UINT32_MAX;
+ keyb.repeatFrac &= (1ULL<<52)-1;
keyb.repeatCounter++;
}
}
--- a/src/pt2_main.c
+++ b/src/pt2_main.c
@@ -493,9 +493,9 @@
editor.repeatKeyFlag = (SDL_GetModState() & KMOD_CAPS) ? true : false;
- // set key repeat rate to 49.9204Hz (Amiga PAL vblank rate)
- const double dVblankHzRatio = AMIGA_PAL_VBLANK_HZ / (double)VBLANK_HZ;
- keyb.repeatDelta = (uint64_t)floor((UINT32_MAX+1.0) * dVblankHzRatio);
+ // 0.52 fixed-point delta for Amiga PAL vblank (~49.92Hz) at VBLANK_HZ (60.0Hz)
+ const double dRatio = AMIGA_PAL_VBLANK_HZ / (double)VBLANK_HZ;
+ video.amigaVblankDelta = (uint64_t)((dRatio * (1ULL << 52)) + 0.5);
strcpy(editor.mixText, "MIX 01+02 TO 03");
--- a/src/pt2_replayer.c
+++ b/src/pt2_replayer.c
@@ -374,9 +374,10 @@
setVisualsDataPtr(ch->n_chanindex, ch->n_loopstart);
setVisualsLength(ch->n_chanindex, ch->n_replen);
+ // set spectrum analyzer state for this channel
ch->syncAnalyzerVolume = ch->n_volume;
ch->syncAnalyzerPeriod = ch->n_period;
- ch->syncFlags |= UPDATE_ANALYZER;
+ ch->syncFlags |= UPDATE_SPECTRUM_ANALYZER;
setVUMeterHeight(ch);
}
@@ -988,6 +989,14 @@
setVisualsLength(ch->n_chanindex, 1);
setVisualsPeriod(ch->n_chanindex, ch->n_period);
+
+ // set spectrum analyzer state for this channel
+ if (!editor.muted[ch->n_chanindex])
+ {
+ ch->syncAnalyzerVolume = ch->n_volume;
+ ch->syncAnalyzerPeriod = ch->n_period;
+ ch->syncFlags |= UPDATE_SPECTRUM_ANALYZER;
+ }
}
checkMoreEffects(ch);
@@ -1247,13 +1256,7 @@
for (int32_t i = 0; i < PAULA_VOICES; i++, ch++)
{
if (DMACONtemp & ch->n_dmabit) // handle visuals on sample trigger
- {
- ch->syncAnalyzerVolume = ch->n_volume;
- ch->syncAnalyzerPeriod = ch->n_period;
- ch->syncFlags |= UPDATE_ANALYZER;
-
setVUMeterHeight(ch);
- }
// these take effect after the current DMA cycle is done
const uint32_t voiceAddr = 0xDFF0A0 + (i * 16);
--- a/src/pt2_sampler.c
+++ b/src/pt2_sampler.c
@@ -1833,6 +1833,7 @@
unlockAudio();
+ // PT quirk: spectrum analyzer is still handled here even if channel is muted
updateSpectrumAnalyzer(ch->n_volume, ch->n_period);
}
--- a/src/pt2_scopes.c
+++ b/src/pt2_scopes.c
@@ -84,7 +84,11 @@
void scopeSetPeriod(int32_t ch, int32_t period)
{
- assert(period >= 113 && period <= 65535);
+ period &= 0xFFFF;
+
+ if (period < 113) // just in case, should already be clamped
+ period = 113;
+
scope[ch].dDelta = (PAULA_PAL_CLK / (double)SCOPE_HZ) / period;
}
@@ -180,7 +184,7 @@
if (!tmpScope.active || tmpScope.data == NULL || tmpScope.volume == 0 || tmpScope.length == 0)
continue;
- // amount of integer samples getting skipped every frame
+ // amount of integer samples getting skipped every frame (periods < 113 are clamped, this number can't get big)
const int32_t samplesToScan = (const int32_t)tmpScope.dDelta;
if (samplesToScan <= 0)
continue;
@@ -246,7 +250,7 @@
int16_t scopeData;
int32_t pos = tmpScope.pos;
int32_t length = tmpScope.length;
- const int16_t volume = -(tmpScope.volume << 7);
+ const int8_t volume = -(tmpScope.volume >> 1);
const int8_t *data = tmpScope.data;
uint32_t *scopeDrawPtr = &video.frameBuffer[(71 * SCREEN_W) + scopeX];
@@ -254,7 +258,7 @@
{
scopeData = 0;
if (data != NULL)
- scopeData = (data[pos] * volume) >> 16;
+ scopeData = (data[pos] * volume) >> 8;
scopeDrawPtr[(scopeData * SCREEN_W) + x] = fgColor;
--- a/src/pt2_structs.h
+++ b/src/pt2_structs.h
@@ -112,7 +112,7 @@
bool shiftPressed, leftCtrlPressed, leftAltPressed;
bool leftCommandPressed, leftAmigaPressed, keypadEnterPressed;
uint8_t repeatCounter, delayCounter;
- uint64_t repeatDelta, repeatFrac;
+ uint64_t repeatFrac;
SDL_Scancode lastRepKey, lastKey;
} keyb_t;
@@ -135,6 +135,7 @@
hpc_t vblankHpc;
SDL_PixelFormat *pixelFormat;
uint32_t *frameBuffer;
+ uint64_t amigaVblankDelta; // 0.52 fixed-point
SDL_Window *window;
SDL_Renderer *renderer;
@@ -149,7 +150,7 @@
typedef struct editor_t
{
- volatile int8_t vuMeterVolumes[PAULA_VOICES], spectrumVolumes[SPECTRUM_BAR_NUM];
+ volatile uint8_t vuMeterVolumes[PAULA_VOICES], spectrumVolumes[SPECTRUM_BAR_NUM];
volatile int8_t *sampleFromDisp, *sampleToDisp, *currSampleDisp, realVuMeterVolumes[PAULA_VOICES], mod2WavNumLoops, mod2WavFadeOutSeconds;
volatile bool songPlaying, programRunning, mod2WavOngoing, pat2SmpOngoing, mainLoopOngoing, abortMod2Wav, mod2WavFadeOut;
volatile uint16_t *quantizeValueDisp, *metroSpeedDisp, *metroChannelDisp, *sampleVolDisp;
--- a/src/pt2_visuals.c
+++ b/src/pt2_visuals.c
@@ -1731,55 +1731,66 @@
audio.resetSyncTickTimeFlag = true;
}
-void updateSpectrumAnalyzer(int8_t vol, int16_t period)
+void updateSpectrumAnalyzer(uint8_t vol, uint16_t period)
{
- const uint8_t maxHeight = SPECTRUM_BAR_HEIGHT + 1; // +1 because of audio latency - allows full height to be seen
+ if (ui.visualizerMode != VISUAL_SPECTRUM || vol == 0)
+ return;
- if (ui.visualizerMode != VISUAL_SPECTRUM || vol <= 0)
+ /* This routine is buggy in real PT. Behavior for periods outside of 108..907 is undefined.
+ ** Behavior for sane input outside of 113..856 (B-3 finetune > 0 and C-1 finetune < 0)
+ ** seems to be defined, and we simulate this.
+ */
+ if (period < 108 || period > 907)
+ return; // we don't really know what to do here
+
+ // C-1 with finetune < 0 is ignored (confirmed behavior)
+ if (period > 856)
return;
- uint16_t scaledVol = ((uint16_t)vol * 24576) >> 16; // scaledVol = vol / 2.66667 (0..64 -> 0..24)
+ // B-3 with finetune > 0 behaves like finetune 0 (confirmed behavior)
+ if (period < 113)
+ period = 113;
- period = CLAMP(period, 113, 856);
- period -= 113;
+ // just in case
+ if (vol > 64)
+ vol = 64;
- uint32_t scaledNote = 743 - period;
- scaledNote *= scaledNote;
- scaledNote /= 25093; // scaledNote now ranges 0..22, no need to clamp
+ const uint8_t vol24 = (vol * 24) >> 6; // 0..64 -> 0..24
- // increment main spectrum bar
- editor.spectrumVolumes[scaledNote] += (uint8_t)scaledVol;
- if (editor.spectrumVolumes[scaledNote] > maxHeight)
- editor.spectrumVolumes[scaledNote] = maxHeight;
+ // convert period from log (113..856) to linear (0..22)
+ period = (856 - 113) - (period - 113); // 0..743 (inverted)
+ const uint32_t index = (period * period) / 25093; // 0..22 (25093 = round[743^2 / 22])
- // increment left side of spectrum bar with half volume
- if (scaledNote > 0)
+ // increment bar
+ editor.spectrumVolumes[index] += vol24;
+ if (editor.spectrumVolumes[index] > SPECTRUM_BAR_HEIGHT)
+ editor.spectrumVolumes[index] = SPECTRUM_BAR_HEIGHT;
+
+ // increment left and right neighbor bars with half the volume
+
+ if (index > 0)
{
- editor.spectrumVolumes[scaledNote-1] += (uint8_t)(scaledVol >> 1);
- if (editor.spectrumVolumes[scaledNote-1] > maxHeight)
- editor.spectrumVolumes[scaledNote-1] = maxHeight;
+ editor.spectrumVolumes[index-1] += vol24 / 2;
+ if (editor.spectrumVolumes[index-1] > SPECTRUM_BAR_HEIGHT)
+ editor.spectrumVolumes[index-1] = SPECTRUM_BAR_HEIGHT;
}
- // increment right side of spectrum bar with half volume
- if (scaledNote < SPECTRUM_BAR_NUM-1)
+ if (index < SPECTRUM_BAR_NUM-1)
{
- editor.spectrumVolumes[scaledNote+1] += (uint8_t)(scaledVol >> 1);
- if (editor.spectrumVolumes[scaledNote+1] > maxHeight)
- editor.spectrumVolumes[scaledNote+1] = maxHeight;
+ editor.spectrumVolumes[index+1] += vol24 / 2;
+ if (editor.spectrumVolumes[index+1] > SPECTRUM_BAR_HEIGHT)
+ editor.spectrumVolumes[index+1] = SPECTRUM_BAR_HEIGHT;
}
}
-void sinkVisualizerBars(void)
+void sinkVisualizerBars(void) // sinks visualizer bars @ 49.92Hz (Amiga PAL) rate
{
- // sink visualizer bars @ 49.92Hz (Amiga PAL) rate
+ static uint64_t counter50Hz; // pre-initialized to zero because of static
- static uint64_t counter50Hz;
- const uint64_t counter50HzDelta = (uint64_t)(((UINT32_MAX+1.0) * (AMIGA_PAL_VBLANK_HZ / (double)VBLANK_HZ)) + 0.5);
-
- counter50Hz += counter50HzDelta; // 32.32 fixed-point counter
- if (counter50Hz > UINT32_MAX)
+ counter50Hz += video.amigaVblankDelta; // 0.52 fixed-point
+ if (counter50Hz > 1ULL<<52)
{
- counter50Hz &= UINT32_MAX;
+ counter50Hz &= (1ULL<<52)-1;
// sink VU-meters
for (int32_t i = 0; i < PAULA_VOICES; i++)
--- a/src/pt2_visuals.h
+++ b/src/pt2_visuals.h
@@ -43,7 +43,7 @@
void renderFrame2(void);
void renderFrame(void);
void flipFrame(void);
-void updateSpectrumAnalyzer(int8_t vol, int16_t period);
+void updateSpectrumAnalyzer(uint8_t vol, uint16_t period);
void sinkVisualizerBars(void);
void updatePosEd(void);
void updateVisualizer(void);
--- a/src/pt2_visuals_sync.c
+++ b/src/pt2_visuals_sync.c
@@ -375,7 +375,7 @@
// ---------------------------------------------------------------
- if (flags & UPDATE_ANALYZER)
+ if (flags & UPDATE_SPECTRUM_ANALYZER)
updateSpectrumAnalyzer(c->analyzerVolume, c ->analyzerPeriod);
if (flags & UPDATE_VUMETER) // for fake VU-meters only
--- a/src/pt2_visuals_sync.h
+++ b/src/pt2_visuals_sync.h
@@ -14,7 +14,7 @@
STOP_SCOPE = 32,
UPDATE_VUMETER = 64,
- UPDATE_ANALYZER = 128
+ UPDATE_SPECTRUM_ANALYZER = 128
};
// 2^n-1 - don't change this! Total queue buffer length is already big.