waveOut合成器性能不佳

时间:2013-08-01 18:37:09

标签: c++ visual-c++ waveout

我做了一些关于声音合成的研究,并设法编写了一个非常简单的合成器。我使用过microsoft waveOut API。我写了一个界面来简化整个过程。我现在可以初始化(单声道)音频流并调用setSample。因此,采样率为每秒44100个样本,setSample需要每秒至少调用44100次。

这在我的(四核)笔记本电脑上工作正常,但在我父母的旧双核视频上,它的结果非常糟糕。这很奇怪:即使我在一个更复杂的合成器上使用多个效果,FL Studio在我父母的机器上运行得非常流畅,而我的代码非常基本。

我不知道导致这种行为的原因。我的代码远非优化,但很简单,以至于我很难想象单独优化就是问题(除非我做的事情真的会减慢合成速度)。

可能有问题的代码片段:

void AudioStream::setSample(float sample)
{
    unsigned int discreteSample = ((sampleSize > 1) ? 0 : amplitude) + ((float)amplitude * sample);

    for (unsigned int i = 0; i < sampleSize; i++)
    {
        data[pointr++] = (char)(discreteSample & 255);
        discreteSample = discreteSample >> 8;
    }

    if (pointr >= maxSize)
    {
        if (waveOutWrite(hWaveOut, firstHeader ? &header1 : &header2, firstHeader ? sizeof(header1) : sizeof(header2)) != MMSYSERR_NOERROR)
        { throw("Error writing to sound card!"); return; }

        pointr = 0;
        firstHeader = !firstHeader;

        if (WaitForSingleObject(handle, INFINITE) != WAIT_OBJECT_0) { throw("An error occured while waiting for sound to finish"); return; }

        unsigned char *temp;
        temp = data;
        data = play;
        play = temp;

        first = false;
    }
}

我认为从浮点值到离散样本的转换可能很麻烦。我使用它来处理多个样本大小。

我还听说waveOut可能是软件模拟的(这可以解释很多),但我不确定是(或何时,如在什么版本的Windows或在什么情况下)这是这种情况和多少这将产生性能差异。

我希望有人可以帮助我。

修改:可以找到来源here,可执行文件here

3 个答案:

答案 0 :(得分:3)

一次将一个样本传递给waveOutWrite,无论是在代码级别还是在驱动程序内,都会非常低效。它设置缓冲区的DMA传输,如果该缓冲区长一个字节,则会产生每个样本的切换缓冲区的所有开销。我会在每次调用waveOutWrite时发送至少十分之一秒的样本。

答案 1 :(得分:2)

WaveOut API和良好的性能是不可能的。如果使用Windows,请使用更合适的ASIO或WASAPI,或者如果您想要跨平台,请尝试使用Portaudio。

答案 2 :(得分:0)

如果您正在寻找一些非常简单的音频库来制作简单的合成器,我强烈建议 audiere http://audiere.sourceforge.net/ BASS http://www.un4seen.com/

第一个是过时的,但同时也是最简单的一个(不会让它变坏)。我能用它写出那个简单的合成器。第二个是BASS,在更复杂的项目中对你有好处。它带有非常简单的例子(合成器就是其中之一)。它也很容易设置。