Java'da nasıl ses çalabilirim?


Yanıtlar:


133

İyi çalışan aşağıdaki kodu yazdım. Ama bence sadece .wavformatla çalışıyor .

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
Klibin rastgele zamanda kapatılmasını önlemek için bir LineListener gerekir. Bir göz atın: stackoverflow.com/questions/577724/trouble-playing-wav-in-java/…
yanchenko

3
Herkese açık API kullanan bir çözüm için +1. Yine de yeni bir iş parçacığı oluşturmak gereksiz (gereksiz) değil mi?
Jataro

4
Teşekkürler .. Gereksiz mi? İlk klip bitmeden sesi tekrar çalabilmek için yeni bir konuya girdim.
pek

4
Ben clip.start () yeni bir iş parçacığı doğurur, bu yüzden gereksiz olduğundan eminim.
Jataro

44
1) ThreadGereksizdir. 2) Kullanmaya iyi bir örnek Clipiçin JavaSound bilgilerine bakın. sayfası . 3) Bir yöntem bir URL(veya File) gerektiriyorsa, bunu temsil eden bir tanesini kabul etmek yerine bir dang URL(veya File) verin String. (Sadece kişisel 'kaputumdaki arı'.) 4) e.printStackTrace();daha az yazarak daha fazla bilgi sağlar System.err.println(e.getMessage());.
Andrew Thompson

18

Kötü bir örnek:

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 kullanmanın genel API alternatifi vardır.
McDowell

4
@GregHurlman Sun. * Paketi geliştiriciler tarafından kullanılmamak için üretildi mi?
Tom Brito

36
Bu örnek 1997 JavaWorld makalesinden alınmıştır. Güncel değil, sun * paketlerini KULLANMAMALISINIZ.
sproketboy

3
hiç "içeri" kapatmanız gerekiyor mu?
rogerdpack

6
İçin 1 değil güneşi kullanarak. * Paketleri. 1
MB'den büyük

10

Sadece basit bir lanet ses çalmak için çok fazla kod satırına sahip olmak istemedim. JavaFX paketiniz (jdk 8'de zaten var) varsa bu işe yarayabilir.

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();
}

Uyarı: JavaFX'i başlatmanız gerekir . Bunu yapmanın hızlı bir yolu, uygulamanızda bir kez JFXPanel () yapıcısını çağırmaktır:

static{
    JFXPanel fxPanel = new JFXPanel();
}

8

Java'da ses çalmak için aşağıdaki koda başvurabilirsiniz.

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

Her ne sebeple olursa olsun, wchargin tarafından üst yanıt bana this.getClass (). GetResourceAsStream () çağırırken boş bir işaretçi hatası veriyordu.

Benim için işe yarayan şuydu:

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();
}

Ve sesi şu şekilde çalarım:

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

sesler / efektler / sheep1.wav Eclipse projemin temel dizininde yer aldı (src klasörü içinde değil).


merhaba Anrew, kodun benim için çalıştı, ama idamda biraz ekstra zaman alır fark ettim ... yaklaşık 1,5 sn.

getResourceAsStream()dönecektir nullkaynak bulunmazsa, ya eğer istisna nameolduğunu null- üst cevabın bir arıza verilen yolun geçerli değilse
user85421

3

Bir süre önce Android ve Masaüstünde çalışmak için bir oyun çerçevesi oluşturdum, sesi işleyen masaüstü kısmı, ihtiyacınız olan şey için ilham kaynağı olarak kullanılabilir.

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

İşte referans kodu.

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();
        }
    }

}

Bu kod, stream.reset();adresine yönlendirirken hata verebilir Resetting to invalid mark. Bunu düzeltmek için ne yapmayı öneriyorsun?
driima

belki akışı yeniden oluşturun, bkz. stackoverflow.com/questions/18573767/…
hamilton.lima

1
Aslında bunu raw.mark(raw.available()+1)başladıktan sonra rawve sonra while döngüsünde kullanarak ve sonra raw.reset()yerine kullanarak çözdü stream.reset(). Benim sorunum, sıfırlama söz konusu olduğunda, oyunlar arasında bir boşluk olması. Senin gibi sürekli bir döngü elde etmek istiyorum Clip. Ben kullanmıyorum Clipböyle MASTER_GAIN olarak manipüle kontrolleri ~ 500ms bir fark gecikmeye sahip olduğu için. Bu muhtemelen daha sonra soracağım kendi sorusu olmalı.
driima

Değil do { ... } whilemi?
Andreas

2

Hem uygulamalarda hem de uygulamalarda çalışan ses dosyalarını içe aktarmanın bir alternatifi vardır: ses dosyalarını .java dosyalarına dönüştürün ve kodunuzda kullanın.

Bu süreci çok daha kolaylaştıran bir araç geliştirdim. Java Sound API'sını biraz basitleştirir.

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


Ben bir wav dosyasından bir sınıf oluşturmak için sisteminizi kullandı, Ancak, Ne zaman i do my_wave.play (); sesi çalmıyor .. Başlatmam gereken bir ses sistemi falan var mı? ..
Nathan

eğer gerçekten işe yararsa bu gerçekten harika olurdu. Play () çalıştırılırken Get Audio Line başarısız olur ("java.lang.IllegalArgumentException istisnası: PCM_UNSIGNED 44100.0 Hz, 16 bit, stereo, 4 bayt / kare, küçük endian desteklenmeyen satır destekleme arayüzü yok SourceDataLine desteklenmiyor." atılmış). Üzgün.
phil294

2

Kimsenin Applet kullanmayı önermediğine şaşırdım. Kullanın Applet . Bip ses dosyasını bir wavdosya olarak sağlamanız gerekir , ancak çalışır. Ben Ubuntu üzerinde denedim:

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'dan itibaren kullanımdan kaldırılmıştır.
Fre_d

0

Bu iş parçacığı oldukça eskidir, ancak yararlı olabilecek bir seçenek belirledim.

Java AudioStreamkitaplığını kullanmak yerine Windows Media Player veya VLC gibi harici bir program kullanabilir ve Java üzerinden bir konsol komutuyla çalıştırabilirsiniz.

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();
}

Bu aynı zamanda program tarafından kontrol edilebilen ayrı bir süreç yaratacaktır.

p.destroy();

Tabii ki bu, dahili bir kütüphane kullanmaktan daha uzun sürecektir, ancak belirli konsol komutları verildiğinde bir GUI olmadan daha hızlı ve muhtemelen başlayabilen programlar olabilir.

Zamanın özü değilse, bu yararlıdır.


4
Bunun objektif olarak kötü bir çözüm olduğunu düşünmeme rağmen (güvenilirlik, verimlilik ve diğer metrikler açısından), en azından başka türlü düşünmeyeceğim ilginç bir çözüm!
Max von Hippel
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.