JavaのClipで音再生

前回無事Clipを使った再生ができた。そこで、GUIを使ってコントロールしようと試みたが、これがまたなかなかうまくいかない。

再生ボタンで再生し、停止ボタンをクリックすると一時的に止まり、再生ボタンで続きから再生する。ここまではうまくいったが、一度最後まで再生をすると、その後は再生できない。

いろいろ調べると、「ひでっぷの技術メモ」の「Clipで再生した音声ファイルが途中で途切れる」という記事で、Clipでは再生位置を覚えていて、再生終了時に再生位置を0に戻さなければならないことがわかった。

ところが、この記事のように組んでも動かない。これもLinuxのせい?

とりあえず、LineListenerを追加してupdate()内ではsetFramePosition(0)が実行されないことがわかった。

いろいろと考えて、ボタンをクリックしたタイミングで再生位置を確認し、終了位置ならば再生位置を0に戻すようにした。

また、実際にClipを再生してみると、getLongFramePosition()で得られる位置情報は自分の当初の考えとは異なっていた。

getLongFramePosition()で得られる位置は、1回目が終わり2回目の再生に入ると、1回目の終了位置からさらに数値が増えていく。たとえsetFramePosition(0)を行なっても、getLongFramePosition()で得られる情報は0には戻らないことがわかった。どこが再生されているかわかるように、JLabelとJProgressBarを使って再生位置を表示させてみた。

また、「音の再生」と「再生位置情報の表示」を行うためには、どうしてもThreadを使う必要があった。最初は「再生位置情報の表示」の方をThreadにして実行を試みたがうまく動かなかった。そのため、「音の再生」をThreadで行うとうまくいった。「音の再生」をThreadで行う方法は、「駆け出しプログラマの備忘録」の「JavaでWAVを再生するプログラム」に書かれていた。

ということで、次のようにつくったらうまく動いてくれた。

import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.sound.sampled.*;

class ClipPlayer2 {
  static Clip clip;
  static JFrame frame;
  static JButton playButton, stopButton;
  static JLabel counterLabel;
  static JProgressBar pBar;
  static int playCount, maxLength;

  public static void main(String[] args) {
    File file = new File("sa00101.wav");
    if(file.exists()) {
      try {
        AudioInputStream stream = AudioSystem.getAudioInputStream(file);
        AudioFormat format = stream.getFormat();
        DataLine.Info info = new DataLine.Info(Clip.class, format);
        clip = (Clip)AudioSystem.getLine(info);
        clip.open(stream);
        maxLength = clip.getFrameLength() - 1;
        clip.addLineListener(new LineListener() {
          public void update(LineEvent le) {
            if(le.getType() == LineEvent.Type.STOP) {
              if(maxLength * playCount == clip.getLongFramePosition()) {
                playButton.setEnabled(true);
                stopButton.setEnabled(false);
              }
            }
          }
        });
        stream.close();
        ClipPlayer2 cp2 = new ClipPlayer2();
        frame.setVisible(true);
        while(true) {
          counterLabel.setText(clip.getLongFramePosition() + "/" + maxLength);
          pBar.setValue((int)clip.getLongFramePosition() % (maxLength + 1));
          try {
            Thread.sleep(500);
          } catch(Exception e) {
            e.printStackTrace();
          }
        }
      } catch(Exception e) {
        e.printStackTrace();
      }
    } else {
      System.out.println("ファイルが見つかりませんでした。");
      System.exit(1);
    }
  }

  ClipPlayer2() {
    frame = new JFrame("ClipPlayer2");
    playCount = 1;
    playButton = new JButton("再生");
    stopButton = new JButton("停止");
    stopButton.setEnabled(false);
    ActionListener al = new ActionListener() {
      public void actionPerformed(ActionEvent ae) {
        if(ae.getSource() == playButton) {
          playButton.setEnabled(false);
          stopButton.setEnabled(true);
          if((long)(clip.getFrameLength() - 1) * playCount == clip.getLongFramePosition()) {
            clip.stop();
            clip.setFramePosition(0);
            playCount++;
          }
          play();
        } else {
          playButton.setEnabled(true);
          stopButton.setEnabled(false);
          clip.stop();
        }
      }
    };
    playButton.addActionListener(al);
    stopButton.addActionListener(al);
    counterLabel = new JLabel("0", JLabel.RIGHT);
    pBar = new JProgressBar(0, maxLength);
    frame.getContentPane().setLayout(new FlowLayout());
    frame.add(playButton);
    frame.add(stopButton);
    frame.add(counterLabel);
    frame.add(pBar);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(350,100);
    frame.setLocationRelativeTo(null);
  }

  public void play() {
    new Thread() {
      public void run() {
        clip.start();
      }
    }.start();
  }

}

ClipPlayer2


「otosozai.com」から音声データ「sa00101.wav」をいただいて実行してみた。再生・停止が無事操作できた。

コメント
コメントする








   
この記事のトラックバックURL
トラックバック

calendar

S M T W T F S
      1
2345678
9101112131415
16171819202122
23242526272829
3031     
<< July 2017 >>

selected entries

categories

archives

links

profile

書いた記事数:84 最後に更新した日:2016/09/11

search this site.

others

mobile

qrcode

powered

無料ブログ作成サービス JUGEM