Looper with oversampling and linear interpolation

 avatar
unknown
c_cpp
5 months ago
3.5 kB
15
Indexable
class Looper
{
  public:
    Looper() : crossfade_length_(1200), oversample_factor_(8) {}
    ~Looper() {}

    void Init(float *mem1, size_t size)
    {
        buffer_size_ = size * oversample_factor_;
        buff_   = mem1;
        InitBuff();
        antialias_filter_.Init(48000); 
    }

    /** Handles reading/writing to the Buffer depending on the mode. */
    float Process(const float input, float speed)
    {
        float sig = 0.f;
        float filteredsig = 0.f;
        inc = changePitch(speed);
        antialias_filter_.SetFreq(24000);
        switch(state_)
        {
            case State::PLAYING:
                switch(mode_) {
                    case Mode::SOS:
                        sig = Read(pos_);
                        antialias_filter_.Process(sig);
                        filteredsig = antialias_filter_.Low();
                        pos_ += oversample_factor_ * inc; 
                }
            case State::REC_DUB:                
                switch(mode_)
                {   
                    case Mode::SOS:
                    {
                        sig = Read(pos_);
                        antialias_filter_.Process(sig);
                        filteredsig = antialias_filter_.Low();
                        for (unsigned int i = 0; i < oversample_factor_; i++) {
                            Write(pos_ + i, input + sig * blend);    
                         }
                        pos_ += oversample_factor_ * inc;  // Adjust position increment for oversampling
                    }
        return filteredsig * blend;
    }

    float changePitch(float pknob) {
    static const float speedValues[] = {
        0.5f,       // -12 semitones
        0.529732f,  // -11 semitones
        0.561231f,  // -10 semitones
        0.594604f,  // -9 semitones
        0.629961f,  // -8 semitones
        0.667420f,  // -7 semitones
        0.707107f,  // -6 semitones
        0.749154f,  // -5 semitones
        0.793701f,  // -4 semitones
        0.840896f,  // -3 semitones
        0.890899f,  // -2 semitones
        0.943874f,  // -1 semitone
        1.0f,       // 0 semitones (unchanged)
        1.059463f,  // +1 semitone
        1.122462f,  // +2 semitones
        1.189207f,  // +3 semitones
        1.259921f,  // +4 semitones
        1.334840f,  // +5 semitones
        1.414214f,  // +6 semitones
        1.498307f,  // +7 semitones
        1.587401f,  // +8 semitones
        1.681793f,  // +9 semitones
        1.781797f,  // +10 semitones
        1.887749f,  // +11 semitones
        2.0f        // +12 semitones
    };
    int index = static_cast<int>(pknob * 24.999);
    return speedValues[std::min(index, 24)];
}

    void InitBuff() 
    { 
        std::fill(&buff_[0], &buff_[buffer_size_], 0); 
    }

   inline float Read(float pos) const
        {
            int int_pos = static_cast<int>(pos); 
            float frac = pos - int_pos;     

            float y0 = buff_[int_pos % buffer_size_];
            float y1 = buff_[(int_pos + 1) % buffer_size_];

            // Perform linear interpolation
            return y0 + frac * (y1 - y0);
        }

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



    /** Private Member Variables */
    Mode   mode_;
    State  state_;
    float *buff_;
    unsigned int writebuff_;
    size_t buffer_size_;
    float  pos_, wpos_
    float  inc;
    size_t recsize_, playsize_;
    const int oversample_factor_;
    Svf antialias_filter_;
};

}
Editor is loading...
Leave a Comment