What is Synthesizer and Sequencer(javax.sound.midi) in Java? - java

I want to know the Actual Work of Synthesizer and Sequencer or what did they acually do?

A synthesizer is a component that converts MIDI messages into actual sounds.
A sequencer handles the timing of MIDI messages, i.e., it allows to record MIDI messages together with their time stamps, and allows to later play them back (i.e., to send them to some other device) with the same timing.

Related

MIDI Sequencer stop without flushing

For a project I am working on I need to pause the midi sequencer and I want all the sounding notes to sustain and thus make those notes endless. The problem I am facing is that sequencer.stop() apparently not only stops the playback, but also sends MIDI note off messages to all sounding notes, terminating all sounding notes (in some literature refered to as flushing).
I have tried to use sequencer.setTempoInBPM(0) and that gets the job done, but has other unwanted side-effects specific to my project.
The most obvious solution then seems overriding Sequencer.stop(), but how do I do that? And how exactly will that overridden method look like?
Edit:
I would like to edit the question in response to the comment of gpasch.
not only stops the playback, but also sends MIDI note off messages to
all sounding notes: what are you talking about?? isnt this the same
thing??
That is true for audio, but that is not true for MIDI. The MIDI protocol doesnt specify any audio data by itself. It only gives instructions to a musical instruments on what to play. The instrument interprets the MIDI messages and makes the final sound.
In order to let an instrument play a sound of one second, this are the actions:
[Sequencer] MIDI Message Out: note on
[Instrument] MIDI Message In: note on
[Instrument] Starts interpreting note on: starts producing sound
[Sequencer] Waits one second
[Sequencer] MIDI Message Out: note off
[Instrument] MIDI Message In: note off
[Instrument] Starts interpreting note off: stops producing sound
So, if this process gets interrupted on step 4, it would create an "endless note". Because the MIDI instrument got instructions to begin playing a certain note, but never got an instruction to stop playing that note. [*]
Looking back to my question. When I call sequencer.stop() in the middle of a note (step 4), instead of having an "endless note", all notes that are being played on that moment that did not yet have got an note off message, stop sounding. The logical explenation for that, is that sequencer.stop() sends a MIDI All Note Off message under the hood. We can be really thankfull for that, because otherwhise sequencer.stop() would be a real mess. In my particular case though I really need the sequencer to not send the note off message. So the question is: can I make a workaround for that?
*
If it is a piano sound with a natural decay of the sound, the sound will eventually die. But with a synth sound the sound will persist till there has been
The way I would do it is. Create a filter which would basically receive everything sent from the sequencer and send it to your midi out. Inside this filter create a condition where if the "pause flag" is true all note offs would be received but not sent.
Create a pause() method which when called first sets your "pause flag" to true and then does sequencer.stop().
Of course you would need some way to keep track of the note offs that have been blocked so that you can actually stop them when you eventually do want to or else they will really stay on for ever.

Sending pitch bend to MIDI sequencer in Java

I understand the basics of getting a MIDI sequencer up and running and I would like to be able to increase/decrease the pitch of the sequence during playback, but pitch bend is a message that gets sent to the synthesizer, not the sequencer.
I tried setting the sequencer's receiver to be the synthesizer's transmitter, and when I sent pitch-bend short messages, the sequencer stayed the same pitch but then the synthesizer played a second track at the new pitch bend value, creating some pretty awful-sounding music.
Is there a good way of bending pitch during playback like there is for changing tempo?
Another option (which seems like a big kluge) is to have a few versions of the MIDI files in different keys ready to load when called.
You could try to send the messages directly to the synthesizer's receiver by calling its send method, but the synthesizer might not allow its receivers to influence each other.
Ultimately, the messages sent to the synthesizer are stored in the sequencer's track, so to have pitch-bend messages, edit the sequence to add those messages.
The MIDI protocol doesn't define any standards for pitch, except for pitch bend which is generally intended to be used as a temporary effect rather than a way of setting the arrangement's tuning. It sounds like you are implementing a sequencer in Java, in which case I would rather suggest having a global detune preference. Then you would simply render the audio with the default tuning (440Hz) and then apply pitchbend to the bounced arrangement. There are several libraries which can do pitchbend for you, including the excellent DIRAC.

Hardware MIDI Out for Playback in Java?

