Java midi音量控制将无法正常工作

我一直试图让Midi音量控制在MidiPlayer课程中工作很长一段时间.我已经在stackoverflow和整个互联网上搜索了完成此操作的示例,但我尝试的任何东西似乎都没有用.音量保持不变!它没有像我想要的那样改变.

我在Windows 7专业版上运行Java 1.6.0_32.

这里!有一个SSCCE:

  import java.io.*;
  import javax.sound.midi.*;
  import java.net.URL;

  public class MidisSCCE {
     public static void main(String[] args)
     {
        // creates the midi player and sets up its sequencer and synthesizer.
        MidiPlayer midiP = new MidiPlayer();    
        double volume = 1.0;

        // loads a midi from a url into the sequencer,but doesn't start playing it yet.
        midiP.load("http://www.vgmusic.com/music/computer/microsoft/windows/touhou_6_stage3_boss.mid",true);

        // set the midi to loop indefinitely.
        midiP.loop(-1);

        // start playing the midi.
        midiP.play(true);

        // while loop changes the volume of the midi while it is playing.
        while(true) {
           midiP.setVolume(volume);
           try { Thread.sleep(300); } catch(Exception e) {}
           volume -= 0.1;
           if(volume < 0) volume += 1.0;
        }
     }
  }

  /**
  * MidiPlayer
  * author: Stephen Lindberg
  * Last modified: Oct 14,2011
  * 
  * A class that allows midi files to be loaded and played.
  **/

  class MidiPlayer {
     private Sequence seq;
     private Sequencer seqr;
     private Synthesizer synth;
     private Receiver receiver;
     private File midiFile;
     private String midiID;
     private boolean loaded;
     private boolean usingHardwareSoundbank;

     // CONSTRUCTORS

     public MidiPlayer() {
        loaded = false;
        try  {
           // obtain the sequencer and synthesizer.
           seqr = Midisystem.getSequencer();
           synth = Midisystem.getSynthesizer();

           // print the user's midi device info
           System.out.println("Setting up Midi Player...");
           System.out.println("MidiDeviceInfo: ");
           for(MidiDevice.Info info : Midisystem.getMidiDeviceInfo()) {
              System.out.println("\t" + info.getName() + ": " +info.getDescription());
           }
           System.out.println();

           // obtain the soundbank and receiver.
           Soundbank soundbank = synth.getDefaultSoundbank();
           if(soundbank == null) {
              receiver = Midisystem.getReceiver();
              usingHardwareSoundbank = true;
              System.out.println("using hardware soundbank");
           }
           else {
              synth.loadAllInstruments(soundbank);
              receiver = synth.getReceiver();
              usingHardwareSoundbank = false;
              System.out.println("using default software soundbank:" + soundbank);
           }
           seqr.getTransmitter().setReceiver(receiver);
        }
        catch(Exception e) {
           System.out.println("MIDI error: I just don't kNow what went wrong! 6_9");
        }
     }


     // DATA METHODS

     /**
     *  load(String fileName)
     *  loads a midi file into this MidiPlayer.
     *  Preconditions: fileName is the name of the midi file to be loaded.
     *  Postconditions: fileName is loaded and is ready to be played.
     **/

     public void load(String fileName,boolean isOnline) {
        this.unload();
        try {
           URL midiURL;
           if(isOnline) midiURL = new URL(fileName);
           else midiURL =  getClass().getClassLoader().getResource(fileName);

           seq = Midisystem.getSequence(midiURL);

           seqr.open();
           synth.open();

           // load our sequence into the sequencer.

           seqr.setSequence(seq);
           loaded = true;
        }
        catch(IOException ioe) {
           System.out.println("MIDI error: Problem occured while reading " + midiFile.getName() + ".");
        }
        catch(InvalidMidiDataException imde)  {
           System.out.println("MIDI error: " + midiFile.getName() + " is not a valid MIDI file or is unreadable.");
        }
        catch(Exception e)  {
           System.out.println("MIDI error: I just don't kNow what went wrong! 6_9");
        }
     }

     /**
     *  unload()
     *  Unloads the current midi from the MidiPlayer and releases its resources from memory.
     **/

     public void unload() {
        this.stop();
        seqr.close();
        synth.close();
        midiFile = null;
        loaded = false;
     }

     // OTHER METHODS


     /**
     *  play(boolean reset)
     *  plays the currently loaded midi.
     *  Preconditions: reset tells our midi whether or nor to begin playing from the start of the midi file's current loop start point.
     *  Postconditions: If reset is true,then the loaded midi begins playing from its loop start point (default 0). 
     *      If reset is false,then the loaded midi resumes playing from its current position.
     **/

     public void play(boolean reset) {
        if(reset)   seqr.setTickPosition(seqr.getLoopStartPoint());
        seqr.start();
     }

     /**
     *  stop()
     *  Pauses the current midi if it was playing.
     **/

     public void stop() {
        if(seqr.isopen())   seqr.stop();
     }

     /**
     *  isRunning()
     *  Returns true if the current midi is playing. Returns false otherwise.
     **/

     public boolean isRunning() {
        return seqr.isRunning();
     }





     /**
     *  loop(int times)
     *  Sets the current midi to loop from start to finish a specific number of times.
     *  Preconditions: times is the number of times we want our midi to loop.
     *  Postconditions: The current midi is set to loop times times. 
     *      If times = -1,the current midi will be set to loop infinitely.
     **/

     public void loop(int times)
     {
        loop(times,-1);
     }

     /**
     *  loop(int times)
     *  Sets the current midi to loop from a specified start point to a specified end point a specific number of times.
     *  Preconditions: times is the number of times we want our midi to loop.
     *      start is our loop's start point in ticks.
     *      end is our loop's end point in ticks.
     *  Postconditions: The current midi is set to loop from tick start to tick end times times. 
     *      If times = -1,the current midi will be set to loop infinitely.
     **/

     public void loop(int times,long start,long end) {
        if(start < 0)   start = 0;
        if(end > seqr.getSequence().getTickLength() || end <= 0)   end = seqr.getSequence().getTickLength();

        if(start >= end && end != -1)   start = end-1;

        seqr.setLoopStartPoint(start);
        seqr.setLoopEndPoint(end);

        if(times == -1)   seqr.setLoopCount(Sequencer.LOOP_CONTINUOUSLY);
        else   seqr.setLoopCount(times);

     }




     public void setVolume(double vol) {
        System.out.println("Midi volume change request: " + vol);

        try {
           if(usingHardwareSoundbank) {
              ShortMessage volumeMessage = new ShortMessage();
              for ( int i = 0; i < 16; i++ ) {
                 volumeMessage.setMessage( ShortMessage.CONTROL_CHANGE,i,7,(int)(vol*127) );
                 receiver.send( volumeMessage,-1 );
              }
           }
           else {
              MidiChannel[] channels = synth.getChannels();

              for( int c = 0; c < channels.length; c++ ) {
                 if(channels[c] != null)   channels[c].controlChange( 7,(int)( vol*127) );
              }
           }
        } 
        catch ( Exception e ) {
           e.printstacktrace();
        }
     }

  }

