#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: return stepsLabels() [juce::jlimit (0, 15, (int) juce::roundToInt (n01))]; 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