How to get a reference to a non default MIDI Sequencer? - java

I am building a Java application that programatically generates a MIDI Sequence that is then sent over the LoopBe Internal Midi Port so that I can use Ableton Live instruments for better sound playback quality.
Please correct me if I am wrong. What I need is to generate a Sequence, that will contain Tracks that will contains MidiEvents, that will contain MIDI messages with time information. That I think I got down.
The real problem is how to send it over the LoopBe MIDI Port. For that I supposedly need a Sequencer, but I don't know how I can get one rather than the default one, and I don't want that.
I guess a workaround would be to write the Sequence to a .mid file and then programatically play it back on the LoopBe Port.
So my question is: How can I obtain a non-default Sequencer?

You need method MidiSystem.getSequencer(boolean). When you call it with false parameter, it gives you unconnected sequencer.
Get Receiver instance from your target MIDI device and set it to sequencer with seq.getTransmitter().setReceiver(rec) call.
Example snippet:
MIDIDevice device = ... // obtain the MIDIDevice instance
Sequencer seq = MidiSystem.getSequencer(false);
Receiver rec = device.getReceiver();
seq.getTransmitter().setReceiver(rec)
For examples on Sequencer use, see tutorial on http://docs.oracle.com/javase/tutorial/sound/MIDI-seq-methods.html

For my own project I use LoopBe1 to send MIDI signals to REAPER.
Of course, LoopBe1 should already be installed.
In this example I iterate through the system's MIDI devices for the external MIDI port of LoopBe and then send the note C 10 times.
import javax.sound.midi.*;
public class Main {
public static void main(String[] args) throws MidiUnavailableException, InvalidMidiDataException, InterruptedException {
MidiDevice external;
MidiDevice.Info[] devices = MidiSystem.getMidiDeviceInfo();
//Iterate through the devices to get the External LoopBe MIDI port
for (MidiDevice.Info deviceInfo : devices) {
if(deviceInfo.getName().equals("LoopBe Internal MIDI")){
if(deviceInfo.getDescription().equals("External MIDI Port")){
external = MidiSystem.getMidiDevice(deviceInfo);
System.out.println("Device Name : " + deviceInfo.getName());
System.out.println("Device Description : " + deviceInfo.getDescription() + "\n");
external.open();
Receiver receiver = external.getReceiver();
ShortMessage message = new ShortMessage();
for (int i = 0; i < 10; i++) {
// Start playing the note Middle C (60),
// moderately loud (velocity = 93).
message.setMessage(ShortMessage.NOTE_ON, 0, 60, 93);
long timeStamp = -1;
receiver.send(message, timeStamp);
Thread.sleep(1000);
}
external.close();
}
}
}
}
}
For further information about the sending a MIDI signal, refer to this link:
https://docs.oracle.com/javase/tutorial/sound/MIDI-messages.html
I hope this helps!

Related

Modbus TCP in Java / Android

