DirectPCMFeed.java :  » Port » aacplayer-android » com » spoledge » aacplayer » Android Open Source

Android Open Source » Port » aacplayer android 
aacplayer android » com » spoledge » aacplayer » DirectPCMFeed.java
/*
** AACPlayer - Freeware Advanced Audio (AAC) Player for Android
** Copyright (C) 2010 Spolecne s.r.o., http://www.spoledge.com
**  
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
** 
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
** 
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software 
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**/
package com.spoledge.aacplayer;

import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;

import android.util.Log;

import java.nio.ShortBuffer;


/**
 * This is the PCM Feeder.
 * Uses java.nio.* API.
 */
public class DirectPCMFeed implements Runnable {

    private static final String LOG = "DirectPCMFeed";


    ////////////////////////////////////////////////////////////////////////////
    // Attributes
    ////////////////////////////////////////////////////////////////////////////

    private int sampleRate;
    private int channels;
    private int minBufferSizeInBytes;

    private ShortBuffer buffer;

    private boolean stopped;


    ////////////////////////////////////////////////////////////////////////////
    // Constructors
    ////////////////////////////////////////////////////////////////////////////

    public DirectPCMFeed( int sampleRate, int channels) {
        this( sampleRate, channels,
            AudioTrack.getMinBufferSize( sampleRate, channels == 1 ?
                AudioFormat.CHANNEL_CONFIGURATION_MONO :
                AudioFormat.CHANNEL_CONFIGURATION_STEREO,
                AudioFormat.ENCODING_PCM_16BIT ) * 9 / 3 );
    }


    public DirectPCMFeed( int sampleRate, int channels, int minBufferSizeInBytes ) {
        this.sampleRate = sampleRate;
        this.channels = channels;
        this.minBufferSizeInBytes = minBufferSizeInBytes;
    }


    ////////////////////////////////////////////////////////////////////////////
    // Public
    ////////////////////////////////////////////////////////////////////////////


    public void run() {
        Log.d( LOG, "run(): sampleRate=" + sampleRate + ", channels=" + channels + ", minBufferSizeInBytes=" + minBufferSizeInBytes);
        AudioTrack atrack = new AudioTrack(
                                AudioManager.STREAM_MUSIC,
                                sampleRate,
                                channels == 1 ?
                                    AudioFormat.CHANNEL_CONFIGURATION_MONO :
                                    AudioFormat.CHANNEL_CONFIGURATION_STEREO,
                                AudioFormat.ENCODING_PCM_16BIT,
                                minBufferSizeInBytes,
                                AudioTrack.MODE_STREAM );

        atrack.play();

        short[] lsamples = null;

        while (!stopped) {
            ShortBuffer lbuffer = null;

            synchronized (this) {
                while (buffer == null && !stopped) {
                    Log.d( LOG, "run() waiting...");
                    try { wait(); } catch (InterruptedException e) {}
                    Log.d( LOG, "run() awaken...");
                }

                lbuffer = buffer;
                buffer = null;
                notify();
            }

            if (stopped) break;

            int ln = lbuffer.remaining();

            if (lbuffer.hasArray()) {
                lsamples = lbuffer.array();
            }
            else {
                if (lsamples == null || lsamples.length < lbuffer.capacity()) {
                    Log.d( LOG, "ShortBuffer not backed by array, creating own one...");
                    lsamples = null;
                    lsamples = new short[ lbuffer.capacity()];
                }

                lbuffer.get( lsamples, 0, ln );
            }

            int playedTotal = 0;

            do {
                if (playedTotal != 0) {
                    Log.d( LOG, "too fast for playback, sleeping...");
                    try { Thread.sleep( 100 ); } catch (InterruptedException e) {}
                }

                Log.d( LOG, "feeding PCM...");
                int played = atrack.write( lsamples, 0, ln );
                Log.d( LOG, "PCM fed by " + ln + " and played " + played + " samples");

                if (played < 0) {
                    Log.e( LOG, "error in playback feed: " + played );
                    stopped = true;
                    break;
                }

                if (lbuffer.hasArray()) {
                    lbuffer.clear();
                }

                playedTotal += played;
            } while (playedTotal < ln);
        }

        Log.d( LOG, "run() stopped." );
    }


    public synchronized void stop() {
        stopped = true;
        notify();
    }


    public synchronized void feed( ShortBuffer buffer ) {
        Log.d( LOG, "feed() len=" + buffer.remaining());
        while (this.buffer != null && !stopped) {
            Log.d( LOG, "feed() waiting...");
            try { wait(); } catch (InterruptedException e) {}
            Log.d( LOG, "feed() awaken");
        }

        this.buffer = buffer;

        notify();
    }

}


java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.