何时释放 AudioRecord 对象?

Posted

技术标签:

【中文标题】何时释放 AudioRecord 对象?【英文标题】:When to release AudioRecord object? 【发布时间】:2013-06-08 09:29:25 【问题描述】:

我正在使用以下代码。它工作正常并显示频率。但每次在启动应用程序之前,我都需要重新安装它以使其正常工作。会不会是对象没有被释放?我在这里包含我的代码。

public class Test extends Activity

String TAG;
public boolean recording;
AudioRecord recorder;
int numCrossing,p;
short audioData[];
int bufferSize,srate;
TextView disp;
float frequency;
private static int[] sampleRate = new int[]  44100, 22050, 11025, 8000 ;

@Override
protected void onCreate(Bundle Testing) 
    // TODO Auto-generated method stub
    super.onCreate(Testing);
    setContentView(R.layout.activity_start);
    disp = (TextView) findViewById (R.id.tvDisp);

    Thread t1 = new Thread(new Runnable()

        public void run() 

            Log.i(TAG,"Setting up recording");
            for (int rate : sampleRate) 
                try

                        Log.d(TAG, "Attempting rate " + rate);

            bufferSize=AudioRecord.getMinBufferSize(rate,AudioFormat.CHANNEL_CONFIGURATION_MONO,
            AudioFormat.ENCODING_PCM_16BIT)*3; //get the buffer size to use with this audio record

            if (bufferSize != AudioRecord.ERROR_BAD_VALUE) 

            recorder = new AudioRecord (MediaRecorder.Audiosource.MIC,rate,AudioFormat.CHANNEL_CONFIGURATION_MONO,
            AudioFormat.ENCODING_PCM_16BIT,bufferSize); //instantiate the AudioRecorder
            srate = rate;
            break;
            

             catch (Exception e) 
                Log.e(TAG, rate + "Exception, keep trying.",e);
            
        


            recording=true; //variable to use start or stop recording
            audioData = new short [bufferSize]; //short array that pcm data is put into.
            Log.i(TAG,"Got buffer size =" + bufferSize);                
            while (recording)   //loop while recording is needed
                   Log.i(TAG,"in while 1");
            if (recorder.getState()==android.media.AudioRecord.STATE_INITIALIZED) // check to see if the recorder has initialized yet.
            if (recorder.getRecordingState()==android.media.AudioRecord.RECORDSTATE_STOPPED)
            recorder.startRecording();  //check to see if the Recorder has stopped or is not recording, and make it record.

            else 
                   Log.i(TAG,"in else");
            recorder.read(audioData,0,bufferSize); //read the PCM audio data into the audioData array

            numCrossing=0; //initialize your number of zero crossings to 0
            for (p=0;p<bufferSize/4;p+=4) 
                   if (audioData[p]>0 && audioData[p+1]<=0) numCrossing++;
                    if (audioData[p]<0 && audioData[p+1]>=0) numCrossing++;
                    if (audioData[p+1]>0 && audioData[p+2]<=0) numCrossing++;
                    if (audioData[p+1]<0 && audioData[p+2]>=0) numCrossing++;
                    if (audioData[p+2]>0 && audioData[p+3]<=0) numCrossing++;
                    if (audioData[p+2]<0 && audioData[p+3]>=0) numCrossing++;
                    if (audioData[p+3]>0 && audioData[p+4]<=0) numCrossing++;
                    if (audioData[p+3]<0 && audioData[p+4]>=0) numCrossing++;
                    //for p

              for (p=(bufferSize/4)*4;p<bufferSize-1;p++) 
                    if (audioData[p]>0 && audioData[p+1]<=0) numCrossing++;
                    if (audioData[p]<0 && audioData[p+1]>=0) numCrossing++;
                    



            frequency=(srate/bufferSize)*(numCrossing/2);//calculating frequency

             Log.i(TAG, "Calculated Frequency");
             runOnUiThread(new Runnable()
                 public void run()
                 
                     Log.i(TAG,"In printing statement");
                     disp.setText("The frequency is " + frequency);
                     if(frequency>=15000)
                         recording = false;
                 
             );


             //else recorder started


     //while recording

   if (recorder.getState()==android.media.AudioRecord.RECORDSTATE_RECORDING) 
    recorder.stop(); //stop the recorder before ending the thread
    recorder.release(); //release the recorders resources
    recorder=null; //set the recorder to be garbage collected.

//运行

    );
    t1.start();

【问题讨论】:

【参考方案1】:

我没有对您的代码进行详尽的阅读,但我确实看到您仅在频率 >= 15000 时才设置recording = false。您可能不会退出while 循环。

顺便说一句...我相信这就是正在发生的事情...您的线程占用了您设备的录制资源。当您退出活动,离开应用程序,线程继续运行。当您尝试再次启动应用程序时,会创建一个新线程,但旧线程仍在运行并仍在占用录制资源。我相信,重新安装应用程序的效果是杀死那个流氓线程。

【讨论】:

好的.. 所以我可以保留一个停止按钮之类的东西来停止它并设置recording=false? 是的。您最终要做的是在您的 UI(或“主”)线程上设置一个变量,然后在您的录制线程中引用该变量。注意线程之间的同步。这是一个特别好的教程:math.hws.edu/javanotes/c12/s1.htmlSection 12.1.3 特别适用。

以上是关于何时释放 AudioRecord 对象?的主要内容,如果未能解决你的问题,请参考以下文章

Audio子系统之AudioRecord.startRecording

Android 5.1 Audio系统笔记:AudioRecord

Audio子系统之AudioRecord.read

Audio子系统之AudioRecord.stop

Audio子系统之AudioRecord.release

Audio子系统之new AudioRecord()