This is the kind of question that seems to come up most often around patterns:
// Why is my kick playing at the wrong frequency?
(
SynthDef(\kick, {
var env = Env.perc(0.01, 0.6).ar(doneAction: 2);
var sig = SinOsc.ar(\freq.kr(60) * XLine.ar(6, 1, 0.05));
sig = sig * env * \amp.kr(0.3);
Out.ar(0, sig ! 2);
}).add;
)
Pbind(\instrument, \kick).trace(\freq).play; // plays middle C
So the issue is that many new users are unaware of the default parent Event and what exactly happens behind the scenes when you .play an Event or Pbind.
One workaround is to use a custom parent (or proto) Event:
(
// ignore only pitch-related keys:
var partials = Event.partialEvents;
~proto = ().putAll(
// partials.pitchEvent, // uncomment to include default pitch keys
partials.ampEvent,
partials.durEvent,
partials.bufferEvent,
partials.serverEvent,
partials.playerEvent,
partials.midiEvent
)
.parent_(()); // must do this to override defaultParentEvent??
)
// usage examples:
(instrument: \kick).parent_(~proto).play;
Pbind(\instrument, \kick).play(protoEvent: ~proto);
But that’s a lot to ask of beginners, and I think there are simpler solutions. For example, we could offer them a new event type that uses default controls unless the user specifies otherwise:
(
Event.addEventType(\noteDefault, {arg server;
var synthLib, desc, defaults;
synthLib = ~synthLib ? SynthDescLib.global;
desc = synthLib.at(~instrument.asDefName);
defaults = desc.controlDict.collect(_.defaultValue);
currentEnvironment.proto = defaults;
~eventTypes[\note].value(server);
});
)
// usage examples:
(instrument: \kick, type: \noteDefault).play;
Pbind(\instrument, \kick, \type, \noteDefault).play;
Again, somewhat complicated for a new user to write a new event type, but if we include that event type in the class library or a Quark, or just in the documentation, it is pretty easy to understand the usage.
Another option might be to include something like the following code at the top of the \note
event type function:
if(~useDefaultControls ? false){
var synthLib, desc, defaults;
synthLib = ~synthLib ? SynthDescLib.global;
desc = synthLib.at(~instrument.asDefName);
defaults = desc.controlDict.collect(_.defaultValue);
currentEnvironment.proto = defaults;
};
Then the user could specify when they want to use default controls like this:
(instrument: \kick, useDefaultControls: true).play;
Pbind(\instrument, \kick, \useDefaultControls, true).play;
Thoughts? Other ideas?