【问题标题】:Difficulty porting raw PCM output code from Java to Android AudioTrack API难以将原始 PCM 输出代码从 Java 移植到 Android AudioTrack API
【发布时间】:2010-04-25 05:50:17
【问题描述】:

我正在尝试将播放 Chiptunes(NSF、SPC 等)音乐文件的应用程序从 Java SE 移植到 Android。 Android API 似乎缺少此应用程序用于输出原始 PCM 音频的 javax 多媒体类。我在 API 中找到的最接近的模拟是 AudioTrack,所以我一直在努力解决这个问题。

但是,当我尝试通过正在进行的端口运行我的示例音乐文件之一时,我得到的只是静态的。我怀疑是我设置的 AudioTrack 有问题。我尝试了各种不同的构造函数,但最后都只是输出静态的。

原始代码中的 DataLine 设置类似于:

AudioFormat audioFormat = new AudioFormat( AudioFormat.Encoding.PCM_SIGNED,
                44100, 16, 2, 4, 44100, true );
DataLine.Info lineInfo = new DataLine.Info( SourceDataLine.class, audioFormat );
DataLine line = (SourceDataLine)AudioSystem.getLine( lineInfo );

我现在使用的构造函数是:

AudioTrack = new AudioTrack( AudioManager.STREAM_MUSIC,
        44100,
        AudioFormat.CHANNEL_CONFIGURATION_STEREO,
        AudioFormat.ENCODING_PCM_16BIT,
        AudioTrack.getMinBufferSize( 44100,
                AudioFormat.CHANNEL_CONFIGURATION_STEREO,
                AudioFormat.ENCODING_PCM_16BIT ),
        AudioTrack.MODE_STREAM );

我已经替换了其中的常量和变量,以便它们尽可能简洁地有意义,但我的基本问题是,我在从一种格式转换到另一种格式时所做的假设是否存在任何明显的问题。

【问题讨论】:

  • 即使你是静态的,你是否检查过轨道长度是否正确?
  • 有问题的音乐文件并没有确定的曲目长度。也就是说,它们是 DSP 的代码形式,它只是继续循环播放,直到被告知停止。

标签: java android audio pcm


【解决方案1】:

所以今天我有一点时间来进一步研究这个问题,我想我已经确定了。上面第一个代码示例中的 AudioFormat 声明将 big endian 参数设置为“true”,但 Android AudioTrack 要求 PCM 数据采用 little endian 格式。

所以我写了一个小循环来测试我的预感,如下所示:

 for( int i = 0; i + LEN_PCM_SAMPLE_BYTES < LEN_PCM_BUFFER; i += LEN_PCM_SAMPLE_BYTES ) {
    // Really rude endian conversion.
    byte bytTemp = a_bytBuffer[i];
    a_bytBuffer[i] = a_bytBuffer[i + 1];
    a_bytBuffer[i + 1] = bytTemp;
 }

基本上,此循环会翻转缓冲区中每个(16 位)样本的字节。这很好用,除了它有点不稳定,因为它非常低效。我尝试使用 ByteBuffer,但这似乎并没有翻转单个样本中的字节。

我会想出一些更好的东西,但这里的基本问题已经解决了。希望其他人觉得这很有用!

【讨论】:

  • 你有办法解决波动吗?
猜你喜欢
  • 2011-08-30
  • 2018-09-28
  • 1970-01-01
  • 2012-01-27
  • 1970-01-01
  • 2015-07-15
  • 2023-03-09
  • 2013-09-29
  • 1970-01-01
相关资源
最近更新 更多