| 143 | } |
| 144 | |
| 145 | void Resampler::prewarm() |
| 146 | { |
| 147 | if (std::abs(m_srcRate - m_dstRate) < 0.001) return; |
| 148 | |
| 149 | // Called from the constructor for every Resampler instance (RX, TX, BNR, RADE, etc.). |
| 150 | // r8brain with DoConsumeLatency=true silently discards the first Latency input samples |
| 151 | // before emitting any output. Feeding zeros here consumes that startup latency so the |
| 152 | // first real audio sample produces output immediately, removing the transient that would |
| 153 | // otherwise appear at the start of every audio session. |
| 154 | double* outPtr = nullptr; |
| 155 | int lenRequired = m_resampler->getInLenBeforeOutPos(0); |
| 156 | while (lenRequired > 0) { |
| 157 | int len = std::min(lenRequired, m_maxBlockSamples); |
| 158 | std::vector<double> zeros(len, 0.0); |
| 159 | m_resampler->process(zeros.data(), len, outPtr); |
| 160 | lenRequired -= len; |
| 161 | } |
| 162 | } |
| 163 | |
| 164 | } // namespace AetherSDR |