4

以前、データを BigEndian に変換する/変換しないという新しい問題が発生byte[]しました。 何が起こっているかは次のとおりです。short[]byte[]

  • TargetDataLineデータをに読み込むために使用していbyte[10000]ます。
  • AudioFormatオブジェクトは任意にtrueBigEndianに設定されています。
  • これは、 Xuggler を使用してエンコードできるようbyte[]に変換する必要があります。short[]
  • AudioFormatBigEndian を true に設定するか false に設定する必要があるかわかりません。
    両方のケースを試しましたが、両方のケースで例外が発生しました。
    に変換するbyte[]short[]は、次のようにします。

    fromMic.read(tempBufferByte, 0, tempBufferByte.length);
    for(int i=0;i<tempBufferShort.length;i++){
    tempBufferShort[i] = (short) tempBufferByte[i];
    }  
    

    ここで:
    fromMicis TargetDataLine
    tempBufferbyteis is byte[10000]
    tempBufferShortisshort[10000]
    私は例外を取得します:

       java.lang.RuntimeException: failed to write packet: com.xuggle.xuggler.IPacket@90098448[complete:true;dts:12;pts:12;size:72;key:true;flags:1;stream index:1;duration:1;position:-1;time base:9/125;]
    

    必要なその他の情報:

  • Xuggler でオーディオを追加するためのストリームを設定する方法:
  • writer.addAudioStream(0,1,fmt.getChannels(),(int)fmt.getSampleRate());
    

  • エンコーディングの実行方法
  • writer.encodeAudio(1,tempBufferShort,timeStamp,TimeUnit.NANOSECONDS);
    

    AudioFormat に関する Java ドキュメント

    ...エンコーディングに加えて、オーディオ形式には、データの正確な配置をさらに指定する他のプロパティが含まれます。これらには、チャネル数、サンプル レート、サンプル サイズ、バイト オーダー、フレーム レート、およびフレーム サイズが含まれます...

    16 ビット サンプル (または 1 バイトより大きいその他のサンプル サイズ) の場合、バイト順が重要です。各サンプルのバイトは、「リトル エンディアン」または「ビッグ エンディアン」スタイルで配置されます。

    質問:

  • オブジェクトのBigEndianas trueを維持する必要がありますか?javax.sound.sampled.AudioFormat

  • エラーの原因は何ですか? フォーマットですか?



  • AudioFormat オブジェクトによって事前にフォーマットされた BigEndian データを取得していると思います。

    4

    3 に答える 3

    3

    データが実際にビッグ エンディアンである場合は、次のように (ビッグ エンディアンの) short 配列に直接変換できます。

    ByteBuffer buf = ByteBuffer.wrap(originalByteArray);
    short[] shortArray = buf.asShortBuffer().array();
    

    データがビッグ エンディアンである場合、結果のshort配列にはすべての元のbyte配列が直接、正しくマップされます。したがって、次のような元の配列:

    // bytes
    [00], [ae], [00], [7f]
    

    に変換されます:

    // shorts
    [00ae], [007f]
    
    于 2012-12-25T20:57:22.593 に答える
    2

    2 バイト1 つの shortに変換する必要があるため、次の行は間違っています。

    tempBufferShort[i] = (short) tempBufferByte[i];
    

    次のようなものが必要です

    tempBufferShort[i] = (short) 
       (tempBufferByte[i*2] & 0xFF)*256 + (tempBufferByte[i*2+1] & 0xFF);
    

    これは、ビッグエンディアンのバイト配列と一致します。

    于 2012-12-25T20:42:26.000 に答える
    1

    ここで他の人がバイトからショートへの変換について言ったことは正しいですが、それはあなたが見る問題を引き起こすことはできません、それは出力オーディオがほとんどノイズになるだけです。すべてゼロ(または実際には何でも)のバッファーを使用してwriteAudioを呼び出すことができるため、他のすべてが等しい場合、バッファー内の値は、呼び出しが成功するかどうかには関係ありません(出力で聞こえるものに関係します。コース :)

    1. 例外はストリームの最初(最初のオーディオチャンク)で発生しますか?音声のみのストリームを正常に作成できますか?

    2. を呼び出すときにオーディオコーデックを設定しますaddAudioStreamICodec.ID.CODEC_ID_MP3またはを試してくださいICodec.ID.CODEC_ID_AAC

    3. それを確認してfmt.getChannels()fmt.getSampleRate()正しいです。すべての可能な値が特定のコーデックでサポートされているわけではありません。(2 ch、44100 Hzは、ほぼすべてでサポートされているはずです)。

    4. タイムスタンプが厳密に減少しないようにオーディオとビデオを作成していますか?

    5. タイムスタンプが示している期間に十分なオーディオサンプルがありますか?しますかtempBufferShort.length == ((timeStamp - lastTimeStamp) / 1e+9) * sampleRate * channels?(これはほぼ等しい場合がありますが、非常に近いはずであり、わずかな丸め誤差はおそらく問題ありません)。

    于 2012-12-25T23:54:38.413 に答える