/**
 * Description: SoundFont Technical Specification.
 *
 * @package     midi-Synth
 * @category    module js
 * @author      Oleg Klenitsky <https://adminkov.bcr.by/midi/>
 * @copyright
 * @license     GPL-2.0-or-later
 */

"use strict";

var arrDocGenSF = [
  {name: "startAddrsOffset", description: "The offset, in sample data points, beyond the Start sample header parameter to the first sample data point to be played for this instrument.For example, if Start were 7 and startAddrOffset were 2, the first sample data point played would be sample data point 9."},
  {name: "endAddrsOffset", description: "The offset, in sample sample data points, beyond the End sample header parameter to the last sample data point to be played for this instrument. For example, if End were 17 and endAddrOffset were -2, the last sample data point played would be sample data point 15."},
  {name: "startloopAddrsOffset", description: "The offset, in sample data points, beyond the Startloop sample header parameter to the first sample data point to be repeated in the loop for this instrument. For example, if Startloop were 10 and startloopAddrsOffset were -1, the first repeated loop sample data point would be sample data point 9."},
  {name: "endloopAddrsOffset", description: "The offset, in sample data points, beyond the Endloop sample header parameter to the sample data point considered equivalent to the Startloop sample data point for the loop for this instrument. For xample, if Endloop were 15 and endloopAddrsOffset were 2, sample data point 17 would be considered equivalent to the Startloop sample data point, and hence sample data point 16 would effectively precede Startloop during looping."},
  {name: "startAddrsCoarseOffset", description: "The offset, in 32768 sample data point increments beyond the Start sample header parameter and the first sample data point to be played in this instrument. This parameter is added to the startAddrsOffset parameter. For example, if Start were 5, startAddrsOffset were 3 and startAddrsCoarseOffset were 2, the first sample data point played would be sample data point 65544."},
  {name: "modLfoToPitch", description: "This is the degree, in cents, to which a full scale excursion of the Modulation LFO will influence pitch. A positive value indicates a positive LFO excursion increases pitch; a negative value indicates a positive excursion decreases pitch. Pitch is always modified logarithmically, that is the deviation is in cents, semitones, and octaves rather than in Hz. For example, a value of 100 indicates that the pitch will first rise 1 semitone, then fall one semitone."},
  {name: "vibLfoToPitch", description: "This is the degree, in cents, to which a full scale excursion of the Vibrato LFO will influence pitch. A positive value indicates a positive LFO excursion increases pitch; a negative value indicates a positive excursion decreases pitch. Pitch is always modified logarithmically, that is the deviation is in cents, semitones, and octaves rather than in Hz. For example, a value of 100 indicates that the pitch will first rise 1 semitone, then fall one semitone."},
  {name: "modEnvToPitch", description: "This is the degree, in cents, to which a full scale excursion of the Modulation Envelope will influence pitch. A positive value indicates an increase in pitch; a negative value indicates a decrease in pitch. Pitch is always modified logarithmically, that is the deviation is in cents, semitones, and octaves rather than in Hz. For example, a value of 100 indicates that the pitch will rise 1 semitone at the envelope peak."},
  {name: "initialFilterFc", description: "This is the cutoff and resonant frequency of the lowpass filter in absolute cent units. The lowpass filter is defined as a second order resonant pole pair whose pole frequency in Hz is defined by the Initial Filter Cutoff parameter. When the cutoff frequency exceeds 20kHz and the Q (resonance) of the filter is zero, the filter does not affect the signal."},
  {name: "initialFilterQ", description: "This is the height above DC gain in centibels which the filter resonance exhibits at the cutoff frequency. A value of zero or less indicates the filter is not resonant; the gain at the cutoff frequency (pole angle) may be less than zero when zero is specified. The filter gain at DC is also affected by this parameter such that the gain at DC is reduced by half the specified gain"},
  {name: "modLfoToFilterFc", description: "This is the degree, in cents, to which a full scale excursion of the Modulation LFO will influence filter cutoff frequency. A positive number indicates a positive LFO excursion increases cutoff frequency; a negative number indicates a positive excursion decreases cutoff frequency. Filter cutoff frequency is always modified logarithmically, that is the deviation is in cents, semitones, and octaves rather than in Hz."},
  {name: "modEnvToFilterFc", description: "This is the degree, in cents, to which a full scale excursion of the Modulation Envelope will influence filter cutoff frequency. A positive number indicates an increase in cutoff frequency; a negative number indicates a decrease in filter cutoff frequency. Filter cutoff frequency is always modified logarithmically, that is the deviation is in cents, semitones, and octaves rather than in Hz."},
  {name: "endAddrsCoarseOffset", description: "The offset, in 32768 sample data point increments beyond the End sample header parameter and the last sample data point to be played in this instrument. This parameter is added to the endAddrsOffset parameter."},
  {name: "modLfoToVolume", description: "This is the degree, in centibels, to which a full scale excursion of the Modulation LFO will influence volume. A positive number indicates a positive LFO excursion increases volume; a negative number indicates a positive excursion decreases volume. Volume is always modified logarithmically, that is the deviation is in decibels rather than in linear amplitude."},
  {name: "unused1", description: "Unused, reserved. Should be ignored if encountered."},
  {name: "chorusEffectsSend", description: "This is the degree, in 0.1% units, to which the audio output of the note is sent to the chorus effects processor. A value of 0% or less indicates no signal is sent from this note; a value of 100% or more indicates the note is sent at full level. Note that this parameter has no effect on the amount of this signal sent to the “dry” or unprocessed portion of the output."},
  {name: "reverbEffectsSend", description: "This is the degree, in 0.1% units, to which the audio output of the note is sent to the reverb effects processor. A value of 0% or less indicates no signal is sent from this note; a value of 100% or more indicates the note is sent at full level. Note that this parameter has no effect on the amount of this signal sent to the “dry” or unprocessed portion of the output."},
  {name: "pan", description: "This is the degree, in 0.1% units, to which the “dry” audio output of the note is positioned to the left or right output. A value of -50% or less indicates the signal is sent entirely to the left output and not sent to the right output; a value of +50% or more indicates the note is sent entirely to the right and not sent to the left. A value of zero places the signal centered between left and right."},
  {name: "unused2", description: "Unused, reserved. Should be ignored if encountered."},
  {name: "unused3", description: "Unused, reserved. Should be ignored if encountered."},
  {name: "unused4", description: "Unused, reserved. Should be ignored if encountered."},
  {name: "delayModLFO", description: "This is the delay time, in absolute timecents, from key on until the Modulation LFO begins its upward ramp from zero value. A value of 0 indicates a 1 second delay. A negative value indicates a delay less than one second and a positive value a delay longer than one second. The most negative number (-32768) conventionally indicates no delay."},
  {name: "freqModLFO", description: "This is the frequency, in absolute cents, of the Modulation LFO’s triangular period. A value of zero indicates a frequency of 8.176 Hz. A negative value indicates a frequency less than 8.176 Hz; a positive value a frequency greater than 8.176 Hz."},
  {name: "delayVibLFO", description: "This is the delay time, in absolute timecents, from key on until the Vibrato LFO begins its upward ramp from zero value. A value of 0 indicates a 1 second delay. A negative value indicates a delay less than one second; a positive value a delay longer than one second. The most negative number (-32768) conventionally indicates no delay."},
  {name: "freqVibLFO", description: "This is the frequency, in absolute cents, of the Vibrato LFO’s triangular period. A value of zero indicates a frequency of 8.176 Hz. A negative value indicates a frequency less than 8.176 Hz; a positive value a frequency greater than 8.176 Hz."},
  {name: "delayModEnv", description: "This is the delay time, in absolute timecents, between key on and the start of the attack phase of the Modulation envelope. A value of 0 indicates a 1 second delay. A negative value indicates a delay less than one second; a positive value a delay longer than one second. The most negative number (-32768) conventionally indicates no delay."},
  {name: "attackModEnv", description: "This is the time, in absolute timecents, from the end of the Modulation Envelope Delay Time until the point at which the Modulation Envelope value reaches its peak. Note that the attack is “convex”; the curve is nominally such that when applied to a decibel or semitone parameter, the result is linear in amplitude or Hz respectively. A value of 0 indicates a 1 second attack time. A negative value indicates a time less than one second; a positive value a time longer than one second."},
  {name: "holdModEnv", description: "This is the time, in absolute timecents, from the end of the attack phase to the entry into decay phase, during which the envelope value is held at its peak. A value of 0 indicates a 1 second hold time. A negative value indicates a time less than one second; a positive value a time longer than one second. The most negative number (-32768) conventionally indicates no hold phase."},
  {name: "decayModEnv", description: "This is the time, in absolute timecents, for a 100% change in the Modulation Envelope value during decay phase. For the Modulation Envelope, the decay phase linearly ramps toward the sustain level. If the sustain level were zero, the Modulation Envelope Decay Time would be the time spent in decay phase. A value of 0 indicates a 1 second decay time for a zero-sustain level. A negative value indicates a time less than one second; a positive value a time longer than one second."},
  {name: "sustainModEnv", description: "This is the decrease in level, expressed in 0.1% units, to which the Modulation Envelope value ramps during the decay phase. For the Modulation Envelope, the sustain level is properly expressed in percent of full scale. Because the volume envelope sustain level is expressed as an attenuation from full scale, the sustain level is analogously expressed as a decrease from full scale. A value of 0 indicates the sustain level is full level; this implies a zero duration of decay phase regardless of decay time. A positive value indicates a decay to the corresponding level."},
  {name: "sustainModEnv", description: "This is the decrease in level, expressed in 0.1% units, to which the Modulation Envelope value ramps during the decay phase. For the Modulation Envelope, the sustain level is properly expressed in percent of full scale. Because the volume envelope sustain level is expressed as an attenuation from full scale, the sustain level is analogously expressed as a decrease from full scale. A value of 0 indicates the sustain level is full level; this implies a zero duration of decay phase regardless of decay time. A positive value indicates a decay to the corresponding level."},
  {name: "releaseModEnv", description: "This is the time, in absolute timecents, for a 100% change in the Modulation Envelope value during release phase. For the Modulation Envelope, the release phase linearly ramps toward zero from the current level. If the current level were full scale, the Modulation Envelope Release Time would be the time spent in release phase until zero value were reached. A value of 0 indicates a 1 second decay time for a release from full level. A negative value indicates a time less than one second; a positive value a time longer than one second."},
  {name: "keynumToModEnvHold", description: "This is the degree, in timecents per curNote units, to which the hold time of the Modulation Envelope is decreased by increasing MIDI key number. The hold time at key number 60 is always unchanged. The unit scaling is such that a value of 100 provides a hold time which tracks the keyboard; that is, an upward octave causes the hold time to halve."},
  {name: "keynumToModEnvDecay", description: "This is the degree, in timecents per curNote units, to which the hold time of the Modulation Envelope is decreased by increasing MIDI key number. The hold time at key number 60 is always unchanged. The unit scaling is such that a value of 100 provides a hold time that tracks the keyboard; that is, an upward octave causes the hold time to halve."},
  {name: "delayVolEnv", description: "This is the delay time, in absolute timecents, between key on and the start of the attack phase of the Volume envelope. A value of 0 indicates a 1 second delay. A negative value indicates a delay less than one second; a positive value a delay longer than one second. The most negative number (-32768) conventionally indicates no delay."},
  {name: "delayVolEnv", description: "This is the delay time, in absolute timecents, between key on and the start of the attack phase of the Volume envelope. A value of 0 indicates a 1 second delay. A negative value indicates a delay less than one second; a positive value a delay longer than one second. The most negative number (-32768) conventionally indicates no delay."},
  {name: "attackVolEnv", description: "This is the time, in absolute timecents, from the end of the Volume Envelope Delay Time until the point at which the Volume Envelope value reaches its peak. Note that the attack is “convex”; the curve is nominally such that when applied to the decibel volume parameter, the result is linear in amplitude. A value of 0 indicates a 1 second attack time. A negative value indicates a time less than one second; a positive value a time longer than one second. The most negative number (-32768) conventionally indicates instantaneous attack."},
  {name: "holdVolEnv", description: "This is the time, in absolute timecents, from the end of the attack phase to the entry into decay phase, during which the Volume envelope value is held at its peak. A value of 0 indicates a 1 second hold time. A negative value indicates a time less than one second; a positive value a time longer than one second. The most negative number (-32768) conventionally indicates no hold phase."},
  {name: "decayVolEnv", description: "This is the time, in absolute timecents, for a 100% change in the Volume Envelope value during decay phase. For the Volume Envelope, the decay phase linearly ramps toward the sustain level, causing a constant dB change for each time unit. If the sustain level were -100dB, the Volume Envelope Decay Time would be the time spent in decay phase. A value of 0 indicates a 1-second decay time for a zero-sustain level. A negative value indicates a time less than one second; a positive value a time longer than one second."},
  {name: "sustainVolEnv", description: "This is the decrease in level, expressed in centibels, to which the Volume Envelope value ramps during the decay phase. For the Volume Envelope, the sustain level is best expressed in centibels of attenuation from full scale. A value of 0 indicates the sustain level is full level; this implies a zero duration of decay phase regardless of decay time. A positive value indicates a decay to the corresponding level. Values less than zero are to be interpreted as zero; conventionally 1000 indicates full attenuation."},
  {name: "releaseVolEnv", description: "This is the time, in absolute timecents, for a 100% change in the Volume Envelope value during release phase. For the Volume Envelope, the release phase linearly ramps toward zero from the current level, causing a constant dB change for each time unit. If the current level were full scale, the Volume Envelope Release Time would be the time spent in release phase until 100dB attenuation were reached. A value of 0 indicates a 1-second decay time for a release from full level.A negative value indicates a time less than one second; a positive value a time longer than one second."},
  {name: "keynumToVolEnvHold", description: "This is the degree, in timecents per curNote units, to which the hold time of the Volume Envelope is decreased by increasing MIDI key number. The hold time at key number 60 is always unchanged. The unit scaling is such that a value of 100 provides a hold time which tracks the keyboard; that is, an upward octave causes the hold time to halve."},
  {name: "keynumToVolEnvDecay", description: "This is the degree, in timecents per curNote units, to which the hold time of the Volume Envelope is decreased by increasing MIDI key number. The hold time at key number 60 is always unchanged. The unit scaling is such that a value of 100 provides a hold time that tracks the keyboard; that is, an upward octave causes the hold time to halve."},
  {name: "instrument", description: "This is the index into the INST sub-chunk providing the instrument to be used for the current preset zone. A value of zero indicates the first instrument in the list. The value should never exceed two less than the size of the instrument list. The instrument enumerator is the terminal generator for PGEN zones. As such, it should only appear in the PGEN sub-chunk, and it must appear as the last generator enumerator in all but the global preset zone."},
  {name: "reserved1", description: "Unused, reserved. Should be ignored if encountered."},
  {name: "keyRange", description: "This is the minimum and maximum MIDI key number values for whichthis preset zone or instrument zone is active. The LS byte indicates the highest and the MS byte the lowest valid key. The keyRange enumerator is optional, but when it does appear, it must be the first generator in the zone generator list."},
  {name: "velRange", description: "This is the minimum and maximum MIDI velocity values for which this preset zone or instrument zone is active. The LS byte indicates the highest and the MS byte the lowest valid velocity. The velRange enumerator is optional, but when it does appear, it must be preceded only by keyRange in the zone generator list."},
  {name: "startloopAddrsCoarseOffset", description: "The offset, in 32768 sample data point increments beyond the Startloop sample header parameter and the first sample data point to be repeated},in this instrument’s loop. This parameter is added to the startloopAddrsOffset parameter. For example, if Startloop were 5, startloopAddrsOffset were 3 and startAddrsCoarseOffset were 2, the first sample data point in the loop would be sample data point 65544."},
  {name: "keynum", description: "This enumerator forces the MIDI key number to effectively be interpreted as the value given. This generator can only appear at the instrument level. Valid values are from 0 to 127."},
  {name: "velocity", description: "This enumerator forces the MIDI velocity to effectively be interpreted as the value given. This generator can only appear at the instrument level. Valid values are from 0 to 127."},
  {name: "initialAttenuation", description: "This is the attenuation, in centibels, by which a note is attenuated belowbfull scale. A value of zero indicates no attenuation; the note will be played at full scale. For example, a value of 60 indicates the note will be played at 6 dB below full scale for the note."},
  {name: "reserved2", description: "Unused, reserved. Should be ignored if encountered."},
  {name: "endloopAddrsCoarseOffset", description: "The offset, in 32768 sample data point increments beyond the Endloop sample header parameter to the sample data point considered equivalent to the Startloop sample data point for the loop for this instrument. This parameter is added to the endloopAddrsOffset parameter. For example, if Endloop were 5, endloopAddrsOffset were 3 and endAddrsCoarseOffset were 2, sample data point 65544 would be considered equivalent to the Startloop sample data point, and hence sample data point 65543 would effectively precede Startloop during looping."},
  {name: "coarseTune", description: "This is a pitch offset, in semitones, which should be applied to the note. A positive value indicates the sound is reproduced at a higher pitch; a negative value indicates a lower pitch. For example, a Coarse Tune value of -4 would cause the sound to be reproduced four semitones flat."},
  {name: "coarseTune", description: "This is a pitch offset, in semitones, which should be applied to the note. A positive value indicates the sound is reproduced at a higher pitch; a negative value indicates a lower pitch. For example, a Coarse Tune value of -4 would cause the sound to be reproduced four semitones flat."},
  {name: "fineTune", description: "This is a pitch offset, in cents, which should be applied to the note. It is additive with coarseTune. A positive value indicates the sound is reproduced at a higher pitch; a negative value indicates a lower pitch. For example, a Fine Tuning value of -5 would cause the sound to be reproduced five cents flat."},
  {name: "sampleID", description: "This is the index into the SHDR sub-chunk providing the sample to be used for the current instrument zone. A value of zero indicates the first sample in the list. The value should never exceed two less than the size of the sample list. The sampleID enumerator is the terminal generator for IGEN zones. As such, it should only appear in the IGEN sub-chunk, and it must appear as the last generator enumerator in all but the global zone."},
  {name: "sampleModes", description: "This enumerator indicates a value which gives a variety of Boolean flags describing the sample for the current instrument zone. The sampleModes should only appear in the IGEN sub-chunk, and should not appear in the global zone. The two LS bits of the value indicate the type of loop in the sample: 0 indicates a sound reproduced with no loop, 1 indicates a sound which loops continuously, 2 is unused but should be interpreted as indicating no loop, and 3 indicates a sound which loops for the duration of key depression then proceeds to play the remainder of the sample."},
  {name: "reserved3", description: "Unused, reserved. Should be ignored if encountered."},
  {name: "scaleTuning", description: "This parameter represents the degree to which MIDI key number influences pitch. A value of zero indicates that MIDI key number has no effect on pitch; a value of 100 represents the usual tempered semitone scale."},
  {name: "exclusiveClass", description: "This parameter provides the capability for a key depression in a given instrument to terminate the playback of other instruments. This is particularly useful for percussive instruments such as a hi-hat cymbal. An exclusive class value of zero indicates no exclusive class; no special action is taken. Any other value indicates that when this note is initiated, any other sounding note with the same exclusive class value should be rapidly terminated. The exclusive class generator can only appear at the instrument level. The scope of the exclusive class is the entire preset. In other words, any other instrument zone within the same preset holding a corresponding exclusive class will be terminated."},
  {name: "overridingRootKey", description: "This parameter represents the MIDI key number at which the sample is to be played back at its original sample rate. If not present, or if present with a value of -1, then the sample header parameter Original Key is used in its place. If it is present in the range 0-127, then the indicated key number will cause the sample to be played back at its sample header Sample Rate. For example, if the sample were a recording of a piano middle C (Original Key = 60) at a sample rate of 22.050 kHz, and Root Key were set to 69, then playing MIDI key number 69 (A above middle C) would cause a piano note of pitch middle C to be heard."},
  {name: "unused5", description: "Unused, reserved. Should be ignored if encountered."},
  {name: "endOper", description: "Unused, reserved. Should be ignored if encountered. Unique name provides value to end of defined list."}
];

