Modified looper.h: grainy/crinkly noise on overdubs

Hello Daisy Forum! I’m currently working on a delay/phaser combo guitar pedal using the Daisy Seed. I’m a bit rusty with C++, but so far I’ve been making good progress.

I’m modifying the “looper.h” header file found in the DaisySP C++ library to work as a “hold mode” with the delay-time knob being used to set the playback speed. I’ll refer to it as the “modified looper” from now on.

So far everything else works smoothly enough, but I have an issue with the overdubs. My first recording to the modified looper below will sound clear, however the overdubs will have this grainy, crinkly noise throughout, which I’ve struggled to find a fix for. I want to note that each overdub does not become progressively noisier.

My modified looper.h code is as follows:

#pragma once
#ifndef DSY_DL_HOLD_H
#define DSY_DL_HOLD_H
#include "daisysp.h"
#include "daisy_seed.h"
namespace daisysp
{
class DLHold
{
public:
DLHold() {}
~DLHold() {}

    void Init(float *mem, size_t size) {
        buff_size_ = size;
        buff_ = mem;

        InitBuff();

        state_ = State::EMPTY;
        win_idx_ = 0;  
        inc_size_ = 1.0f;
    }

    inline void Clear() { state_ = State::EMPTY; }

    float Process(const float in) {
        float sig = 0.0f;
        float inc;

        inc = state_ == State::EMPTY || state_ == State::REC_FIRST
            ? 1.f
            : inc_size_;
        win_ = WindowVal(win_idx_ * kWindowFactor);

        switch(state_) {
            case State::EMPTY:
                sig = 0.0f;
                pos_ = 0;
                rec_size_ = 0;
                break;
            case State::REC_FIRST:
                sig = 0.0f;
                Write(pos_, in * win_);
                if(win_idx_ < kWindowSamps - 1)
                    win_idx_ += 1;
                rec_size_ = pos_;
                pos_ += inc;
                if(pos_ > buff_size_ - 1) {
                    state_ = State::PLAYING;
                    rec_size_ = pos_ - 1;
                    pos_ = 0;
                }
                break;
            case State::PLAYING:
                sig = Read(pos_);

                if(win_idx_ < kWindowSamps - 1) {
                    Write(pos_, sig + in * (1.0f - win_));
                    win_idx_ += 1;
                }

                pos_ += inc;
                if(pos_ > (float)rec_size_ - 1) {
                    pos_ = 0.0f;
                }
                else if(pos_ < 0.0f) {
                    pos_ = (float)rec_size_ - 1;
                }
                break;
            case State::REC_DUB:
                sig = Read(pos_);

                Write(pos_, (in * win_) + sig);

                if(win_idx_ < kWindowSamps - 1) {
                    win_idx_ += 1;
                }

                pos_ += inc;
                if(pos_ > (float)rec_size_ - 1) {
                    pos_ = 0.0f;
                }
                else if(pos_ < 0.0f) {
                    pos_ = (float)rec_size_ - 1;
                }
                break;
            default: break;
        }
        return sig;
    }

    inline void TrigRecord() {
        switch(state_) {
            case State::EMPTY:
            pos_ = 0.0f;
            rec_size_ = 0;
            state_ = State::REC_FIRST;
            break;
            case State::REC_FIRST:
            case State::REC_DUB: state_ = State::PLAYING; break;
            case State::PLAYING: state_ = State::REC_DUB; break;
            default: state_ = State::EMPTY; break;
        }
        win_idx_ = 0;
    }

    inline const bool Recording() const
    {
        return state_ == State::REC_DUB || state_ == State::REC_FIRST;
    }

    float Lerp(float start, float end, float t) {
        return start + (end - start) * t;
    }

    void SetIncrementSize(float inc_set) { inc_size_ = inc_set; }

    inline void SetPlaybackSpeed(float del_time) {
        constexpr float kMinSpeed = 0.5f;
        constexpr float kMaxSpeed = 2.0f;

        float speed;
        if(del_time <= 0.5f) {
            speed = Lerp(kMinSpeed, 1.0f, del_time / 0.5f);
        }
        else {
            speed = Lerp(1.0f, kMaxSpeed, (del_time - 0.5f) / 0.5f);
        }

        SetIncrementSize(speed);
        }

private:
    static constexpr int kWindowSamps = 1200;
    static constexpr float kWindowFactor = (1.0f / kWindowSamps);
    
    void InitBuff() { std::fill(&buff_[0], &buff_[buff_size_ - 1], 0); }
    
    inline const float Read(size_t pos) const { return buff_[pos]; }

    inline void Write(size_t pos, float val) { buff_[pos] = val; }

    float WindowVal(float in) { return sin(HALFPI_F * in); }

    enum class State
    {
        EMPTY,
        REC_FIRST,
        PLAYING,
        REC_DUB
    };

    float *buff_;
    float inc_size_;
    float pos_, win_;
    size_t buff_size_;
    size_t rec_size_;
    size_t win_idx_;
    State state_;

};
};
#endif

Any help is greatly appreciated! Thank you.

Welcome @r-r-o-t-r-n-r!!

When you get a chance, could you please share the audio file of the overdubbing? You should be able to embed an audio file to a post.
Hearing what the noise sounds like may gives us more idea of what the issue could be. Thanks!!