1

我正在尝试编写一个迷你合成器程序。本质上,每 200 毫秒触发一个计时器。当它被触发时,循环会生成 200mS 的 PCM 样本(例如锯齿波、正弦波等),样本的数量与采样率和扫描周期有关。例如,每 200 毫秒,波形阵列中有 4000 个样本可供播放。我的问题是,我该如何播放这个数组,即 PlaySound 方法应该做什么?每 200 毫秒调用一次 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 个样本可能包含实际时间稍微太少或太多的样本。我并不担心这一点,因为我可以根据后续计时器触发之间的实际时间调整样本数量。

4

1 回答 1

2

大多数音频合成程序不是在计时器上创建声音,而是使用两个缓冲区 - 一个正在填充,而另一个正在播放。NAudio 允许您通过在 ISampleProvider 或 IWaveProvider 派生类中实现 Read 函数来执行此操作。每当声卡想要播放更多音频时,都会调用此方法。如果需要,您可以将缓冲区大小设置为 200 毫秒。

于 2012-03-06T20:23:44.890 回答