2010-04-21 20 views
9

¿hay un tipo de datos integral primitivo de 24 bits en C++?int24 - tipo de datos integral de 24 bits

Si no hay ninguno, ¿sería posible crear una clase int24 (, uint24)?

su propósito podría ser:
* manipular archivos de sonido en formato de 24 bits
* manipular BitmapData sin alphachannel

muchas gracias de antemano

Vaya

Respuesta

12

escribí esto a mí ayudar con audio manipulación. No es el más rápido, pero a mí me funciona :)

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

esto se ve muy bien, gracias. también tiene operadores de cambio de bit, ¡gran cosa! 1 pregunta: ¿cómo usar la clase para almacenar los datos en a, o para leer desde una secuencia? ¿sería posible usar el operador << and >> también? – OlimilOops

+0

@Oops: Creo que no, ya que hay dos posibles conversiones implícitas de Int24 - para int y para flotar, y el compilador no tiene forma de elegir qué lanzamiento realizar, y luego usa el resultado con 'ostream :: operator << '. Pero puede agregar fácilmente operadores << and >> para ostreams y se distribuye usted mismo ... – conio

+0

Como conio dice que si desea soporte de transmisión necesitará agregar las implementaciones usted mismo. Aunque no es particularmente difícil :) – Goz

1

No - todo lo que realmente puede hacer es:

typedef int32_t int24_t; 

que ayuda a hacer que el código/la intención más legible/obvio, pero no lo hace impone límites en el rango o espacio de almacenamiento.

+0

gracias por su publicación. Pero no sería muy comsumable de memoria al leer un archivo enorme? porque el audio en bruto de 24 bits es muy grande. – OlimilOops

+1

@Oops: es probable que desee descomprimir su 24 datos de bit a 32 bit cuando lo leyó, de lo contrario tendrá que empaquetar/desempaquetar muestras en límites desalineados sobre la marcha. La única razón para mantener los datos en su forma empaquetada sería si usted fue * realmente * presionado para la memoria. –

+0

La mejor razón para dejar los Sounddata empaquetados tal como están, es simplemente reproducir el sonido, ¿no es así? – OlimilOops

18

Según los requisitos, utilizaría un campo de bits para ello.

struct int24{ 
    unsigned int data : 24; 
}; 

O, si una separación es más fácil, solo use 3 bytes (caracteres).

Por cierto, ambos casos de uso que mencionas en la pregunta generalmente usan enteros de 32 bits. En el caso del procesamiento de audio generalmente se convertirá a 32 bits (o flotantes, preferiblemente, para evitar situaciones de desbordamiento que obtendría con un punto fijo o matemáticas enteras) al cargar en fragmentos de audio porque no va a tener todo el archivo en la memoria a la vez.

Para datos de imagen, la gente tiende a usar enteros de 32 bits e ignorar los alfa 8 bits alfa en total, o si se trata de un formato compacto, es mejor que simplemente manipularlos como char-pointers de todos modos porque tendrás todos los canales separados. Va a ser una compensación de rendimiento/memoria de todos modos porque escribir un int es generalmente más rápido que tres caracteres por separado; sin embargo, llevará un 25% más de memoria.

Estructuras de embalaje como esta es específica del compilador. Sin embargo, en Visual Studio haría lo siguiente para hacer que la estructura sea exactamente de 24 bits.

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

todavía estaría acolchada a 32bits en la mayoría de los casos. – nothrow

+1

La mayoría de los compiladores le permiten desactivar el relleno para habilitar estos formatos muy compactos. –

+0

¿podría explicar cómo "desactivar el relleno"/"crear una estructura empaquetada"? tal vez podría modificar su código – OlimilOops

4

Trabajar con algo más pequeño que un entero (32 o 64 bits según su arquitectura) no es ideal. Todas las operaciones de CPU de los tipos de datos más pequeños (cortos, etc.) se realizan usando aritmética de enteros. La conversión hacia y desde la CPU tiene que hacerse, reduciendo la velocidad de su aplicación (incluso si solo es un poco).

Mi consejo: Guárdelos como enteros de 32 (o 64 bits) para mejorar su velocidad general. Cuando llega el momento de hacer I/O, tendrá que hacer la conversión usted mismo.

En cuanto a la manipulación de datos de audio, hay muchas bibliotecas disponibles que se encargan de las E/S, a menos que desee comenzar a aprender cómo se almacenan PCM, etc., así como otras funciones DSP. Sugeriría usar una de las muchas bibliotecas que hay.

Cuestiones relacionadas