Exemplo n.º 1
0
        public static int RunGenerateAndReturnExitCode(GenerateOptions opts)
        {
            if (!opts.PatchType.Equals("single"))
            {
                Console.WriteLine($"Sorry, I don't know how to generate {opts.PatchType} patches.");
                return(-1);
            }

            Console.WriteLine("OK, you want to generate a single patch.");
            Console.WriteLine($"And you want to call it '{opts.PatchName}'.");

            SinglePatch singlePatch = new SinglePatch();

            // Override the patch defaults
            singlePatch.Name   = opts.PatchName;
            singlePatch.Volume = 100;
            singlePatch.Effect = 1;

            byte[] data = GenerateSystemExclusiveMessage(singlePatch, PatchUtil.GetPatchNumber(opts.PatchNumber));

            Console.WriteLine("Generated single patch as a SysEx message:");
            Console.WriteLine(Util.HexDump(data));

            // Write the data to the output file
            File.WriteAllBytes(opts.OutputFileName, data);

            return(0);
        }
Exemplo n.º 2
0
        public static int RunExtractAndReturnExitCode(ExtractOptions opts)
        {
            if (!opts.PatchType.Equals("single"))
            {
                Console.WriteLine($"Sorry, I don't know how to extract {opts.PatchType} patches.");
                return(-1);
            }

            string inputFileName = opts.InputFileName;

            byte[] fileData = File.ReadAllBytes(inputFileName);

            Bank bank = new Bank(fileData);
            int  sourcePatchNumber = PatchUtil.GetPatchNumber(opts.SourcePatchNumber);

            SinglePatch patch = bank.Singles[sourcePatchNumber];

            int destinationPatchNumber = PatchUtil.GetPatchNumber(opts.DestinationPatchNumber);

            byte[] patchData = GenerateSystemExclusiveMessage(patch, destinationPatchNumber);

            // Write the data to the output file
            File.WriteAllBytes(opts.OutputFileName, patchData);

            return(0);
        }
Exemplo n.º 3
0
        private void LoadFile()
        {
            if (_fileName != null)
            {
                var data = System.IO.File.ReadAllBytes(_fileName);

                _singlePatch = new SinglePatch(data);

                _singlePatchView.Patch = _singlePatch;
            }
        }
Exemplo n.º 4
0
        public static int RunDumpAndReturnExitCode(DumpOptions opts)
        {
            string fileName = opts.FileName;

            byte[] fileData = File.ReadAllBytes(fileName);
            Console.WriteLine($"SysEx file: '{fileName}' ({fileData.Length} bytes)");

            List <byte[]> messages = Util.SplitBytesByDelimiter(fileData, 0xf7);

            Console.WriteLine($"Got {messages.Count} messages");

            foreach (byte[] message in messages)
            {
                byte[] rawData = ExtractPatchData(message);
                byte[] data    = Util.ConvertFromTwoNybbleFormat(rawData);

                SystemExclusiveHeader header = new SystemExclusiveHeader(message);
                Console.WriteLine(header);
                // TODO: Check the SysEx file header for validity

                Console.WriteLine(String.Format("Function = {0}", ((SystemExclusiveFunction)header.Function)).ToString().ToUpper());

                if (header.Substatus1 == 0x00)
                {
                    Console.WriteLine("SINGLE");
                }
                else if (header.Substatus1 == 0x01)
                {
                    Console.WriteLine("MULTI");
                }

                Console.WriteLine(String.Format("Program = {0}", header.Substatus2));
                int    programNumber = header.Substatus2;
                string programType   = "INTERNAL";
                if (programNumber >= 48)
                {
                    programType    = "EXTERNAL";
                    programNumber -= 48;
                }
                string programName = GetProgramName(programNumber);
                Console.WriteLine(String.Format("{0} {1}", programType, programName));

                SinglePatch s = new SinglePatch(data);
                System.Console.WriteLine(s.ToString());
            }

            return(0);
        }
Exemplo n.º 5
0
        public static int RunExtractAndReturnExitCode(ExtractOptions opts)
        {
            string fileName = opts.FileName;

            byte[] fileData = File.ReadAllBytes(fileName);
            Console.WriteLine($"SysEx file: '{fileName}' ({fileData.Length} bytes)");

            List <byte[]> messages = Util.SplitBytesByDelimiter(fileData, 0xf7);

            Console.WriteLine($"Got {messages.Count} messages");

            int programNumber = GetProgramNumber(opts.PatchNumber);

            foreach (byte[] message in messages)
            {
                SystemExclusiveHeader header = new SystemExclusiveHeader(message);

                if (header.Substatus2 != programNumber)
                {
                    continue;
                }

                byte[] rawData = ExtractPatchData(message);
                byte[] data    = Util.ConvertFromTwoNybbleFormat(rawData);

                SinglePatch s = new SinglePatch(data);

                int    channel   = opts.Channel - 1; // adjust channel 1...16 to range 0...15
                byte[] newHeader = new byte[] { 0xF0, 0x40, (byte)(channel - 1), 0x20, 0x00, 0x02, 0x00, (byte)programNumber };

                List <byte> newData = new List <byte>();
                newData.AddRange(newHeader);
                newData.AddRange(Util.ConvertToTwoNybbleFormat(s.ToData()));
                newData.Add(0xf7);

                var folder      = Environment.SpecialFolder.Desktop;
                var newFileName = Path.Combine(new string[] { Environment.GetFolderPath(folder), $"{s.Name.Trim()}.syx" });
                Console.WriteLine($"Writing SysEx data to '{newFileName}'...");
                File.WriteAllBytes(newFileName, newData.ToArray());
            }

            return(0);
        }
