
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.core.util.StatusPrinter;
import ch.qos.logback.core.joran.spi.JoranException;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;

import javax.sound.sampled.*;
import javax.sound.midi.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import org.xml.sax.InputSource;


// set classpath=.;%classpath%
// set classpath=.\*;%classpath%
// java crkodrt2 -PCDFAP 20190714Di2WAPACC.xml -S1 -M1

// javac -cp ".;\AliansProjects\crkodrt2\logback-classic-1.0.2.jar;\AliansProjects\crkodrt2\slf4j-api-1.6.4.jar;\AliansProjects\crkodrt2\log4j-over-slf4j-1.6.4.jar;\AliansProjects\crkodrt2\logback-core-1.0.2.jar;\AliansProjects\crkodrt2\commons-cli-1.4" crkodrt2.java
//
// java -cp ".;\AliansProjects\crkodrt2\logback-classic-1.0.2.jar;\AliansProjects\crkodrt2\slf4j-api-1.6.4.jar;\AliansProjects\crkodrt2\log4j-over-slf4j-1.6.4.jar;\AliansProjects\crkodrt2\logback-core-1.0.2.jar" crkodrt2 1 AboriginalConstellation_Chart.xml
//
// javac crkodrt2.java
// java crkodrt2 1 AboriginalConstellation_Chart.xml 5
//
// java crkodrt2 -N1 -PCDFAP AboriginalConstellation_Chart.xml -C5 -CLFAP crkodrt2_20170812225836.log -S1
//
//   for midi file output of song
//

public class crkodrt2 extends JPanel implements ChangeListener, Runnable
{

  static double BeatsPerMinute;
  static double FullSequenceDuration;
  static HashMap FullSequenceDurationByMovementNameHashMap;
  static double QuarterOfABeatDuration;
  static FileInputStream fisPrintChartDataFileInputStream;
  static DocumentBuilderFactory dbfPCD_DocumentBuilderFactoryInstance;
  static DocumentBuilderFactory dbfC2C_DocumentBuilderFactoryInstance;
  static String strPrintChartDataPathname;
  static String PrintChartDataXmlData;
  static int NumberOfStackTraceElementsToOutput = 20;
  static DocumentBuilder dbPCD_DocumentBuilderInstance;
  static DocumentBuilder dbC2C_DocumentBuilderInstance;
  static StringReader PrintChartDataStringReader;
  static InputSource PrintChartDataInputSource;
  static Document dPCD_DocumentInstance;
  static Document dC2C_DocumentInstance;
  static Element ePCD_RootElementInstance;
  static Element eC2C_RootElementInstance;
  static String HorizontalScaleFactorInput;
  static String VerticalScaleFactorInput;
  static String KeysStringModeSelect;
  static String AlternateModeNameSelect;
  static NodeList nlGEBTNNodeList;
  static Node nGEBTNitem0NodeInstance;
  static Node nGEBTNitem0FirstChildNodeInstance;
  static NodeList nlChartNodeList;
  static int intChartNodeListLength;
  static Node nChartNodeInstance;
  static NodeList nlChartChildNodeList;
  static int intChartChildNodeListLength;
  static Node nChartChildNodeInstance;
  static short shNodeType01;
  static String strNodeName01;
  static String strNodeValue01;
  static String strNodeValue03;
  static NodeList nlChart_XXChildNodeList;
  static int intChart_XXChildNodeListLength;
  static Node nChart_XXChildNodeInstance;
  static String strNodeName02;
  static short shNodeType02;
  static String strNodeValue02;
  static String strFormDataKey;
  static String ObjectSelect                  ;
  static String ObjectColorSelect             ;
  static String ObjectStyleSelect             ;
  static String ObjectFontSelect              ;
  static String ObjectFontSizeSelect          ;
  static String DirectorySelect               ;
  static String FilenameSelect                ;
  static String GenerateMethodSelect          ;
  static String NumberOfChartsSelect          ;
  static String MeasuresString                ;
  static String SequencesString               ;
  static String RepeatsSelect                 ;
  static String PartsSelect                   ;
  static String DifferencesSelect             ;
  static String AdditionalSelect              ;
  static String SetsSelect                    ;
  static String TypesSelect                   ;
  static String StringsSelect                 ;
  static String StringTuningSelect            ;
  static String StringNumberSelect            ;
  static String FretRangesCheckbox            ;
  static String YScaleFactorsCheckbox         ;
  static String XScaleFactorsCheckbox         ;
  static String SecondOctaveCheckbox          ;
  static String ObjectStylesCheckbox          ;
  static String StringTuningControlsCheckbox  ;
  static String FullRangeChartCheckbox        ;
  static String ScaleFilteringControlsCheckbox;
  static String ChartTopMarginInput           ;
  static String ChartTopMarginTextarea        ;
  static String StringPresetsSelect           ;
  static String ScaleFilteringPresetsSelect   ;
  static String CurrentChartIndexString       ;
  static String ScalesString                  ;
  static String ModesString                   ;
  static String KeysString                    ;
  static String ScaleOperandString            ;
  static String KeyOperandString              ;
  static String ScaleOperatorString           ;
  static String YScaleFactorString            ;
  static String XScaleFactorString            ;
  static int ModeArrayIndex;
  static int ScaleFoundFlag;
  static String ModesCsvFileAbsolutePathname;
  static File ModesCsvFile;
  static FileReader ModesCsvFileReader;
  static BufferedReader brModesCsvBufferedReader;
  static int MaxModeArrayEntries;
  static int MaxScaleArrayEntries;
  static String[][] ModeArray = new String[1024][16];
  static boolean EofFlag;
  static String TempString;
  static String[] SplitString = new String[256];
  static int intSplitStringLength;
  static String AlternateModeName;
  static String[] AlternateModeNameAmnLines = new String[1024];
  static Scanner scTempScanner;
  static int[] ModeArrayBaseScaleIndexArray = new int[1024];
  static int CurrentChartMode;
  static int[][] ChartModeArray = new int[32][8];
  static int CurrentChartIndex;
  static String UploadChartTempString;
  static int ModeFoundFlag;
  static int[][] ChromaticIndexArray = new int[32][13];
  static String CurrentModeArrayValueString;
  static int CurrentModeArrayValue;
  static int ModeArraySecondaryIndex;
  static String[] KeyStrings = {"","C","C#/Db","D","D#/Eb","E","F","F#/Gb","G","G#/Ab","A","A#/Bb","B"};
  static boolean KeyFoundFlag;
  static int KeyOffset;
  static int RandomOctaveNumber;
  static int RandomModeNumber;
  static int RandomNoteNumber;
  static int NumberOfQuarterBeatsNoteDuration;
  static int NumberOfQuarterBeatsRestDuration;
  static double NoteDurationDouble;
  static double RestDurationDouble;
  static int NoteDurationInt;
  static int RestDurationInt;
  static ShortMessage NoteOnShortMessage;
  static ShortMessage NoteOffShortMessage;
  static String      NoteFilterValueString;
  static String      BeatFilterValueString;
  static String      RestFilterValueString;
  static String      OctaveFilterValueString;
  static String      VelocityFilterValueString;
  static String[]      NoteFilterValueSplitStringArray;
  static String[]      BeatFilterValueSplitStringArray;
  static String[]      RestFilterValueSplitStringArray;
  static String[]      OctaveFilterValueSplitStringArray;
  static String[]      VelocityFilterValueSplitStringArray;
  static int      NoteFilterValueSplitStringArraySize;
  static int      BeatFilterValueSplitStringArraySize;
  static int      RestFilterValueSplitStringArraySize;
  static int      OctaveFilterValueSplitStringArraySize;
  static int      VelocityFilterValueSplitStringArraySize;
  static int RandomOctaveFilterIndex;
  static int RandomNoteFilterIndex;
  static int RandomVelocityFilterIndex;
  static int RandomVelocityNumber;
  static String GlobalBeatsPerMinuteValueString;
  static double GlobalBeatsPerMinute;
  static String GlobalTimeSignatureValueString;
  static String[] CurrentTimeSignatureValueSplitStringArray;
  static int GlobalNumberOfBeatsInAMeasure;
  static int GlobalFractionOfAMeasureThatGetsTheBeat;
  static int[] RandomNoteNumberArray     = new int[320];
  static int[] RandomVelocityNumberArray = new int[320];
  static int[] NoteDurationIntArray      = new int[320];
  static int[] RestDurationIntArray      = new int[320];
  static int RandomBeatFilterIndex;
  static int RandomRestFilterIndex;
  static int RandomNumberOfQuarterBeatsNumber;
  static double CurrentSequenceTimeLeft;
  static double CurrentSequenceAdjustedTimePointer;
  static double CurrentSequenceRealTimePointer;
  static boolean TrackCompletedFlag;
  static int NumberOfEventsInTrack;
  static int ModeArrayBaseScaleIndex;
  static int ModeArrayIndexOffset;
  static int ModeOffset;
  static boolean ModeOffsetComputedFlag;
  static int BaseScaleIndex;
  static int RelativeModeIndex;
  static Logger c2_Logger;
  static Thread tCrkodrt2PlayMidiTrackThread;
  static int MidiChannel;
  static ArrayList MidiTrackHashMapArrayList;
  static HashMap MidiTrackHashMapArrayListByMovementNameHashMap;
  static int MaxNumberOfSongSegments;
  static int SegmentStartingMillisecond;
  static String[] MidiTrackHashMapValueSplitStringArray;
  static int[] GlobalMidiChannelArray = new int[16];
  static String[] GlobalNoteFilterStringArray      = new String[16];
  static String[] GlobalBeatFilterStringArray      = new String[16];
  static String[] GlobalRestFilterStringArray      = new String[16];
  static String[] GlobalOctaveFilterStringArray    = new String[16];
  static String[] GlobalVelocityFilterStringArray  = new String[16];
  static ArrayList GlobalArrayIndexByMidiChannelHashMapArray = new ArrayList();
  static int[] TempMidiChannelArray = new int[16];
  static String[] TempNoteFilterStringArray      = new String[16];
  static String[] TempBeatFilterStringArray      = new String[16];
  static String[] TempRestFilterStringArray      = new String[16];
  static String[] TempOctaveFilterStringArray    = new String[16];
  static String[] TempVelocityFilterStringArray  = new String[16];
  static NodeList nlGlobalMidiSpecificationNodeList;
  static int intGlobalMidiSpecificationNodeListLength;
  static Node nGlobalMidiSpecificationNodeInstance;
  static NodeList nlGlobalMidiSpecificationChildNodeList;
  static int intGlobalMidiSpecificationChildNodeListLength;
  static Node nGlobalMidiSpecificationChildNodeInstance;
  static NodeList nlGlobalMidiSpecification_XXChildNodeList;
  static int intGlobalMidiSpecification_XXChildNodeListLength;
  static Node nGlobalMidiSpecification_XXChildNodeInstance;
  static String ChannelNumberString;
  static double FullMeasureDuration;
  static int GlobalMeasures;
  static int GlobalSequences;
  static double BeatDuration;
  static int BeatNumber;
  static String strCrkodrt2ConfigPathname;
  static String Crkodrt2ConfigXmlData;
  static StringReader Crkodrt2ConfigStringReader;
  static InputSource Crkodrt2ConfigInputSource;
  static String DesiredMidiDeviceInfoName;
  static int RandomModeNumberRange;
  static int RandomModeNumberRemainder;
  static int BeatFilterValueSplitStringArrayIndex;
  static int CurrentBeatFilterValue;
  static int DesiredSingleChartNumber;
  static String DesiredSingleChartNumberString;
  static String NumberOfLoopsString;
  static int NumberOfLoops;
  static HashMap NumberOfLoopsByMovementNameHashMap;
  static String CurrentCrkodrt2LogFileLine;
  static int    NumberOfLoopsLocation;
  static int      TildeLocation;
  static int    FullSequenceDurationLocation;
  static String      FullSequenceDurationString;
  static int    intChartNodeListLengthLocation;
  static String      intChartNodeListLengthString;
  static int    GlobalSequencesLocation;
  static String      GlobalSequencesString;
  static int    intGlobalMidiSpecificationNodeListLengthLocation;
  static String      intGlobalMidiSpecificationNodeListLengthString;
  static int    GlobalMidiChannelArrayLocation;
  static int    MidiTrackHashMapArrayListLocation;
  static int    DesiredSingleChartNumberLocation;
  static String Crkodrt2LogFileData;
  static String Crkodrt2LogFilePathname;
  static String[] Crkodrt2LogFileDataSplitStringArray;
  static int Crkodrt2LogFileDataSplitStringArraySize;
  static int RightSquareBracketLocation;
  static int IntegerparseIntLocation;
  static int RightParenLocation;
  static String GlobalMidiChannelArrayIndexString;
  static int GlobalMidiChannelArrayIndex;
  static String GlobalMidiChannelArrayValueString;
  static int GlobalMidiChannelArrayValue;
  static int putLocation;
  static String MidiTrackHashMapArrayListIndexString;
  static int MidiTrackHashMapArrayListIndex;
  static String MidiTrackHashMapArrayListPutParameterString;
  static String[] MidiTrackHashMapArrayListPutParameterStringSplitStringArray;
  static boolean LogFileInputFlag;
  static int NumberOfMidiSpecificationsProcessed;
  static Element e_nChartChildNodeInstance;
  static ArrayList ChartMidiChannelArrayListOfArrayLists;
  static String[][] ChartNoteFilterStringArray = new String[32][16];
  static String[][] ChartBeatFilterStringArray = new String[32][16];
  static String[][] ChartRestFilterStringArray = new String[32][16];
  static String[][] ChartOctaveFilterStringArray = new String[32][16];
  static String[][] ChartVelocityFilterStringArray = new String[32][16];
  static String[][] ChartGlobalMidiSpecificationArray = new String[32][16];
  static String[][] OriginalChartNoteFilterStringArray = new String[32][16];
  static String[][] OriginalChartBeatFilterStringArray = new String[32][16];
  static String[][] OriginalChartRestFilterStringArray = new String[32][16];
  static String[][] OriginalChartOctaveFilterStringArray = new String[32][16];
  static String[][] OriginalChartVelocityFilterStringArray = new String[32][16];
  static ArrayList MidiChannelArraySizeArrayList;
  static HashMap[] ChartArrayIndexByMidiChannelHashMapArray = new HashMap[32];
  static String[] GlobalMidiSpecificationIncludeListSplitStringArray;
  static String GlobalMidiSpecificationIncludeListString;
  static int GlobalMidiSpecificationIncludeListSplitStringArraySize;
  static int ChartArrayIndex;
  static int GlobalMidiSpecificationArrayIndex;
  static int GlobalMidiSpecificationIncludeListSplitStringArrayIndex;
  static String GlobalMidiSpecificationDesiredMidiChannelNumber;
  static String GlobalMidiSpecificationArrayIndexString;
  static String ChartArrayIndexString;
  static ArrayList CurrentChartIndexArrayList;
  static HashMap CurrentChartIndexArrayListByMovementNameHashMap;
  static int GlobalParts;
  static int GlobalRepeats;
  static int CurrentChartIndexArrayListSize;
  static HashMap CurrentChartIndexArrayListSizeByMovementNameHashMap;
  static int CurrentChartIndexArrayListIndex;
  static HashMap GlobalArrayIndexByMidiChannelHashMap;
  static ArrayList GlobalArrayIndexByMidiChannelHashMapArrayList;
  static HashMap TempHashMap;
  static ArrayList TempArrayList;
  static String MovementMap;
  static String[] MovementMapSplitStringArray = new String[16];
  static int intMovementMapSplitStringArrayLength;
  static double DesiredBeatsPerMinute;
  static double DesiredFullMeasureDuration;
  static int DesiredTIMING_CLOCK_IntervalDuration;
  static int TenthTIMING_CLOCK_IntervalDuration;
  static int TIMING_CLOCK_IntervalDuration;
  static int OffsetTo4;
  static int OffsetTo5;
  static int TempIndex;
  static String TIMING_CLOCK_DivisorString;
  static int TIMING_CLOCK_Divisor;
  static int ChromaticIndex;
  static int Offset4BackToBase;
  static int Offset5BackToBase;
  static int ModeArray4SecondaryIndex;
  static int ModeArray5SecondaryIndex;
  static String CurrentModeArray4ValueString;
  static int CurrentModeArray4Value;
  static String CurrentModeArray5ValueString;
  static int CurrentModeArray5Value;
  static int KeyOperandOffset;
  static boolean KeyOperandFoundFlag;
  static int ScaleOperandFoundFlag;
  static int ScaleOperandIndex;
  static int KeyOperandBackToBase;
  static int ModeOffsetToBase;
  static int ModeArrayOperandSecondaryIndex;
  static int ModeArrayBaseOperandSecondaryIndex;
  static String CurrentModeArrayOperandValueString;
  static int CurrentModeArrayOperandValue;
  static String CurrentModeArrayBaseOperandValueString;
  static int CurrentModeArrayBaseOperandValue;
  static int ChromaticIndexArraySecondaryIndex;
  static int[] ChromaticOrIndexArray = new int[1664];
  static int ChromaticOrIndexArrayStartingIndex;
  static int RandomChromaticOrIndexArrayIndex;
  static int RandomChromaticIndex;
  static int CurrentNumberOfMeasures;


  static NodeList nlMovementNodeList;
  static int intMovementNodeListLength;
  static Node nMovementNodeInstance;
  static NodeList nlMovementChildNodeList;
  static int intMovementChildNodeListLength;
  static Node nMovementChildNodeInstance;
  static NodeList nlMovement_XXChildNodeList;
  static int intMovement_XXChildNodeListLength;
  static Node nMovement_XXChildNodeInstance;

  static String Movement_NameString;
  static String Movement_BeatsPerMinuteString;
  static String Movement_TimeSignatureString;
  static String Movement_GenerateMethodsString;
  static String Movement_MeasuresString;
  static String Movement_SequencesString;
  static String Movement_repeatsString;
  static String Movement_partsString;
  static String Movement_differencesString;
  static String Movement_AdditionalString;
  static String Movement_SetsString;
  static String Movement_ChangeTypesString;
  static String Movement_FirstChartCheckboxString;
  static String Movement_ChartIncludeListString;
  static HashMap Movement_BeatsPerMinuteStringByMovement_NameStringHashMap;
  static HashMap Movement_TimeSignatureStringByMovement_NameStringHashMap;
  static HashMap Movement_MeasuresStringByMovement_NameStringHashMap;
  static HashMap Movement_SequencesStringByMovement_NameStringHashMap;
  static HashMap Movement_repeatsStringByMovement_NameStringHashMap;
  static HashMap Movement_partsStringByMovement_NameStringHashMap;
  static HashMap Movement_ChartIncludeListStringByMovement_NameStringHashMap;
  static HashMap Movement_GlobalMidiSpecificationsIncludeListByMovement_NameStringHashMap;
  static String CurrentMovementName;
  static int Movement_repeats;
  static String Movement_ChartIncludeList;
  static String[] Movement_ChartIncludeListSplitStringArray = new String[256];
  static int Movement_ChartIncludeListSplitStringArraySize;
  static String CurrentMovement_ChartString;
  static int CurrentMovement_ChartNumber;
  static int Movement_Measures;
  static int Movement_Sequences;
  static int Movement_parts;
  static int CurrentNumberOfSequences;
  static HashMap CurrentNumberOfSequencesByMovementNameHashMap;
  static int CurrentNumberOfparts;
  static double Movement_BeatsPerMinute;
  static double CurrentBeatsPerMinute;
  static String CurrentTimeSignatureValueString;
  static int MovementMapSplitStringArrayIndex;
  static Receiver DesiredReceiver;
  static HashMap ChartMidiChannelArrayListOfArrayListsByMovementNameHashMap;
  static HashMap MidiChannelArraySizeArrayListByMovementNameHashMap;
  static int MidiChannelArraySize;
  static int[][] ChartMidiChannelArray = new int[128][32];
  static ArrayList ChartMidiChannelArrayList;
  static int DesiredSongSegmentDuration;
  static HashMap SongSegmentDurationByMovementNameHashMap;
  static HashMap BeatsPerMinuteByMovementNameHashMap;
  static ShortMessage CurrentShortMessage;
  static String MidiShortMessageArrayListByMillisecondHashMapKey;
  static HashMap MidiShortMessageArrayListByMillisecondHashMap;
  static ArrayList MidiShortMessageArrayList;
  static String DefaultGlobalMidiSpecificationIncludeList;
  static String Movement_GlobalMidiSpecificationsIncludeList;
  static String SpecificationIndexString;
  static int SpecificationIndex;
  static String DefaultGlobalMidiSpecificationIncludeListString;
  static String[] DefaultGlobalMidiSpecificationIncludeListSplitStringArray = new String[16];
  static int DefaultGlobalMidiSpecificationIncludeListSplitStringArraySize;
  static int DefaultGlobalMidiSpecificationIncludeListSplitStringArrayIndex;
  static int intGlobalMidiSpecificationNodeListIndex;
  static int GlobalMidiSpecificationSpecificationIndex;
  static String[] Movement_GlobalMidiSpecificationsIncludeListSplitStringArray = new String[16];
  static int Movement_GlobalMidiSpecificationsIncludeListSplitStringArraySize;
  static int Movement_GlobalMidiSpecificationsIncludeListSplitStringArrayIndex;
  static String DefaultMovement_ChartIncludeListString;
  static int DefaultMovement_ChartIncludeListStringSize;
  static int CurrentChartArrayIndexByMidiChannelHashMapSize;
  static int CurrentChartArrayIndex;
  static boolean Movement_GlobalMidiSpecificationsIncludeListFlag;
  static HashMap CurrentChartArrayIndexByMidiChannelHashMap;
  static Iterator CurrentChartArrayIndexByMidiChannelHashMapIterator;
  static Map.Entry CurrentChartArrayIndexByMidiChannelHashMapEntry;
  static String CurrentChartArrayIndexByMidiChannelHashMapKey;
  static HashMap GlobalMidiSpecificationIncludeListByChartIndexHashMap;
  static int ChartGlobalMidiSpecificationsIncludeListSplitStringArrayIndex;
  static String[] ChartGlobalMidiSpecificationsIncludeListSplitStringArray = new String[16];
  static int ChartGlobalMidiSpecificationsIncludeListSplitStringArraySize;
  static String ChartGlobalMidiSpecificationIncludeList;
  static String[] NoteFilterValueColonSplitStringArray = new String[4];
  static String[] NoteFilterSimultaneousNotesValueSplitStringArray = new String[16];
  static int NoteFilterSimultaneousNotesValueSplitStringArraySize;
  static ArrayList TempMidiOnShortMessageArrayList;
  static ArrayList TempMidiOffShortMessageArrayList;
  static int TempMidiOnShortMessageArrayListIndex;
  static int TempMidiOffShortMessageArrayListIndex;
  static int TempMidiOnShortMessageArrayListSize;
  static int TempMidiOffShortMessageArrayListSize;
  static int StartingRandomNoteFilterIndex;
  static int RandomNumberOfSimultaneousNotes;
  static int RandomNoteFilterSimultaneousNotesIndex;
  static String NumberOfSongRepeatsString;
  static int NumberOfSongRepeats;
  static int Movement_ChartIncludeListIndex;

  static int NoteOctaveCombinationStringArrayIndex;
  static int TotalPossibleChordsStringArrayIndex;
  static int NoteFilterSimultaneousNotesValueSplitStringArrayIndex;
  static int NoteFilterSimultaneousNotesValue;
  static int CombinationGeneratorIndexArraySecondaryIndex;
  static int[] CombinationGeneratorIndexArray = new int[8];
  static int CombinationGeneratorIndexArrayIndex;
  static String PossibleChordString;
  static String[] TotalPossibleChordsStringArray = new String[4096];
  static boolean IndexesAdjustedFlag;
  static String[] NoteOctaveCombinationStringArray = new String[256];
  static int NoteFilterValueSplitStringArrayIndex;
  static int OctaveFilterValueSplitStringArrayIndex;
  static int RandomChordCombinationSplitStringArrayIndex;
  static String[] CurrentRandomChordCombinationSplitStringSplitStringArray = new String[8];
  static String CurrentRandomChordCombinationSplitString;
  static String[] RandomChordCombinationSplitStringArray = new String[8];
  static int RandomChordCombinationSplitStringArraySize;
  static int TotalPossibleChordsStringArraySize;
  static String RandomChordCombinationString;

  static int ExtensionLocation;
  static String MidiFilePathname;
  static String BasePathname;
  static double MidiTickDuration;
  static double CurrentNumberOfMidiTicks;
  static HashMap MidiFileOutputStreamByMidiChannelHashMap;
  static FileOutputStream MidiFileOutputStream;
  static int MidiFileOutputFlagNumber;
  static String MidiFileOutputFlagString;
  static boolean MidiFileOutputFlag;

  static String GlobalMidiSpecificationValueString;

    Vector demos = new Vector(4);
    JTabbedPane tabPane = new JTabbedPane();
    int width = 760, height = 500;
    int index;


