mirror of
https://codeberg.org/armin/ambivalence.git
synced 2026-09-01 04:10:48 +02:00
349 lines
No EOL
17 KiB
C++
349 lines
No EOL
17 KiB
C++
#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 <array>
|
|
|
|
namespace FDNReverb {
|
|
|
|
static constexpr int NUM_BANDS = 10;
|
|
static constexpr int NUM_ALGORITHMS = 7;
|
|
|
|
// Octave-band centre frequencies (Hz)
|
|
static constexpr std::array<float, NUM_BANDS> 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<float, NUM_BANDS> rt60; // RT60 (s)
|
|
std::array<float, NUM_BANDS> edt; // EDT (s)
|
|
std::array<float, NUM_BANDS> d50; // Definition 0-1
|
|
std::array<float, NUM_BANDS> c50; // Clarity 50 ms (dB)
|
|
std::array<float, NUM_BANDS> 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<PresetDefaults, 7> 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<ERTap, MAX_ER_TAPS> taps;
|
|
};
|
|
|
|
// preset ER
|
|
static constexpr std::array<ERPattern, 7> 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<const AlgorithmPreset*, NUM_ALGORITHMS> ALL_PRESETS = { {
|
|
&PRESET_ROOM1,
|
|
&PRESET_ROOM2,
|
|
&PRESET_HALL1,
|
|
&PRESET_HALL2,
|
|
&PRESET_PLATE,
|
|
&PRESET_SPRING,
|
|
&PRESET_GOLDFOIL
|
|
} };
|
|
|
|
} // namespace FDNReverb
|