Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 4347309
Votes 10
Synopsis Simultaneous capture/playback of audio does not work on Linux.
Category java:classes_sound
Reported Against 1.3 , ladybird-rc1
Release Fixed 1.4.2(mantis)
State 10-Fix Delivered, bug
Priority: 4-Low
Related Bugs
Submit Date 21-JUN-2000
Description




java version "1.3.0beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0beta-b07)
Java HotSpot(TM) Client VM (build 1.3.0beta-b04, mixed mode)

Operating System: Red Hat Linux 6.1 and 6.2

Environment (tried two different machines):
Machine 1:  customer  Dimension XPS R400 running Red Hat Linux 6.1, with 256 MB ECC
SDRAM, Ensonic AudioPCI model es1371 sound card.

Machine 2: PC running Red Hat Linux 6.2,  customer  440BX-2 motherboard, Celeron 400
MHz, 384 MB SDRAM, with SB Live! (emu10k1) sound card.

Both sound cards support full-duplex operation.

  Description:

Simultaneous capture/playback (full-duplex audio) appears to be broken in the
Linux release of JDK 1.3.0. I am able to run the Sun Java Sound demos, which do
not require full-duplex operation. The attached code illustrates the problem.
This program runs successfully under the Sun JDK 1.3 on Windows 2000, but does
not work under Linux. I have tried different formats, samples rates, buffers
sizes, but nothing works.

Error messages encountered: Program prints the following output and then hangs.
Opened playback line.
Opened capture line.
Capture started.
Playback started.
Trying to read data


More Java Sound examples that also require simultaneous capture/playback (and
also do not work) can be found at:
http://rupert.informatik.uni-stuttgart.de/~pfistere/jsexamples/


Example code: (Run it by typing javac Duplex1.java; java Duplex1)



import	javax.sound.sampled.DataLine;
import	javax.sound.sampled.SourceDataLine;
import	javax.sound.sampled.TargetDataLine;
import	javax.sound.sampled.AudioFormat;
import	javax.sound.sampled.AudioSystem;
import	javax.sound.sampled.LineUnavailableException;
import	javax.sound.sampled.AudioFileFormat;


/**  Duplex1.java written by Brian K. Vogel (  xxxxx@xxxxx  )
 *   Purpose: Test full-duplex capture/playback. Capture from mic/line-in
 *            and play captured audio to speaker.
 */
public class Duplex1
{
	public static void main(String[] args)
	{
	    TargetDataLine	targetLine;
	    SourceDataLine	sourceLine;
	    AudioFormat	audioFormat = new AudioFormat( 44100.0F, 16, 2, true, true);
	
		try
		{
		    
		DataLine.Info	sourceDataLineInfo = new DataLine.Info(SourceDataLine.class,
audioFormat);
		sourceLine = (SourceDataLine) AudioSystem.getLine(sourceDataLineInfo);
		sourceLine.open(audioFormat);
		System.out.println("Opened playback line.");
		
		DataLine.Info	targetDateLineInfo = new DataLine.Info(TargetDataLine.class,
audioFormat);
		targetLine = (TargetDataLine) AudioSystem.getLine(targetDateLineInfo);
		targetLine.open(audioFormat);
		System.out.println("Opened capture line.");

		// Start capture.
		targetLine.start();
		System.out.println("Capture started.");
		// Start playback.
		sourceLine.start();
		System.out.println("Playback started.");

		int buffSize = 4096;
		byte[]	sampleBuffer = new byte[buffSize];
		int bytesRead;
		while(true) {
		    System.out.println("Trying to read data");
		    bytesRead = targetLine.read(sampleBuffer, 0, buffSize);
		    System.out.println("Read data");
		    System.out.println("Trying to write data");
		    sourceLine.write(sampleBuffer, 0, bytesRead);
		    System.out.println("Wrote data");
		    System.out.println("************************");
		}

		}
		catch (LineUnavailableException e)
		{
			e.printStackTrace();
			System.exit(1);
		}

	}
}
(Review ID: 105809) 
======================================================================




13 Jan 2001,   xxxxx@xxxxx   -- seems related to #'s 4257234 & 4347309 (one
of which should be closed as a duplicate of the other).
-----------------
java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0)
Java HotSpot(TM) Client VM (build 1.3.0, mixed mode)


I swear I read that Java Sound API was supposed to be able to do full duplex if
the card supports it.  I know my card supports it, but I cannot get it to work.
This may not be a bug; maybe I just don't know how to do it, but I haven't been
able to find any information on how to do simultaneous playback and record
correctly.  Even though I'm using the same *instance* of AudioFormat to open
both lines, I consistently get the following exception:

javax.sound.sampled.LineUnavailableException: Requested format incompatible with
already established device format: PCM_SIGNED, 44100.0 Hz, 16 bit, stereo,
big-endian, audio data
	at com.sun.media.sound.AbstractMixer.open(AbstractMixer.java:271)
	at com.sun.media.sound.SimpleInputDevice.open(SimpleInputDevice.java:528)
	at com.sun.media.sound.AbstractDataLine.open(AbstractDataLine.java:83)
	at com.sun.media.sound.AbstractDataLine.open(AbstractDataLine.java:114)
	at SimpleMultiTracker$TinyRecorder.fileRecord(SimpleMultiTracker.java:138)
	at SimpleMultiTracker$TinyRecorder.run(SimpleMultiTracker.java:102)
	at java.lang.Thread.run(Thread.java:484)

Here's the sample program I've written while trying to figure out how this
works.  Please pardon the general crapiness of it; I'll design it right when I
figure out the details:

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

public class SimpleMultiTracker
{
    protected AudioFormat _audioFormat;

    public static void main(String[] args)
    {
        new SimpleMultiTracker().begin(args);

        return;
    }

    protected static class TinyPlayer implements Runnable
    {
        protected SimpleMultiTracker _parent;
        protected String _filename;

        public TinyPlayer(SimpleMultiTracker parent, String filename)
        {
            _parent = parent;
            _filename = filename;
        }

        public void run()
        {
            filePlayback(_filename);
        }

        protected void filePlayback(String filename)
        {
            SourceDataLine line = null;
            File file = null;
            AudioFileFormat fileFormat = null;
            AudioFormat audioFormat = null;
            DataLine.Info info = null;

            try
            {
                file = new File(filename);
                fileFormat = AudioSystem.getAudioFileFormat(file);
                // this is the AudioFormat we expect to use for recording as
                // well.
                audioFormat = fileFormat.getFormat();
                _parent.setAudioFormat(audioFormat);
                System.out.println(audioFormat);
                System.out.flush();
                info = new DataLine.Info(SourceDataLine.class, audioFormat);
            }
            catch(Exception e)
            {
                e.printStackTrace();
            }

            if(!AudioSystem.isLineSupported(info))
            {
                System.err.println("Line not supported: " + info);
                System.err.flush();
            }

            try
            {
                line = (SourceDataLine)AudioSystem.getLine(info);
                line.open(audioFormat);
                line.start();

                int bytesRead = 0;
                byte[] buf = new byte[1024];
                FileInputStream in = new FileInputStream(file);
                for(int total = 0; total < file.length() && bytesRead != -1;)
                {
                    bytesRead = in.read(buf, 0, 1024);
                    total += bytesRead;
                    line.write(buf, 0, bytesRead);
                }

                line.drain();
                line.stop();
                line.close();
                line = null;
            }
            catch(Exception e)
            {
                e.printStackTrace();
            }
        }
    }

    protected static class TinyRecorder implements Runnable
    {
        protected SimpleMultiTracker _parent;
        protected String _filename;

        public TinyRecorder(SimpleMultiTracker parent, String filename)
        {
            _parent = parent;
            _filename = filename;
        }

        public void run()
        {
            fileRecord(_filename);
        }

        protected void fileRecord(String filename)
        {
            TargetDataLine lineIn = null;
            AudioInputStream in = null;
            // clearly I'm using the same AudioFormat, because I'm referring
            // to the same instance that the player is using.  Naturally I
            // I tried it with a separate instance initially, but when that
            // didn't work, I tried this, which also didn't work.
            AudioFormat format = null;
            while(format == null)
            {
                format = _parent.getAudioFormat();
                try{Thread.sleep(1000);}
                catch(Exception e)
                {}
            }

            DataLine.Info info =
                new DataLine.Info(TargetDataLine.class, format);
            File file = null;

            try
            {
                file = new File(filename);
                lineIn = (TargetDataLine)AudioSystem.getLine(info);
                in = new AudioInputStream(lineIn);
            }
            catch(Exception e)
            {
                e.printStackTrace();
            }

            try
            {
                lineIn.open(format);
                lineIn.start();

                AudioSystem.write(in, AudioFileFormat.Type.WAVE, file);
            }
            catch(Exception e)
            {
                e.printStackTrace();
            }
        }
    }

