Java로 사운드를 재생하려면 어떻게해야합니까?


답변:


133

잘 작동하는 다음 코드를 작성했습니다. 그러나 .wav형식 에서만 작동한다고 생각 합니다.

public static synchronized void playSound(final String url) {
  new Thread(new Runnable() {
  // The wrapper thread is unnecessary, unless it blocks on the
  // Clip finishing; see comments.
    public void run() {
      try {
        Clip clip = AudioSystem.getClip();
        AudioInputStream inputStream = AudioSystem.getAudioInputStream(
          Main.class.getResourceAsStream("/path/to/sounds/" + url));
        clip.open(inputStream);
        clip.start(); 
      } catch (Exception e) {
        System.err.println(e.getMessage());
      }
    }
  }).start();
}

7
임의의 시간에 클립이 종료되지 않도록하려면 LineListener가 필요합니다. 보세요 : stackoverflow.com/questions/577724/trouble-playing-wav-in-java/…
yanchenko

3
공개 API를 사용하는 솔루션의 경우 +1 그래도 새로운 스레드를 만들 필요는 없습니까 (중복)?
Jataro

4
감사합니다. 중복입니까? 새 스레드로 만들었으므로 첫 번째 클립이 끝나기 전에 사운드를 다시 재생할 수 있습니다.
pek

4
clip.start ()가 새로운 스레드를 생성한다는 것을 알고 있으므로 불필요하다고 확신합니다.
Jataro

44
1) Thread불필요합니다. 2)를 사용하는 좋은 예 ClipJavaSound 정보를 참조하십시오 . 페이지 . 3) 방법이 URL(또는 File)을 요구하는 경우, 방법 을 나타내는 것을 받아들이지 않고 댕 URL(또는 File)을 제공하십시오 String. (개인적인 '내 보닛에있는 꿀벌'입니다.) 4) e.printStackTrace();보다 타이핑이 적 으면서 더 많은 정보를 제공합니다 System.err.println(e.getMessage());.
Andrew Thompson

18

나쁜 예 :

import  sun.audio.*;    //import the sun.audio package
import  java.io.*;

//** add this into your application code as appropriate
// Open an input stream  to the audio file.
InputStream in = new FileInputStream(Filename);

// Create an AudioStream object from the input stream.
AudioStream as = new AudioStream(in);         

// Use the static class member "player" from class AudioPlayer to play
// clip.
AudioPlayer.player.start(as);            

// Similarly, to stop the audio.
AudioPlayer.player.stop(as); 

13
java.sun.com/products/jdk/faq/faq-sun-packages.html sun.audio 사용에 대한 공개 API 대안이 있습니다.
McDowell

4
@GregHurlman 개발자가 사용하지 않도록 제작 된 sun. * 패키지가 아닙니까?
Tom Brito 2016 년

36
이 예제는 1997 JavaWorld 기사에서 제공됩니다. 오래된 방법으로 sun. * 패키지를 사용해서는 안됩니다.
sproketboy

3
"in"을 닫아야합니까?
rogerdpack

6
sun. * 패키지를 사용 하지 않는 경우 +1 1MB를
초과

10

단순한 소리를 재생하기 위해 너무 많은 코드 줄을 갖고 싶지 않았습니다. JavaFX 패키지 (이미 jdk 8에 포함되어 있음)가있는 경우 작동합니다.

private static void playSound(String sound){
    // cl is the ClassLoader for the current class, ie. CurrentClass.class.getClassLoader();
    URL file = cl.getResource(sound);
    final Media media = new Media(file.toString());
    final MediaPlayer mediaPlayer = new MediaPlayer(media);
    mediaPlayer.play();
}

주의 : JavaFX초기화 해야합니다 . 이를 수행하는 빠른 방법은 앱에서 JFXPanel () 생성자를 한 번 호출하는 것입니다.

static{
    JFXPanel fxPanel = new JFXPanel();
}

8

Java에서 사운드를 재생하려면 다음 코드를 참조하십시오.

import java.io.*;
import java.net.URL;
import javax.sound.sampled.*;
import javax.swing.*;

// To play sound using Clip, the process need to be alive.
// Hence, we use a Swing application.
public class SoundClipTest extends JFrame {

