Read mp3 binary data for visualization - java

In my previous post, I had a little trouble trying to read a mp3 file. Now I am able to do that and I want to be able to render the data from the mp3 with java swing. And it would be nice to play the mp3 and visualize at the same time.
I have the binary data (which I piped to the outputstream) but I don't know how to interpret the data.
Essentially, at around LINE57, what do I need to do with the byte array so I can interpret the data as db values?
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
public class MainSound {
public static void main(final String [] args) throws Exception {
System.out.println("Running");
System.out.println(System.getProperty("java.version"));
final AudioFileFormat.Type [] types = AudioSystem.getAudioFileTypes();
for (final AudioFileFormat.Type t : types) {
System.out.println("Returning Type : " + t);
} // End of the for //
final String PATH = "C:\\Users\\bbrown\\Downloads\\swing-hacks-examples-20060109\\Ch10-Audio\\75\\soundcloud2.mp3";
final File file = new File(PATH);
final AudioInputStream in = AudioSystem.getAudioInputStream(new BufferedInputStream(new FileInputStream(file)));
AudioInputStream din = null;
final AudioFormat baseFormat = in.getFormat();
final AudioFormat decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
baseFormat.getSampleRate(),
16,
baseFormat.getChannels(),
baseFormat.getChannels() * 2,
baseFormat.getSampleRate(),
false);
System.out.println("Channels : " + baseFormat.getChannels());
din = AudioSystem.getAudioInputStream(decodedFormat, in);
rawplay(decodedFormat, din);
in.close();
System.out.println("Done");
}
private static synchronized void rawplay(final AudioFormat targetFormat, final AudioInputStream din) throws IOException, LineUnavailableException {
final byte[] data = new byte[4096];
final SourceDataLine line = getLine(targetFormat);
if (line != null) {
System.out.println("Entering ...");
// Start
line.start();
int nBytesRead = 0, nBytesWritten = 0;
while (nBytesRead != -1) {
nBytesRead = din.read(data, 0, data.length);
if (nBytesRead != -1) {
// LINE57, HOW CAN INTERPRET this data for VISUALIZATION.
nBytesWritten = line.write(data, 0, nBytesRead);
System.out.println("... -->" + data[0] + " bytesWritten:" + nBytesWritten);
}
} // End of while //
System.out.println("Done ...");
// Stop
line.drain();
line.stop();
line.close();
din.close();
} // End of the if //
}
private static synchronized SourceDataLine getLine(AudioFormat audioFormat) throws LineUnavailableException {
SourceDataLine res = null;
final DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
res = (SourceDataLine) AudioSystem.getLine(info);
res.open(audioFormat);
return res;
}
} // End of the class //

Have a look at Extreme Media Player source code which is a cross Platform Media Player that supports visualizations, and of course written in Java.
A study of the code should help you understand how to read the decibels of the byte data being played. (I loved the question as I haven't seen this asked before).
As seen here:
UPDATE:
Its a pity Java does not natively support MP3 format, but have a look at this link showing us JMF (Java Media Framework) which is a plugin for j2SE which enables MP3 support, with help of extra MP3 Plugin for JMF.

Related

HTTP 500 error when I try to retrieve the audio file

I'm trying to get this Java program to receive audio files using a URL. When I do this, it just gives an error:
javax.sound.sampled.UnsupportedAudioFileException: could not get audio input stream from input stream
at javax.sound.sampled.AudioSystem.getAudioInputStream(Unknown Source)
at Starter.main(Starter.java:21)
When you go to the URL in your browser, it downloads a file without a .mp3 extension with the hash that was used to store it in the database.
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.SourceDataLine;
public class Starter {
public static void main(String[] args) {
AudioInputStream din = null;
try {
URL url = new URL("http://www.roblox.com/asset/?id=138738005");
HttpURLConnection httpcon = (HttpURLConnection) url.openConnection();
InputStream bufferedIn = new BufferedInputStream(httpcon.getInputStream());
//AudioInputStream in = AudioSystem.getAudioInputStream(Starter.class.getResourceAsStream("338876528.mp3"));
AudioInputStream in = AudioSystem.getAudioInputStream(bufferedIn);
AudioFormat baseFormat = in.getFormat();
AudioFormat decodedFormat = new AudioFormat(
AudioFormat.Encoding.PCM_SIGNED,
baseFormat.getSampleRate(), 16, baseFormat.getChannels(),
baseFormat.getChannels() * 2, baseFormat.getSampleRate(),
false);
din = AudioSystem.getAudioInputStream(decodedFormat, in);
DataLine.Info info = new DataLine.Info(SourceDataLine.class, decodedFormat);
SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info);
if(line != null) {
line.open(decodedFormat);
byte[] data = new byte[4096];
// Start
line.start();
int nBytesRead;
while ((nBytesRead = din.read(data, 0, data.length)) != -1) {
line.write(data, 0, nBytesRead);
}
// Stop
line.drain();
line.stop();
line.close();
din.close();
}
}
catch(Exception e) {
e.printStackTrace();
}
finally {
if(din != null) {
try { din.close(); } catch(IOException e) { }
}
}
}
}
The content of http://www.roblox.com/asset/?id=138738005 is
<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.roblox.com/roblox.xsd" version="4">
<External>null</External>
<External>nil</External>
<Item class="ShirtGraphic" referent="RBX0">
<Properties>
<Content name="Graphic">
<url>http://www.roblox.com/asset/?id=138738004</url>
</Content>
<string name="Name">Shirt Graphic</string>
<bool name="archivable">true</bool>
</Properties>
</Item>
</roblox>
so I would expect an exception when trying to treat it as an audio file.
The file referenced in the url tag http://www.roblox.com/asset/?id=138738004 is a PNG:
So, even extracting that would not help here.

