2012-08-12 73 views
6

Estoy tratando de reproducir dos sonidos wav a la vez durante un juego (Música de fondo y un efecto). Primero construí este fragmento de código usando otro controlador de audio en Java que manejaría la reproducción, la detención y el bucle del sonido. Este constructo reproduciría la música de fondo o el efecto, pero solo uno a la vez. Miré a través de Internet y me dijeron que usara javax.sound.sampled.Clip para manejar los sonidos, así que reutilicé el mismo constructo (play, stop, loop) pero lo cambié para usar javax.sound.sampled.Clip. Ahora estoy completamente perdido. Por lo que he leído hasta ahora, he hecho todo lo correcto y no he recibido errores en el editor de eclipse, pero cuando lo ejecuto obtengo uno de dos errores. En eclipse (ejecutándose en Linux) se lanza una excepción LineUnavailableException. En eclipse (se ejecuta en Windows 7) obtengo una java.lang.NullPointerException en la sección loop() de este código. Si pudiera mostrarme lo que estoy haciendo mal o señalarme alguna documentación relevante, lo agradecería. Asumo que es algo con mi código que maneja Excepciones, pero no estoy seguro. Si ve algún otro error en el código, por favor dígame que me esfuerzo por ser el mejor programador que pueda y realmente aprecio la crítica constructiva. Gracias por tu tiempo.Usando javax.sound.sampled.Clip para reproducir, repetir y detener sonidos múltiples en un juego. Errores inesperados

import java.io.File; 
    import java.io.IOException; 
    import java.net.MalformedURLException; 
    import javax.sound.sampled.AudioInputStream; 
    import javax.sound.sampled.AudioSystem; 
    import javax.sound.sampled.Clip; 
    import javax.sound.sampled.LineUnavailableException; 
    import javax.sound.sampled.UnsupportedAudioFileException; 

    /** 
    * Handles play, pause, and looping of sounds for the game. 
    * @author Tyler Thomas 
    * 
    */ 
    public class Sound { 
     private Clip myClip; 
     public Sound(String fileName) { 
       try { 
        File file = new File(fileName); 
        if (file.exists()) { 
         Clip myClip = AudioSystem.getClip(); 
         AudioInputStream ais = AudioSystem.getAudioInputStream(file.toURI().toURL()); 
         myClip.open(ais); 
        } 
        else { 
         throw new RuntimeException("Sound: file not found: " + fileName); 
        } 
       } 
       catch (MalformedURLException e) { 
        throw new RuntimeException("Sound: Malformed URL: " + e); 
       } 
       catch (UnsupportedAudioFileException e) { 
        throw new RuntimeException("Sound: Unsupported Audio File: " + e); 
       } 
       catch (IOException e) { 
        throw new RuntimeException("Sound: Input/Output Error: " + e); 
       } 
       catch (LineUnavailableException e) { 
        throw new RuntimeException("Sound: Line Unavailable: " + e); 
       } 
     } 
     public void play(){ 
      myClip.setFramePosition(0); // Must always rewind! 
      myClip.loop(0); 
      myClip.start(); 
     } 
     public void loop(){ 
      myClip.loop(Clip.LOOP_CONTINUOUSLY); 
     } 
     public void stop(){ 
      myClip.stop(); 
     } 
    } 

Respuesta

12

que era capaz de conseguir el código de trabajo y ahora tenemos una mejor comprensión de los clips. La página que más me ayudó fue http://www3.ntu.edu.sg/home/ehchua/programming/java/J8c_PlayingSound.html. Desglose todo y me ayudó a ver dónde cometí errores. Aquí está mi código de trabajo final. Como antes, si ve errores horribles o puntos de vista en lógica o estilo, hágamelo saber.

import java.io.File; 
import java.io.IOException; 
import java.net.MalformedURLException; 
import javax.sound.sampled.AudioInputStream; 
import javax.sound.sampled.AudioSystem; 
import javax.sound.sampled.Clip; 
import javax.sound.sampled.LineUnavailableException; 
import javax.sound.sampled.UnsupportedAudioFileException; 

/** 
* Handles playing, stoping, and looping of sounds for the game. 
* @author Tyler Thomas 
* 
*/ 
public class Sound { 
    private Clip clip; 
    public Sound(String fileName) { 
     // specify the sound to play 
     // (assuming the sound can be played by the audio system) 
     // from a wave File 
     try { 
      File file = new File(fileName); 
      if (file.exists()) { 
       AudioInputStream sound = AudioSystem.getAudioInputStream(file); 
      // load the sound into memory (a Clip) 
       clip = AudioSystem.getClip(); 
       clip.open(sound); 
      } 
      else { 
       throw new RuntimeException("Sound: file not found: " + fileName); 
      } 
     } 
     catch (MalformedURLException e) { 
      e.printStackTrace(); 
      throw new RuntimeException("Sound: Malformed URL: " + e); 
     } 
     catch (UnsupportedAudioFileException e) { 
      e.printStackTrace(); 
      throw new RuntimeException("Sound: Unsupported Audio File: " + e); 
     } 
     catch (IOException e) { 
      e.printStackTrace(); 
      throw new RuntimeException("Sound: Input/Output Error: " + e); 
     } 
     catch (LineUnavailableException e) { 
      e.printStackTrace(); 
      throw new RuntimeException("Sound: Line Unavailable Exception Error: " + e); 
     } 

    // play, stop, loop the sound clip 
    } 
    public void play(){ 
     clip.setFramePosition(0); // Must always rewind! 
     clip.start(); 
    } 
    public void loop(){ 
     clip.loop(Clip.LOOP_CONTINUOUSLY); 
    } 
    public void stop(){ 
      clip.stop(); 
     } 
    } 
