我正在尝试编写一个迷你合成器程序。基本上,每200mS定时器被触发。当发射时,环路产生200mS的PCM样本(例如锯齿波,正弦波等),样本数量与采样率和扫描周期有关。例如每200毫秒,4000个样本准备好在波阵列中播放。我的问题是,如何播放这个数组,即PlaySound方法应该怎么做?每200mS调用一次PlaySound应该以连续的方式播放后续样本。我玩过DirectSound和NAudio无济于事。
const int SAMPLE_RATE = 20000;
const double SCAN_PERIOD = .2; // S
Timer _ScanTimer = new Timer();
double[] wave = new double[(int)((double)SAMPLE_RATE * SCAN_PERIOD)];
_ScanTimer.Tick += new EventHandler(_ScanTimer_Tick);
private void _ScanTimer_Tick(object sender, EventArgs e) {
int numSamplesPerTick = (int)((double)SAMPLE_RATE * SCAN_PERIOD);
double secondsPerTick = (double)2 / SAMPLE_RATE;
for (int i = 0; i < numSamplesPerTick; i++) {
wave[i] = GetSynthOutput();
_CurrentTime += secondsPerTick;
if (_CurrentTime > double.MaxValue - 1)
_CurrentTime = 0;
}
PlaySound(wave);
}
我意识到计时器可能不会每200毫秒准确发射一次,并且4000个样本可能包含的实际时间内的样本数量太少或太多。我并不担心这一点,因为我可以根据后续定时器触发之间的实际时间来调整样本数量。
答案 0 :(得分:1)
大多数音频合成程序不是在计时器上创建声音,而是使用两个缓冲区 - 一个正在填充而另一个正在播放。 NAudio允许您通过在ISampleProvider或IWaveProvider派生类中实现Read函数来实现此目的。只要声卡需要播放更多音频,就会调用此方法。如果需要,可以将缓冲区大小设置为200毫秒。