summaryrefslogtreecommitdiffstats
path: root/src/engine/filters/enginefilterpansingle.h
blob: 3a91f1cf785b66aad81d3035ec6d74a5a88e5231 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/**
 * FilterPan Single :
 * + This delay will be applied on left channel following the
 * leftDelayFrames parameter and on the right one by minus leftDelayFrames.
 * + This delay is applied sample by sample and not on the full buffer.
 */

#pragma once

#include <string.h>

#include "engine/engineobject.h"
#include "util/assert.h"

static const int numChannels = 2;

template<unsigned int SIZE>
class EngineFilterPanSingle {
  public:
    EngineFilterPanSingle()
            : m_delayFrame(0),
              m_doStart(false) {
        // Set the current buffers to 0
        memset(m_buf, 0, sizeof(m_buf));
    }

    virtual ~EngineFilterPanSingle() {};

    void pauseFilter() {
        // Set the current buffers to 0
        if (!m_doStart) {
            memset(m_buf, 0, sizeof(m_buf));
            m_doStart = true;
        }
    }

    virtual void process(const CSAMPLE* pIn, CSAMPLE* pOutput, double leftDelayFrames) {
        double delayLeftSourceFrame;
        double delayRightSourceFrame;

        if (leftDelayFrames > 0) {
            delayLeftSourceFrame = m_delayFrame + SIZE - leftDelayFrames;
            delayRightSourceFrame = m_delayFrame + SIZE;
        } else {
            delayLeftSourceFrame = m_delayFrame + SIZE;
            delayRightSourceFrame = m_delayFrame + SIZE + leftDelayFrames;
        }

        // put in samples into delay buffer
        m_buf[m_delayFrame * 2] = pIn[0];
        m_buf[m_delayFrame * 2 + 1] = pIn[1];
        // move the delay cursor forward
        m_delayFrame = (m_delayFrame + 1) % SIZE;

        // prepare coefficients for linear interpolation using a linear stretching
        CSAMPLE_GAIN timeBetweenFullSamplesLeft = fmod(delayLeftSourceFrame, 1);
        CSAMPLE_GAIN timeBetweenFullSamplesRight = fmod(delayRightSourceFrame, 1);

        // applying the delay on left channel with linear interpolation between each sample
        pOutput[0] =
                m_buf[(static_cast<int>(floor(delayLeftSourceFrame)) % SIZE) * 2] *
                (1 - timeBetweenFullSamplesLeft);
        pOutput[0] +=
                m_buf[(static_cast<int>(ceil(delayLeftSourceFrame)) % SIZE) * 2] *
                timeBetweenFullSamplesLeft;
        // then on right channel
        pOutput[1] =
                m_buf[(static_cast<int>(floor(delayRightSourceFrame)) % SIZE) * 2 + 1] *
                (1 - timeBetweenFullSamplesRight);
        pOutput[1] +=
                m_buf[(static_cast<int>(ceil(delayRightSourceFrame)) % SIZE) * 2 + 1] *
                timeBetweenFullSamplesRight;

        m_doStart = false;
    }

  protected:
    int m_delayFrame;
    CSAMPLE m_buf[SIZE * numChannels];
    bool m_doStart;
};