5

将 void 数组转换为 typedef 的最佳做法是什么?

这就是我目前的做法:

typedef struct {
    int16_t left,right;
} SampleStereo16;

void *buffer[100000]; // data buffer
SampleStereo16* sample;

// insert something here that writes to the buffer

sample = (SampleStereo16*) buffer;

这似乎工作正常,但不知何故我觉得有更好的方法。我还想知道是否有办法让样本数组和缓冲区共享相同的内存(现在他们每个人都使用自己的内存)。

这是我目前正在处理的完整代码:

#include "fmod.h"
#include "fmod.hpp"
#include "fmod_errors.h"
#include "wincompat.h"
#include <stdio.h>

typedef struct {
    int16_t left,right;
} SampleStereo16;

void ERRCHECK(FMOD_RESULT result)
{
    if (result != FMOD_OK)
    {
        printf("\nFMOD error! (%d) %s\n", result, FMOD_ErrorString(result));
        if (result != FMOD_ERR_FILE_EOF)
            exit(-1);
    }
}


int main(int argc, char *argv[])
{
    FMOD::System     *system;
    FMOD::Sound      *sound;
    FMOD_RESULT       result;
    unsigned int      version;

    int channels;
    int bits;

    unsigned int         lenbytes; // length in bytes read
    void                 *buffer[1000000]; // data buffer
    unsigned int         *read; // number of bytes actually read
    unsigned int        position; // offset in PCM samples
    unsigned int         samplesread; // number of PCM samples read
    unsigned int        samplesbuffer; //
    unsigned int        cueposition;

    SampleStereo16*     sample;


    /*
        Create a System object and initialize.
    */

    result = FMOD::System_Create(&system);
    ERRCHECK(result);

    system->getVersion(&version);

    result = system->getVersion(&version);
    ERRCHECK(result);

    if (version < FMOD_VERSION)
    {
        printf("Error!  You are using an old version of FMOD %08x.  This program requires %08x\n", version, FMOD_VERSION);
        getch();
        return 0;
    }

    result = system->setOutput(FMOD_OUTPUTTYPE_ALSA);
    ERRCHECK(result);

    result = system->init(32, FMOD_INIT_NORMAL, 0);
    ERRCHECK(result);

    result = system->createStream("/home/dpk/Dropbox/Music/Will Smith - Miami.mp3", FMOD_SOFTWARE, 0, &sound);


    result = sound->getFormat(0, 0, &channels, &bits);
    ERRCHECK(result);

    printf("channels : %d   bits : %d \n", channels, bits);

    if (channels!=2 and bits!=16)
    {
        printf("File must be stereo (2 channels) 16 bits \n");
        exit(-1);
    }

    lenbytes = sizeof(buffer);
    samplesbuffer = lenbytes / channels / ( bits / 8 );
    position = 0;
    cueposition = 0;

    do
    {
        result = sound->seekData(position);
        ERRCHECK(result);

        printf("Reading block : %u  ",position);

        result = sound->readData(&buffer, lenbytes, read);
        ERRCHECK(result);

        samplesread = *read / channels / ( bits / 8 );

        sample = (SampleStereo16*) buffer;

        printf("number of PCM samples read : %u \n", samplesread);


        for(unsigned int i=0; i<samplesread; i++)
        {
            if (cueposition==0 && ( abs(sample[i].left)>500 || abs(sample[i].right)>500 ) )
            {
                cueposition = position+i;
                printf("cue point : %u \n", cueposition);
            }
        }

        position += lenbytes / channels / ( bits / 8 );

    } while(samplesread==samplesbuffer);

    printf("\nExit\n");

    /*
        Shut down
    */
    result = sound->release();
    ERRCHECK(result);
    result = system->close();
    ERRCHECK(result);
    result = system->release();
    ERRCHECK(result);

    return 0;
}

当缓冲区增加太多时,我也会遇到分段错误,但从我目前能够找到的情况来看,这似乎是堆栈大小限制。

也可以随意评论我做错的任何事情,我最近(上周)才开始使用 C++,所以我很确定我的代码中有些东西看起来很糟糕。

4

2 回答 2

5

buffer是一个指针数组void。这是不寻常的。通常我们将缓冲区声明为charorunsigned charuint8_t或其他字节大小类型的数组:

char buffer[100000]; // data buffer

无论如何,“正确”的 C++ 风格转换是reinterpret_cast

sample = reinterpret_cast<SampleStereo16 *>(buffer);

另一方面,您可以首先声明buffer为数组SampleStereo16。那么你根本不需要演员表:

SampleStereo16 buffer[6250];
SampleStereo16 *sample;

sample = buffer;
于 2013-05-01T15:39:47.097 回答
0

您应该使用 sizeof 运算符来确定读取了多少样本。即,您的字节数组应该是大小的偶数倍(SampleStereo16)。

然后,您通常会以该大小的块形式遍历字节数组。您 malloc(sizeof(SampleStereo16)) 获取每个 SampleStereo16* 指针,然后从您的字节数组中存储该数量的数据并将其添加到您的向量或数组中。

如果您以这种方式一致地打包和解包结构的每个数组,那么您应该没有问题。

将序列化文件中的前几个字节分配给某种版本号也是很常见的,以防您决定稍后向结构添加更多字段,但这似乎不是您的用例,基于您的整个代码示例。

于 2013-05-01T15:42:49.573 回答