如何在 C++ 中高效地从 void* 数组中解压 float、int16、int32 等数据?

发布于 2024-10-11 01:04:24 字数 908 浏览 5 评论 0原文

我有一组 PCM 数据;它可以是16位、24位打包、32位等。它可以是有符号的,也可以是无符号的,并且可以是32位或64位浮点。它当前存储为 void** 矩阵,首先按通道索引,然后按帧索引。目标是让我的库能够采用任何 PCM 格式并对其进行缓冲,而不需要对数据进行操作以适应指定的结构。如果 A/D 转换器输出 24 位交错 PCM 打包数组,我需要优雅地接受它。我还需要支持 16 位非交错以及上述格式的任何排列。

我知道运行时的位深度和其他信息,并且我尝试高效编码而不重复代码。我需要的是一种有效的方法来投射矩阵,将PCM数据放入矩阵中,然后稍后将其拉出。

对于 32 位和 16 位有符号 PCM,我可以将矩阵分别转换为 int32_tint16_t;对于 32 位、8 位字节系统,我可能还必须将 24 位 PCM 存储在 int32_t 中。

谁能推荐一种将数据放入该数组并稍后将其取出的好方法?我想避免使用如下所示的大段代码:

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 时,事情变得更加棘手。

有人愿意分享一些有用的宏吗?

I’ve got an array of PCM data; it can be 16-bit, 24-bit packed, 32-bit, etc. It can be signed, or unsigned, and it can be 32 or 64-bit floating point. It is currently stored as a void** matrix, indexed first by channel, then by frame. The goal is to allow my library to take in any PCM format and buffer it, without requiring manipulation of the data to fit a designated structure. If the A/D converter spits out 24-bit packed arrays of interleaved PCM, I need to accept it gracefully. I also need to support 16-bit non-interleaved, as well as any permutation of the above formats.

I know the bit depth and other information at runtime, and I’m trying to code efficiently while not duplicating code. What I need is an effective way to cast the matrix, put PCM data into the matrix, and then pull it out later.

I can cast the matrix to int32_t, or int16_t for the 32 and 16-bit signed PCM respectively; I’ll probably have to store the 24-bit PCM in an int32_t for 32-bit, 8-bit byte systems as well.

Can anyone recommend a good way to put data into this array, and pull it out later? I’d like to avoid large sections of code which look like:

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

Limitations: I’m working in C/C++, no templates, no RTTI, no STL. Think embedded. Things get trickier when I have to port this to a DSP with 16-bit bytes.

Does anybody have any useful macros they might be willing to share?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

二手情话 2024-10-18 01:04:24

这会将类型代码与转换函数进行匹配。基本思想是,它为每种类型创建一组微小的转换函数和一个函数指针数组,然后根据数据格式索引该数组,以便找到要调用的正确转换函数。

用法示例:

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

希望有帮助

This one will match typecodes to casting functions. The basic idea is that it creates a set of tiny conversion functions for each type, and an array of function pointers, and then indexes into that array based on the data format in order to find the correct conversion function to call.

Usage example:

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

The header file:

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

hope helps

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文