【问题标题】:Android: AudioTrack vs. multithreadingAndroid:AudioTrack 与多线程
【发布时间】:2012-09-20 20:46:09
【问题描述】:

我遇到了一个问题,我想在静态模式下反复播放半秒长的 AudioTrack,但声音断断续续。但是,我注意到TransitionDrawable 并行运行时声音非常清晰。

我的代码的简化骨架是:

thread = new Thread(new Runnable() {

  public void run() {
    createTransition();

    try {
      createAudioTrack();

      while (true) {
        if (audio) {
          playSoundClip();
        }

        if (display) {
          playScreenTransition();
        }

        Thread.sleep(getDelayBetweenBeats());
      }
    } catch (InterruptedException e) {
    } finally {
      resetScreenTransition();
      stopSoundClip();
    }
  }

  private void createAudioTrack() {
    short[] samples = generateSamples();
    track = new AudioTrack(AudioManager.STREAM_MUSIC, SAMPLERATE, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, samples.length * 2, AudioTrack.MODE_STATIC);
    if (track.getState() != AudioTrack.STATE_UNINITIALIZED) {
      track.write(samples, 0, samples.length);
    }
  }

  private void playSoundClip() {
    if (track != null && track.getState() != AudioTrack.STATE_UNINITIALIZED) {
      track.stop();
      track.reloadStaticData();
      track.play();
    }
  }

  private void playScreenTransition() {
    view.post(new Runnable() {

      public void run() {
        view.setBackgroundDrawable(transition);
        transition.startTransition(DURATION);
      }

    });
  }

});
thread.start();

如您所见,thread 未在 UI 线程上执行,因此我假设 track 面临多线程问题。我不认为播放转换的 UI 线程会消耗整个 CPU,因为我的音频是并行播放的。似乎该活动以某种方式消耗了 CPU,并且没有执行任何其他操作。

我也曾尝试在playSoundClip() 中使用view.post(new Runnable() {...});,但这没有帮助。

我曾考虑将所有内容更改为 AsyncTask,但恕我直言,这不会改变任何内容,因为它仍然是后台任务。因为我不需要用声音更新 UI 元素,而且过渡仍然必须并行播放,所以我什至没有尝试过。

一种解决方案可能是始终并行运行一些过渡(实际过渡或虚拟过渡),但这对我来说听起来很糟糕(双关语?)。

有谁知道如何让track 始终清晰播放?


编辑:
在这个问题上做了更多工作并扩展了我的程序后,我注意到我必须使用上面列出的线程方法,因为那里的逻辑需要一些时间才能完成,而且我无法在 UI 线程上完成所有操作更多的。目前,我在播放音频时播放了一个虚拟过渡,这对我来说仍然听起来很糟糕。因此,如果您仍然可以对该主题提供一些见解,欢迎您在此处发布/回答。

【问题讨论】:

    标签: android multithreading audiotrack


    【解决方案1】:

    您可能想看看SoundPool,它允许您将短音频样本静态加载到内存中一次,然后以低得多的延迟按需播放。您使用AudioTrack 的方式很好地使用了无需重新加载即可重放音频,但对于如此短且经常重复的声音字节,它可能仍然有点重。

    您也可以考虑完全不使用后台线程。从您的 sn-p 看起来您实际上只是将 Thread 用作计时器,并且您可能会通过使用 Handler 在定时间隔上发布您的 Runnable 获得更好的性能(这也将允许您在主线程上调用您的音频/转换方法)。

    HTH

    【讨论】:

    • 我查看了SoundPool 的文档并搜索了一下。似乎它不允许生成自己的样本并将其发送给扬声器。就Handler 而言,我必须多看一些。我不是很熟悉。
    • 道歉。我错过了您在应用程序代码中生成音频数据的部分。
    • 没什么大不了的。我想我找到了一个example of what you think I should do,并且非常接近我想要做的事情。但是,同样的问题。
    【解决方案2】:

    我有更大的音频块,但我很幸运能在我创建的服务中播放它们。

    附:好双关

    【讨论】:

    • 根据documentation Service 本身非常简单,必须将持久的东西委托给单独的线程。好吧,它确实说明了其他线程的优先级。我会看看我能用它做什么。
    • 这也没有帮助。服务中的startForeground() 没有帮助,使用额外的Handler 也没有帮助。您是否使用AudioTrack 播放文件?或SoundPoolMediaPlayer
    • 当你说音频断断续续时,它是不是在剪辑片段上或片段内开始播放音频时断断续续
    • 剪辑本身很短,所以我不知道剪辑一段时间后它是否会变得更好。据我所知,排骨并不总是在同一个位置。 -- 如果您使用AudioTrack 或其他其中之一,我仍然会很感兴趣。
    • 我的服务也在后台运行,也就是不在 ui 线程中。我在服务中使用了 MediaPlayer。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-17
    • 1970-01-01
    • 2013-02-02
    • 2015-08-21
    相关资源
    最近更新 更多