Java Media Framework: extract audio info from mp3 file - java

I'm analyzing music mp3 files. What I'm doing is extracting the audio data from the file and computing music similarity.
I've been using javazoom in order to handle mp3 files. By using audioFormat I'm extracting the raw data from the mp3 file:
byte[] audioBytes = new byte[numBytes];
in_format_init = AudioSystem.getAudioInputStream(musicFile);
AudioFormat formatInit = in_format_init.getFormat();
AudioFormat formatFinal = new AudioFormat(
AudioFormat.Encoding.PCM_SIGNED,
formatInit.getSampleRate(),
16,
formatInit.getChannels(),
formatInit.getChannels()*2,
formatInit.getSampleRate(),
false);
AudioInputStream streamIn = AudioSystem.getAudioInputStream(formatFinal, in_format_init);
while (((numBytesRead = streamIn.read(audioBytes)) != -1))
{...}
By doing this I store the audio data (without headers or tags) in audioBytes and then the info stored in the array is processed.
My question is: is it posible to extract the audio information from an mp3 audio file and store it as I do it in my example? I've been reading about JMF, but it's confusing for me.
Thanks.

I've just had a quick look at the JMF API so I'm not a 100% sure this will be correct or even work at all, but try something like this:
try {
File f = new File ("/path/to/my/audio.mp3");
DataSource ds = Manager.createDataSource(f.toURI().toURL());
ds.connect();
ds.start();
...
} catch (java.io.IOException e) {
...
} catch (NoDataSourceException e) {
...
}
After this try getting the controls from the DataSource: ds.getControls(), and see if any of the controls allows you to read the raw audio data.
You'll probably have to do all kinds of cleanup as well, e.g. ds.disconnect(), after you're done reading the audio.
Also, don't forget to install the JMF MP3 plugin
-- Lauri

Related

How to write Java AudioInputStream to MP3?

Now I have an AudioInputStream, using the following code I can write it to a WAVE file. While what I want is an MP3 file, what should I do?
AudioInputStream ais= new AudioInputStream(bais1, audioFormat, bufferSize);
try {
AudioSystem.write(ais, AudioFileFormat.Type.WAVE, new File("demoFile.wav")
);
}
catch(Exception e) {
e.printStackTrace();
}
In my project, the cache is not big enough to store big files, which means solution like using a tool to convert WAVE to MP3 is not allowed(WAVE file is too big).
Here is a github library of java audio utilities that include claims of being able to encode mp3.
pududits.soundlibs
I haven't used the mp3 libraries, only ogg/vorbis decoding. I'd be tempted to try the JOrbis encoder for ogg/vorbis before getting into mp3's.

Parsing Custom Created MIDI Files in Android

I have re-created a MIDI file without altering any of its Meta events. I have merely added SysEx (System Exclusive) messages under each note_on and note_off event. I use this library to parse MIDI files and extract tracks in order to get the MIDI messages.
Following is some sample code that I have tried (I have the MIDI file inside the raw folder).
try {
InputStream is = getResources().openRawResource(R.raw.mysamplemidifile);
File tempFile = File.createTempFile("temp", ".mid");
tempFile.deleteOnExit();
FileOutputStream out = new FileOutputStream(tempFile);
IOUtils.copy(is, out);
MidiFile midi = new MidiFile(tempFile);
ArrayList<MidiTrack> tracks = midi.getTracks();
MidiTrack sysExTrack = tracks.get(tracks.size() - 1);
} catch (Exception e) {
e.printStackTrace();
}
Originally the total number of MIDI messages is ~2500. But the library is able to fetch only about 2300 MIDI messages.
The sysExTrack variable contains the incompletely parsed SysEx data.
I am at a loss to understand what is going wrong here. Any help with the same is appreciated.
Edit:
The MIDI file gets parsed correctly in iOS.

How to read mp3 file to a byte array in Java?

I want to read the content of the .mp3 file into a byte array(Not including header and metadata). For this purpose I'm using following code.
File myFile = new File("C:\\Users\\Kaushal28\\Desktop\\a.mp3");
byte[] samples;
AudioInputStream is = AudioSystem.getAudioInputStream(myFile);
DataInputStream dis = new DataInputStream(is); //So we can use readFully()
try{
AudioFormat format = is.getFormat();
samples = new byte[(int)(is.getFrameLength() * format.getFrameSize())];
dis.readFully(samples);
}
finally{
dis.close();
}
Here is the link where it is posted: Here.
I executed this code with a mp3 file of a song. but got following exception:
javax.sound.sampled.UnsupportedAudioFileException: could not get audio input stream from input file
I've also tried this with .au file type, but got same exception.
For this I searched on Internet and found this: This SO link.
It says that all wav formats are not supported by java. Is it also true for .mp3 file formats? Or any other reasons due to which I'm getting this exception?

Playing a song in java [duplicate]

