Android AudioRecord - не инициализируется 2 раза - PullRequest
13 голосов
/ 28 февраля 2011

Привет, я сейчас пытаюсь заставить AudioRecord работать. Потому что мне это нужно в большем проекте. Но, похоже, это сильно испортило. Я много чего пробовал, поэтому вернулся к основам, когда отследил эту ошибку. Я использую свой Samsung Galaxy S в качестве устройства отладки.

Моя проблема в том, что в первый раз после перезагрузки устройства я могу без проблем инициализировать созданный мной объект AudioRecord. Но при втором запуске он не инициализирует объект AudioRecord. Я пробовал несколько частот, к вашему сведению.

Вот мой код:

package android.audiorecordtest;

import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class AudioRecordTest extends Activity {

    int frequency;
    AudioRecord audRec;
    TextView txtVw;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        txtVw = (TextView) findViewById(R.id.txtVw);


        frequency=8000;
        int bufferSize=(AudioRecord.getMinBufferSize(frequency, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT))*2;
        if (bufferSize>0) {
            audRec = new AudioRecord(MediaRecorder.AudioSource.MIC, frequency, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize);
                int status = audRec.getState();
        if (status == AudioRecord.STATE_INITIALIZED) {
            txtVw.setText("Initialized" + frequency);
        } else {
            txtVw.setText("Not Initialized i=" + frequency);
        }
        }

После нескольких часов просмотра информации logcat я нашел это событие

    02-28 10:46:37.048: DEBUG/dalvikvm(4477): GC_EXPLICIT freed 1801 objects / 98944 bytes in 97ms
02-28 10:46:37.048: VERBOSE/AudioRecord(4477): stop

Что, похоже, "освобождает родную блокировку AudioRecord. Поэтому я попытался сделать переопределение finalize с моим объектом Audiorecord object.release (). Это не сработало, хотя .. Кто-нибудь есть идеи?

Ответы [ 4 ]

10 голосов
/ 13 апреля 2011

Мне удалось воспроизвести вашу проблему (на телефоне Samsung). Я добавил метод onDestroy () для освобождения записи:

@Override
public void onDestroy() { 
    super.onDestroy();
    System.out.println("OnDestroy");
    audRec.release();
}

После добавления аудиоRecord, кажется, правильно инициализируется при каждом запуске действия.

5 голосов
/ 25 июля 2011

У меня была такая же проблема, обычно audRec.release () действительно помогает, но если вам нужно остановиться и запустить несколько раз, следующий код будет более надежным. Кроме того, у меня была проблема с тем, что запись происходила в отдельном потоке, и Android иногда убивал потоки при длительной работе. Итак, взгляните на этот код, он гарантирует, что запись удерживается даже тогда, когда другой поток мертв, и после следующего audRec.start () останавливается и выпускает:

import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder; 

public class RecorderSingleton {

    private static final int FREQUENCY = 16000;

    public static RecorderSingleton instance = new RecorderSingleton();
    private AudioRecord recordInstance = null;
    private int bufferSize;

    private RecorderSingleton() {
        bufferSize = AudioRecord.getMinBufferSize(FREQUENCY, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
    }

    public boolean init() {
        recordInstance = new AudioRecord(MediaRecorder.AudioSource.MIC, FREQUENCY, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize);
        if (recordInstance.getState() == AudioRecord.STATE_UNINITIALIZED) {
            return false;
        }
        return true;
    }

    public int getBufferSize() {
        return bufferSize;
    }
    public boolean start() {
        if (recordInstance != null && recordInstance.getState() != AudioRecord.STATE_UNINITIALIZED) {
            if (recordInstance.getRecordingState() != AudioRecord.RECORDSTATE_STOPPED) {
                recordInstance.stop();
            }
            recordInstance.release();
        }
        if (!init()) {
            return false;
        }
        recordInstance.startRecording();
        return true;
    }

    public int read(short[] tempBuffer) {
        if (recordInstance == null) {
            return AudioRecord.ERROR_INVALID_OPERATION;
        }
        int ret = recordInstance.read(tempBuffer, 0, bufferSize);
        return ret;
    }

    public void stop() {
        if (recordInstance == null) {
            return;
        }
        recordInstance.stop();
        recordInstance.release();
    }
}

Тогда, если у вас есть записывающее устройство, вы можете использовать его следующим образом:

import android.media.AudioRecord;

public class Recorder implements Runnable {
    private int requiredSamples;
    private int takenSamples = 0;
    private boolean cancelled = false;

    public void run() {

        // We're important...
        android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);

        int bufferRead = 0;
        int bufferSize = RecorderSingleton.instance.getBufferSize();
        short[] tempBuffer = new short[bufferSize];
        if (!RecorderSingleton.instance.start()) {
            return;
        }
        try {
            Log.d(RoomieConstants.LOG_TAG, "Recorder Started");
            while (takenSamples < requiredSamples && !cancelled) {
                bufferRead = RecorderSingleton.instance.read(tempBuffer);
                if (bufferRead == AudioRecord.ERROR_INVALID_OPERATION) {
                    throw new IllegalStateException("read() returned AudioRecord.ERROR_INVALID_OPERATION");
                } else if (bufferRead == AudioRecord.ERROR_BAD_VALUE) {
                    throw new IllegalStateException("read() returned AudioRecord.ERROR_BAD_VALUE");
                }
                takenSamples += bufferRead;
                // do something with the samples ...
                // ...
                // ...
            }
        } finally {
            // Close resources...
            stop();
        }
    }

    public void stop() {
        RecorderSingleton.instance.stop();
    }

    public void cancel() {
        cancelled  = true;
    }
}
1 голос
/ 07 марта 2011

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

0 голосов
/ 03 марта 2011

Вы должны попытаться вызвать audRec.stop () для освобождения ресурса.

...