Results 1 to 4 of 4
  1. #1
    cris9288 is offline Member
    Join Date
    Dec 2011
    Posts
    11
    Rep Power
    0

    Default playing audio and managing memory

    Hi,

    I am trying to implement a small audio player (currently no GUI) but I am having some concerns regarding the amount of RAM my program is using. What I have written works as expected; however, with every next and previous command I notice my RAM usage go up. I guess this isn't really surprising based on what my code is doing, but I do expect some memory to be freed periodically. This never happens despite my calls to close(), drain(), and flush() on the respective line/stream objects. My used RAM will keep increasing as I switch audio files.

    I'm hoping to get some feedback on what I could be doing wrong. Initially, I performed audio IO using a Clip, but it took way too long to start playing each mp3 (wav's were actually much faster, but i'm assuming this is due them being uncompressed/unencoded?). I looked googled a bit and found an example that used a SourceDataLine, which turned out to perform much faster. I'm pretty new to working with threads, so I'm sure there's a better approach to doing what I want, but this is what I've come up with based on what I've read up on so far. I appreciate any and all feedback/advice. Thanks.

    Java Code:
    import java.io.File;
    import java.io.IOException;
    import javax.sound.sampled.AudioFormat;
    import javax.sound.sampled.AudioInputStream;
    import javax.sound.sampled.AudioSystem;
    import javax.sound.sampled.Clip;
    import javax.sound.sampled.DataLine;
    import javax.sound.sampled.LineEvent;
    import javax.sound.sampled.LineListener;
    import javax.sound.sampled.LineUnavailableException;
    import javax.sound.sampled.SourceDataLine;
    import javax.sound.sampled.UnsupportedAudioFileException;
    
    /**
     *
     * @author christian
     */
    class AudioControl {
        
        public static final int PLAYING = 0; //audio is being played back
        public static final int STOPPED = 1; //audio playback has been stopped
        public static final int PAUSED = 2; //audio playback has been paused
        public static final int DONE = 3; //audio playback has finished
        public static final int BUFFER_SIZE = 4096;
        
        private int playerState; 
        private SourceDataLine nowPlaying;
        private File soundFile;
        
        /* thread that governs audio playback. Everytime a new track is started
         * a new thread is spawned. 
         */
        private Thread playbackThread;
        
       
        private AudioIORunnable audioIORunnable;
        private AudioInputStream audioStream;
        
        AudioControl() {
            playerState = STOPPED;
        }
      
        
        private class AudioIORunnable implements Runnable {
            
            @Override
            public void run() {
                try {
                    
                    //decode the audio file
                    AudioInputStream in = AudioSystem.getAudioInputStream(soundFile);
                    AudioFormat baseFormat = in.getFormat();
                    AudioFormat decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
                                                                baseFormat.getSampleRate(),
                                                                16,
                                                                baseFormat.getChannels(),
                                                                baseFormat.getChannels() * 2,
                                                                baseFormat.getSampleRate(),
                                                                false);
                    
                    audioStream = AudioSystem.getAudioInputStream(decodedFormat, in);
                    // play it...
                    playerState = PLAYING;
                    writeAudioData(decodedFormat, audioStream);
                    in.close();
                }
                catch(UnsupportedAudioFileException | LineUnavailableException | IOException e) {      
                    stopPlayback();
                }
            }
            
            private synchronized void writeAudioData(AudioFormat targetFormat, AudioInputStream din) throws IOException, LineUnavailableException {
                
                byte[] audioData = new byte[BUFFER_SIZE];
                
                //get and open a line for the formate specified
                getLine(targetFormat);
                
                if (nowPlaying != null) {
                    // Start
                    nowPlaying.start();
                    int bytesRead = 0;
                    bytesRead = din.read(audioData, 0, audioData.length);
                    
                    while (playerState != STOPPED && bytesRead != -1) {
                        
                        
                        if(playerState == PAUSED) {
                            try {
                                wait();
                            }
                            catch(InterruptedException e) {
                                System.out.println(e);
                            }
                        }
                        nowPlaying.write(audioData, 0, bytesRead);
                        bytesRead = din.read(audioData, 0, audioData.length);
                                                            
                    }
    
                    // Stop - discard all read data and close open line/stream
                    nowPlaying.stop();
                    nowPlaying.drain();
                    nowPlaying.close();
                    din.skip(din.available());
                    din.close();
                }
    
            }
            
            private synchronized void getLine(AudioFormat audioFormat) throws LineUnavailableException {
                
                DataLine.Info info =
                        new DataLine.Info(SourceDataLine.class, audioFormat);
                
                nowPlaying = (SourceDataLine) AudioSystem.getLine(info);
                nowPlaying.open(audioFormat);
       
            }
        }
        
        public void play(File audioFile) {
            
            
            stopPlayback(); //stop the current track if it's playing
            soundFile = audioFile; //set the current file 
    
            //start a new thread with a new Runnable object
            audioIORunnable = new AudioIORunnable(); 
            try {
                if(playbackThread != null)
                    playbackThread.join();
            }
            catch(InterruptedException e) {
                System.out.println(e);
            }
            finally {
                playbackThread = new Thread(audioIORunnable);
                playbackThread.start();
            }
            
        }
        
        public void stopPlayback() {
            
            //stop playback 
            if(playerState == PLAYING || playerState == PAUSED) {
                playerState = STOPPED;
                nowPlaying.stop();  
                nowPlaying.flush();
                soundFile = null;
            }
        }
    
        public void pause() {
            
            if(playerState == PLAYING) {
                playerState = PAUSED;
                nowPlaying.stop();
            }
        }
        
        public void resume() {
            final AudioIORunnable audioIO = audioIORunnable;
            
            if(playerState == PAUSED) {
                nowPlaying.start();
                
                synchronized(audioIO) {
                    playerState = PLAYING;
                    audioIO.notifyAll();
                }
            }
        }
        
        public void exit() {
            
            if(playbackThread != null && playbackThread.isAlive()) {
                playbackThread.interrupt();
                playbackThread = null;
            }
            
            if(audioStream != null) {
                
                try {
                    audioStream.close();
                }
                catch(IOException e) {
                    System.out.println(e);
                }
            }
        }
    }

  2. #2
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,170
    Rep Power
    20

    Default Re: playing audio and managing memory

    How are you monitoring your memory usage?
    Please do not ask for code as refusal often offends.

    ** This space for rent **

  3. #3
    cris9288 is offline Member
    Join Date
    Dec 2011
    Posts
    11
    Rep Power
    0

    Default Re: playing audio and managing memory

    I'm just using my OS's process viewer (htop). Is this not a good way of monitoring memory?

  4. #4
    JosAH's Avatar
    JosAH is offline Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,727
    Blog Entries
    7
    Rep Power
    21

    Default Re: playing audio and managing memory

    If there is still free memory available for the jvm process, the garbage collector doesn't do anything; only if it hits an 'out of memory' condition it starts freeing objects and reclaiming memory. The symptom you see is that the process takes up more and more memory until it hits the OS imposed barrier; the garbage collector (almost) never gives back free memory to the OS but keeps it as free memory, to be used by newly instantiated objects.

    kind regards,

    Jos
    cenosillicaphobia: the fear for an empty beer glass

Similar Threads

  1. JMF Playing an audio error
    By vivekme77 in forum New To Java
    Replies: 2
    Last Post: 02-11-2013, 05:28 AM
  2. How to clear Audio Clips from memory
    By JagFig in forum Advanced Java
    Replies: 0
    Last Post: 11-01-2012, 04:45 AM
  3. Playing audio clips
    By robs in forum Threads and Synchronization
    Replies: 24
    Last Post: 06-26-2012, 08:14 PM
  4. Highlight text on playing audio
    By archanaanbu in forum Java Applets
    Replies: 1
    Last Post: 02-22-2011, 02:34 PM
  5. playing audio in J-App??
    By ashton in forum New To Java
    Replies: 3
    Last Post: 01-30-2009, 09:50 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •