Sanity: no NaN/inf under a nasty transient sequence.
| 409 | |
| 410 | // Sanity: no NaN/inf under a nasty transient sequence. |
| 411 | void testTransientSanity() |
| 412 | { |
| 413 | ClientComp comp; |
| 414 | comp.prepare(kSampleRate); |
| 415 | comp.setEnabled(true); |
| 416 | comp.setThresholdDb(-24.0f); |
| 417 | comp.setRatio(10.0f); |
| 418 | comp.setKneeDb(6.0f); |
| 419 | comp.setMakeupDb(12.0f); |
| 420 | comp.setAttackMs(5.0f); |
| 421 | comp.setReleaseMs(100.0f); |
| 422 | comp.setLimiterEnabled(true); |
| 423 | comp.setLimiterCeilingDb(-1.0f); |
| 424 | |
| 425 | const int frames = static_cast<int>(kSampleRate) * 2; |
| 426 | std::vector<float> buf(frames * 2); |
| 427 | const double twoPi = 6.283185307179586476; |
| 428 | for (int i = 0; i < frames; ++i) { |
| 429 | // Amplitude-modulated tone + spikes: stress envelope+limiter. |
| 430 | const float env = 0.1f + 0.8f |
| 431 | * static_cast<float>(std::fabs(std::sin(twoPi * 3.0 * i / kSampleRate))); |
| 432 | const float s = env * static_cast<float>( |
| 433 | std::sin(twoPi * 1000.0 * i / kSampleRate)); |
| 434 | buf[i * 2] = s; |
| 435 | buf[i * 2 + 1] = s; |
| 436 | } |
| 437 | |
| 438 | processBlocks(comp, buf.data(), frames); |
| 439 | |
| 440 | const bool finite = !anyNaNorInf(buf.data(), frames); |
| 441 | const float peak = peakAbsStereo(buf.data(), frames); |
| 442 | report("stress: AM tone output is finite", |
| 443 | finite, |
| 444 | ""); |
| 445 | report("stress: output peak respects limiter ceiling (+1 dB headroom)", |
| 446 | peak < 1.0f, |
| 447 | "peak=" + std::to_string(peak)); |
| 448 | } |
| 449 | |
| 450 | // reset() must clear envelope so a new burst starts from silence. |
| 451 | void testResetClearsEnvelope() |
no test coverage detected