2016-01-18 5 views
1

Я пытаюсь записывать аудио в android и хранить его в массиве байтов, и для этого я использую встроенный класс Android AudioRecord.
Я уже использовал этот класс раньше, и все было хорошо, но по какой-то причине кажется, что AudioRecord больше не будет работать.Ошибка Android AudioRecord при вызове метода startRecording()

Проблема заключается в том, что AudioRecord инициализируется и не отображает ошибок, но когда пришло время фактически записать что-либо, вызывая его метод startRecording(), что-то не работает, и я даже не получил правильную причину.

Это ALL выход из LogCat после вызова этого метода:

01-18 18:54:49.545 11303-11338/com.mypackage E/android.media.AudioRecord﹕ MediaRecorder prepare CallingPid = 11303 Callinguid= 10128 

01-18 18:54:49.545 11303-11338/com.mypackage E/android.media.AudioRecord﹕ java.lang.Throwable 
     at android.media.AudioRecord.startRecording(AudioRecord.java:631) 
     at mypackage.AudioRecorder.record(AudioRecorder.java:179) 

Конечно звук не получает записывается после того, для тех, кому интересно, если это просто внутреннее сообщение об ошибке.

Это код инициализации класса AudioRecord:

int bufferSize = AudioRecord.getMinBufferSize(AUDIO_SAMPLE_RATE, RECORDER_CHANNEL, RECORDER_AUDIO_ENCODING); 

     if (bufferSize != AudioRecord.ERROR_BAD_VALUE && bufferSize > 0) 
     { 
      // check if we can instantiate and have a success 
      AudioRecord recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, AUDIO_SAMPLE_RATE, RECORDER_CHANNEL, 
        RECORDER_AUDIO_ENCODING, bufferSize); 

      if (recorder.getState() == AudioRecord.STATE_INITIALIZED) 
      { 
       m_Recorder = recorder; 
       m_RecordingThread = Executors.newSingleThreadExecutor(); 
       m_IsInitialized = true; 
       return; 
      } 
     } 

Когда константы, которые используются:

/** 
* Recorded audio's sample rate. 
*/ 
private static final int AUDIO_SAMPLE_RATE = 44100; 

/** 
* Recorded audio's channel. 
*/ 
private static final int RECORDER_CHANNEL = AudioFormat.CHANNEL_IN_MONO; 

/** 
* Recorded audio's encoding. 
*/ 
private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT; 

Ошибка происходит здесь:

if (m_Recorder != null) 
      m_Recorder.startRecording(); 

So увидев это несколько раз, я решил пойти глубже и попытаться отладить его, как можно глубже, чтобы источник ошибки в самом классе AudioRecord, используя декомпилятор Jetbrain.
По какой-то странной причине, как только приложение попало в точку останова, расположенную в источнике ошибки, следующий шаг не может быть завершен, так как AudioRecord снова разбился с тем же сообщением об ошибке.

Следующий шаг для меня - создать образец проекта, чтобы проверить функциональность AudioRecord, но на этот раз я добавил AudioTrack, который выведет все мои записи мгновенно (своего рода loopback), если класс AudioRecord удается записать что-либо с ошибкой или без нее.
И так случилось волшебство - приложение работает, AudioRecord записывает и проигрывает AudioTrack.
Мне показалось странным, что класс AudioTrack внезапно решил все мои проблемы, поэтому я удалил его из своего кода и снова попытался запустить приложение.
На этот раз AudioRecord работал без проблем, и хотя я не мог слышать его «вывод», могу заверить, что он записывал.

С некоторым облегчением я подумал, что я, наконец, преодолел эту проблему, и я готов двигаться вперед, поэтому я добавил дополнительный код для кодирования и декодирования записанных аудиоданных.
Чтобы услышать вывод, я вернул код, используя класс AudioTrack, и запустил приложение.

Хотите услышать смешную вещь? Приложение разбилось с той же ошибкой, СНОВА.

В настоящее время теоретически проблема может не освобождать экземпляр AudioRecord, когда он был выполнен с его использованием, но я тоже с самого начала рассмотрел это.

Я попытался найти практически всюду в Интернете для решения, но кажется, что никто раньше даже не сталкивался с такой проблемой.

Кроме того, я хотел бы указать, что я попытался сбросить свое устройство, плагин ADB и перестроить все проекты.

