2014-02-18 109 views
0

已經搜索了兩天的解決方案。 我想將32位或24位波形轉換爲16位。閱讀數計算器主題後如何從32位/ 24位從字節到16位轉換爲字節

這是我的代碼):

byte[] data = Convert.FromBase64String("-- Wav String encoded --") (32 or 24 bits) 
int conv = Convert.ToInt16(data); 
byte[] intBytes = BitConverter.GetBytes(conv); 
if (BitConverter.IsLittleEndian) 
    Array.Reverse(intBytes); 
byte[] result = intBytes; 

但是當我writeAllbyte我的結果,沒有聽到......

+0

這是因爲您將數組對象轉換爲一個'short',然後將其轉換爲'int'。如果樣本太大以至'int16'無法保存數據,您希望如何轉換?你想切斷最不重要的位?然後你只需要在輸入數據中拋出這些字節。無需「轉換」。 –

+0

謝謝你的參加。我沒有經驗的位和字節...我讀過你並在互聯網上搜索如何刪除LSB,但沒有太多關於它...而你說,你告訴我,我的Convert.toInt16是不需要的這裏?但是,如何將32b轉換爲16呢? – snakelecaps

+0

如果要將32位轉換爲16位,則必須進行折衷。對於聲音數據來說,放寬一些精度可能是合理的。精度存儲在最低有效位中。所以我們可以拋棄它們(假設其他位中還有一些數據,並且沒有其他編碼,如差分等)。因此,要將32位轉換爲16位,需要2個字節,跳過2個字節,直到您位於數組的末尾。對於24到16位需要2個字節,跳過1個字節。用這個過程構造一個新的數組,或者使用一個列表來移除元素(更方便,但效率更低)。 –

回答

0

這裏是切割至少顯著位的方法:

byte[] data = ... 
var skipBytes = 0; 
byte[] data16bit; 
int samples; 
if(/* data was 32 bit */) { 
    skipBytes = 2; 
    samples = data.Length/4; 
} else if(/* data was 24 bit */) { 
    skipBytes = 1; 
    samples = data.Length/3; 
} 
data16bit = new byte[samples * 2]; 
int writeIndex = 0; 
int readIndex = 0; 
for(var i = 0; i < samples; ++i) { 
    readIndex += skipBytes; //skip the least significant bytes 
    //read the two most significant bytes 
    data16bit[writeIndex++] = data[readIndex++]; 
    data16bit[writeIndex++] = data[readIndex++]; 
} 

這假定一個小端字節順序(至少顯著字節是第一個字節,通常爲WAV RIFF)。如果你有大的字節序,你必須在兩條讀取行之後加上readIndex += ...

您可以實現這個任務你自己的轉換迭代器,像這樣:

IEnumerable<byte> ConvertTo16Bit(byte[] data, int skipBytes) 
{ 
    int bytesToRead = 0; 
    int bytesToSkip = skipBytes; 
    int readIndex = 0; 
    while (readIndex < data.Length) 
    { 
     if (bytesToSkip > 0) 
     { 
      readIndex += bytesToSkip; 
      bytesToSkip = 0; 
      bytesToRead = 2; 
      continue; 
     } 
     if (bytesToRead == 0) 
     { 
      bytesToSkip = skipBytes; 
      continue; 
     } 
     yield return data[readIndex++]; 
     bytesToRead--; 
    } 
} 

這樣,您就不必創建一個新的數組,如果沒有必要的。你可以在數據陣列簡單地轉換到一個新的16位陣列與IEnumerable<T>擴展方法:

var data16bit = ConvertTo16Bit(data, 1).ToArray(); 

或者,如果你不需要的數組,你可以遍歷數據跳過至少顯著字節:

foreach (var b in ConvertTo16Bit(data, 1)) 
{ 
    Console.WriteLine(b); 
} 
+0

感謝您的幫助。我明白你的解釋和代碼。只有一個問題,寫入的新數據不會播放聲音:-(...所以... – snakelecaps

+0

嘿,我想出了當我把'skipBytes = 0'寫入的數據以較低長度(音樂)播放時, 。文件的大小較低,但是質量似乎是一樣的......用較少的聲音 – snakelecaps

+0

你是否已將波頭改爲16位? –