Android Open Source - AndroidPitchPlayer Pitch Player






From Project

Back to project page AndroidPitchPlayer.

License

The source code is released under:

This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a co...

If you think the Android project AndroidPitchPlayer listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package de.showlabor.example.pitchplayer;
/*from   www  . ja v  a 2 s .  co  m*/
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.media.MediaCodec;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.util.Log;

import java.io.IOException;
import java.nio.ByteBuffer;

/**
 * Created by Felix Homann, linuxaudio@showlabor.de
 *
 * This is a quick and dirty demo of how to use MediaExtractor, MediaCodec and AudioTrack
 * to create a pitch shifting audio stream player.
 *
 * Nothing here seems to be copyrightable IMO.
 *
 * NOTE TO MYSELF: DON'T FORGET TO ADD INTERNET PERMISSION TO THE APP!
 *
 */
public class PitchPlayer implements Runnable {

    private MediaCodec mCodec;
    private MediaExtractor mExtractor;
    private String mPath;
    private AudioTrack mAudioTrack = null;
    private int mBufferSize = 0;

    private float mRelativePlaybackSpeed = 1.f;
    private int mSrcRate = 44100;
    private boolean isPlaying = false;
    private boolean doStop = false;

    private final static long TIMEOUT_US = 1000;

    public PitchPlayer(String path) {
        mPath = path;
    }

    private void prepare() {
        // Setup a MediaExtractor to get information about the stream
        // and to get samples out of the stream
        mExtractor = new MediaExtractor();
        try {
            mExtractor.setDataSource(mPath);
        } catch (IOException e) {
            e.printStackTrace();
        }

        if (mExtractor.getTrackCount() > 0) {
            // Get mime type of the first track
            MediaFormat format = mExtractor.getTrackFormat(0);
            String mime = format.getString(MediaFormat.KEY_MIME);
            if (mime.startsWith("audio")) {
                mCodec = MediaCodec.createDecoderByType(mime);
                mCodec.configure(format,
                        null, // We don't have a surface in audio decoding
                        null, // No crypto
                        0); // 0 for decoding

                // Select the first track for decoding
                mExtractor.selectTrack(0);
                mCodec.start(); // Fire up the codec
                // Create an AudioTrack. Don't make the buffer size too small:
                mBufferSize = 8 * AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT);
                mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
                        44100,
                        AudioFormat.CHANNEL_OUT_STEREO,
                        AudioFormat.ENCODING_PCM_16BIT,
                        mBufferSize,
                        AudioTrack.MODE_STREAM);
                // Don't forget to start playing        
                mAudioTrack.play();
            }
        }
    }

    public void start() {
        isPlaying = true;
        doStop = false;
        new Thread(this).start();
    }

    public void stop() {
        doStop = true;
    }

    public void run() {
        // We use a single thread here for decoding stream data and
        // writing to the AudioTrack. Consider using a seperate thread for each task.
        prepare();
        ByteBuffer[] inputBuffers = mCodec.getInputBuffers();
        ByteBuffer[] outBuffers = mCodec.getOutputBuffers();
        ByteBuffer activeOutBuffer = null; // The active output buffer
        int activeIndex = 0; // Index of the active buffer

        int availableOutBytes = 0;
        int writeableBytes = 0;
        // writeBuffer stores the samples until they can be written out to the AudioTrack
        final byte[] writeBuffer = new byte[mBufferSize];
        int writeOffset = 0;

        MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();

        boolean EOS = false;
        
        while (!Thread.interrupted() && !doStop) {
            // Get PCM data from the stream
            if (!EOS) {
                // Dequeue an input buffer
                int inIndex = mCodec.dequeueInputBuffer(TIMEOUT_US);
                if (inIndex >= 0) {
                    ByteBuffer buffer = inputBuffers[inIndex];
                    // Fill the buffer with stream data
                    int sampleSize = mExtractor.readSampleData(buffer, 0);
                    // Pass the stream data to the codec for decoding: queueInputBuffer 
                    if (sampleSize < 0) {
                        // We have reached the end of the stream
                        mCodec.queueInputBuffer(inIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
                        EOS = true;
                    } else {
                        mCodec.queueInputBuffer(inIndex, 0, sampleSize, mExtractor.getSampleTime(), 0);
                        mExtractor.advance();
                    }
                }
            }

            if (availableOutBytes == 0) {
                // we don't have any samples available: Dequeue a new output buffer.
                activeIndex = mCodec.dequeueOutputBuffer(info, TIMEOUT_US);

                // outIndex might carry some information for us.
                switch (activeIndex) {
                case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
                    outBuffers = mCodec.getOutputBuffers();
                    break;
                case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
                    // Update the playback rate
                    MediaFormat outFormat = mCodec.getOutputFormat();
                    mSrcRate = outFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE);
                    mAudioTrack.setPlaybackRate((int) (mSrcRate * mRelativePlaybackSpeed));
                case MediaCodec.INFO_TRY_AGAIN_LATER:
                    // Nothing to do
                    break;
                default:
                    // set the activeOutBuffer
                    activeOutBuffer = outBuffers[activeIndex];
                    availableOutBytes = info.size;
                    assert info.offset == 0;
                }
            }

            if (activeOutBuffer != null && availableOutBytes > 0) {
                writeableBytes = Math.min(availableOutBytes, mBufferSize - writeOffset);
                // Copy as many samples to writeBuffer as possible
                activeOutBuffer.get(writeBuffer, writeOffset, writeableBytes);
                availableOutBytes -= writeableBytes;
                writeOffset += writeableBytes;
            }

            if (writeOffset == mBufferSize) {
                // The buffer is full. Submit it to the AudioTrack
                mAudioTrack.write(writeBuffer, 0, mBufferSize);
                writeOffset = 0;
            }

            if (activeOutBuffer != null && availableOutBytes == 0) {
                // IMPORTANT: Clear the active buffer!
                activeOutBuffer.clear();
                if (activeIndex >= 0) {
                    // Give the buffer back to the codec
                    mCodec.releaseOutputBuffer(activeIndex, false);
                }
            }

            if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
                // Get out of here
                break;
            }
        }

        //Clean up
        isPlaying = false;
        doStop = false;
        mCodec.stop();
        mCodec.release();
        mExtractor.release();
    }

    public void setRelativePlaybackSpeed(float speed) {
        mRelativePlaybackSpeed = speed;
        if (mAudioTrack != null) {
            mAudioTrack.setPlaybackRate((int) (mSrcRate * mRelativePlaybackSpeed));
        }
    }

    public void setVolume(float vol) {
        if (mAudioTrack != null) {
            mAudioTrack.setStereoVolume(vol, vol);
        }
    }

    public boolean isPlaying() {
        return isPlaying;
    }
}




Java Source Code List

de.showlabor.example.pitchplayer.MainActivity.java
de.showlabor.example.pitchplayer.PitchPlayer.java