2010-04-21 111 views
9

在C++中是否有24Bit原始積分數據類型?int24 - 24位積分數據類型

如果沒有,是否可以創建一個類int24(,uint24)?

它的目的可能是:
*,24位格式操縱聲音文件
*提前操縱的BitmapData沒有alpha通道

千恩萬謝

哎呀

回答

12

我寫這幫助我與音頻操縱。它不是最快的,但它爲我工作:)

const int INT24_MAX = 8388607; 

class Int24 
{ 
protected: 
    unsigned char m_Internal[3]; 
public: 
    Int24() 
    { 
    } 

    Int24(const int val) 
    { 
     *this = val; 
    } 

    Int24(const Int24& val) 
    { 
     *this = val; 
    } 

    operator int() const 
    { 
     if (m_Internal[2] & 0x80) // Is this a negative? Then we need to siingn extend. 
     { 
      return (0xff << 24) | (m_Internal[2] << 16) | (m_Internal[1] << 8) | (m_Internal[0] << 0); 
     } 
     else 
     { 
      return (m_Internal[2] << 16) | (m_Internal[1] << 8) | (m_Internal[0] << 0); 
     } 
    } 

    operator float() const 
    { 
     return (float)this->operator int(); 
    } 

    Int24& operator =(const Int24& input) 
    { 
     m_Internal[0] = input.m_Internal[0]; 
     m_Internal[1] = input.m_Internal[1]; 
     m_Internal[2] = input.m_Internal[2]; 

     return *this; 
    } 

    Int24& operator =(const int input) 
    { 
     m_Internal[0] = ((unsigned char*)&input)[0]; 
     m_Internal[1] = ((unsigned char*)&input)[1]; 
     m_Internal[2] = ((unsigned char*)&input)[2]; 

     return *this; 
    } 

    /***********************************************/ 

    Int24 operator +(const Int24& val) const 
    { 
     return Int24((int)*this + (int)val); 
    } 

    Int24 operator -(const Int24& val) const 
    { 
     return Int24((int)*this - (int)val); 
    } 

    Int24 operator *(const Int24& val) const 
    { 
     return Int24((int)*this * (int)val); 
    } 

    Int24 operator /(const Int24& val) const 
    { 
     return Int24((int)*this/(int)val); 
    } 

    /***********************************************/ 

    Int24 operator +(const int val) const 
    { 
     return Int24((int)*this + val); 
    } 

    Int24 operator -(const int val) const 
    { 
     return Int24((int)*this - val); 
    } 

    Int24 operator *(const int val) const 
    { 
     return Int24((int)*this * val); 
    } 

    Int24 operator /(const int val) const 
    { 
     return Int24((int)*this/val); 
    } 

    /***********************************************/ 
    /***********************************************/ 


    Int24& operator +=(const Int24& val) 
    { 
     *this = *this + val; 
     return *this; 
    } 

    Int24& operator -=(const Int24& val) 
    { 
     *this = *this - val; 
     return *this; 
    } 

    Int24& operator *=(const Int24& val) 
    { 
     *this = *this * val; 
     return *this; 
    } 

    Int24& operator /=(const Int24& val) 
    { 
     *this = *this/val; 
     return *this; 
    } 

    /***********************************************/ 

    Int24& operator +=(const int val) 
    { 
     *this = *this + val; 
     return *this; 
    } 

    Int24& operator -=(const int val) 
    { 
     *this = *this - val; 
     return *this; 
    } 

    Int24& operator *=(const int val) 
    { 
     *this = *this * val; 
     return *this; 
    } 

    Int24& operator /=(const int val) 
    { 
     *this = *this/val; 
     return *this; 
    } 

    /***********************************************/ 
    /***********************************************/ 

    Int24 operator >>(const int val) const 
    { 
     return Int24((int)*this >> val); 
    } 

    Int24 operator <<(const int val) const 
    { 
     return Int24((int)*this << val); 
    } 

    /***********************************************/ 

    Int24& operator >>=(const int val) 
    { 
     *this = *this >> val; 
     return *this; 
    } 

    Int24& operator <<=(const int val) 
    { 
     *this = *this << val; 
     return *this; 
    } 

    /***********************************************/ 
    /***********************************************/ 

    operator bool() const 
    { 
     return (int)*this != 0; 
    } 

    bool operator !() const 
    { 
     return !((int)*this); 
    } 

    Int24 operator -() 
    { 
     return Int24(-(int)*this); 
    } 

    /***********************************************/ 
    /***********************************************/ 

    bool operator ==(const Int24& val) const 
    { 
     return (int)*this == (int)val; 
    } 

