3

I have struggled with playing aac encoded audio files with Java a while now.

We had a group project at the end of our first semester and wanted to have a background music and few soundeffects in there. At the end we used WAV files, as we couldn't get the AAC's to play.

9Lukas5
  • 81
  • 9

1 Answers1

4

This weekend I gave it another try and searched along again, and have got a working code searched together from different sites, but nowhere was a complete working solution.

For a more comfortable usage in future projects I made me a small library for aac playback.

As it was hard to find the working solution, I wanted to share it with you, in the hope some one having the same problem in the future will have it a bit easier.
The following code is a snippet from the lib I wrote. You can have a look onto the whole lib on GitLab at Java AAC-Player.
This lib/solution uses the aac decoder JAAD.
The player I wrote around the JAAD library is available as Maven artifact:

<dependency>
    <groupId>com.gitlab.9lukas5</groupId>
    <artifactId>jaad</artifactId>
    <!--
        check latest version on https://search.maven.org
        or try the latest tag you find in git
    -->
</dependency>

public static void play(File[] files)
{
                // local vars
                byte[]          b;              // array for the actual audio Data during the playback
                AudioTrack      track;          // track we are playing atm
                AudioFormat     af;             // the track's format
                SourceDataLine  line;           // the line we'll use the get our audio to the speaker's
                Decoder         dec;            // decoder to get the audio bytes
                Frame           frame;          //
                SampleBuffer    buf;            //
                int             currentTrack;   // index of current track from playlist
                MP4Container    cont;           // container to open the current track with
                Movie           movie;          // and get the content from the container

                try
                {
                    // for-next loop to play each titel from the playlist once
                    for (currentTrack = 0; currentTrack < files.length; currentTrack++)
                    {
                        cont    = new MP4Container(new RandomAccessFile(files[currentTrack], "r")); // open titel with random access
                        movie   = cont.getMovie();                          // get content from container,
                        List<Track> content = movie.getTracks();
                        if (content.isEmpty())                              // check if container HAS content
                            throw new Exception ("insert error message here");  // if so,
                        track   = (AudioTrack) movie.getTracks().get(0);    // grab first track and set the audioformat
                        af      = new AudioFormat(track.getSampleRate(), track.getSampleSize(), track.getChannelCount(), true, true);
                        line    = AudioSystem.getSourceDataLine(af);        // get a DataLine from the AudioSystem
                        line.open();                                        // open and
                        line.start();                                       // start it

                        dec     = new Decoder(track.getDecoderSpecificInfo());

                        buf = new SampleBuffer();
                        while(track.hasMoreFrames())                // while we have frames left
                        {
                            frame = track.readNextFrame();          // read next frame,
                            dec.decodeFrame(frame.getData(), buf);  // decode it and put into the buffer
                            b = buf.getData();                      // write the frame data from the buffer to our byte-array
                            line.write(b, 0, b.length);             // and from there write the byte array into our open AudioSystem DataLine

                            while (paused)                  // check if we should pause
                            {
                                Thread.sleep(500);          // if yes, stay half a second

                                if (Thread.interrupted())   // check if we should stop possibly
                                {
                                    line.close();           // if yes, close line and
                                    return;                 // exit thread
                                }
                            }

                            if (Thread.interrupted())       // if not in pause, still check on each frame if we should
                            {                               // stop. If so
                                line.close();               // close line and
                                return;                     // exit thread
                            }
                        }

                        line.close();           // after titel is over, close line

                        if (loop)               // if we should loop current titel, set currentTrack -1,
                            currentTrack--;     // as on bottom of for-next it get's +1 and so the same titel get's played again
                        else if (repeat && (currentTrack == files.length -1)) // else check if we are at the end of the playlist
                            currentTrack = -1;  // and should repeat the whole list. If so, set currentTrack -1, so it get's 0 on for-next bottom
                    }
                }
                catch (LineUnavailableException | IOException | InterruptedException e)
                {
                    e.printStackTrace();
                }
}
9Lukas5
  • 81
  • 9
  • nice, for me JAAD does not work, output not acceptable. – Sam Ginrich Aug 14 '23 at 19:16
  • Long of forgotten project of mine :D Just out of curiosity: what's the problem for you with the output? – 9Lukas5 Aug 24 '23 at 16:11
  • :) There is no problem if you have no requirement. Player may be fine. What exact JAAD library would you use? – Sam Ginrich Aug 25 '23 at 11:53
  • Sorry I'm a bit lost now. What do you mean with "have no requirement"? Do you mean if the required audio quality basically garbage? Maybe I'm having knot in my thought atm, but this decoder 'just' takes the already present audio bits and dumps them into the output. Where does this have influence on the actual quality of the audio itself? Under problems the decoder may bring I imagine e.g. stuttering. That's why I asked of what kind your problem is, making the output for you not acceptable.^^ For the question about the JAAD library: Are there different ones? – 9Lukas5 Aug 26 '23 at 12:28
  • In my case, the output of the decoder (with any AAC source) is already garbage, 90% of the output buffers are constant zero. So my question: Which version of JAAD (ideally source reference) do you deploy? – Sam Ginrich Aug 26 '23 at 15:25
  • 1
    So in other word, the audio doesn't even play? I searched around a fair bit, where I could find copies of the code, and finally settled with a fork of a fork I think it was. I forked it myself and put it to Maven Central, so I could make use of it in the here already linked player. Source of that would be here: https://gitlab.com/9Lukas5/jaad – 9Lukas5 Aug 27 '23 at 16:07