1. 概要

このチュートリアルでは、Javaでサウンドを再生する方法を学習します。 Java Sound APIは、非常に長いサウンドでもスムーズかつ継続的にサウンドを再生するように設計されています。

このチュートリアルの一環として、[X52X]が提供するClipおよびSourceDataLineサウンドAPIを使用してオーディオファイルを再生します。 また、さまざまなオーディオ形式のファイルを再生します。

さらに、各APIの長所と短所についても説明します。 さらに、サウンドを再生できるサードパーティのJavaライブラリがいくつか表示されます。

2. Javaサウンドを再生するためのAPI

一般に、 javax.soundパッケージに含まれるJavaSoundAPIは、オーディオを再生する2つの方法を提供します。 2つのアプローチでは、サウンドファイルデータの指定方法に違いがあります。 Java Sound APIは、ストリーミングのバッファリングされた方法と、メモリ内のバッファリングされていない方法の両方でオーディオトランスポートを処理できます。 Javaの2つの最もよく知られているサウンドAPIは、ClipSourceDataLine。です。

2.1. クリップAPI

Clip APIは、Java用のバッファなしまたはメモリ内のサウンドAPIです。 Clipクラスはjavax.sound.sampledパッケージの一部であり、短いサウンドファイルを読み取って再生するときに便利です。 。 再生する前に、オーディオファイル全体がメモリにロードされ、ユーザーは再生を完全に制御できます。

ループ音に加えて、ユーザーはランダムな場所で再生を開始することもできます。

まず、サンプルクラス SoundPlayerWithClip を作成します。このクラスは、ラインイベント( OPEN CLOSE START 、および STOP )を再生します。 LineListenerからupdate()メソッドを実装して、再生ステータスを確認します。

public class SoundPlayerUsingClip implements LineListener {

    boolean isPlaybackCompleted;
    
    @Override
    public void update(LineEvent event) {
        if (LineEvent.Type.START == event.getType()) {
            System.out.println("Playback started.");
        } else if (LineEvent.Type.STOP == event.getType()) {
            isPlaybackCompleted = true;
            System.out.println("Playback completed.");
        }
    }
}

次に、プロジェクトのリソースフォルダからオーディオファイルを読み取ります。 リソースフォルダには、WAV、MP3、MPEGの3つの異なる形式のオーディオファイルが含まれています。

InputStream inputStream = getClass().getClassLoader().getResourceAsStream(audioFilePath);

第三に、ファイルストリームから、AudioInputStreamを作成します。

AudioInputStream audioStream = AudioSystem.getAudioInputStream(inputStream);

次に、DataLine.Infoオブジェクトを作成します。

AudioFormat audioFormat = audioStream.getFormat();
DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);

このDataLine.InfoからClip オブジェクトを作成してストリームを開き、startを呼び出してオーディオの再生を開始しましょう。

Clip audioClip = (Clip) AudioSystem.getLine(info);
audioClip.addLineListener(this);
audioClip.open(audioStream);
audioClip.start();

最後に、開いているリソースをすべて閉じる必要があります。

audioClip.close();
audioStream.close();

コードが実行されると、オーディオファイルが再生されます。

オーディオはメモリにプリロードされているため、他にも多くの便利なAPIがあります。

Clip.loop メソッドを使用して、オーディオクリップをループで継続的に再生できます。

たとえば、オーディオを5回再生するように設定できます。

audioClip.loop(4);

または、オーディオを無限に(または中断されるまで)再生するように設定できます。

audioClip.loop(Clip.LOOP_CONTINUOUSLY);

Clip.setMicrosecondPositionはメディアの位置を設定します。 次回クリップの再生を開始すると、この位置からクリップが開始されます。 たとえば、30秒から開始するには、次のように設定できます。

audioClip.setMicrosecondPosition(30_000_000);

2.2. SourceDataLine API

SourceDataLine APIは、java用のバッファリングまたはストリーミングサウンドAPIです。 SourceDataLineクラスはjavax.sound.sampledパッケージの一部であり、メモリにプリロードできない長いサウンドファイルを再生できます。

SourceDataLineを使用すると、大きなオーディオファイル用にメモリを最適化する場合や、リアルタイムオーディオデータをストリーミングする場合に効果的です。サウンドの長さとタイミングが事前にわからない場合にも役立ちます。終了します。

まず、サンプルクラスを作成し、プロジェクトのリソースフォルダーからオーディオファイルを読み取ります。 リソースフォルダには、WAV、MP3、MPEGの3つの異なる形式のオーディオファイルが含まれています。

InputStream inputStream = getClass().getClassLoader().getResourceAsStream(audioFilePath);

次に、ファイル入力ストリームから、AudioInputStreamを作成します。

AudioInputStream audioStream = AudioSystem.getAudioInputStream(inputStream);

次に、DataLine.Infoオブジェクトを作成します。

AudioFormat audioFormat = audioStream.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, audioFormat);

このDataLine.InfoからSourceDataLineオブジェクトを作成し、ストリームを開き、startを呼び出してオーディオの再生を開始しましょう。

SourceDataLine sourceDataLine = (SourceDataLine) AudioSystem.getLine(info);
sourceDataLine.open(audioFormat);
sourceDataLine.start();

ここで、 SourceDataLine の場合、オーディオデータはチャンクでロードされるため、バッファサイズを指定する必要があります。

private static final int BUFFER_SIZE = 4096;

次に、 AudioInputStream からオーディオデータを読み取り、ストリームの最後に到達するまでSourceDataLineの再生バッファーに送信します。

