5

I'm having issues with parsing the data from an mp3 file based on it's bytes.

The first part the output is correct, I have an mp3 file that is 254 seconds long and I obtain its information from the mp3 parsing library mp3agic from Github.

However, the second part of the information, regarding frame length and duration is incorrect.

Length of this mp3 is: 254 seconds
Bitrate: 320 kbps (CBR)
Sample rate: 44100 Hz
Has ID3v1 tag?: NO
Has ID3v2 tag?: YES
Has custom tag?: NO

framelength -1
framerate 38.28125
duration -271265.06

The code that I use to get framelength, framerate and duration is:

File file = musicFile.getFileValue();

    this.audioStream.startMusicStream(file);

    try {
        AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(file);
        AudioFormat format = audioInputStream.getFormat();
        long audioFileLength = file.length();
        int frameSize = format.getFrameSize();
        float frameRate = format.getFrameRate();
        float durationInSeconds = (audioFileLength / (frameSize * frameRate));

        System.out.println("framelength "+frameSize);
        System.out.println("framerate "+frameRate);
        System.out.println("duration "+durationInSeconds);

        this.setDurationLabel(durationInSeconds);
    } catch (Exception e) {
        e.printStackTrace();
    }

Fist of all, why is framelength and the other measurements even negative? What does that even mean? And how can I accurately calculate the duration of an mp3 file using the information from the audioinputstream and audioformat?

nitind
  • 19,089
  • 4
  • 34
  • 43
waylonion
  • 6,866
  • 8
  • 51
  • 92

2 Answers2

2

Working for me, thanks to JAAD library http://jaadec.sourceforge.net/:

import net.sourceforge.jaad.aac.Decoder;
import net.sourceforge.jaad.aac.SampleBuffer;
import net.sourceforge.jaad.adts.ADTSDemultiplexer;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import java.io.*;

public class AACHelper {

    public static AudioInputStream decodeAAC(File inputFile) throws IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        AudioFormat audioFormat;

        try {
            final FileInputStream audioInputStream = new FileInputStream(inputFile);
            final ADTSDemultiplexer adts = new ADTSDemultiplexer(audioInputStream);
            final Decoder dec = new Decoder(adts.getDecoderSpecificInfo());

            final SampleBuffer buf = new SampleBuffer();
            byte[] b;
            while (true) {
                try {
                    b = adts.readNextFrame();
                }
                catch (Exception e) {
                    break;
                }

                dec.decodeFrame(b, buf);
                outputStream.write(buf.getData());
            }

            audioFormat = new AudioFormat(buf.getSampleRate(), buf.getBitsPerSample(), buf.getChannels(), true, buf.isBigEndian());
            LogUtils.i("FrameRate:     " + audioFormat.getFrameRate());
            LogUtils.i("FrameSize:     " + audioFormat.getFrameSize());
            LogUtils.i("SampleRate:    " + buf.getSampleRate());
            LogUtils.i("BitsPerSample: " + buf.getBitsPerSample());
            LogUtils.i("Bitrate:       " + buf.getBitrate());
            LogUtils.i("Length:        " + buf.getLength());

        } finally {
            // nop
        }

        byte[] outputStreamByteArray = outputStream.toByteArray();
        ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStreamByteArray);
        AudioInputStream audioInputStream = new AudioInputStream(inputStream, audioFormat, outputStreamByteArray.length);

        long audioFileLength = audioInputStream.getFrameLength();
        int frameSize = audioFormat.getFrameSize();
        float frameRate = audioFormat.getFrameRate();
        double durationInSeconds = (audioFileLength / (frameSize * frameRate));
        LogUtils.i("Duration:      " + durationInSeconds);

        return audioInputStream;
    }

}

Christopher
  • 136
  • 9
0

For frame length and duration you can use:

long frameLen = audioInputStream.getFrameLength();
double durationInSeconds = (frameLen+0.0) / format.getFrameRate(); 

Function Description:

getFrameLength:Obtains the length of the stream, expressed in sample frames rather than bytes.Returns:the length in sample frames

getFrameRate:Obtains the frame rate in frames per second.Returns:the number of frames per second, or AudioSystem.NOT_SPECIFIED

References:

http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b27/javax/sound/sampled/AudioInputStream.java#AudioInputStream.getFrameLength%28%29

and

http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/javax/sound/sampled/AudioFormat.java#AudioFormat.getFrameRate%28%29

Aajan
  • 927
  • 1
  • 10
  • 23
  • 3
    I use AudioFormat format = audioInputStream.getFormat() to get the format object which seems to work properly. However, when I call audioInputStream.getFrameLength(), it still returns -1. This results in duration being a very small, negative number! Is the issue that I'm getting the audioInputStream from an mp3 file? AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(file); – waylonion Mar 06 '16 at 18:38
  • 1
    @WayWay: Did you ever solve this problem? I'm having the same one. – Grumblesaurus May 03 '17 at 18:08