Я создаю приложение, которое требует от микрофона отменить звук, поступающий из динамика. Похоже, что этот вопрос является почти заговором в режиме онлайн, поскольку другие с той же проблемой никогда не реагировали на длительную продолжительность.Андроид 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 в своем приложении для отмены шума в контексте моих приложений)
Любая помощь будет оценена!