JavaX MIDI - Play MIDI file with custom soundfont - java

I was trying to implement a MIDI player for a java program. So I started using the javax.sound.midi library. I load my Sequencer and my Synthesizer there:
private void playMidiFile() {
Soundbank soundfont = MidiSystem.getSoundbank(Util.internalFile("FluidR3_GM.sf2").getInputStream());
Sequencer sequencer = MidiSystem.getSequencer();
Synthesizer synthesizer = MidiSystem.getSynthesizer();
sequencer.open();
synthesizer.open();
synthesizer.loadAllInstruments(soundfont);
sequencer.getTransmitter().setReceiver(synthesizer.getReceiver());
sequencer.setSequence(Util.internalFile("MyMusic.mid").getInputStream());
sequencer.start();
}
The first second I can clearly hear my loaded soundfont, but after that somehow the midi is played back with a standard soundfont. I checked and the SF2 file is supported by the javax.sound.midi library (synthesizer.isSoundBankSupported(soundfont) returns true).
Does anybody know why my program behaves like this?

Closing all the transmitters solves the standard font being played, but an easier way to do solve the issue is to create a sequencer without any transmitters:
Sequencer sequencer = MidiSystem.getSequencer(false);
Connecting the custom synthesizer to a sequencer created in this way would only produce the customs sounds.

You may have more transmitters still on your sequencer. I ran into that stupid problem, too. Then I came up with this:
for(Transmitter tm: sequencer.getTransmitters())
{
tm.close();
}
sequencer.getTransmitter().setReceiver(synthesizer.getReceiver());
I've only just started playing around with Java altogether, let alone Midi. Seems like few people go there to begin with. I wished there were more...
Anyway, it did the trick for me... hope it helps you, too!

Related

Java jlayer on RasberryPi

I am making a music player for rasberry pi. There is a hifiberry module connected to it. I am using a jlayer library for playing music. When i run the code on my PC (Ubuntu) it works fine, but when i try to run it on the rasberry, i dont get any error, but there is no sound playing. I tried reinstalling java. It does not work even without the module.
I am using this piece of code:
public class Main {
public static void main(String[] args) {
AdvancedPlayer player = new AdvancedPlayer(new FileInputStream(args[0]));
player.play();
}
}
Is there any solution for this? or can u suggest any library that could work, which supports mp3 files?
Somehow the audio was streaming to bad output, and i could not find a way to change the output port, so i used a mp3spi library, which i managed to get working.

Java Midi default soundbank playing at the same time as the new one

