===============================================================================
              MIDI playing bank for Yamaha OPN2 (YM2612) chip
                 file format specification (WOPN and OPNI)
===============================================================================
                         Created in April, 30, 2017
===============================================================================
Author:             Vitaliy Novichkov "Wohlstand"
Contacts emails:    admin@wohlnet.ru, nvd339@yandex.ru
===============================================================================

Versions:
- Version 1: (April, 30, 2017): First release
- Version 2: (November, 24, 2017): Added bank meta-data
              and measured sounding delays per each instrument
             (November, 18, 2018): Added OPN2/OPNA global chip flag
- Version 3: (DRAFT)
             Added pitch envelope options and sample instrument support
             Added per-instrument flags
             Added bank default volume model field
             Instruments now having variable size in dependence on flags

===============================================================================
Contents:
    1. Single-instrument entry
    2. Instrument file (OPNI)
    3. MIDI playing bank file (WOPN)
===============================================================================


===============================================================================
                        1. Single-instrument entry
===============================================================================

    Each instrument file contains a set of data for single
channel of YM2612 chip to setup the timbre

Length of each instrument entry is:
Version 2: Fixed size in 65 bytes or 69 with sounding delays
Version 3: Size is dependent on flags:
    - base (minimal) size: 66 bytes = 1 + (32+2+1+1+1)+(4*(1+1+1+1+1+1+1))
    - flag A adds extra 65 bytes = (32+2+1+1+1)+(4*(1+1+1+1+1+1+1))
    - flag C adds extra 12 bytes = 2+2+2+2+2+2
    - flag D adds extra 10 bytes = 2+2+2+2+1+1
    - sounding delays adding extra: 4 bytes = 2+2

Bytes-Length  | Description
----VERSION>=3-----------------------------
    1         | Instrument flags
              |     [0000DCBA]
              |     A) Pseudo-8op
              |     B) Is Blank instrument
              |     C) Enable pitch envelope
              |     D) Is non-FM voice
-------------------------------------------

----VERSION<=2-OR=when flag D is disabled----

----[When flag A(Pseudo8op) is set - repeat this block 2 times]-------
    32        | Name of instrument null-terminated string
    2         | Big-Endian 16-bit signed integer, MIDI key offset value
    1         | 8-bit unsigned integer, Percussion instrument key number
    1         | Feedback and Algorithm register data
    1         | Global bank flags
              |     [000CBAAA]
              |     A) LFO sensitivity frequency
              |     B) LFO is enabled
              |     C) Chip type: 0:OPN2, 1:OPNA
--- Operators 1/2/3/4 (repeats 4 times) ---
    1         | Detune and frequency multiplication register data
    1         | Total level register data
    1         | Rate scale and attack register data
    1         | Amplitude modulation enable and Decay-1 register data
    1         | Decay-2 register data
    1         | Sustain and Release register data
    1         | SSG-EG register data
-------------------------------------------

----[When flag A(Pseudo8op) is set]--------
    1         | Pan flags //Allows stereo voices splited by left-right channels
              |     [0000DCBA]
              |     A) Left channel of first voice
              |     B) Right channel of first voice
              |     C) Left channel of second vocie
              |     D) Right channel of second voice
    1         | INT8, Second voice detune
----[When flag A(Pseudo8op) is set]-END----

----VERSION<=2-OR-when flag D is disabled-END--

----VERSION>=3-----------------------------
------[Only when flag C is set]-------
    2         | UINT16BE, pitch envelope bend sensitivity
    2         | SINT16BE, pitch envelope bend sustain (+ up, - down)
    2         | UINT16BE, Millisecond pitch attack delay (0 - instant attack)
    2         | UINT16BE, Millisecond pitch decay1 delay (0 - instant decay)
    2         | UINT16BE, Millisecond pitch decay2 delay (0 - instant decay)
    2         | UINT16BE, Millisecond pitch release delay (0 - instant release)
------[Only when flag C is set]-END---
    1         | UINT8, Count of layers (concurrent streams)
----------[Layer begin]-------------------
    1         | UINT8, Count of used chunks
--------------[Chunk begin]-------------------
    2         | UINT16BE, Index into LayeredInstruments
--------------[Chunk end]-------------------
----------[Layer end]-------------------

----VERSION>=3-END-------------------------

--VERSION >= 2---WOPN-Bank-only, OPNI must don't have those fields---
    2         | Big-Endian 16-bit signed integer, Millisecond delay of sound
              | while key is on
    2         | Big-Endian 16-bit signed integer, Millisecond delay of sound
              | after key off
-------------------------------------------


===============================================================================
                         2. Instrument file (OPNI)
===============================================================================

    Each instrument file contains a set of data for single
channel of YM2612 chip to setup the timbre on it.

Total data length:
    Version 1: 77 bytes
    Version 2: 79 bytes
    Version 3:
        102 bytes (with disabled PCM chunk)
        136+[ChunkLength] bytes (with PCM chunk)

Bytes-Length |  Description
---------------Header--------------------
----VERSION==1--------------------------
    11       |  Magic number "WOPN2-INST\0". Where '\0' is a zero byte which
             |  termiates the string
             | (Version-1 has no version number entry!!!)
----VERSION>=2--------------------------
    11       |  Magic number "WOPN2-IN2T\0". Where '\0' is a zero byte which
             |  termiates the string
    2        | Version code Unsigned 16-bit little-endian integer
