MusicWeaver Modules

— MusicWeaver Release 2.8.5 for Haiku August 2015 —


OVERVIEW

There is very much more to the MusicWeaver than just playing back and recording midifiles. And it is not intended as a Sequencer or the like, with facilities to edit MIDI sequences. It is much more slanted to the manipulation of MIDI streams in real-time — either taking input directly from a keyboard or just from a previously recorded file. You can do things like transpose notes, change or add instruments and channels, filter out certain events or note ranges. You can send Controller and PitchBend messages; you can direct selected events to separate processing paths; and so on. The available modules for the MusicWeaver are described below (with a couple of exceptions that have their own pages).

There are many different sorts of things one can do with the considerable set of MIDI modules. There are modules, of course, that connect to your hardware MIDI interface (if you have one), or to other apps, such as true sequencers. There is one that drives the internal Synth, others to play or record Midifiles, and so on, Aside from these, many either modify the MIDI events in some way, or control the path on which they flow. (It is assumed that you have enough knowledge of MIDI to follow these descriptions: if not, there are many sources of information on the subject — check the Web...)

An important module is MidiLink, which connects a MusicWeaver configuration to outside hardware or other apps. Synth is a Filter that will drive the Haiku internal Synth from a MIDI stream. The MidiPlay module generates a real-time MIDI stream from a Midifile read from disc (and MidiFile and RePlay both play and record). There is a Program module that will send user-determined Program-Change events to a MIDI stream, a Controller for Control-changes, and others that similarly send other specific MIDI events.

There are simple Filter modules, such as Transpose and MIdiChannel, that modify some or all of the events that are passed through them. Transpose, naturally, only operates on Note-On and Note-Off events, shifting them up or down by the interval desired; MidiChannel operates on all except System events that pass through it, setting them to the specified channel.

Other modules are used in various combinations to divert specific events that satisfy certain criteria into different paths. For example you could have all notes within a certain range flow along one path, notes outside that along another (keyboard-split deluxe...). Or you could split off certain channels for separate processing, and so on. See 'Marking and Splitting Events' for details on how this is achieved.

There is a different type of (Universal) path-switching module that will change the path of an entire stream in response to 'director' messages. Refer to 'Path Switching' in the documentation on Universal Modules for details of the mechanism.

Notice, by the way, that all element control panels are 'first click' — they do not need to be selected before accessing any of their controls. This is in general much more convenient for live performance, as you are likely to have a number of controls in different windows that you want to manipulate quickly. (It is a little harder to bring a window to the front — you may need to click on the title bar or border — but good prearrangement of the windows minimizes this. Also remember that you can always bring a hidden or minimized panel to the front by selecting 'Panel' from the element's menu. or double-clicking on the element.)




Marking and Splitting Events

A unique feature of the MusicWeaver is that MIDI events flowing along its paths may be "marked". There is one module, Splitter, that responds to these marks and directs the event onto one (or both, or neither) of its two output paths. (It would be quite feasible for these marks to trigger other actions, but to date nothing else has been implemented. The marks are exclusive to the MusicWeaver — they are not part of the MIDI protocol, and therefore not available to the outside environment.)

Desired marks (there are eight possible) are added to an event by 'Marker' elements (for example KeyRange) which can set a mark according to the values of the particular properties they monitor. An event may carry any subset of the eight. (Marks can only be set by these elements; a special ClearMarks element will get rid of them again.)

The Splitter's panel allows you to select which marks will affect the path taken by the event, and what the effect of each will be. Unmarked events, or those with no marks that match any selected in the Splitter, are passed directly to the 'Through' connector. You may choose to have an event with a particular mark sent out the 'Diverted' connector, duplicated to both paths, or blocked completely. You may also use a mark to inhibit all the above effects that would otherwise result from other marks . If marks request conflicting actions, there is a precedence order. [A Splitter never clears any marks either; this is only done, when needed, by the ClearMarks element.]

As you can see, it takes a pairing of a Marker with a Splitter to change the path of an event. If you want to divert events onto a path according to several different criteria, you can link different markers in a chain leading to a single splitter.

By default, a Marker module sets 'mark 1'. This can be changed through a menu in each marker's panel. (The other details of the panel of course depend on the marker's function.) Also by default, a Splitter diverts events with mark 1 and duplicates them if they have mark 2. (There is no default for either the 'Stop' or 'Pass' actions.) You can rearrange this as you desire via the checkboxes in the Splitter's panel.

Each Marker element can only set one of the marks, but successive Markers applied to the same event can be configured to set either the same or different marks. Each event may have as many of the marks as are useful. Several marks can be set first, before the events pass through a network of splitters to achieve all the desired separations.

There is another way of redirecting events, in this case entire event streams. Please refer to the section on the Path Switching in the Universal Modules documentation for details.



Event Timing

MIDI events within the MusicWeaver are each tagged with a time value. When an event is generated — by MidiLink or MidiPlay for example — this is initially just the "current time" (to the millisecond), but it can be modified by one of the "delay" elements — such as the MidiDelay module. This does not itself delay the event in any way — it simply changes its associated time value.

Note, however, that none of the MusicWeaver output modules — MidiLink, ProduceMidi or Synth — pay any attention to that time value: they always output events at the moment they arrive. If events have been 're-timed' by a delay to be output at some future time you must use a TimeSort element to actually hold them up until the intended output time. TimeSort accepts a stream of arbitrarily ordered MIDI events, sorts them according to their time value, and re-emits them when that time arrives, (It only affects "future time" events of course: if for some reason an event has been assigned a time earlier than "now", it is simply re-emitted immediately.)

The ability to delay events is mostly useful for things like "echoes". It takes at least two elements — a MidiDelay followed by a TimeSort — to achieve this, but you can feed several MidiDelays into a single TimeSort (via a Join element or some other merging filter), and its output will be suitably sorted. (Unlike most other elements, the output of a TimeSort can be connected back to its input to create a continuous loop [see Cautions]; however the only way to stop such a loop playing is to break the loop somehow, perhaps with a Marker/Splitter combination or a Switcher. A new element ShiftMarks may be useful for this.)

