2011-01-10 15 views
7

Ich habe ein Array von PCM-Daten, könnte es 16 Bit, 24 Bit gepackt, 32 Bit, etc .. Es könnte unterzeichnet werden, oder unsigniert, und es könnte 32 oder 64 Bit Fließkomma sein. Es wird derzeit als eine "void **" - Matrix gespeichert, indiziert nach Kanal und dann nach Rahmen. Das Ziel ist es, meiner Bibliothek zu erlauben, irgendein PCM-Format aufzunehmen und zu puffern, ohne dass die Daten manipuliert werden müssen, um zu einer bestimmten Struktur zu passen. Wenn der A/D-Wandler 24 Bit gepackte Arrays von verschachteltem PCM ausspuckt, muss ich dies elegant akzeptieren. Ich muss auch 16 Bit non-interleaved, sowie jede Permutation der oben genannten Formate unterstützen.Void * Array-Casting zu float, int32, int16 usw.

Ich kenne die Bittiefe und andere Informationen zur Laufzeit, und ich versuche, Code effizient zu duplizieren, ohne Code zu duplizieren. Was ich brauche, ist eine effektive Möglichkeit, die Matrix zu übertragen, PCM-Daten in die Matrix einzufügen und sie später wieder herauszuziehen.

Ich kann die Matrix zu int32_t, oder int16_t für die 32 und 16 Bit vorzeichenbehafteten PCM jeweils zu werfen, muss ich wahrscheinlich auch die 24-Bit-PCM in einem Int32_t für 32-Bit, 8-Bit-Byte-Systeme speichern.

Kann jemand eine gute Möglichkeit empfehlen, Daten in dieses Array zu legen und später herauszuziehen? Ich möchte große Teile des Codes zu vermeiden, die wie folgt aussehen:

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

Einschränkungen: Ich arbeite in C/C++, ohne Vorlagen, ohne RTTI, ohne STL. Denk eingebettet. Schwieriger wird es, wenn ich dies auf einen DSP mit 16 Bit Bytes portieren muss.

Hat jemand irgendwelche nützliche Makros, die sie vielleicht teilen möchten?

Danke,

-Griff

+4

Ich hätte gedacht, dass dies genau die Problemvorlagen sollten lösen. Ist die "keine Vorlagen" -Ding eine Einschränkung Ihrer Toolchain, eine andere Einschränkung des Projekts oder nur eine persönliche Vorliebe? –

+2

Was machen Sie mit den Daten? Es ist nicht klar aus der Frage, dass Sie tatsächlich das Casting überhaupt tun müssen, wenn Sie nur die Rohdaten puffern und später übergeben. – Kylotan

+2

@Anon, vorausgesetzt das OP akzeptiert nicht einmal replizierte Syntax durch bedingte Verzweigung bewacht, würde ich wahrscheinlich erraten, die ausführbare Größe Angelegenheit rote Flagge auf Vorlagen zu erhöhen. (da Template-Funktionen zu größeren ausführbaren Dateien führen als switch ... case) – YeenFei

Antwort

5

Dieser wird Typcodes zu Casting-Funktionen entsprechen. Die Grundidee besteht darin, dass es für jeden Typ und für ein Array von Funktionszeigern einen Satz winziger Konvertierungsfunktionen erstellt und dann auf der Grundlage des Datenformats in dieses Array indiziert, um die korrekte Konvertierungsfunktion zum Aufrufen zu finden.

mit:

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

Header-Datei:

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

Hoffnung hilft

+0

War es weit von Ihrer Frage entfernt? Ist der Funktionsaufruf auf Ihrer Plattform effizient genug? – ch0kee

+0

Das ist ... Genie. Ich brauchte eine Weile, um zu verstehen, was Sie hier tun, aber es sieht auf den ersten Blick genau das aus, was ich brauche. Mit ein wenig Fingerspitzengefühl kann ich diese Funktionen sogar verwenden, um Daten in die PCM-Matrix zu bringen. Das ist absolut erstaunlich. Der coole Teil ist, dass dies mit den Gleitkommatypen sowie den Int-Typen funktionieren sollte. Danke vielmals! – Griffin

+0

Ich habe dies bearbeitet, um eine kurze Beschreibung der Lösung an der Spitze hinzuzufügen, da (wie Griffin bemerkt) es nicht sofort einfach aus dem Code zu verstehen ist. Hoffe, Sie haben nichts dagegen - ich denke, es ist eine ausgezeichnete Antwort. –

Verwandte Themen