Java 通过SourceDataLine.write播放声音-如何使用字节[]-具有双值的缓冲区

Java 通过SourceDataLine.write播放声音-如何使用字节[]-具有双值的缓冲区,java,audio,buffer,javasound,Java,Audio,Buffer,Javasound,对于如何使用Java的SourceDataLine.write()-方法中的byte[]-缓冲区,我有点困惑:在我的程序中,我试图生成音频数据,并通过SourceDataLine播放。但是,我正在生成双值,我对一个样本使用了4个字节(我的音频格式:新的音频格式(8000f,32,1,true,true)) 将一个double转换为四个bytes(/“播放”一个double)的最佳方法是什么 [PS:32 bis的样本大小适合正常的音频播放吗?]链接的答案非常详细,但我将回答您的直接问题。首先,我

对于如何使用Java的
SourceDataLine.write()
-方法中的
byte[]
-缓冲区,我有点困惑:在我的程序中,我试图生成音频数据,并通过SourceDataLine播放。但是,我正在生成
双值
,我对一个样本使用了4个字节(我的
音频格式
新的音频格式(8000f,32,1,true,true)

将一个
double
转换为四个
byte
s(/“播放”一个double)的最佳方法是什么


[PS:32 bis的样本大小适合正常的音频播放吗?]

链接的答案非常详细,但我将回答您的直接问题。首先,我假设您的双精度值在-1.0到1.0之间。这是典型的设置。要转换为32位有符号整数,需要进行缩放,使1.0变为0x7fffffff,-1.0变为0x80000001,这可以通过简单的乘法完成

int sampleInt = sampleDouble * 0x7fffffff;
接下来,需要将整数拆分为字节:

byte[0] = (byte)((sampleInt >> 24) & 0xff);
byte[1] = (byte)((sampleInt >> 16) & 0xff);
byte[2] = (byte)((sampleInt >> 8)  & 0xff);
byte[3] = (byte)((sampleInt >> 0)  & 0xff);

根据输出的尾数,您可能需要交换订单。

相关:。虽然我的答案通常是关于将字节转换为样本,但有一个代码示例显示了您的要求。另一种常见的方法是使用
java.nio.ByteBuffer/java.nio.DoubleBuffer
。32位的采样大小与音频的大小差不多,但8kHz的采样率非常糟糕。8kHz将频率范围限制在4kHz以下,这通常仅适用于语音(VOIP/电话)。作为参考,16位编码,每秒44100帧,通常称为“CD质量”。对于立体声,即每帧四个字节(两个短字符)。拥有两倍的位无法补偿如此低的采样率。(强化Radiodef对质量的评论)你为什么要分裂?对我来说,用
Integer.MAX\u VALUE
相乘并使用
AudioFormat.Encoding.PCM\u Signed
会更直观。很抱歉,这是个错误。我将编辑答案。您可以自由使用Integer.MAX_值,但它实际上取决于最终位深度。正确的乘法器是2^(numBits-1)-1,在32位的情况下,它恰好是Integer.MAX_值。