4

以前我提出了一个关于将 a 转换为byte[]的问题,我遇到的一个新问题是将数据从BigEndianshort[]转换/不转换。 这是发生了什么:byte[]

  • 我正在使用TargetDataLine将数据读入byte[10000].
  • AudioFormat对象已任意BigEndian设置为true
  • byte[]需要转换为,short[]以便可以使用 Xuggler 对其进行编码
  • 我不知道AudioFormat应该将 BigEndian 设置为 true 还是 false。
    我已经尝试了这两种情况,并且在这两种情况下都得到了异常。
    要转换byte[]short[],我这样做:

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

    其中:
    fromMic是 我得到 TargetDataLine
    tempBufferbyte异常byte[10000]
    tempBufferShortshort[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);
    

    关于音频格式的 Java 文档

    ...除了编码之外,音频格式还包括其他属性,这些属性进一步指定了数据的确切排列。这些包括通道数、采样率、样本大小、字节顺序、帧速率和帧大小......

    对于 16 位样本(或任何其他大于一个字节的样本大小),字节顺序很重要;每个样本中的字节以“小端”或“大端”样式排列。

    问题:

  • 我需要在对象中保持BigEndianas true吗?javax.sound.sampled.AudioFormat

  • 是什么导致了错误?是格式吗?



  • 我想我得到了由 AudioFormat 对象预先格式化的 BigEndian 数据。

    4

    3 回答 3

    3

    如果您的数据确实是大端,您可以直接将其转换为(大端)短数组,如下所示:

    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

    您需要将两个字节转换为一个 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

    What others here have said about the byte-to-short conversion is correct, but it cannot cause the problem you see, it would just cause the output audio to be mostly noise. You can call writeAudio with a buffer of all zeros (or anything, really) so, everything else being equal, the values in the buffer don't matter to whether the call succeeds (they do matter to what you hear in the output, of course :)

    1. Does the exception happen at the beginning of the stream (first audio chunk)? Can you write an audio-only stream successfully?

    2. Set the audio codec when you call addAudioStream. Try ICodec.ID.CODEC_ID_MP3 or ICodec.ID.CODEC_ID_AAC.

    3. Check that fmt.getChannels() and fmt.getSampleRate() are correct. Not all possible values are supported by any particular codec. (2 ch, 44100 Hz should be supported by just about anything).

    4. Are you writing your audio and video such that the timestamps are strictly non-decreasing?

    5. Do you have enough audio samples for the duration your timestamps are indicating? Does tempBufferShort.length == ((timeStamp - lastTimeStamp) / 1e+9) * sampleRate * channels ? (This may be only approximately equal, but it should be very close, slight rounding errors probably ok).

    于 2012-12-25T23:54:38.413 回答