    protected void begin(String[] args)
    {
        if(args.length != 2)
        {
            System.err.println("usage: " + getClass().getName() +
                               " fileToPlayback fileToRecord");
            System.err.flush();
            System.exit(1);
        }

        Thread player = new Thread(new TinyPlayer(this, args[0]));
        Thread recorder = new Thread(new TinyRecorder(this, args[1]));

        player.start();
        recorder.start();
    }

    protected AudioFormat getAudioFormat()
    {
        return _audioFormat;
    }

    protected void setAudioFormat(AudioFormat audioFormat)
    {
        _audioFormat = audioFormat;
    }
}
(Review ID: 114260)
======================================================================
Work Around
N/A
Evaluation
  xxxxx@xxxxx   2002-11-02
	Changed synopsis to include Linux, since this is a linux-specific bug. This bug should be fixed with ALSA support in 1.4.2 (of course, ALSA 0.9 needs to be installed on the Linux system).
Comments
  
  Include a link with my name & email   

Submitted On 28-NOV-2000
oligold
I ran into the same problem and didn't know if it was
something wrong with the sound card.  

Olivier.


Submitted On 09-MAY-2001
insaar
I have the same problem... and I don't want to hurt anybody, but it seems to be a
Java problem, that Java cannot implement sound fullduplex...


Submitted On 03-AUG-2001
jallonzyn
i tried the latter program again on my winME+jdk1.3.0.02.
the results are same:

C:\>javac SimpleMultiTracker.java

C:\>java SimpleMultiTracker
usage: SimpleMultiTracker fileToPlayback fileToRecord

C:\>java SimpleMultiTracker setup0.wav tst1.wav
PCM_UNSIGNED, 22050.0 Hz, 8 bit, stereo, audio data
javax.sound.sampled.LineUnavailableException: Requested 
format incompatible with
 already established device format: PCM_SIGNED, 44100.0 Hz, 
16 bit, stereo, big-
endian, audio data
        at com.sun.media.sound.AbstractMixer.open(Unknown 
Source)
        at com.sun.media.sound.SimpleInputDevice.open
(Unknown Source)
        at com.sun.media.sound.AbstractDataLine.open
(Unknown Source)
        at com.sun.media.sound.AbstractDataLine.open
(Unknown Source)
        at SimpleMultiTracker$TinyRecorder.fileRecord
(SimpleMultiTracker.java:13
7)
        at SimpleMultiTracker$TinyRecorder.run
(SimpleMultiTracker.java:100)
        at java.lang.Thread.run(Unknown Source)


Submitted On 15-OCT-2001
basashi
add more things.
now I'm downloading IBM jdk1.3 and installing.
and run same program is work!!


Submitted On 15-OCT-2001
basashi
I have the same problem too. on Vine linux 2.1 & Ess1968
maestro2 sound card & build 1.4.0-beta2-b77, mixed mode (
same if use jdk1.3.1 )...but If I get rebooting to windows
98, 
no problems happen. I can start TargetDataLine,
SourceDataLine smooth.


Submitted On 06-NOV-2001
shahr00z
me too, I have ran my app on Win2000 prof,but there was an 
Exception UnavailableFileFormat even when I have opened it 
on network streams.


Submitted On 19-MAR-2002
rasmuskjellman
Same problem as jallonzyn... Really annoying.


Submitted On 09-JAN-2003
jmccaughey
how is this closed or fixed?


Submitted On 09-FEB-2004
beltdar
I've got the same problem!!!...i'm doing an Audio 
Conferencing Aplication and I cannot open 
SourceDataLine (speakers for incoming sound from 
the network) and TargetDataLine (microphone for 
sending sound to the network).....
I've read the entire Java Sound User's Guide and it 
doesn't make any reference to simoultaneous 
playback and recording or something like that.

I really believe it doesn't work and  it's not hardware 
problem.

P.D: I'm using WinXP




Submitted On 02-SEP-2004
JavaInstruments
Well, I wrote a code similar to Duplex1.java (see (Review ID: 105809) ), where input is mike and output is speaker, and I get the buffer size from  mike.getBufferSize()/5 (or /25, /55, /10) and although is plays on Windows 2000,  java 1.4.2.04 SE, it does it with a "fixed" delay of about a second, without losing frames. I know that Java may not be the fastest language and I expected to have problems with continuous data stream from device to device, specially for long buffering or delay between reads and writes from and to streams. However, because I don't seem to observe loss of sound, I wonder what could be the problem?

Please, contact me at luizcosta@sbcglobal.net



PLEASE NOTE: JDK6 is formerly known as Project Mustang