首页 > 解决方案 > C++ 试图将几个较小的、不同大小的数据块复制到一个较大的数据块中

问题描述

我有一个奇怪的问题。我的音频引擎 (FMOD) 以不同大小的块请求数据,而我的文件流服务 (Theoraplay) 也在以可变大小的块提供它的音频数据。

我想做的是背靠背地推入音频样本,最后一个可能只是部分压入,差异保存为下次调用时的偏移量。我遇到的问题是 A:memcpy_s 对 FMOD 正在使用的 void 指针不满意,并且 B:我担心使用错误的偏移量可能会导致不同架构的内存问题,并且希望使其可靠。

这是当前的回调函数。pData 是指向 FMOD 想要填充的内容的指针,而 nDatalen 是它的大小。

AudioCallbackQueue 是一个链表,其中包含音频样本、指向下一个样本的链接以及它自己的当前偏移量。由于“框架”,样本本身的大小也有所不同。

数据清理在程序的其他地方。

FMOD_RESULT F_CALLBACK pcmQueue(FMOD_SOUND* pSound, void* pData, unsigned int nDataLen)
{
    FMOD::Sound*            pCurrentSound = (FMOD::Sound*)pSound; //required or else we get compiler errors
    void*                   pUserData = 0;
    AudioCallbackQueue*     pCurrent = 0;
    FMOD_RESULT             fError = FMOD_OK;
    unsigned int            nCurrentOffSet = 0;
    unsigned int            nRemainingLength = nDataLen;

    fError = pCurrentSound->getUserData( &pUserData );

    pCurrent = (AudioCallbackQueue*)pUserData;

    if(pCurrent != 0) //Error checking.
    {
        while (nRemainingLength != 0) //break when full
        {
            unsigned int nSize = (sizeof(float) * (pCurrent->pRawAudio->frames) * (pCurrent->pRawAudio->channels)) - pCurrent->nOffset; //This is the size of the current sample, minus whatever has been used previously
            
            if (nRemainingLength < nSize) //if here our sample is longer than what data is left to fill, so fill it to max and set the offset.
            {
                nSize = nRemainingLength;
                memcpy_s((pData + nCurrentOffSet), nSize, ((pCurrent->pRawAudio->samples) + pCurrent->nOffset), nSize);
                pCurrent->nOffset += nSize;
            }
            else //If here we are using the last of the sample, move on to the next
            {
                memcpy_s((pData + nCurrentOffSet), nSize, ((pCurrent->pRawAudio->samples) + pCurrent->nOffset), nSize);
                pCurrent = pCurrent->pNext;
            }

            nCurrentOffSet += nSize;
            nRemainingLength -= nSize;

            if (nSize > nDataLen)
                nSize = nDataLen;


        }
    }
    else //No samples around, nothing to process
        return FMOD_RESULT::FMOD_ERR_FILE_ENDOFDATA;

    pCurrentSound->setUserData(pCurrent);

    return FMOD_RESULT::FMOD_OK;
}

标签: c++memcpy

解决方案


正如@Retired Ninja 在链接答案中所说,您需要转换pData为 achar *以便您可以对其进行指针运算,如下所示(为了简洁起见,我使用了 C 风格的转换):

memcpy_s(((char *) pData + nCurrentOffSet), nSize, ((pCurrent->pRawAudio->samples) + pCurrent->nOffset), nSize);

另外,让我印象深刻的事情是,当您留下部分框架时,您会怎么做?下次调用时,您需要一些方案来处理它pcmQueue


推荐阅读