Process a single bank.
50 Size actuallyRendered = 0;
52 manager.forEachVoice([&](Voice& v,
Size vi) {
53 if (v.bank != bank.id) {
return true; }
54 if (!v.spatialized) {
return true; }
56 if (!spatial.hasEmitter(v.emitter)) {
57 VAE_DEBUG(
"Spatial voice is missing emitter")
61 auto& source = bank.sources[v.source];
62 auto& signal = source.signal;
64 const auto signalLength = signal.size();
66 if (signalLength == 0) {
return false; }
68 v.time = v.time % signalLength;
70 if (signal.sampleRate != sampleRate) {
75 auto& emitter = spatial.getEmitter(v.emitter);
76 auto& target = bank.mixers[v.mixer].buffer;
77 const Sample gain = v.gain * source.gain;
78 auto& l = spatial.getListeners()[v.listener];
80 Real distanceAttenuated;
81 Vec3 relativeDirection;
87 glm::mat4x4 lookAt = glm::lookAt(l.position, l.position + l.front, l.up);
89 relativeDirection = (lookAt * glm::vec4(emitter.position, 1.f));
92 const
Real distance = std::
max(glm::length(relativeDirection), 0.1f);
93 relativeDirection /= distance;
96 distanceAttenuated = distance;
97 distanceAttenuated =
std::max(distanceAttenuated,
Real(1));
98 distanceAttenuated =
Real(1) / distanceAttenuated;
100 distanceAttenuated = 1.0;
102 distanceAttenuated *= gain;
110 target.setValidSize(frames);
119 bool finished =
false;
123 auto& fd = manager.getVoiceFilter(vi);
127 fd.highpassScratch[0] = 0;
128 fd.lowpassScratch[0] = signal[0][v.time];
138 SampleIndex(std::floor((signalLength - v.time) / speed - fd.timeFract))
140 finished = remaining != frames;
147 position = v.time + (s * speed) + fd.timeFract;
148 const Real lastPosition = std::floor(position);
149 const Size lastIndex = (
Size) lastPosition;
150 const Size nextIndex = (
Size) lastPosition + 1;
152 Real mix = position - lastPosition;
156 const Sample last = signal[0][lastIndex % signalLength];
157 const Sample next = signal[0][nextIndex % signalLength];
159 const Sample in = (last +
mix * (next - last)) * gain;
163 const Sample lpd = in + fd.lowpass * (fd.lowpassScratch[0] - in);
164 fd.lowpassScratch[0] = lpd;
166 const Sample hps = fd.highpassScratch[0];
167 const Sample hpd = hps + fd.highpass * (in - hps);
168 fd.highpassScratch[0] = hpd;
174 fd.timeFract = position - v.time;
185 v.time = (v.time + frames);
195 in = signal[0] + v.time;
196 finished = remaining != frames;
206 Size closestIndex = HRTFUtil::closest(
mHRTF, relativeDirection);
208 if (closestIndex == ~
Size(0)) {
return true; }
213 hrtfVoice.convolutionIndex = 0;
214 hrtfVoice.convolutionBuffer.set();
219 hrtfVoice, remaining, target, in, distanceAttenuated
225 auto& lastPan = manager.getVoicePan(vi);
227 auto& currentVolumes = currentPan.volumes;
228 auto& lastVolumes = lastPan.volumes;
234 const auto pan = [&](const auto& panner) {
238 relativeDirection, currentVolumes,
239 distanceAttenuated, emitter.spread
244 for (
Size c = 0; c < channels; c++) {
245 lastVolumes[c] = currentVolumes[c];
251 const Sample sample = in[s];
254 for (
Size c = 0; c < channels; c++) {
255 target[c][s] += sample * (lastVolumes[c] + t * (currentVolumes[c] - lastVolumes[c]));
261 switch (l.configuration) {
270 lastPan = std::move(currentPan);
274 emitter.autoplaying =
false;
279 return actuallyRendered;
Size mix(VoiceManger &manager, Bank &bank, SpatialManager &spatial, SampleIndex frames, Size sampleRate)
Process a single bank.
T min(const T &v1, const T &v2)
T max(const T &v1, const T &v2)
constexpr Sample MinVolume
Minimum volume before sounds will skip rendering.
constexpr unsigned char MaxChannels
Maximum channel count used to pre allocate buffers.
AudioBuffer::Size SampleIndex
unsigned int Size
How the elements are addressed in the heapbuffer.
float Sample
Default sample types used where ever possible, changing this means the engine needs to be recompiled,...
HeapBuffer< Position > positions
static void apply(HRTF::Position &hrtf, VoiceHRTF &hrtfVoice, SampleIndex frames, ScratchBuffer &target, const Sample *in, Sample distanceAttenuated)
Applies simple time domain convolution.
static const SPCAPConfig< 2 > StereroSPCAP
static const SPCAPConfig< 1 > MonoSPCAP
TODO there's probably a smart way to make this all constexpr.
static const SPCAPConfig< 4 > QuadSPCAP
static const SPCAPConfig< 5 > SuroundSPCAP
static const SPCAPConfig< 2 > HeadphoneSPCAP
#define VAE_DEBUG(msg,...)
#define VAE_ASSERT(condition)