byte[] bufferBytes = new byte[BUFFER_SIZE];
int readBytes = -1;
while ((readBytes = audioStream.read(bufferBytes)) != -1) {
    sourceDataLine.write(bufferBytes, 0, readBytes);
}

最後に、開いているリソースをすべて閉じましょう。

sourceDataLine.drain();
sourceDataLine.close();
audioStream.close();

コードが実行されると、オーディオファイルが再生されます。

ここでは、LineListenerインターフェイスを実装する必要はありません。

2.3. ClipSourceDataLineの比較

両方の長所と短所について説明しましょう。

クリップ SourceDataLine
オーディオの任意の位置からの再生をサポートします。 setMicrosecondPosition(long)または setFramePosition(int)。を参照してください。 サウンドの任意の位置から再生を開始できません。
ループ(サウンドの全部または一部)での再生をサポートします。 setLoopPoints(int、int)および loop(int)。を参照してください。 音の全部または一部を再生(ループ)できません。
再生する前に音の持続時間を知ることができます。 getFrameLength()または getMicrosecondLength()。を参照してください。 再生する前に音の長さがわかりません。
現在の位置で再生を停止し、後で再生を再開することができます。 stop()および start()を参照してください 途中で停止して再生を再開することはできません。
大きなオーディオファイルはメモリ内にあるため、再生には適しておらず、非効率的です。 長いサウンドファイルの再生や、リアルタイムでのサウンドのストリーミングに適しています。
Clipのstart ()メソッドはサウンドを再生しますが、現在のスレッドをブロックしない(すぐに戻る)ため、LineListenerインターフェイスを実装する必要があります再生状態を知るために。 Clip とは異なり、再生がいつ完了するかを知るためにLineListenerインターフェイスを実装する必要はありません。
オーディオラインの再生バッファに書き込むサウンドデータを制御することはできません。 オーディオラインの再生バッファに書き込むサウンドデータを制御することができます。

2.4. JavaMP3形式のAPIサポート

現在、ClipSourceDataLineはどちらも、AIFC、AIFF、AU、SND、およびWAV形式のオーディオファイルを再生できます。

AudioSystem を使用して、サポートされているオーディオ形式を確認できます。

Type[] list = AudioSystem.getAudioFileTypes();
StringBuilder supportedFormat = new StringBuilder("Supported formats:");
for (Type type : list) {
    supportedFormat.append(", " + type.toString());
}
System.out.println(supportedFormat.toString());

ただし、一般的なオーディオ形式のMP3/MPEGをJavaSoundAPIClipおよびSourceDataLineで再生することはできません。MP3形式を再生できるサードパーティのライブラリを探す必要があります。

MP3形式のファイルをClipまたはSourceDataLine APIに提供すると、UnsupportedAudioFileExceptionが発生します。

javax.sound.sampled.UnsupportedAudioFileException: could not get audio input stream from input file
    at javax.sound.sampled.AudioSystem.getAudioInputStream(AudioSystem.java:1189)

3. サウンドを再生するサードパーティのJavaAPI

さまざまなオーディオ形式のファイルを再生できるサードパーティのライブラリのペアを見てみましょう。

3.1. JavaFXライブラリ

JavaFX には、MP3ファイルを再生するMediaクラスとMediaPlayerクラスがあります。 また、WAVなどの他のオーディオ形式を再生することもできます。

サンプルクラスを作成し、MediaおよびMediaPlayerクラスを使用してMP3ファイルを再生してみましょう。

String audioFilePath = "AudioFileWithMp3Format.mp3";
SoundPlayerUsingJavaFx soundPlayerWithJavaFx = new SoundPlayerUsingJavaFx();
try {
    com.sun.javafx.application.PlatformImpl.startup(() -> {});
    Media media = new Media(
      soundPlayerWithJavaFx.getClass().getClassLoader().getResource(audioFilePath).toExternalForm());
    MediaPlayer mp3Player = new MediaPlayer(media);
    mp3Player.play();
} catch (Exception ex) {
    System.out.println("Error occured during playback process:" + ex.getMessage());
}

このAPIの利点の1つは、WAV、MP3、およびMPEGオーディオ形式を再生できることです。

3.2. JLayerライブラリ

The JLayer 図書館 MP3を含むMPEG形式のようなオーディオ形式を再生できます。 ただし、WAVなどの他の形式を再生することはできません。

Javazoom Playerクラスを使用してサンプルクラスを作成しましょう。

String audioFilePath = "AudioFileWithMp3Format.mp3";
SoundPlayerUsingJavaZoom player = new SoundPlayerUsingJavaZoom();
try {
    BufferedInputStream buffer = new BufferedInputStream(
      player.getClass().getClassLoader().getResourceAsStream(audioFilePath));
    Player mp3Player = new Player(buffer);
    mp3Player.play();
} catch (Exception ex) {
    System.out.println("Error occured during playback process:" + ex.getMessage());
}

4. 結論

この記事では、Javaで音を鳴らす方法を学びました。 また、2つの異なるJavaサウンドAPI、ClipSourceDataLineについても学びました。 後で、ClipSourceDataLine APIの違いを確認しました。これは、あらゆるユースケースに適したAPIを選択するのに役立ちます。

最後に、オーディオを再生したり、MP3などの他の形式をサポートしたりできるサードパーティのライブラリをいくつか見ました。

いつものように、この記事で使用されているサンプルコードは、GitHubから入手できます。