/ Ref / HzPlugins

Songs.hz . Music API
Hz.Plugins . 3rd Party Plugins
General MIDI . MIDI CC . MIDI notes
Configure
home . Topics . Interface . Reference . Examples


flag   Hz.Plugins are included with HzWeb. They are built atop the Web Audio Module (WAM) standard and can theoretically be loaded into any WAM host, TOC here

That said, our focus is providing the necessary batteries required to use HzWeb so we offer no guarantees of their functionality in other WAM hosts.

Hz ships with many examples discussed here.

right-click for table of contents


Instruments

Hz.FM7

Hz.FM7 is a polyphonic 6-operator FM synthesizer based on Google's music synthesizer for android (msfa) which itself is based on the Yamaha DX7. We've added support for 33 built-in banks from a variety of public domain patch sets. We've also extended it to support stereo out and more voices. Note that this is the same foundation used by Dexed and a variety of other online sythesizers. If you need more extensive control over a DX7 instrument than Bank and Patch, we recommend you explore online alteratives. Hz.FM7 s a great utility synth that can produce a wide variety of high-quality synthesized sounds.

To instantiate with preset bank and patch:

let fm7 = await ascene.NewAnode("Hz.FM7", {
  name: "myfm7", 
  preset: {
    Bank: 3,
    Patch: 5,
    Gain: 2.3
  }
});

Hz.Samplo

Hz.Samplo is a polyphonic sample-playing instrument. You can initialize it from a variety of online sample-sets.

Hz.Samplo ships capable of producing literally hundreds of different sounds. You can also initialize it with your own samples.

Sample-sets come in two categories:

Hz.Samplo handles both types but your scripts must be aware of this distinction because it affects the interpretation of MIDI key numbers. Be aware that some percussion banks organize their sounds based on the GeneralMIDI standard.

Here is an example instantiation:

let samplo = await scene.NewAnode("Hz.Samplo", { 
  preset: {
    A: 0.1, // soundfonts have a natural attack env.
    D: 0.01,
    S: 1,
    R: 1.5, // user releases prior to end of sbuf.
    Gain: 2,
    instrument: {
      kit: "FatBoy",
      inst: "church_organ"
    }
  }
});

Hz.Osc

Hz.Osc is a simple polyphonic instrument based on WebAudio's oscillator node. It has support for Unison voices which is achieved by assigning multiple (detuned) oscillators to a single note. Hz.Osc implements a custom note expression, _frequency, that can be useful to programmatically control an oscillator frequency while a note is held. This can be thought of as a more general note expression than tuning.

Here is an example instantiation:

let inst = await Anode.New("Hz.Osc", {
  preset: {
    Waveform: 1,
    Gain: .5,
    A: .1,
    D: .01,
    S: 1,
    R: .04,
  }});

Hz.Genish

Hz.Genish is a programmable audio processor based on genish.js which, in turn, was inspired by gen~ for Max.

The cool thing about genish is that it allows you to develop custom synths or effects without all the fuss required to produce a full plugin. Your genish extension/customization is a small JavaScript-let like this:

// a simple FM synth (that plays a single tone)
function FM(g) // g is the genish context with dsp operators.
{
  let sineOsc = g.cycle(g.madd(10, g.cycle(4), 440)); 
  return g.mul(sineOsc, .25);
},

To construct:

let mode = "stereo"; // or "mono"
let type = "instrument"; // or "effect"
let genish = await scene.NewAnode("Hz.Genish", {
                              acfg: {mode, type}
                            });
