Skip to main content
GameDev.net gamedev.net
🔒 Locked

[java] MIDI volume change problem

Started by paulscode Feb 6, 2009 at 4:36 PM 0 replies 2.1k views
Original Post
paulscode
paulscode
Hello, I have been having a problem with changing MIDI volume. What happens is that when a software synthesizer is used, I can send a volume control change message of zero, but volume does not become completely silent. If a hardware synthesizer is used, the volume change works properly. Here are the relevant parts of my code for reference: Set up the MIDI sequence, sequencer, and synthesizer:
    private static final int CHANGE_VOLUME = 7;

    private Sequencer sequencer = null;
    private Synthesizer synthesizer = null;
    private Sequence sequence = null;

...

        URL midiSource = getClass().getClassLoader().getResource( filename );
        if( midiSource == null )
        {
            System.err.println( "Unable to load Midi file." );
            return;
        }

        try
        {
            sequence = MidiSystem.getSequence( midiSource );
            sequencer = MidiSystem.getSequencer();
            sequencer.open();
            sequencer.setSequence( sequence );
        }
        catch( IOException ioe )
        {
            System.err.println( "Failed to read from MIDI file." );
            return;
        }
        catch( InvalidMidiDataException imde )
        {
            System.err.println( "Invalid MIDI data encountered." );
            return;
        }
        catch( MidiUnavailableException mue )
        {
            System.err.println( "MIDI unavailable." );
            return;
        }
        catch( Exception e )
        {
            System.err.println( "Unexpected problem loading MIDI file." );
            return;
        }

        try
        {
            synthesizer = MidiSystem.getSynthesizer();
            synthesizer.open();
            if( synthesizer.getDefaultSoundbank() == null )
            {
                // HARDWARE SYNTHESIZER
                sequencer.getTransmitter().setReceiver(
                    MidiSystem.getReceiver() );
            }
            else
            {
                // SOFTWARE SYNTHESIZER
                sequencer.getTransmitter().setReceiver(
                    synthesizer.getReceiver() );
            }
        }
        catch( MidiUnavailableException mue )
        {
            errorMessage( "MIDI unavailable." );
            return;
        }
        catch( Exception e )
        {
            errorMessage( "Unexpected problem linking to synthesizer " );
            return;
        }
Then, to change the volume:
            // NOTE: variable 'midiVolume' is an int between 0 and 127
            if( synthesizer.getDefaultSoundbank() == null )
            {
                // HARDWARE SYNTHESIZER
                try
                {
                    ShortMessage volumeMessage = new ShortMessage();
                    for( int i = 0; i < 16; i++ )
                    {
                        volumeMessage.setMessage( ShortMessage.CONTROL_CHANGE,
                            i, CHANGE_VOLUME, midiVolume );
                        MidiSystem.getReceiver().send( volumeMessage, -1 );
                    }
                }
                catch( InvalidMidiDataException imde )
                {
                    System.err.println( "Invalid MIDI data." );
                    return;
                }
                catch( MidiUnavailableException mue )
                {
                    System.err.println( "MIDI unavailable." );
                    return;
                }
            }
            else
            {
                // SOFTWARE SYNTHESIZER:
                MidiChannel[] channels = synthesizer.getChannels();
                for( int c = 0; channels != null && c < channels.length; c++ )
                {
                    channels[c].controlChange( CHANGE_VOLUME, midiVolume );
                }
            }
I have also tried using this instead for software-synthesis mode, but it has the same effect (i.e. volume is not silent at midiVolume=0):
                ShortMessage volumeMessage = new ShortMessage();
                for( int i = 0; i < 16; i++ )
                {
                    volumeMessage.setMessage( ShortMessage.CONTROL_CHANGE, i,
                                              CHANGE_VOLUME, midiVolume );
                    synthesizer.getReceiver().send( volumeMessage, -1 );
                }
For reference, here is a link to a test applet: http://www.paulscode.com/source/MIDI/MIDIApplet/ If your output says "getDefaultSoundbank() did NOT return null", that means you are using a software synthesizer, and the volume will not become silent at zero. On the other hand, if your output says "getDefaultSoundbank() returned null", it means you are using a hardware synthesizer, and the volume change will work correctly. Does anyone have any ideas how to correct this problem? Thanks in advance!
INsanityDesign
INsanityDesign
Greetings

That is a known problem of Java since JDK5 if I remember correctly. The problem is that Java Sound is currently no more in active development and I think there has never been a solution/fix been made to this.

Instead we have seen many tries of Sun to accomplish something new like JMF but as we see not much has been done for years now.

You could try FMJ or other Libraries and see if these will work for you.

Regards
-----The next statement is not true!The previous statement is true!

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.