Exemplo n.º 6
0
        public SinglePatch Generate()
        {
            SinglePatch single = new SinglePatch();

            single.SingleCommon.Name                  = Descriptor.Name;
            single.SingleCommon.Volume.Value          = 115;
            single.SingleCommon.SourceCount           = Descriptor.Sources.Count;
            single.SingleCommon.IsPortamentoEnabled   = false;
            single.SingleCommon.PortamentoSpeed.Value = 0;

            single.Sources = new Source[single.SingleCommon.SourceCount];

            for (int i = 0; i < single.SingleCommon.SourceCount; i++)
            {
                single.Sources[i] = GenerateSource(Descriptor.Sources[i]);
            }

            return(single);
        }
Exemplo n.º 7
0
        // Create an init patch. This is a single patch with basic settings.
        public static int RunInitAndReturnExitCode(InitOptions opts)
        {
            Console.WriteLine("Init");

            var patch = new SinglePatch();

            patch.SingleCommon.Name         = "DS Init";
            patch.SingleCommon.Volume.Value = 115;
            patch.SingleCommon.SourceCount  = 2;

            patch.Sources = new Source[patch.SingleCommon.SourceCount];
            for (int i = 0; i < patch.SingleCommon.SourceCount; i++)
            {
                patch.Sources[i] = new Source();
            }

            Console.WriteLine(patch.ToString());

            return(0);
        }
Exemplo n.º 8
0
        private static byte[] GenerateSystemExclusiveMessage(SinglePatch patch, int patchNumber, int channel = 0)
        {
            List <byte> data = new List <byte>();

            SystemExclusiveHeader header = new SystemExclusiveHeader();

            header.ManufacturerID = 0x40;  // Kawai
            header.Channel        = (byte)channel;
            header.Function       = (byte)SystemExclusiveFunction.OnePatchDataDump;
            header.Group          = 0x00; // synth group
            header.MachineID      = 0x04; // K4/K4r
            header.Substatus1     = 0x00; // INT
            header.Substatus2     = (byte)patchNumber;

            data.Add(SystemExclusiveHeader.Initiator);
            data.AddRange(header.ToData());
            data.AddRange(patch.ToData());
            data.Add(SystemExclusiveHeader.Terminator);

            return(data.ToArray());
        }
Exemplo n.º 9
0
        public static int RunCreateAndReturnExitCode(CreateOptions opts)
        {
            //byte[] data = ExtractPatchData(message);
            //Single s = new Single(data);

            SinglePatch s = new SinglePatch();

            s.Name = "FRANKENP";

            byte[] newHarmonics = LeiterEngine.GetHarmonicLevels("saw", Source.HarmonicCount);
            for (int i = 0; i < Source.HarmonicCount; i++)
            {
                s.Source1.Harmonics[i].Level = newHarmonics[i];
                s.Source2.Harmonics[i].Level = newHarmonics[i];
            }
            s.Source1.Amplifier.EnvelopeSegments = Amplifier.Envelopes["regular"].Segments;
            s.Source2.Amplifier.EnvelopeSegments = Amplifier.Envelopes["silent"].Segments;

            int channel = 1;

            byte[]      newHeader = new byte[] { 0xF0, 0x40, (byte)(channel - 1), 0x20, 0x00, 0x02, 0x00, 0x2F };
            List <byte> newData   = new List <byte>();

            newData.AddRange(newHeader);
            newData.AddRange(Util.ConvertToTwoNybbleFormat(s.ToData()));
            newData.Add(0xf7);

            Console.WriteLine("Creating new patch, new SysEx data:\n{0}", Util.HexDump(newData.ToArray()));

            var folder      = Environment.SpecialFolder.Desktop;
            var newFileName = Path.Combine(new string[] { Environment.GetFolderPath(folder), "Frankenpatch.syx" });

            Console.WriteLine($"Writing SysEx data to '{newFileName}'...");
            File.WriteAllBytes(newFileName, newData.ToArray());

            return(0);
        }
