AudioTrack 播放PCM音频数据

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zxd_Android/article/details/82149989

AudioTrack 可以用来播放PCM数据,上一篇博客我讲了AudioRecord可以录制PCM数据
AudioTrack实例可以在两种模式下运行:静态或流式传输。
在Streaming模式下,应用程序使用write()方法之一将连续的数据流写入AudioTrack。当数据从Java层传输到native层并排队等待回放时,这些是阻塞和返回。在播放音频数据块时,流模式最有用,以下情形适用于流模式:
1、由于播放时间太长,数据量太大以至于内存紧张。
2、由于音频数据的特性(高采样率,每个样本的位数……),因此太大而无法存储在内存中。
3、在播放先前排队的音频时接收或生成。

在处理适合内存的短音并且需要以尽可能小的延迟播放时,应选择静态模式。因此,静态模式将优选用于经常播放的UI和游戏声音,并且可能具有最小的开销

AudioTrack的构造函数目前一共是三个,public AudioTrack (int streamType, int sampleRateInHz,int channelConfig, int audioFormat, int bufferSizeInBytes, int mode, int sessionId) 等带有 streamType的已经在API 26以后废弃
下面是使用 示例

package com.example.mediatest;
import android.content.Context;
import android.media.AudioAttributes;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.Environment;
import android.util.Log;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

/**
 * Created by zhangxd on 2018/8/25.
 */

public class AudioTrackManager {

    private static final String TAG = AudioTrack.class.getSimpleName();

    public static String PATH = Environment.getExternalStorageDirectory().getAbsolutePath() + "/audio.pcm";

    private static AudioTrackManager instance;

    private int mSampleRate = 44100;

    private int channelCount = 2;

    private AudioTrack mAudioTrack;

    private int channelConfig = AudioFormat.CHANNEL_IN_STEREO;

    private int bufferSize;

    private int audioFormatEncode = AudioFormat.ENCODING_PCM_16BIT;

    private AudioManager mAudioManager;

    private Context mContext;

    private AudioFormat mAudioFormat;

    private FileInputStream fileInputStream;

    private boolean startPlay = false;

    public AudioTrackManager() {

    }

    public static AudioTrackManager getInstance() {
        if (instance == null) {
            instance = new AudioTrackManager();
        }
        return instance;
    }

    public void setContext(Context context) {
        this.mContext = context;
        init();
    }

    private void init() {
        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
        bufferSize = AudioTrack.getMinBufferSize(mSampleRate, channelConfig, audioFormatEncode);
        int sessionId = mAudioManager.generateAudioSessionId();
        AudioAttributes audioAttributes = new AudioAttributes.Builder()
                .setUsage(AudioAttributes.USAGE_MEDIA)
                .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                .build();
        AudioFormat audioFormat = new AudioFormat.Builder().setSampleRate(mSampleRate)
                .setEncoding(audioFormatEncode)
                .setChannelMask(channelConfig)
                .build();
        mAudioTrack = new AudioTrack(audioAttributes, audioFormat, bufferSize * 2, AudioTrack.MODE_STREAM, sessionId);
        try {
            fileInputStream = new FileInputStream(PATH);
        } catch (FileNotFoundException e) {
            Log.e(TAG, "init: " + e);
        }
    }

    public void startThread() {
        startPlay = true;
        new PlayThread().start();
    }

    public void stopThread() {
        startPlay = false;
        mAudioTrack.stop();
        mAudioTrack.release();
    }

    class PlayThread extends Thread {
        @Override
        public void run() {
            super.run();
            byte[] buffer = new byte[bufferSize];
            mAudioTrack.play();
            try {
                while (fileInputStream.read(buffer) > 0) {
                    mAudioTrack.write(buffer, 0, buffer.length);
                }

            } catch (IOException e) {
                Log.e(TAG, "IOException " + e);
            }

        }
    }


}

猜你喜欢

转载自blog.csdn.net/zxd_Android/article/details/82149989