polyphony with multiple p5.Part instances?

Here's a p5.js sketch using p5.sound - it has two melodies (top and bottom) that I want played at the same time. For each melody I made a separate p5.SinOsc, p5.Env, p5.Phrase, and p5.Part. In mouseClicked() on the bottom I call .start() on both Parts, but I only hear topPart. Interestingly, if you comment out topPart.start(), then you hear bottomPart - but you can't hear both.

The sketch also starts with a test tone to prove that both p5.SinOsc instances can be heard at the same time (they can).

Does p5.sound only support one playing instance of p5.Part at a time? That doesn't seem right - am I missing something?

var topMelody = [60, 60, 62, 65, 64];
var bottomMelody = [48, 41, 43, 43, 36];

var topVoice, bottomVoice;
var topPhrase, bottomPhrase;
var topPart, bottomPart;
var topEnv, bottomEnv;

function setup() {
    createCanvas(400, 400);

    // make an oscillator for each voice
    topVoice = new p5.SinOsc();
    bottomVoice = new p5.SinOsc();

    // give each one its own envelope
    topEnv = new p5.Env();
    bottomEnv = new p5.Env();

    topVoice.amp(topEnv);
    bottomVoice.amp(bottomEnv);

    // generate a sequence for each melody (see makeSeq() function below)
    topSeq = makeSeq(topVoice, topEnv, topMelody, [1]);
    bottomSeq = makeSeq(bottomVoice, bottomEnv, bottomMelody, [0.05]);

    // make a phrase for each voice
    topPhrase = new p5.Phrase('top', singit, topSeq);
    bottomPhrase = new p5.Phrase('bottom', singit, bottomSeq);

    // make Parts for each voice, add the phrases to them
    topPart = new p5.Part();
    topPart.addPhrase(topPhrase);
    topPart.setBPM(60);

    bottomPart = new p5.Part();
    bottomPart.addPhrase(bottomPhrase);
    bottomPart.setBPM(60);


    // start up the oscillators...
    topVoice.start();
    bottomVoice.start();

    // test tones:
    topVoice.freq(midiToFreq(60));
    bottomVoice.freq(midiToFreq(52));
    topEnv.set(0.5, 0.5, 0.5, 0);
    bottomEnv.set(0.5, 0.5, 0.5, 0);
    topEnv.play();
    bottomEnv.play();

}

function draw() {
    background(123);
    textAlign(CENTER, CENTER);
    text("click to play", 0, 0, width, height);
}

function singit(time, noteEvent) {
    var instr = noteEvent.instrument;
    var note = noteEvent.midinote;
    var env = noteEvent.env;
    var dur = noteEvent.dur;

    instr.freq(midiToFreq(note));
    env.set(0.01, 0.5, 0.01, 0.2, dur - 0.03, 0.2, 0.01, 0);
    env.play();
}

function makeSeq(instr, env, notes, durs) {
    var temp = [];
    for (var i = 0; i < notes.length; i++) {
        temp.push({
            instrument: instr,
            env: env,
            midinote: notes[i],
            dur: durs[i % durs.length]
        });
    }
    return temp;
}

function mouseClicked() {
    bottomPart.start();
    topPart.start();
}
Sign In or Register to comment.