Android:AudioRecord 类问题:从不调用回调 [英] Android: AudioRecord Class Problem: Callback is never called

查看:52
本文介绍了Android:AudioRecord 类问题:从不调用回调的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的 Android Java 应用程序需要将音频数据记录到 RAM 中并进行处理.这就是为什么我使用类AudioRecord"而不是MediaRecorder"(仅记录到文件).

My Android Java Application needs to record audio data into the RAM and process it. This is why I use the class "AudioRecord" and not the "MediaRecorder" (records only to file).

到目前为止,我对音频数据使用了带有read()"的忙循环轮询.到目前为止,这一直在工作,但它过多地与 CPU 挂钩.在两次轮询之间,我让线程进入睡眠状态以避免 100% 的 CPU 使用率.然而,这并不是一个真正干净的解决方案,因为睡眠的时间是不能保证,您必须减去安全时间以免丢失音频片段.这不是 CPU 优化的.我需要尽可能多的空闲 CPU 周期一个并行运行的线程.

Till now, I used a busy loop polling with "read()" for the audio data. this has been working so far, but it peggs the CPU too much. Between two polls, I put the thread to sleep to avoid 100% CPU usage. However, this is not really a clean solution, since the time of the sleep is not guaranteed and you must subtract a security time in order not to loose audio snippets. This is not CPU optimal. I need as many free CPU cycles as possible for a parallel running thread.

现在我使用OnRecordPositionUpdateListener"实现了录音.根据 SDK 文档,这看起来非常有前途,并且是正确的方法.一切似乎都正常(打开音频设备,读取()数据等)但从未调用过 Listner.

Now I implemented the recording using the "OnRecordPositionUpdateListener". This looks very promising and the right way to do it according the SDK Docs. Everything seems to work (opening the audio device, read()ing the data etc.) but the Listner is never called.

有人知道为什么吗?

信息:我正在使用真正的设备,而不是在模拟器下.使用 Busy Loop 的录音基本上可以工作(但不满足).只有回调监听器永远不会被调用.

Info: I am working with a real Device, not under the Emulator. The Recording using a Busy Loop basically works (however not satifiying). Only the Callback Listener is never called.

这是我的源代码中的一个片段:

Here is a snippet from my Sourcecode:

public class myApplication extends Activity {

  /* audio recording */
  private static final int AUDIO_SAMPLE_FREQ = 16000;
  private static final int AUDIO_BUFFER_BYTESIZE = AUDIO_SAMPLE_FREQ * 2 * 3; // = 3000ms
  private static final int AUDIO_BUFFER_SAMPLEREAD_SIZE = AUDIO_SAMPLE_FREQ  / 10 * 2; // = 200ms

  private short[] mAudioBuffer = null; // audio buffer
  private int mSamplesRead; // how many samples are recently read
  private AudioRecord mAudioRecorder; // Audio Recorder

  ...

  private OnRecordPositionUpdateListener mRecordListener = new OnRecordPositionUpdateListener() {

    public void onPeriodicNotification(AudioRecord recorder) {
      mSamplesRead = recorder.read(mAudioBuffer, 0, AUDIO_BUFFER_SAMPLEREAD_SIZE);
      if (mSamplesRead > 0) {

        // do something here...

      }
    }

    public void onMarkerReached(AudioRecord recorder) {
      Error("What? Hu!? Where am I?");
    }
  };

  ...

  public void onCreate(Bundle savedInstanceState) {

  try {
      mAudioRecorder = new AudioRecord(
          android.media.MediaRecorder.AudioSource.MIC, 
          AUDIO_SAMPLE_FREQ,
          AudioFormat.CHANNEL_CONFIGURATION_MONO,
          AudioFormat.ENCODING_PCM_16BIT,  
          AUDIO_BUFFER_BYTESIZE);
    } catch (Exception e) {
      Error("Unable to init audio recording!");
    }

    mAudioBuffer = new short[AUDIO_BUFFER_SAMPLEREAD_SIZE];
    mAudioRecorder.setPositionNotificationPeriod(AUDIO_BUFFER_SAMPLEREAD_SIZE);
    mAudioRecorder.setRecordPositionUpdateListener(mRecordListener);
    mAudioRecorder.startRecording();

    /* test if I can read anything at all... (and yes, this here works!) */
    mSamplesRead = mAudioRecorder.read(mAudioBuffer, 0, AUDIO_BUFFER_SAMPLEREAD_SIZE);

  }
}

推荐答案

我相信问题在于您仍然需要执行读取循环.如果您设置回调,当您读取为回调指定的帧数时,它们将触发.但是您仍然需要进行读取.我试过这个,回调被调用得很好.设置标记会导致自记录开始后读取该数量的帧时进行回调.换句话说,在多次阅读之后,您可以将标记设置到很远的将来,然后它就会触发.您可以将周期设置为更大的帧数,并且每次读取该帧数时都会触发该回调.我认为他们这样做是为了让您可以在紧密循环中对原始数据进行低级处理,然后您的回调经常可以进行汇总级处理.您可以使用标记来更轻松地决定何时停止记录(而不是在读取循环中计数).

I believe the problem is that you still need to do the read loop. If you setup callbacks, they will fire when you've read the number of frames that you specify for the callbacks. But you still need to do the reads. I've tried this and the callbacks get called just fine. Setting up a marker causes a callback when that number of frames has been read since the start of recording. In other words, you could set the marker far into the future, after many of your reads, and it will fire then. You can set the period to some bigger number of frames and that callback will fire every time that number of frames has been read. I think they do this so you can do low-level processing of the raw data in a tight loop, then every so often your callback can do summary-level processing. You could use the marker to make it easier to decide when to stop recording (instead of counting in the read loop).

这篇关于Android:AudioRecord 类问题:从不调用回调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