Exemplo n.º 10
0
        private static string MakeTextList(byte[] data, string title)
        {
            //Console.WriteLine($"MakeTextList: data length = {data.Length} bytes");

            StringBuilder sb = new StringBuilder();

            sb.Append("SINGLE patches:\n");

            int offset = 0;

            for (int i = 0; i < SinglePatchCount; i++)
            {
                byte[] singleData = new byte[SinglePatch.DataSize];
                Buffer.BlockCopy(data, offset, singleData, 0, SinglePatch.DataSize);
                //Console.WriteLine($"Constructing single patch from {singleData.Length} bytes of data starting at {offset}");
                SinglePatch single = new SinglePatch(singleData);
                string      name   = PatchUtil.GetPatchName(i);
                sb.Append($"S{name}  {single.Name}\n");
                if ((i + 1) % 16 == 0)
                {
                    sb.Append("\n");
                }
                offset += SinglePatch.DataSize;
            }
            sb.Append("\n");

            sb.Append("MULTI patches:\n");
            for (int i = 0; i < MultiPatchCount; i++)
            {
                byte[] multiData = new byte[MultiPatch.DataSize];
                Buffer.BlockCopy(data, offset, multiData, 0, MultiPatch.DataSize);
                //Console.WriteLine($"Constructing multi patch from {multiData.Length} bytes of data starting at {offset}");
                MultiPatch multi = new MultiPatch(multiData);
                string     name  = PatchUtil.GetPatchName(i);
                sb.Append($"M{name}  {multi.Name}\n");
                if ((i + 1) % 16 == 0)
                {
                    sb.Append("\n");
                }
                offset += MultiPatch.DataSize;
            }

/*
 *          sb.Append("\n");
 *          sb.Append("DRUM:\n");
 *          byte[] drumData = new byte[DrumPatch.DataSize];
 *          Buffer.BlockCopy(data, offset, drumData, 0, DrumPatch.DataSize);
 *          Console.WriteLine($"Constructing drum patch from {drumData.Length} bytes of data starting at {offset}");
 *          DrumPatch drumPatch = new DrumPatch(drumData);
 */

            offset += DrumPatch.DataSize;

            sb.Append("\n");
            sb.Append("EFFECT SETTINGS:\n");
            for (int i = 0; i < 32; i++)
            {
                byte[] effectData = new byte[EffectPatch.DataSize];
                Buffer.BlockCopy(data, offset, effectData, 0, EffectPatch.DataSize);
                //Console.WriteLine($"Constructing effect patch from {effectData.Length} bytes of data starting at {offset}");
                EffectPatch effectPatch = new EffectPatch(effectData);

                sb.Append($"E-{i+1,2}  {effectPatch}");
                offset += EffectPatch.DataSize;
            }

            return(sb.ToString());
        }
Exemplo n.º 11
0
        public static int RunInitAndReturnExitCode(InitOptions opts)
        {
            List <SinglePatch> singlePatches = new List <SinglePatch>();

            for (int i = 0; i < SinglePatchCount; i++)
            {
                SinglePatch single = new SinglePatch();
                singlePatches.Add(single);
            }

            List <MultiPatch> multiPatches = new List <MultiPatch>();

            for (int i = 0; i < MultiPatchCount; i++)
            {
                MultiPatch multi = new MultiPatch();
                multiPatches.Add(multi);
            }

            // Create a System Exclusive header for an "All Patch Data Dump"
            SystemExclusiveHeader header = new SystemExclusiveHeader();

            header.ManufacturerID = 0x40; // Kawai
            header.Channel        = 0;    // MIDI channel 1
            header.Function       = (byte)SystemExclusiveFunction.AllPatchDataDump;
            header.Group          = 0;    // synthesizer group
            header.MachineID      = 0x04; // K4/K4r ID
            header.Substatus1     = 0;    // INT
            header.Substatus2     = 0;    // always zero

            List <byte> data = new List <byte>();

            data.Add(SystemExclusiveHeader.Initiator);
            data.AddRange(header.ToData());

            // Single patches: 64 * 131 = 8384 bytes of data
            foreach (SinglePatch s in singlePatches)
            {
                data.AddRange(s.ToData());
            }

            // Multi patches: 64 * 77 = 4928 bytes of data
            // The K4 MIDI spec has an error in the "All Patch Data" description;
            // multi patches are listed as 87, not 77 bytes
            foreach (MultiPatch m in multiPatches)
            {
                data.AddRange(m.ToData());
            }

            // Drums: 682 bytes of data
            DrumPatch drums = new DrumPatch();

            data.AddRange(drums.ToData());

            List <EffectPatch> effectPatches = new List <EffectPatch>();

            for (int i = 0; i < EffectPatchCount; i++)
            {
                EffectPatch effect = new EffectPatch();
                effectPatches.Add(effect);
            }

            // Effect patches: 32 * 35 = 1120 bytes of data
            foreach (EffectPatch e in effectPatches)
            {
                data.AddRange(e.ToData());
            }

            data.Add(SystemExclusiveHeader.Terminator);

            // SysEx initiator:    1
            // SysEx header:       7
            // Single patches:  8384
            // Multi patches:   4928
            // Drum settings:    682
            // Effect patches:  1120
            // SysEx terminator:   1
            // Total bytes:    15123

            // Write the data to the output file
            File.WriteAllBytes(opts.OutputFileName, data.ToArray());

            return(0);
        }
