2014-02-05 562 views
1

我有一個聲音文件,我正在練習相位聲碼。我已將文件的字節轉換爲double [],並通過快速傅里葉變換和快速傅立葉逆變換來處理該文件的波形。現在的問題是我需要將byte []轉換回double。下面是一些有用的代碼片段:Java如何將包含多個雙精度的byte []轉換爲雙精度[]

我如何在第一時間轉換的數據:

/** 
* 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; 
} 

和我在做什麼的數據:

public static byte[] shift(byte[] data, int factor){ 
    double[] audioData = bytesToDoubleArray(data); 
    audioData = Arrays.copyOf(audioData, roundToPowerOf2(audioData.length)); 
    Complex[] transformed = FFT.fft(doubleToComplex(audioData)); 
    transformed = shiftArray(transformed, 3); 
    Complex[] reverted = FFT.ifft(transformed); 
    for(int i = 0; i<reverted.length; i++){ 
     audioData[i] = reverted[i].re(); 
    } 
    return null;//How do I convert audioData[] back into a byte[]???? 
} 

如何彌補任何想法這個問題?任何解決方案將不勝感激。另外任何已經實現相位聲碼處理的Java庫都會非常棒。

+2

查找到'ByteBuffer'的序列,而不是序列。 –

+0

您可以通過閱讀Double的規範來完成。 –

+0

但是你沒有轉換字節<=>雙倍,你有效地轉換字節<=>整數並將整數轉換爲雙精度。如果使用相同的方案將雙重結果轉換回字節,您將失去一些重要意義。 –

回答

2

大約在這裏。我確信我搞砸了。 scaleFactor大概是327.68,以扭轉上面的縮放比例。上面的代碼看起來很大。你是否想要f​​ullNormalize取決於你。

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; 
     } 
    } 
} 

更新時間:意識到我需要考慮的標準化比例因子。而且通常不會指定不是1.0的scaleFactorfullNormalize = true

0

就像您從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; 
} 

這當然假定double[]陣列中的數據可以被存儲在一個陣列byte[]無需進一步轉換/縮放。否則,複製時需要注意。

+0

對於有3-4個字節的意義的情況,不會很好地工作,是嗎? –

+0

這就是爲什麼我提到進一步的轉換/縮放可能會或可能不需要取決於應用程序。我的任務不是質疑OP的動機 - 我只是回答實際問題。 – Grodriguez

1

這取決於您將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(); 

有效上述方法並沒有轉換什麼,但你只是解釋字節流的字節雙

+1

如果讀取原始代碼,則將N個整數(其中N是可變的)字節轉換爲一個雙精度值,並且大概需要將雙精度值轉換回每個N整數字節。它不是簡單地將雙打映射到字節緩衝區中。 –