2010-08-12 49 views
3

我需要重複將1024個連續的4字節浮點數(範圍-1至1)轉換爲2字節短路(範圍-32768至32767)並寫入磁盤。將範圍-1的浮點數轉換爲1的快速方法?

目前,我這樣做有一個循環:

short v = 0; 
for (unsigned int sample = 0; sample < length; sample++) 
{ 
    v = (short)(inbuffer[sample * 2] * 32767.0f); 
    fwrite(&v, 2, 1, file); 
} 

而這個工作,但浮點計算和循環是昂貴的。有什麼辦法可以優化?

+2

警告:如果-1.0轉換爲-32768且0.0轉換爲0,那麼+1.0應轉換爲+32768,這不在「短」範圍內。 – mouviciel 2010-08-12 09:32:20

+0

也許OP的意思是「從-1直到但不包括1」。即便如此,浮點舍入錯誤也會造成麻煩。也許最好將計算暫時保存在一個'int'中,然後在將其存儲在'float'中之前檢查它的值。 – David 2010-08-12 09:34:47

+0

好點,-32767至32767應該沒問題。 – Morrowless 2010-08-12 09:41:08

回答

6
short v = 0; 
for (unsigned int sample = 0; sample < length; sample++) 
{ 
    v = (short)(inbuffer[sample * 2] * 32767.0f); 
    // The problem is not here-------^^^^^^^^^^^ 
    fwrite(&v, 2, 1, file);   
    // it is here ^^^^^^^ 
} 

一個典型的Mac(?Objective-C的標籤,還是我們談論iPhone在這裏)可以做每秒數十億次浮點乘法。然而,fwrite是一個庫調用,它遵循一些間接指令將其數據寫入某個緩衝區並可能將其刷新。這是更好地填寫自己的緩衝區中的批次:

short v[SZ] = 0; 
// make sure SZ is always > length, or allocate a working buffer on the heap. 
for (unsigned int sample = 0; sample < length; sample++) 
{ 
    v[sample] = (short)(inbuffer[sample * 2] * 32767.0f); 
} 
fwrite(v,sizeof(v),1,file); 
2

我原以爲重複撥打fwrite將是昂貴的部分。如何:

short outbuffer[length]; // note: you'll have to malloc this if length isn't constant and you're not using a version of C that supports dynamic arrays. 
for (unsigned int sample = 0; sample < length; sample++) 
{ 
    outbuffer[sample] = (short)(inbuffer[sample * 2] * 32767.0f); 
} 
fwrite(outbuffer, sizeof *outbuffer, length, file); 
+0

即使他有動態數組,如果在不知道大小限制的上下文中使用它們,也不是一個好主意。當心堆棧溢出。 – 2010-08-12 11:59:39

2

我想,你的循環的瓶頸可能不是短期浮動轉換,但輸出寫入到文件 - 嘗試移動文件輸出迴路

short v = 0; 
short outbuffer = // create outbuffer of required size 
for (unsigned int sample = 0; sample < length; sample++) 
{ 
    outbuffer[sample] = (short)(inbuffer[sample * 2] * 32767.0f); 
} 

fwrite(outbuffer, 2, sizeof(outbuffer), file); 
0

你可以嘗試這樣的事:

out[i] = table[((uint32_t *)in)[i]>>16]; 

其中table是一個IEEE浮點的高16位映射到查找表你想要的價值。但是,這會失去一些精確度。您需要保留並使用23位(1個符號位,8個指數位和14個尾數位)以獲得完全精度,這意味着一個16 MB的表,這將消除高速緩存一致性和性能。

您確定浮點轉換速度很慢嗎?只要你以這種方式使用fwrite,那麼你在fwrite中花費的CPU時間就是浮點運算的50-100倍。如果你處理這個問題並且代碼仍然太慢,你可以使用一種方法來增加一個魔術偏差並讀取尾數位以轉換爲int16_t而不是乘以32767.0。這可能會或可能不會更快。

相關問題