快速转换字节数组到短数字音频数据

ant*_*nth 5 c#

我需要最快的方法将字节数组转换为短数据音频数据.

音频数据字节数组包含以这种方式放置的两个音频通道的数据:

C1C1C2C2 C1C1C2C2 C1C1C2C2 ...

where

C1C1 - two bytes of first channel

C2C2 - two bytes of second channel
Run Code Online (Sandbox Code Playgroud)

目前我使用这样的算法,但我觉得有更好的方法来执行这个任务.

byte[] rawData = //from audio device
short[] shorts = new short[rawData.Length / 2];
short[] channel1 = new short[rawData.Length / 4];
short[] channel2 = new short[rawData.Length / 4];
System.Buffer.BlockCopy(rawData, 0, shorts, 0, rawData.Length);
for (int i = 0, j = 0; i < shorts.Length; i+=2, ++j)
{
    channel1[j] = shorts[i];
    channel2[j] = shorts[i+1];
}
Run Code Online (Sandbox Code Playgroud)

Jul*_*lia 3

您可以使用不安全代码来避免数组寻址或位移位。但正如PVitt所说,在新 PC 上,如果数据大小很重要,最好使用标准托管代码和 TPL。

short[] channel1 = new short[rawData.Length / 4];
short[] channel2 = new short[rawData.Length / 4];

fixed(byte* pRawData = rawData)
fixed(short* pChannel1 = channel1)
fixed(short* pChannel2 = channel2)
{
    byte* end = pRawData + rawData.Length;
    while(pRawData < end)
    {
        (*(pChannel1++)) = *((short*)pRawData);
        pRawData += sizeof(short);
        (*(pChannel2++)) = *((short*)pRawData);
        pRawData += sizeof(short);
    }
}
Run Code Online (Sandbox Code Playgroud)

与所有优化问题一样,您需要仔细计时,特别注意缓冲区分配,通道 1 和通道 2 可能是自动增长的静态(大)缓冲区,并且您只能使用第 n 个第一个字节。您将能够为该函数的每次执行跳过 2 个大数组分配。并且会减少 GC 的工作量(当时间很重要时总是更好)

正如CodeInChaos所指出的,字节序可能很重要,如果您的数据字节序不正确,您将需要进行转换,例如在大字节序和小字节序之间进行转换,假设 8 位原子元素,代码将如下所示:

short[] channel1 = new short[rawData.Length / 4];
short[] channel2 = new short[rawData.Length / 4];

fixed(byte* pRawData = rawData)
fixed(byte* pChannel1 = (byte*)channel1)
fixed(byte* pChannel2 = (byte*)channel2)
{
    byte* end = pRawData + rawData.Length;
    byte* pChannel1High = pChannel1 + 1;
    byte* pChannel2High = pChannel2 + 1;

    while(pRawData < end)
    {
        *pChannel1High = *pRawData;
        pChannel1High += 2 * sizeof(short);

        *pChannel1 = *pRawData;
        pChannel1 += 2 * sizeof(short);

        *pChannel2High = *pRawData;
        pChannel2High += 2 * sizeof(short);

        *pChannel2 = *pRawData;
        pChannel2 += 2 * sizeof(short);
    }
}
Run Code Online (Sandbox Code Playgroud)

我没有使用实际的编译器编译本文中的任何代码,因此如果您发现错误,请随意编辑它。