var arrDocModSF = [
  {name: "type",
    0: {value: 0, description: "<b>Linear</b><br>The SoundFont modulator controller moves linearly from the minimum to the maximum value in the direction and with the polarity specified by the ‘D’ and ‘P’ bits."},
    1: {value: 1, description: "<b>Concave</b><br>The SoundFont modulator controller moves in a concave fashion from the minimum to the maximum value in the direction and with the polarity specified by the ‘D’ and ‘P’ bits. The negative unipolar concave characteristic follows variations of the mathematical equation:<br><i>output = -20/96 * log((value^2)/(range^2))</i><br><i>where value = input value - min value</i><br><i>range = max value – min value</i>"},
    2: {value: 2, description: "<b>Convex</b><br>The SoundFont modulator controller moves in a convex fashion from the minimum to the maximum value in the direction and with the polarity specified by the ‘D’ and ‘P’ bits. The convex curve is the same curve as the concave curve, except the start and end points are reversed."},
    3: {value: 3, description: "<b>Switch</b><br>The SoundFont modulator controller output is at a minimum value while the controller input moves from the minimum to half of the maximum, after which the controller output is at a maximum. This occurs in the direction and with the polarity specified by the ‘D’ and ‘P’ bits."}
  },
  {name: "palette",
    0: {value: 0, description: "<b>No Controller</b><br>No controller is to be used. The output of this controller module should be treated as if its value were set to ‘1’. It should not be a means to turn off a modulator."},
    1: {value: 2, description: "<b>Note-On Velocity</b><br>The controller source to be used is the velocity value which is sent from the MIDI note-on command which generated the given sound."},
    2: {value: 3, description: "<b>Note-On Key Number</b><br>The controller source to be used is the key number value which was sent from the MIDI note-on command which generated the given sound."},
    3: {value: 10, description: "<b>Poly Pressure</b><br>The controller source to be used is the poly-pressure amount that is sent from the MIDI poly-pressure command."},
    4: {value: 13, description: "<b>Channel Pressure</b><br>The controller source to be used is the channel pressure amount that is sent from the MIDI channel-pressure command."},
    5: {value: 14, description: "<b>Pitch Wheel</b><br>The controller source to be used is the pitch wheel amount which is sent from the MIDI pitch wheel command"},
    6: {value: 16, description: "Pitch Wheel Sensitivity</b><br>The controller source to be used is the pitch wheel sensitivity amount which is sent from the MIDI RPN 0 pitch wheel sensitivity command."}
  },
  {name: "direction",
    0: {value: 0, description: "<b>Is set to 0</b>, the direction of the controller should be from the minimum value to the maximum value. So, for example, if the controller source is Key Number, then Key Number value of 0 corresponds to the minimum possible controller output, and Key Number value of 127 corresponds to the maximum possible controller input."},
    1: {value: 1, description: "<b>Is set to 1</b>, the direction of the controller should be from the maximum value to the minimum value. So, for example, if the controller source is Key Number, then a Key Number value of 0 corresponds to the maximum possible controller output, and the Key Number value of 127 corresponds to the minimum possible controller input."}
  },
  {name: "polarity",
    0: {value: 0, "description": "<b>Is set to 0</b>, the controller should be mapped with a minimum value of 0 and a maximum value of 1. This is also called Unipolar. Thus it behaves similar to the Modulation Wheel controller of the MIDI specification."},
    1: {value: 1, "description": "<b>Is set to 1</b>, the controller sound be mapped with a minimum value of -1 and a maximum value of 1. This is also called Bipolar. Thus it behaves similar to the Pitch Wheel controller of the MIDI specification."}
  },
  {name: "index", description: "In the context of SoundFont files, a 'modulator index' refers to information within a SoundFont file that determines which sound parameters (modulators) can be modified and how to control the characteristics of an instrument. SoundFont files contain instrument samples and instructions for processing them, allowing users to play music with different sounds. The 'index' is a kind of index or list of which modulators are present in a SoundFont file and how they are applied to different instruments. This allows the synthesizer to understand how to manipulate the sound parameters to achieve the desired sound."}
];

