31    constexpr static size_t kMaxSize = 88200;
 
   32    constexpr static size_t kMinSize = 1;
 
   33    constexpr static size_t kNeutralSize = 16384;
 
   35    DelayBuffer() = 
default;
 
   36    ~DelayBuffer() { discard(); }
 
   37    Error init(uint32_t newRate, uint32_t failIfThisSize = 0, 
bool includeExtraSpace = 
true);
 
   41    constexpr void invalidate() { start_ = 
nullptr; }
 
   43    void makeNativeRatePrecise();
 
   44    void makeNativeRatePreciseRelativeToOtherBuffer(
const DelayBuffer& otherBuffer);
 
   49    [[gnu::always_inline]] 
constexpr int32_t advance(C callback) {
 
   50        longPos += resample_config_.value().actualSpinRate;
 
   51        uint8_t newShortPos = longPos >> 24;
 
   52        uint8_t shortPosDiff = newShortPos - lastShortPos;
 
   53        lastShortPos = newShortPos;
 
   55        while (shortPosDiff > 0) {
 
   59        return (longPos >> 8) & 65535;
 
   62    [[gnu::always_inline]] 
constexpr int32_t retreat(C callback) {
 
   63        longPos -= resample_config_.value().actualSpinRate;
 
   64        uint8_t newShortPos = longPos >> 24;
 
   65        uint8_t shortPosDiff = lastShortPos - newShortPos; 
 
   66        lastShortPos = newShortPos;
 
   68        while (shortPosDiff > 0) {
 
   72        return (longPos >> 8) & 65535; 
 
   75    void setupForRender(int32_t rate);
 
   77    static std::pair<int32_t, bool> getIdealBufferSizeFromRate(uint32_t rate);
 
   79    [[nodiscard]] 
constexpr bool isActive()
 const { 
return (start_ != 
nullptr); }
 
   81    inline bool clearAndMoveOn() {
 
   87    inline bool moveOn() {
 
   89        bool wrapped = (current_ == end_);
 
   96    inline bool moveBack() {
 
   97        if (current_ == start_) {
 
  107    inline void writeNative(StereoSample<q31_t> toDelay) {
 
  108        StereoSample<q31_t>* writePos = current_ - delaySpaceBetweenReadAndWrite;
 
  109        if (writePos < start_) {
 
  110            writePos += sizeIncludingExtra;
 
  112        writePos->l = toDelay.l;
 
  113        writePos->r = toDelay.r;
 
  116    inline void writeNativeAndMoveOn(StereoSample<q31_t> toDelay, StereoSample<q31_t>** writePos) {
 
  117        (*writePos)->l = toDelay.l;
 
  118        (*writePos)->r = toDelay.r;
 
  121        if (*writePos == end_) {
 
  126    [[gnu::always_inline]] 
void write(StereoSample<q31_t> toDelay, int32_t strength1, int32_t strength2) {
 
  129            StereoSample<q31_t>* writePos = current_ - delaySpaceBetweenReadAndWrite;
 
  130            if (writePos < start_) {
 
  131                writePos += sizeIncludingExtra;
 
  133            writePos->l = toDelay.l;
 
  134            writePos->r = toDelay.r;
 
  138        writeResampled(toDelay, strength1, strength2);
 
  141    [[gnu::always_inline]] 
void writeResampled(StereoSample<q31_t> toDelay, int32_t strength1, int32_t strength2) {
 
  142        if (!resample_config_) {
 
  146        if (resample_config_->actualSpinRate >= kMaxSampleValue) {
 
  157            int32_t howFarRightToStart = (strength2 + (resample_config_->spinRateForSpedUpWriting >> 8)) >> 16;
 
  161            int32_t distanceFromMainWrite = (int32_t)howFarRightToStart << 16;
 
  164            StereoSample<q31_t>* writePos = current_ - delaySpaceBetweenReadAndWrite + howFarRightToStart;
 
  165            while (writePos < start_) {
 
  166                writePos += sizeIncludingExtra;
 
  168            while (writePos >= end_) {
 
  169                writePos -= sizeIncludingExtra;
 
  173            while (distanceFromMainWrite != 0) { 
 
  175                int32_t strengthThisWrite =
 
  176                    (0xFFFFFFFF >> 4) - (((distanceFromMainWrite - strength2) >> 4) * resample_config_->divideByRate);
 
  178                writePos->l += multiply_32x32_rshift32(toDelay.l, strengthThisWrite) << 3;
 
  179                writePos->r += multiply_32x32_rshift32(toDelay.r, strengthThisWrite) << 3;
 
  181                if (--writePos < start_) {
 
  185                distanceFromMainWrite -= 65536;
 
  190                int32_t strengthThisWrite =
 
  191                    (0xFFFFFFFF >> 4) - (((distanceFromMainWrite + strength2) >> 4) * resample_config_->divideByRate);
 
  192                if (strengthThisWrite <= 0) {
 
  196                writePos->l += multiply_32x32_rshift32(toDelay.l, strengthThisWrite) << 3;
 
  197                writePos->r += multiply_32x32_rshift32(toDelay.r, strengthThisWrite) << 3;
 
  202                if (writePos < start_) {
 
  205                distanceFromMainWrite += 65536;
 
  224            StereoSample<q31_t>* writePos = current_ - delaySpaceBetweenReadAndWrite + 2;
 
  226            while (writePos < start_) {
 
  227                writePos += sizeIncludingExtra;
 
  235            strength[1] = strength1 + resample_config_->rateMultiple - 65536; 
 
  236            strength[2] = strength2 + resample_config_->rateMultiple - 65536; 
 
  239            strength[0] = strength[1] - 65536;
 
  240            strength[3] = strength[2] - 65536;
 
  244                if (strength[i] > 0) {
 
  246                        multiply_32x32_rshift32(toDelay.l, (strength[i] >> 2) * resample_config_->writeSizeAdjustment)
 
  249                        multiply_32x32_rshift32(toDelay.r, (strength[i] >> 2) * resample_config_->writeSizeAdjustment)
 
  259                if (writePos < start_) {
 
  266    [[nodiscard]] 
constexpr bool isNative()
 const { 
return !resample_config_.has_value(); }
 
  267    [[nodiscard]] 
constexpr bool resampling()
 const { 
return resample_config_.has_value(); }
 
  268    [[nodiscard]] 
constexpr uint32_t nativeRate()
 const { 
return native_rate_; }
 
  271    [[nodiscard]] 
constexpr StereoSample<q31_t>& current()
 const { 
return *current_; }
 
  272    [[nodiscard]] 
constexpr StereoSample<q31_t>* begin()
 const { 
return start_; }
 
  273    [[nodiscard]] 
constexpr StereoSample<q31_t>* end()
 const { 
return end_; }
 
  274    [[nodiscard]] 
constexpr size_t size()
 const { 
return size_; }
 
  278    constexpr void setCurrent(StereoSample<q31_t>* sample) { current_ = sample; }
 
  283    uint8_t lastShortPos;
 
  285    size_t sizeIncludingExtra;
 
  289        uint32_t actualSpinRate;           
 
  290        uint32_t spinRateForSpedUpWriting; 
 
  291        uint32_t divideByRate;             
 
  292        uint32_t rateMultiple;
 
  293        uint32_t writeSizeAdjustment;
 
 
  296    void setupResample();
 
  298    uint32_t native_rate_ = 0;
 
  300    StereoSample<q31_t>* start_ = 
nullptr;
 
  301    StereoSample<q31_t>* end_;
 
  302    StereoSample<q31_t>* current_;
 
  307    std::optional<ResampleConfig> resample_config_{};