[Audio-engine-dev] Bug in RealTimeSequencer when used with Gervill
Karl Helgason
kalli at midverk.is
Wed Feb 6 06:40:09 PST 2008
I found a bug in RealTimeSequencer when used with Gervill.
The doAutoConnect opens Gervill synthesizer explicitly
when it is supposed to open Gervill implicitly.
Here is the code that reproduced the bug:
// When we call MidiSystem.getSequencer()
// a instance of RealTimeSequencer is created
// that is connected to Gervill Receiver opened implicitly
Sequencer seqr = MidiSystem.getSequencer();
seqr.open();
// When we call seqr.close the Receiver is also closed and
// hence the gervill synthesizer is also closed because the
// receiver was opened implicitly.
seqr.close();
// Here is the bug, RealTimeSequencer tries to auto connect
// again, but opens the Gervill synthesizer explicitly
// before it tries to get instance of Receiver opened implicitly.
seqr.open();
// Gervill synthesizer is never closed
// when we finally call seqr.close,
// because it was opened explicitly above.
seqr.close();
--------------------------------------
The error lies here below:
The doAutoConnect performs synth.open();
before it tries to get Receiver opened implicity
by calling getReceiverReferenceCounting.
private void doAutoConnect() {
if (Printer.trace) Printer.trace(">> RealTimeSequencer: doAutoConnect()");
Receiver rec = null;
// first try to connect to the default synthesizer
// IMPORTANT: this code needs to be synch'ed with
// MidiSystem.getReceiver(boolean), because the same
// algorithm needs to be used!
try {
Synthesizer synth = MidiSystem.getSynthesizer();
synth.open();
if (synth instanceof ReferenceCountingDevice) {
rec = ((ReferenceCountingDevice) synth).getReceiverReferenceCounting();
if (synth.getClass().toString().contains("com.sun.media.sound.MixerSynth")
&& (synth.getDefaultSoundbank() == null)) {
// don't use this receiver if no soundbank available
rec = null;
synth.close();
}
} else {
rec = synth.getReceiver();
}
} catch (Exception e) {
// something went wrong with synth
}
if (rec == null) {
// then try to connect to the default Receiver
try {
rec = MidiSystem.getReceiver();
} catch (Exception e) {
// something went wrong. Nothing to do then!
}
}
if (rec != null) {
autoConnectedReceiver = rec;
try {
getTransmitter().setReceiver(rec);
} catch (Exception e) {}
}
if (Printer.trace) Printer.trace("<< RealTimeSequencer: doAutoConnect() succeeded");
}
------------------------
Here is a example of corrected RealTimeSequencer.
It now works like MidiSystem.getSequencer(boolean).
e.g. is now correctly synch'ed with MidiSystem.getReceiver(boolean).
private void doAutoConnect() {
if (Printer.trace) Printer.trace(">> RealTimeSequencer: doAutoConnect()");
Receiver rec = null;
// first try to connect to the default synthesizer
// IMPORTANT: this code needs to be synch'ed with
// MidiSystem.getReceiver(boolean), because the same
// algorithm needs to be used!
try {
Synthesizer synth = MidiSystem.getSynthesizer();
if (synth instanceof ReferenceCountingDevice) {
rec = ((ReferenceCountingDevice) synth).getReceiverReferenceCounting();
if (synth.getClass().toString().contains("com.sun.media.sound.MixerSynth")
&& (synth.getDefaultSoundbank() == null)) {
// don't use this receiver if no soundbank available
rec = null;
synth.close();
}
} else {
synth.open();
try {
rec = synth.getReceiver();
} finally {
// make sure that the synth is properly closed
if (rec == null) {
synth.close();
}
}
}
} catch (Exception e) {
// something went wrong with synth
}
if (rec == null) {
// then try to connect to the default Receiver
try {
rec = MidiSystem.getReceiver();
} catch (Exception e) {
// something went wrong. Nothing to do then!
}
}
if (rec != null) {
autoConnectedReceiver = rec;
try {
getTransmitter().setReceiver(rec);
} catch (Exception e) {}
}
if (Printer.trace) Printer.trace("<< RealTimeSequencer: doAutoConnect() succeeded");
}
More information about the audio-engine-dev
mailing list