This question already has an answer here:
javax.sound.sampled.UnsupportedAudioFileException: could not get audio input stream from input file when loading wav file
(1 answer)
Closed 8 years ago.
I want to play a audio clip from my computer while a game is playing. But i can only use very very short sounds. Is there any similar way to playing songs like i play sound effects?
Im using swing graphics for the game if that matters.
The error i get when i try to use a song
"javax.sound.sampled.UnsupportedAudioFileException: could not get audio input stream from input file"
public static void main(String args[]) {
Sound s = new Sound();
s.playSound("C:/Users/isac/Desktop/banjos.wav");
}
}
public void playSound(String file) {
try {
AudioInputStream audio = AudioSystem.getAudioInputStream(new File(
file));
Clip clip = AudioSystem.getClip();
clip.open(audio);
clip.start();
}
catch (UnsupportedAudioFileException uae) {
System.out.println(uae);
} catch (IOException ioe) {
System.out.println(ioe);
} catch (LineUnavailableException lua) {
System.out.println(lua);
}
}
}
The error message you are getting indicates the problem is probably with the format of the file, not its length.
You can check the format of an audio file by looking at it's properties--usually requires a right click on Windows. The properties that matter may be on an "Advanced" tab. Java can read many formats, but where I've most often seen it hang up is with the following:
a person tries to load a .mp3 or .ogg or other form of compression but hasn't implemented any libraries that can decompress those files (not your situation, since your banjo.wav is a wav).
the .wav is not the standard "CD Quality" format (44100 fps, 16-bit encoding, stereo) but rather something like 24-bit or 32-bit encoding or 48000 or 96000 fps.
Current DAWs often make it easy to record in formats that are superior to "CD Quality" but Java doesn't support them yet.
For the most part, you can convert audio files that are not readable with Java to one that is with Audacity (free), if you aren't working from another home studio program. Be careful where you obtain Audacity as some sites that provide it (other than the official site) will include adware or malware or viruses.
As a side note, for a longer file, it would be better to load into a SourceDataLine for playback instead of a Clip. With a SourceDataLine, you don't have to wait for the entire file to load before it will start playing back, and it won't take up anywhere near as much RAM. The Java Tutorials has a section for Java Sound and a page there specifically on playback.

Write RTP video stream (H264 codec) to a mp4 file

i want to store a H264 video that is recorded from a rtp (live)stream to a file.
i've tried this with a simple java program, but vlc player cannot open the file.
here is my code:
try
{
socket = new DatagramSocket(port);
fos = new FileOutputStream(filePath + outputFileName);
do
{
DatagramPacket in = new DatagramPacket(inData, inData.length);
socket.receive(in);
byte[] bytes = in.getData();
if (curPos < buffer.length)
{
for (int i = 0; i < bytes.length; i++)
{
buffer[curPos] = bytes[i];
curPos++;
if (curPos >= buffer.length)
{
receivePackets = false;
break;
}
}
}
else
{
receivePackets = false;
}
Thread.sleep(SOCKET_TIMEOUT);
}
while (receivePackets);
fos.write(buffer, 0, buffer.length);
if (fos != null)
{
fos.close();
}
if (socket != null)
{
socket.close();
}
}
catch (IOException e)
{
e.printStackTrace();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
the file will be created, but it's not possible to open it.
are there any header informations i've to cut of or add to the byte array to get a correct video file?
UPDATE:
ok, the problem seems to be the nal header information of the h264 rtp packet, because i can open a recorded h263 video with a standard rtp header (but the quality of the video is really bad).
Rtp has headers in their packets that aren't part of the h264 stream, as well as has mechanics for splitting one nal unit (essentially a single h264 "packet") over multiple packets or merging multiple nal units into one packet, both of which add metadata that can't be a part of the final product.
Additionally, the RTP stream may not contain some of the metadata necessary to play the video, especially if its negotiated over rtsp. If that's the case you'll have to pull some NAL units out of the sprop-parameter-sets in the SDP.
You can find the documentation on how all of that works here: https://www.rfc-editor.org/rfc/rfc6184. It's really not as hard as it sounds.
When h264 is written to a file, each nal unit must be preceded by three 0 bytes and then a 1 byte. You can find more details on that here: https://www.itu.int/rec/T-REC-H.264-201906-I/en
VLC has to be talked into playing raw h264 files. You can google that and find easy steps to do so, its not related to the code so I won't copy them here.
If you want the file as a mp4, your best using a library to do this. If you want to do it all yourself, heaven help you, but you can find the spec here: https://web.archive.org/web/20180921052457/http://l.web.umkc.edu:80/lizhu/teaching/2016sp.video-communication/ref/mp4.pdf. The https://github.com/sannies/mp4parser library is java and may do that but, has some issues. Ffmpeg is a wonderful program to do this, and I've had luck running it as a subprocess to Java and feeding its standard in and reading from its standard out.
As a side note, ffprobe is a great program, running it on a broken video file can provide some insight on what's wrong with it.
You have to unpack the video data from RTP packets

Categories

Resources