Sound Process Error

I'm currently developing a software using JavaTM Sound API which plays a numeric sound inputed from numeric keys.

The Software finds numeric wav file matches the number inputed from numeric key and plays it in order.

I have wav files plays "0" to "999" numeric sound , "thousands" and "ten thousands".

For example if "1300" is inputed from numeric key, it finds "1" wav file, "thousand" wav file and "300" wav file to play "1300".

If another numeric key is pressed while playing sound, it quit playing current sound and plays the sound of inputed sound.

There are no problem if the key is pressed slowly, however, if the key is pressed rapidly, I get hs_err_pid2240.log and the process is terminated.

Here is the part of hs_err_pid2240.log.

#

# An unexpected error has been detected by HotSpot Virtual Machine:

#

# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x6d5126c8, pid=2240, tid=2352

#

# Java VM: Java HotSpot(TM) Client VM (1.5.0_06-b05 mixed mode)

# Problematic frame:

# C [jsoundds.dll+0x26c8]

#

THREAD

Current thread (0x008a03f0): JavaThread "Thread-7" [_thread_in_native, id=2352]

siginfo: ExceptionCode=0xc0000005, reading address 0x00000010

Registers:

EAX=0x0d9d70a0, EBX=0x0b70fad8, ECX=0x00000000, EDX=0x00000c22

ESP=0x0b70fa94, EBP=0x0b70faac, ESI=0x0e2700f0, EDI=0x0e272770

EIP=0x6d5126c8, EFLAGS=0x00210202

Top of Stack: (sp=0x0b70fa94)

0x0b70fa94:0d9d70a0 0b70fad4 0b70fad8 0e272770

0x0b70faa4:0e2700f0 008a03f0 0b70fadc 6d512a8b

0x0b70fab4:0e2700f0 0b70fad4 0b70fad8 0b70fae4

0x0b70fac4:00000001 00000c22 00000001 02c44e70

0x0b70fad4:0e2700f0 0e2700f0 0b70fb08 6d511bae

0x0b70fae4:0e2700f0 00000001 00d19c4d 008a04b0

0x0b70faf4:0b70fb04 0e272770 00000000 00000001

0x0b70fb04:07377b20 0b70fb68 00d0070d 00000001

Instructions: (pc=0x6d5126c8)

0x6d5126b8:0f 84 9f 00 00 00 8b 5d 10 8b 08 53 ff 75 0c 50

0x6d5126c8:ff 51 10 85 c0 0f 8c 9f 00 00 00 8b 7d 14 8b 4e

Stack: [0x0b6d0000,0x0b710000), sp=0x0b70fa94, free space=254k

Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)

C [jsoundds.dll+0x26c8]

C [jsoundds.dll+0x2a8b]

C [jsoundds.dll+0x1bae]

J com.sun.media.sound.DirectAudioDevice$DirectDL.drain()V

J com.abc.sound.SoundControl.play(Ljava/lang/String;)V

J com.abc.sound.SoundControl.pooling()V

v ~OSRAdapter

j com.abc.sound.SoundControl.run()V+1

v ~StubRoutines::call_stub

V [jvm.dll+0x845a9]

V [jvm.dll+0xd9317]

V [jvm.dll+0x8447a]

V [jvm.dll+0x841d7]

V [jvm.dll+0x9ed69]

V [jvm.dll+0x109fe3]

V [jvm.dll+0x109fb1]

C [MSVCRT.dll+0x2a3b0]

C [kernel32.dll+0xb683]

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)

J com.sun.media.sound.DirectAudioDevice.nIsStillDraining(JZ)Z

J com.sun.media.sound.DirectAudioDevice$DirectDL.drain()V

J com.abc.sound.SoundControl.play(Ljava/lang/String;)V

J com.abc.sound.SoundControl.pooling()V

v ~OSRAdapter

j com.abc.sound.SoundControl.run()V+1

v ~StubRoutines::call_stub

THREAD END

Here is the actual programme source.

package com.abc.sound;

import java.io.FileInputStream;

import java.io.InputStream;

import java.util.*;

import javax.sound.sampled.AudioFormat;

import javax.sound.sampled.AudioInputStream;

import javax.sound.sampled.AudioSystem;

import javax.sound.sampled.DataLine;

import javax.sound.sampled.SourceDataLine;

import com.abc.center.Path;

