vII MidiOut Help/Documentation (version 1h)

Contents
1.Introduction/Purpose
2.Basic Usage <--- read at least this !
2.1 Getting started
2.3 Menu Commands
2.2 Option Settings
3.Advanced Usage
3.1 The different methods
3.2 Delay and effect slides
3.3 The Cut/Retrigger command
3.4.Effects/MIDI controllers
3.5 Some explanations about MIDI data
3.6 NRP for AWE32/64
3.7 Timing/synchronizing
4.History
5.Plans/Future/Missing Things
Contacting the author

1.Introduction/Purpose

- This is a first implementation of a MidiOut Machine for BUZZ. It is to regard as beta and will maybe heavily changed in the future, although I already tried to prepare all needed parameters and designed vMidiOut to be fit for everything else than SysX (for all still missing things look at the future plans).
- I guess a MIDI out machine generally isn't that suited for distributed songs, because it will behave and sound different on every computer.
- The main purposes may be using BUZZ to make music with all your MIDI-equipment (and mixing all together by other means than BUZZ itself) and the possiblility to sync another device or programm to BUZZ (BUZZ itself currently can't adapt to the timing of another timing source/master).

Some remarks:

- Synchronizing with a MIDI sequencer and external devices should work fine now, also it may be possible to share a DirectX wavedevice with softsynths like Rebirth.
- I doubt the Wavein machine already is adequate for the mixing task (to get any external sounds back into a final mix), but haven't tried it yet. I don't know how the VirtualAudioCable fits in yet, but Hubis MidiLoopback Device and MidiCable sure help a lot.

More exotic usages would be

- controlling BUZZ parameters via MIDI, either by the MidiOut machine itself or with a (synchronized) sequencer, the latter would finally allow to change parameters live and record this with the sequencer ;)
- Concerning the MIDI conversion and merging options of m2buzz there is now a possibility to synchronize a sequencer with BUZZ (either with MID clocks or MTC) playing some rhythm loops or backing parts of a song , record something live with the sequencer and convert and merge this together with the rest of the song.
- Another fine usage is the recently discovered MIDI playability of the ES-9, so you could really record the played notes with a synchronized sequencer and convert the stuff to ES-9. (This applies even better to the new version of Geonik's PrimiFun).
- Since m2buzz v3e you can also just convert MIDI files for use with the MIDIout machine, although controllers and tempo changes aren't processed yet.

2.Basic Usage
To get vMidiOut working:

- put it into the Gear/Generators directory and
- choose the devices you want to use in the BUZZ Preferences->Midioutput (don't forget this!), they will be opened by BUZZ and stay this until you terminate BUZZ or uncheck them.
- Set the device for a vMidiOut machine in the options dialog, since version 1d you can just do this by name without remembering the device number (which will nonetheless be stored as normal BUZZ attribute of the machine). To adress several devices you need more MidiOut machines (since version 1b).
- You also have to connect every machine to the master and set a volume greater zero, although it doesn't produce any sound, because otherwise the machine won't be activated by BUZZ (at least with the method attribute set to 4 or 5). Don't worry, CPU times seem to be very low (not always: sync messages and slides need some more power).

Use DirectSound or Silent output, not the default WaveOut driver of BUZZ !
After being able to use the standard WaveOut driver of BUZZ again, it showed me something terrible: using it as output device makes the vMidiOut timing VERY random, regardless of the settings. So I only can recommend the DirectSound output of BUZZ (maybe with settings similar to mine used for testing: latency 60...100ms, resolution 4, timing 5ms) or the Silent one (giving a big gap between the visible song position and the outgoing events, but quite usable for MIDI only). Probably the best settings will vary between the systems.
After changing driver settings or the machine method I'd recommend to save and reload the song to avoid some misbehaviours.

I'm aware that this machine seems a bit complicated, but keep in mind that in difference to other generators it is used to control very different kinds of MIDI equipment, so it has to have this lot of parameters. And BUZZ 1 doesn't seem best adapted for MIDI integration, so I had to go around several corners to get some things done, but finally I really can use this machine. And if you just start with the simple things in the next chapter, you will be able to use this as well ;)
There is another MIDI machine by Hagen in preparation, especially for controlling Rebirth. Have a look at his work for this purpose or as alternative to my machine.

2.1 Getting Started
After you have set up the machine and BUZZ for using one of your MIDI devices, you can use the notes in the first column like you would do with other BUZZ generators. If you're using a General MIDI device (like intern synthesizers of most sound cards) chances are great that you're listening to some piano sounds. You can change these sounds in the 5th column (MIDI patch) or with the slider in the parameters window.

The second column (velocity) is what volume is for other generators, only that the range is from 0...127(0x7f) with default 64(0x40) instead of double these values, sorry for this, I just used the MIDI standard here.

If you only want to let BUZZ play some melody, you don't need to deal with the channel value in the 4th column. But for using several voices or effects this is necessary: MIDI associates most events with one of 16 (logical) channels: most effects apply to all notes on one channel, and every channel has always only one active instrument. This instrument can be switched with every note you play, but it is more convenient to use different channels for different instruments.

This can be handled very easy with vMidiOut by also using a different channel for every BUZZ track. In this case you have to put the values for the channel and the instrument (=MIDI patch or MIDI program) only once: at the start of your song.

With General MIDI the channel number 10 (0x0a) has a special function: it's the drum channel, and the notes you play on this channel don't change the pitch of one instrument but trigger different drums.

The most useful effects to start with are probably the MIDI controllers 0x000a (volume) and 0x0007 (pan) as the BUZZ sliders don't work for this machine :( The pitch wheel (0x0101) and modulation wheel (0x0001) come handy as well. Of the things I implemented additionally to the MIDI standard I'm most excited about the cut/retrigger command (0x0120), because you won't find this in any sequencer. But with this we are already in the advanced usage topics I'll deal with below. The same goes for the delay, effect slides and synchronizing.

2.2 Menu Commands
The menu just has some reset functions (where all note-off functions can also be configured to sent with the BUZZ pause button) and the option settings.

If you've got a lot of hanging notes (especially if working without checked "monophone tracks" option), you can kill them with the following commands:
All notes off just sends MIDI controller 123 to the device on channel 1, which is very fast but doesn't work with some devices,
Stop all notes really sends a Note-Off for all 128 notes on all 16 channels, this is the PANIC button, but may several secondes on some devices.
If neither this doesn't help, you could try to disable the nasty device for a short time in the BUZZ preferences.
Reset controllers sends MIDI controller 121 to the device. It depends on the MIDI device if it really resets everything.

2.3 Option settings
In the options dialog you can change the following parameters:

- MIDI device: as explained above, don't forget to activate the device in the BUZZ MIDI out preferences.
- Help mode: BUZZ allows to show a short description for machine parameters, in case of MIDI controllers (effect commands 0x0000-0x007f) I give the standard General MIDI meaning here as default, but for controlling Rebirth it's more convenient to show the special meaning of those controllers for this program. Help modes for other programs/ devices may follow. Changing the help mode doesn't affect anything else of the behaviour of vMidiOut.
- monophone tracks: You can switch off the default behaviour of the machine, to send a note-off for every new note it finds on a track. In this case every note-off just cancels the last note sent on this track, all others have to be switched off explicitely with a velocity off zero, so you'll probably soon end with a lot of hanging notes ;)
- MIDI play/channel: not very useful for a MIDI machine, if checked the machine listens to the selected MIDI channel (0-15) of the device you choosed as BUZZ MIDI input and repeats every note on the output MIDI device with the same channel, note value and velocity. This is like MIDI through, but for note messages only.

Some options dealing with the BUZZ stop button and a following continue of BUZZ playback, especially for syncing
purposes:

- BUZZ pause options: You can configure the messages, the machine will send, if the BUZZ pause button is pressed. The "all note off message" would be controller 123 on channel 1, which is great for getting rid of the hanging notes, if your MIDI device supports it. If not, choose "all note-offs" here.
The "sync stop message" depends on the device/program you want to sync with BUZZ. The sync messages (0xf8) will be stopped in every case, but some programs explicitely need the stop messages to stop their timer, while my sequencer already pauses completely without sync messages, but would leave the "extern MIDI sync mode" with a stop message.
The BUZZ continue options apply only if you have stopped a running sync and it get's restarted by the "sync refresh" commands (0x0110 0x0000 or 0x0113 0x0000)
- smart sync restart: If this is checked (default), sync start commands 0x0110 with given song position are only processed after a BUZZ pause, if no sync was running or if the song position is less than the last one set (good for loops):
advantage: Just start start every pattern with the appropriate 0x0110 + song position command (yes, this is some work, a song position command for the BUZZ machine interface would be very handy) and your sync slave is always where you want it, even with the usual looping of a part of the song for editing purposes.
disadvantage: You have always to press the pause button after position changes (at least for setting it forward). You also shouldn't use the refresh sync command 0x0110 0x0000 with this, as this makes the sync running again and prevents the use of the correct restarting position at the next pattern.

Some probably rarely used extended options:

- MIDI delay: If the method attribute of the machine is set to 4 or 5 all MIDI output can be delayed in the range from 0 (no delay) to 0x1ff (delay ca. 2 Rows). For method 5 you probably should leave this at zero, while for method 4 you can use this to correct the gap between MIDI and wave output.
- slide resolution (methods 4, 5 and 6 only): At 125BPM / 4TPB MIDI controllers would be sent about 20-30 times per row for sliding with the maximal resolution of 1. This fine resolution probably isn't needed and just causes a high CPU usage and unecessary MIDI messages, so this is set to 2 as default (=half message rate). Keep in mind, that the actual amount of steps in row (=tick subdivision) is decreasing with higher BPM rate, as the used BUZZ wave routines have a constant time grid.
- allow timer You should try the sync command 0x0110 instead of the timer sync command 0x0113, it seems to be better and doesn't use an extra timer. But to use method 7, the MIDI time code command 0x0115 or the old timer sync command 0x0113 you have to explicitely allow timer usage for a machine with this option. Keep in mind that for every machine you use this command one of a limited number of timer-resources is needed. You also should have this checked for one machine in the song only. The timer resolution of 5ms generally shouldn't be changed..

Using different scales (this is completely experimental, I'm not even certain that the resulting pitches are correct): Scale 0 always is the default chromatic scale, for all other scales every note is adapted to the active scale and preceeded by a pitchwheel command (even for incomming notes via MIDI play). Since the pitchwheel is common for all notes on a MIDI channel, only one single note can be correct, in case of chords there will be errors. Another thing often occuring with playing these scales by an extern keyboard is erasing a new note with the old one: assume you're playing two neighbour notes, which will be mapped to the same MIDI note, but with different pitchwheel values. If you release the old note after triggering the new one, both will be cancelled and you hear nothing :(

You can either chose one of the predefined scales (there may be more in the future) or load a scale as user scale (number 1).
The format is very simple: comment lines have to start with an '!', the first non-comment line is a description string, the second giving the number of tones in the scale (for instance 12 for the default chromatic). Now the given number of lines has to follow, containing the pitch values in comparision to the scale root note, either as proportion a/b or in cents (the root note must not be contained in the file! ). Here a simple example for the chromatic scale :

!this is the scale file for the chromatic scale
standard chromatic scale with 12 tones
12
!now the notes follow, the first with proportion 1/1 or 0.000 cents
100 cents
200 cents
300 cents
400 cents
500 cents
600 cents
700 cents
800 cents
900 cents
1000 cents
1100 cents
2/1
!the last line also could have been 1200 cents

After chosing a scale file for loading you will be asked for the MIDI root note, this will be the note number of the first note for the scale, all notes equal or less than this number will have the same pitch value: the scale root. This one is given in cent, compared to C0. The defaults are 0 for both: keyboard or BUZZ C0 will just be mapped to the real C0 pitch. To transpose everything up 2 octaves you could set the scale root to 2400.0 (=C2). Beginning with this the scaling intervalls are calculated
up to MIDI note 127. For the example this would be:
C-0 -> 0 cents, C#0 -> 100 cents, D-0 -> 200 cents, ... B-0 ->1100 cents, C-1 -> 1200 cents, now the scale is full once,
and we start again with C#1 -> 1200 cents + 100 cents = 1300 cents,...

3.Advanced usage information
The machine allows 16 tracks, default for every track is MIDI channel 1 at startup. You can change the channels in the corresponding column of the track as you like, several tracks can access one MIDI channel, so it's possible to apply different controllers together. Drum channel generally is 10 (0x0a). This has to be set only once (at the start of the song) and will be remembered later.

If you choose an instrument number a program change message will be sent to the actual channel, so you also only should do this at the start of the song or if you want to change the actual patch. Now every note will be transmitted, default velocity is 64 (0x40), highest possible 127 (0x7f). If you use the default of "monophone tracks", an already running note will be canceled. If not and you only have one running note, a note-off or just a zero in the velocity column will stop it, otherwise only the last one stops and all other have to explicitely switched off with the note-number and a zero velocity.

To reduce the amount of typing into the BUZZ track columns, you have to set only one of the three effect columns. The others are replaced by the last value you've put in there or some defaults (for the effect-slide byte this is to do no sliding at all, and the sync commands generally behave different with or without data values). So if you're working with one effect per track only (during some rows or patters at least), you have to set the effect kind only once together with a starting value for the data. Later only set the data or just the "Slide-To value". After a slide this value will be used as default data instead of the last data value.

3.1 The different methods
If I had a method to solve all timing things, I'd make it the only one and nobody had to care about them. But since I don't have this final solution (yet?), I only can give a summary of the advantages and disadvantages of the different methods. You can set them as attribute in the machine menu:

- method 0: simple timing <--- use this, if nothing else works :(
+very few CPU usage
+compatible, should work on every PC
-not realtime, is a bit early (up to one row), especially no sync between MIDI and WAVE output, mididelay can't be used to correct this
-timing resolution is once per row
->only timer sync
->no delay, slide, retrigger
- method 3: event based timing <--- gives the best timing for undelayed events
+very few CPU usage
+compatible, should work on every PC
+sync between MIDI and WAVE output ( tolerance 5 ms?) ,
(-) but maybe disturbed by high CPU usage
-(was?) a bit unstable, gave some crashes for me
-timing resolution is once per row
->only timer sync
->no delay (including mididelay), slide, retrigger
- method 4: wave based timing <--- largest range of adjustable mididelay
+delay, slide, retrigger
+new wave based sync without timer (but why is this incorrect again?)
+sync between MIDI and WAVE output, (-) has to be adjusted with mididelay
-not tested much yet (was just a step on the way to method 5, but may still have some advantages)
-maybe dependent on system + driver + BPM settings settings (for me it works with 125 BPM and a latency of about 100 ms, but doesn't with <50ms or >110 ms) (is this still the case?)
-timing resolution limited by Wave-functions ( for 125BPM this is about 25 per row)
- method 5: event+wave based timing <--- default, best one for synchronizing (command 0x0110)
+delay, slide, retrigger
+new wave based sync
+sync between MIDI and WAVE output (automatical)
-system dependency? (similar method 4)
-timing resolution limited by Wave-functions, especially disturbing for start of undelayed events
- method 6: mixture of methods 3+5 <-- still in testing phase, only slightly worse than method 3
+delay, slide, retrigger
+new wave based sync
+sync between MIDI and WAVE output (automatical)
+undelayed events should have a timing as method 3, others are limited by Wave functions
-system dependency? (similar method 4,5)
- method 7: timer based <-- still in testing phase, seems no very big improvement over method 3
-needs timer (you have to activate it in the options dialog)
-> no other timer commands (timer sync 0x0113, MTC 0x0115) allowed currently
+timing resolution is adjustable (options dialog), but not saved currently!
+sync between MIDI and WAVE output, but still depends on BUZZ driver capabilities (seems best with DirectSound output)
-no delay (including mididelay), slide, retrigger implemented yet

The obsolete methods 1 and 2 are removed from the machine because they weren't usable or had no advantages over method 3. I still use method 5 as default, the new method 6 may give some better results for undelayed events, still allowing delays/slides and retriggers. But without these, method 3 should give the best possible timing without using an extra timer. Method 4 could be used to adjust the timing in both directions, allowing compensation of delays of your MIDI devices, but this isn't worked out in detail yet. I hope to have fixed most of the reasons method 3 crashed before and also the system dependency of methods 4, 5 and 6 should be gone now. Even method 7 showed to be not the final one: everything seems to depend on the wave driver settings with DirectSound giving by far better results than the multimedia waveout driver.

3.2 Delays and Effect slides
The delay and effect-change bytes are used only with the method attribute of the machine set to 4, 5 or 6. The delay byte can be in the range from 0...0xff (255), the latter gives approximately a delay of a whole row. Currently it may happen, that high delays prevent the event from being triggered at all. If you've choosen a general mididelay for the machine, values are just added together.
The time resolution for the delay and the effect slides of course isn't 255/row, but system, driver and BPM dependent. The actual value is shown in the description field for the effect slide byte, or as minimal difference for the delays in the description for the delay columns. On my system (P200,AWE32) for instance it's about 30/row for 125 BPM with the DirectX driver at a resolution of 4 and a latency of 100ms and gets lower with a higher BPM rate or less latency. The resolution for effect slides additionally is divided by the number you have as slide resolution in the options dialog (default is 2).
Effect slides are currently implemented for continuous MIDI controllers 0x0001...0x0061, all NRP's and the pitchwheel. You just put the MSB (most significant byte = higher byte) of the effect data value you wish to slide to until the next row into the effect change column (the last one). This would look like

      Note  Vel Del Chan  Patch  Effect   EData  Slide

       C-4  ..  ..  ..     10     0007    fffe    80

       ..   ..  ..  ..     ..      ..     8000    01

       ..   ..  ..  ..     ..      ..     0000    ..

for a volume slide to zero in rows. The last zero just makes sure the effect data is really at the target, the slide itself may stop a bit earlier. The second data value (0x8000) can be omitted.
For 7Bit controller and NRP data you can slide trough the whole possible range this way, as a slide value of 01 would be exactly the same as an effect value of 0000.
For 14Bit controllers (not yet implemented) and the pitchwheel this is different: the slide value of 0x01...0xff really just gives effect values in the range 0x0100...0xff00, so you not only get just 8Bit resolution, you also miss a small range at the start and the end. This will probably not fixed without releasing a completely new version 2 with a 16Bit effect slide value (and a normal volume range instead of the velocity) although I already had plans to abuse the (only rarely needed) channel byte for the LSB...

3.3 Cut and Retrigger
The lower byte of the data for the cut/retrigger command (0x0120) is a delay in the same format as the mididelay or the delay column. The higher byte gives a counter for the events to happen, that means 0 just toggles note off after the delay(=cut), 1 starts it again immediately after the cut (=Retrigger), 2 cuts again after another delay and so on.
This way every even number let's you with the note cut off, every odd one with a note-on. If there's an event on the next row the process of retriggering is stopped after reaching it and again the delay values near 0xff aren't reached for sure. If there's no new event, the retrigger process may last about several rows.

3.4 Effects/MIDI controllers
You can apply a lot of effects, which generally depend on your MIDI-equipment. If you just use the effect data column the last applied effect is used. You can try to reset all controllers with the command in the machines menu, it just sends controller 121. Since I wanted to have a full 16Bit range for some of the effects, but also wanted to allow using the BUZZ parameter sliders, I expanded the data ranges of continuous controllers to 16Bit (with version 1b). Some mesages need exact values, so I tried to keep them (controller 0,32 and 98-127 currently). There probably will be more changes here in the future :]
For most commands a (very much shortened down) description is shown on the bottom line of the pattern editor, you can also switch to the Rebirth help mode in the options dialog, to get some information about the usage of the controllers for Rebirth, which isn't given here in the table.

vMidiOut Effects | MIDI events | MIDI Data Range | BUZZ/vMidiOut Data Range (if different)
0x00xx | MIDI controller | * | *
0x0000-0x007f | (7Bit) Midi Controller xx (0-0x7f) (Ctrl 0-31 are MSB and 32-63 LSB of 14Bit ctrl) | 0-0x7f | ctrl 1-0x1f,0x21-0x61: 0-0xfffe (shifted 9Bit left) ctrl 0,0x20,0x62-0x7f: 0-0x007f (=MIDI)
| 00:Bank change | (MSB of) bank number 0-0x7f | 0-0x7f
| 01:Modulation wheel 02:Breath controller 04:Foot Pedal 05:Portamento Time 06: Data Entry (Registered Parameter) 07:Volume 08:Balance 0x0a (10):Pan 0x0b (11):Expression |  | 0-0xfffe (shifted 9Bit left)
| 0x0c (12):Effect control 1 0x0d (13):Effect control 2 |  | 0-0xfffe (shifted 9Bit left)
| 0x10 (16):Slider 1 0x11 (17):Slider 2 0x12 (18):Slider 3 0x13 (19):Slider 4 |  | 0-0xfffe (shifted 9Bit left)
| 0x20-0x3f (32-63):least significant bytes of controllers 0-31 for 14Bit precision 0x26: Data Entry (NRP)
| 0x40-0x5f (64-69):Switches: 0x40 (64):Sustain 0x41 (65):Portamento 0x42 (66):Sustenuto 0x43 (67):Soft 0x44 (68):Legato 0x45 (69):Hold 2 Pedal | 0: off, 0x7f: on | 0: off, 0xfffe: on
| 70 Sound Variation 71 Sound Timbre 72 Sound Release Time 73 Sound Attack Time 74 Sound Brightness 75 Sound Control 6 76 Sound Control 7 77 Sound Control 8 78 Sound Control 9 79 Sound Control 10 |  | 0-0xfffe (shifted 9Bit left)
| 80 General Purpose Button 1 81 General Purpose Button 2 82 General Purpose Button 3 83 General Purpose Button 4 | 0: off, 0x7f: on | 0: off, 0xfffe: on
| 0x5b (91):Reverb/Effects level 0x5c (92):Tremolo level 0x5d (93):Chorus level 0x5e (94):Celeste level 0x5f (95):Phaser level |  | 0-0xfffe (shifted 9Bit left)
| 0x60 (96):Data Button increment 0x61 (97):Data Button decrement |  |
| controller combinations (NRP/RP, see below) 0x62 (98):NRP controller (data at 0x26) 0x63 (99):NRP preselect (MSB?) 0x64 (100):RP LSB (data at 0x06) 0x65 (101):RP MSB |  |
| 0x78-0x7f (120-127) Mode messages |  |
| 0x78(120):All sound off | 0 | 0
| 0x79(121):Reset all controllers | 0 | 0
| 0x79(122):Local Mode off/on | 0 or 0x7f | 0 or 0x7f
| 0x7b(123):All notes off | 0 | 0
| 0x7c (124): Omni Mode on 0x7d (125): Omni Mode off 0x7e (126): Mono Mode 0x7f (127): Poly Mode |  |
0x0080-0x00ff | 14 Bit Midi Controller 0x80+xx (not implemented yet) | 0-0x03fff | 0-0xfffe (shifted 2Bit left)
0x010x | other MIDI messages | * | *
0x0101 | Pitchwheel | 0-0x3fff (default:0x2000) | 0-0xfffe (shifted 2Bit left) (default:0x8000)
0x0102 | Channel pressure (Aftertouch) | 0-0x7f | 0-0xfffe (shifted 9Bit left)
0x0103 | Key pressure (Aftertouch) | note: 0-0x7f +pressure:0-0x7f | 0-0x7fffe: high byte: MIDI note 0-0x7f low byte: 0-0xff (shifted 1Bit)
0x011x | Sync macros | * | *
| 0x0110: start wave sync (methods 4,5,6 only!) | (song position 0...0x3fff in beats) | ....(no value): start (without setting songposition) 0000: refresh/correct sync 1...0x3fff: starting position 0x4000: start position 0 (in general not needed because equal ....) 0x8000+xxxx: continue at position xxxx 0xfffe: continue (without setting songposition)
| 0x0111: stop syncing (for commands 0x0110,0x0113,0x0115) |  | ....(no value): stop + sync stop message 0xfc 0000: dont send 0xfc
| 0x0112: wave sync (!obsolete) |  |
| 0x0113: start timer sync (activate timer in options dialog!, don't use with method 7) |  | ....(no value): get timerrate from BPM 0000: refresh sync xxxx: set timer rate (in ms)
| 0x0115: start MIDI Time Code sync (activate timer in options dialog!, don't use with method 7), only 25 frames/sec implemented |  | ....(no value): start MTC at offset 0 0000: refresh sync xxxx: set offset (in sec) (set additional frame offset in effect slide column)
0x12x...0x14x | Special vMidiOut commands | * | *
0x12x | Cut/Retrigger | * | *
0x0120 | cut/retrigger |  | 0xAABB: A=count,B=delay even A cuts, odd A retriggers
0x13x | Transposing | * | *
0x130 | transpose machine (drum channel 0x0a will not be transposed) |  | 0 or .... (no value) no/reset transpose two formats are possible: 0xAB00: A octave: 0..7 or 8...f (-8....-1) B halftone 0....c 0x00CC: halftones: 1...0x7f or 0x80...0xff (-128...-1)
0x131 | tranpose current track only |  | as above (command 0x130)
0x132 | reset all transposing (for machine and all tracks) |  | -
0x14x | Chords | * | *
0x140 | chords (from "library") |  | chord numbers are compatible to Argüelles TB3003: 0: no chord 1: maj 4, 7 2: min 3, 7 3: min 4, 8 4: maj 3, 8 5: min 5, 8 6: maj 5, 9 7: min 5,10 8: maj 4, 7,11 9: min 3, 7,10 a: maj 3, 7, 9 others may follow...
0x141 | build chord (up) |  | 0xABCD: every 4bit number A,B,C or D (0..0xf) gives the halftone difference to the base note, a value of 0 will be ignored, for example chord maj 4,7 would be 0x4700 or 0x4007 or 0x0047
0x142 | build chord (down and up) |  | 0xABCD: as above, but A and B give tones less than the base note 1-> -1, 2-> -2...
0x143 | build chord (down) |  | 0xABCD: all chord tones will be less than the base note 1-> -1,2->-2,...
0x144 | build chord (down transpose and up) |  | as 0x142, but A,B are taken positive with transposing one octave down 1-> -11, 2-> -10...
0x145 | buid chord (down transpose) |  | as 0x143, but all numbers are taken as positive with transposing one octave down 1-> -11, 2-> -10
0x01fx | System message fx | * | *
| f0:SysX start (no way to implement SysX here) |
| f1: MIDI time code quarter frame (use 0x0115 instead) |
| f2:song position (in beats) | 0-0x03fff
| f3:song select | 0-0x7f
| f6: tune request | none
| f7: SysX end |
* | realtime messages (use the sync commands 0x011x instead of 0x01f8-0x1fc) | none | *
| f8:timing clock (to be sent 6 times per Beat) |
| fa:start |
| fb:continue |
| fc:stop |
| fe:active sense |
| ff:system reset |
0x02xx | 7Bit NRP xx (short cut, see NRP ) (signification given here is for SB AWE 32/64) | 0-0x07f | 0-0xfffe (shift 9Bit left)
| 00: LFO1 delay |
| 01: LFO1 frequency |
| 02: LFO2 delay |
| 03: LFO2 frequency |
| 04: Envelope1 delay |
| 05: Envelope1 attack |
| 06: Envelope1 hold |
| 07: Envelope1 decay |
| 08: Envelope1 sustain |
| 09: Envelope1 release |
| 0x0a (10) Envelope2 delay |
| 0x0b (11) Envelope2 attack |
| 0x0c (12) Envelope2 hold |
| 0x0d (13) Envelope2 decay |
| 0x0e (14) Envelope2 sustain |
| 0x0f (15) Envelope2 release |
| 0x10 (16) Initial pitch |
| 0x11 (17) LFO1 to pitch |
| 0x12 (18) LFO2 to pitch |
| 0x13 (19) Envelope 1 to pitch |
| 0x14 (20) LFO1 to volume |
| 0x15 (21) Initial Filter Cutoff |
| 0x16 (22) Initial Resonance (Filter-Q) |
| 0x17 (23) LFO1 to Filter Cutoff |
| 0x18 (24) Envelope 1 to Filter |
| 0x19 (25) Chorus |
| 0x1a (26) Reverb |

3.5 Some explanations about MIDI data
I'm not that MIDI expert and just tried to apply the information I collected from several sources and bring them into an useful form for the MidiOut machine. MIDI is a protocoll for communication between musical devices, which basically consists of a stream of bytes (8Bit), where the single bits are transmitted sequentially, like serial communication (mouse,modem) does, but with a higher bitrate. If the highest bit is set, the byte is a so called status byte, which means some kind of command, while without the highest bit there are only 7 bits remaining for data, that's just the range 0-0x7f (0-127) in the table. To complicate things, different commands/statusbytes need/allow different data, some combining two (7Bit) data bytes to a 14Bit value (range 0-0x03fff). For controllers 0-31 this get's even worse: you can decide for yourself, if 7Bit resolution are enough and just send one data byte, or if you need some finer adjustments sending the second (least significant byte:LSB) as controller xx+32 (32-63). Also the meaning of the controllers is only rarely standard with General MIDI just giving a start. I don't know much about GS and XG.

3.6 NRP for AWE32/64 (and RP)
The NRP (non registered parameter) stuff is especially useful for the AWE, at least with this values (don't know if there's some kind of standard; GS and XG seem to use NRP too, but with other values). For instance if you use an effect 0x215, a value of 127 for controller 99 and a value 0x15 (21) for controller 98 will be sent for the current channel. Finally the effect data is transmitted on controller 0x26 (38).
Since version 1e all 3 controllers are sent every time you use a NRP command, so you can apply different NRP's from several BUZZ tracks. In case of sliding the two first controllers are only sent, if the same vMidiOut machine has sent a different NRP command to the same MIDI channel in the meantime. So you can do slide for more than one NRP, but you have to do this with the same machine.

Registered Parameter (RP) as part of the General MIDI standard
I've not added a shortcut for the RP's yet, but I also have found only few used ones:
To set the pitch bend range for a channel, set controller 0x64 (100) (RP LSB) to a value of 0, and controller 0x65 (101) (RP MSB) to a value of 0, then set controller 6 to the desired range in semitones (up to 12).
RP's 1 and 2 are fine and coarse tune, no idea about the parameters.

3.7 Timing/Synchronizing/MIDI TimeCode

Basic Ideas
To sync a sequencer with BUZZ, you would select some option like "MIDI Sync" there, connect BUZZ and the sequencer with Hubi's LoopBack device (or any other of that kind) and BUZZ would have to send a sync start message (=effect 0x01fa), a stop (= 0x1fc) and between a lot of sync timer messages (=0x1f8).
But only one sync message per row isn't enough, you need 6 of them, and this with as equal distance as possible. This was the thing, which should be easy to achieve (BUZZ manages several times 44100 samples the second, shouldn't it manage these 6 syncs in a row?), but nonetheless was rather hard to implement, and even now has (still?) some drawbacks.

One simple solution is to set the TBP rate to 6*4=24 and use only every 6th line for your song (but you don't have to restrict to these) and every line for a sync message 0x01f8. This should get you going, but the resulting patterns are hard to deal with.

To get timing more correct I used the event mechanism of the BUZZ machine interface, so at least a synchronisation between Wave and MIDI output can be achieved (method attribute set to 3 or 5).

Hubis Loopback Setup
Most of the problems I had with synchronizing were caused by the fuse mechanism of Hubis Loopback device (versions >2.4). This shall prevent system crashes caused by a circular loop of MIDI messages by inhibiting the same message to occur more than a certain amount in a certain time. The default values are o.k. for normal MIDI usage, even for equidistant sync messages, but for the correction mechanism I use, some sync messages were swallowed. So go to your control panel -> multimedia->extended and choose one of your Hubi's Loopback port (default names are LB1,...) and change the "duplicates" setting to a higher value (for instance 20). This may prevent the fuse mechanism from working, but lets all sync messages of vMidiOut pass. Other programs similar to Hubis Loopback Device may have a similar fuse mechanism, take care to adapt it to the needs of vMidiOut.

Timer Sync (command 0x0113)
Further I experimented with an own timer, which is based on the BUZZ BPM and TBP settings, but else works independent from the BUZZ timing (sync command 0x0113). This came close, but had a lot of disadvantages:
-limited timer resources
-distortion of BUZZ timer ?
-even best resolution of 1ms matches only distinct BPM rates, for instance 119 BPM <-> 21ms, 125 BPM <-> 20ms, 131 BPM <-> 19ms, the formula is

                 time_ms=60000/ BeatsPerMin/6/TicksPerBeat;

(This is also of concern for doing the sync messages with an extern programm, like Vellocets vmidisync, and BUZZ sending only start and stop messages (effects 0x01fa and 0x01fc): get vmidisync together with other useful programs (vmidijoy and c2nrp) at Vellocets homepage .

Starting the timer with effect 0x0113 and a non-zero data just does the same as Vellocets vmidisync, with the advantage to let the BUZZ pause button send a configurable stop message and pausing the sync messages. So 0x0113 0x00014 just would give the BPM rate of 125 (unfortunately not exact), without any further adjustments (=not synced to BUZZ).
Starting the timer with no data-value (0x0113 ....) calculates the rate nearest to the actual BPM setting of BUZZ and starts the timer. Now you have to put a command 0x0113 0x0000 (or just .... 0x0000) in EVERY row. This does two things: it corrects the mismatch between the BUZZ BPM setting and the timer rate by sending additional or inhibiting sync messages if necessary, and further it allows to restart the timer after you pressed the pause button in BUZZ (I really found no other way, strange).

Using the timer requires to check the "allow timer" option of the machine.

Wave based sync (command 0x0110)
The last implemented method is based on the wave based timing of the methods 4, 5 or 6 and basically just tries to always send 6 sync messages between two BUZZ rows (for 4TPB). This doesn't need an additional timer, but the timing between the single sync messages may a bit vary.

To use this you would make 3 patterns for vMidiOut. In the start pattern place a command 0x0110 .... in the first row, followed by all other lines set to .... 0000. The second pattern, which just refreshs the sync and has to be repeated the whole sequence, just consists of .... 0000 (or maybe a 0x0110 0000 in the first row). The last pattern to stop the sync messages has a single 0x0111 in it (either a 0x0111 .... to send a final stop message or a 0x0111 0000 to leave this out).

Since version 1e other TPB values than 4 should also work, but recommended are still the values 4,6,8,12 and 24.

Since version 1f you can use a starting song position as argument. It is measured in MIDI beats, which are just the BUZZ rows for 4 TPB, and can be in the range from 1...0x3fff.

MIDI Time Code (command 0x0115)
Synchronizing via MIDI clocks only controlls the flow of time: every 6 MIDI clocks a beat passes, if the clock messages are sent faster, the resulting BPM rate increases (or vice versa: if the BUZZ BPM rate increases, the sync messages have to be sent faster, this is done automatically for the 0x0110 commnad, but for the 0x0113 command the timer has to be restarted).

MIDI Time Code in contrary is used to transmit the absolute time (in seconds, minutes and hours) and not only some kind of clock tick. This way an additional control mechanism is given to correct the timing. A second is partitioned in several frames, where 24, 25 and 30 frames per second are usual values. The smallest time unit is a quarter frame, for the value of 25 frames per second this are just 10 ms. This is the only framerate I've implemented in vMidiOut. It causes a higher activity of the machine compared to the sync clock messages every 20 ms at 125 BPM, so the CPU usage of vMidiOut is higher with MTC. The actual frame position is corrected via the refresh MTC sync command (0x0115 0000) in every BUZZ row by comparing the ellapsed time with the BUZZ sample position divided by the sample rate.

The command 0x0115 is used as the other sync commands: 0x0115 .... starts sending quarter frame messages with an offset of 0, so if you place this command at the start of your BUZZ song, the ellapsed time in BUZZ and in your sequencer should be the same all the time. The command 0x0115 0000 corrects the actual frame position and also is used to restart synchronizing after a break. Starting MTC with another value gives an offset in seconds, an additional frame offset can be given in the EffectSlide column. Using a value of 0xfffe doesn't change the offset at all, if no offset was given before, it's value is undefined.

A sequencer synchronized via MTC usually needs 1 or 2 seconds to adapt to the given timing (in difference to synchronisation via MIDI clocks), this should be taken into consideration. Also you need to allow the usage of the timer in the options dialog.

4. History
version 1a:
-Menu commands for Note-off, Controller reset

version 1b:
-Data incompatibilities! (at least it should not crash with old ones)
-MIDI device is now machine attribute
-delay byte on place of former device byte and new effect change byte as last byte (both still unused)
-changed parameter ranges for continuous controllers, NRP and pitchwheel to 0...0xfffe (ctrl 0, 98-127 stay 0..0x7f)
-assumed 7Bit for all controllers (14Bit maybe come later as extra effects)
-Bugfix with NRP causing System reset (0xff) message
-implemented event method by Jeskola with correct timing (Attribute method=1), still causes some crashs :(
-process program change, controllers and notes in this order (seems more logical)
-two new event based methods (2 and 3), but you should use method 0 or 3 only
-two new experimental sync macros:

- -0x0110 sends a start message and begins a series of event based sync messages (set effectdata to 1), (these are still too slow)
- -0x0112 bases it's timing on the BUZZ wave routines, but very imperfect currently :( you'll get a BPM independent, very fast and inconstant rate for effect data 1, you can divide the rate by raising the data value.

-Effect 0x0111 stops these syncmessages for both and sends a stop message (don't use 0x01fc only!).
-Unfortunately all these messages don't stop with BUZZ pausing :(

version 1c:
-added option for playing machine with Midi (very useful for a MIDI machine :]
-BUZZ stop now ends sync messages and sends ctrl. 123 :)
-timer sync command 0x0113 :)
-configuration dialog
-stop command 0x0111 0x0000 doesn't send stop message

version 1d:
-option for BUZZ-stop to send all note-offs (finally getting rid of all hanging notes :)
-removed some obsololete things: event sync (0x0110) and methods 1 and 2
-timer sync must be enabled in options dialog (this way you won't have several timers without thinking about it ;)
-option to have monophon BUZZ tracks
-fixed event based timing of method 3
-some people say, my machine is rather hard to understand: it will get worse ;)
-added method 4 with wave based timing (delta time =method 0) --> slides and delays should now be possible
-added method 5 with event + wave based timing (delta time =method 3)
-added general MIDIout delay, works only with methods 4+5 (with method 5 this should usually set to 0, with method 4 this shall be used to correct the gap between wave and MIDI)
-added event delay for methods 4+5 (still in "work"-units)
-changed code to use several (2) event cues to have correct delay for method 5
-added effect slides (still system/bpm dependent) for 7Bit Ctrl, NRPN and pitch wheel
-added a lot of descriptions for the pattern and parameter view, for the idea and instruments thanks to Rout
-all time units are now (more or less) system independent (delay 0...0xff for one row)
-added new sync command based on methods 4 or 5 as 0x0110 (it's as poor as 0x0113 :( but without timer :)
-added cut/retrigger command :)
-changed defaults to method 5 and monophone tracks
-changed option dialog a lot, especially choose device by name now
-fixed some bugs with synchronizing
-use 3 event cues now (to access old data for sync and may be other purposes)
-fixed crashes during machine startup and avoided them for shutdown
-added sync finetune: finally some positive results with this
-use slide-end value as new default data value

version 1e:
-implemented Midi Time Code (MTC, command 0x0115), finally something works without finetune ;)
-improved method 3 handling to allow faster BPM rates
-special thanks to Hagen: He's working on a MIDI machine especially for controlling Rebirth; we finally didn't join our machines because of different aims, but from his contributions resulted the Rebirth help mode (gives meaning of controllers for Rebirth instead of GMIDI), some synchronizing corrections (multi threading) and the timer sync command 0x0114 (unfinished and removed again because of the next point ;) I recommend to test his machine if you just want to control Rebirth from BUZZ, it's easier to understand/manage and has an additional Rebirth buffer correction.
-detected wrong setup of Hubis Midi Loopback -> removed sync finetune ;)
-added method 6 to fix the limited resolution for undelayed events in method 5
-added MTC offset (in seconds, additional frame offset in Effect Slide column)
-correct 14Bit songposition command (0x01f2)
-tried to fix malfunctioning sync with newer Cakewalk versions (added delay value for 0x0110 command), partial success only?
-fixed/enhanced method 4: mididelay maybe up to 0x1ff (=2 rows) now
-increased cue number to 10! -> this allows BPM rates up to 500 at 4TPB for methods 3, 4 and 5
-fixed missing MIDI events for higher BPM rates and method 5
-fixed some casually missing sync clocks for sync start
-fixed missing sync clocks for higher BPM rates
-expanded sync messages for all TPB values (but best for 4,6,8,12 and 24)
-increased cue number to 20-> now 150BPM at 24 TPB are possible (interesting for converted MIDI files), but don't raise the BPM rate much higher (for high TPB values only of course), BUZZ may crah sometimes
-improved NRP handling: all 3 necessary controllers are sent once every row but for slides only if another NRP (in another track, but with the same machine) was sent to the same MIDI channel -> you can do slides with more than one NRP on the same channel now, but they have to be done with the same machine
-added option slide_resolution to reduce CPU usage and MIDI traffic, default is 2 (for version 1d this was 1)

version 1f:
-some additional controller descriptions
-changed channel pressure range -> 0-0xfffe, key pressure 0-0x7ffe (MIDI note + pressure 0-0xfe)
-added song position as argument to command 0x0110
-slightly changed (improved?) timing behaviour for methods 3 and 5 (use time at start of tick processing as reference)
-new experimental timing method 7 with own timer running at constant resolution (you must additionally enable the timer in the options menu), but without much improvement ?, it also doesn't allow delay, slide, retrigger, sync and MTC
-timer resolution is now saved with the song
-added smart sync restart option (greetings to Rikard and Hagen for this one), sync start commands with given song position are only processed after a BUZZ pause, if no sync was running or if song position decreases (to allow looping).

version 1g:
some funny things inspired by the buzz-talk community:
-track and machine transposing (commands 0x0130,0x0131 and 0x0132)
-using different scales (implemented via pitchwheel, so monophone channels are needed, a pitchwheel reange of 2 halftones up/down is assumed), a few hard coded scales (taken from VAZ) and >1000 loadable from a scale library I had on my HD.
Thanks to these people for the work, read the text file for details
>These scales were brought together mostly by John Chalmers
>(non12@cyber.net) and Manuel Op de Coul (coul@ezh.nl).
The user scale will be saved with the song. And finally MIDI playability is useful a bit ;)
-chords command 0x0140: the chord values are completely taken from Argüelles TB3003, I hope you don't mind. Of course this doesn't work with any non-standard scales.

version 1h:
-pitchwheel reset in machine menu
-additional chord commands 0x141-0x145 to build almost any chord

possible plans/future (and still missing things):

- any way of further improving timer sync or new wave based sync?
- cue-switching per track? -> more convenient retrigger if longer than 1 row
- correct handling of 14Bit controllers and NRP's
- "personal sync" for m2buzz: send a note on one channel every row, volume set to zero (hopefully obsolete now ;)
- easy slides option? (for systems with high latency only):
probably not, it's easy enough now ;)
- retrigger commands with varying pitch and/or delay (using the Effect slide byte)
- another version with velocity [0...0x7f] ->volume [0...0xfe] and 16Bit Effect Change ?:
probably not before everything else is working nice enough
- SysX-Realtime: MTC full frame messages
- SysX: MasterVolume
- allow/handle several timers ?

contact me: ( vII) or look at my Homepage