2016-02-11 11 views
4

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

Исходное аппаратное обеспечение Android, ускоренное AcousticEchoCanceler, похоже, не работает на большинстве устройств. Тесты, выполненные на многих устройствах, и те, которые, казалось, работали, включают Nexus 5 и Moto X, в то время как почти все тестируемые устройства Samsung не смогли удалить фоновый звук. Примечание: все проверенные телефоны возвращаются для AcousticEchoCanceler.isAvailable()

Однако, решение, так как приложения, такие как Skype или WhatsApp, похоже, отменяют звук вне контекста приложения, то есть звонок на динамике, а микрофон отменяет полученную обратную связь.

Это упрощенное приложение записи записывает звук в файл и воспроизводит его позже, когда нажата кнопка воспроизведения.

MainActivity.java

public class MainActivity extends Activity { 

Button startRec, stopRec, playBack; 
int minBufferSizeIn; 
AudioRecord audioRecord; 
short[] audioData; 
Boolean recording; 
int sampleRateInHz = 48000; 
private String TAG = "TAG"; 

/** 
* Called when the activity is first created. 
*/ 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    startRec = (Button) findViewById(R.id.startrec); 
    stopRec = (Button) findViewById(R.id.stoprec); 
    playBack = (Button) findViewById(R.id.playback); 

    startRec.setOnClickListener(startRecOnClickListener); 
    stopRec.setOnClickListener(stopRecOnClickListener); 
    playBack.setOnClickListener(playBackOnClickListener); 
    playBack.setEnabled(false); 
    startRec.setEnabled(true); 
    stopRec.setEnabled(false); 

    minBufferSizeIn = AudioRecord.getMinBufferSize(sampleRateInHz, 
      AudioFormat.CHANNEL_IN_MONO, 
      AudioFormat.ENCODING_PCM_16BIT); 

    audioData = new short[minBufferSizeIn]; 

    audioRecord = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION, 
      sampleRateInHz, 
      AudioFormat.CHANNEL_IN_MONO, 
      AudioFormat.ENCODING_PCM_16BIT, 
      minBufferSizeIn); 

} 

OnClickListener startRecOnClickListener 
     = new OnClickListener() { 

    @Override 
    public void onClick(View arg0) { 
     playBack.setEnabled(false); 
     startRec.setEnabled(false); 
     stopRec.setEnabled(true); 
     Thread recordThread = new Thread(new Runnable() { 

      @Override 
      public void run() { 
       recording = true; 
       startRecord(); 
      } 

     }); 

     recordThread.start(); 

    } 
}; 


OnClickListener stopRecOnClickListener 
     = new OnClickListener() { 

    @Override 
    public void onClick(View arg0) { 
     playBack.setEnabled(true); 
     startRec.setEnabled(false); 
     stopRec.setEnabled(false); 
     recording = false; 
    } 
}; 



OnClickListener playBackOnClickListener 
     = new OnClickListener() { 

    @Override 
    public void onClick(View v) { 
     playBack.setEnabled(false); 
     startRec.setEnabled(true); 
     stopRec.setEnabled(false); 
     playRecord(); 
    } 

}; 


