質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.96%

Android AudioRecordの正しい初期化方法

受付中

回答 0

投稿

  • 評価
  • クリップ 0
  • VIEW 3,017

ArksNoble

score 6

実現したいこと

お世話になっております。

私は今、Android端末のマイクを使ってリアルタイムな処理を行うアプリケーションを作成しております(音の大きさを逐次表示など)。

最初に試したこと

AudioRecordを使って実装しようとした所、以下のコードにおいてエラーが発生しました。

public static final String TAG = "DEBUG_TAG";

final int SAMPLING_RATE = 44100;
AudioRecord audioRecord;
int bufferSize;

bufferSize = android.media.AudioRecord.getMinBufferSize(
                SAMPLING_RATE, AudioFormat.CHANNEL_IN_MONO,AudioFormat.ENCODING_PCM_16BIT);

audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,SAMPLING_RATE,
                AudioFormat.CHANNEL_IN_MONO,AudioFormat.ENCODING_PCM_16BIT,bufferSize*2);

audioRecord.startRecording();  //ここでエラー

エラーメッセージ

E/AudioRecord﹕ AudioFlinger could not create record track, status: -1
E/AudioRecord-JNI﹕ Error creating AudioRecord instance: initialization check failed with status -1.
E/android.media.AudioRecord﹕ Error code -20 when initializing native AudioRecord object.
W/System.err﹕ java.lang.IllegalStateException: startRecording() called on an uninitialized AudioRecord.
.
.
.

コンストラクタをいろいろ変えてみた

いろいろなサイトで調べると「機種やバージョンによって設定できるパラメータが異なる」という情報があるようです。しかし、いろいろなパターンを試してみるソースに変更した所、全てのパターンで初期化失敗になってしまいました。以下がそのときのソースコードです。
参考:stackoverflow AudioRecord object not initializing

ソースコード

AndroidManifest.xml

<uses-permission android:name="ANDROID.PERMISSION.RECORD_AUDIO"/>


MainActivity.java

public class MainActivity extends Activity{
    private AudioRecord audioRecord;
    private boolean isRecording = false;
    private int bufferSize;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    protected void onResume() {
        super.onResume();
        startRecord();
    }

    @Override
    protected void onPause() {
        super.onPause();
        stopRecord();
    }

    private void startRecord(){
        audioRecord = getAudioRecord();
        if(audioRecord == null)
            Log.i(TAG,"audioRecordはnullです");
        else {
            audioRecord.startRecording();
            isRecording = true;
            new Thread(new recordRunnable()).start();
        }

    }

    public void stopRecord(){
        isRecording = false;
    }

    private AudioRecord getAudioRecord(){
        for(int rate:new int[]{8000, 11025, 16000, 22050, 44100}){
            for(short audioFormat:new short[]{AudioFormat.ENCODING_PCM_8BIT,AudioFormat.ENCODING_PCM_16BIT}){
                for(short channelConfig : new short[]{AudioFormat.CHANNEL_IN_MONO,AudioFormat.CHANNEL_IN_STEREO}){
                    try{
                        Log.i(TAG,"Attempting rate:"+rate+"Hz ,bits:"+audioFormat+",channel:"+channelConfig);
                        int buffSize = AudioRecord.getMinBufferSize(rate,channelConfig,audioFormat);
                        if(buffSize != AudioRecord.ERROR_BAD_VALUE){
                            AudioRecord recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,rate,channelConfig,audioFormat,buffSize);

                            if(recorder.getState() == AudioRecord.STATE_INITIALIZED){
                                bufferSize = buffSize;
                                return recorder;
                            }
                        }
                    }catch (Exception e){
                        Log.i(TAG,"Exception,keep trying.",e);
                    }
                }
            }
        }
        return null;
    }

    private class recordRunnable implements Runnable{
        @Override
        public void run() {
            short shortBuffer[] = new short[bufferSize];
            while (isRecording){
                audioRecord.read(shortBuffer, 0, shortBuffer.length);
                //リアルタイムな処理など

            }

            audioRecord.stop();
            audioRecord.release();
        }
    }



}

実行結果

I/DEBUG_TAG﹕ audioRecordはnullです

実行環境

Androidバージョン:Android 5.1.1
実行端末:Xperia Z3
AndroidStudioバージョン:1.3.1

質問

audioRecord.getState()がAudioRecord.STATE_INITIALIZEDとなり、
audioRecord.startRecording()を実行可能な状態にするにはどのように初期化すれば良いのかを教えて下さい。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

まだ回答がついていません

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.96%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る