[linux-audio-dev] XAP: Pitch control

David Olofson david at olofson.net
Mon Dec 9 18:46:01 UTC 2002


On Monday 09 December 2002 23.05, Steve Harris wrote:
[...]
> > 	* Getting what you actually *need* for the synth. Is
> > 	  this something that can be narrowed down to one or
> > 	  two formats (frequency and period?), or is it perhaps
> > 	  better left to plugins to perform the linear->"value"
> > 	  conversion? Is there a point in using a host callback
> > 	  to make sure you have linear pitch, if you *still*
> > 	  need to convert again, into something else?
>
> Surely this is another argument for using explicit function calls?

If they can do more than give you the linear pitch. (Which IMHO, you 
should get right in your events in the first place.)

Question is, how many version do we need to make that a useful 
resource to plugins, rather than just another required step along the 
way to the final value?


> > 	* How do you manage scales, if they're not handled by
> > 	  "normal" plugins? Should all hosts have built-in UIs
> > 	  for this? How sophisticated must this be to actually
> > 	  be usable?
>
> I was jsut thinking that there would be a scale hint on a control,
> and the host could manage it. I would image that some hosts would
> only support 12tET in which case they dont need to expose it.

And the way I want it, 12tET-only hosts would have nothing at all 
related to scales - not even two functions that multiply or divide by 
12.0. Plugins don't really have to know anything about this; 
designers only need to answer *one* question:

	"Do you care about notes or actual pitch?"

If "notes"; hint your pitch inputs as "note_pitch". That way, you 
will always get 1.0/tone, whatever the scale is. In 12tET, this "just 
happens" to be exactly the same thing as 12.0/octave.

If "actual pitch"; hint your pitch inputs as "linear_pitch". Now, you 
get 12.0/octave, period. It could have been 1.0, but then someone 
would need to convert back and forth, even in pure 12tET nets. Now, 
you can effectively have your synth just "think" in 12tET, and still 
be capable of playing in any scale. Scale conversion just expresses 
the pitch of tones of the real scale as 12.0/octave - just as it 
would have done with 1.0/octave; just a factor 12.0.


> > Again, that's why 12.0/octave makes sense. It doesn't make a
> > difference technically, but it makes *this* stuff a whole lot
> > easier, since it just "happens" to result in note_pitch and
> > linear_pitch being identical as long as you stick with 12tET.
>
> It makes note steps marinally simpler for 12tET and illogical for
> other tunings. I dont see that as a big win.

It doesn't matter if they seem illogical, since your synth (the kind 
of plugins that would normally want linear_pitch) can effectively 
think in 12tET regardless of which scale it's being used with.

It it cared about the actual *values*, it would have asked for 
note_pitch instead, or as well.


> It also ecourages the
> 12tone way of thinking, which I dont particularly like (can you
> tell ;).

Well, I must agree - but does representing note_pitch a 1.0/octave 
make more sense? :-)

You could do that as well, but it means most control processors, 
sequencers and stuff will have to multiply with 12.0 to get the 
actual note pitch (1.0/tone) - which is pretty illogical as well, 
considering that your output may well be interpretted as 16.0/octave!

Question is basically, do we "deal" with this in synths 
(linear_pitch) or event processors (note_pitch)?


> I prefer APIs to be culturaly neutral.

So do I, but is it worth wasting cycles and add complexity, just to 
prevent synth programmers from even thinking about 12tET?

In fact, I can already see the FAQ:

	"What's this 1.0/octave thing? Where are the *notes*!?"


With 12.0/octave, it's almost the opposite. 12tET brainwashed synth 
coders will go "Huh? How can *my* synth play that weird scale? I 
didn't implement that!" (There's definitely no way ever that will 
happen with VSTis... :-)


> > Why make this a special case, when it's actually just another
> > event processor - on that most people will never need to use?
>
> OK, I can concede that providing scale conversion functions is a
> special case, but so are conversion plugins and you still havent
> explained how your going to implement conversion plugins without
> host provided functions.

