MIDI triggered set of arguments

I want to assign a unique set of arguments including frequency and an output channel to each key of of MIDI keyboard. I’m familiar with Elie Fieldsteel’s MIDI tutorials/lectures for exposing note number and velocity. I just need help with the syntax of assigning a note number [nn], say for example #60, with a pre-defined frequency of 211 Hz, at Channel 3, so that each time nn #60 is pressed, an oscillator with a fundamental frequency of 211 Hz is produced out of Channel 3? And so on for each key. I think it should involve a table or an array (?).

I don’t quite understand what you are after. Is an ‘output channel’ a Bus?

I think this does what you want? I am not sure what Channel 3 is though? Do you mean a speaker, or a virtual bus?

(
s.waitForBoot {
	SynthDef(\test, {
		var sine = SinOsc.ar(\freq.kr);
		var env = EnvGen.ar(Env.perc, doneAction: 2);
		Out.ar(\out.kr, sine * env)
	}).add;
	
	s.sync;
	
	~outputBus = Bus.audio(s, 1);

	~freqOfKeys = (0..127).linlin(0, 127, 50, 2000);
	
	MIDIdef.noteOn(\test, {
		|...msg|
		var notenum = msg[1];
		Synth(\test, [\freq, ~freqOfKeys[notenum], \out, ~outputBus]);
	});
}
)

~outputBus.scope
MIDIIn.doNoteOnAction(1, 1, 12, 64);

Thanks jordan for your reply. Here’s some code that is probably not too pretty, but does what I was looking for. I would make use the following code with MIDIdef.noteOn() like you did to get notenum (nn):

(
var nn, freq, chan, temp, aa;
temp = [50, 55, 60, 63, 65, 67];
aa = Array.new[3];
nn = temp.choose;
aa = case
    { nn == 50 } { [nn,freq,chan].put(1,100).put(2,1) }'
    { nn == 55 } { [nn,freq,chan].put(1,200).put(2,2) }'
    { nn == 60 } { [nn,freq,chan].put(1,300).put(2,3) }'
    { nn == 63 } { [nn,freq,chan].put(1,400).put(2,4) }'
    { nn == 65 } { [nn,freq,chan].put(1,500).put(2,5) }'
    { nn == 67 } { [nn,freq,chan].put(1,600).put(2,6) };'
)

If you want some sort of lookup mechanism, use an event

~notenum2freq = (
	50: 100,
	55: 200,
	60: 300,
	// somenotenumber: somefreq
    // etc
);

~notenum2freq[50] == 100

But I still don’t really know what you mean by…

Are you talking about midi channels, or busses?

Excellent–thanks jordan! That is much better syntax. By output bus I don’t mean midi channels, but audio busses out of a multichannel audio interface. I read in MIDI notenumber and assign a fixed frequency to that event and output it along with MIDI velocity to a particular (preassigned) output audio bus. Make more sense now?
Matthew

Gotcha!

So the synthdef wants an \amp argument, then you convert the velocity to amplitude some how.

SynthDef(\test, {
	var sine = SinOsc.ar(\freq.kr);
	var env = EnvGen.ar(Env.perc, doneAction: 2);
	Out.ar(\out.kr, sine * env * \amp.kr(0))
}).add;

The mididef would then look something like this…

MIDIdef.noteOn(\test, {
	|...msg|
      // unpack msg
	var notenum = msg[1];
	var vel = msg[0];	
      // convert to more musical terms
	var amp = vel.linlin(0,127, -60, 0).dbamp;
	var freq = ~notenum2freq[notenum]; 
      // make synth
	Synth(\test, [\freq, freq, \out, 2, \amp, amp]); // 2 is the third speaker
});

You haven’t mentioned how long the sound should go on for, or if you want the sounds to only play when you hold down the key, rather than just start on strike? That is actually a bigger change that you might expect.

There needs to be another event that assigns an output bus depending on notenum, e.g. bass notes get assigned to Ch. 0 and treble notes get assigned to Ch. 1. The MIDI keyboard should act like an organ, so that notes sustain for as long as the key(s) is(are) pressed. Thanks so much for the help!
Matthew