@TargetApi(Build.VERSION_CODES.JELLY_BEAN) 
private void startRecord() { 
    File file = new File(Environment.getExternalStorageDirectory(), "test.pcm"); 

    try { 
     FileOutputStream outputStream = new FileOutputStream(file); 
     BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream); 
     DataOutputStream dataOutputStream = new DataOutputStream(bufferedOutputStream); 

     NoiseSuppressor ns; 
     AcousticEchoCanceler aec; 

     if (NoiseSuppressor.isAvailable()) { 
      ns = NoiseSuppressor.create(audioRecord.getAudioSessionId()); 
      if (ns != null) { 
       ns.setEnabled(true); 
      } else { 
       Log.e(TAG, "AudioInput: NoiseSuppressor is null and not enabled"); 
      } 
     } 

     if (AcousticEchoCanceler.isAvailable()) { 
      aec = AcousticEchoCanceler.create(audioRecord.getAudioSessionId()); 
      if (aec != null) { 
       aec.setEnabled(true); 
      } else { 
       Log.e(TAG, "AudioInput: AcousticEchoCanceler is null and not enabled"); 
      } 
     } 
     audioRecord.startRecording(); 

     while (recording) { 
      int numberOfShort = audioRecord.read(audioData, 0, minBufferSizeIn); 
      for (int i = 0; i < numberOfShort; i++) { 
       dataOutputStream.writeShort(audioData[i]); 
      } 
     } 

     audioRecord.stop(); 
     dataOutputStream.close(); 

    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

void playRecord() { 
    File file = new File(Environment.getExternalStorageDirectory(), "test.pcm"); 

    int shortSizeInBytes = Short.SIZE/Byte.SIZE; 

    int bufferSizeInBytes = (int) (file.length()/shortSizeInBytes); 
    short[] audioData = new short[bufferSizeInBytes]; 

    try { 
     FileInputStream inputStream = new FileInputStream(file); 
     BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream); 
     DataInputStream dataInputStream = new DataInputStream(bufferedInputStream); 

     int i = 0; 
     while (dataInputStream.available() > 0) { 
      audioData[i] = dataInputStream.readShort(); 
      i++; 
     } 

     dataInputStream.close(); 

     AudioTrack audioTrack = new AudioTrack(
       AudioManager.STREAM_MUSIC, sampleRateInHz, 
       AudioFormat.CHANNEL_OUT_MONO, 
       AudioFormat.ENCODING_PCM_16BIT, 
       bufferSizeInBytes, 
       AudioTrack.MODE_STREAM); 
     while(audioTrack.getState() != AudioTrack.STATE_INITIALIZED){ 

     } 
     audioTrack.play(); 
     audioTrack.write(audioData, 0, bufferSizeInBytes); 


    } catch (FileNotFoundException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

} 

} 

activity_main.xml

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
      android:layout_width="fill_parent" 
      android:layout_height="fill_parent" 
      android:orientation="vertical" > 

<TextView 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/hello_world" /> 
<Button 
    android:id="@+id/startrec" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="Start Recording Test" /> 
<Button 
    android:id="@+id/stoprec" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="Stop Recording" /> 
<Button 
    android:id="@+id/playback" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="Play Back" /> 

</LinearLayout> 

AndroidManfist.xml разрешения

<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/> 
    <uses-permission android:name="android.permission.RECORD_AUDIO"/> 
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 

Чтобы проверить, если устройство работает просто играть что-то в фоновом режиме, а затем нажмите Start Recording запишите небольшой сектор, а затем нажмите Stop Recording нажмите Play Back и проверьте, слышен ли фоновый звук. Если вы слышите фоновый звук, AEC не работает. Но почему это несоответствие происходит или как я могу добиться отмены эха (я уже использую WebRTC в своем приложении для отмены шума в контексте моих приложений)

Любая помощь будет оценена!

ответ

2

У меня была такая же проблема на моем устройстве S6. Я играл с различными настройками и нашел набор, который, похоже, позволяет AEC. Различия между моей и вашей установки кажутся:

  • частота дискретизации 16k
  • audioManager.setMode (AudioManager.MODE_IN_COMMUNICATION);

Для других я не уверен, какие настройки необходимы для работы AEC. Я знаю, что мое же приложение с

  • скорость 48k образца
  • NO audioManager.setMode (AudioManager.MODE_IN_COMMUNICATION);
  • NO android.permission.MODIFY_AUDIO_SETTINGS

не успешно AEC.

0

Проблема:

AudioTrack audioTrack = new AudioTrack(
    AudioManager.STREAM_MUSIC, sampleRateInHz, 
    AudioFormat.CHANNEL_OUT_MONO, 
    AudioFormat.ENCODING_PCM_16BIT, 
    bufferSizeInBytes, 
    AudioTrack.MODE_STREAM); 

должно быть:

AudioTrack audioTrack = new AudioTrack(
    AudioManager.STREAM_MUSIC, sampleRateInHz, 
    AudioFormat.CHANNEL_OUT_MONO, 
    AudioFormat.ENCODING_PCM_16BIT, 
    bufferSizeInBytes, 
    AudioTrack.MODE_STREAM 
    sessionId); // this param is important, which is audioRecord. getAudioSessionId() 

 Смежные вопросы

  • Нет связанных вопросов^_^