Top | 日本の山岳データベース | GPS 入門 | 装備品 | 本棚 | 技術研究本部 | ブログ || 旧ウェブサイト
日本は山だらけ〜 技術研究本部 報告書 第二号 平成二十一年九月三十日 公開

合成したサウンドを Java で再生する

更新:コードのライセンスを MIT ライセンスに変更しました。(平成二十四年五月十日)

概要

(このレポートはブログで紹介したものと基本的に同じです。)

コンピュータ上で合成した音の波形データを、 Java 言語を用いて再生する方法を調査しました。 最終的な目標は、モールス符号発生・練習プログラムを Java で作成することです。 必要な要素技術をここで紹介しながら、プログラムの作成を進めたいと思います。 インターネットで検索すると、リアルタイムに波形データを合成し、即、再生する、 という方法はわりと多く紹介されているのですが、そこまで高度な事ではなく、 あらかじめ作成しておいたデータを再生するだけで今回は十分です。 今回はまず、サイン波をメモリ上に合成しそれを再生する、ということに挑戦しました。

基本

Java を開発しているサン・マイクロシステムズが「Java Sound プログラマーズガイド」というドキュメントを出しています。 基本的にこのドキュメントに必要な情報がすべて載っています。 メモリ上にある音声波形データを再生するには javax.sound.sampled パッケージの Clip インターフェイスを用いれば良いようです。 Java のサウンド機能はかなりの高機能ですが、とりあえず再生するだけでしたら、 同じく java.xound.sampled パッケージの AudioSystem クラスにある getClip() メソッドを用いれば、デフォルトの Clip オブジェクトを取得可能です。これに音データのフォーマットの情報を AudioFormat クラスで、再生するデータを byte[] (byte の配列) で用意すれば、 すぐさま再生が可能です。
▲ Top

サンプルプログラム

プログラムは「MIT ライセンス」に従うことを条件に自由に利用できます。

解説

音質にこだわる必要は全くありませんので、モノラル・ 8 kHz ・ 8 bit (CD はステレオ・44.1 kHz・16 bit)でデータを作成します。 AudioFormat クラスのコンストラクタでこれらの情報を指定し、 AudioFormat クラスのオブジェクトを作成します。

サイン波はラの音=440 Hz のサイン波を作成します。 Math.sin() 関数でサイン波を合成します。 1 Hz の音は 0 度から 360 度までのサイン関数の値を 1 秒間で再生すれば得られます。 実際のサイン関数の引数(角度)の単位はラジアンですので 0 から 2 π までです。 440 Hz の音は 1 秒間に 440 回。つまり 0 から 2 π × 440 までを 1 秒の間に再生すれば良いことになります。 サンプリングレート 8 kHz では 1 秒間に 8000 個のデータを流し込む、 というわけですので 2 π × 440 を 8000 で割った値が、 1 個のデータで進むサインの角度になります。

合成するサイン波の振幅は、今回 8 bit でデータを作りますので -127 〜 127 の値になるようにサイン関数の値を単純にこれに掛ければ OK です。 計算した値をそのまま byte 配列に入れていけばデータの発生は完了です。

あとは AudioSystem.getClip() メソッドで取得した Clip をフォーマット情報と再生データを指定して open() し、start() で再生します。最後は close() で閉じます。Clip#drain() を用いると、再生した音が終了するのを待つことができます。 (待たずに別の処理をすることも可能です。)

コード

/*
  SoundTest1.java

  Make a sine wave sound of 440 Hz for 1 second.

  Copyright (C) 2009 Yamadarake
*/

import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;

public class SoundTest1 {
  public static void main(String[] args){
	/* ------------------------------------------------- */
	/* Parameters                                        */
	/* ------------------------------------------------- */
	int samplingRate = 8000; /* [Hz] : Sampling rate */
	int length = 1; /* [s] : Length of sound */
	int tone = 440; /* [Hz] : Pitch of sound. 440 [Hz] = 'la' */
	int bit = 8; /* [bit] : Quantization bit rate */

	/* For storing a sine wave. */
	byte[] data = new byte[samplingRate * length];

	/* ------------------------------------------------- */
	/* Generate a sine wave                              */
	/* ------------------------------------------------- */
	/* Radian (angle) of a sine wave with respect to 1 sample. */
	double rad = tone * 2 * Math.PI / samplingRate;

	/* Maximum amplitude = 2^(bit-1) - 1 */
	double max = (1 << (bit - 1)) - 1;

	/* Generation of a sine wave. */
	for(int i = 0; i < samplingRate * length; i++){
	  data[i] = (byte) (Math.sin(rad * i) * max);
	}

	/* ------------------------------------------------- */
	/* Prepara and play the sound                        */
	/* ------------------------------------------------- */
	/* Format */
	AudioFormat format = 
	  new AudioFormat((float) samplingRate, /* Sampling Rate (float) */
					  8,      /* Bits (int) */
					  1,      /* Num of channels. 1 = mono, 2 = stereo */
					  true,   /* Signed (true) or unsigned (false) */
					  true    /* Big (true) or little (false) endian */
					  );
	
	try {
	  /* Obtaining the default clip. */
	  Clip clip = AudioSystem.getClip();

	  /* Open the clip */
	  clip.open(format,  /* Format of the sound to play */
				data,    /* Data to play */
				0,       /* Start position of data */
				samplingRate * length); /* Buffer size */

	  clip.start(); /* Start to play */
	  clip.drain(); /* Wait for the sound to be finished */
	  clip.close(); /* Close the clip */
	  
	} catch(LineUnavailableException e){
	  System.err.println("Error. Cannot open the default clip.");
	  System.exit(1);
	}
  }
}
/* End of file.  Copyright (C) 2009 Yamadarake */

実行例。プログラムのコンパイル・実行には Java の開発環境が必要です。

$ javac SoundTest.java   # コンパイル
$ java SoundTest         # 実行
▲ Top



Copyright © 2007-2012   やまだらけ   無断転載禁止   Since 2007/7/26   このウェブサイトについて
当ウェブサイトで使用しているテキスト、情報、画像等の権利は、明記してある場合を除き全て やまだらけ に帰属します。無断転載は一切禁止します。 当データベースの情報に限り、複製・二次利用等は出典を明記すれば自由に行うことができます。