Optimal way to read vector _4 params/inputs?

hi there,

trying to use simd and read params/inputs for x4 osc, on 16 voices. here’s my actual code for a single param (freq offset):

// freq offset
	const rack::simd::float_4 v0 = 0.0f;
	const rack::simd::float_4 v1 = 1.0f;
	const rack::simd::float_4 v10 = 10.0f;
	const rack::simd::float_4 vMinFreq = kMinFreqOffset;
	const rack::simd::float_4 vMaxFreq = kMaxFreqOffset;
	rack::simd::float_4 paramKnob;
	for (int oscIndex = 0; oscIndex < kNumOscs; oscIndex++) {
		paramKnob[oscIndex] = params[FREQ_OFFSET_PARAM + oscIndex].getValue();

	for (int voiceIndex = 0; voiceIndex < kMaxNumVoices; voiceIndex++) {
		rack::simd::float_4 paramInput;
		for (int oscIndex = 0; oscIndex < kNumOscs; oscIndex++) {
			paramInput[oscIndex] = inputs[FREQ_OFFSET_INPUT + oscIndex].getPolyVoltage(voiceIndex);

		rack::simd::float_4 value = paramKnob + paramInput / v10;
		value = clamp(value, v0, v1);
		value = rescale(value, v0, v1, vMinFreq, vMaxFreq);

		mFreqOffset[voiceIndex] = value;

that’s the only code i have on process(), but it takes +1% of CPU (for a “single” pair param/input). this means that for 6-7 params, its +7 or more on CPU (in the extreme case, of course).

do you see any improvements (expect putting a control-rate settings, which id like to avoid)? i think the main problem is this:

paramInput[oscIndex] = inputs[FREQ_OFFSET_INPUT + oscIndex].getPolyVoltage(voiceIndex);

it will have lots of cache miss i guess; not sure how to process them consecutively and add them on _4 variable for params.

note: i need mod per voice, of course :slight_smile:


Two thoughts. First - why does your loop go up to kMaxNumVoices? If you only are using one channel, why process 16?

Second - you may prefer not to, but all my modules process CV at 1/4 SR, with no user choice. Not ideal, but works for me.

Oh, and usually it’s the processing of the CV that takes all the CV, not reading the port. Are you sure it’s not your clamping and re-scaling that’s taking the time? And if this is a VCO, don’t you need an exponential function somewhere?

Sound like you are probably too advanced to get much out of this, but this ancient paper of mine is… a classic? SquinkyVCV/efficient-plugins.md at main · squinkylabs/SquinkyVCV · GitHub

1 Like

i’m using 16 channels. Its 4xOsc, x16 voices. in fact in the bottom you can see it:

mFreqOffset[voiceIndex] = value;

which is a

rack::simd::float_4 mFreqOffset[kMaxNumVoices]

So it always uses 16 channels? Not like most oscillators that set their number of voices to the number of channels on the V/Oct input? ok.

that could be piloted by v/oct input yes, but for what im working on, all 16 voices will be used constantly. if you can’t got it for now, as i said, just consider it as the “worst case” :slight_smile:

to start with, it doesn’t look like you are breaking your voices down into groups of 4 for the simd to work on. (look at the index in getPolyVolatage)

pretty sure there is simd:clamp function too

There certainly is!

i’m breaking a single voice down to 4 osc group:


than add each 4x osc group to param_4.

and yes, the clamp/rescale function used above recall each rack::simd::clamp and rack::simd::rescale.