2011-11-16 27 views
2

私は、VoIPアプリケーション用にいくつかのアコースティックエコーキャンセル実験を行っています。私がやろうとしていることは簡単です:前に音を録音しました。今私はそのサウンドを再生し、再生中に、別のサウンドを録音します。これは、全二重VoIPシナリオの実際のケースです。私はサウンドを再生するためにMedaiPlayerを使用し、新しいサウンドを録音するためにMediaRecorderを使用します。以下はAndroid SoundRecorder Sampleから変更されたクラスの完全なコードです。重要な点は、 です。mPlayer.setAudioStreamType(AudioManager.MODE_IN_COMMUNICATION); Android版docsでは、「通信中の音声モードで、音声/ビデオチャットまたはVoIP通話が確立されました」と表示されます。および mRecorder.setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION); for Androidのドキュメントでは、「VoIPなどの音声通信用に調整されたマイクロフォンのオーディオソースです。利用可能な場合は、エコーキャンセレーションまたは自動ゲインコントロールを利用します」などの音声処理が適用されていない場合はDEFAULTのように動作します。これはとても有望です。 しかし、私はスピーカーから出てくるものを再生すると、私はほとんど何も奇妙な騒音だけを記録します。私はここでは新しいユーザーであるので、私は録音の音波を添付することはできませんが、最初のものは通常の音の波がある通常の録音です。 2番目のレコーディングは、ほとんど何も含まれていない最初のものを再生しながらの録音です。スピーカーに何か活動がある場合、Androidはマイクをオフにするようです。私はMediaRecorderとMediaPlayerには異なる可能性を試しましたが、使用はありません。 Androidでアコースティックエコーキャンセルを実装する正しい方法は何ですか?私はSony Tablet Sで試してAndroid 3.0 SDKを使って開発しました。 ありがとうございます。私はMediaRecorderとMediaPlayerのパラメータを変更 : Android AECは役に立たない音を発生しません

package com.kadir.sample; 
import android.app.Activity; 
import android.widget.LinearLayout; 
import android.widget.Toast; 
import android.os.Bundle; 
import android.os.Environment; 
import android.view.ViewGroup; 
import android.widget.Button; 
import android.view.View; 
import android.content.Context; 
import android.util.Log; 
import android.media.AudioManager; 
import android.media.MediaRecorder; 
import android.media.MediaPlayer; 

import java.io.IOException; 


public class AudioRecordTest extends Activity 
{ 
    private static final String LOG_TAG = "AudioRecordTest"; 
    private static String mFileName = null; 
    private static String mFileNameConst = null; 

    private RecordButton mRecordButton = null; 
    private MediaRecorder mRecorder = null; 

    private PlayButton mPlayButton = null; 
    private MediaPlayer mPlayer = null; 
    private PlayConstButton mPlayConstButton = null; 

    private void onRecord(boolean start) { 
     if (start) { 
      startRecording(); 
     } else { 
      stopRecording(); 
     } 
    } 

    private void onPlay(boolean start) { 
     if (start) { 
      startPlaying(); 
     } else { 
      stopPlaying(); 
     } 
    } 

    private void onPlayConst(boolean start) { 
     if (start) { 
      startConstPlaying(); 
     } else { 
      stopConstPlaying(); 
     } 
    } 

    private void startPlaying() { 
     mPlayer = new MediaPlayer(); 
     try { 
      mPlayer.setDataSource(mFileName); 
      mPlayer.prepare(); 
      mPlayer.start(); 
     } catch (IOException e) { 
      Toast.makeText(this, "prepare() failed", Toast.LENGTH_LONG).show(); 
      Log.e(LOG_TAG, "prepare() failed"); 
     } 
    } 

    private void stopPlaying() { 
     mPlayer.release(); 
     mPlayer = null; 
    } 

    private void startConstPlaying() { 
     mPlayer = new MediaPlayer(); 
     try { 
      mPlayer.setDataSource(mFileNameConst); 
      mPlayer.setAudioStreamType(AudioManager.MODE_IN_COMMUNICATION); 
      mPlayer.prepare(); 
      mPlayer.start(); 
     } catch (IOException e) { 
      Toast.makeText(this, "prepare() failed", Toast.LENGTH_LONG).show(); 
      Log.e(LOG_TAG, "prepare() failed"); 
    } 
} 

private void stopConstPlaying() { 
     mPlayer.release(); 
     mPlayer = null; 
    } 