var arrDocSmplSF = [
  {name: "name", description: "The ASCII character field <b>name</b> contains the name of the sample expressed in ASCII, with unused terminal characters filled with zero valued bytes. Sample names are case-sensitive. A unique name should always be assigned to each sample in the SoundFont compatible bank to enable identification. However, if a bank is read containing the erroneous state of samples with identical names, the samples should not be discarded. They should either be preserved as read or preferably uniquely renamed."},
  {name: "start", description: "The field <b>start</b> contains the index, in sample data points, from the beginning of the sample data field to the first data point of this sample.<br>The values of <b>start</b>, <b>end</b>, <b>startLoop</b>, and <b>endLoop</b> must all be within the range of the sample data field included in the SoundFont compatible bank or referenced in the sound ROM. Also, to allow a variety of hardware platforms to be able to reproduce the data, the samples have a minimum length of 48 data points, a minimum loop size of 32 data points and a minimum of 8 valid points prior to dwStartloop and after dwEndloop. Thus <b>start</b> must be less than <b>startLoop</b>-7, <b>startLoop</b> must be less than dwEndloop-31, and <b>endLoop</b> must be less than <b>end</b>-7. If these constraints are not met, the sound may optionally not be played if the hardware cannot support artifact-free playback for the parameters given."},
  {name: "end", description: "The field <b>end</b> contains the index, in sample data points, from the beginning of the sample data field to the first of the set of 46 zero valued data points following this sample.<br>The values of <b>start</b>, <b>end</b>, <b>startLoop</b>, and <b>endLoop</b> must all be within the range of the sample data field included in the SoundFont compatible bank or referenced in the sound ROM. Also, to allow a variety of hardware platforms to be able to reproduce the data, the samples have a minimum length of 48 data points, a minimum loop size of 32 data points and a minimum of 8 valid points prior to dwStartloop and after dwEndloop. Thus <b>start</b> must be less than <b>startLoop</b>-7, <b>startLoop</b> must be less than dwEndloop-31, and <b>endLoop</b> must be less than <b>end</b>-7. If these constraints are not met, the sound may optionally not be played if the hardware cannot support artifact-free playback for the parameters given."},
  {name: "startLoop", description: "The field <b>startLoop</b> contains the index, in sample data points, from the beginning of the sample data field to the first data point in the loop of this sample.<br>The values of <b>start</b>, <b>end</b>, <b>startLoop</b>, and <b>endLoop</b> must all be within the range of the sample data field included in the SoundFont compatible bank or referenced in the sound ROM. Also, to allow a variety of hardware platforms to be able to reproduce the data, the samples have a minimum length of 48 data points, a minimum loop size of 32 data points and a minimum of 8 valid points prior to dwStartloop and after dwEndloop. Thus <b>start</b> must be less than <b>startLoop</b>-7, <b>startLoop</b> must be less than dwEndloop-31, and <b>endLoop</b> must be less than <b>end</b>-7. If these constraints are not met, the sound may optionally not be played if the hardware cannot support artifact-free playback for the parameters given."},
  {name: "endLoop", description: "The field <b>endLoop</b> contains the index, in sample data points, from the beginning of the sample data field to the first data point following the loop of this sample. Note that this is the data point “equivalent to” the first loop data point, and that to produce portable artifact free loops, the eight proximal data points surrounding both the Startloop and Endloop points should be identical.<br>The values of <b>start</b>, <b>end</b>, <b>startLoop</b>, and <b>endLoop</b> must all be within the range of the sample data field included in the SoundFont compatible bank or referenced in the sound ROM. Also, to allow a variety of hardware platforms to be able to reproduce the data, the samples have a minimum length of 48 data points, a minimum loop size of 32 data points and a minimum of 8 valid points prior to dwStartloop and after dwEndloop. Thus <b>start</b> must be less than <b>startLoop</b>-7, <b>startLoop</b> must be less than dwEndloop-31, and <b>endLoop</b> must be less than <b>end</b>-7. If these constraints are not met, the sound may optionally not be played if the hardware cannot support artifact-free playback for the parameters given."},
  {name: "sampleRate", description: "The field <b>sampleRate</b> contains the sample rate, in hertz, at which this sample was acquired or to which it was most recently converted. Values of greater than 50000 or less than 400 may not be reproducible by some hardware platforms and should be avoided. A value of zero is illegal. If an illegal or impractical value is encountered, the nearest practical value should be used."},
  {name: "originalPitch", description: "The field <b>originalPitch</b> contains the MIDI key number of the recorded pitch of the sample. For example, a recording of an instrument playing middle C (261.62 Hz) should receive a value of 60. This value is used as the default “root key” for the sample, so that in the example, a MIDI key-on command for note number 60 would reproduce the sound at its original pitch. For unpitched sounds, a conventional value of 255 should be used. Values between 128 and 254 are illegal. Whenever an illegal value or a value of 255 is encountered, the value 60 should be used."},
  {name: "pitchCorrection", description: "The field <b>pitchCorrection</b> contains a pitch correction in cents that should be applied to the sample on playback. The purpose of this field is to compensate for any pitch errors during the sample recording process. The correction value is that of the correction to be applied. For example, if the sound is 4 cents sharp, a correction bringing it 4 cents flat is required; thus the value should be -4."},
  {name: "link", description: "If <b>type</b> indicates a mono sample, this is undefined and its value should be conventionally zero, but will be ignored regardless of value. If <b>type</b> indicates a left or right sample, this is the sample header index of the associated right or left stereo sample respectively. Both samples should be played entirely syncrhonously, with their pitch controlled by the right sample’s generators. All non-pitch generators should apply as normal; in particular the panning of the individual samples to left and right should be accomplished via the pan generator. Left-right pairs should always be found within the same instrument. No instrument should be designed in which it is possible to activate more than one instance of a particular stereo pair. The linked sample type is not currently fully defined in the SoundFont 2 specification, but will ultimately support a circularly linked list of samples using wSampleLink. This value is two bytes in length."},
  {name: "type", description: "The value in <b>type</b> is an enumeration with eight defined values: <br>monoSample = 1,<br>rightSample = 2,<br>leftSample = 4,<br>linkedSample = 8,<br>RomMonoSample = 32769,<br>RomRightSample = 32770,<br>RomLeftSample = 32772,<br>RomLinkedSample = 32776.<br>It can be seen that this is encoded such that bit 15 of the 16 bit value is set if the sample is in ROM, and reset if it is included in the SoundFont compatible bank. The four LS bits of the word are then exclusively set indicating mono, left, right, or linked. If the sound is flagged as a ROM sample and no valid “irom” sub-chunk is included, the file is structurally defective and should be rejected at load time."},
];

