Examples / Voices

Right-click to copy examples to your workspace


record_voice_over
Wherein we show the use of Voices to produce polyphonic bliss.

Intro

The MusicAPI includes a polyphonic voice manager, Voices, to transform a monophonic instrument into a polyphonic one. It does this simply by creating multiple independent instances of the instrument and tracking the lifetime of notes that it delivers.

voices.js

This code produces the audio graph that follows it.

// The usual startup boilerplate
let scene = await Ascene.BeginFiber(this);
let osc = scene.NewAnode("Hz.Osc", {cfg: "mono"});
let pan = scene.NewAnode("Hz.Mix", {cfg: "1to2"});
let dac = scene.GetDAC()
scene.Chain(osc, pan, dac);

// create our voice manager and request 20 voices of our synth 
// defined by the sink node of its "voice". The number of voices 
// active is governed by the combination of the note duration 
// and the // ADSR release time.  AudioStatus shows the number 
// of active voices in the LoadAvg display.
let voicemgr = scene.NewVoices();
voicemgr.AddVoices(pan, 20);
scene.VisualizeGraph("Voices"); // 20 * 2 + 1 == 41 nodes.
await scene.Sync();

Now when we send notes to voicemgr it finds an available voice and assigns it the task of performing the note. Note that the Note method (NoteOn too), returns two values, noteId and voiceId. The latter is useful in setting parameters for an individual voice in the voicemgr's pool.

pan.SetParam("Gain", -5); // sets gain for all voices.
osc.SetParam("/adsr/A", .5); // sets long Release for all voices.
osc.SetParam("/adsr/R", 1); // sets long Release for all voices.

for(let j=0;j<20;j++)
{
    for(let i=0;i<10;i++)
    {
        // provide a random parameter value (pan.pan) for each note
        // parameters key is anode (orig), value is map of paramId to value.
        let [noteId,voiceId] = voicemgr.Note(30+3*i,
                                    .1 +.4*Math.random(), 
                                    scene.Seconds(.5), 0);
        voicemgr.SetVoiceParam(voiceId, pan, "Pan", Math.random());
        await scene.Wait(scene.Seconds(.3));
    }
}

delay.js

This example shows that more complex subgraphs can be voiced.
Here's the subgraph of a single voice.

This example also shows how to use /adsr/T to account for delay effects to finish before a voice is released. As with the prior example, keep an eye on the live voice counter within AudioStatus/LoadAvg.

See Also

Voices Ref

home .. topics .. interface .. reference .. examples .. tipjar