Implementing Chords in Sequenced Synthesizer

Hello, I’m working on a sequenced synthesizer with some named controls. One feature I’m trying to implement is the ability to play chords, and I want to set these chords using an array chord control. Currently, I have the chord array hardcoded to [0, 2, 4] , but when I replace it with the chord array, it seems to be ignored. What could be causing this issue?

(
b = Buffer.loadCollection(s, Scale.scriabin);
Ndef(\test, {
	var deg, env, freq, sig, trig;
    var chord = \chord.kr(0!4);
    var chordSize = \chordSize.kr(4);
    var dur = \dur.kr(0!4);
    var durSize = \durSize.kr(4);
    var degree = \degree.kr(0!4);
    var degreeSize = \degreeSize.kr(4);

    // Sequencer
    dur = Dser(dur, durSize);
    trig = Dseq([dur], inf) / TempoClock.tempo;
    trig = TDuty.ar(trig, 0, 1);

    // Frequency
    deg = Dser(degree, degreeSize);
    deg = Demand.ar(trig, 0, Dseq([deg], inf));
    freq = (DegreeToKey.ar(b, deg + [0, 2, 4]) + 48).midicps;
    env = Env.perc(0.005, 0.5).ar(gate: trig);
    sig = Pulse.ar(freq)!2 * env;
});
)

(
Ndef(\test).play;
Ndef(\test).set(\dur, 1/2);
Ndef(\test).set(\degree, [0, 1, 2, 3]);
Ndef(\test).set(\degreeSize, 4);
)

Thank you!

It works for me, maybe you forgot to set the chord like Ndef(\test).set(\chord, [0, 2, 4, 6])? Initially you will only hear one note as the chord is initialized to [0, 0, 0, 0].

@Thor_Madsen It should not repdoduce a single note because the notes come from \degree. I find that it works if we set a default chord to [0, 0, 0, 0] but it generates 4 voices. My intention was to set the array length with Dser so we can get a [0] and disable the chord. This works:

freq = (DegreeToKey.ar(b, deg + \chord.kr([0, 0, 0, 0])) + 48).midicps;

Ndef(\test).set(\chord, [0, 2, 3, 4]);

I’d do it like this:

(
b = Buffer.loadCollection(s, Scale.scriabin);
)

(
Ndef(\test, {
	var deg, env, freq, sig, trig;
    var chord = \chord.kr(0!4);
    var chordSize = \chordSize.kr(4);
    var dur = \dur.kr(0!4);
    var durSize = \durSize.kr(4);
    var degree = \degree.kr(0!4);
    var degreeSize = \degreeSize.kr(4);
	
	var trigMask = Array.fill(4, { |i| i < chordSize });

    // Sequencer
    dur = Dser(dur, durSize);
    trig = Dseq([dur], inf) / TempoClock.tempo;
    trig = TDuty.ar(trig, 0, 1);

    // Frequency
    deg = Dser(degree, degreeSize);
    deg = Demand.ar(trig, 0, Dseq([deg], inf));
	freq = (DegreeToKey.ar(b, deg + chord) + 48).midicps;
	env = Env.perc(0.005, 0.5).ar(gate: trig * trigMask);
	sig = ((Pulse.ar(freq)* env).sum * 0.1).dup;
});
)

(
Ndef(\test).play;
Ndef(\test).set(\dur, 1/2);
Ndef(\test).set(\degree, [0, 1, 2, 3]);
Ndef(\test).set(\degreeSize, 4);
// now you are just playing 1 note
// so it's incorrect to leave chordSize at 4
Ndef(\test).set(\chordSize, 1);
)

Ndef(\test).set(\chord, [0, 2, 4], \chordSize, 3);

hjh

@jamshark70 , thank you, the solution you provided works, but I’ve noticed that when the chord control is disabled with [0] , the sound plays in mono. However, when we remove chord from the DegreeToKey function, it sounds stereo.

Additionally, I’m curious if it’s possible to achieve the same effect without using an envelope. Any insights on these points?

Hmm, it’s not clear to me how that’s possible.

The degree sequencer (Demand) outputs a single degree. Adding chord produces an array of 4 degrees, converted to 4 frequencies, which drive 4 Pulse units. These are summed into a single channel, and then dup-ed to stereo. I don’t see anything in my example that would silence one of the duplicated output channels.

Maybe you’re running something different? But I can’t evaluate that, since code wasn’t shared.

The chordSize technique depends on silencing unused voices. To do this, each voice needs its own envelope, of some form or another. (An envelope may be produced by many other UGens, not only EnvGen.) Envelopes aren’t optional here.

hjh

Sorry, you are right. I copied partially your example and I missed the dup.

Your approach is very good. I was considering to control the envelope but I must prioritize chords:

env = Env.perc(0.005, 0.5).ar(gate: trig);
sig = Select.ar(\env.kr(0) > 0, [sig, sig * env]);

Thank you very much :slightly_smiling_face: