var context=null;   // the Web Audio "context" object
var midiAccess=null;  // the MIDIAccess object.
var oscillator=null;  // the single oscillator
var envelope=null;    // the envelope for the single oscillator
var attack=0.05;      // attack speed
var release=0.05;   // release speed
var portamento=0.05;  // portamento/glide speed
var activeNotes = []; // the stack of actively-pressed keys

window.addEventListener('load', function() {
  // patch up prefixes
  window.AudioContext=window.AudioContext||window.webkitAudioContext;

  context = new AudioContext();
  if (navigator.requestMIDIAccess)
    navigator.requestMIDIAccess().then( onMIDIInit, onMIDIReject );
  else
    alert("No MIDI support present in your browser.  You're gonna have a bad time.")

  // set up the basic oscillator chain, muted to begin with.
  oscillator = context.createOscillator();
  oscillator.frequency.setValueAtTime(110, 0);
  envelope = context.createGain();
  oscillator.connect(envelope);
  envelope.connect(context.destination);
  envelope.gain.value = 0.0;  // Mute the sound
  oscillator.start(0);  // Go ahead and start up the oscillator
} );

function onMIDIInit(midi) {
  midiAccess = midi;

  var haveAtLeastOneDevice=false;
  var inputs=midiAccess.inputs.values();
  for ( var input = inputs.next(); input && !input.done; input = inputs.next()) {
    input.value.onmidimessage = MIDIMessageEventHandler;
    haveAtLeastOneDevice = true;
  }
  if (!haveAtLeastOneDevice)
    alert("No MIDI input devices present.  You're gonna have a bad time.");
}

function onMIDIReject(err) {
  alert("The MIDI system failed to start.  You're gonna have a bad time.");
}

function MIDIMessageEventHandler(event) {
  // Mask off the lower nibble (MIDI channel, which we don't care about)
  switch (event.data[0] & 0xf0) {
    case 0x90:
      if (event.data[2]!=0) {  // if velocity != 0, this is a note-on message
        noteOn(event.data[1]);
        return;
      }
      // if velocity == 0, fall thru: it's a note-off.  MIDI's weird, y'all.
    case 0x80:
      noteOff(event.data[1]);
      return;
  }
}

function frequencyFromNoteNumber( note ) {
  return 440 * Math.pow(2,(note-69)/12);
}

function noteOn(noteNumber) {
  activeNotes.push( noteNumber );
  oscillator.frequency.cancelScheduledValues(0);
  oscillator.frequency.setTargetAtTime( frequencyFromNoteNumber(noteNumber), 0, portamento );
  envelope.gain.cancelScheduledValues(0);
  envelope.gain.setTargetAtTime(1.0, 0, attack);
}

