ref: 525505abf8d09aac0cc7e0518a0c6d268d040dc2
parent: aa1481048c9a0e969ebb944cbbc01978003fc1d3
author: Olav Sørensen <olav.sorensen@live.no>
date: Wed May 21 09:16:17 EDT 2025
Faster scopes (and reverted to previous scaling behavior)
--- a/src/ft2_audio.c
+++ b/src/ft2_audio.c
@@ -368,7 +368,7 @@
if (status & IS_Vol)
{
v->fVolume = ch->fFinalVol; // 0.0f .. 1.0f
- v->scopeVolume = (uint8_t)((ch->fFinalVol * 255.0f) + 0.5f); // 0..255, rounded
+ v->scopeVolume = (uint8_t)((ch->fFinalVol * (SCOPE_HEIGHT*4.0f)) + 0.5f);
}
if (status & IS_Pan)
--- a/src/scopes/ft2_scope_macros.h
+++ b/src/scopes/ft2_scope_macros.h
@@ -109,8 +109,7 @@
LINEAR_INTERPOLATION8(frac) \
else \
CUBIC_INTERPOLATION8(frac) \
- sample = (int32_t)roundf((float)sample * s->fVolume); \
- if (sample > (SCOPE_HEIGHT/2)-1) sample = (SCOPE_HEIGHT/2)-1; /* upper-clamp needed */
+ sample = (sample * s->volume) >> (16+2);
#define INTERPOLATE_SMP16(pos, frac) \
const int16_t *s16 = s->base16 + pos; \
@@ -120,8 +119,7 @@
LINEAR_INTERPOLATION16(frac) \
else \
CUBIC_INTERPOLATION16(frac) \
- sample = (int32_t)roundf((float)sample * s->fVolume); \
- if (sample > (SCOPE_HEIGHT/2)-1) sample = (SCOPE_HEIGHT/2)-1; /* upper-clamp needed */
+ sample = (sample * s->volume) >> (16+2);
#define INTERPOLATE_SMP8_LOOP(pos, frac) \
const int8_t *s8 = s->base8 + pos; \
@@ -131,8 +129,7 @@
LINEAR_INTERPOLATION8(frac) \
else \
CUBIC_INTERPOLATION8_LOOP(pos, frac) \
- sample = (int32_t)roundf((float)sample * s->fVolume); \
- if (sample > (SCOPE_HEIGHT/2)-1) sample = (SCOPE_HEIGHT/2)-1; /* upper-clamp needed */
+ sample = (sample * s->volume) >> (16+2);
#define INTERPOLATE_SMP16_LOOP(pos, frac) \
const int16_t *s16 = s->base16 + pos; \
@@ -142,37 +139,25 @@
LINEAR_INTERPOLATION16(frac) \
else \
CUBIC_INTERPOLATION16_LOOP(pos, frac) \
- sample = (int32_t)roundf((float)sample * s->fVolume); \
- if (sample > (SCOPE_HEIGHT/2)-1) sample = (SCOPE_HEIGHT/2)-1; /* upper-clamp needed */
+ sample = (sample * s->volume) >> (16+2);
#define SCOPE_GET_SMP8 \
if (s->active) \
- { \
- sample = (int32_t)roundf((float)(s->base8[position] << 8) * s->fVolume); \
- if (sample > (SCOPE_HEIGHT/2)-1) sample = (SCOPE_HEIGHT/2)-1; /* upper-clamp needed */ \
- } \
+ sample = (s->base8[position] * s->volume) >> (8+2); \
else \
- { \
- sample = 0; \
- }
+ sample = 0;
#define SCOPE_GET_SMP16 \
if (s->active) \
- { \
- sample = (int32_t)roundf((float)s->base16[position] * s->fVolume); \
- if (sample > (SCOPE_HEIGHT/2)-1) sample = (SCOPE_HEIGHT/2)-1; /* upper-clamp needed */ \
- } \
+ sample = (s->base16[position] * s->volume) >> (16+2); \
else \
- { \
- sample = 0; \
- }
+ sample = 0;
#define SCOPE_GET_SMP8_BIDI \
if (s->active) \
{ \
GET_BIDI_POSITION \
- sample = (int32_t)roundf((float)(s->base8[actualPos] << 8) * s->fVolume); \
- if (sample > (SCOPE_HEIGHT/2)-1) sample = (SCOPE_HEIGHT/2)-1; /* upper-clamp needed */ \
+ sample = (s->base8[actualPos] * s->volume) >> (8+2); \
} \
else \
{ \
@@ -183,8 +168,7 @@
if (s->active) \
{ \
GET_BIDI_POSITION \
- sample = (int32_t)roundf((float)s->base16[actualPos] * s->fVolume); \
- if (sample > (SCOPE_HEIGHT/2)-1) sample = (SCOPE_HEIGHT/2)-1; /* upper-clamp needed */ \
+ sample = (s->base16[actualPos] * s->volume) >> (16+2); \
} \
else \
{ \
--- a/src/scopes/ft2_scopedraw.c
+++ b/src/scopes/ft2_scopedraw.c
@@ -40,11 +40,11 @@
double t3 = (-(1.0/2.0) * x3) + ( (1.0/2.0) * x2) + ( (1.0/2.0) * x1) + (1.0/6.0);
double t4 = (1.0/6.0) * x3;
- // rounding here would make the scopes clip, but we clamp the scopes for another reason anyway
- *ptr16++ = (int16_t)round(t1 * SCOPE_INTRP_SCALE);
- *ptr16++ = (int16_t)round(t2 * SCOPE_INTRP_SCALE);
- *ptr16++ = (int16_t)round(t3 * SCOPE_INTRP_SCALE);
- *ptr16++ = (int16_t)round(t4 * SCOPE_INTRP_SCALE);
+ // truncate, do not round!
+ *ptr16++ = (int16_t)(t1 * SCOPE_INTRP_SCALE);
+ *ptr16++ = (int16_t)(t2 * SCOPE_INTRP_SCALE);
+ *ptr16++ = (int16_t)(t3 * SCOPE_INTRP_SCALE);
+ *ptr16++ = (int16_t)(t4 * SCOPE_INTRP_SCALE);
}
return true;
--- a/src/scopes/ft2_scopes.c
+++ b/src/scopes/ft2_scopes.c
@@ -428,7 +428,7 @@
}
volatile scope_t s = scope[i]; // cache scope to lower thread race condition issues
- if (s.active && s.fVolume > 0.0f && !audio.locked)
+ if (s.active && s.volume > 0 && !audio.locked)
{
// scope is active
scope[i].wasCleared = false;
@@ -489,7 +489,7 @@
const uint8_t status = scopeUpdateStatus[i];
if (status & IS_Vol)
- sc->fVolume = ch->scopeVolume * (1.0f / (255.0f / (SCOPE_HEIGHT/2) * 32768.0f));
+ sc->volume = ch->scopeVolume;
if (status & IS_Period)
sc->delta = (uint64_t)(dPeriod2Hz(ch->period) * (SCOPE_FRAC_SCALE / (double)SCOPE_HZ));
--- a/src/scopes/ft2_scopes.h
+++ b/src/scopes/ft2_scopes.h
@@ -21,8 +21,8 @@
#define SCOPE_INTRP_WIDTH_BITS 2 /* log2(SCOPE_INTRP_WIDTH) */
#define SCOPE_INTRP_SCALE 32768
#define SCOPE_INTRP_SCALE_BITS 15 /* log2(SCOPE_INTRP_SCALE) */
-#define SCOPE_INTRP_PHASES 512 /* plentiful for FT2-styled scopes */
-#define SCOPE_INTRP_PHASES_BITS 9 /* log2(SCOPE_INTRP_PHASES) */
+#define SCOPE_INTRP_PHASES 256 /* enough for the scopes */
+#define SCOPE_INTRP_PHASES_BITS 8 /* log2(SCOPE_INTRP_PHASES) */
int32_t getSamplePositionFromScopes(uint8_t ch);
void stopAllScopes(void);
@@ -40,9 +40,9 @@
const int16_t *base16;
bool wasCleared, sample16Bit, samplingBackwards, hasLooped;
uint8_t loopType;
+ int16_t volume;
int32_t loopStart, loopLength, loopEnd, sampleEnd, position;
uint64_t delta, drawDelta, positionFrac;
- float fVolume;
// if (loopEnabled && hasLooped && samplingPos <= loopStart+MAX_LEFT_TAPS) readFixedTapsFromThisPointer();
const int8_t *leftEdgeTaps8;
--
⑨