If you are merging streams of delayed events, there is one headache you may encounter. If more than one stream addresses the same notes in the same channel (as when you're generating an echo), note-ons and note-offs can interfere with each other, causing stuttering and stuck notes. A module included to protect against just this sort of problem is DeGlitch, which monitors a stream and ensures that note events are properly ordered.




MODULES

MIDI I/O:

MidiLink

The MidiLink module is the main route to the outside world. It can connect to any Haiku MIDI 'Producer' or 'Consumer' endpoints — corresponding either to external hardware or some other app that consumes or produces MIDI. It is a Multiconnector element, accepting a MusicWeaver MIDI stream on its 'MIDI Out' connector to send elsewhere, and passing a stream that arrives from outside to downstream elements on the 'From MIDI In' connector. (See 'Multiconnector Modules')

It has a control panel where you select the actual producer ("Source:") and consumer ("Dest:") to connect to. Each selector is a pop-up menu that will show all endpoints currently active. If you have MIDI hardware connected you should see names corresponding to the entries in the /dev/midi/… hierarchy. Endpoints supplied by other apps may have whatever name they think appropriate.

There can be as many MidiLink elements in a diagram as is useful. They can even connect to the same endpoints: input streams will be duplicated to all paths, and output will be merged. This module will only connect to already existng endpoints. If you want to create endpoints of your own for other apps to know about, use ProduceMidi and/or AcceptMidi elements. Note that, due to a quirk in Haiku which won't let an app see its own endpoints, you will not see these in MidiLink's selectors.

ProduceMidi

With ProduceMidi you can provide an endpoint which other apps can see, and through which you can send a MIDI stream to them. The text label you type in to its control panel (followed by <ENTER>) is published as a "MidiProducer" endpoint, that becomes globally visible — except, you will find, to any MidiLink elements in any MusicWeaver diagram. (This is an idiosyncracy of Haiku, that apps cannot see their own endpoints.)

If you do want to, say, connect two diagrams together, you can use ProduceMidi and AcceptMidi elements, and link them together with the PatchBay app (available on the Web if you don't have it).

If you enter a new label, the original endpoint will be deleted, and a new one opened. If you delete the text completely, the endpoint is simply closed. There is no system restriction against having more than one endpoint with the same name, but this is something to avoid.

The element is a 'Filter', so it passes on its input stream for other elements if desired.

AcceptMidi

AcceptMidi is the reverse of ProduceMidi (above) in that it provides a labelled consumer endpoint for other apps to see and send MIDI events to. It also has a control panel, where the text label entered will be published globally (except to the MusicWeaver) as a "MidiConsumer" endpoint. Label/endpoint behaviour is as for its companion.

It is of course a "Source" element, and has no input.

Synth

This is a Filter that opens an instance of the Haiku internal synth (fluidsynth) to play to your audio output from a MusicWeaver MIDI stream. There can be several separate Synth elements in a diagram, each with its own instrument-set (Soundfont). The instruments in the soundfont are what actually translate the MIDI into music.

Each instance of the Synth in a diagram must have an assigned Soundfont. This can be the same as or different from those assigned to other instances, but be aware that they are never shared — memory is used by each one. Most likely you will want a "General Midi" soundfont for playing the usual standard midifile, but there are many others with custom instrument selections available. For more on Soundfonts and where you can find them look here. As of alpha-3 Haiku includes a (smallish) default soundfont (/boot/system/data/synth/TimGM6mb.sf2) but there are many other excellent choices around. You can choose your own folder for any you decide to download. (This module, by the way, is completely independent of the MidiKit's BSynth, used by the MidiPlayer app — aside from them both using the fluidsynth library. BSynth uses only the default soundfont.)

You load a soundfont from the element's control panel. You can just drag a font file onto the control panel, or click on the 'Soundfont' button to open a File Panel from where you can select it. You can even type the pathname directly into the text field if that happens to be convenient.

The Volume slider below these adjusts fluidsynth's output level (for that element only). It is independent of other volume controls in the audio chain: you may need to adjust them all to ensure adequate undistorted final output.

At the bottom are Reverb and Chorus buttons that open sub-panels where the characteristics of these effects can be set. The actual amount of Reverb is normally determined by MIDI controller 91, and Chorus by 93, but the final decision as to whether this is so or not is up to the soundfont. Some, for instance, seem to force reverb fully on, or there may always be some reverb or chorus applied, whatever the actual controller settings.

Each of the sub-panels has four sliders that set the corresponding fluidsynth parameters. Unfortunately there doesn't seem to be any explicit documentation on these or what real-world values they might relate to. A rough guide follows, but you will want to experiment. The ranges of the sliders are the exact ranges that fluidsynth expects, and initial values in a freshly placed element are fluidsynth's own defaults.

Reverb: Chorus:

Whether you can play the synth 'live' from an external MIDI keyboard may be affected by your particular Haiku installation. Some audio chains may have a large latency between requesting a sound and hearing it, far too slow for live playing. The Synth element uses "Recording" mode to generate sound, though, so latency will not be increased by the glitches that currently occur in the Haiku scheduler. You may hear the occasional "snap", but you should be able to minimize this by ensuring that windows are not being updated while playing.


MidiPlay

MidiPlay is a MultiConnector module that will read standard Midifiles from disc and play them out onto a MusicWeaver path. You can specify as many files as you like to be played in sequence, either by selecting them through the 'Queue...' button, or by dragging them onto its control panel. It can also have an input connection ("Control") to allow triggering of play by an arriving packet; when enabled (and the current file is at its start), any arriving packet will initiate play. As of this release, you can also send midifile names as text packets to the Control input (more details below). Depending on the mode (below), all files in the queue may be played through automatically, or individually, as triggered. (A file is preloaded while the previous is playing, so there should be bo appreciable delay between files.)

It has a control panel with six buttons:

'Queue...' opens a standard File Panel where you can select a Midifile, or group of files, to be played. All the files you select will be queued to be played in turn. Play does not actually begin until you click PLAY. You can re-open the File Panel to select more files at any time, even while previous ones are playing. The file that is currently loaded is always shown in the box at the top (although unfortunately there is no way of viewing or editing the queue itself; hopefully it will gain an editable playlist sometime in the future).

'PLAY' starts the music playing (from the current point if it has been stopped). (It is a "touchbutton" that activates on press rather than release.) Its central pad turns blue while the sequence is actually playing.

'STOP' while music is playing halts the performance immediately, but does not try to silence things, so any notes playing at that moment will continue doing so.. Pressing PLAY will resume from that point. Clicking STOP a second time after play has stopped will send "All Notes Off', thus preventing ugly unstoppable tonality (but will not reset other things like controllers and program settings); you can still resume playing without much loss if you wish. Using STOP three times in succession will reset all controllers as well (but not the programs).

'Rewind' returns to the beginning of the file. It is only active when the music has been paused.

'Next' will skip the current piece in memory (stopping and silencing it if playing) and get the next in the queue. If the end is reached, it will return to the first in the queue. (Next never starts playback.)

'Clear' empties the queue, but does not affect the current file.

There are two popup menus at the bottom. On the right is one that determines how the queue will be played. "Play All" means to go through the entire queue without intervention. After the last file, play stops, but the first one will start again the next time PLAY is pressed. With "Play Each", one file will be played for each click of the PLAY button (or incoming trigger if enabled) but then the next one will be readied. "Play Single" never progresses to the next file, but rather re-cues the current file to the beginning ready for another trigger. "Continuous Play" will loop to the first file again and continue playing.

On the left, you can select whether to accept triggers on the 'Control' input ("Trig on Event") or inhibit them so only the PLAY button itself is active ("No Trigger"). "Play on Load" will start play immediately a new file is loaded (provided no midi is currently in playing position — this is probably a bug). Note, though, that if the queue is not empty, a loaded file will be placed at the end of the queue, and play will begin with the first in line!

At the very bottom of the panel is a checkbox "Include track with MIDI". If this is enabled, MidiPlay will pass on the track number of each event as recorded in the file. (Don't confuse this with the Channel number, which is an essential part of most MIDI events. The 'track' is a convenient division for the use of sequencers and the like.) The track of non-MIDI events is always passed.

In addition to MIDI events, MidiPlay outputs System Exclusive sequences, Tempo Changes, and MetaEvents that may appear in a midifile. Remember that most elements don't recognize these packets (usually passing them straight through with no other action). System Exclusives will be sent out through MidiLink and recorded by MidiFile or RePlay. Tempo Changes and MetaEvents are only recognized and recorded by MidiFile elements. All of them will always pass straight out the 'Through' connection of a Splitter — they can't be diverted.

You can specify files to be played via text packets sent to the Control input. The files will be loaded into the queue irrespective of the trigger mode setting, and will not trigger play when the setting is "Play on Event". If the mode is "Play on Load" the behaviour is the same as if the file was dropped or selected from the panel.

The simplest way to send a packet is from a StreamView element. You can either send a single line, or select a group of files to be added to the queue, each on its own line, and send that. If the MidiPlay element already knows which folder you want to play midifiles from (by having a file previously loaded), you can send just the name. Otherwise you can send a full pathname to select the folder as well. Other ways to supply the text might be from a file (via Getfile) or by running a program or script in a PipeStream.

When a configuration is saved, both the current file and the queue are noted and will be restored (if possible) when reloaded.


MidiFile

MidiFile will both play back and record standard midifiles. It can play files of either type 0 (Single-track) or type 1 (Multi-track), but can only record type 0. It is fully described on its own page, to save space here.

RePlay

The RePlay element is another way of recording and playing back MIDI and other data, but it uses its own specific format rather than that of the standard midifile. Its advantage is that it will also record the MusicWeaver 'marks' on an event, as well as the 'Director' packets used to control Weaver paths. It doesn't handle midifile metaevents, or the other packet types associated with various modules. It has its own description page.

Transformation:

MidiChannel

This Filter sets the MIDI channel of all events (except System Messages of course — they don't have a channel) that pass through it. It has a control panel with Radio buttons from which you can select the desired channel


Transpose

This Filter can shift all Note-On and Note-Off events that pass through it by up to three octaves up or down. The control panel has Radio Buttons to shift by octaves (+ or - 2) and a slider to shift in semitones by up to one octave in either direction. It also has a checkbox where you can select not to have events on the percussion channel 10 transposed; this is normally desirable to keep the drums sounding as intended.

Note that otherwise it affects all notes, whatever their channel. If you want different effects on different channels, use separate paths.


VelAdjust

This is a Filter that lets you adjust velocity characteristics of Note-On events.

The top slider in the control panel sets a threshold value that will first be subtracted from the original velocity; if the velocity was less than this, the result will be zero. Default is 0 (no cutoff).

The middle slider is a multiplier for velocity values; it is scaled in per cent, from '0' (all variation is removed) to '200' (values are doubled). Default is 100%.

The bottom slider is an offset that will be added to all velocities, ranging from 0 to 126 (so Note minimums range from '1' — softest — to '127' — loudest possible). Default is 0.

The threshold is subtracted first (with reset to zero if necessary), and then scaling is applied before the offset. The resultant value is adjusted to be within the range 1—127 if necessary. ('0' is not permitted, as it represents Note-Off.)

A VelAdjust element is a good way of adding "highlights" to notes above a certain volume. If you want to completely suppress soft notes, or divert loud ones to some other processing, use a VelMarker and suitable splitting.

NoteOff

This is a Filter that may find occasional use, for instance in conjunction with a delay (and a forked and rejoined path) to generate notes of a fixed length. It simply turns all arriving Note On events into Note-Offs (zero-velocity Note-Ons). All other events (including Note-Offs) are completely discarded. It has no control panel.


OneNote

This is another Filter with rather restricted uses. It sets the note value of all Note-On and Note-Off events to a selected value, according to the slider in its control panel (default 60 = 'Middle C'). The velocity value is not affected, and all other events are passed unchanged. It will probably be mainly useful in percussion tracks, where you may wish to reduce varying incoming events to a single sound.


NoteOffType

The MIDI Standard specifies two distinct kinds of 'Note Off' events. There is a special message type ('0') defined, but many keyboards generate and recognize a 'Note On' (type '1') with a zero velocity value for the purpose instead. It is possible that one or the other may not be recognized at all, so this module is provided to make the conversion if needed.

MusicWeaver modules have tended to use the 'zero-note-on' convention, so the default action of this module is to convert to 'true note off'. It has a control panel with a pop-up menu where you can select the inverse conversion if appropriate.


ValueAdjust

Similar to VelAdjust except that, rather than affecting only Note-On events, it will adjust all MIDI events that have a "value" byte i.e. Note-On, Note-Off, Individual- and Overall-Key-Pressure ("Aftertouch"), and Control-Change. It doesn't affect Program-Change, Pitch-Bend, or System events. The value of each event can be clipped with a threshold, then scaled by a multiplier, and a minimum offset added. It will allow a result of zero, which VelAdjust does not. Consequently you'll normally have to put it a path where all irrelevant events have been filtered out.

By default only the first event that reaches the upper or lower limiting value will be passed on; succeeding ones will be blocked until the value moves away from the limit again. A checkbox in its control panel can change this to allow it to pass all arriving events (still adjusted according to the sliders, of course).


Polyphony

A Filter module intended mainly for very specialized use. It restricts the total number of active notes on its path to a set limit (1..16). If a Note-On arrives when the maximum has been reached, the earliest note still sounding is ended with an extra Note-Off. Superfluous Note-Offs that arrive when the source itself ends that note are suppressed. The count of active notes is a total across all channels.

All non-note MIDI events are passed unchanged. You probably want to avoid 'sustain' events, as they will prevent notes turning off as intended.

The intended use of this module is to limit CPU saturation when using a software sound generator that needs a lot of computing power. Csound (a well-known cross-platform synthesis app), for instance, can chew up a lot of CPU, and may choke if you try to play too many notes at once. You might also find it useful, though, to ensure that a wind-instrument voice or the like does only emit one note at a time when you're playing it from a keyboard.

The control panel is fairly obvious. The single slider sets the maximum number of notes that can sound simultaneously. The RESET button is unlikely to be needed, but can be used to reset everything to the initial state if somehow notes get out of sync. (A System Reset event at the input will do the same.) a 'gold' background to the panel indicates that the set maximum has been reached, and notes will be dropped if more arrive.

Event Sources:

Program

This is a Source module that sends Program Change events to a MusicWeaver MIDI stream. It can precede these with Bank Select (Controller) events if required. The transmitted events are always on channel 1. To send to a different channel, link it to a following MIdiChannel element.

The major portion of the panel is a scrolling list of General MIDI Program Change values by name (and number). You can select any entry by clicking on it. By default the list is the General Midi set, but you can load other sets (below) if appropriate. Note that this module always specifies Program numbers as between 1 and 128. This seems to be the more common convention, but differs from the internal MIDI message range of 0 to 127. Some manufacturers use the latter, so you may have to do a mental conversion.

The requisite events are sent when you select a new Program from the list, but if you ever have to reselect the currently selected entry (you might have two preset Program elements that you wish to switch between, for example), use 'ReSend' (or you can double-click on the list item) — just clicking once on the currently selected item will have no effect.

When you load a Diagram file containing a Program element, any alternative list file is reloaded, and values are set as they were when the file was saved. When loading is complete, events appropriate to the selection are transmitted. Other parameters (such as channels) will have been properly set before this, so setup should be as expected. [In BeOS, you couldn't initialize its Synth in this way, because it wouldn't accept events before instruments were all loaded which could take some time. FluidSynth, though, will accept settings before it has actually loaded its instruments, so this works.]

If you are using synth hardware or a Soundfont that has more than the General Midi set of instruments, the default list is not really adequate, so the element will let you replace it with a more suitable list. You might also want to do this if you want quick access to a smaller set of instruments. A custom list can specify bank selection in addition to the Program Change itself (the default set does not send bank-select messages).

You load an alternative Program List file either by simply dragging its icon onto the element's control panel, or by clicking on the 'Get List' button to open a FilePanel and browse for it. It's simple text, so trying to load an inappropriate file may give you strange results! Use the 'Default List' button to restore the GM set. When you load a new list, any current Program selection will be lost.

The source of the alternative list is a text file with a simple format. You can see an example — "GS_extended.presets" — in the "Tables" sub-folder of the Weaver hierarchy. Each line of the file representing an instrument selection must begin with one, two, or three numbers of appropriate ranges; they should be separated with white space; initial white space is also OK. Following the numbers is the name/description of the patch. Each line will appear verbatim in the list. Lines that don't begin with a number are completely ignored, so they may be used as comments if desired. The following descriptions assume some knowledge of the actual MIDI events involved.

If there is just a single number, this is the Program number (range 1..128) that will be sent in a Program Change message when the item is selected. No Bank-Select message will be sent in this case. (The default instrument list is this way.)

If there are two numbers, the first is a Bank number (range 0..127), followed by the Program number (still 1..128!). In this condition, the Program Change event will be preceded by a CC#0 (Bank MSB) Controller event to select the specified bank. (No CC#32 (LSB) event is sent.)

With all three, the first is again the Bank MSB, the second is the LSB value, and the third is the Program. The element will first send a CC#0 for the MSB, then a CC#32 for the LSB, and finally the Program Change.

Be aware that the handling of Bank Select messages depends very much on the synth in use. Many respond only to CC#0 (MSB) and ignore CC#32, but others may need both to function properly. Yamaha XG, for instance, uses the LSB, but I think requires the MSB to be explicitly set to 0. Roland may need the LSB to be explicitly 0. You would think therefore that it would be safest to always set both controllers, but unfortunately fluidsynth doesn't think this way (!). You can use either CC#0 or CC#32 by itself to set a bank between 0 and 127, but if you send them both (in the order CC#0/CC#32 anyway) it combines them into one 14-bit number, which will mostly be nonsensical. (However, soundfonts specify the percussion set(s) as "bank 128", so you can actually access these directly on any channel by sending CC#0=1, CC$32=0.) [This may have changed in a later version than Haiku has.] If, for some reason, you should need to send only the LSB value, use '-1' in the MSB position.


Controller

This is a Source module that will send setting events for a desired MIDI Controller. Select the Controller number that you wish to affect from the scrolling list in its control panel, and the value you wish to set with the slider below.

Below the slider to the left is a popup menu that determines how events are sent. By default ('When Set') a single event is sent when the slider is moved to a new value and released. If 'Single' is selected, no event is sent automatically when the slider is changed: the 'SEND' button below must be used. (This button is always active in any case.) In the third 'Continuous' mode, events are sent continually while the slider is being moved (though not if the mouse button is depressed but stationary). Changing the controller number never sends an event by itself.

The five buttons at lower right are associated with the value-entry boxes immediately below each. When a button is clicked it will send its respective value to the current controller directly (but does not affect the slider value). Initially, the values are 0, 32, 64, 96, and 127, but may be changed to any desired integers in the range 0 to 127. (You will not be allowed to enter a value outside this range.) The currently-set values are saved with the configuration.

When an event is sent, the relevant button remains highlighted to indicate the fact. If an event results from slider movement, the SEND button gets the highlight.

By default, the Controller names provided in the list are as defined in the current MIDI standard. However, most setups won't conform exactly to the standard — missing some, and perhaps adding others that are not defined there (notice the many blanks!). Optionally, therefore, you can provide your own list of relevant Controllers and their numbers, either globally or individually by element.

A variant global list is supplied by a file named "Controller.list" in the folder "Tables" at the top level of the Weaver hierarchy. The global file is only read when the first Controller element is placed, so all elements share the same list, and changes won't show up until you have removed all Controllers from all running diagrams.

An individual list is loaded into an element either by dragging the list file's icon onto the element's control panel, or by opening a FilePanel with the 'Get List' button and browsing for it. The 'Default List' button restores the current global set — the built-in default set if no global file exists.

In all cases, the file is just plain text, with the first non-blank item on each line being the Controller number, followed by any desired name and description. The line will be copied verbatim into the list, and associated with that number. (Any lines not in this form will be ignored and could be used as comments if desired.) An example is provided as "Controller.list SAMPLE" in the above folder.

As usual, this module only generates events on MIDI channel 1. To affect other channels follow it with a MIdiChannel element. As with the Program element, when it is in a configuration file that is loaded, it sends the appropriate Control Change after loading is complete.


SetRPN

In addition to the regular set of MIDI 'Controllers', your synth may accept 'Registered Parameter Numbers' ('RPNs'). These are actually supplied by a suitable sequence of Controller events, but they would be tedious to generate from standard MusicWeaver Controller elements. A separate module is therefore provided for RPNs.

The control panel for a SetRPN element has similar form to a Controller element, except that it doesn't need a scrolling list, and there are only three buttons, with fixed values. Use it as described in that section. (The default mode here, however, is 'Single', so normally nothing gets sent until the 'SEND' button is activated. ) Note, though, that where a Controller element would send one event, SetRPN will send five! This means that you will not want to use 'Continuous' mode too extensively...

The initial position of the slider is set appropriately when you select a particular RPN — i.e. for 'Fine-' and 'Coarse Tuning' it is set central, for the others it is set to 0. As with the Controller, sending an event leaves the relevant button highlighted.


PitchBend

This is a Source module that generates Pitch Bend events as the slider in its control panel is moved. The slider knob returns to zero automatically (and instantaneously) when it is released.

Earlier versions of this module only generated the high 7-bits of the pitchbend value. It now drives the full 14-bits.

One trick that may be useful: if you resize the window, the slider resizes too (in both directions). This means that you can make a very 'thick' slider track that is easy to grab in a hurry!


SysReset

This may be a useful element to include in a configuration, for those occasions when playing a Midifile has left your synth in an indeterminate state or something. It simply sends a MIDI System Reset event when the button in its Control Panel is clicked. This should reset the entire state of any MIDI hardware that receives it back to its power-up condition. However, be aware that many devices do not respond to this event at all (it is often considered unsafe…).


MasterVolume

This uses a Universal System Exclusive message to set the overall volume of all channels, sent each time the slider in its panel is moved and released. The setting is superimposed on the more local "Channel Volume" and "Expression" Controller settings. (Some older MIDI hardware might not recognize this message, but most do.)

SysExGen

This element accepts text input packets (from a StreamView or ReadFile element) that specify desired System Exclusive sequences, and generates actual sequences to match. The format of the text input is a series of numeric byte values (0-7F hex) separated by white space, with the entire sequence enclosed in square brackets. In other words, exactly what is output by SysExMon above.

In addition to hex values, though, you can use decimal ones (0-127), by prefixing an 'n' to the first. The radix will remain decimal until a prefixed 'x' is encountered. The header and terminator bytes that are part of a transmitted SysEx sequence (actually 0xF0 and 0xF7) should not be included — they are represented here by the enclosing brackets. (Within MusicWeaver, by the way, a SysEx sequence is not processed as a set of MIDI events, but rather as a single packet of its own type.)

As a specific example, the Universal System Exclusive Message "Turn GM On" (bytes actually sent: F0, 7E, 7F, 09, 01, F7) can be generated by passing in the text: "[7E 7F 9 1]".

Metronome

As you would expect, this module provides a steady beat at a desired rate, which can be set either in Beats-per-Minute or Milliseconds. It also has the ability to adjust to incoming Tempo Change messages from a MidiFile element, or even to attempt to follow the beat of an incoming midi stream. The success of this last depends strongly on how rhythmic the stream actually is, and you may have to play with the settings before getting a reasonable result.

A tick rate is set by typing in a value, rather than by slider, to allow sufficient precision. At the top of the Control Panel are the two alternative text entry fields ("Beats/Min" and "Interval"). Entering a value in one automatically adjusts the other. You must terminate the entry with the Enter key — nothing gets updated until you do.

Below the text fields are the obvious RUN and STOP buttons, which are always enabled. As in RePlay, they are "touch buttons" that are activated when pressed, not released, to give more convenient precise control. The RUN button goes blue while the element is ticking. If you click RUN while the element is already running, the ticks will get resynchronized to the button-press (and the rate will get reset — see below).

Next down is a popup selector that sets the mode. In the default Fixed mode, only the rate setting and the RUN/STOP buttons have any effect. (The sliders below remain enabled so you can preset them, but have no effect.) When set to Trig Start, the metronome will be started by the first Note-On MIDI event to arrive at its input connector; other types of event are ignored. Again, the sliders are not effective. The other two modes, Entrain and Unforced, attempt to adjust to an incoming beat, and use the sliders to do so, as explained below.

A midifile may contain Tempo Change events (there is usually at least one at the very beginning), and MidiFile passes these out. In both Trig Start and Entrain modes, but not in the other two, the Metronome will adjust itself — and the displayed rate values — when one arrives at its input. This can result in excellent sync with the beat of the file, even if the piece varies in tempo. The only difference between Entrain and Unforced is that the latter is not affected by Tempo Change messages, only responding to incoming notes.

The way that the Metronome attempts to follow the "beat" of an incoming MIDI stream should definitely be classed as experimental and first-effort. I'm hoping to find ways to improve it — particularly its tendency to speed up indefinitely when the incoming tempo slows down! The algorithm is really pretty dim. It simply compares each tick with the closest Note-On event to arrive, and adjusts its parameters according to the difference. It pays no attention to other factors, such as the strength of the note. The sliders control how big a discrepancy it can respond to, and how much it tweaks either the next interval or the overall rate.

The Capture Range slider sets how far before or after the scheduled beat a note can be to alter anything. Its value is in terms of percentage of the current beat interval (actual, not as set in the entry fields). If it is small, only notes that occur very close to the expected beat will be effective. If it is full 50%, every note will get captured! In all cases, the actual offset of the note from the beat is the base for the effect of the other two sliders.

The Tick Sensitivity slider determines by what percentage of the above offset the next interval will be changed. It only controls the tick that follows; it has no long-term effect.

The Rate Sensitivity slider causes changes to the overall tick-rate itself, again by a percentage of the offset. It does not affect the entered rate values; instead the current computed rate is shown (as msec) to the right of the popup selector, above the sliders. The entered rate is restored every time the element is restarted, either by directly clicking the RUN button (which also restarts the ticking immediately) or by clicking STOP and letting the next Note-On resynchronize things.

The Ticks output of the element is a "metronome click" (note 33) on rhythm channel 10. (Each tick is a Note-On immediately followed by a Note-Off, which should always work for a "click".) If you want something else for your beat, use a Transpose and/or other elements to get what suits you. The Sync input to the element is also passed through to an output as usual.


Drawbars

This module was really written for my own personal convenience, but is included in the suite in case others might find some use. It is intended to emulate the sets of nine "drawbars" on a Hammond organ, sending out MIDI Controller messages when a slider is moved. Each "bar" has its own controller number, by default the set CC20..CC28, and has a possibly limited range of positions (0..8 by default, emulating an actual Hammond's control).

The vertical 'Drawbars' in its control panel have '0' at the top (the reverse of a normal slider, but again emulating its real counterpart). The pop-up selector at bottom left determines whether output is only when the mouse is released after moving a slider (the default) or continuously while a slider is being moved. (Non-default is actually more realistic.) Only the drawbar being moved sends MIDI, except for the very first use when all the initial drawbar settings are sent at once. (This avoids confusion as to which actual drawbars have been transmitted.) Otherwise, use the button at bottom right to simultaneously transmit all nine values as displayed.

The original version of this module had fixed parameters (determined by what I needed at the time). Now, the base of the CC set, the number of steps between a 'fully-closed' and 'fully-open' drawbar, and the corresponding minimum and maximum output values, are all user-settable parameters. These controls are normally hidden in a default-sized panel — drag the right side of the panel larger to expose them.


Mark & Split:

Splitter

The Splitter is a 'Multiconnector' Module with two outputs: 'Through', and Diverted. It is used to determine which of the two paths arriving MIDI events will be sent out on. (see Marking and Splitting Events) The determination is made on the basis of 'marks' that may be set on the event. (Marks can only be set on MIDI events. Other type of packets and items, including MIDI-related ones such as System Exclusive and Tempo, do not know about them. Non-MIDI data is always simply passed on out the 'Through' connector.) Its panel has checkboxes that can be used to control its behaviour.

There are eight possible marks that may be attached to an event, and four possible actions a Splitter may take if it is set to respond to it. If the box in the 'Dupe:' column of the panel is checked for that mark, the event will be sent to both output paths; if the box in the 'Split:' column is checked, the event will go out only on the 'Diverted' path; if the mark is in the 'Stop' column, the event will be removed from the stream at that point. If there is no match between any mark and checkbox, or there is a match with a selection in the 'Pass' column, the event continues on along the 'Through' path. The initial default is that mark 1 causes a Split, and mark 2 causes a Dupe; other marks are initially ignored.

You can set as many of the marks on a single event as you like, and you can check any desired set of marks in the splitter (although you can only choose a single column for each). If an event is marked (with multiple marks) for more than one action, Dupe takes precedence over Split, Stop takes precedence over both, and Pass overrides them all.

[Note that a Splitter does not clear any marks. Use the 'ClearMarks'' element for this.]


ClearMarks

The function of this module is simply to clear marks that may have been previously set on an event. (See Marking and Splitting Events) You can select those you wish cleared in its control panel. By default, all marks will be cleared.


ChanMarker

This Marker (Filter) can set a mark on all events on a particular channel or set of channels. (see Marking and Splitting Events) Checkboxes in the panel control the selection. Like all marker modules, the mark applied is determined from a drop-down menu in its panel.

This latest version also indicates in its display which channels are, or have been, active. An active channel is highlighted in yellow. A menu option selects whether all channel events are indicated — in which case the flag remains until reset — or whether only Note-Ons and Note-Offs flip the flag. In the latter case it doesn't try to keep track of individual notes, only the total excess of Ons over Offs on that channel. Another menu option will reset the display (but does not effect marking).

You would use this element, together with a suitably set-up following Splitter to divert a channel for special processing, or simply to mute it. You can 'solo' a channel by having it diverted by the Splitter, and ignoring everything on the latter's 'Through' output.


KeyMarker

This Marker can mark selected notes of the scale. Any subset of the twelve notes of the octave may be marked; this setting then applies to all octaves.


KeyRange

This module can mark a range of notes for splitting. You can select either to mark events that are within the range (inclusive of the set limits), or those that are strictly outside it.

The 'Low Limit' slider in its control panel sets the lowest note that will be in the range; "High Limit' determines the highest. Both limits are inclusive. If you set 'High' less than 'Low', all notes are in range!)

A drop down menu next to the usual Mark selection at the top of the panel determines whether notes within or outside the selected range are marked (default is within). The ranges are MIDI note numbers, of course, with '60' being Middle-C.


MsgMarker

This module can mark individual types of MIDI Events ("Messages"). These types are 'Note-On', 'Note-Off', 'Program Change', 'Controller', 'Poly Afterouch', 'Channel Aftertouch', 'Pitch Bend', and 'System'. (Some of these are abbreviated for space in the panel, and the order there is numerically correct.)

Note-On events with velocity zero are considered by this module to be Note-Off events (a usual convention). So you needn't be concerned which convention is actually generated by your keyboard or other source.


VelMarker

This module will mark all Note-On events that exceed a threshold velocity. A slider in its control panel sets this threshold. When a Note-Off to match a marked Note-On arrives (same note and channel), it is tagged with the same mark, so that it will be diverted by subsequent switching in the same way that the original Note-On was.

Proper operation of this element does presume that On and Off events are properly ordered. If you have merged MIDI streams as input, or there is any other reason to doubt this, it is safest to precede it with a DeGlitch element.


ControlMarker

This module lets you mark all events targetted at a selected set of MIDI Controllers — for example 'Sustain Pedal' events (Controller 64). You select the desired Controllers by clicking on them in the list displayed in its Control Panel. Holding down the ALT ('CMD') key while clicking lets you add more than one selection (or remove it if it is already selected); the SHIFT key will enable selecting a range. [See the Haiku User's Guide, under "Shortcuts and Key Combinations".] The number of controllers currently selected is shown at the bottom of the panel.

(An earlier version of the module used a slider to select a single controller number. This module is backward-compatible with configurations that were built using that version, though you will need to resize the panel.)

As with other marker modules, the specific mark to be applied is determined by a drop-down menu.


ValueRange & IndexRange

These two modules can be discussed together. They let you mark rather less specific attributes of MIDI events than most of the other modules. Because the meaning of these attributes is a function of the type of event, you will generally want to pre-restrict the events you pass to these elements to be only those of interest.

A quick word on the structure of MIDI events. A single event is represented as one to three bytes. The first specifies the type of event (and the channel, if appropriate). The second — except for single-byte 'system' events — is an 'index' as to the exact target of the event... the note to be played, the controller to be addressed, or the program-number to be set. etc. The third, where present, always represents a 'value' — note velocity, control setting, and so on. (Pitch Bend is an exception — the second and third bytes are combined into a value of higher precision.) If you're not already familiar with these technicalities, please read up on it in one of the many books on the subject.

A ValueRange element will mark all three-byte events (except Pitch Bend) according to their third, 'value', byte. IndexRange does the same for the second byte of two- and three-byte events (again ignoring Pitch Bend). (The first byte can of course be handled by a suitable combination of MsgMarker and ChanMarker elements.)

As with other range markers, the specific mark is selected from a drop-down menu, as is whether marks should be set within or outside the selected range. Range is inclusive of the set slider positions (Low should be less than or equal to High!).


ChordMarker

With a ChordMarker element you can mark note-on events that complete a specified chord, and the note-off events that terminate it. (Neither the order nor transposition of notes is considered — only that all specified notes of the scale are active.) In addition it may have use in showing the notes that are playing (although octave cannot be distinguished). Like most other filters in the suite, it pays no attention to channel (except when matching note-on/offs as described in the next paragraph) — all arriving note events are considered.

There are actually two distinct marks that the element may set on an event. The note-on that completes a chord will always get tagged with both, but different criteria govern which note-off events get marked with each. The first of the two always marks the note-off event that exactly matches (in note-number and channel) the one that completed the chord (irrespective of where in the sequence the key is released). The other tags whichever note-off is first to end the full chord; this is very likely to not be the same note that completed the chord, so you should not expect matching on/off pairs based on this mark.

The control panel of a ChordMarker element comprises a stylized octave of a 'keyboard' on a grey surround. Arriving notes highlight the corresponding 'key' in the window. (It does keep track of note-ons versus note-offs — the highlight will not be removed until the note-offs match the note-ons. You should therefore be careful to ensure that only 'rational' MIDI sequences, with matching on/off events, are passed to the element.)

Each key has a checkbox: select the ones you wish to make up the chord to be detected. (Each element can only react to one chord.) When a complete matching chord is formed — i.e. when note-ons for each selected note have been received, without any corresponding note-offs to cancel them — the panel background turns green, and remains so until the full chord is no longer maintained.

The menubar at the top of the panel has two drop-down menus. The left-hand one selects the first mark-number (the one that tags matching note-on/note-off events as explained above), and the right hand one determines the second (to mark 'chord-on' and 'chord-off')

The uses of this module are likely to be a bit esoteric, but for example you could arrange for a particular chord to trigger a path change (through a Splitter|TriggerSwitch|Switcher chain or similar). Or whatever you might think of...


ShiftMarks

This element shifts the marks on an event up by one. It has a fairly specific intended use: to manage a loop (though you aren't discouraged fron thinking of others...).

Loops aren't that often wanted in the MusicWeaver, but they can come in handy for generating an echo, for example. You do need to be careful when using them, though [see Cautions]. Without something to break it, a loop will usually be endless. ShiftMarks, together with a Splitter set to stop or divert the looped event on a given mark, can provide this break (after up to 8 iterations). Or you can do more than just break the loop — do different processing on successive iterations perhaps.

The slider at the top of the control panel sets the range of marks (always starting at '1') that will be shifted. Any above the range will be left alone. If "Recycle" is not checked, a mark shifted out of the range is lost; if it is checked, each mark going out of range sets mark 1 again, so the initial pattern cycles. The "Prime" checkbox causes mark 1 to be set if the range is empty on entry.


Event Timing Control:

TimeSort

This element re-orders incoming events according to their time-value [see Event Timing]. It is a multiconnector element, with one input (the original stream) and two outputs (a 'Through' output for the original, and a 'Sorted' copy).. Events are sent out the 'Sorted' connector at their specified time (or immediately if this moment has already passed). It has no control panel.

Used by itself, it will have no effect, as all events by default have "now" as their time value. One or more MidiDelay elements must precede it to usefully alter this. If you are messing with event timing to produce multiple echoes for example, you may also need a following DeGlitch element to prevent ugly note cut-offs.


MidiDelay

This adds a specified time interval (in milliseconds) to the time value of an event [see Event Timing]. This has no effect on its own (as output modules ignore the time value); the event should (eventually) be passed to a TimeSort element to transmit it at the desired time.

The slider in the element's panel represents delay in milliseconds, up to one second. If you need a longer delay, you can concatenate MidiDelay elements to reach the desired value (within reason).


RanDelay

This element is similar to MidiDelay, except that the delay applied is random withing a set range, rather than fixed. Used judiciously, it might add a bit more "human" feel to a stream. As with MidiDelay, it requires a following TimeSort to actually provide the delay.

The slider in its panel sets the maximum delay it will apply, in the range 0-1000msec. Be careful, though: it randomly delays all MIDI events that pass through it; if the set range is too large, you might for instance get a note-off occurring before its note-on! (For complete safety, you might want a DeGlitch element following the TimeSort.)

DeGlitch

This is a special-purpose module that needs a bit of explaining. It should be used when you have merging streams of MIDI note events that might interfere with each other.

Normally a MIDI stream (from a keyboard or whatever) is nicely ordered, with each note being turned on by a Note-On event, and off by a Note-Off. If the same note (on the same channel) sounds twice, the sequence is always On-Off-On-Off, because a key must be released before it can be struck again. However, if you have more than one stream that can possibly activate the same note, this order can be lost — a problem often known as "ReTriggering". The particular difficulty is that if there is a second Note-On that arrives just before the Note-Off that corresponds to the first Note-On, that second note gets abruptly cut off at that point (and its Note-Off is ignored) — undoubtedly not what was intended.

For example, if you try to use a MidiDelay/TimeSort pair to create an 'echo' (on a single channel) you are likely to get such ugly cut-offs on any sustained notes. One solution is to route the echo to a separate channel, but this wastes a channel if you actually want the same voice. A better solution is to put a DeGlitch element in the merged stream.

What this element does is to keep track of the number of Note-Ons and Note-Offs. It inserts an extra Note-Off before every "unmatched" Note-On, and "swallows" each corresponding Note-Off that actually arrives, only passing on the final one that "balances" the complete sequence. The result is a proper On-Off-On-Off....On-Off sequence that sounds as intended.

Conversely, if a Note-Off arrives without a preceding matching Note-On, it will be removed from the stream, and no corresponding Note-On will be allowed through until the (incoming) events once again balance. In other words, an On that is later than its Off will never sound.

Each channel is tracked separately, so you can feed a complete MIDI sequence through it if you like. It only pays attention to Note events, not others — such as the sustain pedal — that might also suffer from Retriggering. These, though, don't usually need delaying and can be diverted to pass around the delay section of the diagram.

The element has a Control Panel with a RESET button, which could be needed if a stream is very badly formed, or is interrupted. Also the panel turns red while there are any unbalanced events.

Although it keeps track of both "kinds" of Note-Off events (true status-0 events, and Note-Ons with zero velocity), it only inserts the latter, assuming that most Synthesizers respond to this. If Ons and Offs arriving at the module are in fact widely unbalanced, the element could eventually lose track. (It has a finite range over which it can count.) The RESET button in its Control Panel will allow it to start over cleanly. It is also reset by any arriving SysReset event. Further, if a channel "All Notes Off" or "All Sounds Off" message is received, only that channel will be reset.


ChordPacker

When you play a chord on a keyboard, no matter how precise you try to be, none of the notes are truly simultaneous. This is a nuisance for modules that attempt to extract chord data, such as Analyze and KeySig, as all the intermediate combinations will be registered as separate chords. The ChordPacker module attempts to reduce this by adjusting the timestamps of midi events arriving within a specified short timespan to be exactly the same. It has to delay all events by the size of that time-window, so it must be followed by a TimeSort element to do its job. If the source is a live performance, you will probably want this and the analysis elements on a branch path from that driving the synth, so you don't hear the delay.

Its Control Panel has a slider that sets the size of the window in milliseconds (up to 200). It delays each event by that window time, unless it occurs within that window after a previous event, in which case its (delayed) timestamp is set to match that.


Note and Chord Analysis:

KeyTrack

A KeyTrack element keeps track of the keys that are apparently sounding (Note-Ons exceeding Note-Offs, disregarding channel), and adds this information to all midi packets passing through. It is not affected by other MIDI messages — the sustain pedal in particular. It actually adds two items: Chord Info, and the full set of Keys Down (out of the full 128 range). Chord Info is needed by the Analyze, KeySig, and ChordSelect modules. Keys Down is currently only used by the new Notator. Be careful: if the arriving MIDI stream includes Channel-10 'percussion' events, they will almost certainly interfere with expectations, as they aren't part of the harmony. Usually you will want to block or divert Channel-10 from the input to the element. See Packets and Items for more on these packets. [Caution: There is currently a bug in that, if these items are once added by inserting a KeyTrack in a path, they will not be removed if the KeyTrack is! This could cause confusion...]

The element has a Control Panel that shows the keys currently seen as active (compressed into one octave). There is a RESET item in the Options menu that can be used to clear the state if, for example, a piece has been interrupted while notes are sounding. It is also cleared when a midi SysReset — or 'All-Sounds-Off' or 'All-Notes-Off' — message is received.


Analyze

This uses the information provided by a preceding KeyTrack element to keep a count of all the apparent chords for each root note in a piece. As noted in Packets and Items, a "chord" is often ambiguous, so the information collected has some limitations, but it can be quite useful. The element doesn't try to count every possible chord type, and lumps some together, but the common ones are shown.

It has a large Control Panel where all the counts are displayed. The Options menu has a RESET item to clear these, plus an option to Output Data as a text stream to be sent presumably to a WriteFile element for storage, and a Discard Subchords toggle. If this last is set, any 'intermediate' chord that is immediately superseded by one formed by adding notes will not be counted. If not set, every chord change is counted separately.

In the largest section of the panel, each row represents a possible root note. The Notes column is a count of total notes, whether part of a chord or not — each Note-On is counted. The columns following this are counts of the various chord types. At the right of a row for the relevant root, a short specification of the latest chord will be displayed. Some of these types are ambiguous or don't actually have a defined root (augmented, diminished and other miscellaneous chords); these will just get displayed in an arbitrary row.

The Major column counts major triads, inverted or not. These are all unambiguous three-note chords, so the count is true.

The Minor column similarly counts all minor triads.

The Seventh column totals the (four-note) (Minor) Seventh chords with that root. Remember that the common 'seventh' chord that is most used in pieces of a given key is the one that is rooted on the 'dominant' (fifth note) of that scale. So for instance when playing in the key of C, most sevenths are likely to show up in the G row (G B D F).

The Maj-x column counts up all the various other chords that are generally considered 'major'. Specifically, it totals 'Third', 'Fifth', and 'Major Seventh' (two-note) chords. These are all ambiguous. It only looks for fifths, not fourths, so it will for instance always call a 'C fourth' an 'F fifth'. Similarly if the interval is actually a 'minor sixth', it will record it as a (major) 'third', and a 'minor second' is a 'major seventh'.

The Min-x column similarly counts some miscellaneous chords that I've somewhat cavalierly labelled 'minor': two-note 'Minor Third', 'Diminished Fifth', and 'Minor Seventh', and the three-note 'Diminished Triad'. Only the first and third of these are truly minor, but it seemed reasonable to count them all together. Again, they're all two-note except the last, so there's lots of ambiguity.

There are two types of chord for which there is no sensible distinguishable root, or rather every one of their notes could be the root, so these get separate counters in sections of the lower panel. A four-note Diminished chord (in all inversions) has only three variants, so each of these is totalled in the right hand box. A three-note Augmented one has four, tracked in the left hand one.

Any other three or four note chord, aside from Diminished or Augmented (below), gets dumped into the "Other Misc:" box at bottom right without regard to any 'root'.


KeySig

This module makes an attempt to guess the key of a piece. Sometimes it even gets it right (:-/). It takes into account both the midi event stream itself and chord information supplied by a preceding KeyTrack element if present [it should be...]. It uses Bayesian estimation to make its guesses based on a likelihood table; a default one is built in, but you can load others for experimentation (In fact the whole thing is pretty experimental!). It is a filter element that only displays its results in its Control Panel; its conclusions cannot be output anywhere. [Remember that drum events on Channel 10 will confuse things badly. Make sure they're blocked before the preceding KeyTrack element can see them.]

Its panel has two "best guess" bars at the top. The topmost (yellow) shows its current, continuously revised Bayesian estimate — reflecting the highest numerical value seen in the table below (typically it can fluctuate quite wildly). The lower green one indicates the most favoured key over the whole piece, and how consistently it has been maintained.

The table entries in the lower panel show the complete set of estimated probabilities for all possible major and (natural) minor keys. The highest current probability is flagged with a marker, as well as being echoed visually in the top bargraph.

The left Options menu has the usual RESET item, plus three toggle options. Setting Slow Update causes the display to be updated by timer rather than at every packet; this may help when the CPU is heavily loaded, as a lot of formatted text is involved. Use Notes and Use Chords, both set by default, are probably self-evident: setting the first means that the notes in the original midi stream contribute to the computation, the second uses the chord information from KeyTrack. Sometimes it may be interesting to unset one or the other to see what changes. (Unsetting both is not very helpful — unless you want to freeze the results.)

The File menu lets you change the likelihood tables. Read Likelihoods opens a file panel where you can select a likelihood file to load. Two examples are provided in the subfolder 'Tables': 'KeySig_LHood_0' is the default set initially provided within the module, 'KeySig_LHood_Slow' is a set that might cause it to be less ready to change its mind on each note. Restore Defaults puts back the original set.

A likelihood file is just a text file of numerical values, in a very specific order. Formatting of the numbers is unimportant (except for clarity) as long as they are separated by some white space. They can be floating point, but as they are likelihoods rather than probabilities, it is usually clearer to use integers as large as needed. Other characters (like comments!) are not allowed.

The values are in a series of groups of 24 (two subgroups of 12). Each group represents how it evaluates a given type of event — single notes, major triads, minor triads, diminished triads, and dominant sevenths. The first 12 are likelihoods for major scales, the second set are for minor. All scales are treated equivalently, so only one set of likelihoods is needed. The position of a value within a subgroup represents the offset of the note or chord-root from the tonic of the scale being evaluated; the value is the relative likelihood of that event occurring given that the scale is actually that. Likelihoods are only compared within a group (of 24); scaling is otherwise arbitrary. [Apologies for this convoluted exposition, but Bayesian logic can be hard to explain!]

As an example, take the first group from 'KeySig_LHood_0', which evaluates how likely single notes are to occur in a piece of a given key. The first subgroup of 12, handling major scales, is:
    555 1 172 55 143 333 1 444 11 111 55 233
Taking the C major scale as an example, we can see that the first value (at 'offset 0') shows that we think the note 'C' has a strong likelihood of appearing in that key. The next value, for 'C#', has a very low (but not zero) likelihood. 'D' (offset 2) has a good likelihood, and so do 'E' (offset 4), 'F' (offset 5), 'G' (offset 7), and so on. If we are considering, say, the G major scale, the thinking is the same, but now offset 0 is 'G', offset 1 is 'G#' etc.

The next line, for the minor scale, is almost the same, except that the relevant offsets of the minor scale now take the place of the major ones:
    555 1 172 143 55 333 1 444 11 81 233 55

The other groups in the file, for chords, are filled similarly (remembering that their scaling is independent of other groups). Thus the first entry for major triads shows the (high) likelihood of a C-major chord appearing in a piece in C. C#-major is not likely to show up, so it gets a low value. Most minor chords are less likely to show up in a major piece, so they get lower values. The minor-triad group is just about the reverse, with minor chords being likely, major ones not. The remaining groups, for diminished and seventh chords, are very empty, because only specific instances are likely to occur in a given scale.

The above likelihoods are completely empirical, arrived at by looking at counts from typical pieces, and deciding what seemed reasonable. One point to note: a "zero" likelihood really means that that event is impossible, so if it actually occurs bad things (like divide by zero) would ensue! The algorithm actually always replaces zero likelihoods and probabilities with very small non-zero values. Zero is therefore safe to use as a shorthand for "highly unlikely". A file need not actually contain all the groups; if later ones are omitted, they will be filled with the default values.


Notator

This element's panel shows the currently active notes as a "chord" in standard staff notation. It requires a preceding KeyTrack in the path to provide the set of keys currently down. It has no notion of time, sequence, or 'hand', so notes are just shown in a column without stems, but sharps, flats and naturals are added when appropriate.

A menu is provided to set the Key Signature, which will be displayed as usual to the right of the clef signs. Accidentals on the displayed notes will adjust appropriately. A second menu lets you select whether both treble and bass clefs will be shown (separated only by middle-C) or just one or the other. Notes outside the clefs will always be shown with suitable ledger lines. A 'RESET' option is available if notes are left displayed after an interruption.


ChordSelect

This is a complex module, but is fun to play with. Which is what you'll have to do for now! Apologies for lack of description here... See the Help file for brief details.


MidiCounter

This simply counts the different types of MIDI messages arriving on its input, and displays the counts in its Control Panel. The Options menu has a RESET item that clears the counts.


MIDI to Text:

MidiMon

For each MIDI event that arrives at this multiconnector's input, it outputs a text packet briefly describing the event. This must be passed on to an element that can handle text, such as 'StreamView'. (No other MusicWeaver modules are aware of this kind of data.) It will also show any 'DIRECTOR' packets that arrive on its input, and any midifile metaevent and track information that is present.

There is one input — the data stream. The first of the two outputs is the resulting text packets, the other is a pass-through of the incoming data.

For each MIDI event, the output line begins with the event time in milliseconds. (This is the time recorded in the packet, not the time it actually arrives at the monitor.) For any Channel Event, the next field on the line is the channel (1..16), followed by the type of the event. The rest of the information on the line depends on this type.

For a 'Controller', you get the controller number with its associated General Midi function if any, and then the event's value. On a 'Program Change', you get its number (range 0..127) and GM name. [Note that this is internal MIDI code numbering — user numbering, as in the "Program" module, more usually goes from 1..128.] 'Note On' and 'Note Off' show the note number (with the key name) and its 'velocity'; it distinguishes true Note-Off events from the zero-velocity Note-Ons often used. Other events similarly are displayed in appropriate form. System Messages obviously have no channel.

Tempo Change (Meta)Events generated by a MidiFile module are shown as well. These have the usual timestamp, followed by the tempo setting, first in "Beats Per Minute" and then the actual interval-per-quarter-note value supplied (shown as 'seconds' for convenience, rather than the microseconds used internally).

MidiMon also handles System Exclusive and (Midifile) 'Meta Event' sequences, but gives only a brief sketch. The first item is again the time, but for System Exclusive this is followed by 'SysEx size' and the (decimal) number of bytes in the sequence. The first and last bytes only of the sequence are then listed, in hexadecimal and then decimal. Obviously this is not much use for any detailed understanding of the sequence — it is really only intended to indicate that such a sequence has occurred. Meta Events (other than Tempo Change) are shown similarly, but only the hexadecimal type code and the size are displayed. If it is a 'Text' metaevent, the first few characters will be shown as well; no decoding of the various other types is done.

As "Chord" descriptions are available from the KeyTrack module, MidiMon shows these as well. These are always associated with at least one actual MIDI event, so the output line for the chord doesn't have a timestamp. It just shows the name of the chord and its root note. [MidiMon will fail to show any chord if, for example, all the actual notes have been split away!]

If the stream is from a MidiFile or MidiPlay element, it will also contain indications of the file's Track that originally held the data, depending on a setting in the source element.

MidiMon also recognizes 'Director' events (see e.g. GamePort). These do not have a timestamp, so are simply labelled 'DIRECTOR', followed by either 'Switch' or 'Control n', depending on the type. The bits set in a Switch message are shown, and for a Control message it presents the 'Index' and 'Value'. The 'n' following 'Control' indicates the subtype: '1' is another form of (single-bit) Switch, '2' is a 'Parameter' event (generated by GamePort and used by D_PitchBend etc. (No other types are yet defined.)

SysExMon

This module is specialized to show the contents of any System Exclusive message that may be transmitted by a MidiFile element (or a RePlay, or generated by an external device). For each such message that arrives at this multiconnector's input, it outputs a text packet listing its contents as hex byte values. This output must be passed on to an element that can handle text, such as 'StreamView'.

The string of bytes represents exactly what would be sent to any hardware expecting the message, except that the actual MIDI sequence always begins with a header byte with value 0xF0 and terminates with 0xF7. These two bytes are represented by opening and closing square brackets in this module's output. Lines are kept to a maximum of ten values, so a message can extend over several lines.

[Apparently there is some hardware that requires SysEx messages to be sent in pieces, and the midifile protocol has provision for this. However, the OS doesn't, so the MusicWeaver cannot handle such messages. (I've never seen any.)]


Karaoke

Just for fun... This element is much like MidiMon except that it only extracts text metaevents from the stream (to pass on to StreamView as usual), and tries to limit these to the lyric fragments. It seems to work on the files I've tried.

Be aware that the metaevent packets that carry the karaoke only pass along the main data stream from the source element. If the stream is diverted by a Splitter for example, the metaevents get lost.

If you actually want to sing along, you may want to insert a delay into the MIDI path itself, so the words appear in time for you to read them.

Specials: Gameport and Director Control

For those with experimental inclinations, the MusicWeaver package includes some modules that give you the opportunity to control your configuration and generate MIDI from some less usual inputs. There are still lots of gaps in the capabilities of these modules, but you can, for instance, use a joystick axis for Pitch Bend or Expression control, and have gameport button actions change paths and so on in your diagram. If you're happy to wire things up yourself, you can connect switch foot-pedals to gameport button inputs, and variable-resistor pedals to joystick inputs to give yourself more features than your MIDI keyboard controller may be capable of.

They are of course dependent on relevant hardware and drivers being available on your installation. I have been using vatious USB gamepad controllers. These should now work with the standard 'usb_hid" driver in Haiku. (Except that Microsoft's SideWinder Strategic Commander is — of course! — non-compliant, and requires a hacked driver...)

You will find the modules described in this section in the 'Modules/MIDI_Extra' folder of the Weaver.

GamePort

This module is the core of these features. It will monitor a gameport device connected to your computer, and send out 'Director' messages as the user moves sticks and presses buttons. You must select the particular GamePort device that an element is to respond to from a popup menu in its Control Panel

Once assigned a device, a GamePort element emits Director events that report joystick and button activity. It must be revealed here that there are actually two kinds of Director message (currently). The Switcher, TriggerSwitch, and so on only respond to and generate the 'Switch' type of Director, but the GamePort adds another type — 'Parameter' events. See the Switcher for details on the Switch type of event. Parameter events have two components: an 'Index' and a 'Value'. The Index distinguishes between different parameters, and its Value (meaning I hope obvious) is a signed integer, potentially up to 16 bits long, though limited to 7 bits (unsigned) for MusicWeaver usage.

When a button on the stick (or whatever) is pressed, the element sends a Switch event with a mark corresponding to the button number (1, 2,...,8). When the button is released, it send another event with a mark '8 + button'. E.g. when button 2 is pressed, Mark '2' is sent; when it is released, Mark '10' goes out. (It's very confusing [Sorry!] that MidiMon shows Switch data as a 32-bit hex word indicating the actual bit(s) set. So the above example will appear there as "00000002" for button-press, "00000200" for release.) Because there are only 16 marks available to the Switcher (the upper 16 in a Switch event are inaccessible for now) it can only properly handle eight buttons; a USB controller may have more than this, but for most purposes hopefully "Eight Is Enough"...

For stick movement, it sends (streams of) Parameter events. In these, the Index represents the axis, and the Value is stick position scaled by default to 0..127. (This range corresponds to the usual MIDI value range.) If the stick is calibrated properly, 'zero-stick' should be represented by Value="64," and excursions should cover pretty much the available range.

The two types of messages will have different destinations and function in your configuration. Button activity events will usually go to Switcher or Stepper elements to reroute data flows. Parameter events will have to go to either D_PitchBend, D_Controller, or D_Aftertouch elements, because as yet no other modules know about them. These modules convert Parameter event streams to appropriate MIDI streams, so that you can emulate 'Bend Wheels' and so on with a joystick. [Note: if you want to see the Director events that are generated in a clearer form, you can view them via MidiMon.]

The Control Panel just has two popup selectors. The top one is where you select the GamePort device you desire as input. The lower one is where you would change the scaling of the output — but don't! The current modules all expect the standard MIDI 0..127 range.


D_Controller

This module is mostly identical to the Controller Source, except that it also accepts "driving" events (hence the "D_") to cause the generation of MIDI Controller events. (It therefore becomes a multiconnector element, with a "Drive" input and pass-through added.) Driving events may be either "Director" Parameter-type packets, or MIDI packets.

It will accept Parameter events (see GamePort above) with a selected Index, and values in the range 0..127, to generate Controller events with the same (or scaled) value. If configured to use MIDI input, any MIDI event that has a 'value' (i.e. Note On/Off, Controller, Key or Channel Aftertouch, and PitchBend) will generate an output event (also scaled). The MIDI Controller number of the output event is determined by the selection in the Control Panel (as with the original Controller module).

Its Control Panel has two extra popup menus at top right. The first lets you select how the element will respond to the full (0..127) range of incoming parameter values. In "direct" mode, the values are sent out unchanged as Controller values. When "inverted", the values are reversed: "0..127" becoming "127..0". If set to "only >= 64", the lower half of the input value range is ignored (no events will be transmitted for input events in that range), and those within the range will be rescaled: "64..127" becomes "0..127". Similarly "only <= 64" rescales values "64..0" as "0..127".

These options let you relate e.g. joystick movement to the actual response you require. 'Stick-down' may output high Parameter values for example, but you want 'Stick-up' to give high controller values. Or you may want 'up' to drive one controller and 'down' to drive another.

The other "Control Index:" menu lets you set the Index of the Parameter events you wish it to respond to, or to select "MV" to respond to MIDI instead.

As with a normal Controller element, you can load a custom list with the "Get List" button, or restore the default with "Default List". Unlike the other element, it does not have user-settable 'send value' buttons, just three fixed-value ones for quick resets: '0', '64' and '127'.

Note that if you want to do more scaling on incoming MIDI than is provided by the menu options, you can precede it with a ValueAdjust element to give fairly unlimited control.


D_PitchBend

Like D_Controller above, D_PitchBend is similar to the PitchBend module, except that in this case it has no slider at all in its Control Panel. (It seems pointless to have one, because it's always at zero when not being dragged. If you do want mouse control as well, just connect a standard PitchBend in parallel.) It is driven solely by Parameter or MIDI events arriving on its "Drive" input. [Originally this connector was labelled "Control", but has been changed to match D_Controller. As a result, some links in earlier existing configurations mauy need to be remade.]

The Control Panel has the same "Index" control as D_Controller above. It doesn't need all the scaling options that has, though, so it just has an "Invert" Checkbox. Select the events you want to generate PitchBend from the "Index" menu, and select "Invert" if they would otherwise have the wrong sense.

D_Aftertouch

This module will generate Channel Aftertouch events, either from Director messages (from a GamePort element) or MIDI events arriving at its input, or simply by moving the slider in its control panel. Like the D_Controller, its control panel has "Index" selection, and value-scaling, menus.

MIDI<—>Byte Stream Conversion:

MidiStream

Converts incoming MusicWeaver MIDI events into outgoing MIDI byte sequences in a form that can be received by a (StreamWeaver) PipeStream element for some command-line app to process. For example one could write a Ruby or Python script that takes the bytes on stdin, does some processing and spits out a variant sequence on stdout, to be turned back into MusicWeaver form by a following StreamMidi element. It has no control panel.

Be aware that output from an app running in StreamView is usually buffered (depending on the app), so is not suitable for real-time throughput. For a real-time script, you will need to set the output unbuffered, by whatever method the language specifies ("STDOUT.sync = true" in Ruby, "bufsize=0" in a Python "open()" statement).

StreamMidi

The reverse of MidiStream. Takes byte-sequence MIDI data, and turns it into MusicWeaver MIDI events. It has no control panel.

Path Switching and Director packets:

Switcher

The Switcher is not exclusive to the MusicWeaver. It is more a part of the Weaver itself — like 'JoinPaths' — because it is totally agnostic as to the type of data flowing through it. It is documented in the Universal Modules file.


TriggerSwitch

A TriggerSwitch element is the most basic source of director messages [see the Switcher]. It will generate such a message each time anything arrives at its input. ( "Anything" actually means a data packet, but in the MusicWeaver context this is usually a MIDI event.) The mode of use is to filter off the desired trigger events from the event stream (using marker and splitter elements) and pass only these to the TriggerSwitch input.

A director message needs at least one of its tags set to have any effect on a Switcher. The TriggerSwitch control panel has a set of checkboxes to select the ones you want. It also has a button to trigger a message directly if you wish.

The element has only one input ('Trigger'). The outputs are 'Switch Out', where the director messages appear, and a pass-through of 'Trigger'. The complete documentation is in the Universal Modules file.


UseIndex

This is another — more specialized — way of generating director messages [see the Switcher in the Universal Modules docs]. Its intended purpose is to turn Program Change events into director messages, but it was written rather more generally than this so that future modules can make use of it in other ways. (The message it generates is actually in a different format from TriggerSwitch messages, but you don't need to be concerned with that until other modules than the Switcher make use of it.) There is no control panel.

The element will generate a director message that effectively has a tag set to match the 'index' byte of each arriving MIDI event. [see IndexRange]. To respond only to Program Change events, the stream should be filtered to pass only these to the element, as most MIDI events have an 'index' value. It will generate a suitable message for all 128 possible index numbers, but the Switcher can only respond to the first sixteen of these, so you are similarly limited in the Program Change numbers that will be useful.


UseValue

This module is similar to the UseIndex module above, except that it generates a director message from the 'value' (last — usually 3rd) byte of a MIDI event. It is mostly only appropriate for events that are 3-bytes long (Note On and Off, Control Change, and Poly Aftertouch, though not Pitch Bend), but as a special case it also accepts the value of a 2-byte Channel Aftertouch. It will respond to any suitable events that arrive, so appropriate filtering is required before it.

It is intended for example to respond to a keyboard controller that can send specific Control Change MIDI messages when a button is pressed, so that this can then switch a path in the configuration. It also can be useful to, say, convert channel-aftertouch events from your keyboard into chorus-depth controller ones or something (by driving a D_Controller element in this case).


Copyright and Distribution of the MusicWeaver

This documentation, the Weaver program, and all associated modules, are Copyright 1997-2015 by Peter J. Goodeve. All rights are reserved.

You are permitted to distribute the Weaver program, the current modules, and documentation in the form of the supplied ZIP archive without charge for non-commercial purposes, provided that the whole package is kept intact. For commercial use or distribution (other than charging a reasonable media and copying fee) please contact the author.

Developers interested in writing their own modules for MIDI or any other purpose, please contact the author.



Author:

				Pete Goodeve
				Berkeley, California

        e-mail: pete@GoodeveCa.net
                pete.goodeve@computer.org