在可更新的后台线程上播放音

时间:2018-04-20 20:33:39

标签: c# winforms

我有一个C#Windows Forms应用程序,它连接到第三方设备,感应环境中的变化。我想在一个可更新的线程上运行一个不断运行的音调。根据我传入线程的值,频率会变高或变低。我可以指出这个例子或想法吗?我的声音生成不太流畅,我不确定Beep(int,int)是否可行。

谢谢!

1 个答案:

答案 0 :(得分:0)

The NAudio NuGet-Package is quite easy to use. I have a working snipped here that you can modify if you want:

void Main()
{
    var sine = new SineGenerator();

    var waveOut = new WaveOut();
    waveOut.DesiredLatency = 100;

    waveOut.Init(sine);
    waveOut.Play();

    var random = new Random();

    while (true)
    {
        Thread.Sleep(100);
        sine.Frequency = random.Next(100, 500);
    }

    waveOut.Stop();
}

public class SineGenerator : IWaveProvider
{
    private WaveFormat waveFormat;
    private int sample;

    public SineGenerator()
        : this(44100, 1)
    {
        Frequency = 1000;
        Amplitude = 0.25f;
    }

    public float Frequency { get; set;}
    public float Amplitude { get; set; }

    public SineGenerator(int sampleRate, int channels)
    {
        SetWaveFormat(sampleRate, channels);
    }

    public void SetWaveFormat(int sampleRate, int channels)
    {
        this.waveFormat = WaveFormat.CreateIeeeFloatWaveFormat(sampleRate, channels);
    }

    public int Read(byte[] buffer, int offset, int count)
    {
        WaveBuffer waveBuffer = new WaveBuffer(buffer);
        int samplesRequired = count / 4;
        int samplesRead = this.Read(waveBuffer.FloatBuffer, offset / 4, samplesRequired);
        return samplesRead * 4;
    }

    public int Read(float[] buffer, int offset, int sampleCount)
    {
        int sampleRate = WaveFormat.SampleRate;
        int channels = WaveFormat.Channels;

        double p = 2.0 * Math.PI / channels * Frequency;

        for (int n = 0; n < sampleCount; n += channels)
        {
            float value = (float)(Amplitude * Math.Sin((sample * p) / sampleRate));

            var b = Convert.ToByte((value + 0.5) * 255);
            value = (float)b / 255;

            for (int c = 0; c < channels; c++)
            {
                buffer[n + offset + c] = value;
            }

            sample += channels;
            if (sample == int.MaxValue) sample = 0;
        }

        return sampleCount;
    }

    public WaveFormat WaveFormat
    {
        get { return waveFormat; }
    }
}

See also this thread for more solutions.