   public SoundClipTest() {
      this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      this.setTitle("Test Sound Clip");
      this.setSize(300, 200);
      this.setVisible(true);

      try {
         // Open an audio input stream.
         URL url = this.getClass().getClassLoader().getResource("gameover.wav");
         AudioInputStream audioIn = AudioSystem.getAudioInputStream(url);
         // Get a sound clip resource.
         Clip clip = AudioSystem.getClip();
         // Open audio clip and load samples from the audio input stream.
         clip.open(audioIn);
         clip.start();
      } catch (UnsupportedAudioFileException e) {
         e.printStackTrace();
      } catch (IOException e) {
         e.printStackTrace();
      } catch (LineUnavailableException e) {
         e.printStackTrace();
      }
   }

   public static void main(String[] args) {
      new SoundClipTest();
   }
}

7

어떤 이유로 든 wchargin의 최상위 답변은 this.getClass (). getResourceAsStream ()을 호출 할 때 null 포인터 오류를 발생시키는 것입니다.

나를 위해 일한 것은 다음과 같습니다.

void playSound(String soundFile) {
    File f = new File("./" + soundFile);
    AudioInputStream audioIn = AudioSystem.getAudioInputStream(f.toURI().toURL());  
    Clip clip = AudioSystem.getClip();
    clip.open(audioIn);
    clip.start();
}

그리고 나는 다음과 같이 소리를 재생할 것입니다.

 playSound("sounds/effects/sheep1.wav");

sounds / effects / sheep1.wav는 Eclipse의 프로젝트 기본 디렉토리 (src 폴더가 아닌)에 있습니다.


안녕하세요 Anrew, 귀하의 코드가 나를 위해 일했지만 실행에 약간의 시간이 더 걸린다는 것을 알았습니다 ... 약 1.5 초.

getResourceAsStream()반환 null자원이 발견되지 않는 경우, 또는 경우에 예외를 던질 name것입니다 null- 최고 대답이 아니 잘못 지정된 경로가 유효하지 않은 경우
user85421가

3

언젠가 안드로이드와 데스크탑에서 작업하기 위해 게임 프레임 워크를 만들었습니다. 사운드를 다루는 데스크탑 부분은 필요한 것에 영감을 줄 수 있습니다.

https://github.com/hamilton-lima/jaga/blob/master/jaga%20desktop/src-desktop/com/athanazio/jaga/desktop/sound/Sound.java

다음은 참조 용 코드입니다.

package com.athanazio.jaga.desktop.sound;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;

public class Sound {

    AudioInputStream in;

    AudioFormat decodedFormat;

    AudioInputStream din;

    AudioFormat baseFormat;

    SourceDataLine line;

    private boolean loop;

    private BufferedInputStream stream;

    // private ByteArrayInputStream stream;