Streaming audio from microphone with Java

I'm developing a project which requires me to stream audio from microphone from a client to a server. The code shown below is what I have written. When I run both the client and server code the audio is not streamed live. In fact the audio from the client is stored in the buffer and when I terminate the execution of the client side code the audio from the buffer on the server gets output to the speaker. What am I doing wrong? (I'm developing on eclipse)
server:
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.TargetDataLine;
//import org.apache.commons.io.output.ByteArrayOutputStream;
public class ServerStream {
private OutgoingSoudnListener osl = new OutgoingSoudnListener();
boolean outVoice = true;
AudioFormat format = getAudioFormat();
private ServerSocket serverSocket;
Socket server;
private AudioFormat getAudioFormat() {
float sampleRate = 16000.0F;
int sampleSizeBits = 16;
int channels = 1;
boolean signed = true;
boolean bigEndian = false;
return new AudioFormat(sampleRate, sampleSizeBits, channels, signed, bigEndian);
}
public ServerStream() throws IOException{
try{
System.out.println("Creating Socket...");
serverSocket = new ServerSocket(3000);
osl.runSender();
}catch(Exception e){
e.printStackTrace();
}
}
class OutgoingSoudnListener{
public void runSender(){
try{
server = serverSocket.accept();
System.out.println("Listening from mic.");
DataOutputStream out = new DataOutputStream(server.getOutputStream());
DataLine.Info micInfo = new DataLine.Info(TargetDataLine.class,format);
TargetDataLine mic = (TargetDataLine) AudioSystem.getLine(micInfo);
mic.open(format);
System.out.println("Mic open.");
byte tmpBuff[] = new byte[mic.getBufferSize()/5];
mic.start();
while(outVoice) {
System.out.println("Reading from mic.");
int count = mic.read(tmpBuff,0,tmpBuff.length);
if (count > 0){
System.out.println("Writing buffer to server.");
out.write(tmpBuff, 0, count);
}
}
mic.drain();
mic.close();
System.out.println("Stopped listening from mic.");
}catch(Exception e){
e.printStackTrace();
}
}
}
public static void main (String args[]) throws IOException{
new ServerStream();
}
}
client:
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.SourceDataLine;
import org.apache.commons.io.IOUtils;
public class ClientStream{
public ClientStream() throws IOException{
isl.runListener();
}
private IncomingSoundListener isl = new IncomingSoundListener();
AudioFormat format = getAudioFormat();
InputStream is;
Socket client;
String serverName = "192.168.2.8";
int port=3000;
boolean inVoice = true;
private AudioFormat getAudioFormat(){
float sampleRate = 16000.0F;
int sampleSizeBits = 16;
int channels = 1;
boolean signed = true;
boolean bigEndian = false;
return new AudioFormat(sampleRate, sampleSizeBits, channels, signed, bigEndian);
}
class IncomingSoundListener {
public void runListener(){
try{
System.out.println("Connecting to server:"+serverName+" Port:"+port);
client = new Socket(serverName,port);
System.out.println("Connected to: "+client.getRemoteSocketAddress());
System.out.println("Listening for incoming audio.");
DataLine.Info speakerInfo = new DataLine.Info(SourceDataLine.class,format);
SourceDataLine speaker = (SourceDataLine) AudioSystem.getLine(speakerInfo);
speaker.open(format);
speaker.start();
while(inVoice){
is = client.getInputStream();
byte[] data = IOUtils.toByteArray(is);
ByteArrayInputStream bais = new ByteArrayInputStream(data);
AudioInputStream ais = new AudioInputStream(bais,format,data.length);
int bytesRead = 0;
if((bytesRead = ais.read(data)) != -1){
System.out.println("Writing to audio output.");
speaker.write(data,0,bytesRead);
// bais.reset();
}
ais.close();
bais.close();
}
speaker.drain();
speaker.close();
System.out.println("Stopped listening to incoming audio.");
}catch(Exception e){
e.printStackTrace();
}
}
}
public static void main(String [] args) throws IOException{
new ClientStream();
}
}
The problem is in client side,
in the line
byte[] data = IOUtils.toByteArray(is);
It deals with the object itself, not with the content.
So, you must change it to this:
byte[] data = new byte[1024];
I am not familiar with this, so don't get mad if I am way off here, but reading the api for DataLine it seems to function like a buffer, that you have to flush or drain in this case to get the output. Have you attempted to put the mic.drain()/speaker.drain() command in the while loop?

