MidiSystem.start() makes no sound - java

Im new to java and im creating a test application demonstrating creating sounds. i have this test code:
public class MiniMiniMusicApp {
public MiniMiniMusicApp(){
}
public void play(){
try{
Sequencer player = MidiSystem.getSequencer();
player.open();
Sequence seq = new Sequence(Sequence.PPQ, 4);
Track track = seq.createTrack();
ShortMessage a = new ShortMessage();
a.setMessage(144,1,20,100);
MidiEvent noteOn = new MidiEvent(a, 1);
track.add(noteOn);
ShortMessage b = new ShortMessage();
a.setMessage(128, 1, 44, 100);
MidiEvent noteOff = new MidiEvent(b, 3);
track.add(noteOn);
Track[] t = seq.getTracks();
player.setSequence(seq);
player.start();
System.out.println("Done");
}
catch (Exception ex){
System.out.println("Ooops something went wrong");
ex.printStackTrace();
}
}
}
and i can hear no sound. I've read somewhere that i need a soundbank, so i downloaded the deluxe version from here and i have copied it into C:\Program File\Java\jdk1.7.0_45\jre\lib created a folder called audio and copied soundbank.gm in there. What am i missing here?

I don't have enough rep to comment on the question - but do you mean to have this line
track.add(noteOn);
in there twice?
Also you call
a.setMessage(...)
twice.
There's a couple of other strange things going on, creating an array that's never used etc.
I suggest cleaning up your code a little.

Related

Track fast moving fiducial using BoofCV

I am trying to track a person's head with a binary fiducial printed. It can track fine when the person is moving slowly, but when they move their head quickly, it loses the track and then regains it when they stop moving. What can I do to track the person while they are moving quickly?
For reference, here is a screenshot and code:
camera = UtilWebcamCapture.openDefault(1920, 1080);
intrinsicParameters = new IntrinsicParameters();
intrinsicParameters.setCx(camera.getViewSize().getWidth()/2f);
intrinsicParameters.setCy(camera.getViewSize().getHeight()/2f);
intrinsicParameters.setFx(1);
intrinsicParameters.setFy(1);
intrinsicParameters.setWidth((int)camera.getViewSize().getWidth());
intrinsicParameters.setHeight((int)camera.getViewSize().getHeight());
detector = FactoryFiducial.squareBinary(
new ConfigFiducialBinary(1),
ConfigThreshold.local(ThresholdType.LOCAL_SQUARE, 10),
//ConfigThreshold.fixed(100),
GrayU8.class);
detector.setIntrinsic(intrinsicParameters);
...
while (true) {
BufferedImage image = camera.getImage();
GrayU8 input = ConvertBufferedImage.convertFrom(image, (GrayU8) null);
WorldToCameraToPixel transform;
try {
detector.detect(input);
Se3_F64 targetToSensor = new Se3_F64();
for (int i = 0; i < detector.totalFound(); i++) {
detector.getFiducialToCamera(i, targetToSensor);
transform = PerspectiveOps.createWorldToPixel(intrinsicParameters, targetToSensor);
Point2D_F64 centre = transform.transform(
new Point3D_F64(0, 0, 0));
System.out.println(centre);
}
} catch (Exception e) {
e.printStackTrace();
}
}
Thanks!
I solved this issue by creating an object tracker using the initial location of the fiducial, and using that when the user moves quickly.

InvalidMidiDataException: command out of range

I have this app from Head First Java
import javax.sound.midi.*;
public class MiniMiniMusicApp{
public static void main(String[] args){
MiniMiniMusicApp mini = new MiniMiniMusicApp();
mini.play();
}
public void play(){
try{
Sequencer player = MidiSystem.getSequencer();
player.open();
Sequence seq = new Sequence(Sequence.PPQ,4);
Track track = seq.createTrack();
ShortMessage a = new ShortMessage();
a.setMessage(114,1,44,100);
MidiEvent noteOn = new MidiEvent(a,1);
track.add(noteOn);
ShortMessage b = new ShortMessage();
b.setMessage(128,1,44,100);
MidiEvent noteOff = new MidiEvent(b,16);
track.add(noteOff);
player.setSequence(seq);
player.start();
} catch(Exception ex){
ex.printStackTrace();
System.out.println("damn");
}
}
}
And this throws the following exception at runtime
javax.sound.midi.InvalidMidiDataException: command out of range: 0x72
at javax.sound.midi.ShortMessage.setMessage(ShortMessage.java:280)
at MiniMiniMusicApp.play(MiniMiniMusicApp.java:15)
at MiniMiniMusicApp.main(MiniMiniMusicApp.java:6)
I read some docs on setMessage and it seems the exception is thrown when you pass an invalid MidiMessage but I'm simply following the example from the book. I've read on other forums and it appears that this code works for other people.
Any idea on what is causing the issue? Can you try running this on your end and see if it works? At least that'll tell me if it's something on my environment.
You probably want to send a NoteOn message (144, not 114). The class ShortMessage contains constants which prevent such mistakes. You could use it like this:
import static javax.sound.midi.ShortMessage.*;
a.setMessage(NOTE_ON, 1, 44, 100);
Such code is probably easier to read for most people than directly using the numbers.
Figured it out
a.setMessage(114,1,44,100);
should be
a.setMessage(144,1,44,100);

Unable to get terrain loaded with PhysicsEditor-Extension to collide

