pitchEvent keys image in Event helpfile

Hi all,

It occurred to me today that the help file image currently used to represent pitchEvent keys, located at the bottom of the Event help file, is not quite correct. It currently looks like this:

The detune parameter is added to freq to produce detunedFreq, but this image puts detune on the tier just beneath freq.

Event.partialEvents.pitchEvent[\freq].postcs;

Event.partialEvents.pitchEvent[\detunedFreq].postcs;

So, I think a more accurate version of the image would look something like this?

Eli

I’m not sure there’s a good way – Event defines a function detunedFreq but puts the result into the freq key.

e = (degree: 3).play;
e[\detunedFreq]
-> a Function

So maybe it’s misleading to suggest that there is a detunedFreq result.

I don’t have a good idea how to fix it just now.

hjh

In that case, I think I’m misunderstanding the underlying process. If there’s a detunedFreq function that calculates the sum of freq and detune, then why does Event put the result (back) into the freq key?

For example, I had always assumed that the following two Events would produce the same pitch when played — now I hear that they do not. Is there something I’m not understanding? What is the point of the detunedFreq key/function?

s.boot;

(
SynthDef(\a, {
	arg detunedFreq=300;
	var sig;
	sig = SinOsc.ar(detunedFreq)!2;
	sig = sig * XLine.kr(1,0.001,1,doneAction:2) * 0.2!2;
	Out.ar(0, sig);
}).add;
)

x = (instrument: \a, freq: 500, detune: 100).play;
x.freq;

x = (instrument: \a, freq: 600, detune:0).play;
x.freq;

Ah, I think I see it, at least partially.

Event.eventTypes[\note].postcs;\

The \note Event stores the value of ~detunedFreq in a local variabled named ‘freqs’, which is then passed to the ~freq key in the new, resulting Event created from the ‘play’ message.

…I think I understand now why the two examples in my previous post sound different. They’ll sound the same if in the SynthDef I replace detunedFreq with freq…but I still don’t really understand the purpose of the ~detunedFreq Function.

I think it’s just naming (and naming is always interesting!).

detune is in Hertz, it’s what you set to tune to A416 instead of A440.

(midinote: 69, detune: -24).play

This looks nice! It sets freq to 416, and freq is the control name at the synthesiser.

But if you work in Hertz then you set freq directly.

(freq: 416).play

This looks nice too! It does the same thing.

So there needs to be another step (and name) to apply detune to freq.

Hence detunedFreq, which calculates freq using freq as an input.

If you set both freq and detune it works, but you go in a bit of a circle.

(freq: 440, detune: -24).play

Ps. Of course, additive detune is not for everyone, and a less quixotic person might rather type:

(midinote:69, ctranspose: -0.971).play

Not exactly.

Midinote 69 with detune -24 will indeed produce A416.

But D, at A416 and assuming 12ET, should be 416 * (2 ** (-7/12)) = 277.6467 but setting detune to -24 would produce (440 * (2 ** (-7/12))) - 24 = 269.6648 which is not the same as tuning to 416. (I suspect, rdd, that you know that :wink: but it might confuse other readers so I thought it best to clarify.)

The convention has always been that the SynthDef defines the frequency to play as freq and the client supplies the sounding frequency to freq.

Tbh I don’t remember why detunedFreq was added. Rohan is correct that it’s an additive (inharmonic) detuner, but I don’t recall the context under which this was initially discussed.

In any case, I’m not even sure that midinote in a SynthDef is reliable, when played by an event… it might work because of asControlInput or it might not work.

hjh

Thanks both, this is making sense. I did catch this potential misunderstanding regarding the combined use of detune and midinote — that detune is a linear shift in Hz, which distorts the frequency of a midinote sequence nonlinearly (an example just for the sake of clarity):

s.boot;

(
Pbind(
	\dur, 0.3,
	\sustain, 0.2,
	\midinote, Pseq([69,71,73,74,76],inf),
	\detune, -24 //values further from 0 exaggerate the nonlinearity
).play;
)

(
Pbind(
	\dur, 0.3,
	\sustain, 0.2,
	\midinote, Pseq([69,71,73,74,76],inf),
	\ctranspose, -0.971 //"normal" equal-tempered sound
).play;
)

My understanding now is that ~detunedFreq is really just an inner mechanism of Event, and that freq is the more central container. My confusion did originate in these naming conventions.

So, from a visual perspective, I agree that it isn’t appropriate to include a fifth detunedFreq column in the image, which would probably just confuse the reader. But, I do think it would make much more sense to move detune from the third column to the fourth column, because it does not “work” with MIDI note numbers in the expected way. Instead, detune is a parameter which is mathematically more closely associated with freq, both conceptually, and literally (as implemented in the ~detunedFreq function as #{ ~freq.value + ~detune })

Would this, then, be more accurate than the current image?

I think the chart is Ok because detune is indeed used to calculate freq.

(In a sense it’s a cyclic graph, there’s an arrow from freq to freq.)

It’s nice to have a detune that works for both freq and midinote.

The additive form’s a bit eccentric though.

harmonic is the traditional multiplicative detune, but it’s before freq, and the name suggests other uses.

(midinote: 69, harmonic: 416/440).play is somewhat nice.

(freq: 440, harmonic: 416/440).play is confusing.

ratio is a nice name too, perhaps it could be detunedFreq = (freq + detune) * ratio.

Ps. Graph drawing, c.f. http://www.graphviz.org/

digraph {
 {degree scale mtranspose} -> note
 {note root octave gtranspose stepsPerOctave octaveRatio} -> midinote
 {midinote ctranspose harmonic} -> freq
 {freq detune} -> freq
}

Here’s a funny one, illustrating the risk of relying on automatic function evaluation:

(
SynthDef(\test, { |midinote = 60, detunedFreq = 261|
	var trig = Impulse.kr(0);
	[midinote, detunedFreq].poll(trig);
	FreeSelf.kr(trig <= 0);
}).add;
)

(instrument: \test, detune: -24, note: 9).play;

UGen Array [0]: 69
UGen Array [1]: 392

But 440 - 392 = 48, not 24.

“69” and “392” are produced because the SynthDef’s msgFunc embeds the midinote and detunedFreq functions into the argument list, and then asOSCArgArray calls asControlInput on the functions, which evaluates them.

But detune has already modified ~freq so then detune gets doubly applied.

hjh

calling Edward Tufte…

I don’t see any useful information being conveyed by the increasing size of the boxes containing degree, note, midinote and freq, nor exacltly what’s meant by the wide arrows!

Degree         Note
_____   --->   ____
scale      |  root
mtranspose |  octave
           |  gtranspose

etc maybe clearer…

By convention in patterns only out, freq, amp, pan (other?) are synth input names and all pitch related event keys are means to calculate freq. There are indeed some inconsistencies if keys are given the same importance. For example, from freq is not possible to obtain midinote, the key will be empty, or degree, there is implicit information needed, and so on with different combinations. The code logic is only one way and freq would be the root.