    public crkodrt2(String audioDirectory)
    {

        setLayout(new BorderLayout());

        JMenuBar menuBar = new JMenuBar();

        if (JavaSoundApplet.applet == null) {
            JMenu fileMenu = (JMenu) menuBar.add(new JMenu("File"));
            JMenuItem item = (JMenuItem) fileMenu.add(new JMenuItem("Exit"));
            item.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) { System.exit(0); }
            });
        }
        JMenu options = (JMenu) menuBar.add(new JMenu("Options"));
        JMenuItem item = (JMenuItem) options.add(new JMenuItem("Applet Info"));
        item.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) { showInfoDialog(); }
        });
        add(menuBar, BorderLayout.NORTH);

        tabPane.addChangeListener(this);

        EmptyBorder eb = new EmptyBorder(5,5,5,5);
        BevelBorder bb = new BevelBorder(BevelBorder.LOWERED);
        CompoundBorder cb = new CompoundBorder(eb,bb);
        JPanel p = new JPanel(new BorderLayout());
        p.setBorder(new CompoundBorder(cb,new EmptyBorder(0,0,90,0)));
        final Juke juke = new Juke(audioDirectory);
        p.add(juke);
        demos.add(juke);
        tabPane.addTab("Juke Box", p);

        new Thread(this).start();

        add(tabPane, BorderLayout.CENTER);
    }


    public void stateChanged(ChangeEvent e) {
        close();
        System.gc();
        index = tabPane.getSelectedIndex();
        open();
    }


    public void close() {
        ((ControlContext) demos.get(index)).close();
    }


    public void open() {
        ((ControlContext) demos.get(index)).open();
    }


    public Dimension getPreferredSize() {
        return new Dimension(width, height);
    }


    public static void showInfoDialog() {
        final String msg =
            "When running the Java Sound demo as an applet these permissions\n" +
            "are necessary in order to load/save files and record audio :  \n\n"+
            "grant { \n" +
            "  permission java.io.FilePermission \"<<ALL FILES>>\", \"read, write\";\n" +
            "  permission javax.sound.sampled.AudioPermission \"record\"; \n" +
            "  permission java.util.PropertyPermission \"user.dir\", \"read\";\n"+
            "}; \n\n" +
            "The permissions need to be added to the .java.policy file.";
        new Thread(new Runnable() {
            public void run() {
                JOptionPane.showMessageDialog(null, msg, "Applet Info", JOptionPane.INFORMATION_MESSAGE);
            }
        }).start();
    }



    /**
     * Lazy load the tabbed pane with CapturePlayback, MidiSynth and Groove.
     */
    public void run() {
        EmptyBorder eb = new EmptyBorder(5,5,5,5);
        BevelBorder bb = new BevelBorder(BevelBorder.LOWERED);
        CompoundBorder cb = new CompoundBorder(eb,bb);
        JPanel p = new JPanel(new BorderLayout());
        p.setBorder(new CompoundBorder(cb,new EmptyBorder(0,0,90,0)));
        CapturePlayback capturePlayback = new CapturePlayback();
        demos.add(capturePlayback);
        p.add(capturePlayback);
        tabPane.addTab("Capture/Playback", p);

        MidiSynth midiSynth = new MidiSynth();
        demos.add(midiSynth);
        tabPane.addTab("Midi Synthesizer", midiSynth);

        p = new JPanel(new BorderLayout());
        p.setBorder(new CompoundBorder(cb,new EmptyBorder(0,0,5,20)));
        Groove groove = new Groove();
        demos.add(groove);
        p.add(groove);
        tabPane.addTab("Groove Box", p);
    }






























    public static void main(String[] CommandLineArguments)
    {

      // get a Logger so that we can send stuff to slf4j

      c2_Logger = LoggerFactory.getLogger(crkodrt2.class);
      LoggerContext LoggerContextInstance = (LoggerContext) LoggerFactory.getILoggerFactory();

      try
      {

        JoranConfigurator JoranConfiguratorInstance = new JoranConfigurator();
        JoranConfiguratorInstance.setContext(LoggerContextInstance);
        // Call context.reset() to clear any previous configuration, e.g. default
        // configuration. For multi-step configuration, omit calling context.reset().
        LoggerContextInstance.reset();
        String TempPathname = "./crkodrt2.logback.xml";
        System.err.println("crkodrt2.main:JoranConfiguratorInstance.doConfigure(" + TempPathname + ")");
        JoranConfiguratorInstance.doConfigure(TempPathname);
        StatusPrinter.printInCaseOfErrorsOrWarnings(LoggerContextInstance);

      }
      catch (Exception e)
      {
        System.err.println("c2_ERROR:" + e.getMessage());
        StackTraceElement[] steArray = e.getStackTrace();
        int steArraySize = java.lang.reflect.Array.getLength(steArray);
        for(int x = 0;x < NumberOfStackTraceElementsToOutput;x++)
        {
          if(x < steArraySize)
          {
            System.err.println("c2_ERROR:" + steArray[x].toString());
          }
        }
        System.exit(1);
      }

      //
      // check the parameters that were passed
      //


      if(CommandLineArguments.length < 2)
      {
        c2_Logger.info("usage:crkodrt2 NumberOfLoops PrintChartDataFileAbsolutePathname [OptionalChartNumberToPlay]\n");
        c2_Logger.info("usage:crkodrt2 -Nn -PCDFAP <PrintChartDataFileAbsolutePathname> -Cc -Ss -Rr -Mm\n");
        c2_Logger.info("usage:where:\n");
        c2_Logger.info("usage:      n = optional override number of loops\n");
        c2_Logger.info("usage:      c = optional override play single chart number\n");
        c2_Logger.info("usage:      s = optional override with song s\n");
        c2_Logger.info("usage:      r = optional override number of times to repeat song\n");
        c2_Logger.info("usage:      m = optional override write to midi files\n");
        System.exit(1);
      }


      try
      {








        // create Options object

        Options CommandLineOptionsInstance = new Options();

        // add N option

        CommandLineOptionsInstance.addOption("N", true, "NumberOfLoops");

        // add C option

        CommandLineOptionsInstance.addOption("C", true, "DesiredSingleChartNumber");

        // add S option

        CommandLineOptionsInstance.addOption("S", true, "SongNumber");

        // add R option

        CommandLineOptionsInstance.addOption("R", true, "SongRepeats");

        // add M option

        CommandLineOptionsInstance.addOption("M", true, "MidiFileOutput");

        // add the PCDFAP option

        Option PCDFAP_Option = OptionBuilder.withArgName( "PrintChartDataFileAbsolutePathname" )
                                            .hasArg()
                                            .withDescription(  "PrintChartDataFileAbsolutePathname" )
                                            .create( "PCDFAP" );
        CommandLineOptionsInstance.addOption(PCDFAP_Option);

        Option CLFAP_Option = OptionBuilder.withArgName( "Crkodrt2LogFileAbsolutePathname" )
                                            .hasArg()
                                            .withDescription(  "Crkodrt2LogFileAbsolutePathname" )
                                            .create( "CLFAP" );
        CommandLineOptionsInstance.addOption(CLFAP_Option);

        // parse the command line parameters into commons cli

        CommandLineParser CommandLineParserInstance = new DefaultParser();
        CommandLine CommandLineInstance = CommandLineParserInstance.parse( CommandLineOptionsInstance, CommandLineArguments);












        DesiredSingleChartNumber = 0;


        if(CommandLineInstance.hasOption("C"))
        {
          DesiredSingleChartNumberString = CommandLineInstance.getOptionValue("C");
          DesiredSingleChartNumber = Integer.parseInt(DesiredSingleChartNumberString);
        }

        MidiFileOutputFlag = false;
        if(CommandLineInstance.hasOption("M"))
        {
          MidiFileOutputFlagString = CommandLineInstance.getOptionValue("M");
          MidiFileOutputFlagNumber = Integer.parseInt(MidiFileOutputFlagString);
          MidiFileOutputFlag = true;
        }



        // if(CommandLineArguments.length > 2)
        // {
        //   DesiredSingleChartNumber = Integer.parseInt(CommandLineArguments[2]);
        // }
        c2_Logger.info("crkodrt2:main:DesiredSingleChartNumber:" + DesiredSingleChartNumber);

        //
        // read in Modes.CSV into a BufferedReader
        //

        ModesCsvFileAbsolutePathname = "modes.csv";
        ModesCsvFile = new File(ModesCsvFileAbsolutePathname);
        ModesCsvFileReader = new FileReader(ModesCsvFile);
        brModesCsvBufferedReader = new BufferedReader(ModesCsvFileReader);

        // //
        // //  if there is an alternate mode name file called for, read it in
        // //
        //
        // if(AlternateModeName != "")
        // {
        //   AlternateModeNameAmnPathname = String.format("%s.amn",AlternateModeName);
        //   InputStream isAlternateModeNameAmnInputStream = amCurrentAssetManager.open(AlternateModeNameAmnPathname);
        //   byte[] baAlternateModeNameAmnByteArray = new byte[isAlternateModeNameAmnInputStream.available()];
        //   isAlternateModeNameAmnInputStream.read(baAlternateModeNameAmnByteArray);
        //   isAlternateModeNameAmnInputStream.close();
        //   String strAlternateModeNameAmnCsv = new String(baAlternateModeNameAmnByteArray);
        //   StringReader srAlternateModeNameAmnCsvStringReader = new StringReader(strAlternateModeNameAmnCsv);
        //   BufferedReader brAlternateModeNameAmnCsvBufferedReader = new BufferedReader(srAlternateModeNameAmnCsvStringReader);
        //
        //   EofFlag = false;
        //   MaxAlternateModeNameAmnArrayEntries = 0;
        //   while (!EofFlag)
        //   {
        //
        //
        //     //
        //     // read a line of data
        //     //
        //
        //
        //     TempString = brAlternateModeNameAmnCsvBufferedReader.readLine();
        //
        //
        //     //
        //     // if the string is empty, then we got to the end
        //     //
        //
        //
        //     if (TempString == null)
        //     {
        //       EofFlag = true;
        //     }
        //
        //
        //     //
        //     // otherwise, process the data
        //     //
        //
        //
        //     else
        //     {
        //
        //       AlternateModeNameAmnLines[MaxAlternateModeNameAmnArrayEntries] = TempString;
        //
        //       MaxAlternateModeNameAmnArrayEntries++;
        //
        //     }
        //
        //   }
        //
        //
        //   //
        //   // close the readers
        //   //
        //
        //
        //   brAlternateModeNameAmnCsvBufferedReader.close();
        //   srAlternateModeNameAmnCsvStringReader.close();
        //
        //
        // }


        //
        // init the number of mode entries read
        //


        MaxModeArrayEntries = 0;
        MaxScaleArrayEntries = 0;
        AlternateModeName = "";


        //
        // load the Modes array
        //


        EofFlag = false;
        while (!EofFlag)
        {


          //
          // read a line of data
          //


          TempString = brModesCsvBufferedReader.readLine();
          c2_Logger.info("crkodrt2:main:TempString:" + TempString);


          //
          // if the string is empty, then we got to the end
          //


          if (TempString == null)
          {
            EofFlag = true;
          }


          //
          // otherwise, process the data
          //


          else
          {


            //
            // split the input up
            //


            SplitString = TempString.split(",");
            intSplitStringLength = SplitString.length;


            //
            // if this is not an empty record
            //


            c2_Logger.info("crkodrt2:main:SplitString[0]:" + SplitString[0]);
            if(
               (intSplitStringLength > 0) &&
               (SplitString[0] != "")
              )
            {


              // if this is a base scale record, then take note of the index

              if(
                 (intSplitStringLength > 15) &&
                 (SplitString[15].compareTo("") != 0)
                )
              {
                ModeArrayBaseScaleIndex = MaxModeArrayEntries;
              }

              // save the index to the base scale for all modes, so that can refer back to the base scale

              ModeArrayBaseScaleIndexArray[MaxModeArrayEntries] = ModeArrayBaseScaleIndex;

              //
              // save the MODE name
              //


              if(
                 (AlternateModeName != "") &&
                 (AlternateModeNameAmnLines[(MaxModeArrayEntries - 1)] != "")
                )
              {
                c2_Logger.info("crkodrt2:main:ModeArray[" + MaxModeArrayEntries + "][1] = " + AlternateModeNameAmnLines[(MaxModeArrayEntries - 1)]);
                ModeArray[MaxModeArrayEntries][1] = AlternateModeNameAmnLines[(MaxModeArrayEntries - 1)];
              }
              else
              {
                c2_Logger.info("crkodrt2:main:ModeArray[" + MaxModeArrayEntries + "][1] = " + SplitString[0]);
                ModeArray[MaxModeArrayEntries][1] = SplitString[0];
              }

              //
              // loop through each of the 12 chromatic steps in the MODE
              //


              for(int ChromaticIndex = 1;ChromaticIndex < 13;ChromaticIndex++)
              {


                //
                // if the corresponding database FIELD is not empty, then this
                // chromatic step is used in the scale, so we store the number
                // contained in the field in the internal ModeArray
                //
                //


                if(
                   (ChromaticIndex < intSplitStringLength) &&
                   ((SplitString[ChromaticIndex]) != null) &&
                   (SplitString[ChromaticIndex] != "")
                  )
                {


                  ModeArray[MaxModeArrayEntries][(ChromaticIndex + 1)] = SplitString[ChromaticIndex];
                  scTempScanner = new Scanner(ModeArray[MaxModeArrayEntries][(ChromaticIndex + 1)]);
                  if( ! scTempScanner.hasNextInt())
                  {
                    ModeArray[MaxModeArrayEntries][(ChromaticIndex + 1)] = "0";
                  }



                }


                //
                // if the corresponding database FIELD is empty, then this chromatic
                // step is not used in the scale, so we mark it with a "0" internally.
                //


                else
                {


                  ModeArray[MaxModeArrayEntries][(ChromaticIndex + 1)] = "0";


                }
              }


              //
              // if the final field in the MODE record is not empty, then this is
              // a primary MODE record, and the final field in the record contains
              // the name of the scale, so we save the current index to the ModeArray
              // into the ModeArrayBaseScaleIndexArray, so we can find the base
              // scale name when we need it
              //


              if(
                 (intSplitStringLength > 15) &&
                 ((SplitString[15]) != null) &&
                 (SplitString[15] != "")
                )
              {
                MaxScaleArrayEntries++;
                ModeArrayBaseScaleIndexArray[MaxScaleArrayEntries] = MaxModeArrayEntries;
              }


              //
              // increment the maximum number of modes
              //


              MaxModeArrayEntries++;

            }


          }

        }


        //
        // close the readers
        //


        brModesCsvBufferedReader.close();



















        strCrkodrt2ConfigPathname = "./crkodrt2Config.xml";
        dbfC2C_DocumentBuilderFactoryInstance = DocumentBuilderFactory.newInstance();

        Crkodrt2ConfigXmlData = LoadFileIntoString(strCrkodrt2ConfigPathname);

        // parse the Crkodrt2Config xml file into a DOM

        dbC2C_DocumentBuilderInstance = dbfC2C_DocumentBuilderFactoryInstance.newDocumentBuilder();
        Crkodrt2ConfigStringReader = new StringReader(Crkodrt2ConfigXmlData);
        Crkodrt2ConfigInputSource = new InputSource(Crkodrt2ConfigStringReader);
        dC2C_DocumentInstance = dbC2C_DocumentBuilderInstance.parse(Crkodrt2ConfigInputSource);

        // get the root element, which should be <Crkodrt2Config>

        eC2C_RootElementInstance = dC2C_DocumentInstance.getDocumentElement();

        // get the Crkodrt2Config data

        DesiredMidiDeviceInfoName = FindAndReturnXmlDataAssociatedWithTag(eC2C_RootElementInstance, "DesiredMidiDeviceInfoName");
        c2_Logger.info("crkodrt2:main:DesiredMidiDeviceInfoName:" + DesiredMidiDeviceInfoName);

        // get the TIMING_CLOCK_Divisor

        TIMING_CLOCK_DivisorString = FindAndReturnXmlDataAssociatedWithTag(eC2C_RootElementInstance, "TIMING_CLOCK_Divisor");
        TIMING_CLOCK_Divisor = Integer.parseInt(TIMING_CLOCK_DivisorString);
        c2_Logger.info("crkodrt2:main:TIMING_CLOCK_Divisor:" + TIMING_CLOCK_Divisor);



        // init the ChartMidiChannel list of lists

        ChartMidiChannelArrayListOfArrayLists = new ArrayList();
        for(
            CurrentChartIndex = 0;
            CurrentChartIndex < 32;
            CurrentChartIndex++
           )
        {
          ChartMidiChannelArrayListOfArrayLists.add(new ArrayList());
        }

        NumberOfLoopsByMovementNameHashMap = new HashMap();
        FullSequenceDurationByMovementNameHashMap = new HashMap();
        CurrentNumberOfSequencesByMovementNameHashMap = new HashMap();
        CurrentChartIndexArrayListByMovementNameHashMap = new HashMap();
        CurrentChartIndexArrayListSizeByMovementNameHashMap = new HashMap();
        MidiTrackHashMapArrayListByMovementNameHashMap = new HashMap();
        ChartMidiChannelArrayListOfArrayListsByMovementNameHashMap = new HashMap();
        MidiChannelArraySizeArrayListByMovementNameHashMap = new HashMap();
        SongSegmentDurationByMovementNameHashMap = new HashMap();
        BeatsPerMinuteByMovementNameHashMap = new HashMap();
        GlobalMidiSpecificationIncludeListByChartIndexHashMap = new HashMap();


        // if a log file has been input on the command line

        LogFileInputFlag = false;
        if(CommandLineInstance.hasOption("CLFAP"))
        {
          Crkodrt2LogFilePathname = CommandLineInstance.getOptionValue("CLFAP");
          c2_Logger.info("crkodrt2:main:Crkodrt2LogFileData = LoadFileIntoString(" + Crkodrt2LogFilePathname + ")");
          Crkodrt2LogFileData = LoadFileIntoString(Crkodrt2LogFilePathname);
          Crkodrt2LogFileDataSplitStringArray = Crkodrt2LogFileData.split("\\n");
          Crkodrt2LogFileDataSplitStringArraySize = java.lang.reflect.Array.getLength(Crkodrt2LogFileDataSplitStringArray);

          // now we are going to scan the log for the following pieces of info
          //
          // NumberOfLoops
          // DesiredReceiver
          // FullSequenceDuration
          // intChartNodeListLength
          // GlobalSequences
          // intGlobalMidiSpecificationNodeListLength
          // GlobalMidiChannelArray
          // MidiTrackHashMapArrayList
          // DesiredSingleChartNumber
          //

          for(
              int Crkodrt2LogFileDataSplitStringArrayIndex = 0;
              Crkodrt2LogFileDataSplitStringArrayIndex < Crkodrt2LogFileDataSplitStringArraySize;
              Crkodrt2LogFileDataSplitStringArrayIndex++
             )
          {
            CurrentCrkodrt2LogFileLine = Crkodrt2LogFileDataSplitStringArray[Crkodrt2LogFileDataSplitStringArrayIndex];

            NumberOfLoopsLocation = CurrentCrkodrt2LogFileLine.indexOf("NumberOfLoops:");
            if(NumberOfLoopsLocation >= 0)
            {
              TildeLocation = CurrentCrkodrt2LogFileLine.indexOf("~", NumberOfLoopsLocation);
              NumberOfLoopsString = CurrentCrkodrt2LogFileLine.substring((NumberOfLoopsLocation + 14), TildeLocation);
              NumberOfLoops = Integer.parseInt(NumberOfLoopsString);
              c2_Logger.info("crkodrt2:main:NumberOfLoops:" + NumberOfLoops);
            }

            FullSequenceDurationLocation = CurrentCrkodrt2LogFileLine.indexOf("FullSequenceDuration:");
            if(FullSequenceDurationLocation >= 0)
            {
              TildeLocation = CurrentCrkodrt2LogFileLine.indexOf("~", FullSequenceDurationLocation);
              FullSequenceDurationString = CurrentCrkodrt2LogFileLine.substring((FullSequenceDurationLocation + 21), TildeLocation);
              FullSequenceDuration = Double.parseDouble(FullSequenceDurationString);
              c2_Logger.info("crkodrt2:main:FullSequenceDuration:" + FullSequenceDuration);
            }

            intChartNodeListLengthLocation = CurrentCrkodrt2LogFileLine.indexOf("intChartNodeListLength:");
            if(intChartNodeListLengthLocation >= 0)
            {
              TildeLocation = CurrentCrkodrt2LogFileLine.indexOf("~", intChartNodeListLengthLocation);
              c2_Logger.info("crkodrt2:main:CurrentCrkodrt2LogFileLine:" + CurrentCrkodrt2LogFileLine + ":intChartNodeListLengthLocation:" + intChartNodeListLengthLocation + ":TildeLocation:" + TildeLocation);
              intChartNodeListLengthString = CurrentCrkodrt2LogFileLine.substring((intChartNodeListLengthLocation + 23), TildeLocation);
              intChartNodeListLength = Integer.parseInt(intChartNodeListLengthString);
              c2_Logger.info("crkodrt2:main:intChartNodeListLength:" + intChartNodeListLength);
            }

            GlobalSequencesLocation = CurrentCrkodrt2LogFileLine.indexOf("GlobalSequences:");
            if(GlobalSequencesLocation >= 0)
            {
              TildeLocation = CurrentCrkodrt2LogFileLine.indexOf("~", GlobalSequencesLocation);
              GlobalSequencesString = CurrentCrkodrt2LogFileLine.substring((GlobalSequencesLocation + 16), TildeLocation);
              GlobalSequences = Integer.parseInt(GlobalSequencesString);
              c2_Logger.info("crkodrt2:main:GlobalSequences:" + GlobalSequences);
            }

            intGlobalMidiSpecificationNodeListLengthLocation = CurrentCrkodrt2LogFileLine.indexOf("intGlobalMidiSpecificationNodeListLength:");
            if(intGlobalMidiSpecificationNodeListLengthLocation >= 0)
            {
              TildeLocation = CurrentCrkodrt2LogFileLine.indexOf("~", intGlobalMidiSpecificationNodeListLengthLocation);
              intGlobalMidiSpecificationNodeListLengthString = CurrentCrkodrt2LogFileLine.substring((intGlobalMidiSpecificationNodeListLengthLocation + 41), TildeLocation);
              intGlobalMidiSpecificationNodeListLength = Integer.parseInt(intGlobalMidiSpecificationNodeListLengthString);
              c2_Logger.info("crkodrt2:main:intGlobalMidiSpecificationNodeListLength:" + intGlobalMidiSpecificationNodeListLength);
            }



            // crkodrt2:main:GlobalMidiChannelArray[0] = Integer.parseInt(1)~

            GlobalMidiChannelArrayLocation = CurrentCrkodrt2LogFileLine.indexOf("GlobalMidiChannelArray[");
            if(GlobalMidiChannelArrayLocation >= 0)
            {
              RightSquareBracketLocation = CurrentCrkodrt2LogFileLine.indexOf("]", GlobalMidiChannelArrayLocation);
              IntegerparseIntLocation = CurrentCrkodrt2LogFileLine.indexOf("Integer.parseInt(", GlobalMidiChannelArrayLocation);
              RightParenLocation = CurrentCrkodrt2LogFileLine.indexOf(")", GlobalMidiChannelArrayLocation);
              GlobalMidiChannelArrayIndexString = CurrentCrkodrt2LogFileLine.substring((GlobalMidiChannelArrayLocation + 17), RightSquareBracketLocation);
              GlobalMidiChannelArrayIndex = Integer.parseInt(GlobalMidiChannelArrayIndexString);
              GlobalMidiChannelArrayValueString = CurrentCrkodrt2LogFileLine.substring((IntegerparseIntLocation + 17), RightParenLocation);
              GlobalMidiChannelArrayValue = Integer.parseInt(GlobalMidiChannelArrayValueString);
              c2_Logger.info("crkodrt2:main:GlobalMidiChannelArray[" + GlobalMidiChannelArrayIndex + "] = " + GlobalMidiChannelArrayValue);
              GlobalMidiChannelArray[GlobalMidiChannelArrayIndex] = GlobalMidiChannelArrayValue;
            }

            // crkodrt2:main:MidiTrackHashMapArray[1].put(1~0~1,64~42)~

            MidiTrackHashMapArrayListLocation = CurrentCrkodrt2LogFileLine.indexOf("MidiTrackHashMapArrayList[");
            if(MidiTrackHashMapArrayListLocation >= 0)
            {
              RightSquareBracketLocation = CurrentCrkodrt2LogFileLine.indexOf("]", MidiTrackHashMapArrayListLocation);
              putLocation = CurrentCrkodrt2LogFileLine.indexOf("put(", MidiTrackHashMapArrayListLocation);
              RightParenLocation = CurrentCrkodrt2LogFileLine.indexOf(")", MidiTrackHashMapArrayListLocation);
              MidiTrackHashMapArrayListIndexString = CurrentCrkodrt2LogFileLine.substring((MidiTrackHashMapArrayListLocation + 22), RightSquareBracketLocation);
              MidiTrackHashMapArrayListIndex = Integer.parseInt(MidiTrackHashMapArrayListIndexString);
              MidiTrackHashMapArrayListPutParameterString = CurrentCrkodrt2LogFileLine.substring((putLocation + 4), RightParenLocation);
              MidiTrackHashMapArrayListPutParameterStringSplitStringArray = MidiTrackHashMapArrayListPutParameterString.split(",");

              // need to fix this section
              //
              //if(MidiTrackHashMapArrayList[MidiTrackHashMapArrayListIndex] == null)
              //{
              //  MidiTrackHashMapArrayList[MidiTrackHashMapArrayListIndex] = new HashMap();
              //}
              //c2_Logger.info("crkodrt2:main:MidiTrackHashMapArrayList[" + MidiTrackHashMapArrayListIndex + "].put(" + MidiTrackHashMapArrayListPutParameterStringSplitStringArray[0] + ", " + MidiTrackHashMapArrayListPutParameterStringSplitStringArray[1] + ")");
              //MidiTrackHashMapArrayList[MidiTrackHashMapArrayListIndex].put(MidiTrackHashMapArrayListPutParameterStringSplitStringArray[0], MidiTrackHashMapArrayListPutParameterStringSplitStringArray[1]);
            }


            DesiredSingleChartNumberLocation = CurrentCrkodrt2LogFileLine.indexOf("DesiredSingleChartNumber:");
            if(DesiredSingleChartNumberLocation >= 0)
            {
              TildeLocation = CurrentCrkodrt2LogFileLine.indexOf("~", DesiredSingleChartNumberLocation);
              c2_Logger.info("crkodrt2:main:CurrentCrkodrt2LogFileLine:" + CurrentCrkodrt2LogFileLine);
              c2_Logger.info("crkodrt2:main:DesiredSingleChartNumberLocation:" + DesiredSingleChartNumberLocation);
              c2_Logger.info("crkodrt2:main:TildeLocation:" + TildeLocation);
              DesiredSingleChartNumberString = CurrentCrkodrt2LogFileLine.substring((DesiredSingleChartNumberLocation + 25), TildeLocation);
              DesiredSingleChartNumber = Integer.parseInt(DesiredSingleChartNumberString);
              c2_Logger.info("crkodrt2:main:DesiredSingleChartNumber:" + DesiredSingleChartNumber);
            }
          }
          LogFileInputFlag = true;

        }








        // no log file input, so we need to try and read in a PrintChart xml file

        else
        {

          // strPrintChartDataPathname = CommandLineArguments[1];
          if(CommandLineInstance.hasOption("PCDFAP"))
          {
            strPrintChartDataPathname = CommandLineInstance.getOptionValue("PCDFAP");


            dbfPCD_DocumentBuilderFactoryInstance = DocumentBuilderFactory.newInstance();

            PrintChartDataXmlData = LoadFileIntoString(strPrintChartDataPathname);

            // parse the PrintChartData xml file into a DOM

            dbPCD_DocumentBuilderInstance = dbfPCD_DocumentBuilderFactoryInstance.newDocumentBuilder();
            PrintChartDataStringReader = new StringReader(PrintChartDataXmlData);
            PrintChartDataInputSource = new InputSource(PrintChartDataStringReader);
            dPCD_DocumentInstance = dbPCD_DocumentBuilderInstance.parse(PrintChartDataInputSource);

            // get the root element, which should be <PrintChart>

            ePCD_RootElementInstance = dPCD_DocumentInstance.getDocumentElement();

            // get the PrintChart data

            HorizontalScaleFactorInput = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "HorizontalScaleFactorInput");

            VerticalScaleFactorInput = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "VerticalScaleFactorInput");

            KeysStringModeSelect = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "KeysStringModeSelect");

            AlternateModeNameSelect = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "AlternateModeNameSelect");

            // find all of the <GlobalMidiSpecification> nodes

            GlobalArrayIndexByMidiChannelHashMap = RecurseFromCurrentElementAndProcessAllXxxxMidiSpecifications
                    (
                     ePCD_RootElementInstance,
                     "Global",
                     GlobalMidiChannelArray,
                     GlobalNoteFilterStringArray,
                     GlobalBeatFilterStringArray,
                     GlobalRestFilterStringArray,
                     GlobalOctaveFilterStringArray,
                     GlobalVelocityFilterStringArray
                    );
            NumberOfMidiSpecificationsProcessed = GlobalArrayIndexByMidiChannelHashMap.size();

            intGlobalMidiSpecificationNodeListLength = NumberOfMidiSpecificationsProcessed;
            c2_Logger.info("crkodrt2:main:intGlobalMidiSpecificationNodeListLength:" + intGlobalMidiSpecificationNodeListLength);





            // find the default GlobalMidiSpecificationIncludeList

            DefaultGlobalMidiSpecificationIncludeList = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "DefaultGlobalMidiSpecificationIncludeList");

            if(DefaultGlobalMidiSpecificationIncludeList == null)
            {
              DefaultGlobalMidiSpecificationIncludeList = "1,2,3,4,5,6,7";
            }
            DefaultGlobalMidiSpecificationIncludeListSplitStringArray = DefaultGlobalMidiSpecificationIncludeList.split(",");
            DefaultGlobalMidiSpecificationIncludeListSplitStringArraySize = java.lang.reflect.Array.getLength(DefaultGlobalMidiSpecificationIncludeListSplitStringArray);
            c2_Logger.info("crkodrt2:main:DefaultGlobalMidiSpecificationIncludeListSplitStringArraySize:" + DefaultGlobalMidiSpecificationIncludeListSplitStringArraySize);

            // get the global BeatsPerMinute value

            GlobalBeatsPerMinuteValueString      = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "GlobalBeatsPerMinute");

            // get the global time signature

            GlobalTimeSignatureValueString       = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "GlobalTimeSignature");

            // get the global number of measures

            MeasuresString                 = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "Measures");

            // get the global number of sequences

            SequencesString                = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "Sequences");

            // get the global number of repeats

            RepeatsSelect                  = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "RepeatsSelect");

            // get the global number of parts

            PartsSelect                    = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "PartsSelect");

















            // init the Midi Channel Array Size ArrayList

            MidiChannelArraySizeArrayList = new ArrayList();
            for(
                CurrentChartIndex = 0;
                CurrentChartIndex < 128;
                CurrentChartIndex++
               )
            {
              MidiChannelArraySizeArrayList.add(0);
            }


            DefaultMovement_ChartIncludeListString = "";
            DefaultMovement_ChartIncludeListStringSize = 0;

            // find all of the <Chart> nodes

            nlChartNodeList = ePCD_RootElementInstance.getElementsByTagName("Chart");
            intChartNodeListLength = nlChartNodeList.getLength();
            c2_Logger.info("crkodrt2:main:intChartNodeListLength:" + intChartNodeListLength);

            // loop through all of the <Chart> nodes

            for (
                 int intChartNodeListIndex = 0;
                 intChartNodeListIndex < intChartNodeListLength;
                 intChartNodeListIndex++
                )
            {

              // reset the include list just in case

              GlobalMidiSpecificationIncludeListString = null;


              // get the current Chart node

              nChartNodeInstance = nlChartNodeList.item(intChartNodeListIndex);

              // get the child nodes of this Chart node

              nlChartChildNodeList = nChartNodeInstance.getChildNodes();
              intChartChildNodeListLength = nlChartChildNodeList.getLength();

              // loop through the <Chart> child nodes

              for (
                   int intChartChildNodeListIndex = 0;
                   intChartChildNodeListIndex < intChartChildNodeListLength;
                   intChartChildNodeListIndex++
                  )
              {

                // get the current <Chart> child node

                nChartChildNodeInstance = nlChartChildNodeList.item(intChartChildNodeListIndex);
                strNodeName01 = nChartChildNodeInstance.getNodeName();
                shNodeType01 = nChartChildNodeInstance.getNodeType();
                strNodeValue01 = nChartChildNodeInstance.getNodeValue();

                // get the child nodes of this Chart child node

                nlChart_XXChildNodeList = nChartChildNodeInstance.getChildNodes();
                intChart_XXChildNodeListLength = nlChart_XXChildNodeList.getLength();

                // loop through the child nodes of the <Chart> child node, should be only one TEXT node

                for (
                     int intChart_XXChildNodeListIndex = 0;
                     intChart_XXChildNodeListIndex < intChart_XXChildNodeListLength;
                     intChart_XXChildNodeListIndex++
                    )
                {

                  // get the current child node

                  nChart_XXChildNodeInstance = nlChart_XXChildNodeList.item(intChart_XXChildNodeListIndex);
                  strNodeName02 = nChart_XXChildNodeInstance.getNodeName();
                  shNodeType02 = nChart_XXChildNodeInstance.getNodeType();
                  strNodeValue02 = nChart_XXChildNodeInstance.getNodeValue();

                  // switch based on the NodeName of the parent node

                  c2_Logger.info("crkodrt2:main:switch(" + strNodeName01 + ")");
                  switch(strNodeName01)
                  {

                    case "CurrentChartIndex":
                    {
                      CurrentChartIndexString = strNodeValue02;
                      CurrentChartIndex = Integer.parseInt(CurrentChartIndexString);
                      break;
                    }
                    case "Scales":
                    {
                      ScalesString = strNodeValue02;
                      break;
                    }
                    case "Modes":
                    {
                      ModesString = strNodeValue02;
                      break;
                    }
                    case "Keys":
                    {
                      KeysString = strNodeValue02;
                      KeyOffset = 0;
                      KeyFoundFlag = false;
                      while(
                            ( ! KeyFoundFlag ) &&
                            ( KeyOffset < 12 )
                           )
                      {
                        if(KeysString.compareTo(KeyStrings[(KeyOffset + 1)]) == 0)
                        {
                          KeyFoundFlag = true;
                        }
                        else
                        {
                          KeyOffset++;
                        }
                      }
                      break;
                    }
                    case "ScaleOperand":
                    {
                      ScaleOperandString = strNodeValue02;
                      break;
                    }
                    case "KeyOperand":
                    {
                      KeyOperandString = strNodeValue02;
                      KeyOperandOffset = 0;
                      KeyOperandFoundFlag = false;
                      while(
                            ( ! KeyOperandFoundFlag ) &&
                            ( KeyOperandOffset < 12 )
                           )
                      {
                        if(KeyOperandString.compareTo(KeyStrings[(KeyOperandOffset + 1)]) == 0)
                        {
                          KeyOperandFoundFlag = true;
                        }
                        else
                        {
                          KeyOperandOffset++;
                        }
                      }
                      break;
                    }
                    case "ScaleOperator":
                    {
                      ScaleOperatorString = strNodeValue02;
                      break;
                    }
                    case "YScaleFactor":
                    {
                      YScaleFactorString = strNodeValue02;
                      break;
                    }
                    case "XScaleFactor":
                    {
                      XScaleFactorString = strNodeValue02;
                      break;
                    }
                    case "GlobalMidiSpecificationIncludeList":
                    {
                      GlobalMidiSpecificationIncludeListString = strNodeValue02;
                      break;
                    }

                    default:
                    {
                      break;
                    }

                  }
                }




              }

              // initialize the ChromaticIndexArray

              for(
                  ChromaticIndexArraySecondaryIndex = 0;
                  ChromaticIndexArraySecondaryIndex < 13;
                  ChromaticIndexArraySecondaryIndex++
                 )
              {
                ChromaticIndexArray[CurrentChartIndex][ChromaticIndexArraySecondaryIndex] = -1;
                c2_Logger.info("crkodrt2:main:ChromaticIndexArray[" + CurrentChartIndex + "][" + ChromaticIndexArraySecondaryIndex + "] = -1");
              }

              // find all of the <ChartMidiSpecification> nodes

              e_nChartChildNodeInstance = (Element)nChartNodeInstance;
              ChartArrayIndexByMidiChannelHashMapArray[CurrentChartIndex] = new HashMap();


              ChartArrayIndexByMidiChannelHashMapArray[CurrentChartIndex] = RecurseFromCurrentElementAndProcessAllXxxxMidiSpecifications
                      (
                       e_nChartChildNodeInstance,
                       "Chart",
                       ChartMidiChannelArray[CurrentChartIndex],
                       OriginalChartNoteFilterStringArray[CurrentChartIndex],
                       OriginalChartBeatFilterStringArray[CurrentChartIndex],
                       OriginalChartRestFilterStringArray[CurrentChartIndex],
                       OriginalChartOctaveFilterStringArray[CurrentChartIndex],
                       OriginalChartVelocityFilterStringArray[CurrentChartIndex]
                      );
              NumberOfMidiSpecificationsProcessed = ChartArrayIndexByMidiChannelHashMapArray[CurrentChartIndex].size();


              ModeArrayIndex = 0;
              ScaleOperandFoundFlag = 0;
              while((ModeArrayIndex < MaxModeArrayEntries) && (ScaleOperandFoundFlag == 0))
              {
                c2_Logger.info("crkodrt2:main:if(ModeArray[" + ModeArrayIndex + "][1].compareTo(" + ScaleOperandString + ") == 0)");
                if(ModeArray[ModeArrayIndex][1].compareTo(ScaleOperandString) == 0)
                {
                  ScaleOperandFoundFlag = 1;
                }
                else
                {
                  ModeArrayIndex++;
                }
              }
              ScaleOperandIndex = ModeArrayIndex;




              ModeArrayIndex = 0;
              ScaleFoundFlag = 0;
              while((ModeArrayIndex < MaxModeArrayEntries) && (ScaleFoundFlag == 0))
              {
                c2_Logger.info("crkodrt2:main:if(ModeArray[" + ModeArrayIndex + "][1].compareTo(" + ScalesString + ") == 0)");
                if(ModeArray[ModeArrayIndex][1].compareTo(ScalesString) == 0)
                {
                  ScaleFoundFlag = 1;
                }
                else
                {
                  ModeArrayIndex++;
                }
              }
              BaseScaleIndex = ModeArrayIndex;
              CurrentChartMode = (((ModeArrayIndex - 1) / 7) + 1);
              ChartModeArray[CurrentChartIndex][1] = CurrentChartMode;
              UploadChartTempString = ModesString;
              c2_Logger.info("crkodrt2:main:BaseScaleIndex:" + BaseScaleIndex + ":" + ModesString);

              ModeFoundFlag = 0;
              while((ModeArrayIndex < MaxModeArrayEntries) && (ModeFoundFlag == 0))
              {
                c2_Logger.info("crkodrt2:main:if(ModeArray[" + ModeArrayIndex + "][1].compareTo(" + ModesString + ") == 0)");
                if(ModeArray[ModeArrayIndex][1].compareTo(ModesString) == 0)
                {
                  ModeFoundFlag = 1;
                }
                else
                {
                  ModeArrayIndex++;
                }
              }
              ChartModeArray[CurrentChartIndex][2] = ModeArrayIndex - ((ChartModeArray[CurrentChartIndex][1] - 1) * 7);
              RelativeModeIndex = ModeArrayIndex;
              c2_Logger.info("crkodrt2:main:RelativeModeIndex:" + RelativeModeIndex + ":" + ModesString);

              UploadChartTempString = KeysString;
              //     &DetermineOptionArrayIndexUsingOptionText("TempKeyStrings","KeyStrings",$UploadChartTempString);
              //     ChartModeArray[CurrentChartIndex][3] = $FormData{"TempKeyStrings"};

              UploadChartTempString = ScaleOperandString;
              ModeArrayIndex = 0;
              ScaleFoundFlag = 0;
              while((ModeArrayIndex < MaxModeArrayEntries) && (ScaleFoundFlag == 0))
              {
                if(ModeArray[ModeArrayIndex][1].compareTo(UploadChartTempString) == 0)
                {
                  ScaleFoundFlag = 1;
                }
                else
                {
                  ModeArrayIndex++;
                }
              }
              CurrentChartMode = (((ModeArrayIndex - 1) / 7) + 1);
              ChartModeArray[CurrentChartIndex][4] = CurrentChartMode;

              ChartModeArray[CurrentChartIndex][5] = KeyOffset;
              // ChartModeArray[CurrentChartIndex][6] = ScaleOperatorString;
              //
              //     $UploadChartTempString = substr($ScaleOperatorLines[($CurrentChartIndex - 1)],( ( index $ScaleOperatorLines[($CurrentChartIndex - 1)],">" ) + 1 ),( ( index $ScaleOperatorLines[($CurrentChartIndex - 1)],"</" ) - ( ( index $ScaleOperatorLines[($CurrentChartIndex - 1)],">" ) + 1 )));
              //     &DetermineOptionArrayIndexUsingOptionText("TempScaleOperator","ScaleOperatorSelectOptionArray",$UploadChartTempString);
              //     $ChartModeArray[$CurrentChartIndex][6] = $FormData{"TempScaleOperator"};
              //
              //     $UploadChartTempString = substr($YScaleFactorLines[($CurrentChartIndex - 1)],( ( index $YScaleFactorLines[($CurrentChartIndex - 1)],">" ) + 1 ),( ( index $YScaleFactorLines[($CurrentChartIndex - 1)],"</" ) - ( ( index $YScaleFactorLines[($CurrentChartIndex - 1)],">" ) + 1 )));
              //     $ChartYScaleFactorArray[$CurrentChartIndex] = $UploadChartTempString;
              //
              //     $UploadChartTempString = substr($XScaleFactorLines[($CurrentChartIndex - 1)],( ( index $XScaleFactorLines[($CurrentChartIndex - 1)],">" ) + 1 ),( ( index $XScaleFactorLines[($CurrentChartIndex - 1)],"</" ) - ( ( index $XScaleFactorLines[($CurrentChartIndex - 1)],">" ) + 1 )));
              //     $ChartXScaleFactorArray[$CurrentChartIndex] = $UploadChartTempString;

              // get the ModeArray index to the base scale

              ModeArrayBaseScaleIndex = ModeArrayBaseScaleIndexArray[ModeArrayIndex];
              c2_Logger.info("crkodrt2:main:ModeArrayBaseScaleIndex:" + ModeArrayBaseScaleIndex);

              // compute which mode we are in relative to the base

              ModeArrayIndexOffset = RelativeModeIndex - BaseScaleIndex;
              c2_Logger.info("crkodrt2:main:ModeArrayIndexOffset:" + ModeArrayIndexOffset);

              // compute the chromatic offset to use to get to the desired mode

              ModeOffset = 0;
              if(ModeArrayIndexOffset >= 0)
              {
                ModeArrayIndexOffset++;
              }
              ModeArraySecondaryIndex = 2;
              ModeOffsetComputedFlag = false;
              while(
                    ( ! ModeOffsetComputedFlag ) &&
                    ( ModeArraySecondaryIndex < 14)
                   )
              {
                CurrentModeArrayValueString = ModeArray[BaseScaleIndex][ModeArraySecondaryIndex];
                CurrentModeArrayValue = Integer.parseInt(CurrentModeArrayValueString);
                if(CurrentModeArrayValue == ModeArrayIndexOffset)
                {
                  ModeOffsetComputedFlag = true;
                  ModeOffset += (ModeArraySecondaryIndex - 2);
                }
                else
                {
                  ModeArraySecondaryIndex++;
                }
              }
              c2_Logger.info("crkodrt2:main:ModeOffset:" + ModeOffset);



              // compute the offsets that will be used when computing the 145 scales

              OffsetTo4 = 0;
              OffsetTo5 = 0;
              for(
                  TempIndex = 3;
                  TempIndex < 14;
                  TempIndex++
                 )
              {
                CurrentModeArrayValueString = ModeArray[BaseScaleIndex][TempIndex];
                CurrentModeArrayValue = Integer.parseInt(CurrentModeArrayValueString);
                if(CurrentModeArrayValue == 4)
                {
                  OffsetTo4 = TempIndex - 2;
                }
                if(CurrentModeArrayValue == 5)
                {
                  OffsetTo5 = TempIndex - 2;
                }
              }
              Offset4BackToBase = 12 - OffsetTo4;
              Offset5BackToBase = 12 - OffsetTo5;
              c2_Logger.info("crkodrt2:main:OffsetTo4:" + OffsetTo4);
              c2_Logger.info("crkodrt2:main:OffsetTo5:" + OffsetTo5);


              // compute the offsets that will be used when computing the operand scale

              if(KeyOperandOffset <= KeyOffset)
              {
                KeyOperandBackToBase = KeyOffset - KeyOperandOffset;
              }
              else
              {
                KeyOperandBackToBase = 12 - (KeyOperandOffset - KeyOffset);
              }
              c2_Logger.info("crkodrt2:main:KeyOperandBackToBase:" + KeyOperandBackToBase);

              ModeOffsetToBase = 12 - ModeOffset;
              c2_Logger.info("crkodrt2:main:ModeOffsetToBase:" + ModeOffsetToBase);






              for(
                  ModeArraySecondaryIndex = 2;
                  ModeArraySecondaryIndex < 14;
                  ModeArraySecondaryIndex++
                 )
              {
                ModeArray4SecondaryIndex = ModeArraySecondaryIndex + Offset4BackToBase;
                if(ModeArray4SecondaryIndex > 13)
                {
                  ModeArray4SecondaryIndex -= 12;
                }
                ModeArray5SecondaryIndex = ModeArraySecondaryIndex + Offset5BackToBase;
                if(ModeArray5SecondaryIndex > 13)
                {
                  ModeArray5SecondaryIndex -= 12;
                }
                ModeArrayOperandSecondaryIndex = ModeArraySecondaryIndex + KeyOperandBackToBase;
                if(ModeArrayOperandSecondaryIndex > 13)
                {
                  ModeArrayOperandSecondaryIndex -= 12;
                }
                ModeArrayBaseOperandSecondaryIndex = ModeArraySecondaryIndex + ModeOffsetToBase;
                if(ModeArrayBaseOperandSecondaryIndex > 13)
                {
                  ModeArrayBaseOperandSecondaryIndex -= 12;
                }




                CurrentModeArrayValueString = ModeArray[RelativeModeIndex][ModeArraySecondaryIndex];
                CurrentModeArrayValue = Integer.parseInt(CurrentModeArrayValueString);
                CurrentModeArray4ValueString = ModeArray[RelativeModeIndex][ModeArray4SecondaryIndex];
                CurrentModeArray4Value = Integer.parseInt(CurrentModeArray4ValueString);
                CurrentModeArray5ValueString = ModeArray[RelativeModeIndex][ModeArray5SecondaryIndex];
                CurrentModeArray5Value = Integer.parseInt(CurrentModeArray5ValueString);
                CurrentModeArrayOperandValueString = ModeArray[ScaleOperandIndex][ModeArrayOperandSecondaryIndex];
                CurrentModeArrayOperandValue = Integer.parseInt(CurrentModeArrayOperandValueString);
                CurrentModeArrayBaseOperandValueString = ModeArray[BaseScaleIndex][ModeArrayBaseOperandSecondaryIndex];
                CurrentModeArrayBaseOperandValue = Integer.parseInt(CurrentModeArrayBaseOperandValueString);



                // switch based on the ScaleOperatorString

                c2_Logger.info("crkodrt2:main:switch(" + ScaleOperatorString + ")");
                switch(ScaleOperatorString)
                {

                  case "AND":
                  {
                    if(
                       (CurrentModeArrayOperandValue == 0) ||
                       (CurrentModeArrayBaseOperandValue == 0)
                      )
                    {
                      CurrentModeArrayValue = 0;
                      c2_Logger.info("crkodrt2:main:setting CurrentModeArrayValue = 0:CurrentModeArrayOperandValue:" + CurrentModeArrayOperandValue + ":CurrentModeArrayBaseOperandValue:" + CurrentModeArrayBaseOperandValue);
                    }
                    break;
                  }
                  case "OR":
                  {

                    OrIntoChromaticIndexArray(
                                              CurrentModeArrayOperandValue,
                                              CurrentChartIndex,
                                              ModeOffset,
                                              ModeArraySecondaryIndex
                                             );
                    OrIntoChromaticIndexArray(
                                              CurrentModeArrayBaseOperandValue,
                                              CurrentChartIndex,
                                              ModeOffset,
                                              ModeArraySecondaryIndex
                                             );




                    break;
                  }
                  case "145AND":
                  {
                    if(
                       (CurrentModeArrayValue == 0) ||
                       (CurrentModeArray4Value == 0) ||
                       (CurrentModeArray5Value == 0)
                      )
                    {
                      CurrentModeArrayValue = 0;
                    }
                    break;
                  }
                  case "145OR":
                  {
                    OrIntoChromaticIndexArray(
                                              CurrentModeArrayValue,
                                              CurrentChartIndex,
                                              ModeOffset,
                                              ModeArraySecondaryIndex
                                             );
                    OrIntoChromaticIndexArray(
                                              CurrentModeArray4Value,
                                              CurrentChartIndex,
                                              ModeOffset,
                                              ModeArraySecondaryIndex
                                             );
                    OrIntoChromaticIndexArray(
                                              CurrentModeArray5Value,
                                              CurrentChartIndex,
                                              ModeOffset,
                                              ModeArraySecondaryIndex
                                             );
                    break;
                  }
                  default:
                  {
                    if(CurrentModeArrayValue == 0)
                    {
                      ChromaticIndexArray[CurrentChartIndex][CurrentModeArrayValue] = -1;
                      c2_Logger.info("crkodrt2:main:ChromaticIndexArray[" + CurrentChartIndex + "][" + CurrentModeArrayValue + "] = -1");
                    }
                    else
                    {
                      ChromaticIndexArray[CurrentChartIndex][CurrentModeArrayValue] = (ModeOffset + (ModeArraySecondaryIndex - 2));
                      c2_Logger.info("crkodrt2:main:ChromaticIndexArray[" + CurrentChartIndex + "][" + CurrentModeArrayValue + "] = " + (ModeOffset + (ModeArraySecondaryIndex - 2)));
                    }
                    break;
                  }

                }






              }



              DefaultMovement_ChartIncludeListStringSize++;
              if(DefaultMovement_ChartIncludeListStringSize == 1)
              {
                DefaultMovement_ChartIncludeListString = CurrentChartIndexString;
              }
              else
              {
                DefaultMovement_ChartIncludeListString = DefaultMovement_ChartIncludeListString + "," + CurrentChartIndexString;
              }

              c2_Logger.info("crkodrt2:main:GlobalMidiSpecificationIncludeListByChartIndexHashMap.put(" + CurrentChartIndex + ", " + GlobalMidiSpecificationIncludeListString + ")");
              GlobalMidiSpecificationIncludeListByChartIndexHashMap.put(CurrentChartIndex, GlobalMidiSpecificationIncludeListString);


            }

            // get some more PrintChartData

            ObjectSelect                   = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "ObjectSelect");
            ObjectColorSelect              = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "ObjectColorSelect");
            ObjectStyleSelect              = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "ObjectStyleSelect");
            ObjectFontSelect               = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "ObjectFontSelect");
            ObjectFontSizeSelect           = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "ObjectFontSizeSelect");
            DirectorySelect                = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "DirectorySelect");
            FilenameSelect                 = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "FilenameSelect");
            GenerateMethodSelect           = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "GenerateMethodSelect");
            NumberOfChartsSelect           = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "NumberOfChartsSelect");
            DifferencesSelect              = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "DifferencesSelect");
            AdditionalSelect               = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "AdditionalSelect");
            SetsSelect                     = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "SetsSelect");
            TypesSelect                    = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "TypesSelect");
            StringsSelect                  = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "StringsSelect");
            StringTuningSelect             = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "StringTuningSelect");
            StringNumberSelect             = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "StringNumberSelect");
            FretRangesCheckbox             = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "FretRangesCheckbox");
            YScaleFactorsCheckbox          = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "YScaleFactorsCheckbox");
            XScaleFactorsCheckbox          = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "XScaleFactorsCheckbox");
            SecondOctaveCheckbox           = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "SecondOctaveCheckbox");
            ObjectStylesCheckbox           = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "ObjectStylesCheckbox");
            StringTuningControlsCheckbox   = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "StringTuningControlsCheckbox");
            FullRangeChartCheckbox         = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "FullRangeChartCheckbox");
            ScaleFilteringControlsCheckbox = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "ScaleFilteringControlsCheckbox");
            ChartTopMarginInput            = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "ChartTopMarginInput");
            ChartTopMarginTextarea         = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "ChartTopMarginTextarea");
            StringPresetsSelect            = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "StringPresetsSelect");
            ScaleFilteringPresetsSelect    = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "ScaleFilteringPresetsSelect");


            MovementMap = FindAndReturnXmlDataAssociatedWithTag(ePCD_RootElementInstance, "MovementMap");
            c2_Logger.info("crkodrt2:main:MovementMap:" + MovementMap);
            if(
               (MovementMap != null) &&
               (MovementMap != "")
              )
            {
              MovementMapSplitStringArray = MovementMap.split(",");
              intMovementMapSplitStringArrayLength = MovementMapSplitStringArray.length;
              c2_Logger.info("crkodrt2:main:intMovementMapSplitStringArrayLength:" + intMovementMapSplitStringArrayLength);


            }

            Movement_BeatsPerMinuteStringByMovement_NameStringHashMap = new HashMap();
            Movement_TimeSignatureStringByMovement_NameStringHashMap = new HashMap();
            Movement_MeasuresStringByMovement_NameStringHashMap = new HashMap();
            Movement_SequencesStringByMovement_NameStringHashMap = new HashMap();
            Movement_repeatsStringByMovement_NameStringHashMap = new HashMap();
            Movement_partsStringByMovement_NameStringHashMap = new HashMap();
            Movement_ChartIncludeListStringByMovement_NameStringHashMap = new HashMap();
            Movement_GlobalMidiSpecificationsIncludeListByMovement_NameStringHashMap = new HashMap();

            // find all of the <Movement> nodes

            nlMovementNodeList = ePCD_RootElementInstance.getElementsByTagName("Movement");
            intMovementNodeListLength = nlMovementNodeList.getLength();
            c2_Logger.info("crkodrt2:main:intMovementNodeListLength:" + intMovementNodeListLength);

            // loop through all of the <Movement> nodes

            for (
                 int intMovementNodeListIndex = 0;
                 intMovementNodeListIndex < intMovementNodeListLength;
                 intMovementNodeListIndex++
                )
            {

              // get the current Movement node

              nMovementNodeInstance = nlMovementNodeList.item(intMovementNodeListIndex);

              // get the child nodes of this Movement node

              nlMovementChildNodeList = nMovementNodeInstance.getChildNodes();
              intMovementChildNodeListLength = nlMovementChildNodeList.getLength();

              // loop through the <Movement> child nodes

              for (
                   int intMovementChildNodeListIndex = 0;
                   intMovementChildNodeListIndex < intMovementChildNodeListLength;
                   intMovementChildNodeListIndex++
                  )
              {

                // get the current <Movement> child node

                nMovementChildNodeInstance = nlMovementChildNodeList.item(intMovementChildNodeListIndex);
                strNodeName01 = nMovementChildNodeInstance.getNodeName();
                shNodeType01 = nMovementChildNodeInstance.getNodeType();
                strNodeValue01 = nMovementChildNodeInstance.getNodeValue();

                // get the child nodes of this Movement child node

                nlMovement_XXChildNodeList = nMovementChildNodeInstance.getChildNodes();
                intMovement_XXChildNodeListLength = nlMovement_XXChildNodeList.getLength();

                // loop through the child nodes of the <Movement> child node, should be only one TEXT node

                for (
                     int intMovement_XXChildNodeListIndex = 0;
                     intMovement_XXChildNodeListIndex < intMovement_XXChildNodeListLength;
                     intMovement_XXChildNodeListIndex++
                    )
                {

                  // get the current child node

                  nMovement_XXChildNodeInstance = nlMovement_XXChildNodeList.item(intMovement_XXChildNodeListIndex);
                  strNodeName02 = nMovement_XXChildNodeInstance.getNodeName();
                  shNodeType02 = nMovement_XXChildNodeInstance.getNodeType();
                  strNodeValue02 = nMovement_XXChildNodeInstance.getNodeValue();

                  // switch based on the NodeName of the parent node

                  c2_Logger.info("crkodrt2:main:switch(" + strNodeName01 + ")");
                  switch(strNodeName01)
                  {

                    case "Movement_Name":
                    {
                      Movement_NameString = strNodeValue02;
                      break;
                    }
                    case "Movement_BeatsPerMinute":
                    {
                      Movement_BeatsPerMinuteString = strNodeValue02;
                      break;
                    }
                    case "Movement_TimeSignature":
                    {
                      Movement_TimeSignatureString = strNodeValue02;
                      break;
                    }
                    case "Movement_GenerateMethods":
                    {
                      Movement_GenerateMethodsString = strNodeValue02;
                      break;
                    }
                    case "Movement_Measures":
                    {
                      Movement_MeasuresString = strNodeValue02;
                      break;
                    }
                    case "Movement_Sequences":
                    {
                      Movement_SequencesString = strNodeValue02;
                      break;
                    }
                    case "Movement_repeats":
                    {
                      Movement_repeatsString = strNodeValue02;
                      break;
                    }
                    case "Movement_parts":
                    {
                      Movement_partsString = strNodeValue02;
                      break;
                    }
                    case "Movement_differences":
                    {
                      Movement_differencesString = strNodeValue02;
                      break;
                    }
                    case "Movement_Additional":
                    {
                      Movement_AdditionalString = strNodeValue02;
                      break;
                    }
                    case "Movement_Sets":
                    {
                      Movement_SetsString = strNodeValue02;
                      break;
                    }
                    case "Movement_ChangeTypes":
                    {
                      Movement_ChangeTypesString = strNodeValue02;
                      break;
                    }
                    case "Movement_FirstChartCheckbox":
                    {
                      Movement_FirstChartCheckboxString = strNodeValue02;
                      break;
                    }
                    case "Movement_ChartIncludeList":
                    {
                      Movement_ChartIncludeListString = strNodeValue02;
                      break;
                    }
                    case "Movement_GlobalMidiSpecificationsIncludeList":
                    {
                      Movement_GlobalMidiSpecificationsIncludeList = strNodeValue02;
                      break;
                    }

                    default:
                    {
                      break;
                    }

                  }
                }


              }


              c2_Logger.info("crkodrt2:main:Movement_BeatsPerMinuteStringByMovement_NameStringHashMap.put(" + Movement_NameString + ", " + Movement_BeatsPerMinuteString + ")");
              Movement_BeatsPerMinuteStringByMovement_NameStringHashMap.put(Movement_NameString, Movement_BeatsPerMinuteString);
              c2_Logger.info("crkodrt2:main:Movement_TimeSignatureStringByMovement_NameStringHashMap.put(" + Movement_NameString + ", " + Movement_TimeSignatureString + ")");
              Movement_TimeSignatureStringByMovement_NameStringHashMap.put(Movement_NameString, Movement_TimeSignatureString);
              c2_Logger.info("crkodrt2:main:Movement_MeasuresStringByMovement_NameStringHashMap.put(" + Movement_NameString + ", " + Movement_MeasuresString + ")");
              Movement_MeasuresStringByMovement_NameStringHashMap.put(Movement_NameString, Movement_MeasuresString);
              c2_Logger.info("crkodrt2:main:Movement_SequencesStringByMovement_NameStringHashMap.put(" + Movement_NameString + ", " + Movement_SequencesString + ")");
              Movement_SequencesStringByMovement_NameStringHashMap.put(Movement_NameString, Movement_SequencesString);
              c2_Logger.info("crkodrt2:main:Movement_repeatsStringByMovement_NameStringHashMap.put(" + Movement_NameString + ", " + Movement_repeatsString + ")");
              Movement_repeatsStringByMovement_NameStringHashMap.put(Movement_NameString, Movement_repeatsString);
              c2_Logger.info("crkodrt2:main:Movement_partsStringByMovement_NameStringHashMap.put(" + Movement_NameString + ", " + Movement_partsString + ")");
              Movement_partsStringByMovement_NameStringHashMap.put(Movement_NameString, Movement_partsString);
              c2_Logger.info("crkodrt2:main:Movement_ChartIncludeListStringByMovement_NameStringHashMap.put(" + Movement_NameString + ", " + Movement_ChartIncludeListString + ")");
              Movement_ChartIncludeListStringByMovement_NameStringHashMap.put(Movement_NameString, Movement_ChartIncludeListString);


              CurrentChartIndexArrayList = new ArrayList(128);
              Movement_ChartIncludeListSplitStringArray = Movement_ChartIncludeListString.split(",");
              Movement_ChartIncludeListSplitStringArraySize = java.lang.reflect.Array.getLength(Movement_ChartIncludeListSplitStringArray);
              CurrentChartIndexArrayListSize = Movement_ChartIncludeListSplitStringArraySize;
              for(
                  CurrentChartIndexArrayListIndex = 1;
                  CurrentChartIndexArrayListIndex <= CurrentChartIndexArrayListSize;
                  CurrentChartIndexArrayListIndex++
                 )
              {
                CurrentMovement_ChartString = Movement_ChartIncludeListSplitStringArray[(CurrentChartIndexArrayListIndex - 1)];
                CurrentMovement_ChartNumber = Integer.parseInt(CurrentMovement_ChartString);
                c2_Logger.info("crkodrt2:main:CurrentChartIndexArrayList.add(" + (CurrentChartIndexArrayListIndex - 1) + ", " + CurrentMovement_ChartNumber + ")");
                CurrentChartIndexArrayList.add((CurrentChartIndexArrayListIndex - 1), CurrentMovement_ChartNumber);
              }

              c2_Logger.info("crkodrt2:main:CurrentChartIndexArrayListSizeByMovementNameHashMap.put(" + Movement_NameString + ", " + CurrentChartIndexArrayListSize + ")");
              CurrentChartIndexArrayListSizeByMovementNameHashMap.put(Movement_NameString, CurrentChartIndexArrayListSize);

              c2_Logger.info("crkodrt2:main:CurrentChartIndexArrayListByMovementNameHashMap.put(" + Movement_NameString + ", " + CurrentChartIndexArrayList + ")");
              CurrentChartIndexArrayListByMovementNameHashMap.put(Movement_NameString, CurrentChartIndexArrayList);

              c2_Logger.info("crkodrt2:main:Movement_GlobalMidiSpecificationsIncludeListByMovement_NameStringHashMap.put(" + Movement_NameString + ", " + Movement_GlobalMidiSpecificationsIncludeList + ")");
              Movement_GlobalMidiSpecificationsIncludeListByMovement_NameStringHashMap.put(Movement_NameString, Movement_GlobalMidiSpecificationsIncludeList);


            }

          }

        }


        // compute the number of sequences

        try
        {
          GlobalSequences = Integer.parseInt(SequencesString);
        }
        catch (Exception e)
        {
          c2_Logger.warn("crkodrt2.main:c2_WARNING:" + e.getMessage());
          StackTraceElement[] steArray = e.getStackTrace();
          int steArraySize = java.lang.reflect.Array.getLength(steArray);
          for(int x = 0;x < NumberOfStackTraceElementsToOutput;x++)
          {
            if(x < steArraySize)
            {
              c2_Logger.warn("crkodrt2.main:c2_WARNING:" + steArray[x].toString());
            }
          }
          GlobalSequences = 1;
        }

        CurrentNumberOfSequences = GlobalSequences;
        c2_Logger.info("crkodrt2:main:CurrentNumberOfSequences:" + CurrentNumberOfSequences);














        // compute the number of parts

        try
        {
          GlobalParts = Integer.parseInt(PartsSelect);
        }
        catch (Exception e)
        {
          c2_Logger.warn("crkodrt2.main:c2_WARNING:" + e.getMessage());
          StackTraceElement[] steArray = e.getStackTrace();
          int steArraySize = java.lang.reflect.Array.getLength(steArray);
          for(int x = 0;x < NumberOfStackTraceElementsToOutput;x++)
          {
            if(x < steArraySize)
            {
              c2_Logger.warn("crkodrt2.main:c2_WARNING:" + steArray[x].toString());
            }
          }
          GlobalParts = 1;
        }


        CurrentNumberOfparts = GlobalParts;
        c2_Logger.info("crkodrt2:main:CurrentNumberOfparts:" + CurrentNumberOfparts);












        // the number of sequences used will become the larger of sequences or parts

        if(CurrentNumberOfparts > CurrentNumberOfSequences)
        {
          CurrentNumberOfSequences = CurrentNumberOfparts;
        }




        // if it is NOT song mode, then create a simple one movement song

        if( ! CommandLineInstance.hasOption("S"))
        {
          MovementMapSplitStringArray[0] = "init";
          Movement_NameString = "init";
          intMovementMapSplitStringArrayLength = 1;

          c2_Logger.info("crkodrt2:main:Movement_BeatsPerMinuteStringByMovement_NameStringHashMap.put(" + Movement_NameString + ", " + GlobalBeatsPerMinuteValueString + ")");
          Movement_BeatsPerMinuteStringByMovement_NameStringHashMap.put(Movement_NameString, GlobalBeatsPerMinuteValueString);
          c2_Logger.info("crkodrt2:main:Movement_TimeSignatureStringByMovement_NameStringHashMap.put(" + Movement_NameString + ", " + GlobalTimeSignatureValueString + ")");
          Movement_TimeSignatureStringByMovement_NameStringHashMap.put(Movement_NameString, GlobalTimeSignatureValueString);
          c2_Logger.info("crkodrt2:main:Movement_MeasuresStringByMovement_NameStringHashMap.put(" + Movement_NameString + ", " + MeasuresString + ")");
          Movement_MeasuresStringByMovement_NameStringHashMap.put(Movement_NameString, MeasuresString);
          c2_Logger.info("crkodrt2:main:Movement_SequencesStringByMovement_NameStringHashMap.put(" + Movement_NameString + ", " + SequencesString + ")");
          Movement_SequencesStringByMovement_NameStringHashMap.put(Movement_NameString, SequencesString);
          c2_Logger.info("crkodrt2:main:Movement_repeatsStringByMovement_NameStringHashMap.put(" + Movement_NameString + ", " + RepeatsSelect + ")");
          Movement_repeatsStringByMovement_NameStringHashMap.put(Movement_NameString, RepeatsSelect);
          c2_Logger.info("crkodrt2:main:Movement_partsStringByMovement_NameStringHashMap.put(" + Movement_NameString + ", " + PartsSelect + ")");
          Movement_partsStringByMovement_NameStringHashMap.put(Movement_NameString, PartsSelect);

          // setup the ChartIncludeList based on whether or not we have specified a Chart on the command line

          if(DesiredSingleChartNumber == 0)
          {

            c2_Logger.info("crkodrt2:main:Movement_ChartIncludeListStringByMovement_NameStringHashMap.put(" + Movement_NameString + ", " + DefaultMovement_ChartIncludeListString + ")");
            Movement_ChartIncludeListStringByMovement_NameStringHashMap.put(Movement_NameString, DefaultMovement_ChartIncludeListString);
            Movement_ChartIncludeList = DefaultMovement_ChartIncludeListString;
            Movement_ChartIncludeListSplitStringArray = Movement_ChartIncludeList.split(",");

          }
          else
          {
            c2_Logger.info("crkodrt2:main:Movement_ChartIncludeListStringByMovement_NameStringHashMap.put(" + Movement_NameString + ", " + DesiredSingleChartNumberString + ")");
            Movement_ChartIncludeListStringByMovement_NameStringHashMap.put(Movement_NameString, DesiredSingleChartNumberString);
            Movement_ChartIncludeList = DesiredSingleChartNumberString;
            if(CurrentNumberOfSequences > 1)
            {
              for(
                  Movement_ChartIncludeListIndex = 2;
                  Movement_ChartIncludeListIndex <= CurrentNumberOfSequences;
                  Movement_ChartIncludeListIndex++
                 )
              {
                Movement_ChartIncludeList = Movement_ChartIncludeList + ",";
                Movement_ChartIncludeList = Movement_ChartIncludeList + DesiredSingleChartNumberString;
              }
            }
            Movement_ChartIncludeListSplitStringArray = Movement_ChartIncludeList.split(",");
          }


          CurrentChartIndexArrayList = new ArrayList(128);
          Movement_ChartIncludeListSplitStringArraySize = java.lang.reflect.Array.getLength(Movement_ChartIncludeListSplitStringArray);
          CurrentChartIndexArrayListSize = Movement_ChartIncludeListSplitStringArraySize;
          for(
              CurrentChartIndexArrayListIndex = 1;
              CurrentChartIndexArrayListIndex <= CurrentChartIndexArrayListSize;
              CurrentChartIndexArrayListIndex++
             )
          {
            CurrentMovement_ChartString = Movement_ChartIncludeListSplitStringArray[(CurrentChartIndexArrayListIndex - 1)];
            CurrentMovement_ChartNumber = Integer.parseInt(CurrentMovement_ChartString);
            c2_Logger.info("crkodrt2:main:CurrentChartIndexArrayList.add(" + (CurrentChartIndexArrayListIndex - 1) + ", " + CurrentMovement_ChartNumber + ")");
            CurrentChartIndexArrayList.add((CurrentChartIndexArrayListIndex - 1), CurrentMovement_ChartNumber);
          }

          c2_Logger.info("crkodrt2:main:CurrentChartIndexArrayListSizeByMovementNameHashMap.put(" + Movement_NameString + ", " + CurrentChartIndexArrayListSize + ")");
          CurrentChartIndexArrayListSizeByMovementNameHashMap.put(Movement_NameString, CurrentChartIndexArrayListSize);

          c2_Logger.info("crkodrt2:main:CurrentChartIndexArrayListByMovementNameHashMap.put(" + Movement_NameString + ", " + CurrentChartIndexArrayList + ")");
          CurrentChartIndexArrayListByMovementNameHashMap.put(Movement_NameString, CurrentChartIndexArrayList);

          // use the default GlobalMidiSpecification list

          Movement_GlobalMidiSpecificationsIncludeList = DefaultGlobalMidiSpecificationIncludeList;

          c2_Logger.info("crkodrt2:main:Movement_GlobalMidiSpecificationsIncludeListByMovement_NameStringHashMap.put(" + Movement_NameString + ", " + Movement_GlobalMidiSpecificationsIncludeList + ")");
          Movement_GlobalMidiSpecificationsIncludeListByMovement_NameStringHashMap.put(Movement_NameString, Movement_GlobalMidiSpecificationsIncludeList);

        }


        // loop through the movements in the song

        for(
            MovementMapSplitStringArrayIndex = 0;
            MovementMapSplitStringArrayIndex < intMovementMapSplitStringArrayLength;
            MovementMapSplitStringArrayIndex++
           )
        {





          // get the current Movement Name

          CurrentMovementName = MovementMapSplitStringArray[MovementMapSplitStringArrayIndex];
          c2_Logger.info("crkodrt2:main:CurrentMovementName:" + CurrentMovementName + " = MovementMapSplitStringArray[" + MovementMapSplitStringArrayIndex + "]");




          // get the GlobalMidiSpecificationsIncludeList from the movement


          Movement_GlobalMidiSpecificationsIncludeListFlag = true;
          Movement_GlobalMidiSpecificationsIncludeList = (String)Movement_GlobalMidiSpecificationsIncludeListByMovement_NameStringHashMap.get(CurrentMovementName);
          c2_Logger.info("crkodrt2:main:Movement_GlobalMidiSpecificationsIncludeList:" + Movement_GlobalMidiSpecificationsIncludeList);





          // get the list of charts that will be used in this movement

          CurrentChartIndexArrayList = (ArrayList)CurrentChartIndexArrayListByMovementNameHashMap.get(CurrentMovementName);
          CurrentChartIndexArrayListSize = (int)CurrentChartIndexArrayListSizeByMovementNameHashMap.get(CurrentMovementName);

          // loop through all of the charts in the CurrentChartIndexArrayList

          for(
              CurrentChartIndexArrayListIndex = 0;
              CurrentChartIndexArrayListIndex < CurrentChartIndexArrayListSize;
              CurrentChartIndexArrayListIndex++
             )
          {

            // get the CurrentChartIndex

            CurrentChartIndex = (int)CurrentChartIndexArrayList.get(CurrentChartIndexArrayListIndex);
            c2_Logger.info("crkodrt2:main:CurrentChartIndex:" + CurrentChartIndex);

            CurrentChartArrayIndexByMidiChannelHashMap = ChartArrayIndexByMidiChannelHashMapArray[CurrentChartIndex];
            CurrentChartArrayIndexByMidiChannelHashMapSize = CurrentChartArrayIndexByMidiChannelHashMap.size();
            ChartGlobalMidiSpecificationIncludeList = (String)GlobalMidiSpecificationIncludeListByChartIndexHashMap.get(CurrentChartIndex);

            // if it is NOT song mode and there is either a ChartMidiSpecification or a GlobalIncludeList in the Chart

            if(
               ( ! CommandLineInstance.hasOption("S") ) &&
               (
                (ChartGlobalMidiSpecificationIncludeList != null) ||
                (CurrentChartArrayIndexByMidiChannelHashMapSize > 0)
               )
              )
            {

              if(ChartGlobalMidiSpecificationIncludeList != null)
              {
                ChartGlobalMidiSpecificationsIncludeListSplitStringArray = ChartGlobalMidiSpecificationIncludeList.split(",");
                ChartGlobalMidiSpecificationsIncludeListSplitStringArraySize = java.lang.reflect.Array.getLength(ChartGlobalMidiSpecificationsIncludeListSplitStringArray);

                // convert the ChartGlobalMidiSpecificationIncludeList into an ArrayList

                ChartMidiChannelArrayList = new ArrayList();
                for(
                    int ChartMidiChannelArrayIndex = 0;
                    ChartMidiChannelArrayIndex < 16;
                    ChartMidiChannelArrayIndex++
                   )
                {
                  if(ChartMidiChannelArrayIndex < ChartGlobalMidiSpecificationsIncludeListSplitStringArraySize)
                  {
                    MidiChannel = GlobalMidiChannelArray[(Integer.parseInt(ChartGlobalMidiSpecificationsIncludeListSplitStringArray[ChartMidiChannelArrayIndex]) - 1)];
                  }
                  else
                  {
                    MidiChannel = 0;
                  }
                  c2_Logger.info("crkodrt2:main:ChartMidiChannelArrayList.add(" + MidiChannel + ")");
                  ChartMidiChannelArrayList.add(MidiChannel);
                }

                c2_Logger.info("crkodrt2:main:ChartMidiChannelArrayListOfArrayLists.set(" + CurrentChartIndex + ", ChartMidiChannelArrayList)");
                ChartMidiChannelArrayListOfArrayLists.set(CurrentChartIndex, ChartMidiChannelArrayList);
                c2_Logger.info("crkodrt2:main:MidiChannelArraySizeArrayList.set(" + CurrentChartIndex + ", " + ChartGlobalMidiSpecificationsIncludeListSplitStringArraySize + ")");
                MidiChannelArraySizeArrayList.set(CurrentChartIndex, ChartGlobalMidiSpecificationsIncludeListSplitStringArraySize);

                // loop through all of the <GlobalMidiSpecification> nodes in the chart list

                for (
                     ChartGlobalMidiSpecificationsIncludeListSplitStringArrayIndex = 0;
                     ChartGlobalMidiSpecificationsIncludeListSplitStringArrayIndex < ChartGlobalMidiSpecificationsIncludeListSplitStringArraySize;
                     ChartGlobalMidiSpecificationsIncludeListSplitStringArrayIndex++
                    )
                {

                  // compute the index into the GlobalMidiSpecification collection

                  intGlobalMidiSpecificationNodeListIndex = (Integer.parseInt(ChartGlobalMidiSpecificationsIncludeListSplitStringArray[ChartGlobalMidiSpecificationsIncludeListSplitStringArrayIndex]) - 1);
                  c2_Logger.info("crkodrt2:main:intGlobalMidiSpecificationNodeListIndex:" + intGlobalMidiSpecificationNodeListIndex);

                  // copy the Global Midi data into the appropriate Chart Midi area

                  c2_Logger.info("crkodrt2:main:ChartNoteFilterStringArray[" + CurrentChartIndex + "][" + ChartGlobalMidiSpecificationsIncludeListSplitStringArrayIndex + "]     = " + GlobalNoteFilterStringArray[intGlobalMidiSpecificationNodeListIndex]);
                  ChartNoteFilterStringArray[CurrentChartIndex][ChartGlobalMidiSpecificationsIncludeListSplitStringArrayIndex]     = GlobalNoteFilterStringArray[intGlobalMidiSpecificationNodeListIndex];
                  c2_Logger.info("crkodrt2:main:ChartBeatFilterStringArray[" + CurrentChartIndex + "][" + ChartGlobalMidiSpecificationsIncludeListSplitStringArrayIndex + "]     = " + GlobalBeatFilterStringArray[intGlobalMidiSpecificationNodeListIndex]);
                  ChartBeatFilterStringArray[CurrentChartIndex][ChartGlobalMidiSpecificationsIncludeListSplitStringArrayIndex]     = GlobalBeatFilterStringArray[intGlobalMidiSpecificationNodeListIndex];
                  c2_Logger.info("crkodrt2:main:ChartRestFilterStringArray[" + CurrentChartIndex + "][" + ChartGlobalMidiSpecificationsIncludeListSplitStringArrayIndex + "]     = " + GlobalRestFilterStringArray[intGlobalMidiSpecificationNodeListIndex]);
                  ChartRestFilterStringArray[CurrentChartIndex][ChartGlobalMidiSpecificationsIncludeListSplitStringArrayIndex]     = GlobalRestFilterStringArray[intGlobalMidiSpecificationNodeListIndex];
                  c2_Logger.info("crkodrt2:main:ChartOctaveFilterStringArray[" + CurrentChartIndex + "][" + ChartGlobalMidiSpecificationsIncludeListSplitStringArrayIndex + "]   = " + GlobalOctaveFilterStringArray[intGlobalMidiSpecificationNodeListIndex]);
                  ChartOctaveFilterStringArray[CurrentChartIndex][ChartGlobalMidiSpecificationsIncludeListSplitStringArrayIndex]   = GlobalOctaveFilterStringArray[intGlobalMidiSpecificationNodeListIndex];
                  c2_Logger.info("crkodrt2:main:ChartVelocityFilterStringArray[" + CurrentChartIndex + "][" + ChartGlobalMidiSpecificationsIncludeListSplitStringArrayIndex + "] = " + GlobalVelocityFilterStringArray[intGlobalMidiSpecificationNodeListIndex]);
                  ChartVelocityFilterStringArray[CurrentChartIndex][ChartGlobalMidiSpecificationsIncludeListSplitStringArrayIndex] = GlobalVelocityFilterStringArray[intGlobalMidiSpecificationNodeListIndex];
                  c2_Logger.info("crkodrt2:main:ChartGlobalMidiSpecificationArray[" + CurrentChartIndex + "][" + ChartGlobalMidiSpecificationsIncludeListSplitStringArrayIndex + "]     = " + ChartGlobalMidiSpecificationsIncludeListSplitStringArray[ChartGlobalMidiSpecificationsIncludeListSplitStringArrayIndex]);
                  ChartGlobalMidiSpecificationArray[CurrentChartIndex][ChartGlobalMidiSpecificationsIncludeListSplitStringArrayIndex]     = ChartGlobalMidiSpecificationsIncludeListSplitStringArray[ChartGlobalMidiSpecificationsIncludeListSplitStringArrayIndex];



                }

              }


              // if there are any ChartMidiSpecifications for this Chart

              if(CurrentChartArrayIndexByMidiChannelHashMapSize > 0)
              {

                // convert the CurrentChartArrayIndexByMidiChannelHashMap into an ArrayList

                ChartMidiChannelArrayList = new ArrayList();
                CurrentChartArrayIndexByMidiChannelHashMapIterator = CurrentChartArrayIndexByMidiChannelHashMap.entrySet().iterator();
                while(CurrentChartArrayIndexByMidiChannelHashMapIterator.hasNext())
                {
                  CurrentChartArrayIndexByMidiChannelHashMapEntry = (Map.Entry) CurrentChartArrayIndexByMidiChannelHashMapIterator.next();
                  CurrentChartArrayIndexByMidiChannelHashMapKey = (String)CurrentChartArrayIndexByMidiChannelHashMapEntry.getKey();
                  CurrentChartArrayIndex = (int)CurrentChartArrayIndexByMidiChannelHashMapEntry.getValue();
                  MidiChannel = Integer.parseInt(CurrentChartArrayIndexByMidiChannelHashMapKey);

                  c2_Logger.info("crkodrt2:main:ChartMidiChannelArrayList.add(" + MidiChannel + ")");
                  ChartMidiChannelArrayList.add(MidiChannel);

                }

                // copy in all of the midi data into the appropriate Chart Midi area

                c2_Logger.info("crkodrt2:main:ChartNoteFilterStringArray[" + CurrentChartIndex + "]     = " + OriginalChartNoteFilterStringArray[CurrentChartIndex]);
                ChartNoteFilterStringArray[CurrentChartIndex]     = OriginalChartNoteFilterStringArray[CurrentChartIndex];
                c2_Logger.info("crkodrt2:main:ChartBeatFilterStringArray[" + CurrentChartIndex + "]     = " + OriginalChartBeatFilterStringArray[CurrentChartIndex]);
                ChartBeatFilterStringArray[CurrentChartIndex]     = OriginalChartBeatFilterStringArray[CurrentChartIndex];
                c2_Logger.info("crkodrt2:main:ChartRestFilterStringArray[" + CurrentChartIndex + "]     = " + OriginalChartRestFilterStringArray[CurrentChartIndex]);
                ChartRestFilterStringArray[CurrentChartIndex]     = OriginalChartRestFilterStringArray[CurrentChartIndex];
                c2_Logger.info("crkodrt2:main:ChartOctaveFilterStringArray[" + CurrentChartIndex + "]   = " + OriginalChartOctaveFilterStringArray[CurrentChartIndex]);
                ChartOctaveFilterStringArray[CurrentChartIndex]   = OriginalChartOctaveFilterStringArray[CurrentChartIndex];
                c2_Logger.info("crkodrt2:main:ChartVelocityFilterStringArray[" + CurrentChartIndex + "] = " + OriginalChartVelocityFilterStringArray[CurrentChartIndex]);
                ChartVelocityFilterStringArray[CurrentChartIndex] = OriginalChartVelocityFilterStringArray[CurrentChartIndex];



                c2_Logger.info("crkodrt2:main:ChartMidiChannelArrayListOfArrayLists.set(" + CurrentChartIndex + ", ChartMidiChannelArrayList)");
                ChartMidiChannelArrayListOfArrayLists.set(CurrentChartIndex, ChartMidiChannelArrayList);
                c2_Logger.info("crkodrt2:main:MidiChannelArraySizeArrayList.set(" + CurrentChartIndex + ", " + CurrentChartArrayIndexByMidiChannelHashMapSize + ")");
                MidiChannelArraySizeArrayList.set(CurrentChartIndex, CurrentChartArrayIndexByMidiChannelHashMapSize);

              }
            }

            // otherwise, save the MidiChannelArrayList for this Chart from the Movement_GlobalMidiSpecificationsIncludeList

            else
            {

              // if there is NOT a Movement_GlobalMidiSpecificationsIncludeList
              // then we will set it in order to use the DefaultGlobalMidiSpecificationIncludeList

              if(Movement_GlobalMidiSpecificationsIncludeList == null)
              {
                Movement_GlobalMidiSpecificationsIncludeListFlag = false;
                Movement_GlobalMidiSpecificationsIncludeList = DefaultGlobalMidiSpecificationIncludeList;
              }
              Movement_GlobalMidiSpecificationsIncludeListSplitStringArray = Movement_GlobalMidiSpecificationsIncludeList.split(",");
              Movement_GlobalMidiSpecificationsIncludeListSplitStringArraySize = java.lang.reflect.Array.getLength(Movement_GlobalMidiSpecificationsIncludeListSplitStringArray);

              // convert the GlobalMidiChannelArray into an ArrayList

              ChartMidiChannelArrayList = new ArrayList();
              for(
                  int ChartMidiChannelArrayIndex = 0;
                  ChartMidiChannelArrayIndex < 16;
                  ChartMidiChannelArrayIndex++
                 )
              {
                if(ChartMidiChannelArrayIndex < Movement_GlobalMidiSpecificationsIncludeListSplitStringArraySize)
                {
                  MidiChannel = GlobalMidiChannelArray[(Integer.parseInt(Movement_GlobalMidiSpecificationsIncludeListSplitStringArray[ChartMidiChannelArrayIndex]) - 1)];
                }
                else
                {
                  MidiChannel = 0;
                }
                c2_Logger.info("crkodrt2:main:ChartMidiChannelArrayList.add(" + MidiChannel + ")");
                ChartMidiChannelArrayList.add(MidiChannel);
              }

              c2_Logger.info("crkodrt2:main:ChartMidiChannelArrayListOfArrayLists.set(" + CurrentChartIndex + ", ChartMidiChannelArrayList)");
              ChartMidiChannelArrayListOfArrayLists.set(CurrentChartIndex, ChartMidiChannelArrayList);
              c2_Logger.info("crkodrt2:main:MidiChannelArraySizeArrayList.set(" + CurrentChartIndex + ", " + Movement_GlobalMidiSpecificationsIncludeListSplitStringArraySize + ")");
              MidiChannelArraySizeArrayList.set(CurrentChartIndex, Movement_GlobalMidiSpecificationsIncludeListSplitStringArraySize);

              // loop through all of the <GlobalMidiSpecification> nodes in the movement list

              for (
                   Movement_GlobalMidiSpecificationsIncludeListSplitStringArrayIndex = 0;
                   Movement_GlobalMidiSpecificationsIncludeListSplitStringArrayIndex < Movement_GlobalMidiSpecificationsIncludeListSplitStringArraySize;
                   Movement_GlobalMidiSpecificationsIncludeListSplitStringArrayIndex++
                  )
              {

                // compute the index into the GlobalMidiSpecification collection

                intGlobalMidiSpecificationNodeListIndex = (Integer.parseInt(Movement_GlobalMidiSpecificationsIncludeListSplitStringArray[Movement_GlobalMidiSpecificationsIncludeListSplitStringArrayIndex]) - 1);
                c2_Logger.info("crkodrt2:main:intGlobalMidiSpecificationNodeListIndex:" + intGlobalMidiSpecificationNodeListIndex);

                // copy the Global Midi data into the appropriate Chart Midi area

                c2_Logger.info("crkodrt2:main:ChartNoteFilterStringArray[" + CurrentChartIndex + "][" + Movement_GlobalMidiSpecificationsIncludeListSplitStringArrayIndex + "]     = " + GlobalNoteFilterStringArray[intGlobalMidiSpecificationNodeListIndex]);
                ChartNoteFilterStringArray[CurrentChartIndex][Movement_GlobalMidiSpecificationsIncludeListSplitStringArrayIndex]     = GlobalNoteFilterStringArray[intGlobalMidiSpecificationNodeListIndex];
                c2_Logger.info("crkodrt2:main:ChartBeatFilterStringArray[" + CurrentChartIndex + "][" + Movement_GlobalMidiSpecificationsIncludeListSplitStringArrayIndex + "]     = " + GlobalBeatFilterStringArray[intGlobalMidiSpecificationNodeListIndex]);
                ChartBeatFilterStringArray[CurrentChartIndex][Movement_GlobalMidiSpecificationsIncludeListSplitStringArrayIndex]     = GlobalBeatFilterStringArray[intGlobalMidiSpecificationNodeListIndex];
                c2_Logger.info("crkodrt2:main:ChartRestFilterStringArray[" + CurrentChartIndex + "][" + Movement_GlobalMidiSpecificationsIncludeListSplitStringArrayIndex + "]     = " + GlobalRestFilterStringArray[intGlobalMidiSpecificationNodeListIndex]);
                ChartRestFilterStringArray[CurrentChartIndex][Movement_GlobalMidiSpecificationsIncludeListSplitStringArrayIndex]     = GlobalRestFilterStringArray[intGlobalMidiSpecificationNodeListIndex];
                c2_Logger.info("crkodrt2:main:ChartOctaveFilterStringArray[" + CurrentChartIndex + "][" + Movement_GlobalMidiSpecificationsIncludeListSplitStringArrayIndex + "]   = " + GlobalOctaveFilterStringArray[intGlobalMidiSpecificationNodeListIndex]);
                ChartOctaveFilterStringArray[CurrentChartIndex][Movement_GlobalMidiSpecificationsIncludeListSplitStringArrayIndex]   = GlobalOctaveFilterStringArray[intGlobalMidiSpecificationNodeListIndex];
                c2_Logger.info("crkodrt2:main:ChartVelocityFilterStringArray[" + CurrentChartIndex + "][" + Movement_GlobalMidiSpecificationsIncludeListSplitStringArrayIndex + "] = " + GlobalVelocityFilterStringArray[intGlobalMidiSpecificationNodeListIndex]);
                ChartVelocityFilterStringArray[CurrentChartIndex][Movement_GlobalMidiSpecificationsIncludeListSplitStringArrayIndex] = GlobalVelocityFilterStringArray[intGlobalMidiSpecificationNodeListIndex];

                c2_Logger.info("crkodrt2:main:ChartGlobalMidiSpecificationArray[" + CurrentChartIndex + "][" + Movement_GlobalMidiSpecificationsIncludeListSplitStringArrayIndex + "]     = " + Movement_GlobalMidiSpecificationsIncludeListSplitStringArray[Movement_GlobalMidiSpecificationsIncludeListSplitStringArrayIndex]);
                ChartGlobalMidiSpecificationArray[CurrentChartIndex][Movement_GlobalMidiSpecificationsIncludeListSplitStringArrayIndex]     = Movement_GlobalMidiSpecificationsIncludeListSplitStringArray[Movement_GlobalMidiSpecificationsIncludeListSplitStringArrayIndex];

              }
            }

          }











          // compute the number of measures

          try
          {
            GlobalMeasures = Integer.parseInt(MeasuresString);
          }
          catch (Exception e)
          {
            c2_Logger.warn("crkodrt2.main:c2_WARNING:" + e.getMessage());
            StackTraceElement[] steArray = e.getStackTrace();
            int steArraySize = java.lang.reflect.Array.getLength(steArray);
            for(int x = 0;x < NumberOfStackTraceElementsToOutput;x++)
            {
              if(x < steArraySize)
              {
                c2_Logger.warn("crkodrt2.main:c2_WARNING:" + steArray[x].toString());
              }
            }
            GlobalMeasures = 4;
          }

          Movement_MeasuresString = (String)Movement_MeasuresStringByMovement_NameStringHashMap.get(CurrentMovementName);
          try
          {
            Movement_Measures = Integer.parseInt(Movement_MeasuresString);
          }
          catch (Exception e)
          {
            c2_Logger.warn("crkodrt2.main:c2_WARNING:" + e.getMessage());
            StackTraceElement[] steArray = e.getStackTrace();
            int steArraySize = java.lang.reflect.Array.getLength(steArray);
            for(int x = 0;x < NumberOfStackTraceElementsToOutput;x++)
            {
              if(x < steArraySize)
              {
                c2_Logger.warn("crkodrt2.main:c2_WARNING:" + steArray[x].toString());
              }
            }
            Movement_Measures = 4;
          }

          if(CommandLineInstance.hasOption("S"))
          {
            CurrentNumberOfMeasures = Movement_Measures;
          }
          else
          {
            CurrentNumberOfMeasures = GlobalMeasures;
          }
          c2_Logger.info("crkodrt2:main:CurrentNumberOfMeasures:" + CurrentNumberOfMeasures);





          // compute the number of sequences

          try
          {
            GlobalSequences = Integer.parseInt(SequencesString);
          }
          catch (Exception e)
          {
            c2_Logger.warn("crkodrt2.main:c2_WARNING:" + e.getMessage());
            StackTraceElement[] steArray = e.getStackTrace();
            int steArraySize = java.lang.reflect.Array.getLength(steArray);
            for(int x = 0;x < NumberOfStackTraceElementsToOutput;x++)
            {
              if(x < steArraySize)
              {
                c2_Logger.warn("crkodrt2.main:c2_WARNING:" + steArray[x].toString());
              }
            }
            GlobalSequences = 1;
          }

          Movement_SequencesString = (String)Movement_SequencesStringByMovement_NameStringHashMap.get(CurrentMovementName);
          try
          {
            Movement_Sequences = Integer.parseInt(Movement_SequencesString);
          }
          catch (Exception e)
          {
            c2_Logger.warn("crkodrt2.main:c2_WARNING:" + e.getMessage());
            StackTraceElement[] steArray = e.getStackTrace();
            int steArraySize = java.lang.reflect.Array.getLength(steArray);
            for(int x = 0;x < NumberOfStackTraceElementsToOutput;x++)
            {
              if(x < steArraySize)
              {
                c2_Logger.warn("crkodrt2.main:c2_WARNING:" + steArray[x].toString());
              }
            }
            Movement_Sequences = 1;
          }

          if(CommandLineInstance.hasOption("S"))
          {
            CurrentNumberOfSequences = Movement_Sequences;
          }
          else
          {
            CurrentNumberOfSequences = GlobalSequences;
          }
          c2_Logger.info("crkodrt2:main:CurrentNumberOfSequences:" + CurrentNumberOfSequences);














          // compute the number of parts

          try
          {
            GlobalParts = Integer.parseInt(PartsSelect);
          }
          catch (Exception e)
          {
            c2_Logger.warn("crkodrt2.main:c2_WARNING:" + e.getMessage());
            StackTraceElement[] steArray = e.getStackTrace();
            int steArraySize = java.lang.reflect.Array.getLength(steArray);
            for(int x = 0;x < NumberOfStackTraceElementsToOutput;x++)
            {
              if(x < steArraySize)
              {
                c2_Logger.warn("crkodrt2.main:c2_WARNING:" + steArray[x].toString());
              }
            }
            GlobalParts = 1;
          }

          Movement_partsString = (String)Movement_partsStringByMovement_NameStringHashMap.get(CurrentMovementName);
          try
          {
            Movement_parts = Integer.parseInt(Movement_partsString);
          }
          catch (Exception e)
          {
            c2_Logger.warn("crkodrt2.main:c2_WARNING:" + e.getMessage());
            StackTraceElement[] steArray = e.getStackTrace();
            int steArraySize = java.lang.reflect.Array.getLength(steArray);
            for(int x = 0;x < NumberOfStackTraceElementsToOutput;x++)
            {
              if(x < steArraySize)
              {
                c2_Logger.warn("crkodrt2.main:c2_WARNING:" + steArray[x].toString());
              }
            }
            Movement_parts = 1;
          }

          if(CommandLineInstance.hasOption("S"))
          {
            CurrentNumberOfparts = Movement_parts;
          }
          else
          {
            CurrentNumberOfparts = GlobalParts;
          }
          c2_Logger.info("crkodrt2:main:CurrentNumberOfparts:" + CurrentNumberOfparts);












          // the number of sequences used will become the larger of sequences or parts

          if(CurrentNumberOfparts > CurrentNumberOfSequences)
          {
            CurrentNumberOfSequences = CurrentNumberOfparts;
          }
          c2_Logger.info("crkodrt2:main:CurrentNumberOfSequencesByMovementNameHashMap.put(" + CurrentMovementName + ", " + CurrentNumberOfSequences + ")");
          CurrentNumberOfSequencesByMovementNameHashMap.put(CurrentMovementName, CurrentNumberOfSequences);





          // compute the BPM that will be used


          try
          {
            GlobalBeatsPerMinute = Double.parseDouble(GlobalBeatsPerMinuteValueString);
          }
          catch (Exception e)
          {
            c2_Logger.warn("crkodrt2.main:c2_WARNING:" + e.getMessage());
            StackTraceElement[] steArray = e.getStackTrace();
            int steArraySize = java.lang.reflect.Array.getLength(steArray);
            for(int x = 0;x < NumberOfStackTraceElementsToOutput;x++)
            {
              if(x < steArraySize)
              {
                c2_Logger.warn("crkodrt2.main:c2_WARNING:" + steArray[x].toString());
              }
            }
            GlobalBeatsPerMinute = 120;
          }

          Movement_BeatsPerMinuteString = (String)Movement_BeatsPerMinuteStringByMovement_NameStringHashMap.get(CurrentMovementName);
          try
          {
            Movement_BeatsPerMinute = Double.parseDouble(Movement_BeatsPerMinuteString);
          }
          catch (Exception e)
          {
            c2_Logger.warn("crkodrt2.main:c2_WARNING:" + e.getMessage());
            StackTraceElement[] steArray = e.getStackTrace();
            int steArraySize = java.lang.reflect.Array.getLength(steArray);
            for(int x = 0;x < NumberOfStackTraceElementsToOutput;x++)
            {
              if(x < steArraySize)
              {
                c2_Logger.warn("crkodrt2.main:c2_WARNING:" + steArray[x].toString());
              }
            }
            Movement_BeatsPerMinute = 120;
          }

          if(CommandLineInstance.hasOption("S"))
          {
            CurrentBeatsPerMinute = Movement_BeatsPerMinute;
          }
          else
          {
            CurrentBeatsPerMinute = GlobalBeatsPerMinute;
          }
          c2_Logger.info("crkodrt2:main:CurrentBeatsPerMinute:" + CurrentBeatsPerMinute);





          // compute the time signature to use

          Movement_TimeSignatureString = (String)Movement_TimeSignatureStringByMovement_NameStringHashMap.get(CurrentMovementName);

          if(CommandLineInstance.hasOption("S"))
          {
            CurrentTimeSignatureValueString = Movement_TimeSignatureString;
          }
          else
          {
            CurrentTimeSignatureValueString = GlobalTimeSignatureValueString;
          }
          c2_Logger.info("crkodrt2:main:CurrentTimeSignatureValueString:" + CurrentTimeSignatureValueString);





          CurrentTimeSignatureValueSplitStringArray      = CurrentTimeSignatureValueString.split("/");

          try
          {
            GlobalNumberOfBeatsInAMeasure = Integer.parseInt(CurrentTimeSignatureValueSplitStringArray[0]);
          }
          catch (Exception e)
          {
            c2_Logger.warn("crkodrt2.main:c2_WARNING:" + e.getMessage());
            StackTraceElement[] steArray = e.getStackTrace();
            int steArraySize = java.lang.reflect.Array.getLength(steArray);
            for(int x = 0;x < NumberOfStackTraceElementsToOutput;x++)
            {
              if(x < steArraySize)
              {
                c2_Logger.warn("crkodrt2.main:c2_WARNING:" + steArray[x].toString());
              }
            }
            GlobalNumberOfBeatsInAMeasure = 4;
          }


          try
          {
            GlobalFractionOfAMeasureThatGetsTheBeat = Integer.parseInt(CurrentTimeSignatureValueSplitStringArray[1]);
          }
          catch (Exception e)
          {
            c2_Logger.warn("crkodrt2.main:c2_WARNING:" + e.getMessage());
            StackTraceElement[] steArray = e.getStackTrace();
            int steArraySize = java.lang.reflect.Array.getLength(steArray);
            for(int x = 0;x < NumberOfStackTraceElementsToOutput;x++)
            {
              if(x < steArraySize)
              {
                c2_Logger.warn("crkodrt2.main:c2_WARNING:" + steArray[x].toString());
              }
            }
            GlobalFractionOfAMeasureThatGetsTheBeat = 4;
          }















          // compute some time intervals

          DesiredBeatsPerMinute = CurrentBeatsPerMinute;
          c2_Logger.info("crkodrt2:main:DesiredBeatsPerMinute:" + DesiredBeatsPerMinute);
          DesiredFullMeasureDuration = 60000 / (DesiredBeatsPerMinute / GlobalNumberOfBeatsInAMeasure);
          c2_Logger.info("crkodrt2:main:DesiredFullMeasureDuration:" + DesiredFullMeasureDuration);

          DesiredSongSegmentDuration = (int)Math.floor(DesiredFullMeasureDuration / (GlobalNumberOfBeatsInAMeasure * GlobalFractionOfAMeasureThatGetsTheBeat * TIMING_CLOCK_Divisor));
          c2_Logger.info("crkodrt2:main:DesiredSongSegmentDuration:" + DesiredSongSegmentDuration);






          DesiredTIMING_CLOCK_IntervalDuration = (int)Math.floor(DesiredFullMeasureDuration / (GlobalFractionOfAMeasureThatGetsTheBeat * TIMING_CLOCK_Divisor));
          c2_Logger.info("crkodrt2:main:DesiredTIMING_CLOCK_IntervalDuration:" + DesiredTIMING_CLOCK_IntervalDuration);

          TenthTIMING_CLOCK_IntervalDuration = (int)Math.floor(DesiredTIMING_CLOCK_IntervalDuration / 10);
          c2_Logger.info("crkodrt2:main:TenthTIMING_CLOCK_IntervalDuration:" + TenthTIMING_CLOCK_IntervalDuration);

          TIMING_CLOCK_IntervalDuration = (TenthTIMING_CLOCK_IntervalDuration * 10);
          c2_Logger.info("crkodrt2:main:TIMING_CLOCK_IntervalDuration:" + TIMING_CLOCK_IntervalDuration);


          // FullMeasureDuration = (TIMING_CLOCK_IntervalDuration * (GlobalFractionOfAMeasureThatGetsTheBeat * TIMING_CLOCK_Divisor));
          FullMeasureDuration = (DesiredSongSegmentDuration * (GlobalNumberOfBeatsInAMeasure * GlobalFractionOfAMeasureThatGetsTheBeat * TIMING_CLOCK_Divisor));
          c2_Logger.info("crkodrt2:main:FullMeasureDuration:" + FullMeasureDuration);

          BeatsPerMinute = (60000 * GlobalNumberOfBeatsInAMeasure) / FullMeasureDuration;
          c2_Logger.info("crkodrt2:main:BeatsPerMinute:" + BeatsPerMinute);
          c2_Logger.info("crkodrt2:main:BeatsPerMinuteByMovementNameHashMap.put(" + CurrentMovementName + ", " + BeatsPerMinute + ")");
          BeatsPerMinuteByMovementNameHashMap.put(CurrentMovementName, BeatsPerMinute);


          FullSequenceDuration = CurrentNumberOfMeasures * FullMeasureDuration;
          c2_Logger.info("crkodrt2:main:FullSequenceDurationByMovementNameHashMap.put(" + CurrentMovementName + ", " + FullSequenceDuration + ")");
          FullSequenceDurationByMovementNameHashMap.put(CurrentMovementName, FullSequenceDuration);
          QuarterOfABeatDuration = FullMeasureDuration / (GlobalNumberOfBeatsInAMeasure * 4);
          c2_Logger.info("crkodrt2:main:QuarterOfABeatDuration:" + QuarterOfABeatDuration);

          c2_Logger.info("crkodrt2:main:SongSegmentDurationByMovementNameHashMap.put(" + CurrentMovementName + ", " + DesiredSongSegmentDuration + ")");
          SongSegmentDurationByMovementNameHashMap.put(CurrentMovementName, DesiredSongSegmentDuration);

          // compute the duration in milliseconds of one midi tick assuming that the PPQ is hard coded to 96

          MidiTickDuration = (60000 / (BeatsPerMinute * 96));
          c2_Logger.info("crkodrt2:main:MidiTickDuration:" + MidiTickDuration);













          try
          {
            GlobalRepeats = Integer.parseInt(RepeatsSelect);
          }
          catch (Exception e)
          {
            c2_Logger.warn("crkodrt2.main:c2_WARNING:" + e.getMessage());
            StackTraceElement[] steArray = e.getStackTrace();
            int steArraySize = java.lang.reflect.Array.getLength(steArray);
            for(int x = 0;x < NumberOfStackTraceElementsToOutput;x++)
            {
              if(x < steArraySize)
              {
                c2_Logger.warn("crkodrt2.main:c2_WARNING:" + steArray[x].toString());
              }
            }
            GlobalRepeats = 1;
          }

          Movement_repeatsString = (String)Movement_repeatsStringByMovement_NameStringHashMap.get(CurrentMovementName);
          try
          {
            Movement_repeats = Integer.parseInt(Movement_repeatsString);
          }
          catch (Exception e)
          {
            c2_Logger.warn("crkodrt2.main:c2_WARNING:" + e.getMessage());
            StackTraceElement[] steArray = e.getStackTrace();
            int steArraySize = java.lang.reflect.Array.getLength(steArray);
            for(int x = 0;x < NumberOfStackTraceElementsToOutput;x++)
            {
              if(x < steArraySize)
              {
                c2_Logger.warn("crkodrt2.main:c2_WARNING:" + steArray[x].toString());
              }
            }
            Movement_repeats = 1;
          }



          if(CommandLineInstance.hasOption("N"))
          {
            NumberOfLoopsString = CommandLineInstance.getOptionValue("N");
            NumberOfLoops = Integer.parseInt(NumberOfLoopsString);
          }
          else
          {
            if(CommandLineInstance.hasOption("S"))
            {
              NumberOfLoops = 1;
            }
            else
            {
              NumberOfLoops = GlobalRepeats;
            }
          }

          c2_Logger.info("crkodrt2:main:NumberOfLoopsByMovementNameHashMap.put(" + CurrentMovementName + ", " + NumberOfLoops + ")");
          NumberOfLoopsByMovementNameHashMap.put(CurrentMovementName, NumberOfLoops);

          if(CommandLineInstance.hasOption("R"))
          {
            NumberOfSongRepeatsString = CommandLineInstance.getOptionValue("R");
            NumberOfSongRepeats = Integer.parseInt(NumberOfSongRepeatsString);
          }
          else
          {
            NumberOfSongRepeats = 1;
          }


          TempMidiOnShortMessageArrayList = new ArrayList();
          TempMidiOffShortMessageArrayList = new ArrayList();
          MidiFileOutputStreamByMidiChannelHashMap = new HashMap();

          if( ! LogFileInputFlag )
          {

            // GenerateMethodSelect
            //   possible values:
            //     random
            //     DOC
            //     WAYNE
            //     DIFFERENCES
            //     MARCH
            //     ArrangedInfluence
            //       if this value is supplied, then the song needs to be
            //       structured as:
            //         CHART1 CHART2 CHART3 CHART4
            //         CHART1 CHART2 CHART3 CHART4
            //         CHART5 CHART6 CHART7 CHART8
            //         CHART1 CHART2 CHART3 CHART4


            // create the ArrayList to hold the MidiTrack HashMaps

            MidiTrackHashMapArrayList = new ArrayList();
            for(
                CurrentChartIndex = 0;
                CurrentChartIndex < 32;
                CurrentChartIndex++
               )
            {
              MidiTrackHashMapArrayList.add(new HashMap());
            }

            // now that we have built the ChartIndex array, we will loop through those values and build the tracks

            for(
                CurrentChartIndexArrayListIndex = 0;
                CurrentChartIndexArrayListIndex < CurrentChartIndexArrayListSize;
                CurrentChartIndexArrayListIndex++
               )
            {

              CurrentChartIndex = (int)CurrentChartIndexArrayList.get(CurrentChartIndexArrayListIndex);



              MidiShortMessageArrayListByMillisecondHashMap = new HashMap();





              // // generate START message on track 16
              //
              // MidiChannel = 16;
              // MidiTrackHashMapKey = "1~0~16";
              // MidiTrackHashMapValue = String.format("\250~0");
              // c2_Logger.info("crkodrt2:main:MidiTrackHashMapArray[" + CurrentChartIndex + "].put(" + MidiTrackHashMapKey + "," + MidiTrackHashMapValue + ")");
              // MidiTrackHashMapArray[CurrentChartIndex].put(MidiTrackHashMapKey,MidiTrackHashMapValue);
              //
              //
              //
              //
              // // generate CLOCK messages on track 16
              //
              // MidiChannel = 16;
              // for(
              //     NoteOnAbsoluteMillisecond = TIMING_CLOCK_IntervalDuration;
              //     NoteOnAbsoluteMillisecond < FullSequenceDuration;
              //     NoteOnAbsoluteMillisecond += TIMING_CLOCK_IntervalDuration
              //    )
              // {
              //
              //   MidiTrackHashMapKey = String.format("1~%d~16",NoteOnAbsoluteMillisecond,MidiChannel);
              //   MidiTrackHashMapValue = String.format("\248~0");
              //   c2_Logger.info("crkodrt2:main:MidiTrackHashMapArray[" + CurrentChartIndex + "].put(" + MidiTrackHashMapKey + "," + MidiTrackHashMapValue + ")");
              //   MidiTrackHashMapArray[CurrentChartIndex].put(MidiTrackHashMapKey,MidiTrackHashMapValue);
              //
              // }




              // loop through all of the <ChartMidiSpecification> nodes

              MidiChannelArraySize = (int)MidiChannelArraySizeArrayList.get(CurrentChartIndex);
              c2_Logger.info("crkodrt2:main:MidiChannelArraySize:" + MidiChannelArraySize);
              for (
                   int intChartMidiSpecificationIndex = 0;
                   intChartMidiSpecificationIndex < MidiChannelArraySize;
                   intChartMidiSpecificationIndex++
                  )
              {


                // // NoteOn Message
                // // 00 90 42 64
                //
                // NoteOnMessageByteArray = new byte[]
                // {
                //  (byte)0x00, (byte)0x90, (byte)0x42, (byte)0x64
                // };
                //
                // MidiFileByteArray[MidiFileByteArrayIndex] = (byte)0x00;
                // MidiFileByteArrayIndex++;
                // MidiFileByteArraySize++;
                // TrackChunkLength++;
                // MidiFileByteArray[MidiFileByteArrayIndex] = (byte)0x90;
                // MidiFileByteArrayIndex++;
                // MidiFileByteArraySize++;
                // TrackChunkLength++;
                // MidiFileByteArray[MidiFileByteArrayIndex] = (byte)0x42;
                // MidiFileByteArrayIndex++;
                // MidiFileByteArraySize++;
                // TrackChunkLength++;
                // MidiFileByteArray[MidiFileByteArrayIndex] = (byte)0x64;
                // MidiFileByteArrayIndex++;
                // MidiFileByteArraySize++;
                // TrackChunkLength++;
                //
                //
                // // NoteOff Message
                // // 18 80 42 40
                //
                // NoteOffMessageByteArray = new byte[]
                // {
                //  (byte)0x18, (byte)0x80, (byte)0x42, (byte)0x40
                // };
                //
                // MidiFileByteArray[MidiFileByteArrayIndex] = (byte)0x18;
                // MidiFileByteArrayIndex++;
                // MidiFileByteArraySize++;
                // TrackChunkLength++;
                // MidiFileByteArray[MidiFileByteArrayIndex] = (byte)0x80;
                // MidiFileByteArrayIndex++;
                // MidiFileByteArraySize++;
                // TrackChunkLength++;
                // MidiFileByteArray[MidiFileByteArrayIndex] = (byte)0x42;
                // MidiFileByteArrayIndex++;
                // MidiFileByteArraySize++;
                // TrackChunkLength++;
                // MidiFileByteArray[MidiFileByteArrayIndex] = (byte)0x40;
                // MidiFileByteArrayIndex++;
                // MidiFileByteArraySize++;
                // TrackChunkLength++;




                // note filters
                //   range (  0 - 127) - ( i.e. 1,2,3,4,5,6,7 ) control which modes of the scale get selected in a track
                //   range (128 - 255) - ( i.e. 128,129,130,131,132,133,134,135,136,137,138,139)
                //                       specify specific note values to use within an octave, but the
                //                       octave filter will still be used to select which octave to use
                //   range (256 - 383) - specify EXACT note values to use, the octave filter is not used
                //
                // beat filters control what durations are used when notes are being generated
                //
                //   if the BeatFilter   contains a single 0
                //     then this ChartMidiSpecification defines a metronome track with the following:
                //
                //       ChannelNumber  - the midi channel to output the metronome on
                //       NoteFilter     - this should be two mode numbers
                //                          the first one describes the mode to use for the first beat
                //                          and the second one describes the mode to use for all other beats
                //       OctaveFilter   - the octave to use for calculating the note number
                //       VelocityFilter - this should be two mode numbers
                //                          the first one describes the velocity to use for the first beat
                //                          and the second one describes the velocity to use for all other beats
                //
                // rest filters control which durations are used when rests are being generated
                //
                //   if the RestFilter   contains a single P
                //     then this ChartMidiSpecification defines a pattern to use to fill the track with the following:
                //       BeatFilter     - defines the pattern i.e.  <BeatFilter>-1,1,-2,2,-3,3</BeatFilter>
                //                          positive numbers represent note durations in 1/4s of a beat
                //                          negative numbers represent rest durations in 1/4s of a beat
                //       ChannelNumber  - the midi channel to output the metronome on
                //       NoteFilter     - works the same way as normal
                //       OctaveFilter   - the octave to use for calculating the note number
                //       VelocityFilter - works the same way as normal
                //
                // octave filters control which octaves get selected in a track
                //
                // velocity filters control the velocity values that get used for note on messages
                //   that are being generated
                //





                NoteFilterValueString       = ChartNoteFilterStringArray[CurrentChartIndex][intChartMidiSpecificationIndex]    ;
                c2_Logger.info("crkodrt2:main:NoteFilterValueString:" + NoteFilterValueString + " = ChartNoteFilterStringArray[" + CurrentChartIndex + "][" + intChartMidiSpecificationIndex + "]");
                BeatFilterValueString       = ChartBeatFilterStringArray[CurrentChartIndex][intChartMidiSpecificationIndex]    ;
                RestFilterValueString       = ChartRestFilterStringArray[CurrentChartIndex][intChartMidiSpecificationIndex]    ;
                OctaveFilterValueString     = ChartOctaveFilterStringArray[CurrentChartIndex][intChartMidiSpecificationIndex]  ;
                VelocityFilterValueString   = ChartVelocityFilterStringArray[CurrentChartIndex][intChartMidiSpecificationIndex];
                GlobalMidiSpecificationValueString       = ChartGlobalMidiSpecificationArray[CurrentChartIndex][intChartMidiSpecificationIndex]    ;

                if(NoteFilterValueString.contains(":"))
                {
                  NoteFilterValueColonSplitStringArray      = NoteFilterValueString.split(":");
                  NoteFilterValueSplitStringArray      = NoteFilterValueColonSplitStringArray[0].split(",");
                  NoteFilterSimultaneousNotesValueSplitStringArray      = NoteFilterValueColonSplitStringArray[1].split(",");
                  NoteFilterSimultaneousNotesValueSplitStringArraySize = java.lang.reflect.Array.getLength(NoteFilterSimultaneousNotesValueSplitStringArray);
                }
                else
                {
                  NoteFilterValueSplitStringArray      = NoteFilterValueString.split(",");
                  NoteFilterSimultaneousNotesValueSplitStringArray[0] = "1";
                  NoteFilterSimultaneousNotesValueSplitStringArraySize = 1;
                }

                BeatFilterValueSplitStringArray      = BeatFilterValueString.split(",");
                RestFilterValueSplitStringArray      = RestFilterValueString.split(",");
                OctaveFilterValueSplitStringArray    = OctaveFilterValueString.split(",");
                VelocityFilterValueSplitStringArray  = VelocityFilterValueString.split(",");

                NoteFilterValueSplitStringArraySize        = java.lang.reflect.Array.getLength(NoteFilterValueSplitStringArray);
                BeatFilterValueSplitStringArraySize        = java.lang.reflect.Array.getLength(BeatFilterValueSplitStringArray);
                RestFilterValueSplitStringArraySize        = java.lang.reflect.Array.getLength(RestFilterValueSplitStringArray);
                OctaveFilterValueSplitStringArraySize      = java.lang.reflect.Array.getLength(OctaveFilterValueSplitStringArray);
                VelocityFilterValueSplitStringArraySize    = java.lang.reflect.Array.getLength(VelocityFilterValueSplitStringArray);

                // compute each possible note as a note,octave combination

                NoteOctaveCombinationStringArrayIndex = 0;
                for(
                    NoteFilterValueSplitStringArrayIndex = 0;
                    NoteFilterValueSplitStringArrayIndex < NoteFilterValueSplitStringArraySize;
                    NoteFilterValueSplitStringArrayIndex++
                   )
                {
                  for(
                      OctaveFilterValueSplitStringArrayIndex = 0;
                      OctaveFilterValueSplitStringArrayIndex < OctaveFilterValueSplitStringArraySize;
                      OctaveFilterValueSplitStringArrayIndex++
                     )
                  {
                    c2_Logger.info("crkodrt2:main:NoteOctaveCombinationStringArray[" + NoteOctaveCombinationStringArrayIndex + "] = " + NoteFilterValueSplitStringArray[NoteFilterValueSplitStringArrayIndex] + "," + OctaveFilterValueSplitStringArray[OctaveFilterValueSplitStringArrayIndex]);
                    NoteOctaveCombinationStringArray[NoteOctaveCombinationStringArrayIndex] = NoteFilterValueSplitStringArray[NoteFilterValueSplitStringArrayIndex] + "," + OctaveFilterValueSplitStringArray[OctaveFilterValueSplitStringArrayIndex];
                    NoteOctaveCombinationStringArrayIndex++;
                  }
                }

                TotalPossibleChordsStringArrayIndex = 0;

                // loop through each simultaneous notes value called for

                for(
                    NoteFilterSimultaneousNotesValueSplitStringArrayIndex = 0;
                    NoteFilterSimultaneousNotesValueSplitStringArrayIndex < NoteFilterSimultaneousNotesValueSplitStringArraySize;
                    NoteFilterSimultaneousNotesValueSplitStringArrayIndex++
                   )
                {

                  // get the current simultaneous notes value

                  NoteFilterSimultaneousNotesValue = Integer.parseInt(NoteFilterSimultaneousNotesValueSplitStringArray[NoteFilterSimultaneousNotesValueSplitStringArrayIndex]);

                  // the formula is:   nCr = n! / (r! * (n - r)!)

                  // initialize the CombinationGeneratorIndexes so that we can
                  // march through the NoteOctaveCombinationStringArray and
                  // generate all of the possible combinations that exist
                  // using the current number of simultaneous notes

                  for(CombinationGeneratorIndexArrayIndex = (NoteFilterSimultaneousNotesValue - 1);CombinationGeneratorIndexArrayIndex >= 0;CombinationGeneratorIndexArrayIndex--)
                  {
                    CombinationGeneratorIndexArray[CombinationGeneratorIndexArrayIndex] = ((NoteOctaveCombinationStringArrayIndex - NoteFilterSimultaneousNotesValue) + CombinationGeneratorIndexArrayIndex);
                  }

                  // now we iterate through the combinations backwards
                  // until the first CombinationGeneratorIndex is forced to be below zero

                  while(CombinationGeneratorIndexArray[0] >= 0)
                  {

                    // loop a number of times equal to the current simultaneous notes value
                    // and build a string that describes the current combination

                    PossibleChordString = "";
                    for(CombinationGeneratorIndexArrayIndex = 0;CombinationGeneratorIndexArrayIndex < NoteFilterSimultaneousNotesValue;CombinationGeneratorIndexArrayIndex++)
                    {
                      if(CombinationGeneratorIndexArrayIndex > 0)
                      {
                        PossibleChordString = PossibleChordString + ":";
                      }
                      PossibleChordString = PossibleChordString + NoteOctaveCombinationStringArray[CombinationGeneratorIndexArray[CombinationGeneratorIndexArrayIndex]];
                    }

                    // store the current combination that we just generated
                    // so that it can easily be retrieved later on when we
                    // generate the track

                    c2_Logger.info("crkodrt2:main:TotalPossibleChordsStringArray[" + TotalPossibleChordsStringArrayIndex + "] = " + PossibleChordString);
                    TotalPossibleChordsStringArray[TotalPossibleChordsStringArrayIndex] = PossibleChordString;
                    TotalPossibleChordsStringArrayIndex++;

                    // now we have to adjust the indexes

                    CombinationGeneratorIndexArrayIndex = 0;
                    IndexesAdjustedFlag = false;
                    while(
                          (CombinationGeneratorIndexArrayIndex < NoteFilterSimultaneousNotesValue) &&
                          ( ! IndexesAdjustedFlag )
                         )
                    {
                      CombinationGeneratorIndexArray[CombinationGeneratorIndexArrayIndex]--;
                      if(CombinationGeneratorIndexArray[CombinationGeneratorIndexArrayIndex] >= CombinationGeneratorIndexArrayIndex)
                      {
                        IndexesAdjustedFlag = true;
                        CombinationGeneratorIndexArraySecondaryIndex = CombinationGeneratorIndexArrayIndex - 1;
                        while(CombinationGeneratorIndexArraySecondaryIndex >= 0)
                        {
                          CombinationGeneratorIndexArray[CombinationGeneratorIndexArraySecondaryIndex] = (CombinationGeneratorIndexArray[(CombinationGeneratorIndexArraySecondaryIndex + 1)] - 1);
                          CombinationGeneratorIndexArraySecondaryIndex--;
                        }
                      }
                      CombinationGeneratorIndexArrayIndex++;
                    }
                  }
                }

                // save the size of the chord combination array that we just generated

                TotalPossibleChordsStringArraySize = TotalPossibleChordsStringArrayIndex;

                ChartMidiChannelArrayList = (ArrayList)ChartMidiChannelArrayListOfArrayLists.get(CurrentChartIndex);
                Object TempObject = ChartMidiChannelArrayList.get(intChartMidiSpecificationIndex);
                Class TempClass = TempObject.getClass();
                c2_Logger.info("crkodrt2:main:TempObject:" + TempClass.toString());
                MidiChannel = (int)ChartMidiChannelArrayList.get(intChartMidiSpecificationIndex);
                c2_Logger.info("crkodrt2:main:MidiChannel:" + MidiChannel);

                CurrentSequenceTimeLeft = FullSequenceDuration;
                CurrentSequenceAdjustedTimePointer = 0;
                CurrentSequenceRealTimePointer = 0;
                TrackCompletedFlag = false;
                NumberOfEventsInTrack = 0;

                // if this is a metronome track

                if(BeatFilterValueSplitStringArray[0].compareTo("0") == 0)
                {
                  KeyOffset = ChartModeArray[CurrentChartIndex][5];
                  c2_Logger.info("crkodrt2:main:KeyOffset:" + KeyOffset);

                  RandomOctaveNumber = Integer.parseInt(OctaveFilterValueSplitStringArray[0]);

                  BeatDuration = QuarterOfABeatDuration * 4;
                  NoteDurationDouble = QuarterOfABeatDuration;
                  BeatNumber = 0;
                  CurrentNumberOfMidiTicks = 0;
                  for(
                      CurrentSequenceRealTimePointer = 0;
                      CurrentSequenceRealTimePointer < FullSequenceDuration;
                      CurrentSequenceRealTimePointer += BeatDuration
                     )
                  {

                    if(BeatNumber == 0)
                    {
                      RandomModeNumber = Integer.parseInt(NoteFilterValueSplitStringArray[0]);
                      c2_Logger.info("crkodrt2:main:RandomModeNumber:" + RandomModeNumber);
                      ChromaticIndex = ChromaticIndexArray[CurrentChartIndex][RandomModeNumber];
                      c2_Logger.info("crkodrt2:main:ChromaticIndex:" + ChromaticIndex);
                      if(ChromaticIndex < 0)
                      {
                        ChromaticOrIndexArrayStartingIndex = ((CurrentChartIndex - 1) * 52) + ((RandomModeNumber  - 1) * 4);
                        RandomChromaticOrIndexArrayIndex = ChromaticOrIndexArrayStartingIndex + (int)Math.round(Math.random() * (java.lang.Math.abs(ChromaticIndex) - 1));
                        RandomChromaticIndex = ChromaticOrIndexArray[RandomChromaticOrIndexArrayIndex];
                        RandomNoteNumber = (RandomOctaveNumber * 12) + KeyOffset + RandomChromaticIndex;
                      }
                      else
                      {
                        RandomNoteNumber = (RandomOctaveNumber * 12) + KeyOffset + ChromaticIndex;
                      }
                      RandomVelocityNumber = Integer.parseInt(VelocityFilterValueSplitStringArray[0]);
                    }
                    else
                    {
                      RandomModeNumber = Integer.parseInt(NoteFilterValueSplitStringArray[1]);
                      c2_Logger.info("crkodrt2:main:RandomModeNumber:" + RandomModeNumber);
                      ChromaticIndex = ChromaticIndexArray[CurrentChartIndex][RandomModeNumber];
                      c2_Logger.info("crkodrt2:main:ChromaticIndex:" + ChromaticIndex);
                      if(ChromaticIndex < 0)
                      {
                        ChromaticOrIndexArrayStartingIndex = ((CurrentChartIndex - 1) * 52) + ((RandomModeNumber  - 1) * 4);
                        RandomChromaticOrIndexArrayIndex = ChromaticOrIndexArrayStartingIndex + (int)Math.round(Math.random() * (java.lang.Math.abs(ChromaticIndex) - 1));
                        RandomChromaticIndex = ChromaticOrIndexArray[RandomChromaticOrIndexArrayIndex];
                        RandomNoteNumber = (RandomOctaveNumber * 12) + KeyOffset + RandomChromaticIndex;
                      }
                      else
                      {
                        RandomNoteNumber = (RandomOctaveNumber * 12) + KeyOffset + ChromaticIndex;
                      }
                      RandomVelocityNumber = Integer.parseInt(VelocityFilterValueSplitStringArray[1]);
                    }
                    if(ChromaticIndex != -1)
                    {


                      CurrentShortMessage = new ShortMessage();
                      CurrentShortMessage.setMessage(ShortMessage.NOTE_ON, (MidiChannel - 1), RandomNoteNumber, RandomVelocityNumber);
                      MidiShortMessageArrayListByMillisecondHashMapKey = String.format("%d",(int)CurrentSequenceRealTimePointer);
                      if(MidiShortMessageArrayListByMillisecondHashMap.containsKey(MidiShortMessageArrayListByMillisecondHashMapKey))
                      {
                        MidiShortMessageArrayList = (ArrayList)MidiShortMessageArrayListByMillisecondHashMap.get(MidiShortMessageArrayListByMillisecondHashMapKey);
                      }
                      else
                      {
                        MidiShortMessageArrayList = new ArrayList();
                      }
                      MidiShortMessageArrayList.add(CurrentShortMessage);
                      MidiShortMessageArrayListByMillisecondHashMap.put(MidiShortMessageArrayListByMillisecondHashMapKey, MidiShortMessageArrayList);

                      // // add a NoteOn Message to the MidiFile
                      //
                      // MidiFileByteArray[MidiFileByteArrayIndex] = (byte)Math.round(CurrentNumberOfMidiTicks);
                      // MidiFileByteArrayIndex++;
                      // MidiFileByteArraySize++;
                      // TrackChunkLength++;
                      // MidiFileByteArray[MidiFileByteArrayIndex] = (byte)0x90;
                      // MidiFileByteArrayIndex++;
                      // MidiFileByteArraySize++;
                      // TrackChunkLength++;
                      // MidiFileByteArray[MidiFileByteArrayIndex] = (byte)RandomNoteNumber;
                      // MidiFileByteArrayIndex++;
                      // MidiFileByteArraySize++;
                      // TrackChunkLength++;
                      // MidiFileByteArray[MidiFileByteArrayIndex] = (byte)RandomVelocityNumber;
                      // MidiFileByteArrayIndex++;
                      // MidiFileByteArraySize++;
                      // TrackChunkLength++;
                      //
                      // // compute the number of MidiTicks necessary to get to the NoteOff Message
                      //
                      // CurrentNumberOfMidiTicks = (NoteDurationDouble / MidiTickDuration);
                      // c2_Logger.info("crkodrt2:main:CurrentNumberOfMidiTicks:" + CurrentNumberOfMidiTicks);

                      CurrentShortMessage = new ShortMessage();
                      CurrentShortMessage.setMessage(ShortMessage.NOTE_OFF, (MidiChannel - 1), RandomNoteNumber, 0);
                      MidiShortMessageArrayListByMillisecondHashMapKey = String.format("%d",(int)(CurrentSequenceRealTimePointer + NoteDurationDouble));
                      if(MidiShortMessageArrayListByMillisecondHashMap.containsKey(MidiShortMessageArrayListByMillisecondHashMapKey))
                      {
                        MidiShortMessageArrayList = (ArrayList)MidiShortMessageArrayListByMillisecondHashMap.get(MidiShortMessageArrayListByMillisecondHashMapKey);
                      }
                      else
                      {
                        MidiShortMessageArrayList = new ArrayList();
                      }
                      MidiShortMessageArrayList.add(CurrentShortMessage);
                      MidiShortMessageArrayListByMillisecondHashMap.put(MidiShortMessageArrayListByMillisecondHashMapKey, MidiShortMessageArrayList);

                      // // add a NoteOff Message to the MidiFile
                      //
                      // MidiFileByteArray[MidiFileByteArrayIndex] = (byte)Math.round(CurrentNumberOfMidiTicks);
                      // MidiFileByteArrayIndex++;
                      // MidiFileByteArraySize++;
                      // TrackChunkLength++;
                      // MidiFileByteArray[MidiFileByteArrayIndex] = (byte)0x80;
                      // MidiFileByteArrayIndex++;
                      // MidiFileByteArraySize++;
                      // TrackChunkLength++;
                      // MidiFileByteArray[MidiFileByteArrayIndex] = (byte)RandomNoteNumber;
                      // MidiFileByteArrayIndex++;
                      // MidiFileByteArraySize++;
                      // TrackChunkLength++;
                      // MidiFileByteArray[MidiFileByteArrayIndex] = (byte)0x40;
                      // MidiFileByteArrayIndex++;
                      // MidiFileByteArraySize++;
                      // TrackChunkLength++;
                      //
                      // // compute the number of MidiTicks necessary to get to the next NoteOn Message
                      //
                      // CurrentNumberOfMidiTicks = ((BeatDuration - NoteDurationDouble) / MidiTickDuration);
                      // c2_Logger.info("crkodrt2:main:CurrentNumberOfMidiTicks:" + CurrentNumberOfMidiTicks);



                    }
                    else
                    {
                      c2_Logger.info("crkodrt2:main:skipping ChromaticIndex = -1!");
                    }

                    BeatNumber++;
                    if(BeatNumber >= GlobalNumberOfBeatsInAMeasure)
                    {
                      BeatNumber = 0;
                    }
                  }

                }

                // if this is NOT a metronome track

                else
                {

                  // if this is a pattern track

                  if(RestFilterValueSplitStringArray[0].compareTo("P") == 0)
                  {

                    BeatFilterValueSplitStringArrayIndex = 0;
                    while( ! TrackCompletedFlag )
                    {
                      CurrentBeatFilterValue = Integer.parseInt(BeatFilterValueSplitStringArray[BeatFilterValueSplitStringArrayIndex]);
                      if(CurrentBeatFilterValue < 0)
                      {
                        NoteDurationDouble = 0;
                        NoteDurationInt = 0;
                        RestDurationDouble = -(CurrentBeatFilterValue * QuarterOfABeatDuration);
                        RestDurationInt = (int)Math.floor(RestDurationDouble);

                      }
                      else
                      {
                        NoteDurationDouble = CurrentBeatFilterValue * QuarterOfABeatDuration;
                        NoteDurationInt = (int)Math.floor(NoteDurationDouble);
                        RestDurationDouble = 0;
                        RestDurationInt = 0;

                      }
                      if((NoteDurationDouble + QuarterOfABeatDuration) > CurrentSequenceTimeLeft)
                      {

                        NoteDurationDouble = 0;
                        RestDurationDouble = CurrentSequenceTimeLeft;
                        CurrentBeatFilterValue = 0;
                        TrackCompletedFlag = true;

                      }
                      if(RestDurationDouble > CurrentSequenceTimeLeft)
                      {

                        RestDurationDouble = CurrentSequenceTimeLeft;
                        TrackCompletedFlag = true;

                      }
                      if(CurrentBeatFilterValue > 0)
                      {
                        KeyOffset = ChartModeArray[CurrentChartIndex][5];
                        c2_Logger.info("crkodrt2:main:KeyOffset:" + KeyOffset);

                        RandomOctaveFilterIndex = (int)Math.round(Math.random() * (OctaveFilterValueSplitStringArraySize - 1));
                        RandomOctaveNumber = Integer.parseInt(OctaveFilterValueSplitStringArray[RandomOctaveFilterIndex]);

                        RandomNoteFilterIndex = (int)Math.round(Math.random() * (NoteFilterValueSplitStringArraySize - 1));
                        c2_Logger.info("crkodrt2:main:RandomNoteFilterIndex:" + RandomNoteFilterIndex);

                        RandomModeNumber = Integer.parseInt(NoteFilterValueSplitStringArray[RandomNoteFilterIndex]);
                        c2_Logger.info("crkodrt2:main:RandomModeNumber:" + RandomModeNumber);

                        RandomModeNumberRange = RandomModeNumber / 100;
                        RandomModeNumberRemainder = RandomModeNumber % 100;

                        ChromaticIndex = -1;
                        switch(RandomModeNumberRange)
                        {
                          // in this range, the note filter value represents a mode number
                          case 0:
                          {

                            ChromaticIndex = ChromaticIndexArray[CurrentChartIndex][RandomModeNumber];
                            c2_Logger.info("crkodrt2:main:ChromaticIndex:" + ChromaticIndex);
                            if(ChromaticIndex < 0)
                            {
                              ChromaticOrIndexArrayStartingIndex = ((CurrentChartIndex - 1) * 52) + ((RandomModeNumber  - 1) * 4);
                              RandomChromaticOrIndexArrayIndex = ChromaticOrIndexArrayStartingIndex + (int)Math.round(Math.random() * (java.lang.Math.abs(ChromaticIndex) - 1));
                              RandomChromaticIndex = ChromaticOrIndexArray[RandomChromaticOrIndexArrayIndex];
                              RandomNoteNumber = (RandomOctaveNumber * 12) + KeyOffset + RandomChromaticIndex;
                            }
                            else
                            {
                              RandomNoteNumber = (RandomOctaveNumber * 12) + KeyOffset + ChromaticIndex;
                            }
                            c2_Logger.info("crkodrt2:main:RandomNoteNumber:" + RandomNoteNumber);
                            break;
                          }
                          // in this range, the note filter value represents a specific note, but not a specific octave
                          case 1:
                          {

                            RandomNoteNumber = (RandomOctaveNumber * 12) + RandomModeNumberRemainder;
                            c2_Logger.info("crkodrt2:main:RandomNoteNumber:" + RandomNoteNumber);
                            ChromaticIndex = 0;
                            break;
                          }
                          // in this range, the note filter value represents a specific note in a specific octave
                          case 2:
                          {

                            RandomNoteNumber = RandomModeNumberRemainder;
                            c2_Logger.info("crkodrt2:main:RandomNoteNumber:" + RandomNoteNumber);
                            ChromaticIndex = 0;
                            break;
                          }
                          default:
                          {
                            c2_Logger.error("crkodrt2:main:ERROR:unusable:RandomModeNumberRange:" + RandomModeNumberRange);
                            break;
                          }

                        }

                        if(ChromaticIndex != -1)
                        {
                          RandomVelocityFilterIndex = (int)Math.round(Math.random() * (VelocityFilterValueSplitStringArraySize - 1));
                          RandomVelocityNumber = Integer.parseInt(VelocityFilterValueSplitStringArray[RandomVelocityFilterIndex]);

                          CurrentShortMessage = new ShortMessage();
                          CurrentShortMessage.setMessage(ShortMessage.NOTE_ON, (MidiChannel - 1), RandomNoteNumber, RandomVelocityNumber);
                          MidiShortMessageArrayListByMillisecondHashMapKey = String.format("%d",(int)CurrentSequenceRealTimePointer);
                          if(MidiShortMessageArrayListByMillisecondHashMap.containsKey(MidiShortMessageArrayListByMillisecondHashMapKey))
                          {
                            MidiShortMessageArrayList = (ArrayList)MidiShortMessageArrayListByMillisecondHashMap.get(MidiShortMessageArrayListByMillisecondHashMapKey);
                          }
                          else
                          {
                            MidiShortMessageArrayList = new ArrayList();
                          }
                          MidiShortMessageArrayList.add(CurrentShortMessage);
                          MidiShortMessageArrayListByMillisecondHashMap.put(MidiShortMessageArrayListByMillisecondHashMapKey, MidiShortMessageArrayList);

                          CurrentShortMessage = new ShortMessage();
                          CurrentShortMessage.setMessage(ShortMessage.NOTE_OFF, (MidiChannel - 1), RandomNoteNumber, 0);
                          MidiShortMessageArrayListByMillisecondHashMapKey = String.format("%d",(int)(CurrentSequenceRealTimePointer + NoteDurationDouble));
                          if(MidiShortMessageArrayListByMillisecondHashMap.containsKey(MidiShortMessageArrayListByMillisecondHashMapKey))
                          {
                            MidiShortMessageArrayList = (ArrayList)MidiShortMessageArrayListByMillisecondHashMap.get(MidiShortMessageArrayListByMillisecondHashMapKey);
                          }
                          else
                          {
                            MidiShortMessageArrayList = new ArrayList();
                          }
                          MidiShortMessageArrayList.add(CurrentShortMessage);
                          MidiShortMessageArrayListByMillisecondHashMap.put(MidiShortMessageArrayListByMillisecondHashMapKey, MidiShortMessageArrayList);


                        }
                        else
                        {
                          c2_Logger.info("crkodrt2:main:skipping ChromaticIndex = -1!");
                        }


                        CurrentSequenceTimeLeft -= NoteDurationDouble;
                        CurrentSequenceAdjustedTimePointer += NoteDurationInt;
                        CurrentSequenceRealTimePointer += NoteDurationDouble;

                      }
                      else
                      {
                        CurrentSequenceTimeLeft -= RestDurationDouble;
                        CurrentSequenceAdjustedTimePointer += RestDurationInt;
                        CurrentSequenceRealTimePointer += RestDurationDouble;

                      }

                      BeatFilterValueSplitStringArrayIndex++;
                      if(BeatFilterValueSplitStringArrayIndex >= BeatFilterValueSplitStringArraySize)
                      {
                        BeatFilterValueSplitStringArrayIndex = 0;
                      }

                    }

                  }

                  // if this is NOT a pattern track

                  else
                  {

                    while( ! TrackCompletedFlag )
                    {




                      KeyOffset = ChartModeArray[CurrentChartIndex][5];
                      c2_Logger.info("crkodrt2:main:KeyOffset:" + KeyOffset);

                      RandomVelocityFilterIndex = (int)Math.round(Math.random() * (VelocityFilterValueSplitStringArraySize - 1));
                      RandomVelocityNumber = Integer.parseInt(VelocityFilterValueSplitStringArray[RandomVelocityFilterIndex]);

                      RandomBeatFilterIndex = (int)Math.round(Math.random() * (BeatFilterValueSplitStringArraySize - 1));
                      RandomNumberOfQuarterBeatsNumber = Integer.parseInt(BeatFilterValueSplitStringArray[RandomBeatFilterIndex]);
                      NoteDurationDouble = RandomNumberOfQuarterBeatsNumber * QuarterOfABeatDuration;
                      NoteDurationInt = (int)Math.floor(NoteDurationDouble);


                      RandomRestFilterIndex = (int)Math.round(Math.random() * (RestFilterValueSplitStringArraySize - 1));
                      RandomNumberOfQuarterBeatsNumber = Integer.parseInt(RestFilterValueSplitStringArray[RandomRestFilterIndex]);
                      RestDurationDouble = RandomNumberOfQuarterBeatsNumber * QuarterOfABeatDuration;
                      RestDurationInt = (int)Math.floor(RestDurationDouble);

                      RandomNoteFilterSimultaneousNotesIndex = (int)Math.round(Math.random() * (NoteFilterSimultaneousNotesValueSplitStringArraySize - 1));
                      RandomNumberOfSimultaneousNotes = Integer.parseInt(NoteFilterSimultaneousNotesValueSplitStringArray[RandomNoteFilterSimultaneousNotesIndex]);

                      if(RandomNumberOfSimultaneousNotes > NoteFilterValueSplitStringArraySize)
                      {
                        RandomNumberOfSimultaneousNotes = NoteFilterValueSplitStringArraySize;
                      }
                      if(RandomNumberOfSimultaneousNotes < NoteFilterValueSplitStringArraySize)
                      {
                        StartingRandomNoteFilterIndex = (int)Math.round(Math.random() * (NoteFilterValueSplitStringArraySize - RandomNumberOfSimultaneousNotes));
                      }
                      else
                      {
                        StartingRandomNoteFilterIndex = 0;
                      }

                      c2_Logger.info("crkodrt2:main:RandomNoteFilterSimultaneousNotesIndex:" + RandomNoteFilterSimultaneousNotesIndex);
                      c2_Logger.info("crkodrt2:main:RandomNumberOfSimultaneousNotes:" + RandomNumberOfSimultaneousNotes);
                      c2_Logger.info("crkodrt2:main:StartingRandomNoteFilterIndex:" + StartingRandomNoteFilterIndex);

                      TempMidiOnShortMessageArrayList.clear();
                      TempMidiOffShortMessageArrayList.clear();

                      // randomly select a chord combination from the set that we previously generated

                      TotalPossibleChordsStringArrayIndex = (int)Math.round(Math.random() * (TotalPossibleChordsStringArraySize - 1));
                      RandomChordCombinationString = TotalPossibleChordsStringArray[TotalPossibleChordsStringArrayIndex];

                      RandomChordCombinationSplitStringArray = RandomChordCombinationString.split(":");
                      RandomChordCombinationSplitStringArraySize = java.lang.reflect.Array.getLength(RandomChordCombinationSplitStringArray);

                      // loop through all of the notes to be generated in the combination

                      for(
                          RandomChordCombinationSplitStringArrayIndex = 0;
                          RandomChordCombinationSplitStringArrayIndex < RandomChordCombinationSplitStringArraySize;
                          RandomChordCombinationSplitStringArrayIndex++
                         )
                      {
                        CurrentRandomChordCombinationSplitString = RandomChordCombinationSplitStringArray[RandomChordCombinationSplitStringArrayIndex];
                        CurrentRandomChordCombinationSplitStringSplitStringArray = CurrentRandomChordCombinationSplitString.split(",");
                        RandomModeNumber = Integer.parseInt(CurrentRandomChordCombinationSplitStringSplitStringArray[0]);
                        RandomOctaveNumber = Integer.parseInt(CurrentRandomChordCombinationSplitStringSplitStringArray[1]);



                      // for(
                      //     RandomNoteFilterIndex = 0;
                      //     RandomNoteFilterIndex < RandomNumberOfSimultaneousNotes;
                      //     RandomNoteFilterIndex++
                      //    )
                      // {
                      //   RandomOctaveFilterIndex = (int)Math.round(Math.random() * (OctaveFilterValueSplitStringArraySize - 1));
                      //   RandomOctaveNumber = Integer.parseInt(OctaveFilterValueSplitStringArray[RandomOctaveFilterIndex]);
                      //
                      //   // RandomNoteFilterIndex = (int)Math.round(Math.random() * (NoteFilterValueSplitStringArraySize - 1));
                      //   c2_Logger.info("crkodrt2:main:RandomNoteFilterIndex:" + RandomNoteFilterIndex);
                      //
                      //   RandomModeNumber = Integer.parseInt(NoteFilterValueSplitStringArray[(RandomNoteFilterIndex + StartingRandomNoteFilterIndex)]);
                        c2_Logger.info("crkodrt2:main:RandomModeNumber:" + RandomModeNumber);
                      //
                        RandomModeNumberRange = RandomModeNumber / 100;
                        RandomModeNumberRemainder = RandomModeNumber % 100;


                        ChromaticIndex = -1;
                        switch(RandomModeNumberRange)
                        {
                          // in this range, the note filter value represents a mode number
                          case 0:
                          {

                            ChromaticIndex = ChromaticIndexArray[CurrentChartIndex][RandomModeNumber];
                            c2_Logger.info("crkodrt2:main:ChromaticIndex:" + ChromaticIndex);
                            if(ChromaticIndex < 0)
                            {
                              ChromaticOrIndexArrayStartingIndex = ((CurrentChartIndex - 1) * 52) + ((RandomModeNumber  - 1) * 4);
                              RandomChromaticOrIndexArrayIndex = ChromaticOrIndexArrayStartingIndex + (int)Math.round(Math.random() * (java.lang.Math.abs(ChromaticIndex) - 1));
                              RandomChromaticIndex = ChromaticOrIndexArray[RandomChromaticOrIndexArrayIndex];
                              RandomNoteNumber = (RandomOctaveNumber * 12) + KeyOffset + RandomChromaticIndex;
                            }
                            else
                            {
                              RandomNoteNumber = (RandomOctaveNumber * 12) + KeyOffset + ChromaticIndex;
                            }
                            c2_Logger.info("crkodrt2:main:RandomNoteNumber:" + RandomNoteNumber);
                            break;
                          }
                          // in this range, the note filter value represents a specific note, but not a specific octave
                          case 1:
                          {

                            RandomNoteNumber = (RandomOctaveNumber * 12) + RandomModeNumberRemainder;
                            c2_Logger.info("crkodrt2:main:RandomNoteNumber:" + RandomNoteNumber);
                            ChromaticIndex = 0;
                            break;
                          }
                          // in this range, the note filter value represents a specific note in a specific octave
                          case 2:
                          {

                            RandomNoteNumber = RandomModeNumberRemainder;
                            c2_Logger.info("crkodrt2:main:RandomNoteNumber:" + RandomNoteNumber);
                            ChromaticIndex = 0;
                            break;
                          }
                          default:
                          {
                            c2_Logger.error("crkodrt2:main:ERROR:unusable:RandomModeNumberRange:" + RandomModeNumberRange);
                            break;
                          }

                        }

                        if(ChromaticIndex != -1)
                        {

                          CurrentShortMessage = new ShortMessage();
                          CurrentShortMessage.setMessage(ShortMessage.NOTE_ON, (MidiChannel - 1), RandomNoteNumber, RandomVelocityNumber);
                          TempMidiOnShortMessageArrayList.add(CurrentShortMessage);
                          c2_Logger.info("crkodrt2:main:TempMidiOnShortMessageArrayList.add(ShortMessage.NOTE_ON, " + (MidiChannel - 1) + ", " + RandomNoteNumber + ", " + RandomVelocityNumber + ")");
                          CurrentShortMessage = new ShortMessage();
                          CurrentShortMessage.setMessage(ShortMessage.NOTE_OFF, (MidiChannel - 1), RandomNoteNumber, 0);
                          TempMidiOffShortMessageArrayList.add(CurrentShortMessage);
                          c2_Logger.info("crkodrt2:main:TempMidiOffShortMessageArrayList.add(ShortMessage.NOTE_OFF, " + (MidiChannel - 1) + ", " + RandomNoteNumber + ", 0)");

                        }
                        else
                        {
                          c2_Logger.info("crkodrt2:main:skipping ChromaticIndex = -1!");
                        }

                      }


                      if((NoteDurationDouble + RestDurationDouble) > CurrentSequenceTimeLeft)
                      {

                        if((NoteDurationDouble + QuarterOfABeatDuration) < CurrentSequenceTimeLeft)
                        {
                          NoteDurationDouble = CurrentSequenceTimeLeft;
                          // if(ChromaticIndex != -1)
                          // {

                          //   CurrentShortMessage = new ShortMessage();
                          //   CurrentShortMessage.setMessage(ShortMessage.NOTE_ON, (MidiChannel - 1), RandomNoteNumber, RandomVelocityNumber);

                            TempMidiOnShortMessageArrayListSize = TempMidiOnShortMessageArrayList.size();
                            for(
                                TempMidiOnShortMessageArrayListIndex = 0;
                                TempMidiOnShortMessageArrayListIndex < TempMidiOnShortMessageArrayListSize;
                                TempMidiOnShortMessageArrayListIndex++
                               )
                            {
                              CurrentShortMessage = (ShortMessage)TempMidiOnShortMessageArrayList.get(TempMidiOnShortMessageArrayListIndex);
                              MidiShortMessageArrayListByMillisecondHashMapKey = String.format("%d",(int)CurrentSequenceRealTimePointer);
                              if(MidiShortMessageArrayListByMillisecondHashMap.containsKey(MidiShortMessageArrayListByMillisecondHashMapKey))
                              {
                                MidiShortMessageArrayList = (ArrayList)MidiShortMessageArrayListByMillisecondHashMap.get(MidiShortMessageArrayListByMillisecondHashMapKey);
                              }
                              else
                              {
                                MidiShortMessageArrayList = new ArrayList();
                              }
                              MidiShortMessageArrayList.add(CurrentShortMessage);
                              c2_Logger.info("crkodrt2:main:MidiShortMessageArrayListByMillisecondHashMap.put(" + MidiShortMessageArrayListByMillisecondHashMapKey + ", MidiShortMessageArrayList)");
                              MidiShortMessageArrayListByMillisecondHashMap.put(MidiShortMessageArrayListByMillisecondHashMapKey, MidiShortMessageArrayList);

                            }
                          //   CurrentShortMessage = new ShortMessage();
                          //   CurrentShortMessage.setMessage(ShortMessage.NOTE_OFF, (MidiChannel - 1), RandomNoteNumber, 0);

                            TempMidiOffShortMessageArrayListSize = TempMidiOffShortMessageArrayList.size();
                            for(
                                TempMidiOffShortMessageArrayListIndex = 0;
                                TempMidiOffShortMessageArrayListIndex < TempMidiOffShortMessageArrayListSize;
                                TempMidiOffShortMessageArrayListIndex++
                               )
                            {
                              CurrentShortMessage = (ShortMessage)TempMidiOffShortMessageArrayList.get(TempMidiOffShortMessageArrayListIndex);
                              MidiShortMessageArrayListByMillisecondHashMapKey = String.format("%d",(int)(CurrentSequenceRealTimePointer + NoteDurationDouble));
                              if(MidiShortMessageArrayListByMillisecondHashMap.containsKey(MidiShortMessageArrayListByMillisecondHashMapKey))
                              {
                                MidiShortMessageArrayList = (ArrayList)MidiShortMessageArrayListByMillisecondHashMap.get(MidiShortMessageArrayListByMillisecondHashMapKey);
                              }
                              else
                              {
                                MidiShortMessageArrayList = new ArrayList();
                              }
                              MidiShortMessageArrayList.add(CurrentShortMessage);
                              c2_Logger.info("crkodrt2:main:MidiShortMessageArrayListByMillisecondHashMap.put(" + MidiShortMessageArrayListByMillisecondHashMapKey + ", MidiShortMessageArrayList)");
                              MidiShortMessageArrayListByMillisecondHashMap.put(MidiShortMessageArrayListByMillisecondHashMapKey, MidiShortMessageArrayList);
                            }



                          // }
                          // else
                          // {
                          //   c2_Logger.info("crkodrt2:main:skipping ChromaticIndex = -1!");
                          // }

                        }
                        CurrentSequenceTimeLeft = 0;
                        CurrentSequenceAdjustedTimePointer = FullSequenceDuration;
                        CurrentSequenceRealTimePointer = FullSequenceDuration;

                        TrackCompletedFlag = true;

                      }
                      else
                      {
                        // if(ChromaticIndex != -1)
                        // {

                          // CurrentShortMessage = new ShortMessage();
                          // CurrentShortMessage.setMessage(ShortMessage.NOTE_ON, (MidiChannel - 1), RandomNoteNumber, RandomVelocityNumber);
                            TempMidiOnShortMessageArrayListSize = TempMidiOnShortMessageArrayList.size();
                            for(
                                TempMidiOnShortMessageArrayListIndex = 0;
                                TempMidiOnShortMessageArrayListIndex < TempMidiOnShortMessageArrayListSize;
                                TempMidiOnShortMessageArrayListIndex++
                               )
                            {
                              CurrentShortMessage = (ShortMessage)TempMidiOnShortMessageArrayList.get(TempMidiOnShortMessageArrayListIndex);
                          MidiShortMessageArrayListByMillisecondHashMapKey = String.format("%d",(int)CurrentSequenceRealTimePointer);
                          if(MidiShortMessageArrayListByMillisecondHashMap.containsKey(MidiShortMessageArrayListByMillisecondHashMapKey))
                          {
                            MidiShortMessageArrayList = (ArrayList)MidiShortMessageArrayListByMillisecondHashMap.get(MidiShortMessageArrayListByMillisecondHashMapKey);
                          }
                          else
                          {
                            MidiShortMessageArrayList = new ArrayList();
                          }
                          MidiShortMessageArrayList.add(CurrentShortMessage);
                          c2_Logger.info("crkodrt2:main:MidiShortMessageArrayListByMillisecondHashMap.put(" + MidiShortMessageArrayListByMillisecondHashMapKey + ", MidiShortMessageArrayList)");
                          MidiShortMessageArrayListByMillisecondHashMap.put(MidiShortMessageArrayListByMillisecondHashMapKey, MidiShortMessageArrayList);
                            }

                          // CurrentShortMessage = new ShortMessage();
                          // CurrentShortMessage.setMessage(ShortMessage.NOTE_OFF, (MidiChannel - 1), RandomNoteNumber, 0);
                            TempMidiOffShortMessageArrayListSize = TempMidiOffShortMessageArrayList.size();
                            for(
                                TempMidiOffShortMessageArrayListIndex = 0;
                                TempMidiOffShortMessageArrayListIndex < TempMidiOffShortMessageArrayListSize;
                                TempMidiOffShortMessageArrayListIndex++
                               )
                            {
                              CurrentShortMessage = (ShortMessage)TempMidiOffShortMessageArrayList.get(TempMidiOffShortMessageArrayListIndex);
                          MidiShortMessageArrayListByMillisecondHashMapKey = String.format("%d",(int)(CurrentSequenceRealTimePointer + NoteDurationDouble));
                          if(MidiShortMessageArrayListByMillisecondHashMap.containsKey(MidiShortMessageArrayListByMillisecondHashMapKey))
                          {
                            MidiShortMessageArrayList = (ArrayList)MidiShortMessageArrayListByMillisecondHashMap.get(MidiShortMessageArrayListByMillisecondHashMapKey);
                          }
                          else
                          {
                            MidiShortMessageArrayList = new ArrayList();
                          }
                          MidiShortMessageArrayList.add(CurrentShortMessage);
                          c2_Logger.info("crkodrt2:main:MidiShortMessageArrayListByMillisecondHashMap.put(" + MidiShortMessageArrayListByMillisecondHashMapKey + ", MidiShortMessageArrayList)");
                          MidiShortMessageArrayListByMillisecondHashMap.put(MidiShortMessageArrayListByMillisecondHashMapKey, MidiShortMessageArrayList);
                            }


                        // }
                        // else
                        // {
                        //   c2_Logger.info("crkodrt2:main:skipping ChromaticIndex = -1!");
                        // }


                        CurrentSequenceTimeLeft -= (NoteDurationDouble + RestDurationDouble);
                        CurrentSequenceAdjustedTimePointer += (NoteDurationInt + RestDurationInt);
                        CurrentSequenceRealTimePointer += (NoteDurationDouble + RestDurationDouble);

                      }
                      c2_Logger.info("crkodrt2:main:RandomNoteNumber:" + RandomNoteNumber);

                      RandomNoteNumberArray[NumberOfEventsInTrack]     = RandomNoteNumber;
                      RandomVelocityNumberArray[NumberOfEventsInTrack] = RandomVelocityNumber;
                      NoteDurationIntArray[NumberOfEventsInTrack]      = NoteDurationInt;
                      RestDurationIntArray[NumberOfEventsInTrack]      = RestDurationInt;
                      NumberOfEventsInTrack++;





                    }
                  }
                }

                c2_Logger.info("crkodrt2:main:MidiTrackHashMapArrayList.set(" + CurrentChartIndex + ", MidiShortMessageArrayListByMillisecondHashMap)");
                MidiTrackHashMapArrayList.set(CurrentChartIndex, MidiShortMessageArrayListByMillisecondHashMap);

                if( ! MidiFileOutputStreamByMidiChannelHashMap.containsKey(MidiChannel) )
                {

                  // establish the MidiFileOutputStream for this midi channel
                  // and save it in the HashMap so that it only gets created once

                  ExtensionLocation = strPrintChartDataPathname.indexOf(".xml");
                  BasePathname = strPrintChartDataPathname.substring(0, ExtensionLocation);
                  MidiFilePathname = BasePathname + "_" + GlobalMidiSpecificationValueString + "_" + MidiChannel + ".mid";

                  c2_Logger.info("crkodrt2:main:MidiFileOutputStream = new FileOutputStream(" + MidiFilePathname + ")");
                  MidiFileOutputStream = new FileOutputStream(MidiFilePathname);

                  MidiFileOutputStreamByMidiChannelHashMap.put(MidiChannel, MidiFileOutputStream);

                }


              }





            }

            c2_Logger.info("crkodrt2:main:MidiTrackHashMapArrayListByMovementNameHashMap.put(" + CurrentMovementName + ", MidiTrackHashMapArrayList)");
            MidiTrackHashMapArrayListByMovementNameHashMap.put(CurrentMovementName, MidiTrackHashMapArrayList);

            c2_Logger.info("crkodrt2:main:ChartMidiChannelArrayListOfArrayListsByMovementNameHashMap.put(" + CurrentMovementName + ", ChartMidiChannelArrayListOfArrayLists)");
            ChartMidiChannelArrayListOfArrayListsByMovementNameHashMap.put(CurrentMovementName, ChartMidiChannelArrayListOfArrayLists);

            c2_Logger.info("crkodrt2:main:MidiChannelArraySizeArrayListByMovementNameHashMap.put(" + CurrentMovementName + ", MidiChannelArraySizeArrayList)");
            MidiChannelArraySizeArrayListByMovementNameHashMap.put(CurrentMovementName, MidiChannelArraySizeArrayList);
          }

        }

        // if the output is to go to midi files, then we signal it
        // by setting the DesiredReceiver to null

        if( MidiFileOutputFlag )
        {
          c2_Logger.info("crkodrt2:main:DesiredReceiver = null");
          DesiredReceiver = null;

        }
        else
        {

          // find the desired midi device

          MidiDevice.Info[] MidiDeviceInfoArray = MidiSystem.getMidiDeviceInfo();
          int MidiDeviceInfoArraySize = java.lang.reflect.Array.getLength(MidiDeviceInfoArray);
          c2_Logger.info("crkodrt2:main:MidiDeviceInfoArraySize:" + MidiDeviceInfoArraySize);
          MidiDevice.Info DesiredMidiDeviceInfo = null;
          for
          (
           int MidiDeviceInfoArrayIndex = 0;
           MidiDeviceInfoArrayIndex < MidiDeviceInfoArraySize;
           MidiDeviceInfoArrayIndex++
          )
          {
            MidiDevice.Info CurrentMidiDeviceInfo = MidiDeviceInfoArray[MidiDeviceInfoArrayIndex];
            String CurrentDescription = CurrentMidiDeviceInfo.getDescription();
            String CurrentName = CurrentMidiDeviceInfo.getName();
            String CurrentVendor = CurrentMidiDeviceInfo.getVendor();
            String CurrentVersion = CurrentMidiDeviceInfo.getVersion();
            c2_Logger.info("crkodrt2:main:MidiDeviceInfoArray[" +
                               MidiDeviceInfoArrayIndex +
                               "]" +
                               ":CurrentDescription:" +   CurrentDescription +
                               ":CurrentName:" +          CurrentName        +
                               ":CurrentVendor:" +        CurrentVendor      +
                               ":CurrentVersion:" +       CurrentVersion
                              );
            // if(CurrentName.compareTo("UA-4FX") == 0)
            c2_Logger.info("crkodrt2:main:if(CurrentName.compareTo(" + DesiredMidiDeviceInfoName + ") == 0):" + CurrentName);
            if(CurrentName.compareTo(DesiredMidiDeviceInfoName) == 0)
            {
              DesiredMidiDeviceInfo = CurrentMidiDeviceInfo;
            }
          }

          c2_Logger.info("crkodrt2:main:DesiredMidiDevice = MidiSystem.getMidiDevice(DesiredMidiDeviceInfo)");
          MidiDevice DesiredMidiDevice = MidiSystem.getMidiDevice(DesiredMidiDeviceInfo);
          c2_Logger.info("crkodrt2:main:DesiredMidiDevice.open()");
          DesiredMidiDevice.open();
          c2_Logger.info("crkodrt2:main:DesiredReceiver = DesiredMidiDevice.getReceiver()");
          DesiredReceiver = DesiredMidiDevice.getReceiver();

        }

        // create the Crkodrt2PlayMidiTrack thread


        c2_Logger.info("crkodrt2:main:tCrkodrt2PlayMidiTrackThread = new Crkodrt2PlayMidiTrackThread");
        c2_Logger.info("crkodrt2:main:                               (");
        c2_Logger.info("crkodrt2:main:                                NumberOfLoopsByMovementNameHashMap,");
        c2_Logger.info("crkodrt2:main:                                DesiredReceiver,");
        c2_Logger.info("crkodrt2:main:                                FullSequenceDurationByMovementNameHashMap,");
        c2_Logger.info("crkodrt2:main:                                CurrentChartIndexArrayListByMovementNameHashMap,");
        c2_Logger.info("crkodrt2:main:                                CurrentChartIndexArrayListSizeByMovementNameHashMap,");
        c2_Logger.info("crkodrt2:main:                                CurrentNumberOfSequencesByMovementNameHashMap,");
        c2_Logger.info("crkodrt2:main:                                " + intGlobalMidiSpecificationNodeListLength + ",");
        c2_Logger.info("crkodrt2:main:                                ChartMidiChannelArrayListOfArrayListsByMovementNameHashMap,");
        c2_Logger.info("crkodrt2:main:                                MidiChannelArraySizeArrayListByMovementNameHashMap,");
        c2_Logger.info("crkodrt2:main:                                MidiTrackHashMapArrayListByMovementNameHashMap,");
        c2_Logger.info("crkodrt2:main:                                MovementMapSplitStringArray,");
        c2_Logger.info("crkodrt2:main:                                " + intMovementMapSplitStringArrayLength + ",");
        c2_Logger.info("crkodrt2:main:                                SongSegmentDurationByMovementNameHashMap,");
        c2_Logger.info("crkodrt2:main:                                BeatsPerMinuteByMovementNameHashMap,");
        c2_Logger.info("crkodrt2:main:                                NumberOfSongRepeats,");
        c2_Logger.info("crkodrt2:main:                                MidiFileOutputStreamByMidiChannelHashMap");
        c2_Logger.info("crkodrt2:main:                               )");
        tCrkodrt2PlayMidiTrackThread = new Crkodrt2PlayMidiTrackThread
                                       (
                                        NumberOfLoopsByMovementNameHashMap,
                                        DesiredReceiver,
                                        FullSequenceDurationByMovementNameHashMap,
                                        CurrentChartIndexArrayListByMovementNameHashMap,
                                        CurrentChartIndexArrayListSizeByMovementNameHashMap,
                                        CurrentNumberOfSequencesByMovementNameHashMap,
                                        intGlobalMidiSpecificationNodeListLength,
                                        ChartMidiChannelArrayListOfArrayListsByMovementNameHashMap,
                                        MidiChannelArraySizeArrayListByMovementNameHashMap,
                                        MidiTrackHashMapArrayListByMovementNameHashMap,
                                        MovementMapSplitStringArray,
                                        intMovementMapSplitStringArrayLength,
                                        SongSegmentDurationByMovementNameHashMap,
                                        BeatsPerMinuteByMovementNameHashMap,
                                        NumberOfSongRepeats,
                                        MidiFileOutputStreamByMidiChannelHashMap
                                       );
        c2_Logger.info("crkodrt2:main:tCrkodrt2PlayMidiTrackThread.setName(\"Crkodrt2PlayMidiTrackThread\")");
        tCrkodrt2PlayMidiTrackThread.setName("Crkodrt2PlayMidiTrackThread");


        // start the Crkodrt2PlayMidiTrack thread

        c2_Logger.info("crkodrt2:main:tCrkodrt2PlayMidiTrackThread.start()");
        tCrkodrt2PlayMidiTrackThread.start();


        // wait for the Crkodrt2PlayMidiTrack thread to complete

        c2_Logger.info("crkodrt2:main:tCrkodrt2PlayMidiTrackThread.join(600000)");
        tCrkodrt2PlayMidiTrackThread.join(600000);



        System.exit(0);






















      }
      catch (Exception e)
      {
        c2_Logger.error("crkodrt2.main:c2_ERROR:" + e.getMessage());
        StackTraceElement[] steArray = e.getStackTrace();
        int steArraySize = java.lang.reflect.Array.getLength(steArray);
        for(int x = 0;x < NumberOfStackTraceElementsToOutput;x++)
        {
          if(x < steArraySize)
          {
            c2_Logger.error("crkodrt2.main:c2_ERROR:" + steArray[x].toString());
          }
        }
        System.exit(1);
      }

      // String media = "./audio";
      // if (CommandLineArguments.length > 0) {
      //     File file = new File(CommandLineArguments[0]);
      //     if (file == null && !file.isDirectory()) {
      //         c2_Logger.info("usage: java crkodrt2 audioDirectory");
      //     } else {
      //         media = CommandLineArguments[0];
      //     }
      // }

      final crkodrt2 crkodrt2Instance = new crkodrt2("./audio");
      JFrame crkodrt2JFrame = new JFrame("crkodrt2");
      crkodrt2JFrame.addWindowListener(new WindowAdapter() {
          public void windowClosing(WindowEvent e) {System.exit(0);}
          public void windowDeiconified(WindowEvent e) { crkodrt2Instance.open(); }
          public void windowIconified(WindowEvent e) { crkodrt2Instance.close(); }
      });
      crkodrt2JFrame.getContentPane().add("Center", crkodrt2Instance);
      crkodrt2JFrame.pack();
      Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
      crkodrt2JFrame.setLocation(d.width/2 - crkodrt2Instance.width/2, d.height/2 - crkodrt2Instance.height/2);
      crkodrt2JFrame.setSize(new Dimension(crkodrt2Instance.width, crkodrt2Instance.height));
      crkodrt2JFrame.setVisible(true);
    }






















  // function to load a file into a String
  // call with:
  //                 LFIS_LoadFileIntoStringFileAbsolutePathname = the absolute path where the file can be found
  // returns:
  //                 String containing the contents of the file

  public static String LoadFileIntoString(String LFIS_LoadFileIntoStringFileAbsolutePathname)
  {
    try
    {




      String LoadFileIntoStringReturnString;
      File LoadFileIntoStringFileFile;
      FileReader LoadFileIntoStringFileFileReader;
      BufferedReader LoadFileIntoStringFileBufferedReader;
      String TempString;

      // read in the file

      // MDM_Logger.info("CurrentDatabaseName:" + CurrentDatabaseName + ":ProcessIdString:" + ProcessIdString + ":LoadFileIntoString:LoadFileIntoStringFileReader = new File(" + LFIS_LoadFileIntoStringFileAbsolutePathname + ")");
      LoadFileIntoStringFileFile = new File(LFIS_LoadFileIntoStringFileAbsolutePathname);
      if( LoadFileIntoStringFileFile.exists() )
      {
        // MDM_Logger.info("CurrentDatabaseName:" + CurrentDatabaseName + ":ProcessIdString:" + ProcessIdString + ":LoadFileIntoString:LoadFileIntoStringFileReader = new FileReader(LoadFileIntoStringFileFile)");
        LoadFileIntoStringFileFileReader = new FileReader(LoadFileIntoStringFileFile);
        // MDM_Logger.info("CurrentDatabaseName:" + CurrentDatabaseName + ":ProcessIdString:" + ProcessIdString + ":LoadFileIntoString:LoadFileIntoStringFileBufferedReader = new BufferedReader[LoadFileIntoStringFileFileReader]");
        LoadFileIntoStringFileBufferedReader = new BufferedReader(LoadFileIntoStringFileFileReader);
        LoadFileIntoStringReturnString = "";
        TempString = LoadFileIntoStringFileBufferedReader.readLine();
        while(TempString != null)
        {
          LoadFileIntoStringReturnString = LoadFileIntoStringReturnString + TempString + "\n";
          TempString = LoadFileIntoStringFileBufferedReader.readLine();
        }
        LoadFileIntoStringFileBufferedReader.close();
        LoadFileIntoStringFileFileReader.close();
      }
      else
      {
        // MDM_Logger.warn("CurrentDatabaseName:" + CurrentDatabaseName + ":ProcessIdString:" + ProcessIdString + ":LoadFileIntoString:MDM_WARNING:" + LFIS_LoadFileIntoStringFileAbsolutePathname + ":DOES NOT EXIST!");
        LoadFileIntoStringReturnString = null;
      }
      return LoadFileIntoStringReturnString;

    }
    catch (Exception e)
    {
      c2_Logger.error("LoadFileIntoString:LFIS_ERROR:" + e.getMessage());
      StackTraceElement[] steArray = e.getStackTrace();
      int steArraySize = java.lang.reflect.Array.getLength(steArray);
      for(int x = 0;x < NumberOfStackTraceElementsToOutput;x++)
      {
        if(x < steArraySize)
        {
          c2_Logger.error("LoadFileIntoString:LFIS_ERROR:" + steArray[x].toString());
        }
      }
      return null;
    }
  }























  // this function starts at a given XML Element
  // it traverses the DOM searching for the first element matching the name given
  // and returns the data associated with that element
  // if the data child element does not exist, then it returns an empty string

  public static String FindAndReturnXmlDataAssociatedWithTag(Element eTopElementInstance, String strDesiredXmlTagString)
  {

    String strFARXDAWTNodeName;
    short shFARXDAWTNodeType;
    String strFARXDAWTNodeValue;

    try
    {
      nlGEBTNNodeList = eTopElementInstance.getElementsByTagName(strDesiredXmlTagString);
      strFARXDAWTNodeValue = "";
      if(nlGEBTNNodeList.getLength() > 0)
      {
        nGEBTNitem0NodeInstance = nlGEBTNNodeList.item(0);
        if(nGEBTNitem0NodeInstance.hasChildNodes())
        {
          nGEBTNitem0FirstChildNodeInstance = nGEBTNitem0NodeInstance.getFirstChild();
          strFARXDAWTNodeName = nGEBTNitem0FirstChildNodeInstance.getNodeName();
          shFARXDAWTNodeType = nGEBTNitem0FirstChildNodeInstance.getNodeType();
          strFARXDAWTNodeValue = nGEBTNitem0FirstChildNodeInstance.getNodeValue();
        }
      }
    }
    catch (Exception e)
    {
      c2_Logger.error("FindAndReturnXmlDataAssociatedWithTag:FARXDAWT_ERROR:" + e.getMessage());
      StackTraceElement[] steArray = e.getStackTrace();
      int steArraySize = java.lang.reflect.Array.getLength(steArray);
      for(int x = 0;x < NumberOfStackTraceElementsToOutput;x++)
      {
        if(x < steArraySize)
        {
          c2_Logger.error("FindAndReturnXmlDataAssociatedWithTag:FARXDAWT_ERROR:" + steArray[x].toString());
        }
      }
      return null;
    }

    return strFARXDAWTNodeValue;
  }






















  // this function starts at a given XML Element
  // it traverses the DOM and processes every XxxxMidiSpecification
  // and stores the results
  //
  // returns a HashMap that maps the XxxxMidiSpecifications processed to their corresponding midi channels

  public static HashMap RecurseFromCurrentElementAndProcessAllXxxxMidiSpecifications
                    (
                     Element eTopElementInstance,
                     String strMidiSpecificationTagNamePrefix,
                     int[] XxxxMidiChannelArray,
                     String[] XxxxNoteFilterStringArray,
                     String[] XxxxBeatFilterStringArray,
                     String[] XxxxRestFilterStringArray,
                     String[] XxxxOctaveFilterStringArray,
                     String[] XxxxVelocityFilterStringArray
                    )
  {

    int intNumberOfXxxxMidiSpecificationsProcessed = 0;
    int NumberOfMidiSpecificationsProcessed;
    String strMidiSpecificationTagName;
    NodeList nlXxxxMidiSpecificationNodeList;
    int intXxxxMidiSpecificationNodeListLength;
    Node nXxxxMidiSpecificationNodeInstance;
    NodeList nlXxxxMidiSpecificationChildNodeList;
    int intXxxxMidiSpecificationChildNodeListLength;
    Node nXxxxMidiSpecificationChildNodeInstance;
    NodeList nlXxxxMidiSpecification_XXChildNodeList;
    int intXxxxMidiSpecification_XXChildNodeListLength;
    Node nXxxxMidiSpecification_XXChildNodeInstance;
    HashMap XxxxArrayIndexByMidiChannelHashMap = new HashMap();




    try
    {


      // find all of the <XxxxMidiSpecification> nodes

      strMidiSpecificationTagName = strMidiSpecificationTagNamePrefix + "MidiSpecification";

      nlXxxxMidiSpecificationNodeList = eTopElementInstance.getElementsByTagName(strMidiSpecificationTagName);
      intXxxxMidiSpecificationNodeListLength = nlXxxxMidiSpecificationNodeList.getLength();
      c2_Logger.info("crkodrt2:RecurseFromCurrentElementAndProcessAllXxxxMidiSpecifications:intXxxxMidiSpecificationNodeListLength:" + intXxxxMidiSpecificationNodeListLength);
      intNumberOfXxxxMidiSpecificationsProcessed = intXxxxMidiSpecificationNodeListLength;

      // loop through all of the <XxxxMidiSpecification> nodes

      for (
           int intXxxxMidiSpecificationNodeListIndex = 0;
           intXxxxMidiSpecificationNodeListIndex < intXxxxMidiSpecificationNodeListLength;
           intXxxxMidiSpecificationNodeListIndex++
          )
      {

        // get the current XxxxMidiSpecification node

        nXxxxMidiSpecificationNodeInstance = nlXxxxMidiSpecificationNodeList.item(intXxxxMidiSpecificationNodeListIndex);

        // get the child nodes of this XxxxMidiSpecification node

        nlXxxxMidiSpecificationChildNodeList = nXxxxMidiSpecificationNodeInstance.getChildNodes();
        intXxxxMidiSpecificationChildNodeListLength = nlXxxxMidiSpecificationChildNodeList.getLength();

        // loop through the <XxxxMidiSpecification> child nodes

        for (
             int intXxxxMidiSpecificationChildNodeListIndex = 0;
             intXxxxMidiSpecificationChildNodeListIndex < intXxxxMidiSpecificationChildNodeListLength;
             intXxxxMidiSpecificationChildNodeListIndex++
            )
        {

          // get the current <XxxxMidiSpecification> child node

          nXxxxMidiSpecificationChildNodeInstance = nlXxxxMidiSpecificationChildNodeList.item(intXxxxMidiSpecificationChildNodeListIndex);
          strNodeName01 = nXxxxMidiSpecificationChildNodeInstance.getNodeName();
          shNodeType01 = nXxxxMidiSpecificationChildNodeInstance.getNodeType();
          strNodeValue01 = nXxxxMidiSpecificationChildNodeInstance.getNodeValue();

          // get the child nodes of this XxxxMidiSpecification child node

          nlXxxxMidiSpecification_XXChildNodeList = nXxxxMidiSpecificationChildNodeInstance.getChildNodes();
          intXxxxMidiSpecification_XXChildNodeListLength = nlXxxxMidiSpecification_XXChildNodeList.getLength();

          // loop through the child nodes of the <XxxxMidiSpecification> child node, should be only one TEXT node

          for (
               int intXxxxMidiSpecification_XXChildNodeListIndex = 0;
               intXxxxMidiSpecification_XXChildNodeListIndex < intXxxxMidiSpecification_XXChildNodeListLength;
               intXxxxMidiSpecification_XXChildNodeListIndex++
              )
          {

            // get the current child node

            nXxxxMidiSpecification_XXChildNodeInstance = nlXxxxMidiSpecification_XXChildNodeList.item(intXxxxMidiSpecification_XXChildNodeListIndex);
            strNodeName02 = nXxxxMidiSpecification_XXChildNodeInstance.getNodeName();
            shNodeType02 = nXxxxMidiSpecification_XXChildNodeInstance.getNodeType();
            strNodeValue02 = nXxxxMidiSpecification_XXChildNodeInstance.getNodeValue();

            // switch based on the NodeName of the parent node

            c2_Logger.info("crkodrt2:RecurseFromCurrentElementAndProcessAllXxxxMidiSpecifications:switch(" + strNodeName01 + ")");
            switch(strNodeName01)
            {

              case "SpecificationIndex":
              {
                SpecificationIndexString = strNodeValue02;
                SpecificationIndex = (Integer.parseInt(SpecificationIndexString) - 1);
                c2_Logger.info("crkodrt2:RecurseFromCurrentElementAndProcessAllXxxxMidiSpecifications:SpecificationIndex:" + SpecificationIndex);
                break;
              }
              case "ChannelNumber":
              {
                ChannelNumberString = strNodeValue02;
                XxxxMidiChannelArray[SpecificationIndex] = Integer.parseInt(ChannelNumberString);
                c2_Logger.info("crkodrt2:RecurseFromCurrentElementAndProcessAllXxxxMidiSpecifications:XxxxArrayIndexByMidiChannelHashMap.put(" + ChannelNumberString + ", " + SpecificationIndex + ")");
                XxxxArrayIndexByMidiChannelHashMap.put(ChannelNumberString, SpecificationIndex);
                break;
              }
              case "NoteFilter":
              {
                c2_Logger.info("crkodrt2:RecurseFromCurrentElementAndProcessAllXxxxMidiSpecifications:XxxxNoteFilterStringArray[" + SpecificationIndex + "] = " + strNodeValue02);
                XxxxNoteFilterStringArray[SpecificationIndex] = strNodeValue02;
                break;
              }
              case "BeatFilter":
              {
                c2_Logger.info("crkodrt2:RecurseFromCurrentElementAndProcessAllXxxxMidiSpecifications:XxxxBeatFilterStringArray[" + SpecificationIndex + "] = " + strNodeValue02);
                XxxxBeatFilterStringArray[SpecificationIndex] = strNodeValue02;
                break;
              }
              case "RestFilter":
              {
                c2_Logger.info("crkodrt2:RecurseFromCurrentElementAndProcessAllXxxxMidiSpecifications:XxxxRestFilterStringArray[" + SpecificationIndex + "] = " + strNodeValue02);
                XxxxRestFilterStringArray[SpecificationIndex] = strNodeValue02;
                break;
              }
              case "OctaveFilter":
              {
                c2_Logger.info("crkodrt2:RecurseFromCurrentElementAndProcessAllXxxxMidiSpecifications:XxxxOctaveFilterStringArray[" + SpecificationIndex + "] = " + strNodeValue02);
                XxxxOctaveFilterStringArray[SpecificationIndex] = strNodeValue02;
                break;
              }
              case "VelocityFilter":
              {
                c2_Logger.info("crkodrt2:RecurseFromCurrentElementAndProcessAllXxxxMidiSpecifications:XxxxVelocityFilterStringArray[" + SpecificationIndex + "] = " + strNodeValue02);
                XxxxVelocityFilterStringArray[SpecificationIndex] = strNodeValue02;
                break;
              }
              default:
              {
                break;
              }

            }
          }

        }

      }


    }
    catch (Exception e)
    {
      c2_Logger.error("RecurseFromCurrentElementAndProcessAllXxxxMidiSpecifications:RFCEAPAXMS_ERROR:" + e.getMessage());
      StackTraceElement[] steArray = e.getStackTrace();
      int steArraySize = java.lang.reflect.Array.getLength(steArray);
      for(int x = 0;x < NumberOfStackTraceElementsToOutput;x++)
      {
        if(x < steArraySize)
        {
          c2_Logger.error("RecurseFromCurrentElementAndProcessAllXxxxMidiSpecifications:RFCEAPAXMS_ERROR:" + steArray[x].toString());
        }
      }
    }

    return XxxxArrayIndexByMidiChannelHashMap;
  }











  // this function will add values into the ChromaticIndexArray based on an OR algorithm

  public static int OrIntoChromaticIndexArray
                    (
                     int OICIA_ModeArrayValue,
                     int OICIA_ChartIndex,
                     int OICIA_ModeOffset,
                     int OICIA_ModeArraySecondaryIndex
                    )
  {

    int ChromaticOrIndexArrayStartingIndex;

    try
    {

      if(OICIA_ModeArrayValue != 0)
      {
        ChromaticIndex = ChromaticIndexArray[OICIA_ChartIndex][OICIA_ModeArrayValue];
        ChromaticOrIndexArrayStartingIndex = ((OICIA_ChartIndex - 1) * 52) + ((OICIA_ModeArrayValue  - 1) * 4);
        if(ChromaticIndex > -1)
        {
          ChromaticOrIndexArray[ChromaticOrIndexArrayStartingIndex] = ChromaticIndex;
          c2_Logger.info("crkodrt2:main:ChromaticOrIndexArray[" + ChromaticOrIndexArrayStartingIndex + "] = " + ChromaticIndex);
          ChromaticOrIndexArray[(ChromaticOrIndexArrayStartingIndex + 1)] = (OICIA_ModeOffset + (OICIA_ModeArraySecondaryIndex - 2));
          c2_Logger.info("crkodrt2:main:ChromaticOrIndexArray[" + (ChromaticOrIndexArrayStartingIndex + 1) + "] = " + (OICIA_ModeOffset + (OICIA_ModeArraySecondaryIndex - 2)));
          CurrentModeArrayValue = -2;
          ChromaticIndexArray[OICIA_ChartIndex][OICIA_ModeArrayValue] = CurrentModeArrayValue;
          c2_Logger.info("crkodrt2:main:ChromaticIndexArray[" + OICIA_ChartIndex + "][" + OICIA_ModeArrayValue + "] = " + CurrentModeArrayValue);
        }
        else
        {
          if(ChromaticIndex == -1)
          {
            ChromaticIndexArray[OICIA_ChartIndex][OICIA_ModeArrayValue] = (OICIA_ModeOffset + (OICIA_ModeArraySecondaryIndex - 2));
            c2_Logger.info("crkodrt2:main:ChromaticIndexArray[" + OICIA_ChartIndex + "][" + OICIA_ModeArrayValue + "] = " + (OICIA_ModeOffset + (OICIA_ModeArraySecondaryIndex - 2)));
          }
          else
          {
            ChromaticOrIndexArray[(ChromaticOrIndexArrayStartingIndex + java.lang.Math.abs(ChromaticIndex))] = (OICIA_ModeOffset + (OICIA_ModeArraySecondaryIndex - 2));
            c2_Logger.info("crkodrt2:main:ChromaticOrIndexArray[" + (ChromaticOrIndexArrayStartingIndex + java.lang.Math.abs(ChromaticIndex)) + "] = " + (OICIA_ModeOffset + (OICIA_ModeArraySecondaryIndex - 2)));
            CurrentModeArrayValue = ChromaticIndex - 1;
            ChromaticIndexArray[OICIA_ChartIndex][OICIA_ModeArrayValue] = CurrentModeArrayValue;
            c2_Logger.info("crkodrt2:main:ChromaticIndexArray[" + OICIA_ChartIndex + "][" + OICIA_ModeArrayValue + "] = " + CurrentModeArrayValue);
          }
        }

      }
      return 0;

    }
    catch (Exception e)
    {
      c2_Logger.error("RecurseFromCurrentElementAndProcessAllXxxxMidiSpecifications:RFCEAPAXMS_ERROR:" + e.getMessage());
      StackTraceElement[] steArray = e.getStackTrace();
      int steArraySize = java.lang.reflect.Array.getLength(steArray);
      for(int x = 0;x < NumberOfStackTraceElementsToOutput;x++)
      {
        if(x < steArraySize)
        {
          c2_Logger.error("RecurseFromCurrentElementAndProcessAllXxxxMidiSpecifications:RFCEAPAXMS_ERROR:" + steArray[x].toString());
        }
      }
      return -1;
    }

  }











}
