我需要最快的方法将字节数组转换为短数据音频数据.
音频数据字节数组包含以这种方式放置的两个音频通道的数据:
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)
您可以使用不安全代码来避免数组寻址或位移位。但正如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)
我没有使用实际的编译器编译本文中的任何代码,因此如果您发现错误,请随意编辑它。