按位运算比调用memcpy更快吗?

时间:2015-12-17 22:24:45

标签: c++ performance audio

我正在搞乱音频文件并学习如何提取样本以进行操作而不是。现在我正在使用.wav文件,并假设标头是44个字节,样本大小是16位。

所以我编写了这段代码,它接受两个char值并将其存储为2字节短,以便我可以将其转换为32位浮点数。

        short ss = ((0x0000 | data[i*2+1]) & 0xff) << 8;
        short fs = (0x0000 | data[i*2]) & 0xff;
        short s = fs | ss;

最初我使用memcpy(&s, &data[i*2], 2)来执行此操作。他们都实现了我想做的事情,并且我能够获取值并将其流式传输到输出缓冲区并且工作正常。

我想知道执行按位运算是否值得,而不仅仅是简单地调用memcpy性能。

2 个答案:

答案 0 :(得分:1)

根据编译时使用的各种优化等,对于如此小的副本(两个字节),memcpy会明显变慢。有几种方法可以使这更好。例如,您可以使用union来允许编译器访问内存字的不同部分。

inline float getSamp(char *data, int i)
{
    union char_short
    {
        char d[2];
        short s;
    } sdata;
    float f;

    sdata.d[1] = data[i*2+1];
    sdata.d[0] = data[i*2];

    f = sdata.s / 32768.0f; // using 32768 because this is signed, 
                            // and the maximum negative value is -32768.
                            // This gets you a range of -1 to +0.9999695
    return f;
}

由于数组索引,这种方法仍然不是最优的。

使用内联(因此不执行调用)和位操作可以进一步优化。此外,取消引用该数组可以节省一些数组地址计算。如果您可以将数据点保存到正确的字节,您甚至可以保存此解除引用。

inline float getSample(char *data, int i);
{
    char *d = &data[2 * i];
    short sdata = ((*d) & 0x00FF);
    d++;
    sdata |= ((*d << 8) & 0xFF00);
    return sdata / 32768.0f;
}

虽然您可以进一步调整,但由于编译器的优化会为您带来更多优势,因此不值得付出努力。

所以,回答这个问题 - 这取决于。你移动了多少记忆,你做了多少操纵?鉴于目前多核处理器的速度,音频太容易了。但是,如果您使用的是速度和内存大小很重要的小型ARM嵌入式系统,那么最后一个例程将会产生很大的不同。

祝你好运

答案 1 :(得分:0)

不太重要,但memcpy会慢一点很多。可能慢2到3倍。它需要一个带循环计数的循环。