1

私は脳のデータを操作するプログラムに取り組んでいます。一般的に認識されている 8 種類の EEG (脳波) の現在の大きさを表す値を受け取ります。このデータ値は、リトルエンディアン形式の一連の 8 つの 3 バイト符号なし整数として出力されます。

これが私のコードの一部です:

    if (extendedCodeLevel == 0 && code == ASIC_EEG_POWER_CODE)     
    {
         fprintf(arq4, "EXCODE level: %d CODE: 0x%02X vLength: %d\n", extendedCodeLevel, code, valueLength );
         fprintf(arq4, "Data value(s):" );
         for( i=0; i<valueLength; i++ ) fprintf(arq4, " %d", value[0] & 0xFF );
      }

value[0]は私の出力です。脳波を表す一連のバイトです。現在の出力ファイルには、次のデータが含まれています。

EXCODE level: 0x00  CODE: 0x83 vLength: 24
Data value(s): 16 2 17 5 3 2 22 1 2 1 0 0 0 4 0 0 3 0 0 5 1 0 4 8

必要なのは、EEG を識別するために、上記の一連のバイトを 3 バイトのチャンクに分割することです。ウェーブ デルタは最初の 3 バイト シーケンスで表され、シータは次のバイトで表されます。どうすればいいですか?

4

8 に答える 8

3

入力が常に正確に 8 つの 3 ビット整数であることがわかっていると仮定すると、必要なのは、入力から 3 バイトを読み取り、4 バイト値として書き出す単純なループだけです。これを行う最も簡単な方法は、入力をバイトの配列として扱い、この配列から 3 つのグループでバイトを取り出すことです。

// Convert an array of eight 3-byte integers into an array
//  of eight 4-byte integers.
void convert_3to4(const void* input, void* output)
{
   uint32_t   tmp;
   uint32_t*  pOut = output;
   uint8_t*   pIn = input;
   int        i;

   for (i=0; i<24; i+=3)
   {
      tmp  = pIn[i];
      tmp += (pIn[i+1] << 8);
      tmp += (pIn[i+2] << 16);
      pOut[((i+2) / 3)] = tmp;
   }
}
于 2013-02-20T19:04:12.037 に答える
1

あなたはs.thを試すかもしれません。このような:

union _32BitValue
{
    uint8_t bytes[4];
    uint32_t uval;
}

size_t extractUint32From3ByteSegemented(const std::vector<uint8_t>& rawData, size_t index, uint32_t& result)
{
    // May be do some checks, if the vector size fits extracting the data from it,
    // throwing exception or return 0 etc. ...

    _32BitValue tmp;
    tmp.bytes[0] = 0;
    tmp.bytes[1] = rawData[index + 2];
    tmp.bytes[2] = rawData[index + 1];
    tmp.bytes[3] = rawData[index];

    result = ntohl(tmp.uval);
    return index + 3;
}

生データ配列の値を解析するために使用されるコード:

size_t index = 0;
std::vector<uint8_t> rawData = readRawData(); // Provide such method to read the raw data into the vector
std::vector<uint32_t> myDataValues;

while(index < rawData.size())
{
    uint32_t extractedValue;
    index = extractUint32From3ByteSegemented(rawData,index,extractedValue);
    // Depending on what error detection you choose do check for index returned
    // != 0, or catch exception ...
    myDataValues.push_back(extractedValue);
}

// Continue with calculations on the extracted values ...

他の回答に示されているように、左シフト演算子と加算を使用すると、同様にトリックが実行されます。しかし、私見このサンプルは、何が起こっているのかを明確に示しています。ユニオンバイト配列にビッグエンディアン(ネットワーク)順の値を入力ntohl()し、ホストマシンで使用される形式(ビッグエンディアンまたはリトルエンディアン)で結果を移植可能に取得するために使用します。

于 2013-02-20T19:07:19.430 に答える
1

このような?3 でアラインされていない場合、最後のバイトは出力されません。必要ですか?

for( i=0; i<valueLength; i+=3 ) fprintf(arq4, "%d %d %d - ", value[i] & 0xFF,
                                                             value[i+1] & 0xFF,
                                                             value[i+2] & 0xFF );
于 2013-02-20T18:45:11.107 に答える
1

8 つの 3 バイト リトル エンディアン文字ストリームを 8 つの 4 バイト整数に変換するのは非常に簡単です。

for( int i = 0; i < 24; ++i )
{
    output[ i & 0x07 ] |= input[ i ] << ( i & 0x18 );
}

(テストされていない)コードでそれができると思います。入力が 24 エントリの char 配列で、出力が 8 エントリの int 配列であると仮定します。

于 2013-02-20T19:00:25.023 に答える
0

必要なのは、24バイトのシーケンス全体を表示するのではなく、3バイトのシーケンスを個別に取得する必要があることです。