public class CopyOfSoundControl extends Thread {

private List playlist = new LinkedList();

private AudioFormat format;

private SourceDataLine pline = null;

private AudioInputStream ais;

private boolean playflg = false;

private static final int EXTERNAL_BUFFER_SIZE = 15;

private ThreadWatch tw = ThreadWatch.getIncetance();

public void run(){

this.pooling();

}

public synchronized void pooling( ){

while( true ){

if( this.playlist.size() <= 0 ){

try{

this.wait();

}catch( Exception e ){

}

}

try{

this.play( (String)this.playlist.remove( 0 ) );

}catch( Exception e ){

}

}

}

public void addSound( List list ){

try{

this.playflg = false;

if( this.pline != null ){

this.pline.flush();

this.pline.stop();

}

if( this.playlist.size() > 0 ){

this.playlist.clear();

}

this.sync( list );

}catch( Exception e ){

}

}

public synchronized void sync( List list ){

try{

this.playlist.clear();

this.playlist.addAll( list );

notifyAll();

}catch( Exception e ){

}

}

private AudioInputStream getAudioInputStream( String name ) throws Exception {

AudioInputStream audioInputStream = null;

InputStream is = null;

try{

is = new FileInputStream( Path.SOUND_DIR + name + ".wav" );

}catch( Exception e ){

is = new FileInputStream( Path.SOUND_DIR + name + ".WAV" );

}

audioInputStream = AudioSystem.getAudioInputStream( is );

return audioInputStream;

}

private SourceDataLine createLine( AudioInputStream audioInputStream ) throws Exception {

this.format = audioInputStream.getFormat();

DataLine.Info info = new DataLine.Info(SourceDataLine.class,format);

SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info);

line.open( this.format );

return line;

}

private void play( String name ) throws Exception {

AudioInputStream as = this.getAudioInputStream( name );

this.ais = as;

SourceDataLine line = createLine( as );

this.pline = line;

this.pline.addLineListener( new SoundControlListner( this.pline ) );

this.playflg = true;

this.pline.start();

int nBytesRead = 0;

byte[] abData = new byte[EXTERNAL_BUFFER_SIZE];

long waittime = System.currentTimeMillis();

try{

while (nBytesRead != -1) {

if( !this.playflg ){

throw new Exception( );

}

nBytesRead = this.ais.read(abData, 0, abData.length);

if( !this.playflg ){

throw new Exception( );

}

if (nBytesRead >= 0) {

if( !this.playflg ){

throw new Exception( );

}

int nBytesWritten = this.pline.write(abData, 0, nBytesRead);

if( !this.pline.isOpen() ){

throw new Exception( );

}

if( !this.playflg ){

throw new Exception( );

}

}

if(System.currentTimeMillis() - waittime > 10000 ) {

break;

}

}

}catch( Exception e ){

} finally {

try {

this.pline.drain();

} catch (RuntimeException e) {

}

}

this.pline.stop();

this.ais.close();

this.pline.close();

}

}

Just little note, When the key is pressed, wav file name is inserted into "List" and "addSound" method is called.

"addSound" method can be used by multiple thread.

I'm using 1.5.0_06-b05 JRE on WindowsXP.

I have spent lots of time to solve this problem. But still not found a solution to it.

Could please anyone help me?

Thank you.

[7504 byte] By [dmiwa@webjapan.co.jpa] at [2007-10-3 10:41:39]
# 1

Hi,

first I have to say, that there are some points I do not quite understand.

- The method pooling() is synchronized but once entered cannot be leaved. Therefore calling syncList() causes the current thread to wait forever (because the lock on "this" is never released by pooling()). Is this intended?

- Did you think about keeping the soundfiles in RAM instead of reading them in everytime a key is pressed?

- You create a line for every key press. Why don't you reuse the existing line? I don't think it uses that much system resources.

Maybe the first or third point get you around this strange problem.

And just some notes to your catching-exception style:

I absolutely recommend you not to cast your net to wide, when catching exceptions. Just catch the exception you are forced to by the compiler, but never catch an Exception just because you are too lazy to be more precise ;) The same goes for throwing Exceptions of course. The explanation is easy: If an runtime-exception occurs you didn't think of (NullPointerException or whatever), it gets catched and discarded and you don't even know about it!

DOMOa at 2007-7-15 6:05:25 > top of Java-index,Security,Cryptography...
# 2
Hi, sorry for the late reply.>DOMOThank you for your reply. I'm going to test what you have suggested. I'll get back as soon as I get a result. Thank you once again.
dmiwa@webjapan.co.jpa at 2007-7-15 6:05:25 > top of Java-index,Security,Cryptography...