[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