| 90 | } // namespace |
| 91 | |
| 92 | int main() |
| 93 | { |
| 94 | // ── Test 1: default construction ────────────────────────────────── |
| 95 | { |
| 96 | ClientReverb r; |
| 97 | r.prepare(kSampleRate); |
| 98 | report("constructor starts disabled", !r.isEnabled()); |
| 99 | } |
| 100 | |
| 101 | // ── Test 2: enable toggle ───────────────────────────────────────── |
| 102 | { |
| 103 | ClientReverb r; |
| 104 | r.prepare(kSampleRate); |
| 105 | r.setEnabled(true); |
| 106 | const bool gotOn = r.isEnabled(); |
| 107 | r.setEnabled(false); |
| 108 | const bool gotOff = !r.isEnabled(); |
| 109 | report("enable toggle", gotOn && gotOff); |
| 110 | } |
| 111 | |
| 112 | // ── Test 3: impulse response produces non-trivial tail ──────────── |
| 113 | { |
| 114 | ClientReverb r; |
| 115 | r.prepare(kSampleRate); |
| 116 | r.setEnabled(true); |
| 117 | r.setMix(1.0f); // fully wet |
| 118 | r.setDecayS(2.0f); |
| 119 | r.setPreDelayMs(0.0f); |
| 120 | // Longer buffer so the tail has room to manifest. |
| 121 | const int totalFrames = static_cast<int>(kSampleRate * 1.0); |
| 122 | std::vector<float> buf = makeImpulse(totalFrames, 0.9f); |
| 123 | processBlocks(r, buf.data(), totalFrames); |
| 124 | // Tail region: skip the first 10 ms (direct + initial echoes) |
| 125 | // and measure L2 norm of the next ~100 ms. |
| 126 | const int tailStart = static_cast<int>(kSampleRate * 0.01); |
| 127 | const int tailLen = static_cast<int>(kSampleRate * 0.10); |
| 128 | const float tailEnergy = l2NormStereo( |
| 129 | buf.data() + tailStart * 2, tailLen); |
| 130 | report("impulse → non-zero tail", tailEnergy > 1e-4f, |
| 131 | "energy=" + std::to_string(tailEnergy)); |
| 132 | report("impulse → finite output", |
| 133 | !anyNaNorInf(buf.data(), totalFrames)); |
| 134 | } |
| 135 | |
| 136 | // ── Test 4: tail energy decays over time ────────────────────────── |
| 137 | { |
| 138 | ClientReverb r; |
| 139 | r.prepare(kSampleRate); |
| 140 | r.setEnabled(true); |
| 141 | r.setMix(1.0f); |
| 142 | r.setDecayS(1.5f); |
| 143 | r.setPreDelayMs(0.0f); |
| 144 | const int totalFrames = static_cast<int>(kSampleRate * 2.0); |
| 145 | std::vector<float> buf = makeImpulse(totalFrames, 0.9f); |
| 146 | processBlocks(r, buf.data(), totalFrames); |
| 147 | const int halfLen = totalFrames / 2; |
| 148 | const float firstHalf = l2NormStereo(buf.data(), halfLen); |
| 149 | const float lastHalf = l2NormStereo(buf.data() + halfLen * 2, |
nothing calls this directly
no test coverage detected