Do you usually smooth Pitch?

DSP, Plugin and Host development discussion.
RELATED
PRODUCTS

Post

aciddose wrote:The reason you can't hear a click is because the click is inherently filtered on its own.
I bet due to some "magic" by DSP that I don't know, being a noob :)
But if the click will be inherently filter out, that's nice, I can avoid to smooth pitch-er multiplying ;)

Now, the question "steppy" pitch...
quikquak wrote:You're not instantly moving the pitch wheel though, there's always a physical movement and presumably some musicality involved.
FL Studio has a variable buffer size by default, all the way down to 1 sample. Other hosts may use much larger blocks, and not update the pitch-wheel MIDI as fast as you'd expect. That's all I'm suggesting.
Yes, probably using DAW with higher buffer and/or that won't refresh at sample resolution, a player that do pitch bend (musically) will got steppy pitch change.

But its also true that once one would permit this steppy pitch effect, it can't if I smooth it.
I can't know if the hard "ramp" is due to the low buffer or because user intentionally want to modulate it that way.

I can't have both ways, I guess, so its a matter of design.
I tried Sytrus now, with violent pitch (bend) change, and I hear it very steppy. I think that also it doesn't smooth pitch. Probably I'll take this way :wink:

Post

A little bit, just because my singer couldn't reliably hit a pitch if somebody aimed his voice for him. Come to think of it, I'm much the same way.

EDIT: Oops, didn't read the OP or, well, anything in this topic well enough. I'll keep the comment because it's funny.
Wait... loot _then_ burn? D'oh!

Post

Nowhk wrote:
aciddose wrote:The reason you can't hear a click is because the click is inherently filtered on its own.
I bet due to some "magic" by DSP that I don't know, being a noob :)
But if the click will be inherently filter out, that's nice, I can avoid to smooth pitch-er multiplying ;)

Now, the question "steppy" pitch...
quikquak wrote:You're not instantly moving the pitch wheel though, there's always a physical movement and presumably some musicality involved.
FL Studio has a variable buffer size by default, all the way down to 1 sample. Other hosts may use much larger blocks, and not update the pitch-wheel MIDI as fast as you'd expect. That's all I'm suggesting.
Yes, probably using DAW with higher buffer and/or that won't refresh at sample resolution, a player that do pitch bend (musically) will got steppy pitch change.

But its also true that once one would permit this steppy pitch effect, it can't if I smooth it.
I can't know if the hard "ramp" is due to the low buffer or because user intentionally want to modulate it that way.

I can't have both ways, I guess, so its a matter of design.
I tried Sytrus now, with violent pitch (bend) change, and I hear it very steppy. I think that also it doesn't smooth pitch. Probably I'll take this way :wink:
So you're going to copy how you think another synth works, because it seems to fit with own judgement?
Cool.
Try it in Reaper, which was still free to try when I last looked. Or any other DAW.

Post

quikquak wrote:So you're going to copy how you think another synth works, because it seems to fit with own judgement?
Cool.
Lol :D Yes, in fact it sounds like you said.
I'm in front of a decision. There isn't right or wrong, so what's wrong to entrust on solid product of the past? In both case I have a disadvantage for what I see.
quikquak wrote:Try it in Reaper, which was still free to try when I last looked. Or any other DAW.
Yeah, I already tried in Ableton, which is common to use fixed buffer (as for SAVIHost).
But I can do the same on FL Studio: Wrapper->Processing->Use fixed size buffers.

@256:

- Sytrus not clicking, but stepping. If I want it smooth? I can't...
- Serum not stepping, it smooth pitch (pitch bend kind of). If I want it steppy? I can't...

So really its a matter of choice I think.

Post

User choice?

Post

Since the input is per-sample accurate already it is up to the user to filter the pitch-bend events on the host side. Your plug-in can just respond to them as pure MIDI events on a per-sample basis as usual and if the user wants to sent pulses of +1, -1, +1, -1 every whole note that is their decision.

Any sort of filter will cause more problems than it will solve. In the case of low resolution MIDI controllers with poor pitch-bend control that is really just an unfortunate reality and it isn't practical to attempt to solve all of the world's problems with DSP algorithms.
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

Just do what mystran wrote, and on top of that make it configurable (because you cannot possibly come up with a smoothing algorithm that works optimally in all cases)

Richard
Synapse Audio Software - www.synapse-audio.com

Post

