8

我正在尝试将播放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 );

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

4

1 回答 1

7

所以今天我有一点时间来进一步研究这个问题,我想我已经确定了。上面第一个代码示例中的 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 但这似乎并没有翻转单个样本中的字节。

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

于 2010-04-28T08:18:12.717 回答