Подтвердить что ты не робот

Immediate Audio Input & Output Android

В моем приложении для Android я хотел бы взять немного звука с микрофона смартфона и сразу же воспроизвести его, жить, как микрофон, без запаздывания. В настоящее время я думаю об использовании классов AudioRecord и AudioTrack (из того, что я прочитал), но я не совсем уверен, как действовать дальше.

Я проверил некоторые другие вопросы о переполнении стека, но они точно не отвечают на то, что я хотел бы сделать. И большинство из них - с 2012 года.

Итак, как я могу использовать эти классы для одновременного ввода и вывода звука?

ТАКЖЕ: Я посмотрел на MediaRecorder API, но из того, что я читал, требуется, чтобы вы сохранили звук в файле, который я не хочу делать. Может ли он быть tweeked для удовлетворения моих требований? Или мне лучше использовать AudioRecord?

Спасибо

EDIT:

Вот мой обновленный код ниже, как @Pradip Pramanick предложил:

final Thread record = new Thread(new Runnable() {
        @Override
        public void run() {
            while (!Thread.interrupted()) {
                MediaRecorder microphone = new MediaRecorder();
                microphone.setAudioSource(MediaRecorder.AudioSource.MIC);
                    microphone.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
                microphone.setOutputFile(filename);
                microphone.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
                try {
                    microphone.prepare();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                microphone.start();
            }
        }
    });

    final Thread play = new Thread(new Runnable() {
        @Override
        public void run() {
            while (!Thread.interrupted()) {
                player = new MediaPlayer();
                try {
                    player.setDataSource(filename);
                    player.prepare();
                    player.start();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    });

Я получаю Illegal State Exception | Start failed: -38. Но я называю microphone.start после microphone.prepare... Какая проблема? Я искал другие темы, в которых говорилось, что с помощью микрофона могут быть другие фоновые приложения. Я искал свое устройство: Moto X Play (3rd Gen) и не нашел ни одного. (Я даже отключил распознавание голоса "ОК Google", но ошибка продолжалась).

ОШИБКА:

Вот лог-кота, показывающий самые последние ошибки:

01-31 09:37:21.064 344-3339/? E/MediaPlayerService: offset error
01-31 09:37:21.065 1835-1922/com.synerflow.testapp E/MediaPlayer: Unable to create media player

01-31 09:37:21.065 1835-1922/com.synerflow.testapp I/Player: player.prepare() has failed
01-31 09:37:21.065 1835-1922/com.synerflow.testapp W/System.err: java.io.IOException: setDataSourceFD failed.: status=0x80000000

Исключение IO похоже на player.setDataSource(filename), переменная filename представляет собой строку: Environment.getExternalStorageDirectory().getAbsolutePath() + "\voice.3gp"

4b9b3361

Ответ 1

Насколько я могу думать, это можно сделать очень простым способом. Я не пробовал, но вы это пробовали. Я думаю, это сработает:

Создайте два потока, один для записи другого для воспроизведения. Скажем, что нитями являются TRecord и TPlay.

В методе прогона TRecord выполните следующее:

public void run(){
        MediaRecorder mRecorder = null;
        mRecorder = new MediaRecorder();
        mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        mRecorder.setOutputFile(mFileName);
        mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

        try {
            mRecorder.prepare();
        } catch (IOException e) {
            //todo
        }

        mRecorder.start();
}

И его метод запуска TPlay делает это:

public void run() {
MediaPlayer   mPlayer = null;
mPlayer = new MediaPlayer();
        try {
            mPlayer.setDataSource(mFileName);
            mPlayer.prepare();
            mPlayer.start();
        } catch (IOException e) {
            //todo
        }
}

Теперь на mainactivity просто создайте два потока. Сначала запустите поток TRecord, затем Tplay. Попробуйте.

вот код для расширения файла:

mFileName = Environment.getExternalStorageDirectory().getAbsolutePath();
 mFileName += "/audiorecordtest.3gp";

Ответ 2

На самом деле это действительно сложно на Android. У Google есть очень хороший (но немного длинный) видео, объясняющий проблемы.

Они также имеют страницу, объясняющую методы тестирования и тесты времени ожидания для различных устройств.

По сути, Android Android не может делать звук с нулевой латентностью, однако нет ничего, что мешало бы аппаратным партнерам добавлять необходимые аппаратные средства и расширения платформы для этого.

Ответ 3

попробуйте это. Я не запускал это.

      recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
      RECORDER_SAMPLERATE, RECORDER_CHANNELS,
      RECORDER_AUDIO_ENCODING, bufferSize * BytesPerElement);

    recorder.startRecording();

    isRecording = true;

    recordingThread = new Thread(new Runnable() {

     public void run() {

      try {
          int intSize = android.media.AudioTrack.getMinBufferSize(RECORDER_SAMPLERATE,AudioFormat.CHANNEL_OUT_MONO , RECORDER_AUDIO_ENCODING);
          byte[] sData = new byte[bufferSize];
          AudioTrack at = new AudioTrack(AudioManager.STREAM_MUSIC, RECORDER_SAMPLERATE, AudioFormat.CHANNEL_OUT_MONO, RECORDER_AUDIO_ENCODING, intSize, AudioTrack.MODE_STREAM);
          while(isRecording){
          recorder.read(sData, 0, bufferSize);  //isRecording = false; onStop button

          if (at!=null) { 
              at.play();
              // Write the byte array to the track
              at.write(sData, 0, sData.length); 
              at.stop();
              at.release();
          }
          }
    } catch (IOException e) {
        e.printStackTrace();
    }
 }
  }, "AudioRecorder Thread");
    recordingThread.start();