Error while playing sound in Java - java

I'm trying to play a sound in my Java Application, but every time I call the method I get this exception: javax.sound.sampled.LineUnavailableException: line with format PCM_SIGNED 48000.0 Hz, 24 bit, mono, 3 bytes/frame, little-endian not supported.
Here's the code:
AudioInputStream audio = AudioSystem.getAudioInputStream(new File("src/media/ding2.wav"));
Clip clip = AudioSystem.getClip();
clip.open(audio);
clip.start();
I tried to play a file by passing a URL and it works fine, but with my "ding2.wav" nothing works.
Thanks in advance for your help.

By looking over HERE in Documention, the LineUnavailableException arises when the line is not Available, or the requested resource is in use by Another Application,
Make Sure that your audio file is not open in any other application.
EDIT
As the error message says :line with format PCM_SIGNED 48000.0 Hz, 24 bit, mono, 3 bytes/frame
the file format you are providing is not supported.
and as you said I tried to play a file by passing a URL and it works fine,
put the Old file back and check the file format by using
System.out.println(audio.getFormat());
and check what was the file format of that file , whether that was same to the above _line with format PCM_SIGNED 48000.0 Hz, 24 bit, mono, 3 _ or not,

Related

Converting mp3 to wav in Java

I'm writing a generalized utility for converting audio files to WAV. Works ok for WAV to WAV (I'm also changing some of the attributes), but I can't convert MP3 files. I have mp3spi in my classpath, so it seems to be able to read the MP3, but the WAV file that gets written doesn't seem to work.
In this example, I'm not trying to change any properties. Just reading the MP3 and writing to a WAV file
My code looks something like this
File inputFileObj = new File(input);
AudioInputStream audioInputStream = null;
try {
audioInputStream = AudioSystem.getAudioInputStream(inputFileObj);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Input file format:");
System.out.println(AudioSystem.getAudioFileFormat(inputFileObj));
try {
AudioSystem.write(audioInputStream, outputType, new File(output));
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Output file format:");
System.out.println(AudioSystem.getAudioFileFormat(new File(output)));
Here's the output. As you can see, it appears to write the output file, but when I try to retrieve the format of the output file, it can't handle it. And if I try to play the output file, the player doesn't recognize it.
Input file: c:\testfiles\sample-b-converted.mp3
Output file: c:\testfiles\foo.wav
Output type: wav
Input file format:
MP3 (.mp3) file, byte length: 13227300, data format: MPEG2L3 16000.0 Hz, unknown bits per sample, mono, unknown frame size, 27.777779 frames/second, , frame length: 122475
Bytes written: 13227344
Output file format:
Exception in thread "main" javax.sound.sampled.UnsupportedAudioFileException: file is not a supported file type
at javax.sound.sampled.AudioSystem.getAudioFileFormat(AudioSystem.java:1078)
at org.torchai.AudioFileConvert01.main(AudioFileConvert01.java:60)
Is there something else I need to get this working?
Someone posted a comment referring me to mp3 to wav conversion in java. I had seen this issue, but didn't quite see the main aspect of the answer, since it wasn't really explained well.
An MP3 file apparently needs to go through a 2-step conversion. I don't fully understand why, but it seems you must first convert it to PCM_SIGNED with a sample size of 16 and a framesize of 2*# of channels. At that point, you can convert it again to the final format that you want.
Would still love to have a better explanation, but this at least gets me past my issue.

Ubuntu 16.4, Java, WAV file playback

This is a weird thing. I'm trying to playback some sounds via Java AudioSystem and AudioSystem.getClip(). The files are all "PCM_SIGNED, 22.050.0 Hz, 16 bit, mono, 2 bytes/frame, little endian".
On several Ubuntu 16.4 LTS Linux boxes this format is rejected by PulseAudio with an Invalid Format Exception, because the only accepted format is seemingly "PCM_SIGNED, unknown sample rate, 16 bit, stereo, 4 bytes/frame, big endian".
I already tried to re-sample my WAVs in order to match this strange constraint, to no avail. Those are not even accepted anymore by AudioSystem.getAudioInputStream()
Needless to say, that the same works fine on Mac OS and Windows. And there is also no problem to playback these files using the sox library and play file.wav
OK, solved.
Usually if one asks, how to playback WAV using Java, this is the most common answer:
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(DragonflyApp.class.getResource("/resources/" + soundFile));
clip = AudioSystem.getClip();
clip.addLineListener(e -> {
if (e.getType() == LineEvent.Type.STOP) {
// Do something on end of playback
}
});
clip.open(audioInputStream);
clip.start();
Unfortunately on some Linux systems this ends up in an "Invalid Format" exception, thrown by PulseAudio, which claims to be unable to playback the simplest WAV file (see above).
The workaround is to use this sequence under Linux instead. It generally does also work on MacOS, but the final "STOP" indication comes very late (roughly 5s after playback end), so I make a conditional execution here:
This works on Linux (at least on Ubunutu 16.04) with clips, which have formerly been rejected by PulseAudio:
DataPusher datapusher = null;
DataLine.Info lineinfo = null;
SourceDataLine sourcedataline = null;
lineinfo = new DataLine.Info(SourceDataLine.class, audioInputStream.getFormat());
if (!(AudioSystem.isLineSupported(lineinfo))) {
return;
}
sourcedataline = (SourceDataLine) AudioSystem.getLine(lineinfo);
sourcedataline.addLineListener(e -> {
if (e.getType() == LineEvent.Type.STOP) {
// Do something on end of playback
}
});
datapusher = new DataPusher(sourcedataline, audioInputStream);
datapusher.start();
Both code snippets are used conditionally:
if (System.getProperty("os.name").equals("Mac OS X")) {
// The clip solution
}
else {
// The datapusher solution
}
Hope, that helps others, who will also have this problem.

Java does not play multi channel wave file

I am unable to play a multi channel wave file in java using javax.sound.sampled package.
I am using an external USB 7.1 surround sound card from logilink.
The wave file is generated by myself. If I generate a stereo track, I am able to play the file. If I use the 6 channel track, I get the following error message:
javax.sound.sampled.LineUnavailableException: line with format PCM_SIGNED 48000.0 Hz, 16 bit, 6 channels, 12 bytes/frame, little-endian not supported.
I checked if the line is supported and it is by using this code
AudioFormat format = new AudioFormat(48000, 16, 6, true, false);
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
if (info.isFormatSupported(format)) {
// is supported
}
I play the wave file as follows:
AudioListener listener = new AudioListener();
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(clipFile);
Clip clip = null;
clip = AudioSystem.getClip();
clip.addLineListener(listener);
clip.open(audioInputStream);
clip.start();
Any idea what is wrong?

LineUnavailableException when loading audio clip with Java on RPi

My RPi is Zero W and using Raspbian Jessie 4.9.35 / Oracle JDK8 1.8.0_65.
I'm having problem with loading audio clips on Java Program with RPi.
I have two audio files named "piano_0.wav" and "piano_1.wav" and they are different audio files.
I used this to load the clip:
Clip loadClip(String path) {
Clip clip = null;
try {
clip = AudioSystem.getClip();
AudioInputStream stream = AudioSystem.getAudioInputStream(new File(path));
clip.open(stream);
} catch (Exception e) {
Logger.getLogger(MusicManager.class.getName()).log(Level.SEVERE, null, e);
}
return clip;
}
When I try to load piano_0.wav, there's no error logs and can play returned Clip. but When I try to load piano_1.wav program throws exception:
javax.sound.sampled.LineUnavailableException: line with format PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian not supported.
at com.sun.media.sound.DirectAudioDevice$DirectDL.implOpen(DirectAudioDevice.java:513)
at com.sun.media.sound.DirectAudioDevice$DirectClip.implOpen(DirectAudioDevice.java:1304)
at com.sun.media.sound.AbstractDataLine.open(AbstractDataLine.java:121)
at com.sun.media.sound.DirectAudioDevice$DirectClip.open(DirectAudioDevice.java:1085)
at com.sun.media.sound.DirectAudioDevice$DirectClip.open(DirectAudioDevice.java:1175)
at beatstairscmd.BeatStairsCMD.testMusicClip(BeatStairsCMD.java:81)
at beatstairscmd.BeatStairsCMD.main(BeatStairsCMD.java:42)
But when I used this code on my Desktop there's no problem to load more clips.
I already tried solutions with init the clip with other ways instead of AudioSystem.getClip() and there's no changes.
How should I fix this problem?

Issues with SourceDataLine format support

I have an application written in Java in which I need to play audio. I used OpenAL (with java-openal library) for the task however I would like to use WSOLA which is not supported by OpenAL directly. I found a nice java-native library called TarsosDSP which has support for WSOLA.
The library uses standard Java APIs for audio output. The issue occurs during the SourceDataLine setup:
IllegalArgumentException: No line matching interface SourceDataLine supporting format PCM_UNSIGNED 16000.0 Hz, 16 bit, mono, 2 bytes/frame, little-endian is supported.
I made sure the issue is not caused by the lack of permissions (ran it as root on Linux + tried it on Windows 10) and there are no other SourceDataLines used in the project.
After tinkering with the format I found out that the format is accepted when it's changed from PCM_UNSIGNED to PCM_SIGNED. It seems like a minor issue since only moving the byte range form unsigned to signed should be pretty easy. However it's weird that it's not supported natively.
So, is there some solution in which I wouldn't have to modify the source data?
Thanks, Jan
You don't have to move the byte range by hand. After you've created an AudioInputStream, you create another AudioInputStream, with a signed format and that is connected to the first unsigned stream. If you then read the data using the signed stream, the Sound API automatically converts the format. This way you don't need to modify the source data.
File fileWithUnsignedFormat;
AudioInputStream sourceInputStream;
AudioInputStream targetInputStream;
AudioFormat sourceFormat;
AudioFormat targetFormat;
SourceDataLine sourceDataLine;
sourceInputStream = AudioSystem.getAudioInputStream(fileWithUnsignedFormat);
sourceFormat = sourceInputStream.getFormat();
targetFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
sourceFormat.getSampleRate(),
sourceFormat.getSampleSizeInBits(),
sourceFormat.getChannels(),
sourceFormat.getFrameSize(),
sourceFormat.getFrameRate(),
false);
targetInputStream = AudioSystem.getAudioInputStream(targetFormat, sourceInputStream);
DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, targetFormat);
sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
sourceDataLine.open(targetFormat);
sourceLine.start();
// schematic
targetInputStream.read(byteArray, 0, byteArray.length);
sourceDataLine.write(byteArray, 0, byteArray.length);

Categories