8

チップチューン (NSF、SPC など) の音楽ファイルを再生するアプリケーションを Java SE から Android に移植しようとしています。Android API には、このアプリケーションが生の PCM オーディオを出力するために使用する javax マルチメディア クラスがないようです。API で見つけた最も近いアナログは AudioTrack であり、それと格闘してきました。

しかし、進行中のポートを介してサンプル音楽ファイルの 1 つを実行しようとすると、返されるのは静的なものだけです。私の疑いは、私がセットアップした AudioTrack に問題があるということです。さまざまなコンストラクターを試しましたが、最終的にはすべて static を出力するだけです。

元のコードでの 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 宣言では、ビッグ エンディアン パラメータが「true」に設定されていますが、Android AudioTrack は PCM データがリトル エンディアン形式であると想定しています。

だから私は次のように私の直感をテストするために簡単な小さなループを書きました:

 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 に答える