function noteOff(noteNumber) {
  var position = activeNotes.indexOf(noteNumber);
  if (position!=-1) {
    activeNotes.splice(position,1);
  }
  if (activeNotes.length==0) {  // shut off the envelope
    envelope.gain.cancelScheduledValues(0);
    envelope.gain.setTargetAtTime(0.0, 0, release );
  } else {
    oscillator.frequency.cancelScheduledValues(0);
    oscillator.frequency.setTargetAtTime( frequencyFromNoteNumber(activeNotes[activeNotes.length-1]), 0, portamento );
  }
}
var context=null; // the Web Audio "context" object var midiAccess=null; // the MIDIAccess object. var oscillator=null; // the single oscillator var envelope=null; // the envelope for the single oscillator var attack=0.05; // attack speed var release=0.05; // release speed var portamento=0.05; // portamento/glide speed var activeNotes = []; // the stack of actively-pressed keys window.addEventListener('load', function() { // patch up prefixes window.AudioContext=window.AudioContext||window.webkitAudioContext; context = new AudioContext(); if (navigator.requestMIDIAccess) navigator.requestMIDIAccess().then( onMIDIInit, onMIDIReject ); else alert("No MIDI support present in your browser. You're gonna have a bad time.") // set up the basic oscillator chain, muted to begin with. oscillator = context.createOscillator(); oscillator.frequency.setValueAtTime(110, 0); envelope = context.createGain(); oscillator.connect(envelope); envelope.connect(context.destination); envelope.gain.value = 0.0; // Mute the sound oscillator.start(0); // Go ahead and start up the oscillator } ); function onMIDIInit(midi) { midiAccess = midi; var haveAtLeastOneDevice=false; var inputs=midiAccess.inputs.values(); for ( var input = inputs.next(); input && !input.done; input = inputs.next()) { input.value.onmidimessage = MIDIMessageEventHandler; haveAtLeastOneDevice = true; } if (!haveAtLeastOneDevice) alert("No MIDI input devices present. You're gonna have a bad time."); } function onMIDIReject(err) { alert("The MIDI system failed to start. You're gonna have a bad time."); } function MIDIMessageEventHandler(event) { // Mask off the lower nibble (MIDI channel, which we don't care about) switch (event.data[0] & 0xf0) { case 0x90: if (event.data[2]!=0) { // if velocity != 0, this is a note-on message noteOn(event.data[1]); return; } // if velocity == 0, fall thru: it's a note-off. MIDI's weird, y'all. case 0x80: noteOff(event.data[1]); return; } } function frequencyFromNoteNumber( note ) { return 440 * Math.pow(2,(note-69)/12); } function noteOn(noteNumber) { activeNotes.push( noteNumber ); oscillator.frequency.cancelScheduledValues(0); oscillator.frequency.setTargetAtTime( frequencyFromNoteNumber(noteNumber), 0, portamento ); envelope.gain.cancelScheduledValues(0); envelope.gain.setTargetAtTime(1.0, 0, attack); } function noteOff(noteNumber) { var position = activeNotes.indexOf(noteNumber); if (position!=-1) { activeNotes.splice(position,1); } if (activeNotes.length==0) { // shut off the envelope envelope.gain.cancelScheduledValues(0); envelope.gain.setTargetAtTime(0.0, 0, release ); } else { oscillator.frequency.cancelScheduledValues(0); oscillator.frequency.setTargetAtTime( frequencyFromNoteNumber(activeNotes[activeNotes.length-1]), 0, portamento ); } }

rollz-5

Rollz-5 is Peter Blasser's circuit design, it is the ancestor of Plumbutter. It is can be understood as a Drum Machine, but not quite.

Instead of sequencer on most drum machines, Rollz-5 implies geometric rolls that outputs pulses in different paces, set by component values while building. Even rolls would produce rhythmical signals while odd rolls would yield high frequency oscillations. The rolls can be connected together to form complex rhythms and audible signals.

Then the signals from rolls will be connected to 3 different sound modules, following descriptions are taken from Peter's website :

  • AVDOG : which uses the same resonant filter as Gongs, but at a very low frequency, to transform pulses into a slow undulation. This undulation controls the amplitude of a simple drone tone, to make a ghostly complement to the pulse material. I created this translator to balance with the plucked and pulsed sounds. It’s like sending pulses through a watery wave-tank which speaks a simple tone, a complement to the more abrupt rhythms of the other translators, yet it relates periodically because it is based on the same raw material.

  • ULTRASOUND : knob sets the cutoff frequency around which ultrasounds are reflected down to audible range. It uses a switched capacitor filter, which has a (happy) side-effect of heterodyning high frequency sound by its reference tone. It sounds like an old-time radio as it sweeps through stations; there are audible difference tones swooping up and down. This translator also filters the timbre of the even pulses.

  • GONGS : It works with even pulse material, waiting a period set by the control knob, then pulsing a resonant filter preset to a certain pitch and damping. Normally I would desire moveable pitches, but I reconciled with set pitches because this is a drum machine- The tones mark phrases around which melodies develop externally, and I would rather control the phrase length than the tone of the gong. Anyhow, a creative hacker could easily mod these circuits to make the pitches moveable.  The sonic effect is anything from a short woodblock tone to a long deep resonant gong, synchronized at short or long periods.

Currently Rollz-5 is available as partial kit and PCB from shop.