Audio Input Stream To IVR supported WAV file [JAVA] - java

I want to convert audio InputStream to wav file format in java.
Require format is : mu-law 8000 Hz 64 kbps Mono
I am using the following method for the conversion but generated audio file is corrupted.
public static void getWavFile(String filePath, InputStream audioStream) throws IOException, UnsupportedAudioFileException {
try {
byte[] decodedData = IOUtils.toByteArray(audioStream);
File outFile = new File(filePath);
AudioFormat format = new AudioFormat(AudioFormat.Encoding.ALAW, 8000, 16, 2, 4, 8000, false);
AudioSystem.write(new AudioInputStream(new ByteArrayInputStream(decodedData), format, decodedData.length),
AudioFileFormat.Type.WAVE, outFile);
} catch (IOException ex) {
ex.printStackTrace();
}
}
I am using this audio file to play in my IVR flow and it strictly allow only the given format.

Related

Playing custom audio formats with audio stream

So I started working on a video game and I want to create a custom sound format.
Path file = Paths.get("C:", "Users", "Mariobro85", "Desktop", "test.wav");
public void playFile() throws InterruptedException{
try{
File f = new File(file.toString());
URL url = f.toURI().toURL();
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(url);
Clip clip = AudioSystem.getClip();
clip.open(audioInputStream);
clip.start();
Thread.sleep(15000);
}
catch(UnsupportedAudioFileException uafE){
System.out.println("ERROR: Audio data of the file " + file + " is not in wave format.");
}
catch(IOException ioE){
System.out.println("ERROR: Audio data of the file " + file + " is corrupted.");
}
catch(LineUnavailableException luE){
System.out.println(luE);
}
}
But this only plays standard .wav files.
I use wav in the custom format too, but the problem is that the audio data in my file starts at 0x60 instead of 0x0 and also there is information stored for loops, volume etc. Because of that it always throws an UnsupportedAudioFileException.
Is there any way to tell the AudioStream to jump to a specific address or is that not possible with standard java libraries?
If you want to edit the audio data before it is parsed by the default audio parser, you can edit it as follows
File file=new File("path/to/file");
byte[] bytes= Files.readAllBytes(file.toPath());
//edit or trim bytes as you wish.
ByteArrayInputStream inputStream=new ByteArrayInputStream(bytes);//you can even give an offset in this constructor
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(inputStream);
Clip clip = AudioSystem.getClip();
clip.open(audioInputStream);
clip.start();
Thread.sleep(xAmount);
If your format is truly custom, I recommend just following one of these standardised approaches and simply adding a header or footer to your byte array. No need to remake what has been done. Or, to make things simpler, you can just add a separate file you also load which has different data you wish to load with the audio.

Playing .wav continuously in java: Invalid Format Exception

I want to play a .wav file continuously in Java. I found some code, but I can't make it work.
String fileName = "res/sound/buz.wav";
File file = new File(fileName);
AudioInputStream ais;
try {
Clip clip = AudioSystem.getClip();
ais = AudioSystem.getAudioInputStream(file);
clip.open(ais);
clip.loop(Clip.LOOP_CONTINUOUSLY);
} catch (UnsupportedAudioFileException | IOException
| LineUnavailableException e) {
e.printStackTrace();
}
I get an Invalid Format Exception on clip.open(ais):
Exception in thread "main" java.lang.IllegalArgumentException: Invalid format
at org.classpath.icedtea.pulseaudio.PulseAudioDataLine.createStream(PulseAudioDataLine.java:142)
at org.classpath.icedtea.pulseaudio.PulseAudioDataLine.open(PulseAudioDataLine.java:99)
at org.classpath.icedtea.pulseaudio.PulseAudioDataLine.open(PulseAudioDataLine.java:283)
at org.classpath.icedtea.pulseaudio.PulseAudioClip.open(PulseAudioClip.java:402)
at org.classpath.icedtea.pulseaudio.PulseAudioClip.open(PulseAudioClip.java:453)
at launcher.Launcher.main(Launcher.java:59)
I checked and file is created correctly and exists. So, what is the problem with my code?
If it matters, I'm working on Linux, but this should work on both Linux and Windows...
So I found a solution
try{
File file = new File (fileName);
AudioClip clip = Applet.newAudioClip(file.toURL());
clip.loop();
clip.stop();
}
catch(Exception e){
e.printStackTrace();
}
I can play a .wav file in a loop and stop it. That's what I wanted. And the code is very short.

