Day one.. 6/14/2015

This web page was inspired by the Moog Werkstatt patch sheet. To make the images I scanned the front panel of the Moog Werkstatt and used Gimp and Mspaint to process it. The javascript comes from a project I have been working on for a couple of weeks - Midi file convertor. In Google Chrome browser there is now support for Web Midi Api. Next I plan to add Midi support so that when you change the controls it will send Midi Control Change messages and display the keyboard buttons to send Note On/Off messages. This will allow the control of a Werkstatt using a Midi Interface. I am in the process of updating the Midi keyboard interface I made for the Werkstatt last year.

Below I have links to the sources for this page in the How it works section.

Day two.. 6/15

Improved Save/Load of values. Prompts for name of patch. SaveAsPage also prompts for patch name and removes the SaveAsPage and Load buttons since they do not do anything when the page is loaded from a folder.

Day three.. 6/16

Added a sound object and a selector object. Added setvalues( arg, val) so you can pass an array to the target of the linkto. sound object accepts "key-on" and "key-off" setvalues and plays them if it can. Currently using the selected Midi device. The selector displays 16 buttons which can be used to allow/block key-on and key-off data by midi channel. In the midi file convertor project I make the player send through the midichannels object which then targets the sound object.

          "selector", 17, 71, 500, 60, 10, "bgcolor", "#c00000", "target", "midichannels", "linkto", "sound", "linkarg", "chanselector", "color", "#00ff00",
          "sound", 0, 0, 0, 0, 2, "target", "sound",
        

Day four.. 6/17

Split the midi.js into midifile.js which has the code to decode a MIDI file and split it into tracks and midi.js which now only has the MIDI in and MIDI out code. To midi.js I added a midiin and a midiout object.

          "piano", .23, .81, .7, .15, 6, "target", "piano", "linkto", "midiout", "linkarg","key",
          "midiout", 0, 0, 0, 0, 2, "target", "midiout",
          "midiin", 0, 0, 0, 0, 6, "target", "midiinput", "linkto", "piano", "linkarg", "",
        
So the above entries in the layout table tell the midiin object to send the data to the piano object. The piano object sends data to the midiout object. This allows the piano to display the midi notes being played within it's range. It also allows the piano to send midi note on/off data when you use the PC keyboard and or mouse/touch surface.

Day five.. 6/20 (yes I had a couple of days doing something else)

Adding simple Web Audio Interface to give a crude idea of what the Werkstatt could sound like.

Day six.. Fathers day!

The synth part is working better. Hooked up the Midi input the vco freq (CC-21), vcf cutoff (CC-22), and vcf resonance(CC-23). The control assignments match the first three knobs on my Novation Launchkey Mini. So the synth currently responds to note on/off on midi channel 1 (value 0). So the working synth controls are

      Keyboard
      VCO Freq
      VCF Cutoff
      VCF Resonance - currently the Q factor of the Biquad filter.

Fixed the annoying keypress autorepeat generating key on events. Synth now does last key priority with glide when played legato.

Day seven.. 6/22

Reworked how the save, saveaspage labels work. Removed the action attribute and converted them to normal linkto/linkarg format. There is now kbdobj control that maps actions onto the keyboard object which manages the canvas. Added a Hide button so this text and the text after can be hidden..

Day Ten.. 6/25

Been working on the background code. In the html you can now define multiple canvas areas and have seperate layout tables so you can have multiple instruments on one screen.

6/30 - Argh!!!