I am working on a modbus TCP implementation in Java. I've tried 3 different libraries so far modbus4j, jamod, and j2mod. I can successfully access my slave device with the linux modpoll tool: http://www.modbusdriver.com/modpoll.html
michael#michael-G75VW:~/Documents/modbus-test-tool/linux$ ./modpoll -a255 -r1 -1 192.168.1.101
modpoll 3.4 - FieldTalk(tm) Modbus(R) Master Simulator
Copyright (c) 2002-2013 proconX Pty Ltd
Visit http://www.modbusdriver.com for Modbus libraries and tools.
Protocol configuration: MODBUS/TCP
Slave configuration...: address = 255, start reference = 1, count = 1
Communication.........: 192.168.1.101, port 502, t/o 1.00 s, poll rate 1000 ms
Data type.............: 16-bit register, output (holding) register table
-- Polling slave...
[1]: 256
This causes the barrier on my device to go up which is great. However, working in the Java implementation I am unable to reproduce this. I've tried many different steps but all fail. In J2mod/jamod I continually get a invalid slaveId error when using '255' which is the unit id i use in the above command. If I use anything else, I get a CRC failed error. In mod4j I get various errors including error code = 4. Here is my latest J2mod code which returns either CRC error (if not 255) or invalid slaveId. I know slaveId is mostly used for Serial communications, but my device only responds to a Unit ID of 255 when using other applications.
Integer value = Integer.decode(val).intValue();
Integer unitID = Integer.decode(uid).intValue();
Integer length = Integer.decode(len).intValue();
Integer ref = Integer.decode(reference).intValue();
SimpleRegister MyReg = new SimpleRegister(value);
try {
InetAddress address;
address = InetAddress.getByName(addr);
//2. Open the connection
TCPMasterConnection con = new TCPMasterConnection(address);
con.setPort(port);
con.connect();
//3. Prepare the requestWrite
WriteSingleRegisterRequest WriteReq = new WriteSingleRegisterRequest(ref,MyReg);
WriteReq.setDataLength(length);
WriteReq.setUnitID(unitID);
//4. Prepare the transaction
ModbusTCPTransaction trans = new ModbusTCPTransaction(con);
trans.setRequest(WriteReq);
trans.setRetries(0);
trans.execute();
Log.d(TAG, "Complete: " +trans.toString());
return trans.getResponse().getHexMessage();
} catch (UnknownHostException e) {
Log.d(TAG, "UnknownHostException: " + e.getMessage());
return e.getMessage();
} catch (Exception e) {
Log.d(TAG,"Exception: " + e.toString());
return e.getMessage();
}
My manual for the modbus interface is available here:
https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&ved=0CCsQFjAA&url=http%3A%2F%2Fwww.ac-magnetic.com%2Fgermany%2Fsites%2Fdefault%2Ffiles%2F58150001EN_00_Technical%2520Maunal%2520EM01.pdf&ei=Z1dxUv7qF4a9yAGpooHYBQ&usg=AFQjCNGGZnBx_A0fFjuW3qqgWjhS_ek-0w&bvm=bv.55617003,d.aWc
I can't speak to why, exactly, this is happening. I can tell you that both jamod and j2mod (j2mod is a bug-fixed fork of jamod) simply copy whatever you set as the unit number to the 7th byte of the TCP packet. It's then up to the PLC to respond to the packet, as sent.
For j2mod, setting the system property com.ghgande.modbus.debug equal to "true" from the JVM command line will enable debug messages. That will allow you to view a packet dump that should tell you what's happening.
You do make one very interesting comment, and that is that you are seeing CRC errors. You are aware that Modbus/TCP doesn't use a CRC at all?

Odd InetAddress.isReachable() issue

