blob: 8369ccfe1339780292804503a594eed6de4387c6 (
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
|
#include <functional>
template<class T>
class TGainProcessor : public virtual T {
public:
typedef std::function<void(double* out, double* cur, double* 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(double* bufCur, double* bufNext)> TGainModulator;
TGainDemodulator Demodulate(const std::vector<typename T::SubbandInfo::TGainPoint>& giNow, const std::vector<typename T::SubbandInfo::TGainPoint>& giNext) {
return [=](double* out, double* cur, double* prev) {
uint32_t pos = 0;
const double 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]));
double level = T::GainLevel[levelPos];
const int incPos = ((i + 1) < giNow.size() ? giNow[i + 1].Level : T::ExponentOffset) - giNow[i].Level + T::GainInterpolationPosShift;
double 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 [=](double* bufCur, double* bufNext) {
uint32_t pos = 0;
const double 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]));
double level = T::GainLevel[levelPos];
const int incPos = ((i + 1) < giCur.size() ? giCur[i + 1].Level : T::ExponentOffset) - giCur[i].Level + T::GainInterpolationPosShift;
double gainInc = T::GainInterpolation[incPos];
for (; pos < lastPos; pos++) {
bufCur[pos] /= scale;
bufNext[pos] /= level;
//std::cout << "mod pos: " << pos << " scale: " << scale << " level: " << level << std::endl;
}
for (; pos < lastPos + T::LocSz; pos++) {
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++) {
bufCur[pos] /= scale;
//std::cout << "mod pos: " << pos << " scale: " << scale << std::endl;
}
};
}
};
|