我正在嘗試從麥克風獲取音頻數據。我已經通過使用填充類型爲shorts的緩衝區的AudioRecord
類來實現此目的。麥克風輸入的處理
最後我想繪製這個緩衝區,以便我得到一個像顯示器(實時信息)的示波器。問題是,如果我想顯示一個值(比如說文本),那麼我需要一個不同的線程來更新UI。目前我正在使用AsyncTask
並使用AsyncTasks.publishProgress()
更新UI。到目前爲止,我還沒有很成功,想知道我是否在正確的軌道上?處理更好的方法去?有沒有人曾經做過類似的事情,如果有的話,你有什麼方法?另外,是否可以簡單地輪詢麥克風?
這是我的代碼。它旨在輸出MIC中的每個讀取樣本。它似乎以可接受的速度執行此操作,但偶爾顯示爲零。爲什麼?
package com.ss.audioacquireapp3;
import android.app.Activity;
import android.content.Context;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
public class AudioAcquireApp3Activity extends Activity
{
//Properties (AsyncTask)
protected TextView _percentField;
protected InitTask _initTask;
//Properties (MIC)
public AudioRecord audioRecord;
public int mSamplesRead; //how many samples read
public int recordingState;
public int buffersizebytes;
public int channelConfiguration = AudioFormat.CHANNEL_IN_MONO;
public int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
public static short[] buffer; //+-32767
public static final int SAMPPERSEC = 44100; //samp per sec 8000, 11025, 22050 44100 or 48000
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
_percentField = (TextView) findViewById(R.id.percent_field);
buffersizebytes = AudioRecord.getMinBufferSize(SAMPPERSEC,channelConfiguration,audioEncoding); //4096 on ion
buffer = new short[buffersizebytes];
audioRecord = new AudioRecord(android.media.MediaRecorder.AudioSource.MIC,SAMPPERSEC,channelConfiguration,audioEncoding,buffersizebytes); //constructor
_initTask = new InitTask();
_initTask.execute(this);
}
/**
* sub-class of AsyncTask
*/
protected class InitTask extends AsyncTask<Context, Integer, String>
{
// -- run intensive processes here
// -- notice that the datatype of the first param in the class definition matches the param passed to this method
// -- and that the datatype of the last param in the class definition matches the return type of this method
@Override
protected String doInBackground(Context... params)
{
//-- on every iteration
//-- runs a while loop that causes the thread to sleep for 50 milliseconds
//-- publishes the progress - calls the onProgressUpdate handler defined below
//-- and increments the counter variable i by one
//int i = 0;
audioRecord.startRecording();
while(true)
{
try{
mSamplesRead = audioRecord.read(buffer, 0, buffersizebytes);
int amp;
for(int i = 0; i < buffersizebytes - 1; i++){
amp = (int)buffer[i];
publishProgress(amp);
}
} catch(Exception e){
}
}
}
// -- gets called just before thread begins
@Override
protected void onPreExecute()
{
//Log.i("makemachine", "onPreExecute()");
super.onPreExecute();
}
// -- called from the publish progress
// -- notice that the datatype of the second param gets passed to this method
@Override
protected void onProgressUpdate(Integer... values)
{
super.onProgressUpdate(values);
//Log.i("makemachine", "onProgressUpdate(): " + String.valueOf(values[0]));
_percentField.setText(String.valueOf(values[0]));
}
// -- called as soon as doInBackground method completes
// -- notice that the third param gets passed to this method
@Override
protected void onPostExecute(String result)
{
super.onPostExecute(result);
//Log.i("makemachine", "onPostExecute(): " + result);
}
}
}
這裏是main.xml中
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_vertical|center_horizontal"
>
<TextView android:id="@+id/percent_field"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"/>
</LinearLayout>
請注意,你需要把它添加到AndroidManifest.xml中
<uses-permission android:name="android.permission.RECORD_AUDIO" />
我運行這在LG擎天柱黑。請幫助我儘可能提高此代碼的效率。
謝謝,這有助於很多。我已經使用了代碼鏈接,並有一些現在有用的東西。不幸的是它的運行非常緩慢你可以幫助代碼嗎? – user893825
那麼,沒有真正看到代碼就很難幫助你。找到運行頻率最高的代碼(例如,在AsyncTask.run())並對其進行優化,例如:刪除不需要的調試日誌,長時間運行的操作等。 – pkk
我已經發布了我的代碼。我是否應該在此輸入而不是回答?謝謝 :) – user893825