/**
* 可视化频率*
* @time 下午12:00:21
* @author retacn yue
* @Email zhenhuayue@sina.com
*/
public class AudioProcessingActivity extends Activity implements OnClickListener {
private Button btn_start_stop;
private ImageView img_frequency;
private Bitmap bitmap;
private Canvas canvas;
private Paint paint;
private AudioRecordTask recordTask;
private RealDoubleFFT trasformer;
int blockSize = 256;
int frequency = 8000;
int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
boolean started = false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.audio_processing);
findView();
trasformer = new RealDoubleFFT(blockSize);
bitmap = Bitmap.createBitmap(256, 100, Bitmap.Config.ARGB_8888);
canvas = new Canvas(bitmap);
paint = new Paint();
paint.setColor(Color.RED);
img_frequency.setImageBitmap(bitmap);
}
@Override
public void onClick(View v) {
if (started) {
started = false;
btn_start_stop.setText("Start");
} else {
started = true;
btn_start_stop.setText("Stop");
recordTask = new AudioRecordTask();
recordTask.execute();
}
}
/**
* 实例化控件
*/
private void findView() {
btn_start_stop = (Button) this.findViewById(R.id.btn_start_stop);
btn_start_stop.setOnClickListener(this);
img_frequency = (ImageView) this.findViewById(R.id.img_frequency);
}
/*****************************************************************/
private static int[] mSampleRates = new int[] { 8000, 11025, 22050, 44100 };
public AudioRecord findAudioRecord() {
for (int rate : mSampleRates) {
for (short audioFormat : new short[] { AudioFormat.ENCODING_PCM_8BIT, AudioFormat.ENCODING_PCM_16BIT }) {
for (short channelConfig : new short[] { AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.CHANNEL_CONFIGURATION_STEREO }) {
try {
Log.d("tag", "Attempting rate " + rate + "Hz, bits: " + audioFormat + ", channel: " + channelConfig);
int bufferSize = AudioRecord.getMinBufferSize(rate, channelConfig, audioFormat);
if (bufferSize != AudioRecord.ERROR_BAD_VALUE) {
Log.e("tag", "++++++++");
AudioRecord recorder = new AudioRecord(AudioSource.MIC, rate, channelConfig, audioFormat, bufferSize);
if (recorder.getState() == AudioRecord.STATE_INITIALIZED)
Log.e("tag", "-----");
return recorder;
}
} catch (Exception e) {
Log.e("tag", rate + "Exception, keep trying.", e);
}
}
}
}
Log.e("tag", "===========");
return null;
}
/**
* 音频合成任务
*/
private class AudioRecordTask extends AsyncTask<Void, double[], Void> {
@Override
protected Void doInBackground(Void... params) {
try {
int bufferSize = AudioRecord.getMinBufferSize(frequency, //
channelConfiguration, //
audioEncoding);
AudioRecord audioRecord = findAudioRecord();
/*****************************************************************/
/*
* AudioRecord audioRecord = new
* AudioRecord(MediaRecorder.AudioSource.MIC,// 输入源 frequency,//
* channelConfiguration,// audioEncoding,// bufferSize);
*/
short[] buffer = new short[blockSize];
double[] toTransform = new double[blockSize];
audioRecord.startRecording();
while (started) {
int bufferReadResult = audioRecord.read(buffer, 0, blockSize);
for (int i = 0; i < blockSize && i < bufferReadResult; i++) {
toTransform[i] = (double) buffer[i] / 32768.0;
}
// TODO
trasformer.ft(toTransform);
publishProgress(toTransform);
}
audioRecord.stop();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
}
return null;
}
protected void onProgressUpdate(double[]... toTransform) {
canvas.drawColor(Color.BLACK);
for (int i = 0; i < toTransform[0].length; i++) {
int x = i;
int downy = (int) (100 - (toTransform[0][i] * 10));
int upy = 100;
canvas.drawLine(x, downy, x, upy, paint);
}
img_frequency.invalidate();
}
}
}
注:
1 该程序用 ca.uol.aig.fftpack.RealDoubleFFT这个包
下载路径为:http://www.netlib.org/fftpack/index.html
将文件导入工即可
2 错误信息:java.lang.IllegalStateException: startRecording() called on an uninitialized AudioRecord.
3 添加权限 <uses-permission android:name="android.permission.RECORD_AUDIO" />