2

He encontrado una técnica útil para detener el sonido. Puede copiar estas dos clases y pruébelo usted mismo. Sin embargo, el método clip.stop() es más un método de pausa. Detiene el sonido de la reproducción, sí, pero no borra el sonido de la línea. Como resultado, el sonido todavía está en cola para reproducirse y no se puede reproducir ningún sonido nuevo. Por lo tanto, usar el método clip.close() borrará estos datos en cola y permitirá que se reproduzca un nuevo sonido o que tenga lugar otra acción. También tenga en cuenta que en el siguiente código se colocó un archivo de sonido en la carpeta del proyecto llamado "predator.wav", este sonido puede ser cualquier tipo de sonido que desee usar en lugar del sonido que elija, pero asegúrese de que sea un formato .wav y el sonido debe estar en el nivel superior de la carpeta del proyecto.

/* 
* File: KeyMap.java 
* Author: Andrew Peturis Chaselyn Langley; UAB EE Students 
* Assignment: SoundBox - EE333 Fall 2015 
* Vers: 1.0.0 10/20/2015 agp - initial coding 
* 
* Credits: Dr. Green, UAB EE Engineering Professor 
*/ 

import java.io.File; 
import java.io.IOException; 
import javax.sound.sampled.AudioSystem; 
import javax.sound.sampled.Clip; 
import javax.sound.sampled.LineUnavailableException; 
import javax.sound.sampled.UnsupportedAudioFileException; 

public class KeyMap { 

    private char keyCode; 
    private String song; 
    private Clip clip; 

    // Don't allow default constructor 
    private KeyMap() { 
    } 

    public KeyMap(char keyCode, String song) throws LineUnavailableException { 
     this.keyCode = keyCode; 
     this.song = song; 

     // Create an audiostream from the inputstream 
     clip = AudioSystem.getClip(); 
    } 

    public boolean match(char key) { 
     return key == keyCode; 
    } 

    // Play a sound using javax.sound and Clip interface 
    public String play() { 
     try { 
      // Open a sound file stored in the project folder 
      clip.open(AudioSystem.getAudioInputStream(new File(song + ".wav"))); 

      // Play the audio clip with the audioplayer class 
      clip.start(); 

      // Create a sleep time of 2 seconds to prevent any action from occuring for the first 
      // 2 seconds of the sound playing 
      Thread.sleep(2000); 

     } catch (LineUnavailableException | UnsupportedAudioFileException | IOException | InterruptedException e) { 
      System.out.println("Things did not go well"); 
      System.exit(-1); 
     } 
     return song; 
    } 

    // Stop a sound from playing and clear out the line to play another sound if need be. 
    public void stop() { 
     // clip.stop() will only pause the sound and still leave the sound in the line 
     // waiting to be continued. It does not actually clear the line so a new action could be performed. 
     clip.stop(); 

     // clip.close(); will clear out the line and allow a new sound to play. clip.flush() was not 
     // used because it can only flush out a line of data already performed. 
     clip.close(); 
    } 
} 

/* 
* File: SoundBox.java 
* Author: Andrew Peturis, Chaselyn Langley; UAB EE Students 
* Assignment: GUI SoundBox - EE333 Fall 2015 
* Vers: 1.0.0 09/08/2015 agp - initial coding 
*/ 

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.util.Scanner; 
import javax.sound.sampled.LineUnavailableException; 

/** 
* 
* @author Andrew Peturis, Chaselyn Langley 
* 
*/ 
public class SoundBox { 

    static Scanner scanner = new Scanner(System.in); //Scanner object to read user input 
    InputStream input; 

    /** 
    * @param args the command line arguments 
    * @throws java.io.IOException 
    */ 
    public static void main(String[] args) throws IOException, LineUnavailableException { 

     String line; 
     Character firstChar; 
     String predator = "predator"; 
     String explosion = "explosion"; 

     BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 

     KeyMap[] keyedSongs = { 
      new KeyMap('a', predator),}; 

     while (true) { 
      line = br.readLine(); 
      firstChar = line.charAt(0); 

      for (int i = 0; i < keyedSongs.length; i++) { 
       if (keyedSongs[i].match(firstChar)) { 

        // Notice now by running the code, after the first second of sleep time the sound can 
        // and another sound can be played in its place 
        keyedSongs[i].stop(); 
        System.out.println("Played the sound: " + keyedSongs[i].play()); 
        break; 
       } 
      } 

      if (firstChar == 'q') { 
       break; 
      } 
     } 
    } 
} 
Cuestiones relacionadas