Android AudioTrack/AudioRecord <1>

刚才纠正了一个jni第七节一个错误,昨晚一个晚上没睡着啊.

为什么要看看AudioTrack和AudioRecord,没有为什么,因为不看看,会死人的.

AudioTrack API :http://developer.android.com/reference/android/media/AudioTrack.html

 

<1> : AudioTrack构造函数有两种:第二种我很少用.下面第一种:

public  AudioTrack (int streamType, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes, int mode) 


第一个参数:streamType : 可以去查看AudioManager名下的常量STREAM_VOICE_CALL,STREAM_MUSIC,STREAM_NOTIFICATION等等;

第二个参数:sampleRateInHz : 采样率,一般使用44100,当然还有16000等等;

第三个参数:channelConfig : 通道配置AudioFormat.CHANNEL_OUT_MONO/AudioFormat.CHANNEL_OUT_STEREO;

第四个参数:bufferSizeInBytes : 可以自行根据实际情况配置,也可以通过getMinBufferSize(int, int, int)获取系统能够给出的.

<2> : 初始化如下:

private AudioTrack mPlayer;
private int mPlayBufferSize;
private final int mSampleRateInHz=44100;

...

mPlayBufferSize = AudioTrack.getMinBufferSize(mSampleRateInHz,
                AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);

        mPlayer = new AudioTrack(AudioManager.STREAM_MUSIC, mSampleRateInHz,
                AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT,
                mPlayBufferSize, AudioTrack.MODE_STREAM);


开始准备播放:

mPlayer.play();

AudioTrack是通过向其写入数据流的形式进行播放:
数据流来源:

<a> : 网络;

<b> : 本地存储介质:要读取外部存储介质权限

