问题
When I run FreeTTS examples, I get this error:
LINE UNAVAILABLE: Format is pcm_signed 16000.0 Hz 16 bits 1 channel big endian
In this post, Freetts problem in Java
someone claims it's a known Linux/Java sound bug and has a workaround,
linking to http://forums.sun.com/thread.jspa?threadID=5189363 .
But this link does not work anymore since Oracle screwed it. Archive.org seems not to have this page archived.
Does anyone have the workaround / patch for FreeTTS?
Thanks, Ondra
回答1:
Linux's ALSA is one large, complex API. OpenJDK and Sun's JDK seem to use it differently. Most modern Linux distributions also use PulseAudio, which virtualizes ALSA so that all audio goes through PulseAudio for software mixing before going to ALSA for playback.
When nothing is accessing the sound card, and Java is the only user, it tends to work. However when something else has the sound card open, Java apps quickly break with both your error and "javax.sound.sampled.LineUnavailableException: Audio Device Unavailable".
One potential workaround is to enumerate all mixers in the system with AudioSystem.getMixerInfo()
, then try to open the line with AudioSystem.getSourceDataLine(format, mixerInfo)
for the mixers you want. Some will work better than others. In particular the "Java Sound Audio Engine" and the "default [default]" mixers, if they exist, tend to work.
The only solution if you don't want to modify the FreeTTS source code though, is to install pulse-java. This registers a special PulseAudio sound provider, which bypasses the ALSA virtualization and goes directly to PulseAudio. Ubuntu installs this as part of its OpenJDK package.
Someone should really patch Java Sound to play with ALSA in a friendlier way. For one ALSA device names should be prefixed with plug:
to get ALSA to convert sound formats and sample rates on the fly. And the other rules for safe ALSA subset should also be followed.
回答2:
Hmm, I had better luck googling after asking the question, so...: http://workorhobby.blogspot.com/2011/02/java-audio-freetts-line-unavailable.html A big thanks to the author.
Update: Actually, this is not a nice workaround since it will keep FreeTTS on hold until the line is free.
FWIU, the mentioned patch had better solution - not demanding exclusive access or such.
Update: I've compiled a FreeTTS troubleshooting page.
A program based on FreeTTS, the free text-to-speech engine for Java, was getting occasional errors
"LINE UNAVAILABLE: Format is ..."
Turns out there is no Java Exception or other mechanism to detect this error that occurs inside the FreeTTS library. All you get is the message on System.out, so there is no good way to react programatically.
Workaround: Configure the FreeTTS audio player to attempt accessing the audio device more than once until it succeeds. In this example, a short delay of 0.1 seconds is used to not miss an opportunity to grab the audio device; we keep trying for 30 seconds:
System.setProperty("com.sun.speech.freetts.audio.AudioPlayer.openFailDelayMs", "100");
System.setProperty("com.sun.speech.freetts.audio.AudioPlayer.totalOpenFailDelayMs", "30000");
If the audio device is permanently used by another program, there is of course no way to get access. Under Linux, this command will display the ID of the process that is currently holding the audio device, so you can then try to get rid of the offending program:
/sbin/fuser /dev/dsp
回答3:
Regarding the link screwed by Oracle - given that older SO answer you refer mentions horrendous java linux sound bug that is still not fixed and suggests to check the third post, it is likely that lost thread was migrated to:
- https://forums.oracle.com/forums/thread.jspa?threadID=2206163
- above thread starts with reference to JMF Bug 4352921 at http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4352921_
- third post in the thread says "Yes, according to the API docs it's a "catastrophic" error from which no player can return safely. Which is why it's so strange to be able to trigger it so easily..."
- workaround to the problem discussed is described in the sixth post as follows:
I stumbled upon a blog post that suggested that Java needs to be told to use the OSS libraries as it's not yet up to ALSA. The command to use was "padsp" which forces the application to use OSS. So if I call "padsp jmstudio", it now plays and mixes the audio just fine. I tried it with my application also, which prefetches a number of players in the same JVM, and they all prefetched perfectly. So it would seem, for now, JMF applications on Linux may need to be called through padsp.
来源:https://stackoverflow.com/questions/5035826/freetts-java-linux-workaround-for-line-unavailable-format-is