    private void startRecording() { 
     mRecorder = new MediaRecorder(); 
     mRecorder.setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION); 
     mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); 
     mRecorder.setOutputFile(mFileName); 
     mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); 

     try { 
      mRecorder.prepare(); 
     } catch (IOException e) { 
      Toast.makeText(this, "startRecording() failed", Toast.LENGTH_LONG).show(); 
      Log.e(LOG_TAG, "prepare() failed"); 
     } 

     mRecorder.start(); 
    } 

    private void stopRecording() { 
     mRecorder.stop(); 
     mRecorder.release(); 
     mRecorder = null; 
    } 

    class RecordButton extends Button { 
     boolean mStartRecording = true; 

     OnClickListener clicker = new OnClickListener() { 
      public void onClick(View v) { 
       onRecord(mStartRecording); 
       if (mStartRecording) { 
        setText("Stop recording"); 
       } else { 
        setText("Start recording"); 
       } 
       mStartRecording = !mStartRecording; 
      } 
     }; 

     public RecordButton(Context ctx) { 
      super(ctx); 
      setText("Start recording"); 
      setOnClickListener(clicker); 
     } 
    } 

    class PlayButton extends Button { 
     boolean mStartPlaying = true; 

     OnClickListener clicker = new OnClickListener() { 
      public void onClick(View v) { 
       onPlay(mStartPlaying); 
       if (mStartPlaying) { 
        setText("Stop playing"); 
       } else { 
        setText("Start playing"); 
       } 
       mStartPlaying = !mStartPlaying; 
      } 
     }; 

     public PlayButton(Context ctx) { 
      super(ctx); 
      setText("Start playing"); 
      setOnClickListener(clicker); 
     } 
    } 

    class PlayConstButton extends Button { 
     boolean mStartPlaying = true; 

     OnClickListener clicker = new OnClickListener() { 
      public void onClick(View v) { 
       onPlayConst(mStartPlaying); 
       if (mStartPlaying) { 
        setText("Stop Constant playing"); 
       } else { 
        setText("Start Constant playing"); 
       } 
       mStartPlaying = !mStartPlaying; 
      } 
     }; 

     public PlayConstButton(Context ctx) { 
      super(ctx); 
      setText("Start Constant playing"); 
      setOnClickListener(clicker); 
     } 
    } 

    public AudioRecordTest() { 
     mFileName = Environment.getExternalStorageDirectory().getAbsolutePath(); 
     mFileName += "/audiorecordtest.3gp"; 
     mFileNameConst = Environment.getExternalStorageDirectory().getAbsolutePath(); 
     mFileNameConst += "/constant.3gp"; 
    } 

    @Override 
    public void onCreate(Bundle icicle) { 
     super.onCreate(icicle); 

     LinearLayout ll = new LinearLayout(this); 
     mRecordButton = new RecordButton(this); 
     ll.addView(mRecordButton, 
      new LinearLayout.LayoutParams(
       ViewGroup.LayoutParams.WRAP_CONTENT, 
       ViewGroup.LayoutParams.WRAP_CONTENT, 
       0)); 
     mPlayButton = new PlayButton(this); 
     ll.addView(mPlayButton, 
      new LinearLayout.LayoutParams(
       ViewGroup.LayoutParams.WRAP_CONTENT, 
       ViewGroup.LayoutParams.WRAP_CONTENT, 
       0)); 
     mPlayConstButton = new PlayConstButton(this); 
     ll.addView(mPlayConstButton, 
      new LinearLayout.LayoutParams(
       ViewGroup.LayoutParams.WRAP_CONTENT, 
       ViewGroup.LayoutParams.WRAP_CONTENT, 
       0)); 
     setContentView(ll); 
    } 

    @Override 
    public void onPause() { 
     super.onPause(); 
     if (mRecorder != null) { 
      mRecorder.release(); 
      mRecorder = null; 
     } 

     if (mPlayer != null) { 
      mPlayer.release(); 
      mPlayer = null; 
     } 
    } 
} 

