2012-06-09 13 views
5

He intentado que el control de volumen midi funcione en una clase MidiPlayer durante mucho tiempo. He buscado ejemplos para lograr esto aquí en stackoverflow y en Internet, pero nada de lo que intento parece funcionar. ¡El volumen permanece igual! No cambia como yo quiero.El control de volumen Java midi no funcionará

Estoy ejecutando Java 1.6.0_32 en Windows 7 Professional.

Aquí! Tener una 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(); 
     } 
    } 

    } 

He intentado ejemplos en las siguientes fuentes sin éxito:

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

Eso es bueno. ¿Puedes describir "lo que no funciona"? (Y tal vez ponga un resumen en el título.) –

+0

Olvidé poner "Volumen" en el título. Es el cambio de volumen que no funciona para mí. Parece que en realidad está funcionando correctamente para usted? – Cazra

+0

¿Funciona el cambio de volumen si está listo * antes * de que el MIDI comience a reproducirse? –

Respuesta

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

Eso sí cambió algo ... pero no el volumen. Cuando agregué en esa línea, los cambios de tempo ya no tienen efecto durante la reproducción midi. – Cazra

3

Estoy luchando con estos mismos problemas en el control de sonido y he encontrado un código para cambiar el volumen que funciona. Desgraciadamente, no pude entenderlo, pero hay algo en tu código que es diferente al que he visto. Quizás pueda ayudarte. Intenta cambiar la línea

seqr = MidiSystem.getSequencer(); 

para

seqr = MidiSystem.getSequencer(false); 

Tal vez le ayuda, creo que el uso de la "falsa" del secuenciador se conectará al receptor, y no con el sintetizador, a continuación, cuando se envíe el mensaje al receptor para configurar el volumen, funcionará.

Cuestiones relacionadas