Skip to content

Commit

Permalink
implementation of dB-based scaling in VU meters
Browse files Browse the repository at this point in the history
  • Loading branch information
FulopNandor committed May 18, 2024
1 parent 33226e1 commit d2df194
Show file tree
Hide file tree
Showing 11 changed files with 109 additions and 36 deletions.
11 changes: 8 additions & 3 deletions Source/DXComponents.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ void VuMeter::paint(Graphics &g) {

int numBlocks = roundToInt(totalBlocks * v);

if ( numBlocks > 46 )
if ( numBlocks > totalBlocks )
numBlocks = totalBlocks;
int brkpoint = numBlocks * 3 + 2;

Expand All @@ -343,12 +343,17 @@ VuMeterMain::VuMeterMain() {
void VuMeterMain::paint(Graphics& g) {
g.drawImage(strip3c, 0, 0, 140, 8, 0, 0, 140, 8);

if (v <= 0)
// apply dB scale
v = 10 * log10(v);
v = (v + numNonRedBlocks) * one_per_totalBlocks;
if (v <= 0) {
//v = 0;
return;
}

int numBlocks = roundToInt(totalBlocks * v);

if (numBlocks > 46)
if (numBlocks > totalBlocks)
numBlocks = totalBlocks;
int brkpoint = numBlocks * 3 + 2;

Expand Down
10 changes: 9 additions & 1 deletion Source/DXComponents.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ public :
/// Total number of blocks of the strips,
/// according to content of ''Meter3C_140x8_png''.
static const int totalBlocks = 46;

static constexpr float one_per_totalBlocks = 1.0F / totalBlocks;

// amplitude value corresponding to -(totalBlocks) dB
static constexpr float amp_46dB = 2.51189E-05;

float v;
};

Expand All @@ -65,9 +71,11 @@ class VuMeterMain : public VuMeter {
/// according to the content of ''Meter3C_140x8_png''.
static const int numYellowBlocks = 6;

static const int numNonRedBlocks = totalBlocks - numRedBlocks;

/// Ratio of length of the green+yellow area to total length
/// of the three-colored strip.
static constexpr float VU_0dB = ((float)(totalBlocks - numRedBlocks)) / ((float)totalBlocks);
static constexpr float VU_0dB = ((float)numNonRedBlocks) / ((float)totalBlocks);

/// Image of a three-colored (green-yellow-red) strip,
/// loaded from ''Meter3C_140x8.png''.
Expand Down
10 changes: 10 additions & 0 deletions Source/EngineMkI.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,15 @@ class EngineMkI : public FmCore {
void compute_fb3(int32_t *output, FmOpParams *params, int32_t gain01, int32_t gain02, int32_t *fb_buf, int fb_shift);
};

/// Maximum absolute value of output amplitude of an operator of MkI Engine.
/// TODO: Its value _should_ _be_ derived from other constants used in this engine by some exact calculation
/// giving the maximum absolute value stored or added to ``output[i]`` in methods ``EngineMkI::compute()``,
/// ``EngineMkI::compute_pure()`` and ``EngineMkI::::compute_fb()``.
/// NOTE: this current value is still determined experimentally! 61613110
#define MAX_ABS_AMP_MKI_OP 6113110


/// Value of DC bias of output amplitude of an operator of MkI Engine.
#define DC_BIAS_MKI_OP 1069

#endif // ENGINEMKI_H_INCLUDED
12 changes: 0 additions & 12 deletions Source/EngineOpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,15 +212,3 @@ void EngineOpl::render(int32_t *output, FmOpParams *params, int algorithm,
param.phase += param.freq << LG_N;
}
}












8 changes: 8 additions & 0 deletions Source/EngineOpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ class EngineOpl : public FmCore {
int32_t *fb_buf, int fb_gain, bool add);
};

/// Maximum absolute value of output amplitude of an operator of OPL Engine.
/// TODO: Its value _should_ _be_ derived from other constants used in this engine by some exact calculation
/// giving the maximum absolute value assigned or added to ``output[i]`` in methods ``EngineOpl::compute()``,
/// ``EngineOplFmOpKernel::compute_pure()`` and ``EngineOpl::compute_fb()``.
/// NOTE: this current value is still determined experimentally!
#define MAX_ABS_AMP_OPL_OP 61495214

/// Value of DC bias of output amplitude of an operator of OPL Engine.
#define DC_BIAS_OPL_OP 1069

#endif // ENGINEOPL_H_INCLUDED
11 changes: 11 additions & 0 deletions Source/OperatorEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -533,8 +533,19 @@ void OperatorEditor::bind(DexedAudioProcessor *parent, int op) {
internalOp = 5-op;
}

// v should be > 0
void OperatorEditor::updateGain(float v) {
const float one_per_totalBlocks = 1.0F / VuMeter::totalBlocks;

// apply dB scale
v = 10 * log10(v);
v = (v + VuMeter::totalBlocks) * one_per_totalBlocks;
if (v < 0)
v = 0;
else if (v > 1.0F)
v = 1.0F;
vu->v = v;

vu->repaint();
}

Expand Down
7 changes: 6 additions & 1 deletion Source/PluginEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,12 @@ void DexedAudioProcessorEditor::timerCallback() {
return;

for(int i=0;i<6;i++) {
operators[i].updateGain(sqrt(processor->voiceStatus.amp[5 - i]) / 8196); // TODO: FUGLY !!!! change this sqrt nonsense
//operators[i].updateGain(sqrt(processor->voiceStatus.amp[5 - i]) / 8196); // TODO: FUGLY !!!! change this sqrt nonsense
int32_t amp = processor->voiceStatus.amp[5 - i];
amp -= dc_bias_op;
if (amp < 0) amp = -amp;
if (amp < VuMeter::amp_46dB) amp = VuMeter::amp_46dB;
operators[i].updateGain(amp * flt_cnv_fact_op); // TODO: changed to dB-scale but based on the costly ``log10()``
operators[i].updateEnvPos(processor->voiceStatus.ampStep[5 - i]);
}
global.updatePitchPos(processor->voiceStatus.pitchStep);
Expand Down
6 changes: 6 additions & 0 deletions Source/PluginEditor.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ class DexedAudioProcessorEditor : public AudioProcessorEditor, public ComboBox:

static const int WINDOW_SIZE_X = 866;
static const int WINDOW_SIZE_Y = 674;

// Conversion factor to calculate the int32_t operators' output values into range of 0.0F...1.0F.
float flt_cnv_fact_op = FLT_CNV_FACT_MKI_OP;

// A DC bias value; levels below it are cosidered as 0 on operators' VU meters.
float dc_bias_op = DC_BIAS_MKI_OP;
};


Expand Down
26 changes: 22 additions & 4 deletions Source/PluginProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ void DexedAudioProcessor::processBlock(AudioSampleBuffer& buffer, MidiBuffer& mi

float* sumbufjp = sumbuf;
for (int j = 0; j < N; ++j) {
*sumbufjp++ += (*audiobufjp) * flt_cnv_fact;
*sumbufjp++ += (*audiobufjp) * flt_cnv_fact_main_output;
*audiobufjp++ = 0;
}
}
Expand Down Expand Up @@ -692,18 +692,36 @@ int DexedAudioProcessor::getEngineType() {
void DexedAudioProcessor::setEngineType(int tp) {
TRACE("settings engine %d", tp);

DexedAudioProcessorEditor* dexedEditor = nullptr;
AudioProcessorEditor* editor = getActiveEditor();
if (editor != NULL) {
dexedEditor = (DexedAudioProcessorEditor*)editor;
}

switch (tp) {
case DEXED_ENGINE_MARKI:
controllers.core = &engineMkI;
flt_cnv_fact = FLT_CNV_FACT_MKI;
flt_cnv_fact_main_output = FLT_CNV_FACT_MKI_MAIN_OUTPUT;
if (dexedEditor != nullptr) {
dexedEditor->flt_cnv_fact_op = FLT_CNV_FACT_MKI_OP;
dexedEditor->dc_bias_op = DC_BIAS_MKI_OP;
}
break;
case DEXED_ENGINE_OPL:
controllers.core = &engineOpl;
flt_cnv_fact = FLT_CNV_FACT_OPL;
flt_cnv_fact_main_output = FLT_CNV_FACT_OPL_MAIN_OUTPUT;
if (dexedEditor != nullptr) {
dexedEditor->flt_cnv_fact_op = FLT_CNV_FACT_OPL_OP;
dexedEditor->dc_bias_op = DC_BIAS_OPL_OP;
}
break;
default:
controllers.core = &engineMsfa;
flt_cnv_fact = FLT_CNV_FACT_MSFA;
flt_cnv_fact_main_output = FLT_CNV_FACT_MSFA_MAIN_OUTPUT;
if (dexedEditor != nullptr) {
dexedEditor->flt_cnv_fact_op = FLT_CNV_FACT_MSFA_OP;
dexedEditor->dc_bias_op = DC_BIAS_FM_CORE_OP;
}
break;
}
engineType = tp;
Expand Down
34 changes: 19 additions & 15 deletions Source/PluginProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,33 +74,37 @@ static const int MAX_FLOAT_AMP_PLUGIN_OUTPUT = 1.0F;
// Minimum allowed value of the outgoing float amplitudes from the plugin.
static const int MIN_FLOAT_AMP_PLUGIN_OUTPUT = -1.0F;

/// Maximum absolute value of the experimentally observed amplitudes for engine ``MSFA``.
static const int32_t MAX_ABS_AMP_MSFA = 369373301;
/// Maximum absolute value of the output amplitudes for engine ``MSFA``.
static const int32_t MAX_ABS_AMP_MSFA = MAX_ABS_AMP_FM_CORE_OP * 6; // ``*6`` = because outputs of all the 6 operators may contribute to the final output in Algorithm 32.

/// Maximum absolute value of the experimentally observed amplitudes for engine ``MKI``.
static const int32_t MAX_ABS_AMP_MKI = 369678658;
/// Maximum absolute value of the output amplitudes for engine ``MKI``.
static const int32_t MAX_ABS_AMP_MKI = MAX_ABS_AMP_MKI_OP * 6;

/// Maximum absolute value of the experimentally observed amplitudes for engine ``OPL``.
static const int32_t MAX_ABS_AMP_OPL = 368971281;
/// Maximum absolute value of the output amplitudes for engine ``OPL``.
static const int32_t MAX_ABS_AMP_OPL = MAX_ABS_AMP_OPL_OP * 6;

// An experimental value to reproduce the former Dexed's output loudness, approximately
static const float EXPERIMENTAL_VOLUME_CONSTANT = 0.95;

//--- Conversion factors to convert int32_t sample values to float sample values
// These values _should_ _be_ derived from other constants used in the engines by some exact calculation.
// (The actual values below are determined experimentally.)
//--- Conversion factors to convert in32t_t sample values to float sample values for the indivudual VU indicators of the operators.
static const float FLT_CNV_FACT_MSFA_OP = 1.0F / MAX_ABS_AMP_FM_CORE_OP;
static const float FLT_CNV_FACT_MKI_OP = 1.0F / MAX_ABS_AMP_MKI_OP;
static const float FLT_CNV_FACT_OPL_OP = 1.0F / MAX_ABS_AMP_OPL_OP;

//--- Conversion factors to convert int32_t sample values to float main output sample values

// An experimental value to reproduce about the similar loudness of main output than before
static const float EXPERIMENTAL_VOLUME_CONSTANT = 0.15;

/// Conversion factor to convert int32_t sample values to float sample values
/// into the allowed range of the plugin output for the ``MSFA`` engine
static const float FLT_CNV_FACT_MSFA = MAX_FLOAT_AMP_PLUGIN_OUTPUT / (float)MAX_ABS_AMP_MSFA * EXPERIMENTAL_VOLUME_CONSTANT;
static const float FLT_CNV_FACT_MSFA_MAIN_OUTPUT = MAX_FLOAT_AMP_PLUGIN_OUTPUT / (float)MAX_ABS_AMP_MSFA * EXPERIMENTAL_VOLUME_CONSTANT;

/// Conversion factor to convert int32_t sample values to float sample values
/// into the allowed range of the plugin output for the ``MARK I`` engine
static const float FLT_CNV_FACT_MKI = MAX_FLOAT_AMP_PLUGIN_OUTPUT / (float)MAX_ABS_AMP_MKI * EXPERIMENTAL_VOLUME_CONSTANT;
static const float FLT_CNV_FACT_MKI_MAIN_OUTPUT = MAX_FLOAT_AMP_PLUGIN_OUTPUT / (float)MAX_ABS_AMP_MKI * EXPERIMENTAL_VOLUME_CONSTANT;

/// Conversion factor to convert int32_t sample values to float sample values
/// into the allowed range of the plugin output for the ``OPL`` engine
static const float FLT_CNV_FACT_OPL = MAX_FLOAT_AMP_PLUGIN_OUTPUT / (float)MAX_ABS_AMP_OPL * EXPERIMENTAL_VOLUME_CONSTANT;
static const float FLT_CNV_FACT_OPL_MAIN_OUTPUT = MAX_FLOAT_AMP_PLUGIN_OUTPUT / (float)MAX_ABS_AMP_OPL * EXPERIMENTAL_VOLUME_CONSTANT;

//==============================================================================
/**
Expand Down Expand Up @@ -165,7 +169,7 @@ class DexedAudioProcessor : public AudioProcessor, public AsyncUpdater, public
EngineOpl engineOpl;

// a multiplier used to convert int32_t samples produced by the currently selected engine to float samples
float flt_cnv_fact = FLT_CNV_FACT_MKI;
float flt_cnv_fact_main_output = FLT_CNV_FACT_MKI_MAIN_OUTPUT;

char clipboard[161];
char clipboardContent;
Expand Down
10 changes: 10 additions & 0 deletions Source/msfa/fm_op_kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,14 @@ class FmOpKernel {
int32_t *fb_buf, int fb_gain, bool add);
};

/// Maximum absolute value of output amplitude of an operator of MSFA Engine.
/// TODO: Its value _should_ _be_ derived from other constants used in this engine by some exact calculation
/// giving the maximum absolute value stored or added to ``output[i]`` in methods ``FmOpKernel::compute()``,
/// ``FmOpKernel::compute_pure()`` and ``FmOpKernel::compute_fb()``.
/// NOTE: this current value is still determined experimentally!
#define MAX_ABS_AMP_FM_CORE_OP 61562217

/// Value of DC bias of output amplitude of an operator of MSFA Engine.
#define DC_BIAS_FM_CORE_OP 1069

#endif

0 comments on commit d2df194

Please sign in to comment.