2026-09-11 16:38:28 +02:00
|
|
|
#include "SynthParams.h"
|
|
|
|
|
|
|
|
|
|
namespace sm26 {
|
|
|
|
|
|
|
|
|
|
static const char* const kStepLabels[] = {
|
|
|
|
|
"1/32", "1/16T", "1/16", "1/8T",
|
|
|
|
|
"1/8", "1/4T", "1/4", "1/2T",
|
|
|
|
|
"1/2", "3/4", "1", "3/2",
|
|
|
|
|
"2", "3", "4", "8",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const float kStepBeats[] = {
|
|
|
|
|
0.125f, 0.1667f, 0.25f, 0.3333f,
|
|
|
|
|
0.5f, 0.6667f, 1.0f, 1.3333f,
|
|
|
|
|
2.0f, 3.0f, 4.0f, 6.0f,
|
|
|
|
|
8.0f, 12.0f, 16.0f, 32.0f,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const char* const* stepsLabels() { return kStepLabels; }
|
|
|
|
|
const float* stepsBeats() { return kStepBeats; }
|
|
|
|
|
|
|
|
|
|
int stepsPerBeatFor(float stepIndex)
|
|
|
|
|
{
|
|
|
|
|
const int i = juce::jlimit(0, 15, (int) juce::roundToInt(stepIndex * 15.0f));
|
|
|
|
|
return juce::roundToInt(kStepBeats[i] * 4.0f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float paramReal(int id, float n01)
|
|
|
|
|
{
|
|
|
|
|
n01 = clamp01(n01);
|
|
|
|
|
switch (id)
|
|
|
|
|
{
|
|
|
|
|
case PO1OCT: return -2.0f + n01 * 4.0f;
|
|
|
|
|
case PO1CT: return -100.0f + n01 * 200.0f;
|
|
|
|
|
case PO2OCT: return -2.0f + n01 * 4.0f;
|
|
|
|
|
case PO2CT: return -100.0f + n01 * 200.0f;
|
|
|
|
|
case PMIX: return n01;
|
|
|
|
|
case PNOISE: return n01;
|
|
|
|
|
case PCUTOFF: return (float) std::exp (std::log (20.0) + n01 * (std::log (20000.0) - std::log (20.0)));
|
|
|
|
|
case PRES: return 0.5f + n01 * 19.5f;
|
|
|
|
|
case PFENV: return n01;
|
|
|
|
|
case PATK: return (float) std::exp (std::log (0.001) + n01 * (std::log (8.0) - std::log (0.001)));
|
|
|
|
|
case PDEC: return (float) std::exp (std::log (0.002) + n01 * (std::log (8.0) - std::log (0.002)));
|
|
|
|
|
case PSUS: return n01;
|
|
|
|
|
case PREL: return (float) std::exp (std::log (0.002) + n01 * (std::log (8.0) - std::log (0.002)));
|
|
|
|
|
case PDTIME: return (float) std::exp (std::log (10.0) + n01 * (std::log (1500.0) - std::log (10.0)));
|
|
|
|
|
case PDFB: return n01;
|
|
|
|
|
case PDMIX: return n01;
|
|
|
|
|
case PDRIVE: return n01;
|
|
|
|
|
case PGLIDE: return (float) std::exp (std::log (0.001) + n01 * (std::log (2.0) - std::log (0.001)));
|
|
|
|
|
case PMASTER: return 0.10f + n01 * 0.70f;
|
|
|
|
|
default: return n01;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float unwrapParameter(int id, float n01)
|
|
|
|
|
{
|
|
|
|
|
n01 = clamp01(n01);
|
|
|
|
|
switch (id)
|
|
|
|
|
{
|
|
|
|
|
case PO1OCT: case PO2OCT:
|
|
|
|
|
return juce::jmax (0.0f, juce::jmin (1.0f, (n01 + 2.0f) / 4.0f));
|
|
|
|
|
case PO1CT: case PO2CT:
|
|
|
|
|
return (n01 + 100.0f) / 200.0f;
|
|
|
|
|
case PCUTOFF:
|
|
|
|
|
return (float) ((std::log (n01) - std::log (20.0)) / (std::log (20000.0) - std::log (20.0)));
|
|
|
|
|
case PATK:
|
|
|
|
|
return (float) ((std::log (n01) - std::log (0.001)) / (std::log (8.0) - std::log (0.001)));
|
|
|
|
|
case PDEC:
|
|
|
|
|
return (float) ((std::log (n01) - std::log (0.002)) / (std::log (8.0) - std::log (0.002)));
|
|
|
|
|
case PREL:
|
|
|
|
|
return (float) ((std::log (n01) - std::log (0.002)) / (std::log (8.0) - std::log (0.002)));
|
|
|
|
|
case PDTIME:
|
|
|
|
|
return (float) ((std::log (n01) - std::log (10.0)) / (std::log (1500.0) - std::log (10.0)));
|
|
|
|
|
case PGLIDE:
|
|
|
|
|
return (float) ((std::log (n01) - std::log (0.001)) / (std::log (2.0) - std::log (0.001)));
|
|
|
|
|
case PMASTER:
|
|
|
|
|
return (n01 - 0.10f) / 0.70f;
|
|
|
|
|
default:
|
|
|
|
|
return n01;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char* paramShortName(int id)
|
|
|
|
|
{
|
|
|
|
|
static const char* const names[] = {
|
|
|
|
|
"OSC1", "OSC2", "O1-OCT", "O1-DET", "O2-OCT", "O2-DET",
|
|
|
|
|
"MIX", "NOISE", "CUTOFF", "RES", "F-ENV", "F-TYPE",
|
|
|
|
|
"ATK", "DEC", "SUS", "REL", "D-TIME", "D-STEPS",
|
|
|
|
|
"SYNC", "D-FB", "D-MIX", "DRIVE","GLIDE", "MASTER",
|
|
|
|
|
};
|
|
|
|
|
if (id >= 0 && id < kNumParams) return names[id];
|
|
|
|
|
return "----";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char* paramUnit(int id)
|
|
|
|
|
{
|
|
|
|
|
switch (id)
|
|
|
|
|
{
|
|
|
|
|
case PO1OCT: case PO2OCT: return "oct";
|
|
|
|
|
case PO1CT: case PO2CT: return "ct";
|
|
|
|
|
case PCUTOFF: return "Hz";
|
|
|
|
|
case PDTIME: return "ms";
|
|
|
|
|
default: return "";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int paramWaveIndex(float n01)
|
|
|
|
|
{
|
|
|
|
|
const int i = (int) juce::roundToInt (n01 * 4.0f);
|
|
|
|
|
return juce::jlimit(0, 4, i);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int paramFilterType(float n01)
|
|
|
|
|
{
|
|
|
|
|
return juce::jlimit (0, 2, (int) juce::roundToInt (n01 * 2.0f));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char* waveName(int w)
|
|
|
|
|
{
|
|
|
|
|
switch (w)
|
|
|
|
|
{
|
|
|
|
|
case 0: return "SINE";
|
|
|
|
|
case 1: return "TRI";
|
|
|
|
|
case 2: return "SAW";
|
|
|
|
|
case 3: return "SQRE";
|
|
|
|
|
case 4: return "NSE";
|
|
|
|
|
default: return "----";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char* filterTypeName(int t)
|
|
|
|
|
{
|
|
|
|
|
switch (t)
|
|
|
|
|
{
|
|
|
|
|
case 0: return "LP";
|
|
|
|
|
case 1: return "BP";
|
|
|
|
|
case 2: return "HP";
|
|
|
|
|
default: return "LP";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String formatTimeMs(float ms)
|
|
|
|
|
{
|
|
|
|
|
if (ms >= 1000.0f) return String (ms / 1000.0, 2) + " s";
|
|
|
|
|
return String ((int) juce::roundToInt (ms)) + " ms";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String formatFreq(float hz)
|
|
|
|
|
{
|
|
|
|
|
if (hz >= 1000.0f) return String (hz / 1000.0, 2) + " kHz";
|
|
|
|
|
return String ((int) juce::roundToInt (hz)) + " Hz";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String formatPercent(float v)
|
|
|
|
|
{
|
|
|
|
|
return String ((int) juce::roundToInt (v * 100.0f)) + "%";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String formatParamReal(int id, float n01)
|
|
|
|
|
{
|
|
|
|
|
n01 = clamp01 (n01);
|
|
|
|
|
switch (id)
|
|
|
|
|
{
|
|
|
|
|
case PO1WAVE: case PO2WAVE:
|
|
|
|
|
return waveName (paramWaveIndex (n01));
|
|
|
|
|
case PO1OCT: case PO2OCT:
|
|
|
|
|
return String (paramReal (id, n01), 2);
|
|
|
|
|
case PO1CT: case PO2CT:
|
|
|
|
|
return String ((int) juce::roundToInt (paramReal (id, n01))) + " ct";
|
|
|
|
|
case PMIX: case PNOISE: case PFENV: case PSUS:
|
|
|
|
|
case PDFB: case PDMIX: case PDRIVE: case PMASTER:
|
|
|
|
|
return formatPercent (n01);
|
|
|
|
|
case PCUTOFF: return formatFreq (paramReal (id, n01));
|
|
|
|
|
case PRES: return String (paramReal (id, n01), 1);
|
|
|
|
|
case PFTYPE: return filterTypeName (paramFilterType (n01));
|
|
|
|
|
case PATK: case PDEC: case PREL:
|
|
|
|
|
return formatTimeMs (paramReal (id, n01) * 1000.0f);
|
|
|
|
|
case PDTIME: return formatTimeMs (paramReal (id, n01));
|
|
|
|
|
case PDSTEPS:
|
2026-09-12 21:53:16 +02:00
|
|
|
return stepsLabels() [juce::jlimit (0, 15, (int) juce::roundToInt (n01))];
|
2026-09-11 16:38:28 +02:00
|
|
|
case PDSYNC:
|
|
|
|
|
return n01 > 0.5f ? "SYNC" : "MS";
|
|
|
|
|
case PGLIDE:
|
|
|
|
|
return formatTimeMs (paramReal (id, n01) * 1000.0f);
|
|
|
|
|
default:
|
|
|
|
|
return String ((int) juce::roundToInt (n01 * 100.0f)) + "%";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace sm26
|