ken*_*enj 65 java android android-hardware audiorecord
我想从麦克风录制音频并访问它以便近乎实时地播放.我不确定如何使用Android AudioRecord类来录制一些麦克风音频并快速访问它.
对于AudioRecord类,官方网站说'应用程序及时轮询AudioRecord对象','填充缓冲区的大小决定了在超载未读数据之前记录的时间长度'.后来建议在轮询频率较低时应使用更大的缓冲区.他们实际上从未在代码中显示示例.
我在书中看到的一个例子是使用AudioRecord类连续读取一个新填充了实时麦克风音频的缓冲区,然后应用程序将这些数据写入SD文件.伪代码看起来像 -
set up AudioRecord object with buffer size and recording format info
set up a file and an output stream
myAudioRecord.startRecording();
while(isRecording)
{
// myBuffer is being filled with fresh audio
read audio data into myBuffer
send contents of myBuffer to SD file
}
myAudioRecord.stop();
Run Code Online (Sandbox Code Playgroud)
这段代码如何将其读数与记录速率同步还不清楚 - 布尔"isRecording"是否在其他地方正确地打开和关闭?看起来这段代码可能过于频繁或过于频繁地读取,具体取决于读取和写入所需的时间.
网站doc还说AudioRecord类有一个名为OnRecordPositionUpdateListener的嵌套类,它被定义为一个接口.该信息表明,您以某种方式指定了您希望收到录制进度通知的时间段以及事件处理程序的名称,并且会以指定的频率自动调用您的事件处理程序.我认为伪代码中的结构会像 -
set target of period update message = myListener
set period to be about every 250 ms
other code
myListener()
{
if(record button was recently tapped)
handle message that another 250 ms of fresh audio is available
ie, read it and send it somewhere
)
Run Code Online (Sandbox Code Playgroud)
我需要找到一些特定的代码,它允许我以小于约500毫秒的延迟捕获和处理麦克风音频.Android提供另一个名为MediaRecorder的类,但它不支持流媒体,我可能希望通过Wi-Fi网络近乎实时地传输实时麦克风音频.我在哪里可以找到一些具体的例子?
ton*_*nys 34
在尝试使用通知和一堆其他技术后,我决定使用此代码:
private class AudioIn extends Thread {
private boolean stopped = false;
private AudioIn() {
start();
}
@Override
public void run() {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
AudioRecord recorder = null;
short[][] buffers = new short[256][160];
int ix = 0;
try { // ... initialise
int N = AudioRecord.getMinBufferSize(8000,AudioFormat.CHANNEL_IN_MONO,AudioFormat.ENCODING_PCM_16BIT);
recorder = new AudioRecord(AudioSource.MIC,
8000,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT,
N*10);
recorder.startRecording();
// ... loop
while(!stopped) {
short[] buffer = buffers[ix++ % buffers.length];
N = recorder.read(buffer,0,buffer.length);
//process is what you will do with the data...not defined here
process(buffer);
}
} catch(Throwable x) {
Log.w(TAG,"Error reading voice audio",x);
} finally {
close();
}
}
private void close() {
stopped = true;
}
}
Run Code Online (Sandbox Code Playgroud)
到目前为止,它已经在我尝试过的六款Android手机上运行得非常强劲.
Dav*_*ean 20
我想知道你是否可以通过以下方式结合这些答案......
在while循环之前使用setPositionNotificationPeriod(160).这应该导致每次读取160帧时都会调用回调.而不是在执行读循环的线程内部调用进程(缓冲区),而是从回调中调用进程(缓冲区).使用变量来跟踪最后一个读缓冲区,以便处理正确的缓冲区.就像现在一样,你阻止阅读,然后你在处理时没有阅读.我认为将这两者分开可能会更好.
gre*_*egm 11
以下是使用OnRecordPositionUpdateListener和Notification Period所需的代码.
我注意到在实践中它不会在我想要的同一时间始终发送通知,但它足够接近.
关于detectAfterEvery:
detectEvery的大小必须足够大才能容纳您想要的数据量.因此,对于此示例,我们的采样率为44100 Hz,这意味着我们需要每秒44100个样本.通过将其设置setPositionNotificationPeriod为44100,代码告诉Android在记录44100个样本(大约每1秒)后进行回调.
完整的代码在这里:
final int sampleRate = 44100;
int bufferSize =
AudioRecord.getMinBufferSize(sampleRate,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT);
//aim for 1 second
int detectAfterEvery = (int)((float)sampleRate * 1.0f);
if (detectAfterEvery > bufferSize)
{
Log.w(TAG, "Increasing buffer to hold enough samples " + detectAfterEvery + " was: " + bufferSize);
bufferSize = detectAfterEvery;
}
recorder =
new AudioRecord(AudioSource.MIC, sampleRate,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT, bufferSize);
recorder.setPositionNotificationPeriod(detectAfterEvery);
final short[] audioData = new short[bufferSize];
final int finalBufferSize = bufferSize;
OnRecordPositionUpdateListener positionUpdater = new OnRecordPositionUpdateListener()
{
@Override
public void onPeriodicNotification(AudioRecord recorder)
{
Date d = new Date();
//it should be every 1 second, but it is actually, "about every 1 second"
//like 1073, 919, 1001, 1185, 1204 milliseconds of time.
Log.d(TAG, "periodic notification " + d.toLocaleString() + " mili " + d.getTime());
recorder.read(audioData, 0, finalBufferSize);
//do something amazing with audio data
}
@Override
public void onMarkerReached(AudioRecord recorder)
{
Log.d(TAG, "marker reached");
}
};
recorder.setRecordPositionUpdateListener(positionUpdater);
Log.d(TAG, "start recording, bufferSize: " + bufferSize);
recorder.startRecording();
//remember to still have a read loop otherwise the listener won't trigger
while (continueRecording)
{
recorder.read(audioData, 0, bufferSize);
}
Run Code Online (Sandbox Code Playgroud)