forked from beefviper/hode-vs
-
Notifications
You must be signed in to change notification settings - Fork 1
/
mixer.cpp
91 lines (81 loc) · 2.17 KB
/
mixer.cpp
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
#include "mixer.h"
#include "util.h"
static void nullMixerLock(int lock) {
}
Mixer::Mixer()
: _lock(nullMixerLock) {
memset(_mixingQueue, 0, sizeof(_mixingQueue));
_mixingQueueSize = 0;
}
Mixer::~Mixer() {
}
void Mixer::queue(const int16_t *ptr, const int16_t *end, int panType, int panL, int panR, bool stereo) {
if (_mixingQueueSize >= kMixingQueueSize) {
warning("MixingQueue overflow %d", _mixingQueueSize);
return;
}
MixerChannel *channel = &_mixingQueue[_mixingQueueSize];
channel->ptr = ptr;
channel->end = end;
channel->panL = panL;
channel->panR = panR;
channel->panType = panType;
channel->stereo = stereo;
++_mixingQueueSize;
}
static int gain(int v) {
return v + (v / 8) + (v / 16);
}
template <bool stereo, int panning>
static void mixS16(int16_t *dst, const int16_t *src, int len, int panL, int panR) {
static const int kPanBits = 14; // 0..16384
for (int j = 0; j < len; j += 2, dst += 2) {
const int16_t sampleL = *src++;
const int16_t sampleR = stereo ? *src++ : sampleL;
if (panning != 1) {
dst[0] = CLIP(dst[0] + gain(((panL * sampleL) >> kPanBits)), -32768, 32767);
}
if (panning != 2) {
dst[1] = CLIP(dst[1] + gain(((panR * sampleR) >> kPanBits)), -32768, 32767);
}
}
}
void Mixer::mix(int16_t *buf, int len) {
// stereo s16
assert((len & 1) == 0);
if (_mixingQueueSize == 0) {
return;
}
for (int i = 0; i < _mixingQueueSize; ++i) {
const MixerChannel *channel = &_mixingQueue[i];
const int panL = channel->panL;
const int panR = channel->panR;
if (channel->stereo) {
assert(channel->ptr + len <= channel->end);
switch (channel->panType) {
case 1:
mixS16<true, 1>(buf, channel->ptr, len, panL, panR);
break;
case 2:
mixS16<true, 2>(buf, channel->ptr, len, panL, panR);
break;
default:
mixS16<true, 0>(buf, channel->ptr, len, panL, panR);
break;
}
} else {
assert(channel->ptr + len / 2 <= channel->end);
switch (channel->panType) {
case 1:
mixS16<false, 1>(buf, channel->ptr, len, panL, panR);
break;
case 2:
mixS16<false, 2>(buf, channel->ptr, len, panL, panR);
break;
default:
mixS16<false, 0>(buf, channel->ptr, len, panL, panR);
break;
}
}
}
}