@@ -146,15 +146,18 @@ namespace vae { namespace core {
146
146
// Linear interpolation between two samples
147
147
position = v.time + (s * speed) + fd.timeFract ;
148
148
const Real lastPosition = std::floor (position);
149
- const Size lastIndex = (Size ) lastPosition;
150
- const Size nextIndex = (Size ) lastPosition + 1 ;
149
+
150
+ Size lastIndex = (Size ) lastPosition;
151
+ Size nextIndex = (Size ) lastIndex + 1 ;
152
+ // TODO this kills vectorization
153
+ if (signalLength <= lastIndex) { lastIndex = 0 ; }
154
+ if (signalLength <= nextIndex) { nextIndex = 0 ; }
151
155
152
156
Real mix = position - lastPosition;
153
- // mix = 0.5 * (1.0 - cos((mix) * 3.1416)); // cosine interpolation, introduces new harmonics somehow
157
+ // mix = 0.5 * (1.0 - cos((mix) * 3.1416)); // cosine interpolation, introduces new harmonics, not really better than linear
154
158
155
- // TODO 30% of the time in here is spent on the modulo
156
- const Sample last = signal [0 ][lastIndex % signalLength];
157
- const Sample next = signal [0 ][nextIndex % signalLength];
159
+ const Sample last = signal [0 ][lastIndex];
160
+ const Sample next = signal [0 ][nextIndex];
158
161
// linear resampling, sounds alright enough
159
162
const Sample in = (last + mix * (next - last)) * gain;
160
163
@@ -177,15 +180,19 @@ namespace vae { namespace core {
177
180
} else {
178
181
VAE_PROFILER_SCOPE_NAMED (" Non filtered Voice" )
179
182
if (v.loop ) {
183
+ VAE_PROFILER_SCOPE_NAMED (" Loop" )
180
184
// put the looped signal in scratch buffer eventhough we're not filtering
181
185
// so panning doesn't need to worry about looping
182
- for (SampleIndex s = 0 ; s < frames; s++) {
183
- mScratchBuffer [0 ][s] = signal [0 ][(v.time + s) % signalLength];
186
+ for (SampleIndex s = 0 , i = v.time ; s < frames; s++, i++) {
187
+ // reached the end so reset index, this is slighlty faster than modulo
188
+ if (signalLength <= i) { i = 0 ; }
189
+ mScratchBuffer [0 ][s] = signal [0 ][i];
184
190
}
185
191
v.time = (v.time + frames); // progress the time
186
192
in = mScratchBuffer [0 ]; // set buffer for panning
187
193
finished = false ; // never stop the voice
188
194
} else {
195
+ VAE_PROFILER_SCOPE_NAMED (" No Loop" )
189
196
// Not filtering or looping
190
197
// Means we can use the original signal buffer but need to
191
198
// set the remaining samples so we don't run over the signal end
@@ -233,7 +240,7 @@ namespace vae { namespace core {
233
240
*/
234
241
const auto pan = [&](const auto & panner) {
235
242
// This is actually constexpr but not according to clangd
236
- constexpr Size channels = std::min ( Size (StaticConfig::MaxChannels), panner. speakers );
243
+ constexpr Size channels = Size (StaticConfig::MaxChannels);
237
244
panner.pan (
238
245
relativeDirection, currentVolumes,
239
246
distanceAttenuated, emitter.spread
@@ -245,14 +252,15 @@ namespace vae { namespace core {
245
252
lastVolumes[c] = currentVolumes[c];
246
253
}
247
254
}
248
-
255
+ VAE_PROFILER_SCOPE_NAMED ( " Apply SPCAP " )
249
256
Sample t = 0 ;
250
257
for (SampleIndex s = 0 ; s < remaining; s++) {
251
258
const Sample sample = in[s];
252
259
// lerp between last and current channel volumes
253
260
// Not correct in terms of power convservation, but easy and efficient
254
261
for (Size c = 0 ; c < channels; c++) {
255
- target[c][s] += sample * (lastVolumes[c] + t * (currentVolumes[c] - lastVolumes[c]));
262
+ // target[c][s] += sample * (lastVolumes[c] + t * (currentVolumes[c] - lastVolumes[c]));
263
+ target[c][s] += sample * currentVolumes[c];
256
264
}
257
265
t += Sample (1 ) / Sample (frames);
258
266
}
0 commit comments