なんとかJARファイル内の音源再生に成功

Java Clipをあきらめ、最初に扱ったSourceDataLineを使う方法でいろいろと挑戦した。もともと知識が足りないこともあり、なかなかうまくClipの時と同じような動作をさせることができないまま何日も経った。

一番困ったのは、一度再生を終えると最初に戻すことができない、ということだった。

あちこち見てまわっているうちに、「とりあえずプログラミング」の「JavaでWAVファイルを再生する(2)」という記事を発見。

とすると、どうすればいいかというと、再生位置を先頭に戻すには、一度close()してから再度open()するという処理しかなさそうです。さらに任意の位置に移動させるには、skip()を使うという方法しかないようです。

ということで、skip()を使おうとあれこれ思案したが、これまたなかなかうまくいかない。

次に、「akJとackeyシリーズ 開発日記」の「JavaでWavの部分再生簡単だなー。」という記事を発見。…何をどのように処理しているのかさっぱりわからない。
(T-T)

簡単と書いてあるのにまったくわからない自分の知識と経験のなさを痛感しつつも、もっと簡単にできるのでは、という思いだけは強く、結局まったく同じものを作ろうとすることなく悩み続けることとなった。

Threadの外部からの操作やフラグでの操作など、いろいろと試してみたところ、ふと気づくと、いつの間にかなんとなくでき上がっていた。偶然の産物なので、もっとすっきりさせることができるかもしれないが…。

AudioPlayer.java
import java.io.*;
import javax.sound.sampled.*;

class AudioPlayer {

  AudioInputStream stream;
  AudioFormat format;
  DataLine.Info info;
  SourceDataLine line;
  byte[] buf;
  long nBytesRead;
  boolean playFlag, pauseFlag;
  Thread playThread;
  String filename;

  private AudioPlayer() {
  }

  AudioPlayer(String fn) {
    load(fn);
  }

  public void load(String fn) {
    filename = fn;
    load();
  }

  public void load() {
    playFlag = false;
    pauseFlag = false;
    try {
     stream = AudioSystem.getAudioInputStream(getClass().getResource(filename));
      format = stream.getFormat();
      info = new DataLine.Info(SourceDataLine.class, format);
      line = (SourceDataLine)AudioSystem.getLine(info);
      line.open(format);
      //buf = new byte[line.getBufferSize()]; //大きい数値が入ると停止までに時間がかかる
      buf = new byte[128];
    } catch(Exception e) {
      e.printStackTrace();
    }
  }

  private void makePlayThread() {
    playThread = new Thread() {
      public void run() {
        try {
          int readBytes = 0;
          while(playFlag && readBytes != -1) {
            if(pauseFlag) {
              Thread.sleep(100);
            } else {
              readBytes = stream.read(buf, 0, buf.length);
              if(readBytes >= 0) {
                line.write(buf, 0, readBytes);
              }
            }
          }
          load();
          //line.drain();
        } catch(Exception e) {
          e.printStackTrace();
        }
      }
    };
  }

  public void play() {
    playFlag = true;
    resetFlag = false;
    if(line != null) {
      if(pauseFlag) {
        pauseFlag = false;
      } else {
        makePlayThread();
        line.start();
        playThread.start();
      }
    } else {
      System.out.println("再生するデータがありません。");
    }
  }

  public void pause() {
    pauseFlag = true;
    if(line.getLongFramePosition() == stream.getFrameLength()) {
      try {
        line.close();
        stream.close();
      } catch(Exception e) {
        e.printStackTrace();
      }
      load();
    }
  }

  public long getLength() {
    if(line != null) {
      return stream.getFrameLength();
    } else {
      return 0;
    }
  }

  public long getPosition() {
    if(line != null) {
      return line.getLongFramePosition();
    } else {
      return 0;
    }
  }

}


AudioPlayerTest.java
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

class AudioPlayerTest {

  JButton playButton, stopButton;
  JLabel counterLabel;
  JProgressBar pBar;
  AudioPlayer ap;

  public static void main(String[] args) {
    AudioPlayerTest apt = new AudioPlayerTest();
  }

  AudioPlayerTest() {
    ap = new AudioPlayer("sa00101.wav");
    playButton = new JButton("再生");
    stopButton = new JButton("停止");
    stopButton.setEnabled(false);
    ActionListener al = new ActionListener() {
      public void actionPerformed(ActionEvent ae) {
        playButton.setEnabled(!(playButton.isEnabled()));
        stopButton.setEnabled(!(stopButton.isEnabled()));
        if(ae.getSource() == playButton) {
          ap.play();
        } else {
          ap.pause();
        }
      }
    };
    playButton.addActionListener(al);
    stopButton.addActionListener(al);
    counterLabel = new JLabel("0", JLabel.RIGHT);
    pBar = new JProgressBar(0, (int)ap.getLength());
    JFrame frame = new JFrame(this.getClass().getSimpleName());
    frame.getContentPane().setLayout(new FlowLayout());
    frame.add(playButton);
    frame.add(stopButton);
    frame.add(counterLabel);
    frame.add(pBar);
    frame.setSize(350, 100);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
    long frameLength = ap.getLength();
    while(true) {
      if(ap.getPosition() == 0) {
        playButton.setEnabled(true);
        stopButton.setEnabled(false);
      }
      counterLabel.setText(ap.getPosition() + "/" + frameLength);
      pBar.setValue((int)ap.getPosition());
      try {
        Thread.sleep(200);
      } catch(Exception e ) {
        e.printStackTrace();
      }
    }
  }

}

これらのファイルの場所に音源ファイル「sa00101.wav」を置いて以下を実行。

javac *.java
java AudioPlayerTest

無事音がなったので、「mf.txt」を用意。

mf.txt
Main-Class: AudioPlayerTest

そして、以下を実行。

jar cvfm AudioPlayerTest.jar mf.txt *.class
jar uvf AudioPlayerTest.jar sa00101.wav
java -jar AudioPlayerTest.jar

どうやらstop()を使って再生中の音を止めると、その後うまくいかない。さらに、「byte[] buf」の配列を大きくすると、停止ボタンを押してもその配列に収まったデータの再生が完了するまで音は止まらない。そのため小さな値を入れてみたが、今後これが何かしら問題になるかもしれない。

しかし、とりあえず、なんとか自分の思い通りに動くところまできた。今後は音のなるものをいろいろと作ってみたい。…時間が作れれば。

関連する記事
コメント
コメントする








   
この記事のトラックバック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