Java如何将包含多个double的字节[]转换为double[]

Java如何将包含多个double的字节[]转换为double[],java,arrays,casting,signal-processing,fft,Java,Arrays,Casting,Signal Processing,Fft,我有一个声音文件,我正在练习阶段声码。我已经将文件的字节转换为double[],并通过快速傅立叶变换和快速傅立叶逆变换处理该文件的波形。现在的问题是,我需要将字节[]转换回双精度。以下是一些有用的代码片段: 首先,我是如何转换数据的: /** * Converts bytes from a TargetDataLine into a double[] allowing the information to be read. * NOTE: One byte is lost in the co

我有一个声音文件,我正在练习阶段声码。我已经将文件的字节转换为double[],并通过快速傅立叶变换和快速傅立叶逆变换处理该文件的波形。现在的问题是,我需要将字节[]转换回双精度。以下是一些有用的代码片段:

首先,我是如何转换数据的:

/**
 * Converts bytes from a TargetDataLine into a double[] allowing the information to be read.
 * NOTE: One byte is lost in the conversion so don't expect the arrays to be the same length!
 * @param bufferData The buffer read in from the target Data Line
 * @return the double[] that the buffer has been converted into.
 */
   private static double[] bytesToDoubleArray(byte[] bufferData){
    final int bytesRecorded = bufferData.length;
    final int bytesPerSample = getAudioFormat().getSampleSizeInBits()/8; 
    final double amplification = 100.0; // choose a number as you like
    double[] micBufferData = new double[bytesRecorded - bytesPerSample + 1];
    for (int index = 0, floatIndex = 0; index < bytesRecorded - bytesPerSample + 1; index += bytesPerSample, floatIndex++) {
        double sample = 0;
        for (int b = 0; b < bytesPerSample; b++) {
            int v = bufferData[index + b];
            if (b < bytesPerSample - 1 || bytesPerSample == 1) {
                v &= 0xFF;
            }
            sample += v << (b * 8);
        }
        double sample32 = amplification * (sample / 32768.0);
        micBufferData[floatIndex] = sample32;

    }
    return micBufferData;
}
/**
*将TargetDataLine中的字节转换为允许读取信息的双精度[]。
*注意:转换过程中丢失了一个字节,因此不要期望数组的长度相同!
*@param bufferData从目标数据行读入的缓冲区
*@返回缓冲区已转换为的双精度[]。
*/
专用静态双精度[]ByTestToDoublearray(字节[]缓冲数据){
最终int字节记录=bufferData.length;
final int bytesPerSample=getAudioFormat().getSampleSizeInBits()/8;
最终双放大=100.0;//根据需要选择一个数字
double[]micBufferData=新的double[bytesRecorded-bytesPerSample+1];
for(int index=0,floatIndex=0;indexsample+=v正如您从
byte[]
转换为
double[]
时所做的那样,您现在需要转换回
byte[]
。只需创建一个新的
byte[]
数组并手动从
double[]
数组复制数据:

private static byte[] doublesToByteArray(double[] a) {
    int len = a.length;
    byte[] b = new byte[len];
    for (int i = 0; i < len; i++)
        b[i] = (byte) a[i];
    return b;
}
private static byte[]doublesToByteArray(double[]a){
int len=a.长度;
字节[]b=新字节[len];
对于(int i=0;i

当然,这假定
double[]
数组中的数据可以存储在
字节[]中
数组,无需进一步转换/缩放。否则,您在复制时需要注意这一点。

大致就是这样。我肯定我搞错了。scaleFactor应该是327.68,以反转上面的缩放。上面的代码似乎是big-endian。是否要完全规范化取决于您自己

public byte[] doubleArrayToByteArray(double[] input, int bytesPerSample, double scaleFactor, boolean fullNormalize, boolean bigEndian) {
    byte[] result = new byte[input.length * bytesPerSample];
    performNormalization(input, scaleFactor, fullNormalize);
    for (int i = 0; i < input.length; i++) {
        long sourceVal = (long)(input[i] * scaleFactor);
        sourceVal = sourceVal >> 8 * (8 - bytesPerSample);
        for (int j = 0; j < bytesPerSample; j++) {
            int index = i * bytesPerSample;
            if (bigEndian) {
                index += (bytesPerSample - j);
            }
            else {
                index += j;
            }
            result[index] = (byte) sourceVal;
            sourceVal = sourceVal >> 8;
        }
    }
    return result;
}

public void performNormalization(double[] input, double scaleFactor, boolean fullNormalize) {
    double maxVal = 0.0;
    for (int i = 0; i < input.length; i++) {
        double val = Math.abs(input[i]) * scaleFactor;
        if (val > maxVal) {
            maxVal = val;
        }
    }
    if (fullNormalize || maxVal > Long.MAX_VALUE) {
        double normalizeFactor = (double)(Long.MAX_VALUE) / maxVal;
        for (int i = 0; i < input.length; i++) {
            input[i] *= normalizeFactor;
        }
    }
}
public byte[]doubleArrayToByteArray(double[]输入,int bytesPerSample,double scaleFactor,boolean fullNormalize,boolean bigEndian){
字节[]结果=新字节[input.length*bytesPerSample];
执行规范化(输入、缩放因子、完全规范化);
for(int i=0;i>8*(8字节/样本);
对于(int j=0;j>8;
}
}
返回结果;
}
public void性能规范化(双[]输入、双scaleFactor、布尔fullNormalize){
双maxVal=0.0;
for(int i=0;imaxVal){
maxVal=val;
}
}
if(完全规格化| | maxVal>Long.MAX_值){
double normalizeFactor=(double)(Long.MAX_值)/maxVal;
for(int i=0;i

更新:意识到我需要在规范化中说明scaleFactor。通常,您不会同时指定不是1.0的
scaleFactor
fullNormalize=true
这取决于将double[]转换为byte[]的意思.回想一下,通常double的长度为8字节,而byte的长度为1字节

如果可以以某种方式将double转换为无符号整数0-255(或有符号-128-127),则只需将每个double转换为字节并将其分配给新数组,否则必须使用ByteBuffer:

int capacity = // calculate how much space you need for your byte array
ByteBuffer byteBuf = ByteBuffer(capacity);
for(double d : doubleArray) byteBuf.putDouble(d);
byte[] byteArray = byteBuf.array();

实际上,上述方法没有转换任何内容,但您只是将字节流解释为字节序列,而不是double序列

查看
ByteBuffer
。您可以通过读取double的规范来实现。但您并没有将字节转换为double,而是将字节转换为整数并将整数转换为整数如果你使用相同的方案将双精度结果转换回字节,你将失去一些意义。“失去一些意义”可能完全可以接受,具体取决于应用程序。今晚晚些时候给我安装Bug,我将(合理地)编写一个回答正确。如果有3-4个字节的重要值,那么这种情况不会很好地工作,是吗?这就是为什么我提到,根据应用程序的不同,进一步的转换/缩放可能是必要的,也可能不是。我的任务不是质疑OP的动机——我只是回答实际问题。如果你阅读原始代码,N个字节的teger(其中N是变量)被转换成一个双精度值,人们可能希望将每个双精度值转换回N个整数字节。
int capacity = // calculate how much space you need for your byte array
ByteBuffer byteBuf = ByteBuffer(capacity);
for(double d : doubleArray) byteBuf.putDouble(d);
byte[] byteArray = byteBuf.array();