我做了一些关于声音合成的研究,并成功地写了一个非常简单的合成器。我使用过微软的waveOut API。我写了一个界面来简化整个过程。我现在可以初始化一个(mono)音频流并调用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可能会被软件模仿(这会解释很多),但我不确定(或者什么时候,比如在什么版本或什么情况下)是这样的情况,以及这会产生多大的性能差异。
我希望有人能帮我。
编辑:源代码可以找到这里,可执行这里。
发布于 2013-08-01 18:47:26
WaveOut API和良好的性能在一起是不可能的。如果使用Windows,可以使用更合适的ASIO或WASAPI,或者如果您希望跨平台,可以尝试Port音频。
发布于 2013-08-01 20:30:17
无论是在代码级别还是在驱动程序中,一次向waveOutWrite传递一个示例都将是非常低效的。它设置一个缓冲区的DMA传输,如果该缓冲区有一个字节长,它会为每个示例带来交换缓冲区的所有开销。我会在每次调用waveOutWrite时发送至少十分之一秒的样本。
发布于 2013-08-01 19:04:14
如果你正在寻找一些非常简单的音频库来制作一个简单的合成器,我强烈推荐audiere http://audiere.sourceforge.net/或BASS http://www.un4seen.com/。
第一个非常过时,但同时也是最简单的一个(这并不会使它变坏)。我用它写的不是那么简单的合成器。第二个,低音,将对你有好处,在更复杂的项目也。它提供了非常简单的例子(合成器就是其中之一)。设置起来也很容易。
https://stackoverflow.com/questions/18001938
复制相似问题