安卓:AudioRecord类问题:回调不会被调用 [英] Android: AudioRecord Class Problem: Callback is never called

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

问题描述

我的Andr​​oid Java应用程序需要记录的音频数据到RAM和处理。 这就是为什么我使用的类AudioRecord,而不是MediaRecorder(仅记录到文件)。

直到现在,我用了一个繁忙的循环轮询阅读()为音频数据。这已被工作到目前为止,但它peggs CPU的太多。 两次轮询之间,我把线程睡眠,避免100%的CPU使用率。 然而,这是不是一个真正的干净的解决方案,因为睡眠时间 不能保证,你必须减去一个安全的时间,为了不失去音频 片段。这不是最优的CPU。我需要尽可能多的空闲CPU周期,尽可能为 并行运行的线程。

现在我实现了使用OnRecordPositionUpdateListener的录制。 这看起来非常有前途,并根据该SDK文档以正确的方式来做到这一点。 一切似乎工作(打开音频设备,阅读()荷兰国际集团的数据等) 但听者永远不会被调用。

有谁知道为什么吗?

信息: 我正与一个真实的设备,而不是在模拟器。采用忙循环的录音工作基本(但不是satifiying)。只有回调监听器永远不会被调用。

下面是我的源$ C ​​$ C的一个片段:

 公共类MyApplication的延伸活动{

  / *录音* /
  私有静态最终诠释AUDIO_SAMPLE_FREQ = 16000;
  私有静态最终诠释AUDIO_BUFFER_BYTESIZE = AUDIO_SAMPLE_FREQ * 2 * 3; // = 3000ms
  私有静态最终诠释AUDIO_BUFFER_SAMPLEREAD_SIZE = AUDIO_SAMPLE_FREQ / 10 * 2; // = 200毫秒

  私人短[] mAudioBuffer = NULL; //音频缓冲
  私人诠释mSamplesRead; //是最近看了多少样本
  私人AudioRecord mAudioRecorder; //录音机

  ...

  私人OnRecordPositionUpdateListener mRecordListener =新OnRecordPositionUpdateListener(){

    公共无效onPeriodicNotification(AudioRecord记录器){
      mSamplesRead = recorder.read(mAudioBuffer,0,AUDIO_BUFFER_SAMPLEREAD_SIZE);
      如果(mSamplesRead大于0){

        //做的东西在这里...

      }
    }

    公共无效onMarkerReached(AudioRecord记录器){
      错误(什么!?胡我在哪里?);
    }
  };

  ...

  公共无效的onCreate(包savedInstanceState){

  尝试 {
      mAudioRecorder =新AudioRecord(
          android.media.MediaRecorder.AudioSource.MIC,
          AUDIO_SAMPLE_FREQ,
          AudioFormat.CHANNEL_CONFIGURATION_MONO,
          AudioFormat.ENCODING_PCM_16BIT,
          AUDIO_BUFFER_BYTESIZE);
    }赶上(例外五){
      错误(无法初始化录音!);
    }

    mAudioBuffer =新的短[AUDIO_BUFFER_SAMPLEREAD_SIZE]
    mAudioRecorder.setPositionNotificationPeriod(AUDIO_BUFFER_SAMPLEREAD_SIZE);
    mAudioRecorder.setRecordPositionUpdateListener(mRecordListener);
    mAudioRecorder.startRecording();

    / *测试,如果我能在所有读什么...(是的,这在这里工作!)* /
    mSamplesRead = mAudioRecorder.read(mAudioBuffer,0,AUDIO_BUFFER_SAMPLEREAD_SIZE);

  }
}
 

解决方案

我认为,问题是,你仍然需要做的读取循环。如果设置回调,他们将火当你读到您的回调指定的帧数。但是,你仍然需要做的读取。我已经试过这一点,并在回调被调用就好了。设置一个标记引起的回调时数目的帧已被自记录开始读取。换句话说,你可以远远设置标记进去以后,经过很多的读取,它会火呢。您可以将期限设置为帧的一些比较大的数字,并且回调将会触发的帧数已经被阅读了每一次。我认为他们这样做,所以你可以做的原始数据的低层次处理在紧密循环,然后每隔一段时间你的回调可以做总结性的处理。可以使用标记物,使其更容易决定何时停止记录(而不是在读循环计数)。

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).

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.

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.

Does anybody know why?

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).

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

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