I'm loading a Soundbank of a TR-808 into Java and want to play that kit - the problem is I can't disable the default soundbank from playing along with the drums.
Everything works when just using the GM sounds, but when loading a SoundBank everything gets mashed together.
player = MidiSystem.getSequencer();
player.open();
seqTrans = player.getTransmitter();
synth = MidiSystem.getSynthesizer();
synthRcvr = synth.getReceiver();
seqTrans.setReceiver(synthRcvr);
synth.open();
File file = new File("resources/TR-808.sf2");
Soundbank soundbank = MidiSystem.getSoundbank(file);
// synth.unloadAllInstruments(synth.getDefaultSoundbank()); don't work:(
synth.loadAllInstruments(soundbank);
Sequence seq = new Sequence(Sequence.PPQ, 4);
Track track = seq.createTrack();
ShortMessage instr = new ShortMessage();
instr.setMessage(192, channel, 35, 0);
MidiEvent changeInstrument = new MidiEvent(instr, 1);
track.add(changeInstrument);
for(int i = 1; i < 30; i++){
ShortMessage a = new ShortMessage();
a.setMessage(144, channel, 35, 100);
MidiEvent noteOn = new MidiEvent(a, 4+4*i);
track.add(noteOn);
}
Anything look off here?
EDIT
I just found this, apparently I'm not the only one with this problem:
A guy writes
Someone here seems to have had the same problem, with the default soundbank playing at the same time as the new one:
http://forums.sun.com/thread.jspa?threadID=5182082.
Their "solved" reply doesn't give much info though. Something to do with the location of their new soundbank's .gm file.
Sadly, the link to Sun's forum doesn't work anymore (I'm looking at you, Oracle!) and the post is from 2009, so it's quite old in Internet years and I would've hoped this issue has been resolved - sadly it hasn't, it would seem.
I switched to using the Beads Project (http://beadsproject.net) and they also offer Midi support. I have the audio samples working perfectly (so much better than Java Audio!) and will try my luck with their Midi implementation in the near(-ish) future. If anyone's interested, I can post updates to this question as soon as I get results.
According to the Javadocs, this is expected behaviour of the sequencer.
When calling:
MidiSystem.getSequencer()
Java will connect this sequencer instance with the default synthesizer. This is will output sound using the low-res default soundfonts. When you connect your custom synthesizer to the sequencer, the sequencer will send the sounds to both the default synthesizer and your custom one, creating two sounds.
On the other hand, when calling:
MidiSystem.getSequencer(false)
Java creates a sequencer that is not connected to any synthesizer. By default this sequencer would output no sound. Connecting it to the custom synthesizer that you create will only output the sounds from the loaded instruments.

JFugue 5.0.4 loading Synthesizer does not work

I was doing some really cool stuff with JFugue 4.0.3 when 5 came and I noticed it came with lots of new features.
Now trying to move some code to jfugue 5.0.4 I see that my external soundfont is not being loaded, even when trying it in the new way (using the SynthesizerManager). From what I have read, on using the setSynthesizer method from SynthesizerManager all players would have that Synthesizer loaded by default, but I only hear the default piano sounds. I tested loading the Synthesizer alone and listing the instruments and it works, so I guess the problem is having the SynthesizerManager set the correct Synthesizer to players.
Soundbank coolGuitars = MidiSystem.getSoundbank(new File("/music/guitar.sf2"));
Synthesizer synt = MidiSystem.getSynthesizer();
synt.open();
synt.loadAllInstruments(coolGuitars);
SynthesizerManager s = SynthesizerManager.getInstance();
s.setSynthesizer(synt);
Player player = new Player();
Pattern pattern = new Pattern("C+E+G D+F+A E+G+B F+A+C G+B+D A+C+E B+D+F");
pattern.setInstrument(0);
player.play(pattern);
Thanks in advance for your help!

How to interface Java midi to other applications

Hi I am programming Java on Windows and am very new to working with MIDI interfaces.
I have managed to get java to play midi sounds through Synthesizer objects, natively through the computers speaker however I wish to send midi messages on the fly to a separate synthesis application, namely FLStudio. I think I have to make the java interface look like a hardware midi device but I have no idea how to do this. I also think it may have something to do with Transmitter or MidiDevice but i'm not sure.
Does anyone know how I would begin to go about this. I have looked all over Google about this but always end up at the same 2 documents,
http://www.jsresources.org/faq_midi.html
and
http://www.ibm.com/developerworks/library/it/it-0801art38/
Sorry if this question has been asked before but i couldn't find it.
Here's what I have so far. Any help would be greatly appreciated.
import javax.sound.midi.*;
public class Midi
{
public static final void main(String args[]) throws Exception
{
//create and open synthesizer
Synthesizer syn = MidiSystem.getSynthesizer();
syn.open();
//open midi channels (we'll use channel 5)
final MidiChannel[] mc = syn.getChannels();
//set instruments
Instrument[] instr = syn.getDefaultSoundbank().getInstruments();
//Possible ways to send midi to FLStudio, rather than inbuilt
//javax.sound.midi.Transmitter?
//javax.sound.midi.MidiDevice?
// change instrument, using midi codes
mc[5].programChange(instr[0].getPatch().getProgram());
// Play note
mc[5].noteOn(50,1000); //(noteNumber, velocity)
}
}
You can use a program like MidiOx to create a virtual MIDI endpoint which you can send MIDI messages to. Then, in your sequencer, you just tell it to accept MIDI messages from the output of that device, and you can use it as a passthru pipe.

Why doesn't Java play sounds over Bluetooth headset?

So on my machine I have Bluetooth working fine, I can stream audio to it and record from it, except when I run a Java program that has sound. The sound files work through regular speakers but they don't get forwarded to the headset. My current operating System is Lubuntu 10.04.
My code to play a sound is:
public static void playSound(File sound) {
try {
AudioClip cp = Applet.newAudioClip(sound.toURL());
cp.play();
} catch (MalformedURLException ex) {
ex.printStackTrace();
}
}
The Applet.newAudioClip() method is pretty darn old. Like Java 1.0 old. Since then Java has rewritten a lot of it's sound APIs. I bet whatever code is playing that sound doesn't take into account the various audio settings of the OS. The javax.sound.sampled package has the new APIs, and while they are harder to learn, they give you much more control over how the sound is played and modified.
http://download.oracle.com/javase/tutorial/sound/sampled-overview.html
You could test out to see if Java can play that audio over your bluetooth by downloading
http://www.javazoom.net/index.shtml
And try playing an MP3 see if that goes over your bluetooth headset.

Categories

Resources