2012-06-09 26 views
5

Próbuję uzyskać kontrolę głośności midi do pracy w klasie MidiPlayer przez bardzo długi czas. Szukałem przykładów dla osiągnięcia tego tutaj na stackoverflow i całym Internecie, ale nic, co próbuję kiedykolwiek wydaje się działać. Wielkość pozostaje taka sama! Nie zmienia się tak, jak tego chcę.Regulacja głośności midi Java nie zadziała

Używam Java 1.6.0_32 na Windows 7 Professional.

Tutaj! Masz 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,0,-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(); 
     } 
    } 

    } 

próbowałam przykłady w następujących źródłach bez powodzenia:

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

+0

To miło. Czy możesz opisać "co nie działa"? (A może umieścić podsumowanie w tytule.) –

+0

Zapomniałem umieścić w tytule "Tom". To zmiana objętości nie działa dla mnie. Wygląda na to, że faktycznie działa poprawnie dla ciebie? – Cazra

+0

Czy zmieniająca się głośność działa, jeśli została wykonana * przed * MIDI zaczyna grać? –

Odpowiedz

1
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)); 
      } 
     } 
     // Very important! 
     seqr.setSequence(seq); 
    } 
    catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 
+1

To coś zmieniło ... ale nie wolumin. Kiedy dodałem w tej linii, zmiany tempa wydają się już nie działać podczas odtwarzania midi. – Cazra

3

jestem zmaga się z tych samych zagadnień na kontrolowanie dźwięku i znalazłem kod do zmiany głośności, który działa. Niezrozumiale nie mogłem tego zrozumieć, ale tutaj jest coś w kodzie, które różni się od tego, które widziałem. Może to ci pomoże. Spróbuj zmienić linię

seqr = MidiSystem.getSequencer(); 

dla

seqr = MidiSystem.getSequencer(false); 

Może to pomaga, wierzę, że za pomocą „false” sekwencera połączy się z odbiornika, a nie do syntezatora, a następnie po wyślij wiadomość do odbiornika, aby ustawić głośność, która będzie działać.