我在以下来源尝试了一些例子但没有成功:

http://www.java2s.com/Code/Java/Development-Class/SettingtheVolumeofPlayingMidiAudio.htm

How to controll the MIDI channel’s volume

https://forums.oracle.com/forums/thread.jspa?messageID=5389030

MIDI Song with CC

http://www.codezealot.org/archives/27

http://www.exampledepot.com/egs/javax.sound.midi/Volume.html

最佳答案
我正在努力解决控制声音方面的这些问题,并且我找到了一个可以改变音量的代码.不幸的是,我无法理解它,但是你的代码中的某些东西与我见过的东西不同.也许它可以帮助你.
尝试更改线路

seqr = Midisystem.getSequencer();

对于

seqr = Midisystem.getSequencer(false);

也许它会帮助你,我相信使用“假”序列器将连接到接收器,而不是合成器,然后当你将消息发送到接收器设置音量时它将起作用.

相关文章

最近看了一下学习资料,感觉进制转换其实还是挺有意思的,尤...
/*HashSet 基本操作 * --set:元素是无序的,存入和取出顺序不...
/*list 基本操作 * * List a=new List(); * 增 * a.add(inde...
/* * 内部类 * */ 1 class OutClass{ 2 //定义外部类的成员变...
集合的操作Iterator、Collection、Set和HashSet关系Iterator...
接口中常量的修饰关键字:public,static,final(常量)函数...