MIDISynth driver module
-----------------------
v0.25 20/11/24

This module is a driver for the MidiSupport module. It should be located
in the !MidiSupport.Drivers directory.

Command:
--------

 MidiSynth:

  Syntax: MidiSynth [-option [-option ...]]

  Options:
   -r reset the synthesiser
   -s stereo audio (default)
   -m mono audio
   -w swap L/R audio channels
   -n<x> x = number of generators (polyphony), 4 to 64, default 32
   -g<x> x = glide time, scale factor, 0 to 1000, 0 = disable, default 100 
   -t<x> x = sleep timeout in seconds, 0 to 3600, 0 = disable, default 10
   -v<x> GM variation banks, x = 0 disable, x = 1 allowed, default 0
   -b<x> x = bank override, x = 1 to 127 to use this bank, 0 disables override
   -k<x> x = drum kit override, x = 1 to 127 to use this kit, 0 disables override
   -i display information
   -i+ as -i with additional information

  Following options are used for testing
   -o open log file in the current directory
   -c close log file
   -d<x> x = the sum of the following values
    1 = log midi messages
    2 = log ticker callbacks
   
Notes:
------

Reset:

 To reset the synth, use the command MidiSynth -r

 Changing the polyphony resets the synth.

 A reset will instantly mute all notes and all instruments will
 become Acoustic Grand Pianos.
 
Volume:

 The synth supports the system volume via shared sound and the
 MIDI system exclusive master volume command.
 
Sound Sets:

 The synth starts with a default sound set. It will then try to
 load a sound set file from the <MIDISynthChoices$Dir> directory.
 
 Instrument banks other than bank 0 may contain variations of bank
 0. If this is a problem, variation banks can be disabled using
 the swi or command.


SWI interface:
--------------

MIDISynth_Control  &CA340
-------------------------

 Read/Write general controls
 
 Entry:
  r1 = pointer to block for return data, word aligned (13 integers)
 
  r0 = 0  Do nothing, just read values
  
     = 1  Update number of generators (polyphony)
          r2 = new number of generators 4..64
          
     = 2  Update glide time (portamento) scale factor
          r2 = new scale factor 0..1000,
               0 = disable portamento
               1 = fastest
               1000 = slowest
               100 = default, to suit the current MIDI spec
               
     = 3  Update sleep timeout. Synth stops generating after this period of
          inacivity in seconds, to reduce unnecessary cpu loading.
          Inactivity is defined as no received MIDI messages.
          r2 = timeout 0..3600
               0 = disable timeout so the synth never stops.
               10 = default
          Going to sleep and waking up is instant and not noticeable.
          
     = 4  Update flags, default values are all zero.
          flags = flags AND NOT r2 EOR r3
           
           bit 0: 0 = stereo audio.
                  1 = mono audio.

           bit 1: 0 = normal stereo.
                  1 = swap left/right channels.

           bit 2: 0 = only allow instrument bank 0.
                  1 = allow all banks.

           bit 3: 0 = only allow drum kit 0.
                  1 = allow all kits.

           bit 4: 0 = fixed percussion channel.
                  1 = allow bank hi to select. 

           bit 5: 0 = Bank messages actioned when received.
                  1 = Bank messages actioned on the next Program change.

           bit 6: 0 = CSV bank map includes instrument number. 
                  1 = CSV bank map excludes instrument number.

           bit 7: 0 = Patch list includes drum kits.
                  1 = Patch list excludes drum kits.

           bit 8: 0 = Patch list order is all Banks within each Program.
                  1 = Patch list order is all Programs within each Bank.
                  
     = 5  Reset the synth.
     
     = 6  Bank Override. Sets the bank to use, overriding the bank set by
          MIDI messages. The bank will default to Bank 0 for any instruments
          that are not defined in the override bank.
          r2 = bank number
               0 = disable bank override
               1..127 = bank to use
          
     = 7  Drum kit Override. Sets the kit to use, overriding the kit set by
          MIDI messages. The kit will default to kit 0 for any drum kit parts
          that are not defined in the override kit.
          r2 = drum kit number
               0 = disable drum kit override
               1..127 = drum kit to use
    
     = 8  Percussion channel. Sets the channel number when fixed and not
          selectable via midi bank hi = 127.
          r2 = 1..16, percussion channel
          
     = 9  Set the master volume
          r2 = 0..1023, default 1023
          
     = 10 Set the master balance
          r2 = 0..1023, default 512
          
     = 11 Set the master coarse tuning, in semitones
          r2 = -64..63, default 0
          
     = 12 Set the master fine tuning, to a maximum of +- a semitone
          r2 = -8192..8191, default 0
          
     = 13 Save the current options.
    
 Exit:

  blk[0] = Number of generators.
  blk[1] = Glide time scale factor.
  blk[2] = Sleep timeout.
  blk[3] = Flags.
  blk[4] = Bank override,
  blk[5] = Drum kit override,
  blk[6] = Current percussion channel
  blk[7] = Default percussion channel
  blk[8] = Sample Rate
  blk[9] = Master volume
  blk[10] = Master balance
  blk[11] = Master coarse tuning
  blk[12] = Master fine tuning
  
  Registers unchanged.


