My confusion comes from Max I think where you can output the notevalue as an integer box and plug it everywhere you want…
It’s quite helpful that you said this, thanks. Part of the issue, then, is that you’re very familiar with the Max methodology (idiomatic usage) but not familiar with SC’s idiomatic usage.
One tricky thing in SC is: What is handled in the language (client) and what is handled in the server?
In general (IMO, some users might disagree) you’ll have the easiest time if you treat the server as a dumb animal whose job is just to do the heavy lifting of audio processing. The server (IMO) should not be making flow of control or timing decisions. It should just respond to OSC commands. (Demand UGens try to add some sequencing capabilities into the server, but they aren’t as powerful as client-side patterns – I scarcely ever use them except for LFO types of behavior that I can’t get any other way.)
MIDI files are way outside of that purview – and, in fact, SimpleMIDIFile
is totally a client-side construct.
So I’d recommend a code design where all processing of the MIDI file data, and sequencing, take place in the client, sending messages to the server.
I’d recommend writing the synth like this:
(
// you need to save the Synth object in a variable reference
// {}.play, freestanding, means you can't do anything to control it anymore
// a = {}.play means "a.something" can do stuff to it
a = {
// external input into the synth should be an 'arg'
// not a 'var'
arg freqfrommidifile = 440;
var snd;
// because it's an arg, the synth doesn't have to do any heavy
// thinking about what the freq should be.
// It just obeys what it gets from outside. So delete this.
// freqfrommidifile = //.....?
snd = Resonz.ar(PinkNoise.ar, freqfrommidifile);
Out.ar(0, snd ! 2);
}.play;
)
To play the MIDI data, I’ll recommend piggybacking on the existing MIDI “note” pattern – because this already handles the timing.
This pattern produces events with the default “event type,” \note
– which, as you said, you don’t want.
But, you can add a wrapper around the pattern to change the \note
events into type \set
, which changes the value of an argument of an existing synth (instead of playing new notes).
m = SimpleMIDIFile.read("/home/dlm/share/sc3-plugs-hjh/external_libraries/stk/projects/examples/midifiles/bwv772.mid");
p = Pbindf(
m.p, // this is the original MIDI note pattern
// argument is named "freqfrommidifile"; event needs to match
// The expression reads the MIDI note number and converts to Hz
\freqfrommidifile, Pkey(\midinote).midicps,
\type, \set, // new event type
\id, a.nodeID, // which synth to modify?
\args, [\freqfrommidifile] // which argument names to send?
);
q = p.play;
q.stop;
TBH I wouldn’t expect any new user to figure this out alone. (IMO patterns are the best way to do sequencing in SC, but they aren’t the first thing that you learn, and manipulation of patterns as above is certainly not the first thing that you learn about patterns…) Also TBH, SimpleMIDIFile isn’t a core part of the library and it’s a bit idiosyncratic, so, admittedly, it’s a bit tricky.
Hope that helps,
hjh