Как зациклить аудио с AudioTrack? - PullRequest
0 голосов
/ 02 июля 2019

У меня есть программа, которая записывает файл 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 в цикле?

1 Ответ

0 голосов
/ 02 июля 2019

Я вижу, что вы вызываете функцию main.audioStopped из вашего MainActivity, который уведомляет, что носитель прекратил воспроизведение, я полагаю.Вы можете легко справиться с повторением в этой функции audioStopped вашего MainActivity.

Я изменил класс AudioManager следующим образом.Который принимает context и fileName аудио, которое требуется для воспроизведения в конструкторе.Это поможет вам создать экземпляр AudioManager из вашего MainActivity, и, следовательно, вы можете начать аудио заново, когда воспроизведение закончится.

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

Надеюсь, это поможет!

...