/**
 * [getInfoPrmSF description]
 * @param  {[type]} item  [description]
 * @param  {[type]} prm   [description]
 * @param  {[type]} tdId  [description]
 * @return {[type]}       [description]
 */
function getInfoPrmSF(item, prm, value, tdId){
  let itemsTd = document.getElementById(tdId).childNodes;
  let docPrm = "";

  itemsTd.forEach(function(item, index){
    let itm = item.firstChild;
    if(itm.innerHTML){
      if(itm.innerHTML == prm){
        item.style.backgroundColor = "#E3E3E3";
      }else{
        item.style.backgroundColor = "white";
      }
    }else{
      if(itm.textContent == prm){
        item.style.backgroundColor = "#E3E3E3";
      }else{
        item.style.backgroundColor = "white";
      }
    }
  });

  let descr_ul  = document.getElementById("descr_ul");
  let img_ahdsr = document.getElementById("img_ahdsr");

  img_ahdsr.style.display = "none";
  descr_ul.style.display = "block";
  descr_ul.setAttribute("style", "margin: 0px;padding:0 5px;line-height: 1.0;font-size:14px;color:black;font-family: 'Arial, Helvetica, sans-serif'");

  switch(item){
    case "generators":
      let idxGen = arrDocGenSF.findIndex(item => item.name.toLowerCase() === prm.toLowerCase());
      if(-1 !== idxGen){
        document.getElementById("descr_ul").innerHTML = "<b>"+prm+"</b>"+":<br>"+arrDocGenSF[idxGen].description;
      }
      break;
    case "modulators":
      let idxMod = arrDocModSF.findIndex(item => item.name.toLowerCase() === prm.toLowerCase());
      if(-1 !== idxMod){
        let objData = arrDocModSF[idxMod];
        if("index" == prm){
          document.getElementById("descr_ul").innerHTML = objData.description;
        }else{
          document.getElementById("descr_ul").innerHTML = "<b>"+prm+"</b>"+":<br>"+objData[value].description;
        }
      }
      break;
    case "sample":
      let idxSmpl = arrDocSmplSF.findIndex(item => item.name.toLowerCase() === prm.toLowerCase());
      if(-1 !== idxSmpl){
        document.getElementById("descr_ul").innerHTML = "<b>"+prm+"</b>"+":<br>"+arrDocSmplSF[idxSmpl].description;
      }
      break;
    case "banks":
      let obj = soundFont.banks;
      let filteredArray = obj[prm].presets.filter(element => element !== null);

      let presets = document.getElementById("presets");
      presets.innerHTML = "";

      filteredArray.forEach(function(item, index){
        let p1 = document.createElement("p");
        let numPreset = item.header.preset;
        let namePreset = item.header.name.replace("'","");
        p1.innerHTML = item.header.name;
        p1.setAttribute("style", "display:block;width:80%;margin:0;");
        p1.setAttribute("onclick", `getInfoPrmSF('presets','${namePreset}','${numPreset}', 'presets')`);
        let p2 = document.createElement("p");
        p2.innerHTML = item.header.preset;
        p2.setAttribute("style", "display:block;width:20%;margin:0;");
        p2.setAttribute("onclick", `getInfoPrmSF('presets','${namePreset}','${numPreset}', 'presets')`);

        let pp = document.createElement("p");
        pp.id = "sf2preset_"+index;
        pp.setAttribute("style", "display:flex;width:100%;margin:0;cursor:pointer;");
        pp.appendChild(p1); pp.appendChild(p2);
        presets.appendChild(pp);
      });
      prog.value = 0;
      curBank = prm;
      document.getElementById("Preset_th1").innerHTML = "Preset";
      document.getElementById("bank_view").innerHTML = " Bank "+curBank;

      synth.send([0x20,curBank]);

      break;
    case "presets":
      curPreset    = value;
      curProg      = value;
      prog.value   = value;

      document.getElementById("prog_num").value = value;
      document.getElementById("prog_name").innerHTML = prm;

      document.getElementById("Preset_th1").innerHTML = " Preset "+curPreset;

      let dataNote = soundFont.getKeyData(curBank, curPreset, curNote);
      if(!dataNote) return;

      let preset = dataNote.preset;
      let activeZones = getActiveZones(preset, curNote);

      if(undefined == activeZones) {
        activeZones = getActiveZones(preset, curNote);
        synth.setProgNoteSF(curProg, curNote, activeZones);
      }
      tblTimbreSF(activeZones);

      //Установка нового банка и пресета в синтезатор (core)
      setSynthProgNameSF(curBank);
      synth.setProgram(curCh,curPreset);

      if(false == synth.playing){
        if(ctxRange){
          let posY = arrNotesTrack[127-curNote-curOct*12];
          ctxRange.strokeStyle = "black";
          ctxRange.fillStyle   = "#C3C3C3";
          ctxRange.strokeRect(2, posY, 40, 10);
          ctxRange.fillRect(2, posY, 40, 10);
        }
        kbd.setNote(1, curNote);
        synth.send([0x90+curCh,curNote+curOct*12,100]);
        let interval = setTimeout(() => {
          kbd.setNote(0, curNote);
          synth.send([0x80+curCh,curNote+curOct*12,0]);
          audioNodesDiagram();
          drawVertKbd();
          clearTimeout(interval);
        }, 500);
      }
      audioNodesDiagram();

      break;
  }
}
/**
 * [soundViewerGSXG_info description]
 * @param  {[type]} id [description]
 */