await genish.LoadPreset({genish: {
    name: "coolsynth",
    code: yourFunction.toString(),
    wsdir: this.GetCWD()
  }};

Examples here: hzplugins/genishTestSynth.j,genishTestEfects.js,genishFM2.js and genish scriptlets below hzplugins/genish/.

Hz.Genish operators and implementation details are here.


Hz.RetroVocoder

Hz.RetroVocoder is built atop Paul Kellett's 2008 Talkbox plugin. Its simple interface belies the potential of really cool retro-robot sounds. You must have two signal sources, typically a voice and and instrument. These are wired as follows:

scene.Connect(voice, vocoder, 0, 0); // voice goes to vocoder port 0
scene.Connect(inst, vocoder, 0, 1); // instrument goes to vocoder port 1

Vocoder detects the incoming channel counts and reconfigures accordingly, Stereo operation is twice as expensive as mono.

Example here: hzplugins/retrovocder.js


Hz.Noise

Hz.Noise is a simple synth that produces your choice from three colors of noise.


Effects

Hz.ConvVerb

Hz.ConvVerb is a simple but powerful reverb built atop WebAudio's convolver. Hz.ConvVerb implements a filter that applies an impulse-reponse audio file to the incoming signal. You can use an arbitrary audio sample file (typically length-constrained) for interesting effects. There are also many online sources for impulse-response files captured by a range of cheap-to-expensive tecniques. Make sure to heed their licensing terms!

Here's a snippet from our example: hzplugins/convverb.js.

let rev = await scene.NewAnode("Hz.ConvVerb");
await rev.LoadPreset({Wet: 1, Dry: .2});
// samples CC-BY-SA (C) 2016 Damo
let root = "https://raw.githubusercontent.com/zamaudio/impulses/master";
let ir = `${root}/Hall_mono0.wav`;
await rev.LoadPreset({impulseResponse: ir});

Hz.DynaCompress

Hz.DynaCompress is a simple wrapper of WebAudio's DynamicsCompressorNode.

Example here: hzplugins/dynacompress.js.


Hz.Echo

Hz.Echo is a simple feedback-delay effect with support for PingPong echo. Included in the feedback path is a lowpass filter. The lower the FilterCutoff the darker the echo-return.


Hz.Filter

Hz.Filter implements a SVF filter and provides lowpass, highpass, bandpass and notch filter options. It also supports resonant frequency modulation via a built-in LFO. When Keytrack is enabled the resonant frequency follows the MIDI key events that you provide it.


Hz.Freeverb

Hz.Freeverb is a port of the well-known, public-domain Freeverb effect written by Jezar at Dreampoint, June 2000. Its Freeze parameter can be employed to add reverb glitch. This alternative to Hz.ConvVerb supports continuous variation of room-size, etc.


Hz.Genish Effect

Hz.Genish (above) can also be used to describe custom effects.

Using Hz.Genish as an effect processor requires a couple steps.

First, instantiate the node:

let genish = await scene.NewAnode("Hz.Genish", {
                acfg:{type:"effect"}
              });

Next, wire an input that produces a sound to be processed, something like:

ascene.Chain(audiosrc, genish, dac);

Next, make sure that your genish scriptlet refers to in1 and/or in2. These represent your node's left and right input channels. Here's a simple mono crusher distortion:

function ampcrush(g, ampScale=12)
{
  return g.div(g.round(g.mul(g.in1, ampScale)), ampScale);
},

Finally, load your scriptlet.

await genish.LoadPreset({
  genish: {
    name: "cooleffect",
    code: ampcrush.asString(),
    wsdir: this.GetCWD()
  }
})

More examples here: hzplugins/genishTestEfects.js and genish scriptlets below hzplugins/genish/;


Hz.LFO

Hz.LFO is a simple envelope-based Low Frequency Oscillator. You can design your custom envelopes with envelope editor and paste them into your script or the GUI.

For examples see: hzplugins/lfo.js,lfoModulator.js.

// To initialize `Hz.LFO` with a custom envelope:
let lfo = await scene.NewAnode("Hz.LFO", {preset: {
  envelope: {
      shape: "tooth",
      smooth: false,
      data: [0, 0, 5, 0.5, 1, -5, 1, 0, 0]
    },
  }
});
Run Modes

Hz.LFO supports two run modes and this determines how they should be connected into the audio graph.

// To use `Hz.LFO` as an `amplitude modulator`:
let lfo = await scene.NewAnode("Hz.LFO"); // RunMode:0 is default
scene.Chain(inst, lfo, dac); // inst and dac created elsewhere

// To use `Hz.LFO` as a `parameter modulator`:
let lfo = await scene.NewAnode("Hz.LFO", {preset: {RunMode:1}}); 
scene.ModulateParam(lfo, inst, "Pan"); // inst created elsewhere

flag Important  notes for parameter modulation


Hz.Waveshaper

Hz.Waveshaper is a simple distortion effect built atop WebAudio's WaveShaperNode.

Use the combination of InputDrive and Drive parameters to select your distortion effect. Beside obvious distortion effects, it is often used to add a warm feeling to a signal. Modulating Drive is much more expensive than InputDrive since it updates the wave shaping function.

Here`s an example:

let overdrive = await scene.NewAnode("Hz.Waveshaper", 
            {preset:{InputGain:2, Drive:1, OutputGain:.5}});

Distortion example here: hzplugins/tuner.js (uses Hz.AudioIn).


Audio Utilities

Hz.AudioIn

Hz.AudioIn connects your computer's default/current input device into your soundscape or control script. When run, it attempts to open your computer's audio input device (eg microphone). This may require you to grant it permission.

warning WARNING  if you wire your input directly to Hz.DAC you may produce nasty feedback. This problem depends on whether your input device can "hear" your speakers.

If you have a USB audio interface it's possible to receive signals from other sources, eg guitar or fancy microphone. Such devices typically have headphone support to address the potential feedback problem.

Hz.AudioIn receives a mono mono signal. If your input device has multiple channels, the Channel parameter can be specified during anode construction as follows:

let audioIn = await scene.NewAnode("Hz.AudioIn", {preset:{Channel:1}});

Related nodes: Hz.Tuner, Hz.Recorder, Hz.WebAudioIn.

Examples here: hzplugins/audioin.js, hzplugins/tuner.js.


Hz.DAC (Output)

Most audio scenes include a Hz.DAC node because its the node that delivers the results of the audio graph to your audio system's output. For this reason, all roads lead to Hz.DAC.

Hz.DAC is one of the few singletons in the system. There is no value in creating more than a single instance of it which is why we provide ascene.GetDAC().


Hz.Blackhole

Hz.Blackhole is a utility node that you can use to ensure that an anode, like Hz.Scope triggers without a connection to Hz.DAC. It isn't a common requirement but when you need it, you need it. As with Hz.DAC, Hz.Blackhole is a singleton and therefore available via ascene.GetBlackhole().

There are no useful outputs of Hz.Blackhole, no use chaining them to downstream nodes.

See example: hzplugins/blackhole.js.


Hz.Mix

Hz.Mix is a simple mixing node that provides visual feedback on the signal levels. It can be configured during instantiation to either mixdown or preserve the input channels. When mixdown is enabled, we provide Pan control. This is enabled during construction like so:

let mix1 = await scene.NewAnode("Hz.Mix", {acfg:{mode:"mixdown"}});

See example: hzplugins/mix.js.


Hz.Scope

Hz.Scope is used to visualize the audio signal. Usually you use it as a passthrough anode that intercepts, displays and forwards the audio signal. It defaults to a stereo configuration but you can request mono (depicted above) during construction like so:

let scope = await scene.NewAnode("Hz.Scope", {acfg: {mode:"mono"}});

There may be some cases where you don't want to forward the signal. Unfortunately, unless the scope is ultimately connected to either Hz.DAC or Hz.Blackhole the scope will not trigger.


Hz.SpectraScope

Hz.SpectraScope is use to visualize the frequency content of an audio signal. As with Hz.Scope it must be chained to ultimately arrive at Hz.DAC or Hz.Blackhole in order to triger. The spectrum is computed from the combined input channels. Note that both frequency (x) and amplitude (y) axes are displayed on a logrithmic scale.

See example: hzplugins/spectrascopeTest.js.


Hz.Tuner

Hz.Tuner analyzes the primary pitch of its input signal and works well for singal with strong tonal content like a guitar. Typically Hz.Tuner receives mono input from Hz.AudioIn. As with most audio nodes its output signal must be wired to a downstream node in order to trigger.

See example: hzplugins/tuner.js.


Hz.Recorder

Hz.Recorder records its input signal to a .wav file and deposits the result below your workspace directory HzWeb/_recordings.

Hz.Recorder supports two operating modes:

  1. interactive - you press gui buttons Arm, Record, Pause, Disarm/Save to modify the state of the recorder. When some material has been recorded and you press Disarm/Save, the .wav file will written. If you forget to press Record no material will be recorded and no file will be saved.
  2. preset - first your script requests Arm via LoadPreset. You can specify explicit start and stop times or as shown below your recordEnd can be "a long time away" and then your script can explicitly request a stop.
// start a recording
await recordNode.LoadPreset({
      ctrlMode: "Preset",
      prefix: "radio_" + ts,
      recordStart: 0,
      recordEnd: 1e10, // need to trigger end
  });

// later on stop it.
await recordNode.LoadPreset(
    {
      ctrlMode: "Preset",
      disarm: true, // <---- stop recording
      recordEnd: ascene.Now(),
    });

Interactive example: hzplugins/recorder.js.

Scripted example: algorithmic/radio/radio.js.


Hz.WebAudioIn (WebRadio)

Hz.WebAudioIn is the Hz.AudioIn for the internet. You provide a URL which streams a simple audio signal and it can appear in your soundscape. Note that we currently support a subset of potential audio src URLs. Also note that some website URLs can be offline or become invalid. YMMV.

Here's how to construct:

let mystation = await state.ascene.NewAnode("Hz.WebAudioIn", {
                    preset: {
                      Station: name,
                      URL: url,
                      Gain: .2,
                    }});

See example: algorithmic/radio/radio.js.