首页 > 解决方案 > 如何使用 AudioTrack 循环播放音频?

问题描述

我有一个记录 pcm 文件并保存它的程序。该文件的路径存储在一个名为pcmFile. 我想更改此代码,以便它在无缝循环中播放 PCM 文件,直到线程停止(通过更改isPlaying为 false)。

我有这样的AudioManager课:

public class AudioManager  {
   static final String TAG = "AudioRecorder";

   boolean isPlaying = false;
   static final int frequency = 16000;
   private static final String AUDIO_RECORDER_FOLDER = "4TRACK";
   static final int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
   static final int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
   int playBufSize;

   AudioTrack audioTrack;

   String filename;
   File pcmFile;

   public AudioManager() {    
        playBufSize=AudioTrack.getMinBufferSize(frequency,
                channelConfiguration, audioEncoding);

        audioTrack = new AudioTrack(android.media.AudioManager.STREAM_MUSIC, frequency,
                channelConfiguration, audioEncoding,
                playBufSize, AudioTrack.MODE_STREAM);

        audioTrack.setStereoVolume(0.7f, 0.7f);
    }

    public void startPlaying() {
        isPlaying = true;
        new PlayThread().start();
    }

    public void stopPlaying() {
        isPlaying = false;
    }

    private String getFilename(){
        String filepath = Environment.getExternalStorageDirectory().getPath();
        File file = new File(filepath,AUDIO_RECORDER_FOLDER);

        return (file.getAbsolutePath() + "/" + filename + ".pcm");
    }

    class PlayThread extends Thread {
        public void run() {
            try {
                System.out.println("~~Playing audio");
                byte[] buffer = new byte[playBufSize];
                BufferedInputStream bis = new BufferedInputStream(new FileInputStream(pcmFile), playBufSize);

                audioTrack.play();

                int readSize = -1;
                while (isPlaying && (readSize = bis.read(buffer)) != -1) {
                    audioTrack.write(buffer, 0, readSize);
                }
                audioTrack.stop();
                MainActivity main = (MainActivity) ctx;
                main.audioStopped();
                System.out.println("~~No longer playing");
                bis.close();
            } catch (Throwable t) {
                t.printStackTrace();
            }
        }
    }
}

这里的重要部分是PlayThread类。现在它可以完美地播放 pcm 文件。如何调整此代码以便循环播放 PCM 文件?

标签: javaandroidaudiotrack

解决方案


我可以看到您正在main.audioStopped从您的函数调用MainActivity通知媒体已停止播放的函数。audioStopped您可以轻松处理MainActivity.

我已将AudioManager课程修改如下。其中需要在构造函数中播放的音频的context和。这可以帮助您从您fileName的实例中创建实例,因此,您可以在音频播放完毕后重新开始音频。AudioManagerMainActivity

public class AudioManager {
    static final String TAG = "AudioRecorder";

    Context ctx;
    public static boolean isPlaying = false;
    static final int frequency = 16000;
    private static final String AUDIO_RECORDER_FOLDER = "4TRACK";
    static final int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
    static final int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
    int playBufSize;

    AudioTrack audioTrack;

    String filename;
    File pcmFile;

    public AudioManager(Context ctx, String fileName) {
        this.ctx = ctx;
        this.filename = fileName;

        playBufSize = AudioTrack.getMinBufferSize(frequency,
                channelConfiguration, audioEncoding);

        audioTrack = new AudioTrack(android.media.AudioManager.STREAM_MUSIC, frequency,
                channelConfiguration, audioEncoding,
                playBufSize, AudioTrack.MODE_STREAM);

        audioTrack.setStereoVolume(0.7f, 0.7f);
        startPlaying();
    }

    public void startPlaying() {
        isPlaying = true;
        new PlayThread().start();
    }

    private String getFilename() {
        String filepath = Environment.getExternalStorageDirectory().getPath();
        File file = new File(filepath, AUDIO_RECORDER_FOLDER);

        return file.getAbsolutePath() + "/" + filename + ".pcm";
    }

    class PlayThread extends Thread {
        public void run() {
            try {
                System.out.println("~~Playing audio");
                byte[] buffer = new byte[playBufSize];
                BufferedInputStream bis = new BufferedInputStream(new FileInputStream(getFilename()), playBufSize);

                audioTrack.play();

                int readSize = -1;
                while (isPlaying && (readSize = bis.read(buffer)) != -1) {
                    audioTrack.write(buffer, 0, readSize);
                }
                audioTrack.stop();

                MainActivity main = (MainActivity) ctx;
                main.audioStopped();
                System.out.println("~~No longer playing");
                bis.close();
            } catch (Throwable t) {
                t.printStackTrace();
            }
        }
    }
}

并从中MainActivity,检查第一个的值isPlaying并在找到时重复启动线程true

public void audioStopped() {
    if (AudioManager.isPlaying) {
        AudioManager am = new AudioManager(this, pcmFileName);
    } else {
        // Do something else
    }
}

希望有帮助!


推荐阅读