安卓音视频开发(3)—— AudioTrack两种方式播放pcm音频

前言

之前学习了AudioRecord录制pcm音频,与之对应的就是AudioTrack播放pcm音频(MediaPlayer、SoundPool有其他应用场景),它有两种数据加载模式(MODE_STATIC、MODE_STREAM)。

模式

  • MODE_STATIC:这种模式下,一次将所有的数据放入一个固定的buffer,然后写入到AudioTrack中,后续就不用继续write了。这种模式占用的内存较小,适用于短小的音频,例如手机铃声和系统提示音等。

  • MODE_STREAM:这种模式会持续的把音频数据写入AudioTrack中,write动作将堵塞直到数据流从java层传输到native层,适用于大文件或者播放时间较长的文件。

STATIC模式流程

1.另起线程,将音频文件写入固定buffer。

2.写入完成后,初始化AudioTrack(参数在上一节有详细介绍),接收buffer并播放(play)。

    public void initStatic() {
    
    
        if (staticThread != null) {
    
    
            staticThread.interrupt();
        }
        staticThread = new Thread(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                FileInputStream fileInputStream = null;
                try {
    
    
                    File file = new File(filePath);
                    fileInputStream = new FileInputStream(file);
                    long size = fileInputStream.getChannel().size();

                    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(audiodata.length);
                    int byteValue = 0;
                    long startTime = System.currentTimeMillis();
                    while ((byteValue = fileInputStream.read()) != -1) {
    
    
                        byteArrayOutputStream.write(byteValue);
                    }
                    LogUtils.i("初始化完成" + (System.currentTimeMillis() - startTime));
                    audiodata = byteArrayOutputStream.toByteArray();

                    audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 8000, AudioFormat.CHANNEL_OUT_MONO,
                            AudioFormat.ENCODING_PCM_16BIT, audiodata.length, AudioTrack.MODE_STATIC);
                    audioTrack.write(audiodata, 0, audiodata.length);
                    audioTrack.play();
                    LogUtils.i("Static播放");

                } catch (Exception e) {
    
    
                    e.printStackTrace();
                    LogUtils.e(e);
                } finally {
    
    
                    if (fileInputStream != null) {
    
    
                        try {
    
    
                            fileInputStream.close();
                        } catch (IOException e) {
    
    
                            e.printStackTrace();
                        }
                    }
                }
            }
        });
        staticThread.start();
    }

STREAM模式流程

1.初始化AudioTrack。

2.另起线程,一边写入音频流文件,一边播放。

3.播放结束,关闭流。

    public void startStream() {
    
    
        if (streamThread != null) {
    
    
            streamThread.interrupt();
        }
        if (audioTrack != null) {
    
    
            audioTrack = null;
        }
        audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 8000, AudioFormat.CHANNEL_OUT_MONO,
                AudioFormat.ENCODING_PCM_16BIT, 1600, AudioTrack.MODE_STREAM);
        streamThread = new Thread(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                FileInputStream fileInputStream = null;
                File file = new File(filePath);
                try {
    
    
                    audioTrack.play();
                    fileInputStream = new FileInputStream(file);
                    int byteValue = 0;
                    while ((byteValue = fileInputStream.read(audiodata)) != -1) {
    
    
                        audioTrack.write(audiodata, 0, byteValue);
                    }
                } catch (Exception e) {
    
    
                    e.printStackTrace();
                    LogUtils.e(e);
                } finally {
    
    
                    if (audioTrack != null) {
    
    
                        audioTrack.stop();
                        audioTrack = null;
                    }
                    if (fileInputStream != null) {
    
    
                        try {
    
    
                            fileInputStream.close();
                        } catch (IOException e) {
    
    
                            e.printStackTrace();
                        }
                    }
                }
            }
        });
        streamThread.start();
    }

结语

其实MediaPlayer底层同样使用了AudioTrack,但它封装得比较全面,能支持多种格式得声音,如MP3,AAC,WAV,OGG等,但是无法直接播放pcm文件。我们使用AudioTrack,它能控制和播放每一帧的音频数据,更接近底层。

本期博客参考:

灰色飘零博客园

需要源码的盆友也可以访问我的gitlub,源码

猜你喜欢

转载自blog.csdn.net/m0_57372054/article/details/127200636