Я пользуюсь телефоном Meizu MX5 с Android Lollipop (API 21).

+0

Покажите нам код ... – TDG

+0

@TDG Спасибо за отметив, я добавил соответствующие части кода в настоящее время. –

+0

Пожалуйста, добавьте еще несколько кодов. Я думаю, что вы объявляете и определяете объект 'AudioRecord' в' if {} ', и поэтому его область действия ограничена только {}. , а также я не могу видеть 'm_Recorder.startRecording();' находится в каком блоке. Еще одна вещь: отправить полную статистику стека, это из-за 'AudioRecord' не инициализируется или' IllegalStateException'? – kAmol

ответ

1

Ну, я решил проблему или, по крайней мере, ее часть, заставив ее работать сейчас. Дело в том, что я пытался читать больше байтов, чем размер моего предварительно выделенного буфера, вызывая метод read() класса AudioRecord.
Хотя это не решило главную проблему этого сообщения, это странное сообщение об ошибке и неперехваченное исключение, это сделало AudioRecord отлично, поэтому для меня этот поток можно рассматривать как ответ и закрыт!

0

Полный код

import java.io.IOException; 
import java.net.DatagramPacket; 
import java.net.DatagramSocket; 
import java.net.InetAddress; 
import java.net.UnknownHostException; 
//import com.rdt.facerecord.R; 
import android.app.Activity; 
import android.media.AudioFormat; 
import android.media.AudioRecord; 
import android.media.MediaRecorder; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.Button; 
import android.widget.TextView; 

public class StreamD extends Activity { 
private Button startButton,stopButton; 

public byte[] buffer; 
public static DatagramSocket socket; 
private int port=8089; 

AudioRecord recorder; 

private int sampleRate = 16000 ; // 44100 for music 
private int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;  
private int audioFormat = AudioFormat.ENCODING_PCM_16BIT;  
int minBufSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig,  audioFormat); 
private boolean status = true; 

TextView prompt; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
super.onCreate(savedInstanceState); 
setContentView(R.layout.stream); 

prompt = (TextView)findViewById(R.id.textView1); 

startButton = (Button) findViewById (R.id.start_bbb); 
stopButton = (Button) findViewById (R.id.stop_bbb); 

startButton.setOnClickListener (startListener); 
stopButton.setOnClickListener (stopListener); 

} 

private final OnClickListener stopListener = new OnClickListener() { 

@Override 
public void onClick(View arg0) { 
      status = false; 
      recorder.release(); 

      System.out.println("Recorder released"); 
} 

}; 

private final OnClickListener startListener = new OnClickListener() { 

@Override 
public void onClick(View arg0) { 
      status = true; 
      startStreaming();   
} 

}; 

public void startStreaming() { 


Thread streamThread = new Thread(new Runnable() { 

    @Override 
    public void run() { 
     try { 

      DatagramSocket socket = new DatagramSocket(); 

      System.out.println("Socket Created"); 

      byte[] buffer = new byte[minBufSize]; 

      System.out.println("Buffer created of size " + minBufSize); 

      DatagramPacket packet; 

      final InetAddress destination =  InetAddress.getByName("218.000.000.000"); 

      System.out.println("Address retrieved"); 


      recorder = new    AudioRecord(MediaRecorder.AudioSource.MIC,sampleRate,channelConfig,audioFormat,m inBufSize*10); 
      System.out.println("Recorder initialized"); 

      recorder.startRecording(); 


      while(status == true) { 


       //reading data from MIC into buffer 
       minBufSize = recorder.read(buffer, 0, buffer.length); 

       //putting buffer in the packet 
       packet = new DatagramPacket (buffer,buffer.length,destination,port); 

       socket.send(packet); 
       System.out.println("MinBufferSize: " +minBufSize); 

      } 



     } catch(UnknownHostException e) { 
      System.out.println("UnknownHostException"); 
     } catch (IOException e) { 
      e.printStackTrace(); 
      System.out.println("IOException"); 
     } 
    } 

}); 
streamThread.start(); 
} 
} 

и добавить разрешение

<uses-permission android:name="android.permission.INTERNET" /> 
<uses-permission android:name="android.permission.RECORD_AUDIO" /> 
Смежные вопросы