Recent Chrome update broke Midi Output! Not Happy :(

Found some other great demos of Web Audio at http://webaudiodemos.appspot.com/

This web page is served by a PHP script running under Apache Web server. If you click on the save button on the keyboard, the returned web page can be saved to disk and opened later without the need for a web server. The folder that you save the data into needs to have a sub folder called images and you need to save the werkstatt.png and werkstattr.png files into it. These are used by the saved web page to load the background image.

The web page element with the id of "keyboard" defines where and how big the keyboard is. The keyboard is drawn on an HTML 5 canvas element. The javascript that draws the keyboard on the canvas is driven by a slow timer. The page onload() function is called process() and it starts a timer using setInterval(). The setInterval() function is passed timer_doTempo() which is called every few milliseconds based on a value set in the code.

The javascript defines an number of 'object' types.

objlist
objlist creates a simple linked list of "obj" objects. objlist defines the head of the list and the addobj and removeobj functions. The main objlists are the global timerlist which is used to tell the timer_doTempo() function what to do. And the keyboard ctrllist which is a list of the controls on the keyboard.
obj
"obj" objects have next and prev variables that are used to link them into lists. The "ob" variable is the object that the instance is carrying.

The controls on the page inside the HTML Canvas are defined as data in an array.

            // the keyboard object is the a pseudo object and controls 'canvas'.
            // set the background image and the scale of the position values.
            "keyboard", 0, 0, 0, 0, 8, "bgimage", "images/werkstattr.png", "imagesize", 2497, "scale", "relative", "target", "canvas",
            "piano", .23, .81, .6, .15, 6, "target", "piano", "linkto", "synth", "linkarg","key",
            "label", 0.9, 0.14, 0.05, 0.04, 10, "label", "Save", "linkto", "canvas", "linkarg", "save", "color", "white", "bgcolor", "red",
            "label", 0.9, 0.20, 0.10, 0.04, 10, "label", "SaveAsPage", "color", "white", "bgcolor", "red", "linkto", "canvas", "linkarg", "saveaspage",
            "label", 0.9, 0.26, 0.05, 0.04, 10, "label", "Load", "color", "white", "bgcolor", "blue", "linkto", "canvas", "linkarg", "load",
            "label", 0.58, 0.042, 0.12, 0.04, 8, "label", "Patch", "color", "red", "bgcolor", "white", "target", "patchname",
            "rotary",  0.13375, 0.8, 0.075, 0.12, 10, "value", 0, "color", "blue", "bgcolor", "#ffffff", "linkto", "synth", "linkarg", "glide",
            "rotary",  0.765, 0.62, 0.075, 0.12, 6, "value", 0, "color", "red", "bgcolor", "white",
            "rotary",  0.645, 0.62, 0.075, 0.12, 6, "value", 0, "color", "red", "bgcolor", "white",
            "button",  0.54875, 0.676, 0.025, 0.04, 8, "value", 0, "color", "red", "style", 1, "bgcolor", "black",
            "button",  0.37125, 0.676, 0.025, 0.04, 8, "value", 0, "color", "red", "style", 1, "bgcolor", "black",
            "rotary",  0.16375, 0.62, 0.075, 0.12, 6, "value", 0, "color", "red", "bgcolor", "white",
            "button",  0.78875, 0.452, 0.025, 0.04, 8, "value", 0, "color", "red", "style", 1, "bgcolor", "black",
            "rotary",  0.645, 0.4, 0.075, 0.12, 6, "value", 0, "color", "red", "bgcolor", "white",
            "button",  0.54875, 0.452, 0.025, 0.04, 8, "value", 0, "color", "red", "style", 1, "bgcolor", "black",
            "button",  0.4, 0.452, 0.025, 0.04, 8, "value", 0, "color", "red", "style", 1, "bgcolor", "black",
            "rotary",  0.25875, 0.4, 0.075, 0.12, 6, "value", 0, "color", "red", "bgcolor", "white",
            "button",  0.16125, 0.452, 0.025, 0.04, 8, "value", 0, "color", "red", "style", 1, "bgcolor", "black",
            "button",  0.78875, 0.208, 0.025, 0.04, 8, "value", 0, "color", "red", "style", 1, "bgcolor", "black",
            "rotary",  0.645, 0.17, 0.075, 0.12, 12, "value", 0, "color", "red", "bgcolor", "white", "linkto", "synth", "linkarg", "resonance", "target","CC-23",
            "rotary",  0.525, 0.17, 0.075, 0.12, 12, "value", 8000, "color", "red", "bgcolor", "white", "linkto", "synth", "linkarg", "cutoff", "target","CC-22",
            "rotary",  0.375, 0.17, 0.075, 0.12, 6, "value", 0, "color", "red", "bgcolor", "white",
            "button",  0.28375, 0.208, 0.025, 0.04, 8, "value", 0, "color", "red", "style", 1, "bgcolor", "black",
            "rotary",  0.13625, 0.17, 0.075, 0.12, 12, "value", 0, "color", "red", "bgcolor", "white", "linkto", "synth", "linkarg", "freq", "target","CC-21",
            "synth", 0, 0, 0, 0, 6, "target", "synth", "linkto", "midiout", "linkarg", "",
            "midiout", 0, 0, 0, 0, 2, "target", "midiout",
            "midiin", 0, 0, 0, 0, 10, "target", "midiinput", "linkto", "piano", "linkarg", "key", "linkto", "CC", "linkarg", "CC",
            "", 0, 0, 0, 0, 0
          

The first column is the type of control, the next four are the top left corner (x, y) and width and height. The sixth column is the number of extra data for this object. Currently the extra data is in the form of name/value pairs.

The types of control available are

label
A text label. the label attribute specifies the text. If it has an action attribute then that specifies what to do when it is clicked.
button
This is an indicator that changes state when you click it. Currently has two styles, 0 - colored square, 1 - vertical switch.
rotary
A rotary control. Click and drag to change it's value.
slider
A vertical slider control. Click and drag to change it's value.
keyboard
Pseudo control. The attributes control the canvas as a whole. scale defines if the position values are absolute (default) within the canvas or relative which means they are a fraction of the width or height of the canvas which is specified in the html element with id="keyboard". imagesize is the width in pixels of the specified background image and is used to adjust data.
synth
A simple Web Audio based synth.
midiout
MIDI output. If a midi device is selected it will drive the selected instrument.
midiin
MIDI input. If a midi input device is selected it gives the data to the midiin control. The linkto arguments route the 'key' and 'control change' messages.

There can be a number of scenes on the web page. Each scene is specified by a layout, and a scene name. So you can have two or more of the Werkstatt synths on a web page and control them individually. The Midi IO config will become it's own scene so the evemts it generates can be routed to all or some of the other scenes. The linkto parameter will allow a scene name as part of the specification.

On windows right click and save as to download the following files.

images/werkstatt.png
This is the black background image of the Moog Werkstatt front panel.
images/werkstattr.png
This is the white background image of the Moog Werkstatt front panel.
ZIP of the images folder and sources
ZIP archive of sources etc.
keyboard.js
This is the main javascript file that implements the controls using an HTML 5 canvas element.
processbase.js
This javascript file has the main timer and startup functions. It also has the linked list code.
midi.js
This javascript file does the MIDI web api interface. It also defines the midiin and midiout objects.
 
LittleBits logo
 
radioshack logo
 
Arduino logo