-3

I have a C# Windows Forms app which is connected to third party devices sensing changes in an environment. I would like to have a constantly running tone running on a thread which is update-able. The frequency gets higher or lower depending on the values I pass into the thread. Any examples of this I could be pointed to or an idea? I am not too fluent in sound generation and am not sure if the Beep(int,int) is the way to go.

Thanks!

1 Answers1

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.

Tho Mai
  • 835
  • 5
  • 25
  • Thanks!! I am trying to implement but don't hear a change in the tone using your code, the only thing i changed was the min/max to 1000/2000 to make it easier to hear. I am expecting the tone to change randomly, am I correct? – Winston Smith Apr 20 '18 at 21:48
  • Works great, I got away from testing it with the loop and ran it under live data, works as directed. Thanks @thomai!! – Winston Smith Apr 23 '18 at 16:17