我的教授是一个大学项目。想让我写一个Android应用程序,将是我的第一个。我有一些Java经验,但我是Android编程的新手,所以请温柔地对待我。
首先我创建一个Activity,其中只有两个按钮,一个用于启动AsyncTask,另一个用于停止它,我的意思是我只是将布尔值“isRecording”设置为false,其他所有内容都在AsyncTask中处理,后者附加了作为源代码。
事情运行得很好,但过了一会儿我可以在LogCat中找到一些缓冲区溢出消息,之后它会因未捕获的异常而崩溃。我弄清楚它为什么会崩溃,未捕获的异常不应该是那个问题的目的。
03-07 11:34:02.474: INFO/buffer 247:(558): 40
03-07 11:34:02.484: WARN/AudioFlinger(33): RecordThread: buffer overflow
03-07 11:34:02.484: INFO/MutantAudioRecorder:doInBackground()(558): isRecoding
03-07 11:34:02.484: INFO/MutantAudioRecorder:doInBackground()(558): isRecoding
03-07 11:34:02.494: WARN/AudioFlinger(33): RecordThread: buffer overflow
03-07 11:34:02.494: INFO/buffer 248:(558): -50
我正如你所看到的那样写出了缓冲区,但不知怎的,我认为我在正确配置AudioRecord时犯了一个错误,任何人都可以告诉我为什么会得到缓冲区溢出?
接下来的问题是,我该如何处理缓冲区?我的意思是,我有里面的值,并希望它们在屏幕上以图形频谱图显示。有没有人有这方面的经验,我可以提一下吗?我怎么能继续......
提前感谢您的帮助。
AsyncTask的源代码:
package nomihodai.audio;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.os.AsyncTask;
import android.util.Log;
public class MutantAudioRecorder extends AsyncTask<Void, Void, Void> {
private boolean isRecording = false;
public AudioRecord audioRecord = null;
public int mSamplesRead;
public int buffersizebytes;
public int buflen;
public int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
public int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
public static short[] buffer;
public static final int SAMPLESPERSEC = 8000;
@Override
protected Void doInBackground(Void... params) {
while(isRecording) {
audioRecord.startRecording();
mSamplesRead = audioRecord.read(buffer, 0, buffersizebytes);
if(!readerT.isAlive())
readerT.start();
Log.i("MutantAudioRecorder:doInBackground()", "isRecoding");
}
readerT.stop();
return null;
}
Thread readerT = new Thread() {
public void run() {
for(int i = 0; i < 256; i++){
Log.i("buffer " + i + ": ", Short.toString(buffer[i]));
}
}
};
@Override
public void onPostExecute(Void unused) {
Log.i("MutantAudioRecorder:onPostExecute()", "try to release the audio hardware");
audioRecord.release();
Log.i("MutantAudioRecorder:onPostExecute()", "released...");
}
public void setRecording(boolean rec) {
this.isRecording = rec;
Log.i("MutantAudioRecorder:setRecording()", "isRecoding set to " + rec);
}
@Override
protected void onPreExecute() {
buffersizebytes = AudioRecord.getMinBufferSize(SAMPLESPERSEC, channelConfiguration, audioEncoding);
buffer = new short[buffersizebytes];
buflen = buffersizebytes/2;
Log.i("MutantAudioRecorder:onPreExecute()", "buffersizebytes: " + buffersizebytes
+ ", buffer: " + buffer.length
+ ", buflen: " + buflen);
audioRecord = new AudioRecord(android.media.MediaRecorder.AudioSource.MIC,
SAMPLESPERSEC,
channelConfiguration,
audioEncoding,
buffersizebytes);
if(audioRecord != null)
Log.i("MutantAudioRecorder:onPreExecute()", "audiorecord object created");
else
Log.i("MutantAudioRecorder:onPreExecute()", "audiorecord NOT created");
}
}
答案 0 :(得分:4)
可能有一些实时分析过程处理录制的音频字节?
由于记录的缓冲区大小有限,一旦“分析过程”慢于记录速率,缓冲区中的数据将被卡住,但记录字节总是来临,因此缓冲区溢出。
尝试在录制时使用线程,在记录的字节上使用其他进程,这种方法有一个开源示例代码:http://musicg.googlecode.com/files/musicg_android_demo.zip
答案 1 :(得分:0)
正如我们在聊天室中讨论的那样,解码音频数据并将其显示在屏幕上应该很简单。你提到音频缓冲区每秒有8000个样本,每个样本是16位,它是单声道音频。
显示这一点应该很简单。在视图中将每个样本视为垂直偏移。您需要将-32k到+ 32k的范围缩放到视图的垂直高度。从视图的左边缘开始,每列绘制一个样本。到达右边缘时,再次环绕(根据需要删除上一行)。
这将最终将每个样本绘制为单个像素,这可能看起来不太好。您还可以在相邻样本之间绘制一条线。您可以使用线宽,颜色等来获得最佳效果。
最后一个注意事项:您将每秒绘制8000次,加上更多以清除之前的样本。您可能需要采取一些快捷方式来确保帧速率能够跟上音频。您可能需要跳过样本。