----------------------------------------
    1        |  Is this instrument a percussion. 0 - melodic, or 1 - percussion
----VERSION<=2--Data---------------------
    65       |  [Single-instrument entry], look at top of this text file
----VERSION>=3--Data---------------------
    86       |  [Single-instrument entry], look at top of this text file
----VERSION>=3--PCM Chunk---------------
    <Same as in bottom of WOPN bank>
----------------------------------------


===============================================================================
                      3. MIDI playing bank file (WOPN)
===============================================================================

    Bank format designed to store instrument bank for playing MIDI
in multiple standards like GM, GS and XG. Format allows to save
multiple sets with 128-instruments which is needed to store
GS and XG instrument sets which are have more than standard 128
instruments with a single bank.

Total data length is sum of (version 1):
        16 + (65*128*MBanks) + (65*128*PBanks) bytes
Total data length is sum of (version 2):
        18 + (69*128*MBanks) + (69*128*PBanks) bytes
Total data length is sum of (version 3):
        24 + (92*128*MBanks) + (92*128*PBanks) + (PCMBankSize) bytes

Bytes-Length |      Description
---------------Header--------------------
--Header--

----VERSION==1--------------------------
    11            | Magic number "WOPN2-BANK\0". Where '\0' is a zero byte
                  |     which termiates the string
                  | (Version-1 has no version number entry!!!)
----VERSION==1-END----------------------

----VERSION>=2--------------------------
    11            | Magic number "WOPN2-B2NK\0". Where '\0' is a zero byte
                  |     which termiates the string
    2             | Version code Unsigned 16-bit little-endian integer
----VERSION>=2-END----------------------

    2             | [MBanks] UINT16BE, count of melodic banks
                  |     MIDI banks (every bank contains 128 instruments)
    2             | [PBanks] UINT16BE, count of percussion banks
                  |     MIDI banks (every bank contains 128 instruments)
----VERSION>=3--------------------------
    2             | [SampleChunks] UINT16BE, Count of sample chunks stored in the file
    2             | [LayeredInstruments] UINT16BE, Count of layered instruments stored in the file
----VERSION>=3-END----------------------

    1             | UINT8, Chip global LFO enable flag and frequency register data

----VERSION>=3--------------------------
    1             | UINT8, Volume model type
----VERSION>=3-END----------------------

--VERSION >= 2---Melodic bank meta-data-----
(repeat MBanks times)
    32            | Name of melodic bank null-terminated string
    1             | LSB index of bank (unsigned char)
    1             | MSB index of bank (unsigned char)
--VERSION >= 2---Percussion bank meta-data--
(repeat PBanks times)
    32            | Name of melodic bank null-terminated string
    1             | LSB index of bank (unsigned char)
    1             | MSB index of bank (unsigned char)

-----------Melodic Instruments-----------
    65*128*MBanks | 128 [Single-instrument entries] per each bank,
                  |     look at top of this text file
---------Percussion Instruments----------
    65*128*PBanks | 128 [Single-instrument entries] per each bank,
                  |     look at top of this text file

--VERSION >= 3---Sample chunk--------
(repeat SampleChunks times)
    4             | UINT32BE, Sample name, as byte index into the string segment
    4             | UINT32BE, Sound data, as byte index into the data segment
    4             | UINT32BE, Length of sound data in bytes
    4             | UINT32BE, Sampling rate of the sound data
    1             | UINT8, Number of channels in interleaved sample data
    1             | UINT8, Coding of sample data.
                  |        0 - UINT8 PCM data
                  |        1 - INT16BE PCM data
                  |        Reserved - (Float, Compressed audio...)
----VERSION>=3-END----------------------

--VERSION >= 3---LayeredInstrument chunk----
(repeat LayeredInstruments times)
    1             | UINT8, [Tag] Type of instrument
                  |        0 - Sampled instrument based of SFZ specification
                  |        Reserved - (PSG instrument...)
    4             | UINT32BE, Size of this entire chunk in bytes
-[if Tag=0 for SFZ instrument]-
    2             | UINT16BE, [AttrCount] Count of SFZ attributes as key-value pairs
(repeat AttrCount times)
    1             | UINT8, Number of region on which an attribute is applied
                  |        if $FF, applies to the whole group (all regions)
    4             | UINT32BE, [Opcode] Opcode as index into the string segment
                  |                    The SFZ opcode "sample" references one of the
                  |                    sample chunks by its stored name.
    1             | UINT8, [ValueType] Type of value to follow
                  |        0 - String:  UINT32BE, index into string table
                  |        1 - Integer: INT32BE, integer
                  |        2 - Real:    FLOAT32BE, IEEE754 single precision
                  |        Reserved
    4             | VAR32, Value encoded as indicated by ValueType
(end repeat)
-[/if Tag=0 for SFZ instrument]-
----VERSION>=3-END----------------------

----VERSION>=3---String segment---------
    4            | [StrSize] Segment size expressed in bytes
    StrSize      | UINT8, Concatenation of UTF-8 strings, using a zero byte as
                 |        separator of entries.
----VERSION>=3-END----------------------

----VERSION>=3---Data segment---------
    4            | [DataSize] Segment size expressed in bytes
    DataSize     | UINT8, Data as concatenated sequence of bytes.
----VERSION>=3-END----------------------