Exemplo n.º 12
0
        private static string MakeHtmlList(byte[] data, string title)
        {
            string GetNoteName(int noteNumber)
            {
                string[] notes  = new string[] { "C", "C#", "D", "Eb", "E", "F", "F#", "G", "G#", "A", "Bb", "B" };
                int      octave = noteNumber / 12 + 1;
                string   name   = notes[noteNumber % 12];

                return(name + octave);
            }

            StringBuilder sb = new StringBuilder();

            sb.Append(String.Format("<h1>{0}</h1>\n", title));

            SinglePatch[][] singleBanks = new SinglePatch[BankCount][]; //BankCount, PatchesPerBank];

            int offset    = 0;
            int patchSize = SinglePatch.DataSize;

            for (int bankNumber = 0; bankNumber < BankCount; bankNumber++)
            {
                SinglePatch[] patches = new SinglePatch[PatchesPerBank];
                for (int patchNumber = 0; patchNumber < PatchesPerBank; patchNumber++)
                {
                    byte[] singleData = new byte[patchSize];
                    Buffer.BlockCopy(data, offset, singleData, 0, patchSize);
                    SinglePatch single = new SinglePatch(singleData);
                    patches[patchNumber] = single;
                    offset += patchSize;
                }

                singleBanks[bankNumber] = patches;
            }

            // Now we should have all the single patches collected in four lists of 16 each

            sb.Append("<table>\n");
            sb.Append("<tr>\n    <th>SINGLE</th>\n");
            for (int bankNumber = 0; bankNumber < BankCount; bankNumber++)
            {
                char bankLetter = "ABCD"[bankNumber];
                sb.Append(String.Format("    <th>{0}</th>\n", bankLetter));
            }
            sb.Append("</tr>\n");

            for (int patchNumber = 0; patchNumber < PatchesPerBank; patchNumber++)
            {
                sb.Append("<tr>\n");
                sb.Append(String.Format("    <td>{0,2}</td>\n", patchNumber + 1));
                for (int bankNumber = 0; bankNumber < BankCount; bankNumber++)
                {
                    SinglePatch[] patches = singleBanks[bankNumber];
                    string        patchId = PatchUtil.GetPatchName(bankNumber * patchNumber);
                    SinglePatch   single  = patches[patchNumber];
                    sb.Append(String.Format($"    <td>{single.Name:10}</td>\n"));
                }
                sb.Append("</tr>\n");
            }
            sb.Append("</table>\n");

            //
            // Multi patches
            //

            patchSize = MultiPatch.DataSize;

            MultiPatch[][] multiBanks = new MultiPatch[BankCount][];

            for (int bankNumber = 0; bankNumber < BankCount; bankNumber++)
            {
                MultiPatch[] patches = new MultiPatch[PatchesPerBank];
                for (int patchNumber = 0; patchNumber < PatchesPerBank; patchNumber++)
                {
                    byte[] multiData = new byte[patchSize];
                    Buffer.BlockCopy(data, offset, multiData, 0, patchSize);
                    MultiPatch multi = new MultiPatch(multiData);
                    patches[patchNumber] = multi;
                    offset += patchSize;
                }

                multiBanks[bankNumber] = patches;
            }

            sb.Append("<table>\n");
            sb.Append("<tr>\n    <th>MULTI</th>\n");
            for (int bankNumber = 0; bankNumber < BankCount; bankNumber++)
            {
                char bankLetter = "ABCD"[bankNumber];
                sb.Append(String.Format("    <th>{0}</th>\n", bankLetter));
            }
            sb.Append("</tr>\n");

            for (int patchNumber = 0; patchNumber < PatchesPerBank; patchNumber++)
            {
                sb.Append("<tr>\n");
                sb.Append(String.Format("    <td>{0,2}</td>\n", patchNumber + 1));
                for (int bankNumber = 0; bankNumber < BankCount; bankNumber++)
                {
                    MultiPatch[] patches = multiBanks[bankNumber];
                    string       patchId = PatchUtil.GetPatchName(bankNumber * patchNumber);
                    MultiPatch   single  = patches[patchNumber];
                    sb.Append(String.Format($"    <td>{single.Name:10}</td>\n"));
                }
                sb.Append("</tr>\n");
            }

            sb.Append("</table>\n");

            patchSize = DrumPatch.DataSize;

            // TODO: List drum
// Crash when setting tune of drum note (value out of range)

/*
 *          sb.Append("<table>\n");
 *          sb.Append("<caption>DRUM</caption>\n");
 *          sb.Append("<tr><th>Note</th><th>Parameters</th></tr>\n");
 *
 *          patchSize = DrumPatch.DataSize;
 *          byte[] drumData = new byte[patchSize];
 *          Buffer.BlockCopy(data, offset, drumData, 0, patchSize);
 *          var drum = new DrumPatch(drumData);
 *          for (int i = 0; i < 128; i++)
 *          {
 *              var note = drum.Notes[i];
 *              sb.Append($"<tr><td>E-{GetNoteName(i)}</td><td>{note}</td></tr>\n");
 *          }
 *
 *          sb.Append("</table>\n");
 */
            offset += patchSize;

            sb.Append("<table>\n");
            sb.Append("<caption>EFFECT</caption>\n");
            sb.Append("<tr><th>#</th><th>Type and parameters</th></tr>\n");

            patchSize = EffectPatch.DataSize;

            for (int i = 0; i < 32; i++)
            {
                byte[] effectData = new byte[patchSize];
                Buffer.BlockCopy(data, offset, effectData, 0, patchSize);
                //Console.WriteLine($"Constructing effect patch from {effectData.Length} bytes of data starting at {offset}");
                EffectPatch effectPatch = new EffectPatch(effectData);

                sb.Append($"<tr><td>E-{i+1,2}</td><td>{effectPatch}</td></tr>\n");
                offset += patchSize;
            }

            sb.Append("</table>\n");

            return(sb.ToString());
        }