function soundViewerGSXG_info(id){
  let comment = document.getElementById("descr_ul");
  comment.setAttribute("style","color:black;font-size: 14px;line-height: 1.0;padding:0 15px;font-family: 'Arial, Helvetica, sans-serif'");

  switch(id){
    case "Preset_th1":
      comment.innerHTML = "Preset contains:<br><b>Sound samples:</b>These are recorded snippets of real instrument sounds.<br><b>Processing and tuning parameters:</b>Information about how these samples should be played and modified to create a finished sound.This can include:<br><b>ADSR:</b> Controlling the dynamics of the sound over time.<br><b>Effects:</b> Using different effects such as reverb or delay.";
    break;
    case "keyRange_th2":
      comment.innerHTML = "This is the minimum and maximum MIDI key number values for which this preset zone or instrument zone is active. The LS byte indicates the highest and the MS byte the lowest valid key. The keyRange enumerator is optional, but when it does appear,it must be the first generator in the zone generator list.";
    break;
    case "Generators_th3":
      comment.innerHTML = "Generators define the basic properties of a SoundFont instrument, including how and when a sample is played.<br><b>Sample Data:</b>The actual audio data, mapped to specific MIDI notes.<br><b>Loops:</b> Sections within the sample that repeat. <br><b>Key and Velocity Ranges:</b> The specific MIDI notes and velocity levels that trigger a particular sample or layer.<br><b>Envelopes (ADSR):</b> parameters that control volume or other parameters over time.";
    break;
    case "Modulators_th4":
      comment.innerHTML = "Modulators translate real-time musical input (like MIDI controllers) into changes for the generators, adding expressiveness and dynamism to an instrument.<br><b>Source:</b> A modulator receives input from a primary source, such as a MIDI CC like the mod wheel or channel pressure, or a note's velocity.<br><b>Amount:</b> The normalized value is multiplied by an 'Amount' value, which determines the strength of modulation.";
    break;
    case "Sample_th5":
      comment.innerHTML = "Samples are sounds of different content (real musical instruments, synthetic sounds, effects, voices, etc.) organized in a special way using multisampling and multi-layer technologies, which achieves maximum realism of sound and instructions for hardware (WT (Wave Table) synthesizer), determining the methods of manipulating these samples.";
    break;
    case "curNote_th6":
      comment.innerHTML = "This enumerator forces the MIDI key number to effectively be interpreted as the value given. This generator can only appear at the instrument level. Valid values are from 0 to 127.";
  }
}
