Void * приведение массива к float, int32, int16 и т. Д. - PullRequest
7 голосов
/ 10 января 2011

У меня есть массив данных PCM, он может быть 16-битным, 24-битным упакованным, 32-битным и т. Д. Он может быть со знаком или без знака, и это может быть 32- или 64-битная с плавающей запятой.В настоящее время он хранится в виде матрицы «void **», индексируется по каналу, а затем по кадру.Цель состоит в том, чтобы моя библиотека могла использовать любой формат PCM и буферизовать его, не требуя манипулирования данными для соответствия назначенной структуре.Если аналого-цифровой преобразователь выдает 24-битные массивы чередующихся PCM, я должен принять это изящно.Мне также нужно поддерживать 16-битное без чередования, а также любую перестановку вышеуказанных форматов.

Я знаю битовую глубину и другую информацию во время выполнения, и я пытаюсь эффективно кодировать, не дублируя код.Мне нужен эффективный способ приведения матрицы, помещения данных PCM в матрицу и последующего извлечения их позже.

Я могу привести матрицу к int32_t или int16_t для 32-битной и 16-битной подписанной PCMсоответственно, мне, вероятно, придется хранить 24-битную PCM в int32_t для 32-битных и 8-битных систем.

Может кто-нибудь порекомендовать хороший способ поместить данные в этот массив и извлечь его?потом?Я хотел бы избежать больших разделов кода, которые выглядят следующим образом:

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
...

Ограничения: я работаю на C / C ++, нет шаблонов, нет RTTI, нет STL.Думай встраивай.Все становится сложнее, когда мне нужно перенести это на DSP с 16-битными байтами.

Есть ли у кого-нибудь полезные макросы, которыми он мог бы поделиться?

Спасибо,

-Griff

1 Ответ

5 голосов
/ 10 января 2011

Этот тип будет соответствовать типам для функций приведения. Основная идея состоит в том, что он создает набор крошечных функций преобразования для каждого типа и массив указателей функций, а затем индексирует в этот массив на основе формата данных, чтобы найти правильную функцию преобразования для вызова.

с помощью:

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;
}

заголовочный файл:

// 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

надежда помогает

...