Sequencers, most event processors (basic appregiators and the like) 
etc will send note_pitch. Those plugins think in terms of notes, and 
don't care much about what exact pitch each note represents on 
whatever eventually makes the sound. (This is *exactly* the situation 
you're in when working with MIDI.)

Most synths will want linear_pitch. They generally have no reason to 
know or care about the higher level meaning of a note. It's just like 
your voice; (hopefully) it just produces exact pitch you want - and 
whether that's a tone in the 12tET scale is irrelevant, as long as 
that tone is what you're supposed to sing.

With 1.0/note for note_pitch, and 12.0/octave for linear_pitch, we 
have a nice and extremely simple "shortcut" available for all those 
that use only or mostly 12tET:

	linear_pitch = note_pitch;

No converters needed for that - and linear_pitch --> actual 
frequency, peroid, filter coeffs or whatever, is better done by 
custom, optimized code in plugins. The plugin SDK may provide some 
handy macros, inlines or functions to make life easier for plugin 
authors. Maybe there could even be a few host calls for it - but I 
definitely don't think that the API should *force* you to use those 
by design.


Now, say you have a scale converter plugin. It should take note_pitch 
for input, and output linear_pitch. When set to 12tET, it would 
effectively do *nothing*. (As described above.)

If you pick a different scale, the plugin actually starts doing 
something. For example, for 16tET, it would do:

	linear_pitch = note_pitch * (12.0 / 16.0);

That is, "stretch" the scale so you need 16.0 note_pitch units to 
span one octave. Now, all of a sudden, your synths - apparently 
written for 12tET - can play 16tET. They don't know it, or understand 
it, but they're playing the right notes.


BTW, there is another thing I think is rather important to realize. 
If you consider that we're talking about *continous* pitch 
(note_pitch is float!), you don't *really* need to mess with scales 
at all.

If for example, you have a pitch tracker that generates events from a 
vocal track, it doesn't matter what scale you use for mapping actual 
frequency to pitch values. As long as you use the same scale for 
playing those events on a synth, that synth will play *exactly* the 
same pitches.

Now, you may sing 16tET if you like - the events will still be 12tET, 
and despite that, the synth will still play exactly the same tones 
that you sing. Indeed, it will look weird in the note_pitch based 
piano roll view, but it will *work*.


Conclusion:
	With continous pitch, a scale is basically little more than
	a mapping that makes some forms of higher level "logic"
	easier to implement. You *can* play any pitches you like
	without it, but for harmonizers, appregiators, note editors
	and stuff to understand what you're doing, you should
	preferably use a scale that matches what you're actually
	using.


> > Unless your LFO or whatever *understands* scales (ie has it's own
> > built-in scale converter, or can actually "think" in non-linear
> > scales), it would *always* see and generate 12.0/octave.
> >
> > If you don't like 12.0, scale and use whatever you like
> > internally. It doesn't change anything.
>
> But it does mess up the API.

And forcing plugins to request information about what's going on 
outside their input ports, and passing that to non-optional host 
callbacks does not?


> > > What happens when your not using 12 tone? Do you use eg.
> > > 5.0 per octave?
> >
> > Nothing. You still se, and are expected to send, 12.0/octave.
>
> Right, wouldn't it be less confusing to just always use 1.0. Its
> just that one note is 1/(number of notes), rather than 12/(number
> of notes). I really, really dont think that any 12tET based
> programmer is going to be confused by having to add 1/12 to go up
> one note!

No, but event processor coders are going to think that multiplying 
with 12.0 to get actual note_pitch is rather strange when there could 
be any number of tones/octave... ;-)

I simply don't think that using 1.0/octave and 12.0/octave is worth 
the cost of figuring out when to translate, figuring out *how* to 
translate and actually doing it. The actual translation is trivial 
for 12tET, but getting there is not.


> > > Its what CV
> > > synthesisers settled on after a good few years of battling, it
> > > just makes everything simpler.
> >
> > 1.0 Volt is a nice and handy figure. Easy to remember, and it
> > goes well with SI units when you design analog cirquits. There's
> > nothing magical about the figure as such.
>
> Well, it is /the/ unit, and like you said its easy to remember. Its
> much more magical than 12. Conventions are useful things.
>
> Thsi has been a long discussion, so, my position:
>
> 	I do like 1.0 per octave, linear pitch
> 	I dont like "notes" being in the API.

I agree. But how much is that allowed to cost?

I would be happy to see a clean solution for this, but so far, these 
are the only alternatives we have managed come up with:

	1. 1.0/note for note_pitch, 1.0/octave for linear_pitch.
	   Converter plugins required everywhere, even for 12tET.
	   Even 12tET-only hosts have to handle this.

	2. 1.0/octave for linear_pitch, no note_pitch (?).
	   Host calls required for conversions. Plugins have to
	   find out what scales senders are using, or who is
	   sending what. How does this work if multiple senders
	   send to the same Channel? 

	3. 1.0/note for note_pitch, 12.0/octave for linear_pitch,
	   No conversion needed for 12tET. Converter plugins can
	   be used when other scales are desired. There cannot
	   be 12tET-only hosts, since scales are not a host side
	   matter.


More ideas, anyone?


//David Olofson - Programmer, Composer, Open Source Advocate

.- The Return of Audiality! --------------------------------.
| Free/Open Source Audio Engine for use in Games or Studio. |
| RT and off-line synth. Scripting. Sample accurate timing. |
`---------------------------> http://olofson.net/audiality -'
.- M A I A -------------------------------------------------.
|    The Multimedia Application Integration Architecture    |
`----------------------------> http://www.linuxdj.com/maia -'
   --- http://olofson.net --- http://www.reologica.se ---



More information about the Linux-audio-dev mailing list