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

我需要将上面的字节序列分成 3 个字节的块,以识别 EEG。wave delta 由第一个 3 字节序列表示,theta 由下一个字节表示,依此类推。我该怎么做?

4

8 回答 8

3

假设您知道您的输入总是正好是 8 个 3 位整数,那么您所需要的只是一个简单的循环,它从输入中读取 3 个字节并将它们写成 4 个字节的值。最简单的方法是将输入视为一个字节数组,然后以三个一组的形式从该数组中提取字节。

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

像这样?如果未按 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 字节 little endian 字符流转换为 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 回答
1

你可以试试…… 像这样:

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 回答
0

我需要的是,我需要分别获取 3 字节序列,而不是显示 24 字节的整个序列。

您可以轻松地将 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

您可以使用位操作运算符

我会使用,不遵循实际代码,只显示示例

(对于我 =0 直到 7){

temp val = Value && 111 //与 111 进行与运算

值 = 值 >> 3;//向右移动

}

于 2013-02-20T18:45:49.607 回答
-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 回答