For my android game, based around AndEngine, I am currently working on loading levels.
I came across AndEngine-PhysicsEditor-Extension, which loads an XML and graphics exported by PhysicsEditor.
I am now working on creating a class, conveniently named MapLoader, which takes a map name and calls the PhysicsEditor Extension to load the appropriate files and register them. The problem is that while the graphics are displayed as intended, anything else in the scene pass right through it without colliding.
Here's how the MapLoader is invoked:
MapLoader loader = new MapLoader(this, engine, world); // (Context, PhysicsWorld, Scene)
loader.loadMap("testmap1");
And here's the important bits of the MapLoader class:
// Constructor
public void loadMap(String mapName) {
this.atlas = new BitmapTextureAtlas(game.getTextureManager(), 2048, 1024, TextureOptions.BILINEAR);
atlas.load();
PhysicsEditorLoader loader = new PhysicsEditorLoader();
this.tMap = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.atlas, game, "maps/" + mapName + ".png", 0, 0);
this.sMap = new Sprite(0, 500, this.tMap, game.getVertexBufferObjectManager());
this.world.attachChild(sMap);
try {
loader.load(game, engine, "maps/" + mapName + ".xml", sMap, true, true);
} catch (IOException e) {
e.printStackTrace();
System.out.println("XML load failure");
}
this.sMap = new Sprite(0, 0, this.tMap, game.getVertexBufferObjectManager());
world.attachChild(sMap);
world.registerUpdateHandler(engine);
}
// .......Snip...........
// loadMap method
public void loadMap(String mapName) {
this.atlas = new BitmapTextureAtlas(game.getTextureManager(), 2048, 1024, TextureOptions.BILINEAR);
atlas.load();
final PhysicsEditorLoader loader = new PhysicsEditorLoader();
this.tMap = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.atlas, game, "maps/" + mapName + ".png", 0, 0);
this.sMap = new Sprite(0, 500, this.tMap, game.getVertexBufferObjectManager());
this.world.attachChild(sMap);
try {
loader.load(game, engine, "maps/" + mapName + ".xml", sMap, true, true);
} catch (IOException e) {
e.printStackTrace();
}
this.sMap = new Sprite(0, 0, this.tMap, game.getVertexBufferObjectManager());
world.attachChild(sMap);
world.registerUpdateHandler(engine);
}
Did i miss something? I based the above code on the example.
I've tried editing the source to point to a non-existing directory for the XML loading, after which it started complaining, indicating that the XML is found.
Edit: In case something inherently wrong with the XML is suspected, I've uploaded it for inspection here. It was created in PhysicsEditor by adding sprite, using the shape tracer to get the outline, and export as AndEngine exporter. The XML is stored in assets/maps/ with the associated sprite stored in assets/gfx/maps/
PS: Until i get this test working I'm using the trial version of PhysicsEditor. I do not believe it affects the outcome.

Head First Java - creating the first music player error

I am having trouble with creating a very small music player following the HeadFirstJava recipe. I followed the code in the book but it still has some bugs... When I first compiled it it gave me this error:
Dez 15, 2013 4:13:02 PM java.util.prefs.WindowsPreferences
WARNING: Could not open/create prefs root node Software\JavaSoft\Prefs at root 0x80000002. Windows RegCreateKeyEx(...) returned error code 5.
After googling the error I found out that I should create HKEY_LOCAL_MACHINE\Software\JavaSoft\Prefs and also give full permision for JavaSoft on regedit. That did solve the problem but only partially. The code compliles, the sound is made by the computer but the program will not close util I hit CTRL + C. Here is the code:
import javax.sound.midi.*;//importam pachetul sound.mini
public class MiniMiniMusicApp {
public static void main (String [] args) {
MiniMiniMusicApp mini = new MiniMiniMusicApp();
mini.play();
} //inchidem main
public void play() {
try {
Sequencer player = MidiSystem.getSequencer();
player.open();
Sequence seq = new Sequence(Sequence.PPQ, 4);
Track track = seq.createTrack();
//ShortMessage first = new ShortMessage();
//first.setMessage(192, 1, 102, 0);
//MidiEvent noteOn1 = new MidiEvent(first, 1);
//track.add(noteOn1);
ShortMessage a = new ShortMessage();
a.setMessage(144, 1, 44, 100);
MidiEvent noteOn = new MidiEvent(a, 1);
track.add(noteOn);
ShortMessage b = new ShortMessage();
b.setMessage(128, 1, 44, 100);
MidiEvent noteOff = new MidiEvent(b, 16);
track.add(noteOff);
player.setSequence(seq);
player.start();
} catch (Exception ex) {
ex.printStackTrace();
}
} //inchidem play
}
I would like to mention that I am not using any GUI and that I am a total novice. Any help would be appreciated. Thank you.
The MIDI sequencer is a special thread that runs in the background. As long as it is active (or, in fact, any non-daemon thread is active), Java will not exit on its own.
Try adding this after the player.start(); line:
Thread.sleep(5000);
player.close();
Command Prompt doesn't support the multi-programming. So when you run the above program, the program is in the running state, after it's play() method and wait for the some event to occur(like another Framed based program in java).
you can write System.exit() after putting some delay(so that your voice would come). Currently you are killing the process from the DOS.
The docs [MidiDevice.open()] for player.open() says:
An application opening a device explicitly with this call has to close the device by calling close. This is necessary to release system resources and allow applications to exit cleanly.
So you may use a try-with-resource-statement (Java 7+) to close it safely and wait gracefully (at the end of your try-block) for your track to finish:
try (Sequencer player = MidiSystem.getSequencer()) {
...
while (player.isRunning()) {
Thread.sleep(100);
}
} catch (Exception ex) {
ex.printStackTrace();
}
Prior to Java 7 you would have called player.close(); in a finally-block attached to your try-catch-statement.
Note: The access warning for the root users Preferences could have been suppressed by:
PlatformLogger.getLogger("java.util.prefs")
.setLevel(PlatformLogger.Level.SEVERE);
To solve the first error, just run your compiler as administrator.

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