在 Android 中播放 PCM 流

Play PCM stream in Android

我正在通过以太网端口获取 PCM 流。到目前为止,我能够捕获数据包并从中取出 pcm_payload 数据。

如何在 android 中播放此原始 PCM 数据? PCM数据为16位2通道,44.1kHZ码流。

我是 android 应用程序编程和音频编程的新手。对不起,如果这是一个微不足道的问题。

您可以使用AudioTrack来播放PCM数据!

可能是这样的:

int bufsize = AudioTrack.getMinBufferSize(44100,
           AudioFormat.CHANNEL_OUT_STEREO,
           AudioFormat.ENCODING_PCM_16BIT);

AudioTrack audio = new AudioTrack(AudioManager.STREAM_MUSIC, 
                       44100, //sample rate
                       AudioFormat.CHANNEL_OUT_STEREO, //2 channel
                       AudioFormat.ENCODING_PCM_16BIT, // 16-bit
                       bufsize, 
                       AudioTrack.MODE_STREAM );
audio.play()

然后调用 audio.write() 写入您的 PCM 数据。

这是我的解决方案。将流写入文件并播放

public class AudioTrackPlayer {
private String pathAudio;
private AudioTrack audioPlayer;
private Thread mThread;
private int bytesread = 0, ret = 0;
private int size;
private FileInputStream in = null;
private byte[] byteData = null;
private int count = 512 * 1024; // 512 kb
private boolean isPlay = true;
private boolean isLooping = false;
private static Handler mHandler;

public AudioTrackPlayer() {

}

public void prepare(String pathAudio){
    this.pathAudio = pathAudio;
    mHandler = new Handler();
}

public void play(){
    stop();

    isPlay = true;
    bytesread = 0;
    ret = 0;
    if (pathAudio == null)
        return;

    audioPlayer = createAudioPlayer();
    if (audioPlayer == null) return;
    audioPlayer.play();

    mThread = new Thread(new PlayerProcess());
    mThread.start();
}

private final Runnable mLopingRunnable = new Runnable() {
    @Override
    public void run() {
        play();
    }
};

private AudioTrack createAudioPlayer(){
    int intSize = android.media.AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_OUT_STEREO,
            AudioFormat.ENCODING_PCM_16BIT);
    AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_OUT_STEREO,
            AudioFormat.ENCODING_PCM_16BIT, intSize, AudioTrack.MODE_STREAM);
    if (audioTrack == null) {
        Log.d("TCAudio", "audio track is not initialised ");
        return null;
    }

    File file = null;
    file = new File(pathAudio);

    byteData = new byte[(int) count];
    try {
        in = new FileInputStream(file);

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }

    size = (int) file.length();
    return  audioTrack;
}

private class PlayerProcess implements Runnable{

    @Override
    public void run() {
        while (bytesread < size && isPlay) {
            if (Thread.currentThread().isInterrupted()) {
                break;
            }
            try {
                ret = in.read(byteData, 0, count);
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (ret != -1) { // Write the byte array to the track
                audioPlayer.write(byteData,0, ret);
                bytesread += ret;
            } else break;
        }
        try {
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (audioPlayer!=null){
            if (audioPlayer.getState()!=AudioTrack.PLAYSTATE_STOPPED){
                audioPlayer.stop();
                audioPlayer.release();
                mThread = null;
            }
        }
        if (isLooping && isPlay ) mHandler.postDelayed(mLopingRunnable,100);
    }
}

public void setLooping(){
    isLooping = !isLooping;
}

public void pause(){

}

public void stop(){
    isPlay = false;
    if (mThread != null) {
        mThread.interrupt();
        mThread = null;
    }
    if (audioPlayer != null) {
        audioPlayer.stop();
        audioPlayer.release();
        audioPlayer = null;
    }
}

public void reset(){

}

}