Exemplo n.º 13
0
        public int ListPatches()
        {
            // SysEx header at this point should be "F0 40 00 21 00 0A 00 00" followed by the tone map
            var offset = 8;               // skip to the tone map

            //Console.Error.WriteLine($"offset = {offset}");

            // For a block data dump, need to parse the tone map
            byte[] buffer;
            (buffer, offset) = Util.GetNextBytes(this.data, offset, PatchMap.Size);
            // now the offset has been updated to past the tone map
            //Console.Error.WriteLine($"offset = {offset}");
            var patchMap = new PatchMap(buffer);

            List <int> patchNumbers = new List <int>();

            //Console.WriteLine("Patches included:");
            var patchCount = 0;

            for (var i = 0; i < PatchMap.PatchCount; i++)
            {
                if (patchMap[i])
                {
                    patchCount += 1;
                    //Console.Write(i + 1);
                    //Console.Write(" ");

                    patchNumbers.Add(i);
                }
            }
            //Console.WriteLine($"\nTotal = {patchCount} patches");

            // Whatever the first patch is, it must be at least this many bytes (always has at least two sources)
            var minimumPatchSize = SingleCommonSettings.DataSize + 2 * KSynthLib.K5000.Source.DataSize;
            //Console.Error.WriteLine($"minimum patch size = {minimumPatchSize}");

            var totalPatchSize = 0;              // the total size of all the single patches

            var allPatchInfos = new List <PatchInfo>();

            var singlePatches = new List <SinglePatch>();

            foreach (var patchNumber in patchNumbers)
            {
                var startOffset = offset;                  // save the current offset because we need to copy more bytes later

                var sizeToRead = Math.Max(minimumPatchSize, this.data.Length - offset);
                //Console.WriteLine($"About to read {sizeToRead} bytes starting from offset {offset:X4}h");
                // We don't know yet how many bytes the patch is, but it is at least the minimum size
                (buffer, offset) = Util.GetNextBytes(this.data, offset, sizeToRead);
                // the offset has now been updated past the read size, so need to adjust it back later

                //Console.Error.WriteLine(Util.HexDump(buffer));
                //Console.Error.WriteLine($"checksum = {buffer[0]:X2}H");

                var patch = new SinglePatch(buffer);

                // Find out how many PCM and ADD sources
                var pcmCount = 0;
                var addCount = 0;
                foreach (var source in patch.Sources)
                {
                    if (source.IsAdditive)
                    {
                        addCount += 1;
                    }
                    else
                    {
                        pcmCount += 1;
                    }
                }

                // Figure out the total size of the single patch based on the counts
                var patchSize = 1 + SingleCommonSettings.DataSize                        // includes the checksum
                                + patch.Sources.Length * KSynthLib.K5000.Source.DataSize // all sources have this part
                                + addCount * AdditiveKit.DataSize;
                //Console.WriteLine($"{pcmCount}PCM {addCount}ADD size={patchSize} bytes");

                offset = startOffset;                  // back up to the start of the patch data
                // Read the whole patch now that we know its size
                //Console.WriteLine($"About to read {patchSize} bytes starting from offset {offset:X4}h");
                (buffer, offset) = Util.GetNextBytes(this.data, offset, patchSize);

                totalPatchSize += patchSize;

                singlePatches.Add(patch);

                var patchInfo = new PatchInfo
                {
                    Bank                = this.Header.Bank,
                    PatchNumber         = patchNumber + 1,
                    PatchName           = patch.SingleCommon.Name,
                    PCMSourceCount      = pcmCount,
                    AdditiveSourceCount = addCount,
                };
                Console.WriteLine($"{patchInfo.Bank}{patchInfo.PatchNumber:D3} | {patchInfo.PatchName,8} | {patchInfo.PCMSourceCount}PCM {patchInfo.AdditiveSourceCount}ADD");

                allPatchInfos.Add(patchInfo);
            }

            foreach (var patchInfo in allPatchInfos)
            {
                Console.WriteLine($"{patchInfo.Bank}{patchInfo.PatchNumber:D3} | {patchInfo.PatchName,8} | {patchInfo.PCMSourceCount}PCM {patchInfo.AdditiveSourceCount}ADD");
            }

            return(0);
        }