quikquak wrote:User choice?
Well, yes, this could be the better case. I'm just focusing on somethings more important right now. So for this I'll give 1 option.
aciddose wrote:Since the input is per-sample accurate already it is up to the user to filter the pitch-bend events on the host side
That's really depends. Theoretically it should be per-sample accurate. But if some DAW sends 1 MIDI message "per buffer" about pitch bend, this fail :wink: And I've seen this.
mystran wrote:I actually do my parameter smoothing with linear interpolation with ramp time adjusted depending on the time between successive automation (or MIDI CC, etc) events.
I'm curious: once you smooth all parameter (which are normalized values I believe), do you process them all or do you process them at control rate?

Let say you want to process gain, on a 256 buffer size: you smooth the Gain Parameter along 256 samples. But do you process all of them? Because "wrap" function takes CPU.

For example, gain param 0.0 to 1.0, I first convert to Decibel range I want to operate with linear interpolation:

Code: Select all

double db = CalculateLinearInterpolation(0.0, 1.0, -24.0, 24.0, normalizedGain);

double CalculateLinearInterpolation(double a0, double a1, double b0, double b1, double aX) {
	return b0 + (b1 - b0) * (aX - a0) / (a1 - a0);
}
And than I switch from DB to linear:

Code: Select all

double gain = DecibelToLinear(db);

double DecibelToLinear(double decibel) {
	return pow(10, decibel / 20.0);
}
Buit if you have multiple voices running (i.e. 32), processing this wrap function for each sample on each voice require CPU.

I usually first smooth all parameters, than process/wrap at control rate (i.e. 1/8, so each 32 sample within a buffer of 256).
Is it a good advice? Or can you give to me somethings "smart"?

Post

Nowhk wrote:
aciddose wrote:Since the input is per-sample accurate already it is up to the user to filter the pitch-bend events on the host side
That's really depends. Theoretically it should be per-sample accurate. But if some DAW sends 1 MIDI message "per buffer" about pitch bend, this fail :wink: And I've seen this.
It isn't up to the host. The host can put whatever it wants in the events buffer. The events buffer can then be processed by intermediaries. For example you could add a MIDI echo, or a MIDI filter that low-pass filters your pitch bend, or you could generate the pitch bend with a LFO or envelope follower plug-in.

The event buffer is then passed to your plug-in and it might contain totally arbitrary events which have per-sample accuracy.

This is defined by the interface, not by the host. If the host only places one pitch bend event into the buffer per block, well, that's an extremely stupid and poorly written host. How does the host quantize events from MIDI input or from its internal sequencer? How does it deal with the resulting aliasing and missed min/max events?
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

Nowhk wrote: Let say you want to process gain, on a 256 buffer size: you smooth the Gain Parameter along 256 samples. But do you process all of them? Because "wrap" function takes CPU.
When you receive an automation event (or MIDI CC) you want to calculate the linear segment to smooth it out (from the current interpolated value if there was already one active). I suggest just building a linear polynomial a+b*t with an upper bound on t, so you can use random access to calculate it. Then you know that if the time t is already past the upper bound of the previously setup segment at the beginning of the block it's constant all the way. Then in your DSP code you can check if a parameter needs smoothing and either process it per sample (or per control rate sample, whatever) or just treat it as constant (you need separate code paths, but it's worth it).

The idea here is that the number of parameters that need smoothing is typically a lot larger than the number of parameters that are actually receiving automation, so you can save a lot of CPU by identifying exactly which parameters need smoothing right now and just process those.

Post

... and the secret to that is that since we know the maximum number of parameters that "could" in worst-case be filtered:

Code: Select all

template <int max_elements>
parameter_filter
{
 operator()()
 {
  for (int i = 0; i < active_elements; i++) {
    const bool finished = element[i]();
    if (finished) {
      active_elements--;
      if (i < active_elements) {
        element[i] = element[active_elements];
        i--;
      }
    }
  }
 }

...
array_t<element_t, max_elements> element;
}
... ugh why did I just type that by hand with spaces.

Anyway you can see this is way more optimal than in-lining 50 different filters with "if (filter.is_active()) { ..." since it only needs a simple for statement and a fixed length (no need for heap allocation or dereferencing) array.
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

mystran wrote:The idea here is that the number of parameters that need smoothing is typically a lot larger than the number of parameters that are actually receiving automation, so you can save a lot of CPU by identifying exactly which parameters need smoothing right now and just process those.
Of course, I already have a sort of "prev/current" check on every param.

If different values, do process, wrap and store new value; else use the previously stored wrapped value.

But if you have some parameters that are changing constantly (by DAW lfo automations for example), the value is changed at every sample. That's why "wrap the function" on every sample could become heavy.

So I just calculate the wrap function every N samples (control rate 1/8 in my case). Is it correct in your opinion? Smooth and Process at control rate (i.e. down sampling and apply parameter value every N samples)?

Post Reply

Return to “DSP and Plugin Development”