2011-01-10 15 views
7

Tengo una serie de datos PCM, podría ser de 16 bits, 24 bits, 32 bits, etc. Podría estar firmado, o no, y podría ser un punto flotante de 32 o 64 bits. Actualmente se almacena como una matriz "vacía **", indexada por canal, luego por marco. El objetivo es permitir que mi biblioteca tome cualquier formato PCM y lo guarde, sin que sea necesario manipular los datos para que se ajusten a la estructura designada. Si el convertidor A/D escupe matrices empaquetadas de 24 bits de PCM intercalado, necesito aceptarlo con gracia. También necesito admitir 16 bits no intercalados, así como cualquier permutación de los formatos anteriores.Void * selección de matriz para flotar, int32, int16, etc.

Conozco la profundidad de bits y otra información en tiempo de ejecución, y estoy intentando codificar de manera eficiente sin duplicar el código. Lo que necesito es una forma efectiva de lanzar la matriz, poner datos de PCM en la matriz y luego extraerla más tarde.

puedo echar la matriz a int32_t o int16_t para el 32 y 16 bits con signo PCM, respectivamente, que probablemente tendrá que almacenar el PCM de 24 bits en un int32_t de 32 bits, los sistemas de bytes de 8 bits también.

¿Alguien puede recomendar una buena manera de poner datos en este conjunto, y sacarlo más tarde? Me gustaría evitar grandes secciones de código que se parecen:

switch(mFormat) 
{ 
case 1: // unsigned 8 bit 
    for(int i = 0; i < mChannels; i++) 
    framesArray = (uint8_t*)pcm[i]; 
    break; 
case 2: // signed 8 bit 
    for(int i = 0; i < mChannels; i++) 
    framesArray = (int8_t*)pcm[i]; 
    break; 
case 3: // unsigned 16 bit 
... 

Limitaciones: Estoy trabajando en C/C++, no hay plantillas, sin RTTI, sin STL. Piensa incrustado Las cosas se vuelven más complicadas cuando tengo que portar esto a un DSP con bytes de 16 bits.

¿Alguien tiene alguna macro útil que puedan estar dispuestos a compartir?

Gracias,

-Griff

+4

yo habría pensado que esto es exactamente se suponía que las plantillas problema a resolver. ¿La cosa "sin plantillas" es una limitación de su cadena de herramientas, alguna otra restricción en el proyecto, o simplemente una preferencia personal? –

+2

¿Qué haces con los datos? No está claro en la pregunta que realmente necesites hacer el casting si todo lo que haces es almacenar los datos en bruto y entregarlos después. – Kylotan

+2

@Anon, dado que el OP ni siquiera acepta la sintaxis replicada protegida por una rama condicional, probablemente creo que el asunto del tamaño del archivo ejecutable es levantar la bandera roja en las plantillas. (dado que la función de plantillas da como resultado ejecutables más grandes que el interruptor ... caso) – YeenFei

Respuesta

5

Ésta coincidirá typecodes a funciones de conversión. La idea básica es que crea un conjunto de pequeñas funciones de conversión para cada tipo, y una matriz de punteros a función, y luego indexa en esa matriz en función del formato de datos para encontrar la función de conversión correcta para llamar.

usando: archivo

int main() 
{ 
    void** pcm; 
    int currentChannel; 
    int currentFrame; 
    int mFormat; 

    //gets data casted to our type 
    STORETYPE translatedFrameData = GET_FRAMEDATA(pcm, currentChannel, currentFrame, mFormat); 

    return 0; 
} 

cabecera:

// this is a big type, we cast to this one 
#define STORETYPE int32_t 

// these functions get a single frame 
typedef STORETYPE (*getterFunction)(void**, int, int); 

// this macros make an array that maps format codes to cast functions 
#define BEGIN_RESERVE_FORMAT_CODES getterFunction __getter_array[] = { 
#define RESERVE_FORMAT_CODE(code) __get__##code##__, 
#define END_RESERVE_FORMAT_CODES }; 

// 
#define FORMAT_DEFINITION(code, format) STORETYPE __get__##code##__(void**pcm, int channel, int frame) \ 
{ return (STORETYPE) ((format**)pcm)[channel][frame]; } 

// get corresponding function 
#define GET_FRAMEDATA(pcm, channel, frame, format) __getter_array[format](pcm,channel,frame) 

//serious part, define needed types 
FORMAT_DEFINITION(0, uint8_t) 
FORMAT_DEFINITION(1, int8_t) 
FORMAT_DEFINITION(2, uint16_t) 
FORMAT_DEFINITION(3, int16_t) 

//actually this makes the array which binds types 
BEGIN_RESERVE_FORMAT_CODES 
    RESERVE_FORMAT_CODE(0) 
    RESERVE_FORMAT_CODE(1) 
    RESERVE_FORMAT_CODE(2) 
    RESERVE_FORMAT_CODE(3) 
END_RESERVE_FORMAT_CODES 

//WATCH OUT FOR SEQUENCE 

esperanza ayuda

+0

¿Estaba lejos de su pregunta? ¿La función de llamada es lo suficientemente eficiente en su plataforma? – ch0kee

+0

Eso es ... Genio. Me tomó un tiempo entender completamente lo que estás haciendo aquí, pero _ALTAVOZ_ a primera vista es exactamente lo que necesito. Con un poco de manipulación, incluso puedo usar estas funciones para poner datos en la matriz pcm. Esto es absolutamente increíble. Lo bueno es que esto debería funcionar con los tipos de punto flotante, así como con los tipos int. ¡Gracias una tonelada! – Griffin

+0

Lo edité para agregar una descripción concisa de la solución en la parte superior, ya que (como señala Griffin) no es inmediatamente fácil de entender solo desde el código. Espero que no te importe, creo que es una respuesta excelente. –