I am making a simple application to playback MIDI files in Java.
I am using the javax.sound.midi library.
I can retrieve my MIDI Out Device correctly (USB to MIDI Cable).
But when I playback the sequence it always plays in the default sound synthesizer which is the host OS's General Midi (Soundfont) playback.
The problem I am having is changing the default MIDI Out.
When I execute
Receiver MidiOutReceiver; //instantiated earlier
Sequencer MidiOutSequencer = MidiSystem.getSequencer();
MidiOutSequencer.open();
MidiOutSequencer.start();
I hear the MIDI sequence reproduction out of the speakers.
After referring to the documentation
3.10.
The "Java Sound Sequencer" is implicitly connected to the default Synthesizer,
3.5.
In your program you can obtain a Synthesizer instance yourself and connect
it to a sequencer explicitly using a Transmitter / Receiver pair.
So you know which Synthesizer is used.
In case you obtained a Sequencer that is pre-connected to a Synthesizer,
you can find out the Synthesizer by using the method getTransmitters().
But there is not mention of how to explicitly use this Transmitter / Receiver pair and instantiate the Sequencer object with the new Default Synthesizer.
I have the correct Transmitter and Receiver.
But they are not playing out of the MIDI out.
Also when I try
MidiSystem.getTransmitter().setReceiver(MidiOutReceiver);
It does not seem to change anything.
How do I explicitly use this Receiver / Transmitter Pair with a Synthesizer so that the Default Sequencer will use my MIDI out port?
I overlooked something simple. The default Sequencer returned by MidiSystem.getSequencer(); has a Transmitter which in turn has a setReceiver() method to add a MIDI Out device. But you must have the correct MIDI Out device. I had chosen a wrong device by accident.
So first the correct output device is chosen by looking through the DeviceInfos array, picking the correct device, then instatiating the the Sequencer with the correct Receiver.
MidiDevice.Info[] MidiDeviceInfos = MidiSystem.getMidiDeviceInfo();
//find the suitable device number here, based on some criteria
MidiDevice MidiOutDevice = MidiSystem.getMidiDevice(MidiDeviceInfos[DEVICE_NUMBER]);
Receiver MidiOutReceiver = MidiOutDevice.getReceiver();
Sequencer MidiOutSequencer = MidiSystem.getSequencer();
//Add the new MIDI out device here.
MidiOutSequencer.getTransmitter().setReceiver(MidiOutReceiver);
MidiOutSequencer.open();
Now you can open() a file and play() it, but since the default MIDI Out device is also used you may hear General MIDI/Soundfont MIDI sounds too. This threw me off at first but now the MIDI device will also be sending the opened sequence out of your added Receiver.

Java: How to implement listener to provide realtime audio stream position?

I'm working on an application to synchronize with realtime audio playback. I would like to define a listener with a specific timestep, and use the listener to get updates every time the audio being played has advanced by a timestep. Implementing this functionality must be possible (existence proof being time counter of audio player apps) but the architecture I have in mind might not be possible.
Ideally, I would listen to the audio stream on the SPEAKER or HEADPHONE Target Port of the sound card. The existing LineListener/LineEvent functionality only supports START/STOP/OPEN/CLOSE events, and I can't subclass and augment the Target Port implementation (or SourceDataLine or TargetDataLine).
How can I do this? Do I need to have a Thread constantly polling the getMicrosecondPosition() or getLongFramePosition() methods and fire my own event at the appropriate time? That sounds very inefficient. If I used a Timer to trigger the poll at regular time periods, then I'm better off than just using the system timers between the available START and STOP events that are supported on Port/DataLines. I would call the getMicrosecondPosition() method to synchronize, but I think that is likely to result in occaisional errors due to drift between the system Timer and real time audio. I'd expect to see repeats or skips of the counter (i.e. 1:23:003, 1:23:004, 1:23:006, 1:23:007... or 1:23:003, 1:23:004, 1:23:004, 1:23:005..).
I'm looking at the javazoom mp3 player source to see how they did it but no luck figuring it out so far. Any help/tips will be appreciated.

Java stop MIDI playback

Hi I have java application which plays midi messages from sequence. I'm doing this using jfugue library.
the problem is when I'm tryingto stop playback with stop button (which call sequencer.stop() and sequencer.close()) the last played note is sound all of rest time, and I can't stop it.
So I'm asking about solution about stopping all audio and MIDI too! sound playback from java application.
Notice:
If you want propose just mute volume, you need to know that I want end-use will be able to press play button again and hear the sound again, so muting volumr will be not a solution, or explain please.
Thank you!
I'm guessing you need to call Player.allNotesOff() before calling sequencer.stop(). Untested, so please let me know if it didn't work.
When MIDI plays music, it uses a combination of NOTE_ON and NOTE_OFF events. It sounds like when you press the stop button, the sequence is stopping after a NOTE_ON event had been sent, but before a NOTE_OFF event was sent. That means the sound will continue to play indefinitely.
Player.allNotesOff() in JFugue makes a call to JavaSound's allNotesOff() method in the Channel class; this call is made for each MIDI Channel (there are 16 channels). It's unfortunate that this solution isn't working. Try calling Player.allNotesOff() after sequencer.stop(), see if that helps.

Categories