【问题标题】:How to loop audio with AudioTrack?如何使用 AudioTrack 循环播放音频?
【发布时间】:2019-07-02 00:45:06
【问题描述】:

我有一个记录 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 文件?

【问题讨论】:

    标签: java android audiotrack


    【解决方案1】:

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

    我已将AudioManager 类修改如下。其中需要在构造函数中播放的音频的contextfileName。这有助于您从MainActivity 创建AudioManager 的实例,因此,当音频播放完毕后,您可以重新开始音频。

    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
        }
    }
    

    希望有帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-10
      • 2020-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-18
      • 1970-01-01
      相关资源
      最近更新 更多