Original Post
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!