My work is developing software for network capable cameras for retail enviroments. One of the peices of software my team is developing is a webserver that retrieves various reports generated in HTML by the camera itself (which has its own embedded webserver) and stored on the camera. Our software will then GET these reports from the camera and store it on a central webserver.
While we are fine plugging in the IPs of the cameras into our software, I am developing a simple Java class that will query the network and locate all cameras on the network.
The problem though is that while it runs just fine on my PC, and my coworker's PC, when we attempt to run it on the actual webserver PC that will host our software... it runs, but says every IP in the subnet is offline / unreachable EXCEPT for the gateway IP.
For example, if I run it from my PC or my coworkers PC when plugged into the closed LAN, I get the following active IPs found along with a flag telling me if its a camera or not.
(gateway is 192.168.0.1, subnet mask is 255.255.255.0, which means full range of 256 devices to be looked for)
IP:/192.168.0.1 Active:true Camera:false
IP:/192.168.0.100 Active:true Camera:true <- this is camera 1
IP:/192.168.0.101 Active:true Camera:true <- this is camera 2
IP:/192.168.0.103 Active:true Camera:false <- my PC
IP:/192.168.0.104 Active:true Camera:false <- this is our webserver
But for some reason, when running the same program from the webserver PC, using the same JRE, I only get the following found
IP:/192.168.0.1 Active:true Camera:false
Now my code, instead of enumerating through each IP in order on the main Thread, instead creates a seperate Thread for each IP to be checked and runs them concurrently (else it would take little over 21 minutes to enumerate through the entire IP range at a timeout of 5000ms / IP). The main Thread then re-runs these IP scan threads every 15 seconds over and over.
I have checked that all the threads are running to completion on all the PCs, no exceptions are being thrown. Even verified that none of the threads are getting stuck. Each Thread takes about 5001 to 5050ms from start to complete, and those Threads that have an active IP finish sooner (>5000ms), so I know that its correctly waiting the full 5000ms in the ipAddr.isReachable(5000) method.
Me and my coworker are stumped at this point while it seems to reach those active IPs fine when run on our PCs, yet getting no response from the webserver PC???
We have ruled out firewall issues, admin access issues, etc.. The only difference is that our webserver is Embedded Win XP, and our PCs are Windows 7.
This has us stumped. Any ideas why?
Below is the code that is running each IP Thread:
public void CheckIP() {
new Thread() {
#Override
public void run() {
try {
isActive = ipAddr.isReachable(5000);
if (isActive) {
if (!isCamera) {
isCamera = new IpHttpManager().GetResponse(ipAddr.toString());
}
} else {
isCamera = false;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
EDIT: Here is the code that builds each IP to check after determining the range based on gateway and subnet...
for(int i=subMin; i<=subMax; i++) {
byte[] ip = new byte[] {(byte)oct[0],(byte)oct[1],(byte)oct[2],(byte)i};
try {
scanners[subCount] = new IpScan(InetAddress.getByAddress(ip));
subCount++;
} catch (UnknownHostException e) {
e.printStackTrace();
}}
Thanks everyone, but I never did figure out or pinpoint why this oddity was happening. Everything I checked for was not the cause, so this question can be closed.
In any case, I ended up working around it completely. Instead of using InetAddress, I just went native and built my own ICMP ping class instead, via JNA, invoking Windows libraries IPHLPAPI.DLL and WSOCK32.DLL. Here is what I used...
public interface InetAddr extends StdCallLibrary {
InetAddr INSTANCE = (InetAddr)
Native.loadLibrary("wsock32.dll", InetAddr.class);
ULONG inet_addr(String cp); //in_addr creator. Creates the in_addr C struct used below
}
public interface IcmpEcho extends StdCallLibrary {
IcmpEcho INSTANCE = (IcmpEcho)
Native.loadLibrary("iphlpapi.dll", IcmpEcho.class);
int IcmpSendEcho(
HANDLE IcmpHandle, //Handle to the ICMP
ULONG DestinationAddress, //Destination address, in the form of an in_addr C Struct defaulted to ULONG
Pointer RequestData, //Pointer to the buffer where my Message to be sent is
short RequestSize, //size of the above buffer. sizeof(Message)
byte[] RequestOptions, //OPTIONAL!! Can set this to NULL
Pointer ReplyBuffer, //Pointer to the buffer where the replied echo is written to
int ReplySize, //size of the above buffer. Normally its set to the sizeof(ICMP_ECHO_REPLY), but arbitrarily set it to 256 bytes
int Timeout); //time, as int, for timeout
HANDLE IcmpCreateFile(); //win32 ICMP Handle creator
boolean IcmpCloseHandle(HANDLE IcmpHandle); //win32 ICMP Handle destroyer
}
And then using those to create the following method...
public void SendReply(String ipAddress) {
final IcmpEcho icmpecho = IcmpEcho.INSTANCE;
final InetAddr inetAddr = InetAddr.INSTANCE;
HANDLE icmpHandle = icmpecho.IcmpCreateFile();
byte[] message = new String("thisIsMyMessage!".toCharArray()).getBytes();
Memory messageData = new Memory(32); //In C/C++ this would be: void *messageData = (void*) malloc(message.length);
messageData.write(0, message, 0, message.length); //but ignored the length and set it to 32 bytes instead for now
Pointer requestData = messageData;
Pointer replyBuffer = new Memory(256);
replyBuffer.clear(256);
// HERE IS THE NATIVE CALL!!
reply = icmpecho.IcmpSendEcho(icmpHandle,
inetAddr.inet_addr(ipAddress),
requestData,
(short) 32,
null,
replyBuffer,
256,
timeout);
// NATIVE CALL DONE, CHECK REPLY!!
icmpecho.IcmpCloseHandle(icmpHandle);
}
public boolean IsReachable () {
return (reply > 0);
}
My guess is that your iteration logic to determine the different ip address is based upon different configuration hence your pc's fetches all addresses but your webserver doesn't.
Try adding debug in the logic where you build up the list of ip adresses to check.

SMSLib doesn't receive sms [java edition]

i am trying to use my mobile phone as GSM modem.i use SMSLib for sending and receiving SMS with this modem.
the problem is that when my phone(GSM modem) receive a sms i don't notify with SMSLib.but the code overall is good for example that notifies me when GSM modem receive a call.
my code has not any bug because i only use SMSLib example code for receiving message.
the SMSLib example code is :
public class TestSinaRec
{
public void doIt() throws Exception
{
// Define a list which will hold the read messages.
List<InboundMessage> msgList;
// Create the notification callback method for inbound & status report
// messages.
InboundNotification inboundNotification = new InboundNotification();
// Create the notification callback method for inbound voice calls.
CallNotification callNotification = new CallNotification();
//Create the notification callback method for gateway statuses.
GatewayStatusNotification statusNotification = new GatewayStatusNotification();
OrphanedMessageNotification orphanedMessageNotification = new OrphanedMessageNotification();
try
{
System.out.println("Example: Read messages from a serial gsm modem.");
System.out.println(Library.getLibraryDescription());
System.out.println("Version: " + Library.getLibraryVersion());
// Create the Gateway representing the serial GSM modem.
SerialModemGateway gateway = new SerialModemGateway("modem.com4", "COM4", 115200, "Nokia", " 6303i");
// Set the modem protocol to PDU (alternative is TEXT). PDU is the default, anyway...
gateway.setProtocol(Protocols.PDU);
// Do we want the Gateway to be used for Inbound messages?
gateway.setInbound(true);
// Do we want the Gateway to be used for Outbound messages?
gateway.setOutbound(true);
// Let SMSLib know which is the SIM PIN.
gateway.setSimPin("0444");
// Set up the notification methods.
Service.getInstance().setInboundMessageNotification(inboundNotification);
Service.getInstance().setCallNotification(callNotification);
Service.getInstance().setGatewayStatusNotification(statusNotification);
Service.getInstance().setOrphanedMessageNotification(orphanedMessageNotification);
// Add the Gateway to the Service object.
Service.getInstance().addGateway(gateway);
// Similarly, you may define as many Gateway objects, representing
// various GSM modems, add them in the Service object and control all of them.
// Start! (i.e. connect to all defined Gateways)
Service.getInstance().startService();
// Printout some general information about the modem.
System.out.println();
System.out.println("Modem Information:");
System.out.println(" Manufacturer: " + gateway.getManufacturer());
System.out.println(" Model: " + gateway.getModel());
System.out.println(" Serial No: " + gateway.getSerialNo());
System.out.println(" SIM IMSI: " + gateway.getImsi());
System.out.println(" Signal Level: " + gateway.getSignalLevel() + " dBm");
System.out.println(" Battery Level: " + gateway.getBatteryLevel() + "%");
System.out.println();
// In case you work with encrypted messages, its a good time to declare your keys.
// Create a new AES Key with a known key value.
// Register it in KeyManager in order to keep it active. SMSLib will then automatically
// encrypt / decrypt all messages send to / received from this number.
//Service.getInstance().getKeyManager().registerKey("+306948494037", new AESKey(new SecretKeySpec("0011223344556677".getBytes(), "AES")));
// Read Messages. The reading is done via the Service object and
// affects all Gateway objects defined. This can also be more directed to a specific
// Gateway - look the JavaDocs for information on the Service method calls.
msgList = new ArrayList<InboundMessage>();
Service.getInstance().readMessages(msgList, MessageClasses.ALL);
for (InboundMessage msg : msgList)
System.out.println(msg);
// Sleep now. Emulate real world situation and give a chance to the notifications
// methods to be called in the event of message or voice call reception.
System.out.println("Now Sleeping - Hit <enter> to stop service.");
System.in.read();
System.in.read();
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
Service.getInstance().stopService();
}
}
public class InboundNotification implements IInboundMessageNotification
{
public void process(AGateway gateway, MessageTypes msgType, InboundMessage msg)
{
if (msgType == MessageTypes.INBOUND) System.out.println(">>> New Inbound message detected from Gateway: " + gateway.getGatewayId());
else if (msgType == MessageTypes.STATUSREPORT) System.out.println(">>> New Inbound Status Report message detected from Gateway: " + gateway.getGatewayId());
System.out.println(msg);
}
}
public class CallNotification implements ICallNotification
{
public void process(AGateway gateway, String callerId)
{
System.out.println(">>> New call detected from Gateway: " + gateway.getGatewayId() + " : " + callerId);
}
}
public class GatewayStatusNotification implements IGatewayStatusNotification
{
public void process(AGateway gateway, GatewayStatuses oldStatus, GatewayStatuses newStatus)
{
System.out.println(">>> Gateway Status change for " + gateway.getGatewayId() + ", OLD: " + oldStatus + " -> NEW: " + newStatus);
}
}
public class OrphanedMessageNotification implements IOrphanedMessageNotification
{
public boolean process(AGateway gateway, InboundMessage msg)
{
System.out.println(">>> Orphaned message part detected from " + gateway.getGatewayId());
System.out.println(msg);
// Since we are just testing, return FALSE and keep the orphaned message part.
return false;
}
}
public static void main(String args[])
{
TestSinaRec app = new TestSinaRec();
try
{
app.doIt();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
program output is for example :
Gateway Status change for modem.com4, OLD: STOPPED -> NEW: STARTING
Gateway Status change for modem.com4, OLD: STARTING -> NEW: STARTED
Modem Information: Manufacturer: Nokia Model: Nokia 6303i classic
Serial No: 355382041051833 SIM IMSI: ** MASKED ** Signal Level:
-57 dBm Battery Level: 91%
Now Sleeping - Hit to stop service.
New call detected from Gateway: modem.com4 : +989111007483
New call detected from Gateway: modem.com4 : +989111007483
when i searched for this issue i found this :
The correct operation of this method depends on the unsolicited modem
indications and on the correct operation of the CNMI command. If you
see that you are failing to receive messages using a callback method,
probably the modem indications have not been setup correctly.
so i changed my phone(my GSM modem) with Nokia 6303i rather than Nokia 5200 that i used first but the problem didn't solve.
so now i really don't know the problem will solve with choosing another phones ?! or i should search for a better and more reasonable solution.
thank you for any bit of help for solving this problem.
Well the only thing I can think of is that you're starting the Service and then sending the SMS to the modem. Because of this, this line won't be called: Service.getInstance().readMessages(msgList, MessageClasses.ALL);. However, you should still get the notification that a new message has arrived at the modem.
Try implementing the InboundNotification to fetch the messages when it senses any new messages on the modem. Do this by overriding the process() method.
However, it might also be due to the fact that you're actually pressing <Enter> too soon. As the comment say; you have to wait go give the notifications method a chance to be called.
Sometimes it's just something as silly as that. Let me know if any of it helped or if I completely misunderstood your problem. I'm working on a multi-modem gateway myself, so I'd be happy to help.
i had an issue with a GT-I9000 he received the inbound alert but couldn't fetch it the right sms object, i think this is a matter of the Storage Location,
i tried with another phone (Samsung GT-S5670 Android) of a friend of mine who had some messages stored on the SIM Card Memory, the smslibrary was notified and the ReadMessages Class logged all the messages.
so i think you need to find somehow to change storage location on the ReadMessages.java or find an compatible phone that can stores the sms to Sim Card instead of the phone memory.
hope this help.
The problem was with my phone.Smslib doesn't work in listening sms for a variety of phones(including smartphones,most of Nokia phones,etc.).I didn't check but probably this problem will be solved if you use a dedicated GSM modem(like huawei GSM modems)

How to read and write data to COM/Serial ports in Android? [duplicate]

This question already has answers here:
using serial port RS-232 in android?
(8 answers)
Closed 2 years ago.
I have to read and write data to the COM ports of a device using Android. I am using javax.comm package for that, but when I installed the apk file, it is not displaying any ports of the device. Is there any permission which I need to add in the manifest file?
Your problem is one with operating systems. Android runs Linux under the hood, and Linux treats serial ports differently than Windows does. javax.comm also contains win32com.dll, a driver file, which you won't be able to install on an Android device. If you do find a way to achieve what you're trying to do, you can't actually look for a "COM" port in a Linux environment. The serial ports will go by different names.
Windows Com Port Linux equivalent
COM 1 /dev/ttyS0
COM 2 /dev/ttyS1
COM 3 /dev/ttyS2
So, hypothetically, if your idea were to work, you have to look for these names.
Luckily for you, Android does have provisions for interfacing with USB devices (Which I assume you want to connect to, as opposed to parallel or RS-232 ports). To do this, you will set up your device as a USB Host. Here's what you'll want to do:
Get a USBManager.
Find your device.
Get the USBInterface and USBEndpoint.
Open a connection.
Transfer data.
Here's my rough estimate of how you'll do it. Your code will, of course, have a more mature way of doing things.
String YOUR_DEVICE_NAME;
byte[] DATA;
int TIMEOUT;
USBManager manager = getApplicationContext().getSystemService(Context.USB_SERVICE);
Map<String, USBDevice> devices = manager.getDeviceList();
USBDevice mDevice = devices.get(YOUR_DEVICE_NAME);
USBDeviceConnection connection = manager.openDevice(mDevice);
USBEndpoint endpoint = device.getInterface(0).getEndpoint(0);
connection.claimInterface(device.getInterface(0), true);
connection.bulkTransfer(endpoint, DATA, DATA.length, TIMEOUT);
Extra material for your reading pleasure: http://developer.android.com/guide/topics/connectivity/usb/host.html
I am no expert, but for all those who are looking to connect serial RS-232 ports or open a serial port and can't find their device trough the UsbManager, you can find all your devices using an approach like this:
mDrivers = new Vector<Driver>();
LineNumberReader r = new LineNumberReader(new FileReader("/proc/tty/drivers"));
String l;
while ((l = r.readLine()) != null) {
String drivername = l.substring(0, 0x15).trim();
String[] w = l.split(" +");
if ((w.length >= 5) && (w[w.length - 1].equals("serial"))) {
mDrivers.add(new Driver(drivername, w[w.length - 4]));
}
}
After finding all drivers, iterate trough all the drivers to get all of your devices, using something like this:
mDevices = new Vector<File>();
File dev = new File("/dev");
File[] files = dev.listFiles();
if (files != null) {
int i;
for (i = 0; i < files.length; i++) {
if (files[i].getAbsolutePath().startsWith(mDeviceRoot)) {
Log.d(TAG, "Found new device: " + files[i]);
mDevices.add(files[i]);
}
}
}
Here is the Driver class constructor, with two member variables:
public Driver(String name, String root) {
mDriverName = name;
mDeviceRoot = root;
}
For opening a serial port you can use the Android SerialPort API. Simply open the serial port at your device and write. (You must know your device path and baud rate. For example, my device is ttyMt2 with baud Rate 96000.)
int baudRate = Integer.parseInt("96000");
mSerialPort = new SerialPort(mDevice.getPath(), baudRate, 0);
mOutputStream = mSerialPort.getOutputStream();
byte[] bytes = hexStr2bytes("31CE");
mOutputStream.write(bytes);
Instead of wasting time on this code, you can download the complete project from https://github.com/licheedev/Android-SerialPort-Tool.

Java MIDI Synthesizer - Can't change instruments

I can't seem to get the instrument to change. I switch the value of the instrument but get nothing different on the output. I can only get a piano instrument to play no matter what value I try. Here is the simple code below. Does anyone have any suggestions? Or am I missing a fundamental of the instrument object?
import javax.sound.midi.*;
//import javax.sound.*;
public class Drum {
static int instrument = 45;
static int note = 100;
static int timbre = 0;
static int force = 100;
public static void main(String[] args) {
Synthesizer synth = null;
try {
synth = MidiSystem.getSynthesizer();
synth.open();
}
catch (Exception e) {
System.out.println(e);
}
Soundbank soundbank = synth.getDefaultSoundbank();
Instrument[] instr = soundbank.getInstruments();
synth.loadInstrument(instr[instrument]); //Changing this int (instrument) does nothing
MidiChannel[] mc = synth.getChannels();
mc[4].noteOn(note, force);
try { Thread.sleep(1000); }
catch(InterruptedException e) {}
System.out.println(instr[instrument].getName());
synth.close();
}
}
You need to tell the channel to use the instrument. I admit I've never used MIDI in Java, but something like mc.programChange(instr.getPatch().getProgram()) sounds promising.
To play the percussion instruments you have to use the channel 10, that channel is used only for percussion instruments. (http://en.wikipedia.org/wiki/General_MIDI)
For example:
int instrument = 36;
Sequence sequence = new Sequence(Sequence.PPQ, 1);
Track track = sequence.createTrack();
ShortMessage sm = new ShortMessage( );
sm.setMessage(ShortMessage.PROGRAM_CHANGE, 9, instrument, 0); //9 ==> is the channel 10.
track.add(new MidiEvent(sm, 0));
then every note you add it will sound with percussion.
You need to send a program change event to the sequencer. How? Send a short message.
sound.setMessage(ShortMessage.PROGRAM_CHANGE, channel, instrument, channel);
long timeStam1p = -1;
Receiver rcv1r = MidiSystem.getReceiver();
rcv1r.send(sound, timeStam1p);
sound.setMessage(ShortMessage.NOTE_ON, channel, note, velocity);
long timeStamp = -1;
Receiver rcvr = MidiSystem.getReceiver();
rcvr.send(sound, timeStamp);
Variables are channel (int) note (int), instrument (int), velocity (int).
Also, I suggest to learn midi events. Events are how a midi plays notes, stops notes, change instruments, tempo change, control changes, etc. I spent 2 years using a midi program.

Categories

Resources