Exemplo n.º 14
0
        public static int RunCreateAndReturnExitCode(CreateOptions opts)
        {
            var header = new SystemExclusiveHeader(0x00);

            header.Function   = (byte)SystemExclusiveFunction.OneBlockDump;
            header.Group      = 0x00;
            header.MachineID  = 0x0A;
            header.Substatus1 = 0x00;  // single

            // Get the right bank. Since it is a required parameter, I suppose we can trust that it exists.
            string bankName = opts.BankName.ToLower();
            char   ch       = bankName[0];

            switch (ch)
            {
            case 'a':
                header.Substatus2 = 0x00;
                break;

            case 'd':
                header.Substatus2 = 0x02;
                break;

            case 'e':
                header.Substatus2 = 0x03;
                break;

            case 'f':
                header.Substatus2 = 0x04;
                break;

            default:
                Console.WriteLine(string.Format("Unknown bank: '{0}'", opts.BankName));
                return(-1);
            }

            var allData = new List <byte>();

            // SysEx initiator and basic header data
            allData.Add(SystemExclusiveHeader.Initiator);
            allData.AddRange(header.ToData());

            // Additional header data as required
            var patchNumber = opts.PatchNumber - 1;

            if (patchNumber < 0 || patchNumber > 127)
            {
                Console.WriteLine("Patch number must be 1...128");
                return(-1);
            }
            allData.Add((byte)patchNumber);

            SinglePatchGenerator  generator;
            SinglePatchDescriptor descriptor;

            if (opts.PatchType.Equals("single"))
            {
                if (!string.IsNullOrEmpty(opts.Descriptor))  // we have a JSON descriptor file, parse it
                {
                    var jsonText = File.ReadAllText(opts.Descriptor);
                    descriptor = JsonConvert.DeserializeObject <SinglePatchDescriptor>(jsonText);
                    generator  = new SinglePatchGenerator(descriptor);
                }
                else
                {
                    descriptor = new SinglePatchDescriptor();
                    generator  = new SinglePatchGenerator(descriptor);
                }

                SinglePatch single     = generator.Generate();
                byte[]      singleData = single.ToData();
                Console.Error.WriteLine(string.Format("Generated single data size: {0} bytes", singleData.Length));
                Console.Error.WriteLine(single.ToString());
                allData.AddRange(singleData);

                allData.Add(SystemExclusiveHeader.Terminator);

                File.WriteAllBytes(opts.OutputFileName, allData.ToArray());
            }
            else if (opts.PatchType.Equals("multi"))
            {
                Console.WriteLine("Don't know how to make a multi patch yet");
                return(1);
            }

            return(0);
        }
