Android audio and video development (3) - AudioTrack plays pcm audio in two ways

foreword

I learned AudioRecord to record pcm audio before, and the corresponding one is AudioTrack to play pcm audio (MediaPlayer, SoundPool has other application scenarios), it has two data loading modes (MODE_STATIC, MODE_STREAM).

model

  • MODE_STATIC : In this mode, all data is put into a fixed buffer at one time, and then written into AudioTrack, and there is no need to continue writing later. This mode occupies less memory and is suitable for short audio, such as mobile phone ringtones and system prompts.

  • MODE_STREAM : This mode will continue to write audio data into AudioTrack, and the write action will be blocked until the data stream is transmitted from the java layer to the native layer, which is suitable for large files or files with a long playback time.

STATIC mode process

1. Start another thread to write the audio file into a fixed buffer.

2. After the writing is completed, initialize AudioTrack (the parameters are described in detail in the previous section), receive the buffer and play it.

    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 mode process

1. Initialize AudioTrack.

2. Start another thread, and play while writing the audio stream file.

3. When playback ends, close the stream.

    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();
    }

epilogue

In fact, the bottom layer of MediaPlayer also uses AudioTrack, but it is more comprehensively packaged and can support multiple formats of sound, such as MP3, AAC, WAV, OGG, etc., but it cannot directly play pcm files. We use AudioTrack, which controls and plays the audio data for each frame, closer to the bottom layer.

References for this blog:

Gray floating blog garden

Friends who need source code can also visit my gitub, source code

Guess you like

Origin blog.csdn.net/m0_57372054/article/details/127200636