UPDATE

次のように は、私は少しR & Dを持っていました。それぞれの価値について、私は自分自身を記録し、レコーディング中は別のプレイを開始しました。録音を終え、今録音したものを聴いた。 MediaRecorder.AudioSource.DEFAULT、MediaRecorder.AudioSource.MIC、MediaRecorder.AudioSource.VOICE_CALL、MediaRecorder.AudioSource.VOICE_COMMUNICATION、MediaRecorder.AudioSource.VOICE_DOWNLINK、MediaRecorder.AudioSource.VOICE_RECOGNITION、MediaRecorder.AudioSource.VOICE_UPLINK:MediaRecorderのために、私はこれらの値を試してみました MediaPlayerの場合、これらの値を試しました。 AudioManager.MODE_NORMAL、AudioManager.MODE_CURRENT、AudioManager.MODE_IN_CALL、AudioManager.MODE_IN_COMMUNICATION、 AudioManager.STREAM_VOICE_CALL、AudioManager.STREAM_MUSIC。 私が何を試しても、私はいつも静寂か純粋な騒音のいずれかを持っていました。私は、MediaRecorderクラスとMediaPlayerクラスではVoIPには不十分だと思います。そして、Androidのサウンドシステムは、私のような初心者のために少し奇妙です。

+0

mPlayer.setAudioStreamType(AudioManager.MODE_IN_COMMUNICATION);を設定しています。これは、その呼び出しの正しいパラメータ値ではありません。 STREAM_定数を使用してください。 –

答えて

2

部分的にわかりました。私はAndroid 3.2でSony Tablet Sを使用していました。 Android 2.3搭載のArchos 70で同じプログラムを試しました。別のものを演奏しながら何かを録音すると、両方の音が録音されます。つまり、私はAECを適用する音があることを意味します。ソニーでは、録音は騒音だけだった。ソニータブレットSには、マイクの実装に問題があります(ところで、GTalkはソニーで完璧に動作しますが、Androidに実装されているような特別なものかもしれません)。あるいは、Android 3.2はマイクの実装に問題があります。

+2

私はソニーサポートに連絡してみました。彼らは私のケースを閉鎖することだけに気をつけます。彼らは答えました: "GTalkは正常に動作しているので、誤動作しているアプリケーションの開発者に連絡してください"。私は誤動作するアプリケーションの開発者です!ソニーと十分に対処していると思います。 –

+0

この情報をお寄せいただきありがとうございます。 – Jim

0

多くの場合、Androidのエコーキャンセレーションはあまりうまく機能しません。私は長いエコーテールに関連していると思う。私は、この問題のサードパーティのアルゴリズムがあることを知っています。 Googleのエコーキャンセレーションソフトウェアで、長いエコーテールをサポートしていることを確認してください。

+0

ありがとうございます。しかし、あなたの説明は私の質問には関係ないと思います。私の本当の問題は、元の投稿に記載されているように、何かがスピーカーから出ると、Androidはマイクのゲインを落とします。マイクからは何も来ません。私はそれが機能の場合、この機能を無効にする方法を尋ねています。マイクを管理しているMediaRecorder以外のクラスがあるかもしれません。私のコードにはAECを適用するサウンドがないため、AECについては何も含まれていません。 –

+0

説明をありがとう。私はVOICE_COMMUNICATIONではなく、別の定数でレコーディングを開くことを提案します。 VOICE_COMMUNICATIONは、あなたを邪魔している可能性があるすべてのVoIP機能をアクティブにします。おかげさまで – Jim

+0

他のパラメータを試して結果を報告します。 –

0

なぜストリーミングアプリケーションにMediaRecorderを使用しますか?代わりにAudioRecorderを使用してください。

私は現在、同様の使用例で再生しており、AudioRecorderは問題なく動作します。

+0

Neeraj>この問題に関するご意見はありますか? http://stackoverflow.com/questions/33062660/android-what-audio-mode-should-be-set-to-send-receive-voice- between-devices – Jasper

関連する問題