    /**
     * recreate the stream
     * 
     */
    public void reset() {
        try {
            stream.reset();
            in = AudioSystem.getAudioInputStream(stream);
            din = AudioSystem.getAudioInputStream(decodedFormat, in);
            line = getLine(decodedFormat);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void close() {
        try {
            line.close();
            din.close();
            in.close();
        } catch (IOException e) {
        }
    }

    Sound(String filename, boolean loop) {
        this(filename);
        this.loop = loop;
    }

    Sound(String filename) {
        this.loop = false;
        try {
            InputStream raw = Object.class.getResourceAsStream(filename);
            stream = new BufferedInputStream(raw);

            // ByteArrayOutputStream out = new ByteArrayOutputStream();
            // byte[] buffer = new byte[1024];
            // int read = raw.read(buffer);
            // while( read > 0 ) {
            // out.write(buffer, 0, read);
            // read = raw.read(buffer);
            // }
            // stream = new ByteArrayInputStream(out.toByteArray());

            in = AudioSystem.getAudioInputStream(stream);
            din = null;

            if (in != null) {
                baseFormat = in.getFormat();

                decodedFormat = new AudioFormat(
                        AudioFormat.Encoding.PCM_SIGNED, baseFormat
                                .getSampleRate(), 16, baseFormat.getChannels(),
                        baseFormat.getChannels() * 2, baseFormat
                                .getSampleRate(), false);

                din = AudioSystem.getAudioInputStream(decodedFormat, in);
                line = getLine(decodedFormat);
            }
        } catch (UnsupportedAudioFileException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (LineUnavailableException e) {
            e.printStackTrace();
        }
    }

    private SourceDataLine getLine(AudioFormat audioFormat)
            throws LineUnavailableException {
        SourceDataLine res = null;
        DataLine.Info info = new DataLine.Info(SourceDataLine.class,
                audioFormat);
        res = (SourceDataLine) AudioSystem.getLine(info);
        res.open(audioFormat);
        return res;
    }

    public void play() {

        try {
            boolean firstTime = true;
            while (firstTime || loop) {

                firstTime = false;
                byte[] data = new byte[4096];

                if (line != null) {

                    line.start();
                    int nBytesRead = 0;

                    while (nBytesRead != -1) {
                        nBytesRead = din.read(data, 0, data.length);
                        if (nBytesRead != -1)
                            line.write(data, 0, nBytesRead);
                    }

                    line.drain();
                    line.stop();
                    line.close();

                    reset();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

이 코드는로 stream.reset();이어질 때 오류가 발생할 수 있습니다 Resetting to invalid mark. 이 문제를 해결하기 위해 무엇을 제안합니까?
driima

스트림을 다시 생성하려면 stackoverflow.com/questions/18573767/…을
hamilton.lima

1
실제로 raw.mark(raw.available()+1)초기화 한 후 rawwhile 루프를 사용하고 raw.reset()대신 을 사용 하여이 문제를 해결했습니다 stream.reset(). 내 문제는 이제 재설정 할 때 연극 사이에 간격이 있다는 것입니다. 나는 당신과 같은 연속 루프를 달성하고 싶습니다 Clip. ClipMASTER_GAIN과 같은 제어 조작의 지연 시간이 ~ 500ms이므로 사용하지 않습니다 . 이것은 아마도 나중에 물어 볼 수있는 자체 질문 일 것입니다.
driima

아니 do { ... } while?
안드레아스

2

애플릿과 응용 프로그램 모두에서 작동하는 사운드 파일을 가져 오는 대신 오디오 파일을 .java 파일로 변환하고 코드에서 간단히 사용할 수 있습니다.

이 과정을 훨씬 쉽게하는 도구를 개발했습니다. Java Sound API를 상당히 단순화합니다.

http://stephengware.com/projects/soundtoclass/


나는 당신의 시스템을 사용하여 wav 파일에서 클래스를 만들었습니다. 그러나, 내가 할 때 my_wave.play (); 오디오를 재생하지 않습니다 .. 초기화해야 할 오디오 시스템이 있습니까? ..
Nathan F.

실제로 작동하면 정말 멋질 것입니다. play ()를 실행할 때 오디오 라인 가져 오기가 실패합니다 (예외 "java.lang.IllegalArgumentException : PCM_UNSIGNED 44100.0 Hz, 16 비트, 스테레오, 4 바이트 / 프레임, 리틀 엔디안이 지원되는 라인 일치 인터페이스 SourceDataLine이 지원되지 않음"예외). 던졌습니다). 슬퍼.
phil294

2

애플릿 사용을 제안한 사람이 아무도 없습니다. 사용하십시오 Applet . 경고음 오디오 파일을 파일로 제공해야 wav하지만 작동합니다. 나는 우분투에서 이것을 시도했다 :

package javaapplication2;

import java.applet.Applet;
import java.applet.AudioClip;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;

public class JavaApplication2 {

    public static void main(String[] args) throws MalformedURLException {
        File file = new File("/path/to/your/sounds/beep3.wav");
        URL url = null;
        if (file.canRead()) {url = file.toURI().toURL();}
        System.out.println(url);
        AudioClip clip = Applet.newAudioClip(url);
        clip.play();
        System.out.println("should've played by now");
    }
}
//beep3.wav was available from: http://www.pacdv.com/sounds/interface_sound_effects/beep-3.wav

2
AppletJava 9
부터는

0

이 스레드는 다소 낡았지만 유용 할 수있는 옵션을 결정했습니다.

Java AudioStream라이브러리를 사용하는 대신 Windows Media Player 또는 VLC와 같은 외부 프로그램 을 사용하고 Java 를 통해 콘솔 명령으로 실행할 수 있습니다.

String command = "\"C:/Program Files (x86)/Windows Media Player/wmplayer.exe\" \"C:/song.mp3\"";
try {
    Process p = Runtime.getRuntime().exec(command);
catch (IOException e) {
    e.printStackTrace();
}

또한 프로그램으로 제어 할 수있는 별도의 프로세스가 생성됩니다.

p.destroy();

물론 이것은 내부 라이브러리를 사용하는 것보다 실행하는 데 시간이 오래 걸리지 만 특정 콘솔 명령이 주어지면 GUI없이 더 빨리 시작될 수있는 프로그램이있을 수 있습니다.

시간이 본질이 아닌 경우 유용합니다.


4
나는 이것이 객관적으로 나쁜 해결책이라고 생각하지만 (신뢰성, 효율성 및 기타 다른 메트릭스 측면에서) 적어도 다른 방법으로는 생각하지 못했던 흥미로운 것입니다!
Max von Hippel
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.