Does anyone have an example of how I can play an 24-192 HD FLAC file with JustFLAC?
JustFLAC is an fork of jFLAC and is claiming it can play this types of files.
package org.kc7bfi.jflac.apps;
class Player {
public static void main(String[] args) {
try {
Player decoder = new Player();
// FLAC HDTracks 24-192
String f = "hdflacfile.flac";
decoder.decode(f);
Throws this exception:
Exception in thread "main" java.lang.IllegalArgumentException: No line matching interface SourceDataLine supporting format PCM_SIGNED 192000.0 Hz, 24 bit, stereo, 6 bytes/frame, little-endian is supported.
I have tried a lot of files.
I'm on WIN8 and Java6.
JustFLAC or similar "small" packages is what I need information about.
What is happening is that the JustFLAC code is saying that the audio format of the FLAC file is 'PCM_SIGNED 192000.0 Hz, 24 bit, stereo, 6 bytes/frame, little-endian' (which looks correct).
The player code will then be asking the output device for a SourceDataLine which matches this format so that it can write the decoded data to the line. However the output device is throwing an exception saying that it does not support this format.
This may be because the actual device does not support this format or it may be that the Java Sound API does not support it. Certainly on the Mac version of Java 6 the Java Sound API did not support 24 bit output, this was changed in Java 7 (and 8). Testing on my Mac with Java 8 a 24 bit 192Khz file plays OK.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
Now there seems to be a lot of questions about the Java API itself, but I'm facing a problem I haven't found anywhere: My code runs fine if I run it directly from the class file, but it refuses to work as soon as I put it in a JAR.
public static void main(String[] args) {
Mixer.Info[] mixerInfo = AudioSystem.getMixerInfo();
for (Mixer.Info info: mixerInfo) {
Mixer mixer = AudioSystem.getMixer(info);
Line.Info[] targetLineInfo = mixer.getTargetLineInfo();
for (Line.Info lineInfo: targetLineInfo) {
try {
Line line = mixer.getLine(lineInfo);
line.open(); //<---- problematic line
System.out.println("Success: Opened line " + line.getLineInfo());
if (line.getLineInfo().getLineClass().equals(TargetDataLine.class)) {
TargetDataLine dataLine = (TargetDataLine) line;
byte[] read = new byte[16];
dataLine.start();
dataLine.read(read, 0, 16);
dataLine.stop();
System.out.println("Success: Finished reading from line " + line.getLineInfo());
}
line.close();
} catch (LineUnavailableException e) {
System.out.println("Error: " + e.getMessage());
}
}
}
}
So for this very simple example, the following runs as expected:
src>javac AudioTest.java
src>java AudioTest
Success: Finished reading from line interface TargetDataLine supporting 8 audio formats, and buffers of at least 32 bytes
Success: Finished reading from line interface TargetDataLine supporting 8 audio formats, and buffers of at least 32 bytes
Building a jar out of this yields the following result:
src>jar cfe AudioTest.jar AudioTest AudioTest.class
src>jar tf AudioTest.jar
META-INF/
META-INF/MANIFEST.MF
AudioTest.class
The problem arises when trying to run this jar:
src>java -jar AudioTest.jar
Error: line with format PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian not supported.
Error: line with format PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian not supported.
Running the main class manually and putting the jar on the classpath works as expected.
src>java -classpath .\AudioTest.jar AudioTest
Success: Finished reading from line interface TargetDataLine supporting 8 audio formats, and buffers of at least 32 bytes
Success: Finished reading from line interface TargetDataLine supporting 8 audio formats, and buffers of at least 32 bytes
I'm completely stumped at this point. Any help is appreciated.
I am working on Google cloud Speech-to-text samples.
I took a sample from from this link GoogleCloudPlatform speech to text sample
And I referred Quickstart: Using Client Libraries
Sample files given in that example works fine. It gives text of that audio file.
But If I give my own audio file, it does not returns anything.
Cloud request includes audio file, AudioEncoding and SampleRateHertz.
Issue may be in AudioEncoding and SampleRateHertz of my own audio file.
How to identify AudioEncoding and SampleRateHertz of an audio file?
AudioEncoding's Java enum has the following possible values:
AudioEncoding.AMR -> .awb/.3gp files
AudioEncoding.AMR_WB -> .awb/.3gp files
AudioEncoding.FLAC -> .flac files
AudioEncoding.LINEAR16 -> .wav files
AudioEncoding.MULAW -> .wav files
AudioEncoding.OGG_OPUS -> .ogg/.opus files
AudioEncoding.SPEEX_WITH_HEADER_BYTE -> no clue, maybe .speex
So you could make a first guess by the file extension, for the SampleRateHertz you could use a tool like Tika by Apache. This outputs for the commercial_stereo.wav the following:
Content-Length: 6305632
Content-Type: audio/vnd.wave
X-Parsed-By: org.apache.tika.parser.DefaultParser
X-Parsed-By: org.apache.tika.parser.audio.AudioParser
X-TIKA:digest:MD5: 7e3e8837273e8bb143533894926f7da3
X-TIKA:digest:SHA256: 98fac004fb662ad8f720e680c81e3b4c9dea20190f5d1d908cece2cd6b30f01e
bits: 16
channels: 2
encoding: PCM_SIGNED
resourceName: commercial_stereo.wav
samplerate: 44100.0
xmpDM:audioSampleRate: 44100
xmpDM:audioSampleType: 16Int
I'm working on a system to play, pause and stop music. I'm testing this out with 2 different wav files, one with a length of 45 seconds and other with a length of 3:35 minutes. The problem I'm having is that the 45 second wav file plays without any problem. The 3:35 minute wav file on the other hand, doesn't load. Is there a maximum time limit to wav files in java or is it possible the wav file is broken? It plays without any problem on windows app "groove music".
I've searched around on stack overflow but no one seemed to experience the same problem as I am, one wav file playing, the other one not.
Error code I'm getting:
javax.sound.sampled.LineUnavailableException: line with format PCM_FLOAT 44100.0 Hz, 32 bit, stereo, 8 bytes/frame, not supported.
The method i use for playing the wav file.
public static void playAudio(String name) {
try {
System.out.println("NOTE: Playing audio");
clip = AudioSystem.getClip();
AudioInputStream inputStream = AudioSystem.getAudioInputStream(
Engine.class.getResourceAsStream("/Audio/" + name));
clip.open(inputStream);
clip.start();
} catch(Exception e) {
System.out.println("ERROR: Failed to load audio");
}
}
Calling the method
Engine.playAudio("easy2.wav");
Picture of the wav files in the "src/Audio/" folder
Given the error message, one thing you could try is after opening the AudioInputStream from the resource, do the following:
AudioFormat fmt = inputStream.getFormat();
fmt = new AudioFormat(fmt.getSampleRate(),
16,
fmt.getChannels(),
true,
true);
inputStream = AudioSystem.getAudioInputStream(fmt, inputStream);
This attempts to convert the stream away from a floating-point format, hopefully to something that the system is more likely to support. (Also see JavaDoc for AudioSystem.getAudioInputStream(AudioFormat, AudioInputStream).)
You can run the following code to find out what formats are likely available for playback:
Arrays.stream(AudioSystem.getSourceLineInfo(new Line.Info(SourceDataLine.class)))
.filter(info -> info instanceof DataLine.Info)
.map(info -> (DataLine.Info) info)
.flatMap(info -> Arrays.stream(info.getFormats()))
.forEach(System.out::println);
If the above method of converting the audio stream doesn't work, then probably your best bet is to just convert the file with some editor, such as Audacity. Java sound is unfortunately still pretty limited in what formats it supports by default. (The most reliable format is probably CDDA, which is 44100Hz, 16-bit signed LPCM.)
There may also be 3rd-party SPIs which support conversions from floating-point PCM.
The problem I was facing originated in the wav file itself. Since a wav file can have one of several different formats, the one it was encoded with was not compatible with java. The solution was to change the bitrate and Hz of the wav file to match an encoding that java supported.
More about wav formats: https://en.wikipedia.org/wiki/WAV
What I'm trying now (don't mind about the syntax - it's Kotlin):
audioFormat = AudioFormat(8000f, 8, 2, true, false)
mixerInfo = AudioSystem.getMixerInfo()
mixer = AudioSystem.getMixer(mixerInfo[0]) // have tried all
dataLineInfo = DataLine.Info(TargetDataLine::class.java, audioFormat)
dataLine = mixer.getLine(dataLineInfo) as TargetDataLine // IllegalArgumentException
dataLine.open()
dataLine.start()
AudioSystem.write(AudioInputStream(dataLine), AudioFileFormat.Type.WAVE, File("1.wav"))
Unfortunatelly a IllegalArgumentException is being thrown at mixer.getLine:
java.lang.IllegalArgumentException: Line unsupported: interface TargetDataLine supporting format PCM_SIGNED 8000.0 Hz, 8 bit, stereo, 2 bytes/frame, little-endian
I've tried all the available mixers and audio formats. Still no luck. The only working mixer is the microphone mixer. All the output-mixers cause the exception.
I've also tried to detect supported audio formats using AudioSystem.isLineSupported, but I coudn't detect any single format that would be supported by output-mixers. AudioSystem.isLineSupported always returns false for all the possible formats I've checked.
So, is it possible to record the sound I hear from speakers?
PS: There is some capture soft that can perform such record. For example, SnagIt 12 can record audio from my sound card. And there are lot of similar apps.
I am trying to make Java play different stereo audio in two outputs (front and back audio jacks).
My sound card is configured as to treat both outputs independently, and in the Windows mixer I can make them emit a test sound separately, so it's not a card issue.
I tried the approach on Change Mixer to output sound to in java using different outputs by getting two Clips with different mixers, with AudioSystem.getClip(AudioSystem.getMixerInfo()[i]);. However, this line of code works only with the Java Sound Audio Engine (AudioSystem.getMixerInfo()[0]), which outputs in Windows' default audio output. Anything else throws
java.lang.IllegalArgumentException: Line unsupported: interface Clip supporting format PCM_SIGNED unknown sample rate, 16 bit, stereo, 4 bytes/frame, big-endian
The following example code generates a 5-second long white noise and plays it for 1 second and then finishes. It prints Mixer information as seen on how do I get Mixer channels layout in java. It currently outputs to the "Java Sound Audio Engine" Mixer, and trying to change to any other Mixer throws the exception above.
import java.io.ByteArrayInputStream;
import java.security.SecureRandom;
import java.util.Random;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.Line;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.SourceDataLine;
public class Main {
static int SAMPLE_RATE = 44100;
static AudioFormat format = new AudioFormat(
AudioFormat.Encoding.PCM_SIGNED, // Encoding
SAMPLE_RATE, // sample rate
8, // sample size in bits
2, // channels
4, // frame size
SAMPLE_RATE, // frame rate
true); // is big endian
static int DURATION = 5;
Thread soundThread;
// Noise audio
static AudioInputStream inputStream = new AudioInputStream(new ByteArrayInputStream(generateNoise(DURATION*2*SAMPLE_RATE)), format, DURATION*SAMPLE_RATE);
public static void main(String[] args) {
try {
// https://stackoverflow.com/questions/12863081/how-do-i-get-mixer-channels-layout-in-java
Mixer.Info[] mi = AudioSystem.getMixerInfo();
for (Mixer.Info info : mi) {
System.out.println("info: " + info);
Mixer m = AudioSystem.getMixer(info);
System.out.println("mixer " + m);
Line.Info[] sl = m.getSourceLineInfo();
for (Line.Info info2 : sl) {
System.out.println(" info: " + info2);
Line line = AudioSystem.getLine(info2);
if (line instanceof SourceDataLine) {
SourceDataLine source = (SourceDataLine) line;
DataLine.Info i = (DataLine.Info) source.getLineInfo();
for (AudioFormat format : i.getFormats()) {
System.out.println(" format: " + format);
}
}
}
System.out.println("");
}
// Code only works for AudioSystem.getMixerInfo()[0]
final Clip clip = AudioSystem.getClip(AudioSystem.getMixerInfo()[0]);
clip.open(inputStream);
Thread soundThread = new Thread(new Runnable() {
#Override
public void run() {
try {
clip.loop(Clip.LOOP_CONTINUOUSLY);
Thread.sleep(1000);
clip.close();
System.exit(0);
} catch (Exception e) {
e.printStackTrace();
}
}
});
soundThread.start();
} catch (Exception e) {
e.printStackTrace();
}
}
private static byte[] generateNoise(int size) {
byte[] out = new byte[size];
Random r = new SecureRandom();
r.nextBytes(out);
return out;
}
}
Here is the Mixer information. This code ran with both output jacks connected and Windows recognizes as two different output devices (speakers and headphones). It looks like only Java's audio engine can play sounds.
info: Java Sound Audio Engine, version 1.0
mixer com.sun.media.sound.HeadspaceMixer#22c84d9
info: interface SourceDataLine supporting 8 audio formats
format: PCM_SIGNED unknown sample rate, 8 bit, mono, 1 bytes/frame,
format: PCM_UNSIGNED unknown sample rate, 8 bit, mono, 1 bytes/frame,
format: PCM_SIGNED unknown sample rate, 8 bit, stereo, 2 bytes/frame,
format: PCM_UNSIGNED unknown sample rate, 8 bit, stereo, 2 bytes/frame,
format: PCM_SIGNED unknown sample rate, 16 bit, mono, 2 bytes/frame, big-endian
format: PCM_SIGNED unknown sample rate, 16 bit, mono, 2 bytes/frame, little-endian
format: PCM_SIGNED unknown sample rate, 16 bit, stereo, 4 bytes/frame, big-endian
format: PCM_SIGNED unknown sample rate, 16 bit, stereo, 4 bytes/frame, little-endian
info: interface Clip supporting 8 audio formats, and buffers of 0 to 4194304 bytes
info: Microsoft ?T?E???h, version Unknown Version
mixer com.sun.media.sound.SimpleInputDevice#7e0df503
info: Stereo Mixer (Realtek High Defi, version Unknown Version
mixer com.sun.media.sound.SimpleInputDevice#4650d89c
info: Port Realtek HD Audio 2nd output (Re, version 6.1
mixer com.sun.media.sound.PortMixer#65bd0dd4
info: Port Stereo Mixer (Realtek High Defi, version 6.1
mixer com.sun.media.sound.PortMixer#78b5f53a
info: ?}?X? source port
info: Port Speakers (Realtek High Definiti, version 6.1
mixer com.sun.media.sound.PortMixer#b37c60d
I am using Java 6 because of other limitations. Also, some names are broken probably because I'm in a Japanese environment and Eclipse won't fetch the names in the correct encoding (I've tried changing everything to UTF-8 and Shift_JIS but nothing changed, but I guess it's not related to this problem).
In other words, It looks like can't output in Clips from different Mixers because Java can only output to "Java Sound Audio Engine" which goes to Windows' default audio device. Is there any way to get the other Mixers to work? Is there an alternative to use multiple audio outputs?
Update: It seems like this problem was already fixed but I still can't get it to work. I disabled the "Stereo Mix" recording device and ran the example code given in that link, and got this output:
MIXER 0: Java Sound Audio Engine, version 1.0
OUTPUT LINE (SourceDataLine) 0: interface SourceDataLine supporting 8 audio formats
OUTPUT LINE (SourceDataLine) 1: interface Clip supporting 8 audio formats, and buffers of 0 to 4194304 bytes
MIXER 1: Port Realtek HD Audio 2nd output (Re, version 6.1
INPUT LINE (TargetDataLine) 0: HEADPHONE target port
MIXER 2: Port Speakers (Realtek High Definiti, version 6.1
INPUT LINE (TargetDataLine) 0: SPEAKER target port
So it looks like only Java Sound Audio Engine can output sound as both the mixers for the front and back audio jacks are treated as input lines. Played audio through either Clip or SourceDataLine outputs in the Windows' default playback device.
Also, it looks like they solved the problem by using DirectAudio but I still did not figure out how to use them.
While testing in different computers, I solved this problem by upgrading to Java 1.6.0_17 (which was still okay with my environment limitations to call Java from Matlab) so the DirectAudio drivers would be listed (even though it looks like it should work from Java 1.5). Each DirectAudio sound device gives a SourceDataLine and a Clip for each device.