    bool operator !=(const Int24& val) const 
    { 
     return (int)*this != (int)val; 
    } 

    bool operator >=(const Int24& val) const 
    { 
     return (int)*this >= (int)val; 
    } 

    bool operator <=(const Int24& val) const 
    { 
     return (int)*this <= (int)val; 
    } 

    bool operator >(const Int24& val) const 
    { 
     return (int)*this > (int)val; 
    } 

    bool operator <(const Int24& val) const 
    { 
     return (int)*this < (int)val; 
    } 

    /***********************************************/ 

    bool operator ==(const int val) const 
    { 
     return (int)*this == val; 
    } 

    bool operator !=(const int val) const 
    { 
     return (int)*this != val; 
    } 

    bool operator >=(const int val) const 
    { 
     return (int)*this >= val; 
    } 

    bool operator <=(const int val) const 
    { 
     return (int)*this <= val; 
    } 

    bool operator >(const int val) const 
    { 
     return ((int)*this) > val; 
    } 

    bool operator <(const int val) const 
    { 
     return (int)*this < val; 
    } 

    /***********************************************/ 
    /***********************************************/ 
}; 
+0

這看起來很不錯,謝謝。 你也有點經營者,好東西! 1問題:如何使用類來存儲數據或從流中讀取數據?是否也可以使用運營商? – OlimilOops 2010-04-21 12:33:51

+0

@Oops:我認爲不是,因爲Int24有兩種可能的隱式轉換 - int和float,編譯器沒有辦法選擇要執行哪個轉換,然後使用'ostream :: operator << '。但是,您可以輕鬆地自己添加運營商>以獲取自己的流量和流量... – conio 2010-04-21 13:23:29

+0

由於conio說如果您需要流支持,您需要自己添加實現。它不是特別困難,但:) – Goz 2010-04-21 13:25:55

1

否 - 所有你能做的,只能是:

typedef int32_t int24_t; 

這有助於使代碼/意圖更可讀/顯而易見的,但不對範圍或存儲空間施加任何限制。

+0

感謝您的文章,但讀的時候,豈不是很內存comsumable。一個巨大的文件?因爲24位原始音頻是非常巨大的。 – OlimilOops 2010-04-21 12:36:11

+1

@Oops:你可能想打開你的24當你讀到它時,你將需要在不對齊的邊界上打包/解壓縮樣本。將數據保存在打包表單中的唯一原因是,如果您真的被推送到內存中。 – 2010-04-21 16:14:42

+0

離開聲音數據的最佳原因就是播放聲音,不是嗎? – OlimilOops 2010-04-21 20:48:38

18

根據要求,我會使用它的位域。

struct int24{ 
    unsigned int data : 24; 
}; 

或者,如果分離更容易,只需使用3個字節(字符)。

順便說一句,你提到的兩個用例通常使用32位整數。在音頻處理的情況下,通常在加載大塊音頻時,將其轉換爲32位整數(或浮點數,最好是防止溢出情況下使用固定點或整數數學運算),因爲您不會有整個文件一次存儲在內存中。

對於圖像數據,人們只是傾向於使用32位整數,而忽略alpha 8 alpha位,或者如果你處理的是緊密壓縮格式,那麼你可能更好的操作它們作爲char指針無論如何因爲你將所有的渠道分開。無論如何,這將是一次性能/內存的折衷,因爲寫一個int通常比三個字符分開;但是它會佔用25%的內存。

像這樣的打包結構是編譯器特有的。但是,在Visual Studio中,您需要執行以下操作,使結構精確到24位。

#pragma pack(push, 1) 
struct int24{ 
    unsigned int data : 24; 
}; 
#pragma pack(pop) 
+3

在大多數情況下它仍然會被填充到32位。 – nothrow 2010-04-21 12:31:58

+1

大多數編譯器允許您關閉填充以啓用這些緊湊格式。 – 2010-04-21 12:50:42

+0

你能解釋一下如何「關閉填充」/「創建一個壓縮結構」?也許你可以修改你的代碼 – OlimilOops 2010-04-21 17:10:44

4

使用小於整數(32或64位,取決於您的架構)的任何內容都不理想。較小數據類型(短等)的所有CPU操作均使用整數算術完成。必須完成CPU和CPU之間的轉換,減慢應用程序的速度(即使它只是一時)。

我的建議:將它們存儲爲32位(或64位)整數,以提高整體速度。當需要做I/O時,您必須自己進行轉換。

就操縱音頻數據而言,有許多庫可用於爲您處理I/O - 除非您想開始學習如何存儲PCM等 - 以及其他DSP功能。我會建議使用其中的一個庫。