MIDISynth_Edit  &CA341
----------------------

 Provides control and access to the user instrument which is the instrument
 used by the editor. It is not accessible by MIDI commands. When the Synth
 starts or is reset, the current patch is set to 0 and the user instrument is
 loaded from the instrument the patch defines, usually the Acoustic Grand Piano.
 
 Entry:
  r1 = pointer to block for return data, word aligned (10 integers)
 
  r0 = 0  Do nothing, just read values
  
     = 1  Load user from the given patch.
          r2 = patch number.
          
     = 2 Load user from the given instrument number.
          r2 = instrument number.
     
     = 3  Save user to the given patch.
          r2 = patch number.
          
     = 4  Saves/Copies/Moves the current Instrument.
          r2 = patch,
               bits: 23-16 Program, 15-8 Bank Lo, 7-0 Bank Hi
          If Bank Hi > 127, the instrument is a percussive instrument and
          is located at, Bank Lo = Key, Program = Bank.
          If Bank Hi < 127, the instrument is a melodic instrument and
          is located at, Bank Lo = Bank, Program = Program.
          A new bank or kit is created if required.

          r3 = 0: Save user as a new instrument located at the given
                  patch reference in r2.
                  
          r3 = 1: Make a bank reference to the current instrument at the
                  given patch reference in r2.
          
          r3 = 2: Move the instrument from the current patch reference to
                  the given patch reference in r2.
                  
          Any of these operations will overwrite any existing instrument
          reference pointed to by the patch in r2. 
     
     = 5  Save user as new instrument in the next bank up,
          This creates a new instrument and also creates a new bank if needed.
     
     = 6  Delete the current Instrument and/or bank references to it.
          r2 = 0: Delete the instrument defined by the current patch and all
                  bank references to it. If this results in an empty bank, it
                  will also be deleted.
                  
          r2 = 1: Clears the current bank reference (patch) to the instrument.
                  Does not delete the actual instrument or any other references
                  to it.
     
     The current patch is the most recent instrument to be loaded into the
     user instrument for editing. After creating or deleting instruments a
     new patch list is created.
  
 The following reason codes perform operations on the whole Sound Set.
 
  r0 = 7  Save Sound Set to file.
          r2 = pointer to null terminated pathname. (1)

     = 8  Save Sound Set without waveforms to file.
          r2 = pointer to null terminated pathname. (1)
     
     = 9  Save Sound Set as ...
          r2 = pointer to null terminated pathname. (1)
          r3 = flags:
               bit 0: save a c source code with /c filename extension
               bit 1: save a text patch list with /txt filename extension
               bit 2: save a csv bank map with /csv filename extension
               bit 3: save a text instrument list with /lst filename extension 
          All bits can be set and then 4 files are saved.
          The /c source file can be used for the default sound set
          when building the synth software.
          
     = 10 Load the default Sound Set. This is the set contained within the
          synth code.
               
     = 11 Load the Sound Set from a DATA file. 
          r2 = pointer to null terminated pathname. (1)
          
     = 12 Load a CSV Bank Map file.
          r2 = pointer to null terminated pathname.
          Loads a CSV bank map file and creates a sound set from it using the
          existing instrument array. If an error is encountered, nothing is
          changed and the error is returned. If all is ok, the banks and bank
          selectors are replaced. The instrument and waveform arrays are not
          changed. This means that the sound set name and bank names in the
          file are used but not instrument names, the instrument number is all
          that is needed. All instruments referred to in the CSV file MUST be
          defined in the existing sound set. This method of saving, editing, and
          loading back CSV files can only change the bank mapping. An Instrument
          can be referenced in more than one bank location. 
          The new sound set that is created will need to be saved (if required).
               
     = 13 flags to control the use of the edit waveform by the user instrument
          default values are all zero.
          flags = flags AND NOT r2 EOR r3
           
           bit 0: 0 = normal operation.
                  1 = user instrument oscillator 1 uses the edit waveform.

           bit 1: 0 = normal operation.
                  1 = user instrument oscillator 2 uses the edit waveform.

           bit 2: 0 = normal operation.
                  1 = user instrument modulation oscillator uses the edit
                      waveform.
                      
           r4 = pointer to the edit waveform harmonic array.
           
     = 14 Save / delete wave harmonics data.
           r2 = pointer to harmonic data, if 0 then command is delete
           r3 = array index to store / delete. if -1, then command is
                "save new" and the first empty slot will be used.
          
     (1) If r2 is a pathname pointer and is = 0, files are loaded to and saved
         from the Choices Directory with the default name "SoundSet".
     
 Exit:

  This information is returned after every operation to keep the editor in
  sync with the synth.
    
  blk[0] = pointer to instrument definition array
  blk[1] = current patch number
  blk[2] = pointer to waveform harmonics array
  blk[3] = number of waveforms
  blk[4] = number of patches
  blk[5] = current patch (Hi,Lo,Prg)
  blk[6] = pointer to bank name
  blk[7] = pointer to sound set name
  blk[8] = current instrument number
  blk[9] = number of instruments
  
  Registers unchanged.


MIDISynth_Note  &CA342
----------------------

 Sends note on/off commands to the synth which will apply them to the user
 instrument being edited.

 Entry:

  r0 = MIDI Note on or Note off command.
        bits  0..7  = Status
        bits  8..15 = Pitch
        bits 16..23 = Velocity
        bits 24..31 = 0

 Exit:
  Registers unchanged.
  
 The channel number in the status byte is not used

-----------------------------------------------------

