'javax.sound.sampled.LineUnavailableException: null' ERROR trying to play audio. (Only on Ubuntu)

553 views
Skip to first unread message

caleb...@gmail.com

unread,
Feb 12, 2014, 3:46:22 PM2/12/14
to beagl...@googlegroups.com
Hello! I have a problem thats been stumping me for a while. I'm quite new at developing Java and I may be in over my head with this one. Please forgive me if I haven't posted in the correct format of something.

I am running Ubuntu 12.04 with 'lightweight x11 desktop environment' off of a BeagleBone Black. The Java code below is supposed to play a .wav file (Ive also tried switching to .mp3 with no luck) when a notification occurs. This all works fine on OSX but Errors out on the BeagleBone.

This is my troubleshooting so far:
I have successfully gotten the BeagleBone to make white noise through the terminal command 

speaker-test -D default:CARD=Headset 

I could NOT play anything using the following terminal command:

mplayer -ao alsa:device=default=Headset XXX.mp3

Also, I could not play anything using the built in audio player including the supplied .mp3. This may be irrelevant but I have also successfully commented out relevant java lines to avoid making any sound just so the program can run.

Heres the code:

package com.XXXXXX.ibis.notification;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import javax.sound.sampled.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class AudioNotification implements INotification {

    /**
     *
     * @param audioURL
     * @param intervalMS
     */
    public AudioNotification(URL audioURL, int intervalMS) {

        m_intervalMS = intervalMS;
        m_audioURL   = audioURL;

    }

    /**
     *
     * @param filename
     * @param intervalMS
     */
    public AudioNotification(String filename, int intervalMS) {

        m_intervalMS = intervalMS;

        try {
            m_audioURL = new URI(filename).toURL();
         } catch (URISyntaxException ex) {
            LOG.error("Unable to convert filename(" + filename + ") to URI", ex);
        } catch (MalformedURLException ex) {
            LOG.error("Unable to convert filename(" + filename + ") to URL", ex);
        }

    }

    //**************************************************************************
    //** INotification interface ***********************************************
    //**************************************************************************
    /**
     *
     * @param bActivate
     */
    @Override
    public void activate(boolean bActivate) {
        if (bActivate != isActive()) {
            if (isActive()) {
                stop();
            } else {
                try {
                    start();
                } catch (InterruptedException ex) {
                    java.util.logging.Logger.getLogger(AudioNotification.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
    } // activate

    /**
     *
     * @return
     */
    @Override
    public boolean isActive() {
        return (m_playTask != null);
    } // isActive

    /**
     *
     */
    @Override
    public void signal() {
        LOG.debug("signal()");
    } // signal

    //**************************************************************************
    //** PRIVATE METHODS *******************************************************
    //**************************************************************************
    /**
     *
     */
    private void start() throws InterruptedException {
        LOG.debug("start()");
        // start audio playback timer
        if (m_playTask == null) {
            try {
                // TODO: only play 5 times?
                m_playTask = new PlayClipTask(m_audioURL.openStream());
                long timerIntervalMS = (m_intervalMS + m_playTask.clipLengthMS());
                //m_timer.schedule(m_playTask, timerIntervalMS, timerIntervalMS);
                for (int i = 0; i < REPEAT; i++) {
                    m_timer.schedule(m_playTask, timerIntervalMS);
                    Thread.sleep(timerIntervalMS * SLEEP_TIME);
                    m_playTask = new PlayClipTask(m_audioURL.openStream());
                }
            } catch (IOException ex) {
                LOG.warn("start(): Error creating play task", ex);
            }
        } else {
            LOG.warn("start(): Playback already in progress");
        }
    } // start

    /**
     *
     */
    private void stop() {
        LOG.debug("stop()");
        // cancel audio playback timer
        if (m_playTask != null) {
            m_playTask.stopPlayback();
            m_playTask.cancel();
            m_playTask = null;
        }
    } // stop

    //**************************************************************************
    //** PRIVATE CLASSES *******************************************************
    //**************************************************************************
    private class PlayClipTask extends TimerTask {
        /**
         *
         * @param source
         */
        public PlayClipTask(InputStream source) {
            m_clip = loadAudioClip(source);
        }
        /**
         *
         * @return
         */
        public long clipLengthMS() {
            if (m_clip != null) {
                return (m_clip.getMicrosecondLength() / 1000L);
            } else {
                return (0);
            }
        } // clipLengthMS
        /**
         *
         */
        @Override
        public void run() {
            if (m_clip != null) {
                if (m_clip.isActive()) {
                    LOG.debug("PlayClipTask.run(): stop audio clip");
                    m_clip.stop(); // reset
                }
                m_clip.setFramePosition(0);
                LOG.debug("PlayClipTask.run(): start audio clip");
                m_clip.start();
            } else {
                LOG.warn("PlayClipTask.run(): Clip is NULL");
            }
        } // run
        /**
         *
         */
        public void stopPlayback() {
            if (m_clip != null) {
                LOG.debug("PlayClipTask.stopPlayback(): stop audio clip");
                if (m_clip.isActive()) {
                    m_clip.stop();
                }
                m_clip.flush();
                m_clip.close();
                m_clip = null;
            } else {
                LOG.warn("PlayClipTask.stopPlayback(): Clip is NULL");
            }
        } // stopPlayback
        /**
         *
         * @param source
         * @return
         */
        private Clip loadAudioClip(InputStream source) {

            Clip theClip = null;

            try {

                // read audio from source

                // add buffer for mark/reset support
                InputStream bufferedSource = new BufferedInputStream(source);
                AudioInputStream inStream = AudioSystem.getAudioInputStream(bufferedSource);
                AudioFormat      f        = inStream.getFormat();

                theClip = (Clip)AudioSystem.getLine(new DataLine.Info(Clip.class, f));
                theClip.open(inStream);

            } catch (UnsupportedAudioFileException ex) {
                LOG.error("PlayClipTask.loadAudioFile()", ex);
            } catch (LineUnavailableException ex) {
                LOG.error("PlayClipTask.loadAudioFile()", ex);
            } catch (IOException ex) {
                LOG.error("PlayClipTask.loadAudioFile()", ex);
            }

            return (theClip);

        } // loadAudioClip
        private Clip m_clip = null;
    } // class PlayClipTask

    //**************************************************************************
    //** PRIVATE VARIABLES *****************************************************
    //**************************************************************************
    private static final Logger LOG = LoggerFactory.getLogger(AudioNotification.class);

//    private static final String DEFAULT_SOUND = "com/XXXXXXX/YYYYY/audio/Minke_Whale.wav";

    private final int m_intervalMS;

    private URL          m_audioURL = null;

    private Timer        m_timer    = new Timer();
    private PlayClipTask m_playTask = null;
    private final static int REPEAT = 4;        // HAS
    private final static int SLEEP_TIME = 1;    // HAS

} // class AudioNotification
and the error is:

ERROR AudioNotification - PlayClipTask.loadAudioFile()
javax.sound.sampled.LineUnavailableException: null
Could the BeagleBone Black be incapable of playing audio files using Java? Or is there a change I can implement in the code to work around the error? Any help is appreciated!

caleb frost

unread,
Feb 12, 2014, 3:52:22 PM2/12/14
to beagl...@googlegroups.com
Oh also, I'm using a generic USB sound card FYI

caleb frost

unread,
Feb 12, 2014, 4:29:07 PM2/12/14
to beagl...@googlegroups.com
ugh sorry. its also a beaglebone. not beaglebone black


On Wednesday, February 12, 2014 3:46:22 PM UTC-5, caleb frost wrote:

Rusty Wright

unread,
Feb 12, 2014, 7:19:33 PM2/12/14
to beagl...@googlegroups.com
In your methods that are catching exceptions, they're continuing after you catch the exception
which is not what you want in general.  When you catch an exception the program isn't terminated
unless you throw one in the catch clause.  Catching an exception means that you're going to do
some sort of recovery in general, unless you throw another one in the catch clause.  You could
also close file descriptors in the catch clause and then rethrow the exception that you caught.

Unless you're going to do something when you catch the exception you should just let the
exceptions terminate the program, meaning that you'll need to add the appropriate throws clauses.
That should also give you a stack trace which may be helpful.  And it will include the name of
the exception, and possibly the reason.

I did a google search on javax.sound.sampled.LineUnavailableException and there were some
queries about that exception on StackOverflow.  Try doing a google search and see what you find.


Drew Gonsalves

unread,
Apr 16, 2014, 11:05:30 AM4/16/14
to beagl...@googlegroups.com
Have you been able to solve this problem? I am in the same situation. Thank you. This is what I am seeing:

Exception in thread "main" java.lang.IllegalArgumentException: No line matching interface Clip supporting format PCM_SIGNED unknown sample rate, 16 bit, stereo, 4 bytes/frame, big-endian is supported.

        at javax.sound.sampled.AudioSystem.getLine(AudioSystem.java:476)

        at javax.sound.sampled.AudioSystem.getClip(AudioSystem.java:520)

        at org.mdpnp.helloice.Audio.play(Audio.java:46)

        at org.mdpnp.helloice.HelloICE_Numeric.main(HelloICE_Numeric.java:208)


I am not sure if it has to do with Clip, AudioSystem, Mixer... Do we need to setup anything special due to JAVA being run on BBB? Do we need to modify */java/ejre1.7.0_45/lib/sound.properties file? If I do 'arecord -l' at command line I see my USB audio dongle:

Exception in thread "main" java.lang.IllegalArgumentException: No line matching interface Clip supporting format PCM_SIGNED unknown sample rate, 16 bit, stereo, 4 bytes/frame, big-endian is supported.

        at javax.sound.sampled.AudioSystem.getLine(AudioSystem.java:476)

        at javax.sound.sampled.AudioSystem.getClip(AudioSystem.java:520)

        at org.mdpnp.helloice.Audio.play(Audio.java:46)

        at org.mdpnp.helloice.HelloICE_Numeric.main(HelloICE_Numeric.java:208)


Thank you.

    private class PlayClipTask extends <span style="background-colo
...
Reply all
Reply to author
Forward
0 new messages