- PR -

SoundAPIのLineの内部スレッドが停止しない

1
投稿者投稿内容
かずさ
会議室デビュー日: 2003/04/14
投稿数: 3
投稿日時: 2004-09-12 20:39
問題点:TargetDataLineを使用するとexitを使わないとプログラムが終了しない
OS:WindowsXP HomeEdition
JDK:1.4.2_05

はじめまして。
JAVA Sound API の TargetDataLine を使用して、
音声を取り込みたく考えています。

いろいろ調べ、音声の取り込みには成功したのですが、
Lineを、AudioSystemから得たり、startしたりすると、
どうやら内部でスレッドが作成されているようで、
そのスレッドはLineをcloseしても、stopしても消えることがありません。
試しにnullを代入してからgcしてみましたが、消えません。

そのためプログラムが終了してくれないのです。

JavaSoundDemoのソースを自分なりに解読してみましたが、
最終的にSystem.exitで処理を終了しているようでした。

マイクのようなクラスをつくりたいと思っているので、
できれば、exitによる終了は避けたいのです。

皆様のご教授をいただければ幸いです。

コード:
ソース
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.TargetDataLine;

public class TestSound {
	
	static void msg(String msg){
		System.out.println(msg);
		System.out.println("Therad:"+Thread.activeCount());
		System.out.println();
	}
	
	static public void main(String args[]){ 
		msg("main_start");

		float sampleRate = 8000;
		int sampleSizeInBits = 8;
		int channels = 1;
		boolean signe = true;
		boolean bigEndian = true;
		AudioFormat format = new AudioFormat(
		       sampleRate,sampleSizeInBits,channels,signe,bigEndian);
		DataLine.Info info = new DataLine.Info(
                         TargetDataLine.class,format);
		TargetDataLine line=null;
		
		msg("target_line_create");
		try {
			line = (TargetDataLine)AudioSystem.getLine(info);
		} catch (LineUnavailableException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		}
		msg("tartget_line_create_end");
		
		
		msg("line_open");
		try {
			line.open(format);
		} catch (LineUnavailableException e1) {
			// TODO 自動生成された catch ブロック
			e1.printStackTrace();
		}
		msg("line_open_end");
		
		msg("line_start");
		line.start();
		msg("line_start_end");
		
		msg("line_stop");	
		line.stop();		
		msg("line_stop_end");	
		
		
		msg("line_close");	
		line.close();
		msg("line_close_end");	
		
		msg("main_end");
		
		System.exit(1);//これがないと終了しない
		
	}
}

実行結果:
main_start
Therad:1

target_line_create
Therad:1

tartget_line_create_end
Therad:2

line_open
Therad:2

line_open_end
Therad:2

line_start
Therad:2

line_start_end
Therad:3

line_stop
Therad:3

line_stop_end
Therad:3

line_close
Therad:3

line_close_end
Therad:3

main_end
Therad:3

Kissinger
ぬし
会議室デビュー日: 2002/04/30
投稿数: 428
お住まい・勤務地: 愛知県
投稿日時: 2004-09-12 23:45
かずささん、こんにちは。

かずささん正統派ですね。
System.exit()を使いたくない気持ちわかります。

この問題は、Java 2 SDK 1.3のときには既にありました。
なんか有名な問題のようで、検索で見つかった結果を示します。
(汚いトリックですが。)

http://www.jsresources.org/faq_misc.html より引用
引用:

How can I force my Java Sound program to terminate without using System.exit(int)?


The following is a really ugly trick, and we strongly recommend against using it. It interferes with internals of the JDK's Java Sound implementation, and it may not work in future versions.

final ThreadGroup tg = Thread.currentThread().getThreadGroup();
final Thread[] t = new Thread[tg.activeCount()];
final int active = tg.enumerate(t);
for (int i = 0; i < active; i++)
{
if (t[i].getName().indexOf("Sound") != -1)
{
t[i].interrupt();
}
}

This trick was provided by Sean A. Irvine. (Matthias)

かずさ
会議室デビュー日: 2003/04/14
投稿数: 3
投稿日時: 2004-09-13 03:05
Kissingerさん。返答ありがとうございます。
すぐにでも試し、結果をお知らせしたいのですが、
PCがそれを許してくる状態にはないのです。
実行出来しだい、報告させていただきますが、
直すのに時間がかかりそうなので、
さきにお礼をと思い書き込ませていただきました。
どうもありがとうございます。
英語サイトは見逃してました。
これからはそちらもよく見てから質問させていただきます。
お手数おかけしました。
かずさ
会議室デビュー日: 2003/04/14
投稿数: 3
投稿日時: 2004-09-13 19:23
試してみたところ、うまくいきました。
これでなんとかなりそうです。
ありがとうございました。

あとどうやら既出の内容だったようで、
スレッド全般の停止の話として扱われていました。
過去スレは一通り見たつもりだったのですが、甘かったようです。
お手を煩わせてすいません。
1

スキルアップ/キャリアアップ(JOB@IT)