Hz.Echo implements an echo effect
(stereo or mono) using the same delay machinery as used by
Hz.Delay. Since its simpler
to use, you'll probably use Hz.Echo
more frequently than Hz.Delay
.
console.notice(`
This example uses Hz.Echo to produce a stereo echo effect.
`);
let id = `f${this.GetId()}`;
let scene = await Ascene.BeginFiber(this);
const cfg = "stereo";
let osc = scene.NewAnode("Hz.Osc", {name:"osc", cfg});
let echo = scene.NewAnode("Hz.Echo", {name:"echo", cfg, preset:{maxDelay:2.0}});
scene.Chain(osc, echo, scene.GetDAC());
await scene.Sync();
echo.SetParam("Feedback", .6); // amplitude scale, never >= 1.
echo.SetParam("Delay", 1); // one beat delay
echo.SetParam("DelayUnits", 1); // beats, vs seconds.
osc.SetParam("/adsr/A", .01);
osc.SetParam("/adsr/R", .01);
osc.SetParam("UnisonVoices", 3);
osc.SetParam("UnisonDetune", .1);
osc.SetParam("UnisonSpread", 1);
await scene.Sync();
let timekeeper = new TimeKeeper(scene);
timekeeper.SetTempo(120, .02); // slight acceleration to test beat-based delay.
timekeeper.On("bar", (songpos) =>
{
if(songpos.CurrentBar() == 60)
timekeeper.Stop();
const q = timekeeper.BeatDur();
let n = 50 + Math.floor(30*Math.random());
let vel = Random.InRange(.2, .8);
osc.Note(n, vel, .7*q, songpos.Now());
});
await timekeeper.Start();
// this enables cancelation and updating via the Fibers panel.
const sleepDur = scene.Seconds(1);
while(timekeeper.IsRunning())
{
await scene.Wait(sleepDur);
let msg = yield;
if(msg == "_cancel_")
{
console.log(`${id} canceling`);
timekeeper.Stop();
}
}