Java AudioFormat 当每个样本的位数发生变化时的奇怪行为
Weird behaviout of Java AudioFormat when bits per sample change
我正在尝试播放服务器通过 UDP 返回给我的音频流。服务器使用 DPCM 对音频进行编码,因此每个字节包含两个音频样本。当我用 8 bits/sample 播放音频时,一切正常,但是当我尝试用 16 AudioFormat DPCM = new AudioFormat(8000,16,1,true,false);
播放音频时,剪辑更短而且不太清晰。我做错了什么?
ByteArrayOutputStream sound_buffer = new ByteArrayOutputStream();
clientRequest = new DatagramPacket( sound_request_buffer, sound_request_buffer.length );
server.send(clientRequest);
for(int i=0;i<100;i++){
buffer = new byte[128];
serverResponse = new DatagramPacket( buffer, buffer.length);
client.receive(serverResponse);
sound_buffer.write(buffer);
}
byte[] encoded_sound = sound_buffer.toByteArray();
byte[] decoded_sound = new byte[2*encoded_sound.length];
byte msnibble = (byte)((encoded_sound[0]>>4) & 0x000F);
decoded_sound[0] = (byte)(msnibble - 8);
byte lsnibble = (byte)(encoded_sound[0] & 0x000F );
decoded_sound[1] = (byte) (decoded_sound[0] + lsnibble - 8);
for(int i=1;i<encoded_sound.length;i++){
msnibble = (byte)((encoded_sound[i] >> 4) & 0x000F);
decoded_sound[2*i] = (byte)(decoded_sound[2*i-1] + msnibble - 8);
lsnibble = (byte)(encoded_sound[i] & 0x000F );
decoded_sound[2*i+1] = (byte)(decoded_sound[2*i] + lsnibble - 8);
}
AudioFormat DPCM = new AudioFormat(8000,8,1,true,false);
SourceDataLine lineOut=AudioSystem.getSourceDataLine(DPCM);
lineOut.open(DPCM,decoded_sound.length);
lineOut.start();
lineOut.write(decoded_sound,0,decoded_sound.length);
问题是您给 SourceDataLine
8 位音频并告诉它像 16 位音频一样播放。这将使播放时间减半(因为每个样本使用两倍的位数)。它还使用用于声音的实际数字做一些奇怪的事情,但我不确定是什么(我没有测试你的例子。)
AudioFormat
不会格式化音频,它会告诉 SourceDataLine
您的音频当前是如何格式化的,以便正确播放。
我不太确定您想做什么,我想这取决于您想要 16 位音频的原因。您可能需要从服务器请求 16 位音频而不是 8 位音频,或者您甚至可能不需要 16 位音频。
我正在尝试播放服务器通过 UDP 返回给我的音频流。服务器使用 DPCM 对音频进行编码,因此每个字节包含两个音频样本。当我用 8 bits/sample 播放音频时,一切正常,但是当我尝试用 16 AudioFormat DPCM = new AudioFormat(8000,16,1,true,false);
播放音频时,剪辑更短而且不太清晰。我做错了什么?
ByteArrayOutputStream sound_buffer = new ByteArrayOutputStream();
clientRequest = new DatagramPacket( sound_request_buffer, sound_request_buffer.length );
server.send(clientRequest);
for(int i=0;i<100;i++){
buffer = new byte[128];
serverResponse = new DatagramPacket( buffer, buffer.length);
client.receive(serverResponse);
sound_buffer.write(buffer);
}
byte[] encoded_sound = sound_buffer.toByteArray();
byte[] decoded_sound = new byte[2*encoded_sound.length];
byte msnibble = (byte)((encoded_sound[0]>>4) & 0x000F);
decoded_sound[0] = (byte)(msnibble - 8);
byte lsnibble = (byte)(encoded_sound[0] & 0x000F );
decoded_sound[1] = (byte) (decoded_sound[0] + lsnibble - 8);
for(int i=1;i<encoded_sound.length;i++){
msnibble = (byte)((encoded_sound[i] >> 4) & 0x000F);
decoded_sound[2*i] = (byte)(decoded_sound[2*i-1] + msnibble - 8);
lsnibble = (byte)(encoded_sound[i] & 0x000F );
decoded_sound[2*i+1] = (byte)(decoded_sound[2*i] + lsnibble - 8);
}
AudioFormat DPCM = new AudioFormat(8000,8,1,true,false);
SourceDataLine lineOut=AudioSystem.getSourceDataLine(DPCM);
lineOut.open(DPCM,decoded_sound.length);
lineOut.start();
lineOut.write(decoded_sound,0,decoded_sound.length);
问题是您给 SourceDataLine
8 位音频并告诉它像 16 位音频一样播放。这将使播放时间减半(因为每个样本使用两倍的位数)。它还使用用于声音的实际数字做一些奇怪的事情,但我不确定是什么(我没有测试你的例子。)
AudioFormat
不会格式化音频,它会告诉 SourceDataLine
您的音频当前是如何格式化的,以便正确播放。
我不太确定您想做什么,我想这取决于您想要 16 位音频的原因。您可能需要从服务器请求 16 位音频而不是 8 位音频,或者您甚至可能不需要 16 位音频。