Exemplo n.º 15
0
        private static void ProcessMessage(byte[] message)
        {
            Console.WriteLine($"Message length = {message.Length} bytes");

            var header = new SystemExclusiveHeader(message);
            //Console.WriteLine("{0}", header);

            var functionNames = new Dictionary <SystemExclusiveFunction, string>()
            {
                { SystemExclusiveFunction.OneBlockDumpRequest, "One Block Dump Request" },
                { SystemExclusiveFunction.AllBlockDumpRequest, "All Block Dump Request" },
                { SystemExclusiveFunction.ParameterSend, "Parameter Send" },
                { SystemExclusiveFunction.TrackControl, "Track Control" },
                { SystemExclusiveFunction.OneBlockDump, "One Block Dump" },
                { SystemExclusiveFunction.AllBlockDump, "All Block Dump" },
                { SystemExclusiveFunction.ModeChange, "Mode Change" },
                { SystemExclusiveFunction.Remote, "Remote" },
                { SystemExclusiveFunction.WriteComplete, "Write Complete" },
                { SystemExclusiveFunction.WriteError, "Write Error" },
                { SystemExclusiveFunction.WriteErrorByProtect, "Write Error (Protect)" },
                { SystemExclusiveFunction.WriteErrorByMemoryFull, "Write Error (Memory Full)" },
                { SystemExclusiveFunction.WriteErrorByNoExpandMemory, "Write Error (No Expansion Memory)" }
            };

            var    function = (SystemExclusiveFunction)header.Function;
            string functionName;

            if (functionNames.TryGetValue(function, out functionName))
            {
                Console.Error.WriteLine("Function = {0}", functionName);
            }
            else
            {
                Console.Error.WriteLine("Unknown function: {0}", function);
            }

            switch (header.Substatus1)
            {
            case 0x00:
                Console.WriteLine("Single");
                break;

            case 0x20:
                Console.WriteLine("Multi");
                break;

            case 0x10:
                Console.WriteLine("Drum Kit");      // K5000W only
                break;

            case 0x11:
                Console.WriteLine("Drum Inst");      // K5000W only
                break;

            default:
                Console.Error.WriteLine(string.Format("Unknown substatus1: {0:X2}", header.Substatus1));
                break;
            }

            switch (header.Substatus2)
            {
            case 0x00:
                Console.WriteLine("Add Bank A");
                break;

            case 0x01:
                Console.WriteLine("PCM Bank B");      // K5000W
                break;

            case 0x02:
                Console.WriteLine("Add Bank D");
                break;

            case 0x03:
                Console.WriteLine("Exp Bank E");
                break;

            case 0x04:
                Console.WriteLine("Exp Bank F");
                break;

            default:
                Console.WriteLine("Substatus2 is first data byte");
                break;
            }

            switch (function)
            {
            case SystemExclusiveFunction.OneBlockDump:
                Console.WriteLine("One Block Dump");

                int toneNumber = message[8] + 1;
                Console.WriteLine($"Tone No = {toneNumber} ({message[8]})");
                break;

            case SystemExclusiveFunction.AllBlockDump:
                Console.WriteLine("All Block Dump");
                break;

            default:
                Console.WriteLine($"Unknown function: {function}");
                break;
            }

            if (function == SystemExclusiveFunction.AllBlockDump)
            {
                var patchMapData = new byte[PatchMap.Size];
                Array.Copy(message, SystemExclusiveHeader.DataSize, patchMapData, 0, PatchMap.Size);

                var patchMap = new PatchMap(patchMapData);

                Console.WriteLine("Patches included:");
                for (var i = 0; i < PatchMap.PatchCount; i++)
                {
                    if (patchMap[i])
                    {
                        Console.Write(i + 1);
                        Console.Write(" ");
                    }
                }
                Console.WriteLine();

                var dataLength = message.Length - SystemExclusiveHeader.DataSize - PatchMap.Size;
                var data       = new byte[dataLength];
                Array.Copy(message, SystemExclusiveHeader.DataSize + PatchMap.Size, data, 0, dataLength);
                //Console.WriteLine(Util.HexDump(data));

                var  offset   = 0;
                byte checksum = data[offset];
                Console.WriteLine($"checksum = {checksum:X2}");
                offset += 1;
            }

            // Single additive patch for bank A or D:
            if (header.Substatus1 == 0x00 && (header.Substatus2 == 0x00 || header.Substatus2 == 0x02))
            {
                var dataLength = message.Length - SystemExclusiveHeader.DataSize - PatchMap.Size;
                var data       = new byte[dataLength];
                Array.Copy(message, SystemExclusiveHeader.DataSize + PatchMap.Size, data, 0, dataLength);
                //Console.WriteLine(Util.HexDump(data));

                // Chop the data into individual buffers based on the declared sizes
                var  offset   = 0;
                byte checksum = data[offset];
                Console.WriteLine($"checksum = {checksum:X2}");
                offset += 1;
                var commonData = new byte[SingleCommonSettings.DataSize];
                Array.Copy(data, offset, commonData, 0, SingleCommonSettings.DataSize);
                //Console.WriteLine(Util.HexDump(commonData));
                offset += SingleCommonSettings.DataSize;

                var patch = new SinglePatch(data);
                Console.WriteLine($"Name = {patch.SingleCommon.Name}");
            }
        }