File mFile=new File(Environment.getExternalStorageDirectory(),"yourwavname.wav");
        try {
            FileInputStream fis=new FileInputStream(mFile);
            try {
                while((length=fis.read(stream_buffer, 0, length))!=-1){
                    mPlayer.write(stream_buffer, 0, length);
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } catch (FileNotFoundException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }


<c> : android工程raw文件夹内的wav等文件.

InputStream is=this.getResources().openRawResource(R.raw.dialtone);
        
        try {
            while((length=is.read(stream_buffer))!=-1){
                mPlayer.write(stream_buffer, 0, length);
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        

<d> : 其他等等.

<3> : 停止播放:

if(mPlayer!=null){
                mPlayer.stop();
                mPlayer.release();
            }

也可以再加一个判断播放状态:

getPlayState () 


<4> : 下面给出全部demo :

package com.example.audiodemo01;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity implements OnClickListener{

    private AudioTrack mPlayer;
    private int mPlayBufferSize;
    private final int mSampleRateInHz=44100;
    
    private Button mPlayBtn;
    private Button mStopBtn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mPlayBufferSize = AudioTrack.getMinBufferSize(mSampleRateInHz,
                AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);

        mPlayer = new AudioTrack(AudioManager.STREAM_MUSIC, mSampleRateInHz,
                AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT,
                mPlayBufferSize, AudioTrack.MODE_STREAM);
        
        mPlayer.play();
        
        mPlayBtn=(Button)findViewById(R.id.button1);
        mPlayBtn.setOnClickListener(this);
        mStopBtn=(Button)findViewById(R.id.button2);
        mStopBtn.setOnClickListener(this);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public void onClick(View arg0) {
        // TODO Auto-generated method stub
        int id;
        id=arg0.getId();
        
        switch(id){
        case R.id.button1:
            new Thread(new Runnable(){

                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    playWav();
                }
                
            }).start();
            break;
        case R.id.button2:
            if(mPlayer!=null){
                mPlayer.stop();
                mPlayer.release();
            }
            
            break;
        }
    }
    
    private void playWav(){
        
        byte[] stream_buffer=new byte[44100];
        int length = 0;
        
        /*File mFile=new File(Environment.getExternalStorageDirectory(),"yourwavname.wav");
        try {
            FileInputStream fis=new FileInputStream(mFile);
            try {
                while((length=fis.read(stream_buffer, 0, length))!=-1){
                    mPlayer.write(stream_buffer, 0, length);
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } catch (FileNotFoundException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }*/
        
        InputStream is=this.getResources().openRawResource(R.raw.dialtone);
        
        try {
            while((length=is.read(stream_buffer))!=-1){
                mPlayer.write(stream_buffer, 0, length);
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }

}
View Code

<5> : 上面不够优化,将初始化等所有操作都放到一个单独的线程中:

package com.example.audiodemo01;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity implements OnClickListener {

    private AudioTrack mPlayer;
    private int mPlayBufferSize;
    private final int mSampleRateInHz = 44100;

    private Button mPlayBtn;
    private Button mStopBtn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mPlayBtn = (Button) findViewById(R.id.button1);
        mPlayBtn.setOnClickListener(this);
        mStopBtn = (Button) findViewById(R.id.button2);
        mStopBtn.setOnClickListener(this);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public void onClick(View arg0) {
        // TODO Auto-generated method stub
        int id;
        id = arg0.getId();

        switch (id) {
        case R.id.button1:
            Thread playThread = new Thread(new PlayThread(), "play");
            playThread.start();
            break;
        case R.id.button2:
            stopPlay();

            break;
        }
    }

    private void playInit() {

        mPlayBufferSize = AudioTrack.getMinBufferSize(mSampleRateInHz,
                AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);

        mPlayer = new AudioTrack(AudioManager.STREAM_MUSIC, mSampleRateInHz,
                AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT,
                mPlayBufferSize, AudioTrack.MODE_STREAM);

        mPlayer.play();

    }

    private void playWav() {

        byte[] stream_buffer = new byte[44100];
        int length = 0;

        /*
         * File mFile=new
         * File(Environment.getExternalStorageDirectory(),"yourwavname.wav");
         * try { FileInputStream fis=new FileInputStream(mFile); try {
         * while((length=fis.read(stream_buffer, 0, length))!=-1){
         * mPlayer.write(stream_buffer, 0, length); } } catch (IOException e) {
         * // TODO Auto-generated catch block e.printStackTrace(); } } catch
         * (FileNotFoundException e1) { // TODO Auto-generated catch block
         * e1.printStackTrace(); }
         */

        InputStream is = this.getResources().openRawResource(R.raw.dialtone);

        try {
            while ((length = is.read(stream_buffer)) != -1) {
                mPlayer.write(stream_buffer, 0, length);
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    private void stopPlay() {
        int status;

        if (mPlayer != null) {
            mPlayer.stop();
            mPlayer.release();
            mPlayer = null;
        }
    }

    private class PlayThread implements Runnable {

        @Override
        public void run() {
            // TODO Auto-generated method stub
            playInit();
            playWav();
        }

    }

}
View Code

 

<6> : 将生命变量也放在线程中,即每次播放时重新创建新的播放器对象,可能对AudioTrack做事多余的,但是个人还是比较推荐这种方式.

推荐下面:

package com.example.audiodemo01;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity implements OnClickListener {

    
    private int mPlayBufferSize;
    private final int mSampleRateInHz = 44100;

    private Button mPlayBtn;
    private Button mStopBtn;
    
    private boolean mStopBool=false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mPlayBtn = (Button) findViewById(R.id.button1);
        mPlayBtn.setOnClickListener(this);
        mStopBtn = (Button) findViewById(R.id.button2);
        mStopBtn.setOnClickListener(this);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public void onClick(View arg0) {
        // TODO Auto-generated method stub
        int id;
        id = arg0.getId();

        switch (id) {
        case R.id.button1:
            Thread playThread = new Thread(new PlayThread(), "play");
            playThread.start();
            break;
        case R.id.button2:
            stopPlay();

            break;
        }
    }

    private void stopPlay(){
        mStopBool=true;
    }

    private void playWav() {

        byte[] stream_buffer = new byte[44100];
        int length = 0;
        
        mStopBool=false;
        
        AudioTrack mPlayer = null;

        mPlayBufferSize = AudioTrack.getMinBufferSize(mSampleRateInHz,
                AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);

        mPlayer = new AudioTrack(AudioManager.STREAM_MUSIC, mSampleRateInHz,
                AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT,
                mPlayBufferSize, AudioTrack.MODE_STREAM);

        mPlayer.play();
        
        /*
         * File mFile=new
         * File(Environment.getExternalStorageDirectory(),"yourwavname.wav");
         * try { FileInputStream fis=new FileInputStream(mFile); try {
         * while((length=fis.read(stream_buffer, 0, length))!=-1){
         * mPlayer.write(stream_buffer, 0, length); } } catch (IOException e) {
         * // TODO Auto-generated catch block e.printStackTrace(); } } catch
         * (FileNotFoundException e1) { // TODO Auto-generated catch block
         * e1.printStackTrace(); }
         */

        InputStream is = this.getResources().openRawResource(R.raw.dialtone);

        try {
            while ((length = is.read(stream_buffer)) != -1) {
                mPlayer.write(stream_buffer, 0, length);
                
                if(mStopBool){
                    if (mPlayer != null) {
                        mPlayer.stop();
                        mPlayer.release();
                        mPlayer = null;
                    }
                    break;
                }
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        if (mPlayer != null) {
            mPlayer.stop();
            mPlayer.release();
            mPlayer = null;
        }

    }

    private class PlayThread implements Runnable {

        @Override
        public void run() {
            // TODO Auto-generated method stub
            playWav();
        }

    }

}

 

其中不涉及AudioTrack不组织了.

上面playWav()方法中文件流没关闭,添加上下面一句:

is.close();

 

<7> : 上面再Thread线程中实现播放音乐,在网上看到其他人采用AsyncTask,同样稍微将上面修改一下,demo如下:

package com.example.audiodemo01;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity implements OnClickListener {

    
    private int mPlayBufferSize;
    private final int mSampleRateInHz = 44100;

    private Button mPlayBtn;
    private Button mStopBtn;
    
    private boolean mStopBool=false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mPlayBtn = (Button) findViewById(R.id.button1);
        mPlayBtn.setOnClickListener(this);
        mStopBtn = (Button) findViewById(R.id.button2);
        mStopBtn.setOnClickListener(this);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public void onClick(View arg0) {
        // TODO Auto-generated method stub
        int id;
        id = arg0.getId();

        switch (id) {
        case R.id.button1:
//            Thread playThread = new Thread(new PlayThread(), "play");
//            playThread.start();
            
            PlayTask task=new PlayTask();
            task.execute();
            break;
        case R.id.button2:
            stopPlay();

            break;
        }
    }

    private void stopPlay(){
        mStopBool=true;
    }

    private void playWav() {

        byte[] stream_buffer = new byte[44100];
        int length = 0;
        
        mStopBool=false;
        
        AudioTrack mPlayer = null;

        mPlayBufferSize = AudioTrack.getMinBufferSize(mSampleRateInHz,
                AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);

        mPlayer = new AudioTrack(AudioManager.STREAM_MUSIC, mSampleRateInHz,
                AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT,
                mPlayBufferSize, AudioTrack.MODE_STREAM);

        mPlayer.play();
        
        /*
         * File mFile=new
         * File(Environment.getExternalStorageDirectory(),"yourwavname.wav");
         * try { FileInputStream fis=new FileInputStream(mFile); try {
         * while((length=fis.read(stream_buffer, 0, length))!=-1){
         * mPlayer.write(stream_buffer, 0, length); } } catch (IOException e) {
         * // TODO Auto-generated catch block e.printStackTrace(); } } catch
         * (FileNotFoundException e1) { // TODO Auto-generated catch block
         * e1.printStackTrace(); }
         */

        InputStream is = this.getResources().openRawResource(R.raw.dialtone);

        try {
            while ((length = is.read(stream_buffer)) != -1) {
                mPlayer.write(stream_buffer, 0, length);
                
                if(mStopBool){
                    if (mPlayer != null) {
                        mPlayer.stop();
                        mPlayer.release();
                        mPlayer = null;
                    }
                    break;
                }
            }
            
            is.close();
            
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        if (mPlayer != null) {
            mPlayer.stop();
            mPlayer.release();
            mPlayer = null;
        }

    }

    private class PlayThread implements Runnable {

        @Override
        public void run() {
            // TODO Auto-generated method stub
            playWav();
        }

    }
    
    private class PlayTask extends AsyncTask<Void,Integer,Void>{

        @Override
        protected Void doInBackground(Void... arg0) {
            // TODO Auto-generated method stub
            playWav();
            return null;
        }
        
    }

}


<8> : 在app应用中会在service中进行播放音乐,Activity向其发送广播,附带"命令"进行控制,不过这里不想去回忆一下service如何开发.

 

 

 

 

 

 

 

 

 

 

posted @ 2014-03-19 00:14  MMLoveMeMM  阅读(416)  评论(0)    收藏  举报