19#include "processing/vector_rendering_function.h"
20#include "util/fixedpoint.h"
21#include "util/waves.h"
25[[gnu::always_inline]]
static inline void
26renderOscSync(
auto storageFunction,
auto extraInstructionsForCrossoverSampleRedo,
28 uint32_t& phase, uint32_t phaseIncrement, uint32_t& resetterPhase, uint32_t resetterPhaseIncrement,
29 int32_t resetterDivideByPhaseIncrement, uint32_t retriggerPhase, int32_t& numSamplesThisOscSyncSession,
30 int32_t*& bufferStartThisSync) {
32 bool renderedASyncFromItsStartYet =
false;
33 int32_t crossoverSampleBeforeSync;
34 int32_t fadeBetweenSyncs;
39 uint32_t samplesIncludingNextCrossoverSample = 1;
41 uint32_t distanceTilNextCrossoverSample = -resetterPhase - (resetterPhaseIncrement >> 1);
42 samplesIncludingNextCrossoverSample += (uint32_t)(distanceTilNextCrossoverSample - 1) / resetterPhaseIncrement;
43 bool shouldBeginNextSyncAfter = (numSamplesThisOscSyncSession >= samplesIncludingNextCrossoverSample);
44 int32_t numSamplesThisSyncRender = shouldBeginNextSyncAfter
45 ? samplesIncludingNextCrossoverSample
46 : numSamplesThisOscSyncSession;
48 int32_t
const*
const bufferEndThisSyncRender = bufferStartThisSync + numSamplesThisSyncRender;
49 uint32_t phaseTemp = phase;
50 int32_t* __restrict__ writePos = bufferStartThisSync;
52 storageFunction(bufferEndThisSyncRender, phaseTemp, writePos);
55 if (renderedASyncFromItsStartYet) {
56 int32_t average = (*bufferStartThisSync >> 1) + (crossoverSampleBeforeSync >> 1);
57 int32_t halfDifference = (*bufferStartThisSync >> 1) - (crossoverSampleBeforeSync >> 1);
58 int32_t sineValue = getSine(fadeBetweenSyncs >> 1);
59 *bufferStartThisSync = average + (q31_mult(halfDifference, sineValue));
62 if (shouldBeginNextSyncAfter) {
65 bufferStartThisSync += samplesIncludingNextCrossoverSample - 1;
66 crossoverSampleBeforeSync = *bufferStartThisSync;
67 numSamplesThisOscSyncSession -= samplesIncludingNextCrossoverSample - 1;
68 extraInstructionsForCrossoverSampleRedo(samplesIncludingNextCrossoverSample);
71 resetterPhase += resetterPhaseIncrement * (samplesIncludingNextCrossoverSample - renderedASyncFromItsStartYet);
75 fadeBetweenSyncs = multiply_32x32_rshift32((int32_t)resetterPhase, resetterDivideByPhaseIncrement)
77 phase = multiply_32x32_rshift32(fadeBetweenSyncs, phaseIncrement) + retriggerPhase;
79 phase -= phaseIncrement;
80 renderedASyncFromItsStartYet =
true;
81 samplesIncludingNextCrossoverSample = 2;
83 goto startRenderingASync;
88 phase += phaseIncrement * numSamplesThisSyncRender;
91auto renderWavetableLoop(
auto bufferStartThisSync,
auto firstCycleNumber,
auto bandHere,
auto phaseIncrement,
92 auto crossCycleStrength2,
auto crossCycleStrength2Increment,
auto kernel) {
93 return [&](int32_t
const*
const bufferEndThisSyncRender, uint32_t phaseTemp, int32_t* __restrict__ writePos) {
94 doRenderingLoop(bufferStartThisSync, bufferEndThisSyncRender, firstCycleNumber, bandHere, phaseTemp,
95 phaseIncrement, crossCycleStrength2, crossCycleStrength2Increment, kernel);
100inline Argon<int32_t> createAmplitudeVector(int32_t amplitude, int32_t amplitude_increment) {
102 auto amplitudeVector = Argon<int32_t>{amplitude}.MultiplyAdd(amplitude_increment, int32x4_t{1, 2, 3, 4});
105 return amplitudeVector >> 1;