1dバイト配列を目的の2d形状に簡単にコピーできます。

例:

#include <inttypes.h>
#include <stdio.h>
#include <string.h>

int main() {
    /* make up data */
    uint8_t bytes[] = 
        { 16,  2, 17, 
           5,  3,  2, 
          22,  1,  2,
           1,  0,  0,
           0,  4,  0, 
           0,  3,  0,
           0,  5,  1,
           0,  4,  8 };
    int32_t n_bytes = sizeof(bytes);
    int32_t chunksize = 3;
    int32_t n_chunks = n_bytes/chunksize + (n_bytes%chunksize ? 1 : 0);

    /* chunkify */
    uint8_t chunks[n_chunks][chunksize];
    memset(chunks, 0, sizeof(uint8_t[n_chunks][chunksize]));
    memcpy(chunks, bytes, n_bytes);

    /* print result */
    size_t i, j;
    for (i = 0; i < n_chunks; i++)
    {
        for (j = 0; j < chunksize; j++)
            printf("%02hhd ", chunks[i][j]);
        printf("\n");
    }
    return 0;
}

出力は次のとおりです。

16 02 17 
05 03 02 
22 01 02 
01 00 00 
00 04 00 
00 03 00 
00 05 01 
00 04 08
于 2013-02-20T20:40:06.240 に答える
0

ここでいくつかの例を使用して解決策を見つけたので、共有したいと思いました。これは、オブジェクトが hton および ntoh 関数を使用してネットワーク経由で自身のコピーを送信できるようにするためのインターフェイスの基礎になる可能性があります。これは、実際に私がやろうとしていることです。

#include <iostream>
#include <string>
#include <exception>
#include <arpa/inet.h>



using namespace std;

void DispLength(string name, size_t var){
    cout << "The size of " << name << " is : " << var << endl;
}


typedef int8_t byte;

class Bytes {
public:
    Bytes(void* data_ptr, size_t size)
    : size_(size)
    { this->bytes_ = (byte*)data_ptr; }


    ~Bytes(){ bytes_ = NULL; } // Caller is responsible for data deletion.


    const byte& operator[] (int idx){
        if((size_t)idx <= size_ && idx >= 0)
            return bytes_[idx];
        else
            throw exception();
    }


    int32_t ret32(int idx) //-- Return a 32 bit value starting at index idx
    {
        int32_t* ret_ptr = (int32_t*)&((*this)[idx]);
        int32_t  ret     = *ret_ptr;
        return ret;
    }


    int64_t ret64(int idx) //-- Return a 64 bit value starting at index idx
    {
        int64_t* ret_ptr = (int64_t*)&((*this)[idx]);
        int64_t  ret     = *ret_ptr;
        return ret;
    }


    template <typename T>
    T retVal(int idx) //-- Return a value of type T starting at index idx
    {
        T* T_ptr = (T*)&((*this)[idx]);
        T  T_ret = *T_ptr;
        return T_ret;
    }

protected:
    Bytes() : bytes_(NULL), size_(0) {}


private:
    byte* bytes_; //-- pointer used to scan for bytes
    size_t size_;
};

int main(int argc, char** argv){
    long double LDouble = 1.0;
    Bytes bytes(&LDouble, sizeof(LDouble));
    DispLength(string("LDouble"), sizeof(LDouble));
    DispLength(string("bytes"), sizeof(bytes));
    cout << "As a long double LDouble is " << LDouble << endl;
    for( int i = 0; i < 16; i++){
        cout << "Byte " << i << " : " << bytes[i] << endl;
    }
    cout << "Through the eyes of bytes : " <<
            (long double) bytes.retVal<long double>(0) << endl;
    return 0;
}
于 2014-11-22T04:03:43.023 に答える
-1

一部の自己文書化された保守可能なコードは、次のようになります(テストされていません)。

typedef union
{
    struct {
        uint8_t padding;
        uint8_t value[3];
    } raw;
    int32_t data;
} Measurement;

void convert(uint8_t* rawValues, int32_t* convertedValues, int convertedSize)
{
    Measurement  sample;
    int          i;

    memset(&sample, '\0', sizeof(sample));

    for(i=0; i<convertedSize; ++i)
    {
        memcpy(&sample.raw.value[0], &rawValues[i*sizeof(sample.raw.value)], sizeof(sample.raw.value));
        convertedValues[i]=sample.data;
    }
}
于 2013-02-20T19:20:08.600 に答える
-1

ビット操作演算子を使用できます

実際のコードに従うのではなく、例を示すだけです

(I =0 から 7 まで){

temp val = Value && 111 //111 との AND 演算

値 = 値 >> 3; //右にシフトする

}

于 2013-02-20T18:45:49.607 に答える