2011-01-10 10 views
7

私は16ビット、24ビットのパック、32ビットなどのPCMデータの配列を持っています。それは32または64ビット浮動小数点である可能性があります。これは、現在、チャンネルによって、次にフレームごとにインデックス付けされた「ボイド**」マトリックスとして格納されています。目標は、指定された構造に合わせてデータを操作することなく、私のライブラリが任意のPCM形式を取り込み、バッファリングできるようにすることです。 A/DコンバータがインターリーブされたPCMの24ビットのパックドアレイを吐き出したら、それを正常に受け入れる必要があります。私はまた、16ビットのインターリーブされていない、上記のフォーマットの任意の順列をサポートする必要があります。float、int32、int16などへのVoid *配列キャスト

私は実行時にビット深度などの情報を知っています。コードを複製しないで効率的にコードを作成しようとしています。私が必要とするのは、マトリックスをキャストし、PCMデータをマトリックスに入れ、それを後で取り出すという効果的な方法です。

32ビットと16ビットの符号付きPCMのそれぞれに対してint32_tまたはint16_tにキャストすることができますが、おそらくは32ビット、8ビットのバイトシステムでもint32_tに24ビットPCMを格納する必要があります。

誰もデータをこの配列に入れて後で引き出すことをお勧めしますか?

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で働いています。埋め込みを考えよう。これを16ビット・バイトのDSPに移植しなければならないと、処理が煩雑になります。

誰でも便利なマクロを共有してもらえますか?

おかげで、

+4

に役立ちます。 「テンプレートなし」のことは、あなたのツールチェーンの制限、プロジェクトに対する他の制限、または個人的な好みですか? –

+2

データはどうしていますか?あなたがしているのは、生のデータをバッファして後で取り除くだけであれば、実際にキャスティングを行う必要があるということは、疑問からは明らかではありません。 – Kylotan

+2

@Anon、OPが条件付きブランチで保護された複製された構文を受け入れないとすれば、私はおそらく実行可能なサイズの問題がテンプレート上で赤いフラグを立てていると推測します。 (テンプレート関数はswitch ... caseよりも大きな実行結果になるので) – YeenFei

答えて

5

-Griffは、この1つは機能をキャストする型コードと一致します。基本的な考え方は、それぞれの型の小さな変換関数のセットと関数ポインタの配列を作成し、正しい変換関数を見つけるためにデータ形式に基づいてその配列にインデックスを付けることです。

使用:

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 

を希望は、私は、これは正確にテンプレートが解決になっていた問題であると考えているだろう

+0

これはあなたの質問から遠かったのですか?あなたのプラットフォームで関数呼び出しを十分に効率的に使えますか? – ch0kee

+0

それは...天才。あなたがここで何をしているのかを完全に理解するために私をしばらく時間がかかりましたが、私が必要としていることを最初に見たときに_LOOKS_します。ちょっとした手間をかけて、これらの関数を使ってデータをpcm行列に入れることさえできます。これは絶対に素晴らしいです。クールな部分は、これが浮動小数点型とint型で動作することです。トーンありがとう! – Griffin

+0

これを編集して、ソリューションの簡潔な説明を先頭に追加しました。グリフィンのメモのとおり、コードからすぐに理解するのは簡単ではないためです。あなたが気にしないことを願っています - 私はそれが素晴らしい答えだと思います。 –

関連する問題