Android AudioRecord - Won't Initialize 2nd time

前端 未结 5 1691
刺人心
刺人心 2020-12-31 08:52

Hej, im currently trying to get AudioRecord to work. Because I need it in a bigger project. But it seems to mess up a lot. I have been trying alot of things, so I went back

相关标签:
5条回答
  • 2020-12-31 08:55

    My AudioRecord didn't initialize because it was static

    0 讨论(0)
  • You should try to call audRec.stop() to release the resource.

    0 讨论(0)
  • 2020-12-31 09:09

    I had the same problem, usually the audRec.release() helps indeed, but if you need to stop and start several times the following code is more robust. Plus, I had an issue that the recording took place in a separate thread and Android sometimes kills threads when running for a long time. So take a look at this code, it makes sure the recording is held even when the other thread is dead and upon the following audRec.start() it stops and releases:

    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();
        }
    }
    

    Then if you have a recorder thread you can use it as follows:

    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;
        }
    }
    
    0 讨论(0)
  • 2020-12-31 09:18

    To Answer my own question, the only way i found it doable to use AudioRecord, is to never have it as an global variable, dont know why, but it seems it won't let you release the resources of the instance correctly if you do so.

    0 讨论(0)
  • 2020-12-31 09:22

    I was able to reproduce your problem (on a Samsung phone). I added an onDestroy() method releasing the record:

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

    After adding this, the audioRecord seems to initialize correctly every time the activity is started.

    0 讨论(0)
提交回复
热议问题