#pragma once // ============================================================ // AlgorithmPresets.h FDN Reverb Acoustic Data Library // 7 algorithms x 10 bands of RT60 / EDT / D50 / C50 / C80 // Bands: 31.25 / 62.5 / 125 / 250 / 500 / 1k / 2k / 4k / 8k / 16k Hz // ============================================================ #include namespace FDNReverb { static constexpr int NUM_BANDS = 10; static constexpr int NUM_ALGORITHMS = 7; // Octave-band centre frequencies (Hz) static constexpr std::array BAND_FREQ = { 31.25f, 62.5f, 125.0f, 250.0f, 500.0f, 1000.0f, 2000.0f, 4000.0f, 8000.0f, 16000.0f }; struct AcousticData { std::array rt60; // RT60 (s) std::array edt; // EDT (s) std::array d50; // Definition 0-1 std::array c50; // Clarity 50 ms (dB) std::array c80; // Clarity 80 ms (dB) }; // ----------------------------------------------------------------------------- // PresetDefaults: when a preset is selected load parameter // ----------------------------------------------------------------------------- // when a preset is selected, these APVTS parameters are set automatically: // so the distinctive sound of the preset can be experienced immediately. // the user can still fine-tune every parameter afterwards. // // * v1.1.0 added : saturation // the saturation harmonic intensity that brings out each preset's character. // Room1/Room2: subtle (kept clean, restrained warmth) // Hall1/Hall2: moderate (emphasizes a rich ring) // Plate: moderate (brings out the metallic character) // Spring: high (doubles the distinctive metallic character) // Goldfoil: moderate (balanced) // // design rationale: // - decayTime is the preset's native mid-band (500 Hz) RT60, // giving decayScale = 1.0 so the source RT curve is reproduced exactly // - other parameters are empirical values based on each preset's physical traits // ----------------------------------------------------------------------------- struct PresetDefaults { float roomSize; // 0.5 ~ 2.0 float decayTime; // seconds ( source preset mid-band RT60) float hfDamp; // 0.0 ~ 1.0 float lfAbsorb; // 0.0 ~ 1.0 float diffusion; // 0.0 ~ 1.0 float modAmount; // 0.0 ~ 1.0 float modRate; // 0.1 ~ 10 Hz float erLevel; // 0.0 ~ 1.0 float saturation; // * new in v1.1 : 0.0 ~ 1.0 ( harmonics intensity ) }; // ----------------------------------------------------------------------------- // preset default values // ----------------------------------------------------------------------------- // index corresponds to algorithmIndex (0=Room1, 1=Room2, ..., 6=Goldfoil) // // saturation value rationale: // - Room1/2 (0.15f/0.20f): natural, clean space; harmonics kept subtle. // - Hall1/2 (0.30f/0.35f): adds warmth to the rich reverb. // - Plate (0.40f): metal-plate resonance; moderate harmonics. // - Spring (0.55f): distinctive metallic character is the core; stronger harmonics highlight it. // - Goldfoil (0.35f): balanced, between plate and spring. // ----------------------------------------------------------------------------- static constexpr std::array PRESET_DEFAULTS = { { // Room1: small live room; decayTime = rt60[4] = 0.21 s // keep the natural sense of space; saturation minimal (0.00f) { 0.85f, 0.21f, 0.55f, 0.45f, 0.55f, 0.20f, 0.40f, 0.70f, 0.00f }, // Room2: medium live room; decayTime = rt60[4] = 1.38 s // slightly wider than Room1, add a little warmth (0.05f) { 1.00f, 1.38f, 0.50f, 0.40f, 0.60f, 0.25f, 0.45f, 0.65f, 0.05f }, // Hall1: medium hall; decayTime = rt60[4] = 1.89 s // bring out the hall's richness with moderate harmonics (0.10f) { 1.30f, 1.89f, 0.45f, 0.35f, 0.70f, 0.30f, 0.30f, 0.60f, 0.10f }, // Hall2: large hall; decayTime = rt60[4] = 2.08 s // add harmonics for the grandeur of the large space (0.10f) { 1.50f, 2.08f, 0.50f, 0.30f, 0.75f, 0.30f, 0.30f, 0.55f, 0.10f }, // Plate: plate reverb (metal plate); decayTime = rt60[4] = 1.1431 s // the metal-plate resonance is the core; moderate harmonics bring out its character (0.15f) { 0.70f, 1.14f, 0.65f, 0.55f, 0.85f, 0.15f, 0.50f, 0.20f, 0.15f }, // Spring: spring decayTime = rt60[4] = 2.9252 s // distinctive metallic character spring essence . stronger harmonics character (0.20f) { 0.50f, 2.93f, 0.70f, 0.60f, 0.65f, 0.26f, 0.33f, 0.10f, 0.20f }, // Goldfoil: gold foil decayTime = rt60[4] = 2.0642 s // plate spring in between . balanced (0.18f) { 0.95f, 2.06f, 0.55f, 0.40f, 0.80f, 0.35f, 0.45f, 0.30f, 0.18f } } }; // ----------------------------------------------------------------------------- // ERPattern: preset ISM (Image Source Method) ER // ----------------------------------------------------------------------------- // Allen-Berkley 1979 ISM theory , preset space characteristics // 12 early reflections . // // (delayMs, gain) : // - delayMs: input delay time ( ms ) // - gain: amplitude (0.0 ~ 1.0) // // design principles : // - distance inverse-square law : gain prop 1/distance prop 1/delayMs // - wall absorption coefficient ( reflection about -3dB ~ -6dB) // - physical reflection : floor -> wall -> ceiling -> reflection // // Plate/Spring/Goldfoil space ER // (numTaps = 0). preset ER processing bypass . // ----------------------------------------------------------------------------- static constexpr int MAX_ER_TAPS = 12; struct ERTap { float delayMs; float gain; }; struct ERPattern { int numTaps; // 0 ER bypass std::array taps; }; // preset ER static constexpr std::array PRESET_ER_PATTERNS = { { // ------------------------------------------------------------- // Room1: small live room ( about 40 m^3) // early reflections density , near-field wall surface reflection strong // ------------------------------------------------------------- { 12, {{ { 5.2f, 0.65f }, // floor 1 reflection { 8.7f, 0.58f }, // side wall 1 reflection { 12.4f, 0.52f }, // side wall 1 reflection { 15.8f, 0.46f }, // ceiling 1 reflection { 19.3f, 0.42f }, // rear wall 1 reflection { 24.1f, 0.36f }, // floor + wall 2 reflection { 28.6f, 0.32f }, // wall + ceiling 2 reflection { 33.5f, 0.28f }, // 2 reflection { 38.9f, 0.24f }, // 2 reflection { 45.2f, 0.20f }, // 3 reflection group { 52.8f, 0.16f }, // 3 reflection group { 62.4f, 0.13f } // 3 reflection group }}}, // ------------------------------------------------------------- // Room2: medium live room ( about 100 m^3) // reflection times wide range , ER smooth // ------------------------------------------------------------- { 12, {{ { 7.5f, 0.62f }, { 12.3f, 0.55f }, { 17.1f, 0.49f }, { 22.8f, 0.43f }, { 28.5f, 0.38f }, { 34.2f, 0.33f }, { 41.6f, 0.28f }, { 49.3f, 0.24f }, { 57.8f, 0.20f }, { 67.5f, 0.17f }, { 78.2f, 0.14f }, { 90.6f, 0.11f } }}}, // ------------------------------------------------------------- // Hall1: medium hall ( about 2000 m^3) // side wall reflection dominant , initial delay longer // ------------------------------------------------------------- { 12, {{ { 12.0f, 0.58f }, // floor 1 reflection { 18.5f, 0.52f }, // side wall 1 reflection { 25.7f, 0.47f }, // ceiling 1 reflection { 33.4f, 0.42f }, // side wall 1 reflection { 42.1f, 0.38f }, // rear wall 1 reflection { 51.6f, 0.33f }, // 2 reflection { 62.3f, 0.29f }, // 2 reflection { 73.9f, 0.25f }, // 2 reflection { 86.5f, 0.21f }, // 3 reflection { 99.8f, 0.18f }, // 3 reflection { 113.4f, 0.15f }, // 3 reflection { 128.7f, 0.12f } // diffuse reflection }}}, // ------------------------------------------------------------- // Hall2: large hall ( about 12000 m^3) // reflection times further , initial delay large // ------------------------------------------------------------- { 12, {{ { 16.5f, 0.55f }, { 24.8f, 0.50f }, { 33.7f, 0.45f }, { 43.5f, 0.40f }, { 54.2f, 0.36f }, { 65.8f, 0.32f }, { 78.4f, 0.28f }, { 92.1f, 0.24f }, { 107.3f, 0.21f }, { 123.6f, 0.18f }, { 141.2f, 0.15f }, { 160.5f, 0.12f } }}}, // ------------------------------------------------------------- // Plate: space (ER bypass ) // ------------------------------------------------------------- { 0, {{}} }, // ------------------------------------------------------------- // Spring: space (ER bypass ) // ------------------------------------------------------------- { 0, {{}} }, // ------------------------------------------------------------- // Goldfoil: space (ER bypass ) // ------------------------------------------------------------- { 0, {{}} } } }; struct AlgorithmPreset { const char* name; const char* description; float volumeM3; // estimated room volume (0 = non-room) AcousticData acoustics; }; // ----------------------------------------------------------------------------- // ROOM 1 : OpenAIR Measured Room // ----------------------------------------------------------------------------- static constexpr AlgorithmPreset PRESET_ROOM1 = { "ROOM1", "Real Room 1 (OpenAIR)", 40.0f, { // RT60 (s) 31 62 125 250 500 1k 2k 4k 8k 16k {{ 0.8f, 0.57f, 0.28f, 0.27f, 0.21f, 0.19f, 0.21f, 0.22f, 0.21f, 0.18f }}, // EDT (s) {{ 0.98f, 0.73f, 0.34f, 0.22f, 0.22f, 0.22f, 0.22f, 0.22f, 0.22f, 0.22f }}, // D50 {{ 0.26f, 0.46f, 0.92f, 0.94f, 0.98f, 0.97f, 0.97f, 0.97f, 0.96f, 0.98f }}, // C50 (dB) {{ -4.65f, -0.74f, 10.63f, 11.92f, 16.19f, 15.36f, 14.75f, 14.48f, 13.44f, 17.54f }}, // C80 (dB) {{ -2.33f, 5.82f, 16.5f, 20.03f, 23.87f, 26.0f, 23.59f, 22.54f, 22.92f, 27.99f }} } }; // ----------------------------------------------------------------------------- // ROOM 2 : OpenAIR Measured Room // ----------------------------------------------------------------------------- static constexpr AlgorithmPreset PRESET_ROOM2 = { "ROOM2", "Real Room 2 (OpenAIR)", 100.0f, { {{ 4.46f, 1.53f, 1.65f, 1.59f, 1.38f, 0.94f, 0.93f, 0.87f, 0.67f, 1.54f }}, {{ 1.59f, 1.33f, 1.07f, 1.07f, 1.2f, 1.07f, 0.95f, 0.82f, 0.69f, 0.43f }}, {{ 0.2f, 0.3f, 0.39f, 0.56f, 0.43f, 0.53f, 0.52f, 0.57f, 0.68f, 0.86f }}, {{ -5.99f, -3.59f, -1.96f, 1.05f, -1.16f, 0.51f, 0.41f, 1.21f, 3.23f, 7.73f }}, {{ 0.74f, 0.26f, 3.76f, 3.18f, 1.94f, 3.67f, 4.06f, 5.35f, 7.25f, 12.52f }} } }; // ----------------------------------------------------------------------------- // HALL 1 : OpenAIR Measured Hall // ----------------------------------------------------------------------------- static constexpr AlgorithmPreset PRESET_HALL1 = { "HALL1", "Real Hall 1 (OpenAIR)", 2000.0f, { {{ 3.55f, 2.28f, 2.18f, 2.05f, 1.89f, 1.86f, 1.69f, 1.28f, 0.9f, 5.53f }}, {{ 2.72f, 1.95f, 1.7f, 2.21f, 2.08f, 2.08f, 1.82f, 1.44f, 1.06f, 0.42f }}, {{ 0.06f, 0.19f, 0.25f, 0.12f, 0.15f, 0.19f, 0.2f, 0.33f, 0.41f, 0.83f }}, {{ -12.08f, -6.4f, -4.76f, -8.49f, -7.57f, -6.27f, -6.11f, -3.16f, -1.62f, 6.9f }}, {{ -7.02f, -2.45f, -0.66f, -3.54f, -2.86f, -2.84f, -2.37f, 0.46f, 2.63f, 11.94f }} } }; // ----------------------------------------------------------------------------- // HALL 2 : OpenAIR Measured Hall // ----------------------------------------------------------------------------- static constexpr AlgorithmPreset PRESET_HALL2 = { "HALL2", "Real Hall 2 (OpenAIR)", 12000.0f, { {{ 2.15f, 1.48f, 1.63f, 1.91f, 2.08f, 2.09f, 1.82f, 1.6f, 1.18f, 1.11f }}, {{ 1.83f, 1.45f, 1.45f, 2.34f, 2.22f, 1.96f, 1.83f, 1.7f, 1.45f, 1.19f }}, {{ 0.08f, 0.2f, 0.4f, 0.16f, 0.21f, 0.29f, 0.37f, 0.3f, 0.33f, 0.44f }}, {{ -10.33f, -6.01f, -1.69f, -7.33f, -5.82f, -3.83f, -2.34f, -3.73f, -3.08f, -1.f }}, {{ -2.99f, -3.18f, -0.69f, -3.02f, -3.05f, -0.92f, -0.36f, -0.77f, 0.13f, 2.59f }} } }; // ----------------------------------------------------------------------------- // PLATE : Studio Nord Bremen EMT-Style // ----------------------------------------------------------------------------- static constexpr AlgorithmPreset PRESET_PLATE = { "PLATE", "Vintage Plate (Studio Nord Bremen)", 0.0f, { {{ 4.6257f, 2.4647f, 1.6639f, 1.6039f, 1.1431f, 0.8664f, 0.6561f, 0.4921f, 0.3153f, 0.1973f }}, {{ 4.0113f, 2.1374f, 1.4429f, 1.3909f, 1.1926f, 0.8981f, 0.6476f, 0.5082f, 0.3132f, 0.2154f }}, {{ 0.2421f, 0.3389f, 0.4357f, 0.4841f, 0.3966f, 0.5246f, 0.5914f, 0.7155f, 0.8915f, 0.9695f }}, {{ -0.795f, -0.4236f, -0.286f, -0.2757f, -1.8231f, 0.4282f, 1.6063f, 4.0053f, 9.1464f, 15.0212f }}, {{ 5.9205f, 3.1547f, 2.1296f, 2.0529f, 1.1228f, 3.8402f, 5.8356f, 8.7699f, 14.5235f, 23.4324f }} } }; // ----------------------------------------------------------------------------- // SPRING : Studio Nord Bremen Vintage Spring // ----------------------------------------------------------------------------- static constexpr AlgorithmPreset PRESET_SPRING = { "SPRING", "Vintage Spring (Studio Nord Bremen)", 0.0f, { {{ 10.3635f, 5.522f, 3.7278f, 3.5934f, 2.9252f, 2.7681f, 2.0397f, 2.0373f, 2.1111f, 0.9319f }}, {{ 4.9277f, 2.6256f, 1.7725f, 1.7086f, 1.5756f, 1.875f, 1.3502f, 1.3897f, 1.759f, 0.4177f }}, {{ 0.1261f, 0.1765f, 0.227f, 0.2522f, 0.2939f, 0.1999f, 0.3321f, 0.3724f, 0.3551f, 0.9202f }}, {{ -13.6143f, -7.2541f, -4.8971f, -4.7206f, -3.806f, -6.0225f, -3.0348f, -2.2663f, -2.591f, 10.6169f }}, {{ -3.0172f, -1.6077f, -1.0853f, -1.0462f, -1.6692f, -2.0212f, 0.4169f, 0.5432f, 0.0761f, 13.5636f }} } }; // ----------------------------------------------------------------------------- // GOLD FOIL : Studio Nord Bremen Foil Reverb // ----------------------------------------------------------------------------- static constexpr AlgorithmPreset PRESET_GOLDFOIL = { "GOLDFOIL", "Gold Foil (Studio Nord Bremen)", 0.0f, { {{ 6.3421f, 3.3793f, 2.2813f, 2.1991f, 2.0642f, 2.255f, 2.17f, 1.4604f, 0.8313f, 0.4339f }}, {{ 5.8718f, 3.1287f, 2.1121f, 2.036f, 1.8796f, 2.2713f, 2.0286f, 1.4122f, 0.7486f, 0.3458f }}, {{ 0.1209f, 0.1693f, 0.2177f, 0.2419f, 0.2894f, 0.2261f, 0.2938f, 0.4516f, 0.6304f, 0.8808f }}, {{ -14.3077f, -7.6236f, -5.1466f, -4.9611f, -3.9018f, -5.3429f, -3.8094f, -0.8434f, 2.3195f, 8.6843f }}, {{ -2.5178f, -1.3416f, -0.9057f, -0.873f, -1.4987f, -1.424f, -1.4095f, 1.7577f, 5.4677f, 12.9829f }} } }; // ----------------------------------------------------------------------------- // Master table // ----------------------------------------------------------------------------- static constexpr std::array ALL_PRESETS = { { &PRESET_ROOM1, &PRESET_ROOM2, &PRESET_HALL1, &PRESET_HALL2, &PRESET_PLATE, &PRESET_SPRING, &PRESET_GOLDFOIL } }; } // namespace FDNReverb