aboutsummaryrefslogtreecommitdiffstats
path: root/src/gain_processor.h
blob: 04f2041525250345c07ec965d366f0eadad93667 (plain) (blame)
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include <functional>

#include "config.h"

template<class T>
class TGainProcessor : public virtual T {

public:
    typedef std::function<void(TFloat* out, TFloat* cur, TFloat* prev)> TGainDemodulator;
    /*
     * example GainModulation:
     * PCMinput:
     *     N   b    N        N
     * --------|--------|--------|--------
     * |       | - mdct #1
     *     |        | - mdct #2
     *     a
     *         |        | - mdct #3
     *         ^^^^^ - modulated by previous step
     * lets consider a case we want to modulate mdct #2.
     *     bufCur - is a buffer of first half of mdct transformation (a)
     *     bufNext - is a buffer of second half of mdct transformation and overlaping
     *               (i.e the input buffer started at b point)
     * so next transformation (mdct #3) gets modulated first part
     */
    typedef std::function<void(TFloat* bufCur, TFloat* bufNext)> TGainModulator;
    static TFloat GetGainInc(uint32_t levelIdxCur) {
        const int incPos = T::ExponentOffset - levelIdxCur + T::GainInterpolationPosShift;
        return T::GainInterpolation[incPos];
    }
    static TFloat GetGainInc(uint32_t levelIdxCur, uint32_t levelIdxNext) {
        const int incPos = levelIdxNext - levelIdxCur + T::GainInterpolationPosShift;
        return T::GainInterpolation[incPos];
    }


    TGainDemodulator Demodulate(const std::vector<typename T::SubbandInfo::TGainPoint>& giNow, const std::vector<typename T::SubbandInfo::TGainPoint>& giNext) {
        return [=](TFloat* out, TFloat* cur, TFloat* prev) {
            uint32_t pos = 0;
            const TFloat scale = giNext.size() ? T::GainLevel[giNext[0].Level] : 1;
            for (uint32_t i = 0; i < giNow.size(); ++i) {
                uint32_t lastPos = giNow[i].Location << T::LocScale;
                const uint32_t levelPos = giNow[i].Level;
                assert(levelPos < sizeof(T::GainLevel)/sizeof(T::GainLevel[0]));
                TFloat level = T::GainLevel[levelPos];
                const int incPos = ((i + 1) < giNow.size() ? giNow[i + 1].Level : T::ExponentOffset) - giNow[i].Level + T::GainInterpolationPosShift;
                TFloat gainInc = T::GainInterpolation[incPos];
                for (; pos < lastPos; pos++) {
                    //std::cout << "pos: " << pos << " scale: " << scale << " level: " << level << std::endl;
                    out[pos] = (cur[pos] * scale + prev[pos]) * level;
                }
                for (; pos < lastPos + T::LocSz; pos++) {
                    //std::cout << "pos: " << pos << " scale: " << scale << " level: " << level << " gainInc: " << gainInc << std::endl;
                    out[pos] = (cur[pos] * scale + prev[pos]) * level;
                    level *= gainInc;
                }
            }
            for (; pos < T::MDCTSz/2; pos++) {
                //std::cout << "pos: " << pos << " scale: " << scale << std::endl;
                out[pos] = cur[pos] * scale + prev[pos];
            }
        };
    }
    TGainModulator Modulate(const std::vector<typename T::SubbandInfo::TGainPoint>& giCur) {
        if (giCur.empty())
            return {};
        return [=](TFloat* bufCur, TFloat* bufNext) {
            uint32_t pos = 0;
            const TFloat scale = T::GainLevel[giCur[0].Level];
            for (uint32_t i = 0; i < giCur.size(); ++i) {
                uint32_t lastPos = giCur[i].Location << T::LocScale;
                const uint32_t levelPos = giCur[i].Level;
                assert(levelPos < sizeof(T::GainLevel)/sizeof(T::GainLevel[0]));
                TFloat level = T::GainLevel[levelPos];
                const int incPos = ((i + 1) < giCur.size() ? giCur[i + 1].Level : T::ExponentOffset) - giCur[i].Level + T::GainInterpolationPosShift;
                TFloat gainInc = T::GainInterpolation[incPos];
                for (; pos < lastPos; pos++) {
                    //std::cout << "mod pos: " << pos << " scale: " << scale << " bufCur: " <<  bufCur[pos]  << " level: " << level << " bufNext: " << bufNext[pos] << std::endl;
                    bufCur[pos] /= scale;
                    bufNext[pos] /= level;
                }
                for (; pos < lastPos + T::LocSz; pos++) {

                    //std::cout << "mod pos: " << pos << " scale: " << scale << " bufCur: " <<  bufCur[pos]  << " level: " << level << " (gainInc) " << gainInc << " bufNext: " << bufNext[pos] << std::endl;
                    bufCur[pos] /= scale;
                    bufNext[pos] /= level;
                    //std::cout << "mod pos: " << pos << " scale: " << scale << " level: " << level << " gainInc: " << gainInc << std::endl;
                    level *= gainInc;
                }
            }
            for (; pos < T::MDCTSz/2; pos++) {

                //std::cout << "mod pos: " << pos << " scale: " << scale << " bufCur: " << bufCur[pos] << std::endl;
                bufCur[pos] /= scale;
            }
        };
    }
};