Exemplo n.º 16
0
        public int DumpPatches(string outputFormat)
        {
            var offset = 8;               // skip to the tone map

            byte[] buffer;
            (buffer, offset) = Util.GetNextBytes(this.data, offset, PatchMap.Size);
            var patchMap = new PatchMap(buffer);

            List <int> patchNumbers = new List <int>();

            var patchCount = 0;

            for (var i = 0; i < PatchMap.PatchCount; i++)
            {
                if (patchMap[i])
                {
                    patchCount += 1;
                    //Console.Write(i + 1);
                    //Console.Write(" ");

                    patchNumbers.Add(i);
                }
            }

            var minimumPatchSize = SingleCommonSettings.DataSize + 2 * KSynthLib.K5000.Source.DataSize;
            var totalPatchSize   = 0;            // the total size of all the single patches
            var allPatchInfos    = new List <PatchInfo>();
            var singlePatches    = new List <SinglePatch>();

            foreach (var patchNumber in patchNumbers)
            {
                var startOffset = offset;                  // save the current offset because we need to copy more bytes later

                var sizeToRead = Math.Max(minimumPatchSize, this.data.Length - offset);
                // We don't know yet how many bytes the patch is, but it is at least the minimum size
                (buffer, offset) = Util.GetNextBytes(this.data, offset, sizeToRead);
                // the offset has now been updated past the read size, so need to adjust it back later

                //Console.Error.WriteLine(Util.HexDump(buffer));
                //Console.Error.WriteLine($"checksum = {buffer[0]:X2}H");

                var patch = new SinglePatch(buffer);

                // Find out how many PCM and ADD sources
                var pcmCount = 0;
                var addCount = 0;
                foreach (var source in patch.Sources)
                {
                    if (source.IsAdditive)
                    {
                        addCount += 1;
                    }
                    else
                    {
                        pcmCount += 1;
                    }
                }

                // Figure out the total size of the single patch based on the counts
                var patchSize = 1 + SingleCommonSettings.DataSize                        // includes the checksum
                                + patch.Sources.Length * KSynthLib.K5000.Source.DataSize // all sources have this part
                                + addCount * AdditiveKit.DataSize;
                //Console.WriteLine($"{pcmCount}PCM {addCount}ADD size={patchSize} bytes");

                offset = startOffset;                  // back up to the start of the patch data
                // Read the whole patch now that we know its size
                //Console.WriteLine($"About to read {patchSize} bytes starting from offset {offset:X4}h");
                (buffer, offset) = Util.GetNextBytes(this.data, offset, patchSize);

                totalPatchSize += patchSize;

                singlePatches.Add(patch);
            }

            foreach (var patch in singlePatches)
            {
                if (outputFormat.Equals("text"))
                {
                    Console.WriteLine(patch);
                }
                else if (outputFormat.Equals("json"))
                {
                    string jsonString = JsonConvert.SerializeObject(
                        patch,
                        Newtonsoft.Json.Formatting.Indented,
                        new Newtonsoft.Json.Converters.StringEnumConverter()
                        );
                    Console.WriteLine(jsonString);
                }
            }

            return(0);
        }
Exemplo n.º 17
0
        static int Main(string[] args)
        {
            if (args.Length < 2)
            {
                System.Console.WriteLine("Usage: K5KTool cmd filename.syx");
                return(1);
            }

            string command   = args[0];
            string fileName  = args[1];
            string patchName = "";

            if (args.Length > 2)
            {
                patchName = args[2];
            }

            byte[] fileData = File.ReadAllBytes(fileName);
            System.Console.WriteLine($"SysEx file: '{fileName}' ({fileData.Length} bytes)");

            List <byte[]> messages = Util.SplitBytesByDelimiter(fileData, Constants.SystemExclusiveTerminator);

            System.Console.WriteLine($"Got {messages.Count} messages");

            foreach (byte[] message in messages)
            {
                SystemExclusiveHeader header = new SystemExclusiveHeader(message);
                //System.Console.WriteLine(Util.HexDump(header.Data));
                System.Console.WriteLine(header.ToString());
                int headerLength = header.Data.Length;

                // Examine the header to see what kind of message this is:
                SystemExclusiveFunction function = (SystemExclusiveFunction)header.Function;
                if (function == SystemExclusiveFunction.AllPatchDataDump)
                {
                    // sub2: 0=I or E, 20H=i or e singles
                    if (header.Substatus2 == 0x00 || header.Substatus2 == 0x20)
                    {
                        int offset = headerLength;
                        for (int i = 0; i < NumSingles; i++)
                        {
                            byte[] singleData = new byte[SinglePatch.DataSize];
                            Buffer.BlockCopy(message, offset, singleData, 0, SinglePatch.DataSize);
                            System.Console.WriteLine("INGOING SINGLE DATA = \n" + Util.HexDump(singleData));
                            SinglePatch single = new SinglePatch(singleData);
                            System.Console.WriteLine(single.ToString());

                            byte[] sysExData = single.ToData();
                            System.Console.WriteLine("OUTCOMING SINGLE DATA = \n" + Util.HexDump(sysExData));

                            (bool result, int diffIndex) = Util.ByteArrayCompare(singleData, sysExData);
                            System.Console.WriteLine(String.Format("match = {0}, diff index = {1}", result ? "YES :-)" : "NO :-(", diffIndex));

                            offset += SinglePatch.DataSize;
                        }
                    }
                    else if (header.Substatus2 == 0x40)
                    {
                        System.Console.WriteLine("Multis not handled yet");
                        return(1);
                    }
                }
                else if (function == SystemExclusiveFunction.OnePatchDataDump)
                {
                    System.Console.WriteLine("One patch dumps not handled yet");
                    return(1);
                }
            }

            return(0);
        }