简体   繁体   English

在C#中实时播放合成声音

[英]Realtime time playing of synthesised sounds in C#

I'm trying to write a mini synth program. 我正在尝试编写一个迷你合成器程序。 Essentially, every 200mS a timer is fired. 实质上,每200mS会触发一个计时器。 When this is fired, 200mS worth of PCM samples are generated by the loop (eg sawtooth, sine wave etc, etc.), the number of samples related to the sample rate and scan period. 触发后,环路会生成200mS的PCM样本(例如锯齿,正弦波等),样本数与采样率和扫描周期有关。 eg every 200mS, 4000 samples are ready in the wave array for playing. 例如,每200mS,可在波阵列中准备4000个样本进行播放。 My question is, how do I play this array iewhat should the PlaySound method do? 我的问题是,我该如何播放此数组,即PlaySound方法应该做什么? Invoking PlaySound every 200mS should play subsequent samples in a continuous manner. 每200mS调用一次PlaySound应该以连续的方式播放后续采样。 I have played around with DirectSound and NAudio to no avail. 我玩过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);
    }

I realise that the timer may not fire exactly every 200mS, and that the 4000 samples may contain slightly too few or too many samples for the actual time. 我意识到计时器可能不会精确地每200ms触发一次,并且4000个样本在实际时间中可能包含的样本太少或太多。 I'm not worried about this as I can tweak the number of samples according to the actual time between subsequent timer firing. 我对此并不担心,因为我可以根据后续计时器触发之间的实际时间来调整样本数量。

Instead of creating sound on a timer, most audio synthesis programs work with two buffers - one is being filled while the other one is being played. 大多数音频合成程序不是在计时器上创建声音,而是使用两个缓冲区工作-一个正在填充,而另一个正在播放。 NAudio allows you to do this by implementing the Read function in an ISampleProvider or IWaveProvider derived class. NAudio允许您通过在ISampleProvider或IWaveProvider派生类中实现Read函数来执行此操作。 This method will be called whenever the soundcard wants more audio to play. 每当声卡想要播放更多音频时,都会调用此方法。 You can set up your buffer sizes to be 200ms if you want. 如果需要,可以将缓冲区大小设置为200ms。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM