2011-01-10 9 views
7

Mam szereg danych PCM, może to być 16-bitowy, 24-bitowy, 32-bitowy itp. Może on być podpisany lub unsigned, i może to być 32- lub 64-bitowy zmiennoprzecinkowy. Obecnie jest przechowywany jako macierz "void **", indeksowana według kanału, a następnie według ramki. Celem jest umożliwienie mojej bibliotece przyjęcia dowolnego formatu PCM i buforowanie go, bez konieczności manipulowania danymi w celu dopasowania do wyznaczonej struktury. Jeśli konwerter A/D wypuści 24-bitowe tablice przeplatanych PCM, muszę je przyjąć z wdziękiem. Muszę również obsługiwać 16-bitowe, niezawleczone, jak również dowolną permutację powyższych formatów.Void * array casting to float, int32, int16, itp.

Znam głębokość bitową i inne informacje w czasie wykonywania, a próbuję wydajnie kodować, a nie powielać kodu. Potrzebuję skutecznego sposobu rzucania matrycą, umieszczania danych PCM w macierzy, a następnie wyciągania jej później.

Mogę rzucić matrycę na int32_t, lub int16_t dla odpowiednio 32 i 16 bitowego sygnowanego PCM, prawdopodobnie będę musiał przechowywać 24-bitowe PCM w int32_t również dla 32-bitowych, 8-bitowych systemów.

Czy ktoś może polecić dobry sposób na umieszczenie danych w tej macierzy i wyciągnięcie go później? Chciałbym uniknąć dużych fragmentów kodu, który wygląda tak:

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

ograniczeń: Pracuję w języku C/C++, bez szablonów, bez RTTI, bez STL. Myśl osadzony. Sprawy stają się trudniejsze, gdy muszę przenieść to do DSP z 16-bitowymi bajtami.

Czy ktoś ma przydatne makra, które mogą być udostępniane?

Dzięki,

-Griff

+4

myślałem, że to jest dokładnie to, szablony miały problemów do rozwiązania. Czy "brak szablonów" jest ograniczeniem twojego toolchainu, innym ograniczeniem projektu, czy tylko osobistymi preferencjami? –

+2

Co robisz z danymi? Z tego pytania nie wynika wcale, że faktycznie musisz wykonać casting, jeśli wszystko, co robisz, to buforowanie surowych danych i późniejsze przekazanie. – Kylotan

+2

@Anon, biorąc pod uwagę, że OP nie akceptuje zreplikowanej składni chronionej przez gałąź warunkową, prawdopodobnie zgadłbym, że kwestia rozmiaru wykonywalnego podnosi czerwoną flagę na szablonach. (ponieważ funkcja templates powoduje większe pliki wykonywalne niż przełącznik ... case) – YeenFei

Odpowiedz

5

Ten będzie pasujących typecodes do odlewania funkcji. Podstawową ideą jest to, że tworzy on zestaw małych funkcji konwersji dla każdego typu i tablicę wskaźników funkcji, a następnie indeksuje do tej tablicy w oparciu o format danych, aby znaleźć właściwą funkcję konwersji do wywołania.

używając: plik

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

nagłówka:

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

nadzieja pomaga

+0

Czy to było dalekie od twojego pytania? Czy wywołanie funkcji jest wystarczająco skuteczne na twojej platformie? – ch0kee

+0

To ... Geniusz. Zajęło mi trochę czasu, aby w pełni zrozumieć, co tu robisz, ale to _LOOKS_ przy pierwszym wyświetleniu, aby być dokładnie tym, czego potrzebuję. Przy odrobinie fiddlingu, mogę nawet użyć tych funkcji do umieszczenia danych w matrycy pcm. To jest absolutnie niesamowite. Fajną częścią jest to, że powinno to działać z typami zmiennoprzecinkowymi, jak również z typami int. Dzięki TON! – Griffin

+0

Edytowałem to, aby dodać zwięzły opis rozwiązania na górze, ponieważ (jak zauważa Griffin), nie jest to od razu łatwe do zrozumienia właśnie z kodu. Mam nadzieję, że nie masz nic przeciwko - myślę, że to doskonała odpowiedź. –