Playback the output of recorded Audio using javax.sound.sampled

i have a problem verifying the output I´ve captured. My program should capture Audio from a mic and then save it as a WAVE file. It does that, but listening to the file only results in crumbling noises, no actual voice recorded.
My code is this
import java.io.IOException;
import javax.sound.sampled.*;
import java.io.File;
public class Main
{
public static void main(String[] args) throws IOException, InterruptedException, LineUnavailableException {
TargetDataLine line = null;
DataLine.Info info = new DataLine.Info(TargetDataLine.class, getAudioFormat());
try
{
line = (TargetDataLine) AudioSystem.getLine(info);
line.open(getAudioFormat());
}
catch (LineUnavailableException e)
{
e.printStackTrace();
}
line.start();
AudioInputStream stream = new AudioInputStream(line);
Stopper stopper = new Stopper(line, stream);
stopper.start();
File file = new File("C:/Users/Martin/Documents/soundfile.wav");
AudioSystem.write(stream, AudioFileFormat.Type.WAVE, file);
System.out.println("Stopped...");
System.in.read();
}
public static AudioFormat getAudioFormat()
{
AudioFormat.Encoding encoding = AudioFormat.Encoding.PCM_SIGNED;
float sampleRate = 8000.0f;
int sampleSizeInBits = 16;
int channels = 2;
int frameSize = 4;
int frameRate = 8000;
boolean bigEndian = true;
return new AudioFormat(encoding,
sampleRate,
sampleSizeInBits,
channels,
frameSize,
frameRate,
bigEndian);
}
}
The stopper thread is just this:
import java.io.IOException;
import javax.sound.sampled.*;
public class Stopper extends Thread
{
TargetDataLine line = null;
AudioInputStream stream = null;
public Stopper(TargetDataLine line, AudioInputStream stream)
{
this.line = line;
this.stream = stream;
}
public void run()
{
System.out.println("Press [RETURN] to stop capturing...");
try
{
System.in.read();
}
catch (IOException e)
{}
line.stop();
try
{
stream.close();
}
catch (IOException e)
{}
}
}
The Audioformat I´m using is accepted by my mic:
Supported SourceDataLines of default mixer (Mikrofon (Creative SB X-Fi)):
interface TargetDataLine supporting 8 audio formats, and buffers of at least 32 bytes
max buffer size: -1
min buffer size: 32
Supported Audio formats:
PCM_SIGNED unknown sample rate, 16 bit, stereo, 4 bytes/frame, big-endian

audio to real numbers

