Sample player?

Do you know about the built in SC help / documentation?

Anyway, what I think you’re asking for (polyphonic MIDI sample player with microtonal pitch adjustments / tunings) wouldn’t necessarily be intuitive to build so here’s a template of one way to do it:

First load the soundfile into a buffer:

// save the .scd file in the same directory as your sample for this to work:
~buf = Buffer.read(s, "VoxHumana_A3.wav".resolveRelative);

Make your synthdef to play it, e.g.:

(
SynthDef(\sample_mono, { |out, buf, startSec, rate = 1, gate = 1, amp = 0.1, pan|
  // adjust envelope here
  var env = Env.adsr(0.1, 1, 0.2, 1.0).ar(Done.freeSelf, gate); 
  
  var startPos = startSec * BufSampleRate.kr(buf);
  var sig = PlayBuf.ar(1, buf, BufRateScale.kr(buf) * rate, startPos: startPos);
  Out.ar(out, Pan2.ar(sig * env * amp, pan));
}).add;
)

You can test it out:

x = Synth(\sample_mono, [buf: ~buf])
x.release

Now the MIDI bit. The basic template I use for handling incoming MIDI notes polyphonically is:

(
MIDIClient.init;
MIDIIn.connectAll;

~notes = ();

MIDIdef.noteOn(\sampleOn, { |vel, num|
  ~notes[num].free; // just in case
  ~notes[num] = Synth( ...whatever... );
});

MIDIdef.noteOff(\sampleOff, { |vel, num|
  ~notes[num].release;
  ~notes[num] = nil;
});
)

For your case, maybe:

(
MIDIClient.init;
MIDIIn.connectAll;

~notes = ();
~tuning = Tuning.just;

MIDIdef.noteOn(\sampleOn, { |vel, num|
  var adjustedNum = num - 57; // root note A3 = midi note 57
  var octave = (adjustedNum / 12).floor;
  var semitone = adjustedNum % 12;
  var tuned = ~tuning[semitone] + (octave * 12);
  
  ~notes[num].free; // just in case
  ~notes[num] = Synth(\sample_mono, [
    buf: ~buf, 
    rate: tuned.midiratio.postln,
    amp: vel.linlin(0, 127, -30, -10).dbamp,
  ]);
});

MIDIdef.noteOff(\sampleOff, { |vel, num|
  ~notes[num].release;
  ~notes[num] = nil;
});
)

You can change tunings while playing:

~tuning = Tuning.et12;
~tuning = Tuning.pythagorean;

~tuning = [0, 0.9, 1.6, 3.1, 4.0, 4.9, 5.6, 7.1, 8.0, 8.9, 9.6, 11.1];

hope this gets you closer…

1 Like

Oh I just reread your original question and maybe you don’t need MIDI playability… if you want to play with patterns, much easier, but you need to turn the rate argument into a freq argument:

(
SynthDef(\sample_mono_pat, { |out, buf, startSec, freq, baseFreq = 220, gate = 1, amp = 0.1, pan|
  var env = Env.adsr(0.1, 1, 0.2, 1.0).ar(Done.freeSelf, gate);
  
  var rate = freq / baseFreq;
  var startPos = startSec * BufSampleRate.kr(buf);
  var sig = PlayBuf.ar(1, buf, BufRateScale.kr(buf) * rate, startPos: startPos);
  Out.ar(out, Pan2.ar(sig * env * amp, pan));
}).add;
)


(
Pbind(
  \instrument, \sample_mono_pat,
  \buf, Pfunc { ~buf },
  \scale, Scale.chromatic('pythagorean'),
  \degree, Pseq([0, 2, 7, 9], inf),
  \octave, Prand([3, 4], inf),
  \dur, 0.2
).play;
)
1 Like

Thank you for this. I really appreciate it