• 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Ketron Sd90 registrations changed with MobileSheets
#15
Hi Mike, 
tx for your information.

The two values PC / CC are the values to be set if using the existing way (screenshot mobilesheet midi commands).
Here ist the code i use to fire the complete midi event (using sendmidi console app triggered by java)


The method generating the events is   
Code:
public ArrayList<String> sendRegistrationChange_SD9(String midiDevice, int registerBank, int registrierungNr){

When running in demo (main method) you get output for sendmidi (commandline tool)

KetronBank:1; KetronRegNr:3; CC:0; PC:2   // The Mapping
/Users/k/Downloads/sendmidi-macos-1.0.13/sendmidi dev MIDI_DEVICE_NAME  ch 16 cc 00 0 cc 32 00 pc 2   // the real sendmidi code  "MIDI_DEVICE" depends on the device midi is send to
Channel:16 Bank:1 RegNr:2  MidiCommand:/Users/k/Downloads/sendmidi-macos-1.0.13/sendmidi dev  MIDI_DEVICE_NAME ch 16 cc 00 0 cc 32 00 pc 2

That's the command ketron understands.  
KetronBank:1; KetronRegNr:3; CC:0; PC:2   // The Mapping
ch 16 cc 00 0 cc 32 00 pc 2 // corresponding Midi command using sendmidi console app
I hope, it's possible to understand my infos Smile

If there is something to test with midi commands, let me know.

Code:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package net.gr.midi.midi_sys_ex;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.gr.midi.view.model.Control;

/**
*
* @author k
* Dieses Projekt beinhaltet einen Wrapper, um aus Java heraus System-Exclusive MIDI Daten an ein MIDI-Device zu senden.
* Der eigentliche Transmitter ist das Tool sendmidi
* The project website is https://github.com/gbevin/SendMIDI
*/
public class MIDI_SYS_EX_SENDER {
    public boolean test = false;
   
    File SEND_MIDI_PROGRAM = null; // Programm zum Senden der MIDI-SYS-EX Daten
   
    public MIDI_SYS_EX_SENDER(File sendMidi_Program){
        SEND_MIDI_PROGRAM = sendMidi_Program;
    }
   
    public MIDI_SYS_EX_SENDER(String sendMidi_Program){
        SEND_MIDI_PROGRAM = new File(sendMidi_Program);
    }
   
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        MIDI_SYS_EX_SENDER demo = new MIDI_SYS_EX_SENDER("/Users/k/Downloads/sendmidi-macos-1.0.13/sendmidi");
        System.out.println("Available MIDI-Interfaces:");
        System.out.println(demo.getMidiInterfacesOUT());
       
        // Test
       demo.test = true;
        for (int bank = 1; bank <=4; bank++){
            for (int reg = 1; reg <=10; reg++){
                demo.sendRegistrationChange_SD9("", bank, reg);
            }
           
        }
    }
   
   
    /**
     * Einlesen aller verfügbarer MIDI-Interfaces
     * @return Liefert eine Liste der verfügbaren MIDI-Interfaces OUT (aus sicht des PC) zurück.
     */
    public ArrayList<String> getMidiInterfacesOUT(){
        ArrayList<String> interfaces = new ArrayList<>();
        String[] command = new String[2];
        command[0] = SEND_MIDI_PROGRAM.getPath();
        command[1] = "list";
        Runtime rt = Runtime.getRuntime();
        Process exec;
        try {
            exec = rt.exec(command);
            BufferedReader br = new BufferedReader(new InputStreamReader(exec.getInputStream()));
            String line = "";
            while ( (line=br.readLine())!=null){
                interfaces.add(line.trim());
            }
               
        } catch (IOException ex) {
            Logger.getLogger(MIDI_SYS_EX_SENDER.class.getName()).log(Level.SEVERE, null, ex);
        }
        return interfaces;
    }


   
   
    /**
     * Schickt einen kombinierte Note-ON / Note-OFF Event
     * @param channel
     * @param note
     * @param midiDevice
     * @param noteOFF true: Note-OFF wird nachgesendet false: nur Note-ON Event wird gesendet.
     * @return ArrayList (String) mit Statusmeldungen.
     * @throws Exception
     */
    public ArrayList<String> sendNoteOnOffEvent(int channel, String note, String midiDevice, boolean noteOFF) throws Exception{
        MIDI_TOOLS.get_Note_On_Off_Event(channel, note);

        ArrayList<String> cmd = new ArrayList<>();
        cmd.add( SEND_MIDI_PROGRAM.getPath() );
        cmd.add( "dev" );
        cmd.add( midiDevice );
        cmd.add("ch");
        cmd.add( Integer.toString(channel) );
        cmd.add("on");
        cmd.add(note);
        cmd.add("64");

        String commandArray[] = cmd.stream().toArray(String[]::new);
        ArrayList<String> retMessage = new ArrayList<>();
        Runtime rt = Runtime.getRuntime();
        Process exec;
        try {
            exec = rt.exec(commandArray);
            BufferedReader br = new BufferedReader(new InputStreamReader(exec.getInputStream()));
            String line = "";
            while ( (line=br.readLine())!=null)
                retMessage.add(line);
           
        } catch (IOException ex) {
            Logger.getLogger(MIDI_SYS_EX_SENDER.class.getName()).log(Level.SEVERE, null, ex);
        }
       
       
        if (noteOFF) {
            cmd = new ArrayList<>();
            cmd.add(SEND_MIDI_PROGRAM.getPath());
            cmd.add("dev");
            cmd.add( midiDevice );
            cmd.add("ch");
            cmd.add(Integer.toString(channel));
            cmd.add("off");
            cmd.add(note);
            cmd.add("0");           
           
            rt = Runtime.getRuntime();
            try {
                exec = rt.exec(commandArray);
                BufferedReader br = new BufferedReader(new InputStreamReader(exec.getInputStream()));
                String line = "";
                while ((line = br.readLine()) != null) {
                    retMessage.add(line);
                }
               
            } catch (IOException ex) {
                Logger.getLogger(MIDI_SYS_EX_SENDER.class.getName()).log(Level.SEVERE, null, ex);
            }           
        }
        return retMessage;
    }

   
   
   
    /**
     * Sende System Exclusiv-Midi-Data aus Datei an das MIDIdevice senden
     * @param midiDevice  Empfägner MIDI-Interface
     * @param sysExFile
     * @return Fehlerliste
     * @throws Exception
     */
    public ArrayList<String> sendMidiSysExFile(String midiDevice, File sysExFile) throws Exception{
//        if (!canMIDI_device(MIDIdevice))
//            throw new Exception("Das MIDI-Interface " + MIDIdevice + " ist nicht verfügbar.");
       
        ArrayList<String> cmd = new ArrayList<>();
        cmd.add( SEND_MIDI_PROGRAM.getPath() );
        cmd.add( "dev" );
        cmd.add( midiDevice );
        cmd.add( "syf" );
        cmd.add( sysExFile.getPath() );
       
        String commandArray[] = cmd.stream().toArray(String[]::new);

        ArrayList<String> retMessage = new ArrayList<>();
        Runtime rt = Runtime.getRuntime();
        Process exec;
        try {
            exec = rt.exec(commandArray);
            BufferedReader br = new BufferedReader(new InputStreamReader(exec.getInputStream()));
            String line = "";
            while ( (line=br.readLine())!=null)
                retMessage.add(line);
           
        } catch (IOException ex) {
            Logger.getLogger(MIDI_SYS_EX_SENDER.class.getName()).log(Level.SEVERE, null, ex);
        }
        return retMessage;
    }
    /**
     * Prüfen, ob das übergebene MIDI-Interface verfügbar ist
     * @param midiDevice
     * @return
     * @throws Exception
     */
    private boolean canMIDI_device(String midiDevice) {
        ArrayList<String> midiInterfaces = getMidiInterfacesOUT();
        return midiInterfaces.contains( midiDevice );
    }

   
    public ArrayList<String> sendControlChange(String MIDIdevice, int MIDIchannel, int CC, int value){
        if (Control.IS_TEST)
            System.out.println("Start sendControlChange()");
       
        ArrayList<String> cmd = new ArrayList<>();
        cmd.add( SEND_MIDI_PROGRAM.getPath() );
        cmd.add( "dev" );
//        cmd.add( MIDI_TOOLS.getEscapedDeviceName(MIDIdevice) );
        cmd.add( MIDIdevice );
        cmd.add( "ch" );
        cmd.add( Integer.toString(MIDIchannel) );
        cmd.add("cc");
        cmd.add( Integer.toString(CC));
        cmd.add( Integer.toString(value) );

        String commandArray[] = cmd.stream().toArray(String[]::new);

        if (Control.IS_TEST){
            System.out.println("senControlChange() mit Daten:");
            printArray(commandArray);
            // return r;
       
        }
       
        ArrayList<String> retMessage = new ArrayList<>();
        Runtime rt = Runtime.getRuntime();
        Process exec;
        try {
            exec = rt.exec(commandArray);
            BufferedReader br = new BufferedReader(new InputStreamReader(exec.getInputStream()));
            String line = "";
            while ( (line=br.readLine())!=null)
                retMessage.add(line);
               
        } catch (IOException ex) {
            System.out.println("Exception beim Senden des Command: " + ex.getMessage());
            Logger.getLogger(MIDI_SYS_EX_SENDER.class.getName()).log(Level.SEVERE, null, ex);
        }
        if (Control.IS_TEST){
            System.out.print("Ende sendControlChange()");
            for (String s : retMessage)
                System.out.println(s);
        }
     
        return retMessage;
   
    }
   
   
    /**
     *
     * @param MIDIdevice
     * @param registerBank
     * @param registrierungNr
     * @return  Statusmeldungen
     */
    public ArrayList<String> sendRegistrationChange_SD9(String midiDevice, int registerBank, int registrierungNr){
        if (registerBank>4 | registerBank < 1)
            throw new IndexOutOfBoundsException("Registerbank ungültig");
        if (registrierungNr > 1000 | registrierungNr < 1)
            throw new IndexOutOfBoundsException("Registeriungsnummer ungültig");
       
        int regNr = registrierungNr -1;
        int regBank = registerBank;
        //canMIDI_device(MIDIdevice);
       
        // Bank 1 - 4 => cc 0 = 0, 8, 16, 24
        int bank[] = {0, 8, 16, 24};
       
        // ControlChange 00:
        // Value 0 -   7 Bank 1
        // Value 8 -  15 Bank 2
        // Value 16 - 23 Bank 3
        // Value 24 - 31 Bank 4
       
        // Regnr 0-127     cc 00 = 0;
        // Regnr 128-255   cc 00 = 1;
        // Regnr 256-382   cc 00 = 2;
        // Regnr 382-509   cc 00 = 3;
        // Regnr 509-636   cc 00 = 4;
        // Regnr 636-763   cc 00 = 5;
        // Regnr 763-890   cc 00 = 6;
        // Regnr 890-1000  cc 00 = 7;
        // Beim Überlauf über 10xx nächste Bank 8 und offset aus regNr wieder 0;
       
        int cc00 = Math.round(regNr/128);
        //System.out.println("cc00: " + cc00);
       
        int pcNr = regNr % 128;
        //System.out.println("pcNR: " + pcNr);
       
       
       
        ArrayList<String> cmd = new ArrayList<>();
        cmd.add( SEND_MIDI_PROGRAM.getPath() );
        cmd.add( "dev" );
        cmd.add(midiDevice );
        cmd.add( "ch" );
        cmd.add("16");
        cmd.add("cc");
        cmd.add("00");
        cmd.add(Integer.toString(cc00 + bank[regBank-1]));
        cmd.add("cc");
        cmd.add("32");
        cmd.add("00");
        cmd.add("pc");
        cmd.add(Integer.toString(pcNr));

        String commandArray[] = cmd.stream().toArray(String[]::new);

        if (test){
            String csv = String.format("KetronBank:%d; KetronRegNr:%d; CC:%d; PC:%d", registerBank, registrierungNr, (cc00 + bank[regBank-1]), pcNr);
            System.out.println(csv);
           // return null;
           
            System.out.println(String.format("Channel:%s Bank:%s RegNr:%s  MidiCommand:%s",16, regBank, regNr, printArray(commandArray) ));
            //printArray(commandArray);
            ArrayList<String> r = new ArrayList<>();
            r.add("Test done");
            return r;
       
        }
       
        ArrayList<String> retMessage = new ArrayList<>();
        Runtime rt = Runtime.getRuntime();
        Process exec;
        try {
            exec = rt.exec(commandArray);
            BufferedReader br = new BufferedReader(new InputStreamReader(exec.getInputStream()));
            String line = "";
            while ( (line=br.readLine())!=null)
                retMessage.add(line);
               
        } catch (IOException ex) {
            Logger.getLogger(MIDI_SYS_EX_SENDER.class.getName()).log(Level.SEVERE, null, ex);
        }
        return retMessage;
   
    }
   
   /**
     *
     * @param MIDIdevice    Empfäger für Sys-Ex MIDI Daten
     * @param hex  Hex Array für System Exclusiv Meldungen
     * @return  ArrayList&lt;String%gt; Rückmeldungen aus Konsolenanwendung
     * @throws java.lang.Exception
     */
    public ArrayList<String> sendMidiSysExCommand(String midiDevice, String[] hex) throws Exception{
        if (hex == null)
            throw new Exception("Keine MIDI-Daten zum Senden übergeben");
        if (hex.length==0)
            throw new Exception("Keine MIDI-Daten zum Senden übergeben");
       
        ArrayList<String> cmd = new ArrayList<>();
        cmd.add( SEND_MIDI_PROGRAM.getPath() );
        cmd.add( "dev" );
        cmd.add(midiDevice );
        cmd.add("hex" );
        cmd.add( "syx" );
        cmd.addAll(Arrays.asList(hex));

        String commandArray[] = cmd.stream().toArray(String[]::new);
       
        if (test){
            printArray(commandArray);
            ArrayList<String> r = new ArrayList<>();
            r.add("Test done");
            return r;
       
        }       
       
        ArrayList<String> retMessage = new ArrayList<>();
        Runtime rt = Runtime.getRuntime();
        Process exec;
        try {
            exec = rt.exec(commandArray);
            BufferedReader br = new BufferedReader(new InputStreamReader(exec.getInputStream()));
            String line = "";
            while ( (line=br.readLine())!=null)
                retMessage.add(line);
               
        } catch (IOException ex) {
            Logger.getLogger(MIDI_SYS_EX_SENDER.class.getName()).log(Level.SEVERE, null, ex);
        }
        return retMessage;
    }   
   
   
    /**
     * Wandelt den übergebenen String song in einen YAMAHA GENOS Hex String um
     * Problem: Umlaute können derzeit nicht korrekt umgesetzt werden.
     * @param path
     * @param song
     * @return MIDI-Befehlt für GENOS
     * @throws java.lang.Exception
     */
    public String[] getHexValuesGENOS(String path, String song) throws Exception{
        checkSpecialChars(song);
        String toConvert = "CsR&" +path + "/" + song + ".rgt";
       
        ArrayList<String> hexValues = new ArrayList<>();
        for (int i = 0; i< toConvert.length(); i++){
            String letter = toConvert.substring(i, i+1);
            String hexString = Integer.toHexString( letter.charAt(0));
            hexValues.add( getDoubleZero(hexString) );
        }
        return hexValues.stream().toArray(String[]::new);
    }   
   
   
    private String getDoubleZero(String hex){
        if (hex.length()==1){
            return "0" + hex.toUpperCase();
        }
        return hex.toUpperCase();
    }

   
 
   
   
    /**
     * Prüft den String auf Sonderzeichen, Umlaute etc
     * @param song
     */
    private void checkSpecialChars(String song) throws Exception {     
        String[] SPECIAL_CHARS = {"ä","ö","ü","ß"};
        String search = song.toLowerCase();
        for (String s : SPECIAL_CHARS)
            if (search.contains(s))
                throw new Exception("Unerlaubtes Sonderzeichen im Text enthalten: " + s);
    }
   
    private String printArray(String[] arr ){
        StringBuilder sb = new StringBuilder();
        for (String s : arr){
            System.out.print(s);
            sb.append(s).append(" ");
            System.out.print(" ");
        }
            System.out.println();
       
            return sb.toString();
    }
}


I my java-program i use sendmidi and receivemidi commandline tool because I wasn't able to send/receive midi commands on other way on mac.
Reply


Messages In This Thread
RE: Ketron Sd90 registrations changed with MobileSheets - by musikus - 02-16-2024, 04:53 AM



Users browsing this thread:
3 Guest(s)


  Theme © 2014 iAndrew  
Powered By MyBB, © 2002-2024 MyBB Group.