I am able to convert my audio into byte values.
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;
public class Audio_to_bytes {
public static void main(String args[]) throws IOException {
File WAV_FILE = new File("/home/cybersecurity/Desktop/scream2.wav");
ByteArrayOutputStream out = new ByteArrayOutputStream();
AudioInputStream in = null;
try {
in = AudioSystem.getAudioInputStream(WAV_FILE);
} catch (UnsupportedAudioFileException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
int read, i;
byte[] buff = new byte[1024];
while ((read = in.read(buff)) > 0) {
out.write(buff, 0, read);
}
out.flush();
byte[] audioBytes = out.toByteArray();
}
}
I want to identify audios which contains scream in them.For that i need to convert my audio into real numbers so that i can apply fft on it.Can anyone help me how this can be done
I came up with this code snippet and tested it. I hope it helps. I am allocating 4 floats (as bytes) I previously created and converted to bytes. Then I use the NIO FloatBuffer View of a ByteBuffer so NIO automatically returns 4 bytes as a float number without further treatment.
ByteBuffer bb = ByteBuffer.allocate(4*4);
bb.put(new byte[]{64,-112,0,0,66,-10, 22,-68, 66,9, 73, -43, 63,-114, 56, -38});
bb.rewind();
FloatBuffer floatBuffer = bb.asFloatBuffer();
for(int i = 0; i < 4;i++){
System.out.println(floatBuffer.get());
}

Play/load mp3 using Java APIs and JMF, error unsupported format

I am trying to load a MP3 file. I have jmf.jar (windows version) in my classpath and am trying to run my class through Eclipse. But I get this error when trying to run.
I downloaded and set this version of JMF from the oracle site:
JMF2.1.1e\lib
I am running with Java 7 from Oracle (through Eclipse)
Error:
javax.sound.sampled.UnsupportedAudioFileException:
could not get audio input stream from input stream
at
javax.sound.sampled.AudioSystem.getAudioInputStream
(Unknown Source)
at
org.berlin.sound.WaveformDisplaySimulator.main
(WaveformDisplaySimulator.java:47)
Here is the code:
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import javax.media.Codec;
import javax.media.Format;
import javax.media.PlugInManager;
import javax.media.format.AudioFormat;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
public static void main(final String[] args) {
try {
System.out.println(System.getProperty("java.version"));
final String MP3 = "com.sun.media.codec.audio.mpa.JavaDecoder";
Codec mp3 = (Codec) Class.forName(MP3).newInstance();
final Format input1 = new AudioFormat(AudioFormat.MPEGLAYER3);
final Format input2 = new AudioFormat(AudioFormat.MPEG);
final Format output = new AudioFormat(AudioFormat.LINEAR);
PlugInManager.addPlugIn(
"com.sun.media.codec.audio.mpa.JavaDecoder",
new Format[]{ input1, input2 },
new Format[]{ output },
PlugInManager.CODEC
);
final AudioFileFormat.Type [] types = AudioSystem.getAudioFileTypes();
for (final AudioFileFormat.Type t : types) {
System.out.println("Returning Type : " + t);
} // End of the for //
final String PATH = "C:\\Users\\Downloads\\soundcloud2.mp3";
final File file = new File(PATH);
final AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new BufferedInputStream(new FileInputStream(file)));
} catch (final Exception e) {
e.printStackTrace();
}
} // End of the method //
I never could get the oracle download to work. I ended up downloading a MP3 plugin from this site and then adding the plugin in my classpath. This worked with Eclipse and without.
http://www.tritonus.org/plugins.html
Also, I didn't have to modify my code. I was able to read the mp3 binary data and also stream to output.
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
http://www.tritonus.org/plugins.html
public static void main(final String [] args) throws Exception {
System.out.println("Running");
System.out.println(System.getProperty("java.version"));
final AudioFileFormat.Type [] types = AudioSystem.getAudioFileTypes();
for (final AudioFileFormat.Type t : types) {
System.out.println("Returning Type : " + t);
} // End of the for //
final String PATH = "C:\\Users\\bbrown\\Downloads\\swing-hacks-examples-20060109\\Ch10-Audio\\75\\soundcloud2.mp3";
final File file = new File(PATH);
final AudioInputStream in = AudioSystem.getAudioInputStream(new BufferedInputStream(new FileInputStream(file)));
AudioInputStream din = null;
final AudioFormat baseFormat = in.getFormat();
final AudioFormat decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
baseFormat.getSampleRate(),
16,
baseFormat.getChannels(),
baseFormat.getChannels() * 2,
baseFormat.getSampleRate(),
false);
System.out.println("Channels : " + baseFormat.getChannels());
din = AudioSystem.getAudioInputStream(decodedFormat, in);
rawplay(decodedFormat, din);
in.close();
System.out.println("Done");
}
private static synchronized void rawplay(final AudioFormat targetFormat, final AudioInputStream din) throws IOException, LineUnavailableException {
final byte[] data = new byte[4096];
final SourceDataLine line = getLine(targetFormat);
if (line != null) {
System.out.println("Entering ...");
// Start
line.start();
int nBytesRead = 0, nBytesWritten = 0;
while (nBytesRead != -1) {
nBytesRead = din.read(data, 0, data.length);
if (nBytesRead != -1) {
nBytesWritten = line.write(data, 0, nBytesRead);
System.out.println("... -->" + data[0] + " bytesWritten:" + nBytesWritten);
}
} // End of while //
System.out.println("Done ...");
// Stop
line.drain();
line.stop();
line.close();
din.close();
} // End of the if //
}
AudioInputStream can't open mp3 format sounds cause they are compressed , even if you format them as PCM_SIGNED like wav files they can't be played always . You may like jLayer , I have never seen it to crash
import javazoom.jl.player.advanced.AdvancedPlayer;
`
try{
File file = new File("C:/DMK.mp3");
FileInputStream in = new FileInputStream(file);
AdvancedPlayer player = new AdvancedPlayer(in);
player.play();
}
catch (Exception ex) {
ex.printStackTrace();
}
`
It's 2017, and I added support for mp3 encoding/decoding by using the mp3spi package (http://www.javazoom.net/mp3spi/mp3spi.html)
Somebody was kind enough to set it up as a dependency on Google Code. Here's the gradle entry:
compile group: 'com.googlecode.soundlibs', name: 'mp3spi', version: '1.9.5-1'
So this or the maven equivalent should give you mp3 support in your project.

Categories

Resources