Java LWJGL OGG Background Music

In my game I've have got a very long ogg files(about 8 to 20 mb) and some other machines aren't able to read it direct into memory. So I read that some games uses stream and play method. Is there any lib/code example to load and play ogg files(with LWJGL) in real time?
Thanks for help :)
Do you specifically need to play OGG files? If not, there are plenty of online converters than can convert it to MP3, WAV, etc.
Also, do you specifically need to play it with LWJGL? This is very possible with default java, like so:
static String randomName = "TreasureQuest";
public static Clip clip = null;
public static void playSound(String name) throws Exception{
if (clip != null && clip.isOpen()) clip.close();
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new File("music/" + name + ".wav").getAbsoluteFile());
clip = AudioSystem.getClip();
clip.open(audioInputStream);
FloatControl gainControl =
(FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
gainControl.setValue(0f);
System.out.println(clip.getFrameLength() + " | " + clip.getFramePosition());
clip.start();
}
Personally, I use this for my LWJGL game, and it works perfectly fine.
If you must play an OGG file, and you specifically must play it with LWJGL, I suggest you use OpenAL. You can find the documentation for playing OGG files here.
#Joehot200
So I have two music engines - java clip and lwjgl, so it doesn't metter which one i will be using :)
I have a very similar code to yours(but it includes ogg decompression) and it time loading is still very long - I want to read my sound file and play what I read at the same time(like YOUTUBE). Here is my piece of code:
public static Clip DecodeOgg(String filename)
{
try
{
File file = new File(filename);
// Get AudioInputStream from given file.
AudioInputStream in= AudioSystem.getAudioInputStream(file);
AudioInputStream din = null;
if (in != null)
{
AudioFormat baseFormat = in.getFormat();
AudioFormat decodedFormat = new AudioFormat(
AudioFormat.Encoding.PCM_SIGNED,
baseFormat.getSampleRate(),
16,
baseFormat.getChannels(),
baseFormat.getChannels() * 2,
baseFormat.getSampleRate(),
false);
// Get AudioInputStream that will be decoded by underlying VorbisSPI
din = AudioSystem.getAudioInputStream(decodedFormat, in);
Clip clip = AudioSystem.getClip();
clip.open(din);
return clip;
}
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}

When writing .wav file from AudioInputStream, Windows Media Player can't play it

I'm trying to write a file from an AudioInputStream. The stream can read the original file just fine (as far as I can tell). But when it tries to write, it writes what should be a 15 KB file in 44 bytes. Windows Media Player gives the error "either the file type is unsupported, or WMP doesn't recognize the codec used to convert the file."
I got most of this code from http://docs.oracle.com/javase/tutorial/sound/converters.html. I've looked all over StackOverflow but nothing seemed to pertain to this problem.
I've tried getting the format of the AudioInputStream and it's definitely a .wav. As far as I can tell, a codec is software that converts analog to digital data, and both the wav file and the AudioInputStream are digital already.
EDIT: It looks like the stream is writing the WAVE file header to my new file, but nothing else. That's where my 44 byte file is coming from.
Here's the code. I think the problem is in writeFile() but I included the rest just in case:
public static void getFile()
{
try
{
File test = new File("C:\\Users\\Audrey\\Steganography\\correctamundo.wav"); //file to be written from
AudioInputStream stream = AudioSystem.getAudioInputStream(test);
AudioFileFormat format = AudioSystem.getAudioFileFormat(test);
int bytesPerFrame = stream.getFormat().getFrameSize();
byte[] b = new byte[30000]; //array of arbitrary size to hold the bytes in stream
if (bytesPerFrame == AudioSystem.NOT_SPECIFIED) //not sure why this is necessary
{
bytesPerFrame = 1;
}
int i = 0;
while(stream.available() > 0)
{
byte currentByte = (byte)stream.read();
b[i] = currentByte; //read bytes to array
System.out.println(b[i] + " " +(i+1)); //test statement
i++;
}
writeFile(format, stream);
} catch (IOException | UnsupportedAudioFileException e)
{
e.printStackTrace();
}
}
public static void writeFile (AudioFileFormat format, AudioInputStream stream) //format and stream created in getFile() under the same names
{
try
{
File fileOut = new File("C:\\Users\\Audrey\\Steganography\\testFile2.wav");
AudioFileFormat.Type fileType = format.getType(); //type of file the AudioInputStream can write to, since format refers to stream
if (AudioSystem.isFileTypeSupported(fileType, stream))
{
AudioSystem.write(stream, fileType, fileOut);
System.out.println(stream.getFrameLength()); //test statement
}
System.out.println(fileType); //test statement
}
catch (IOException e)
{
e.printStackTrace();
}
}

Convert audio stream to WAV byte array in Java without temp file

Given an InputStream called in which contains audio data in a compressed format (such as MP3 or OGG), I wish to create a byte array containing a WAV conversion of the input data. Unfortunately, if you try to do this, JavaSound hands you the following error:
java.io.IOException: stream length not specified
I managed to get it to work by writing the wav to a temporary file, then reading it back in, as shown below:
AudioInputStream source = AudioSystem.getAudioInputStream(new BufferedInputStream(in, 1024));
AudioInputStream pcm = AudioSystem.getAudioInputStream(AudioFormat.Encoding.PCM_SIGNED, source);
AudioInputStream ulaw = AudioSystem.getAudioInputStream(AudioFormat.Encoding.ULAW, pcm);
File tempFile = File.createTempFile("wav", "tmp");
AudioSystem.write(ulaw, AudioFileFormat.Type.WAVE, tempFile);
// The fileToByteArray() method reads the file
// into a byte array; omitted for brevity
byte[] bytes = fileToByteArray(tempFile);
tempFile.delete();
return bytes;
This is obviously less desirable. Is there a better way?
The problem is that the most AudioFileWriters need to know the file size in advance if writing to an OutputStream. Because you can't provide this, it always fails. Unfortunatly, the default Java sound API implementation doesn't have any alternatives.
But you can try using the AudioOutputStream architecture from the Tritonus plugins (Tritonus is an open source implementation of the Java sound API): http://tritonus.org/plugins.html
I notice this one was asked very long time ago. In case any new person (using Java 7 and above) found this thread, note there is a better new way doing it via Files.readAllBytes API. See:
How to convert .wav file into byte array?
Too late, I know, but I was needed this, so this is my two cents on the topic.
public void UploadFiles(String fileName, byte[] bFile)
{
String uploadedFileLocation = "c:\\";
AudioInputStream source;
AudioInputStream pcm;
InputStream b_in = new ByteArrayInputStream(bFile);
source = AudioSystem.getAudioInputStream(new BufferedInputStream(b_in));
pcm = AudioSystem.getAudioInputStream(AudioFormat.Encoding.PCM_SIGNED, source);
File newFile = new File(uploadedFileLocation + fileName);
AudioSystem.write(pcm, Type.WAVE, newFile);
source.close();
pcm.close();
}
The issue is easy to solve if you prepare class which will create correct header for you. In my example Example how to read audio input in wav buffer data goes in some buffer, after that I create header and have wav file in the buffer. No need in additional libraries. Just copy the code from my example.
Example how to use class which creates correct header in the buffer array:
public void run() {
try {
writer = new NewWaveWriter(44100);
byte[]buffer = new byte[256];
int res = 0;
while((res = m_audioInputStream.read(buffer)) > 0) {
writer.write(buffer, 0, res);
}
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
}
}
public byte[]getResult() throws IOException {
return writer.getByteBuffer();
}
And class NewWaveWriter you can find under my link.
This is very simple...
File f = new File(exportFileName+".tmp");
File f2 = new File(exportFileName);
long l = f.length();
FileInputStream fi = new FileInputStream(f);
AudioInputStream ai = new AudioInputStream(fi,mainFormat,l/4);
AudioSystem.write(ai, Type.WAVE, f2);
fi.close();
f.delete();
The .tmp file is a RAW audio file, the result is a WAV file with header.

Categories