ChevCast
ChevCast

Reputation: 59193

Is it possible to generate a constant sound in C# while adjusting its frequency?

Is it possible to generate a constant sound in C# and manipulate its frequency as it goes?

I tried something like this:

for (int i = 500; i < 15000; i += 1)
{
    Console.Beep(i, 500));
}

But being synchronous, the loop waits for each beep to finish. So I tried this:

for (int i = 500; i < 15000; i += 1)
{
    new Thread(x => Console.Beep(i, 500)).Start();
}

I would think this would be a start toward generating a constant sound that is ever increasing in frequency. However, it still stutters as it goes. Is there a way to accomplish this but more smoothly?

Upvotes: 9

Views: 7553

Answers (2)

Basil
Basil

Reputation: 205

Code below generate sine wave. You can to change frequency and other parameters

    private void TestSine()
    {
        IntPtr format;
        byte[] data;
        GetSineWave(1000, 100, 44100, -1, out format, out data);
        WaveWriter ww = new WaveWriter(File.Create(@"d:\work\sine.wav"),
            AudioCompressionManager.FormatBytes(format));
        ww.WriteData(data);
        ww.Close();
    }

    private void GetSineWave(double freq, int durationMs, int sampleRate, short decibel, out IntPtr format, out byte[] data)
    {
        short max = dB2Short(decibel);//short.MaxValue
        double fs = sampleRate; // sample freq
        int len = sampleRate * durationMs / 1000;
        short[] data16Bit = new short[len];
        for (int i = 0; i < len; i++)
        {
            double t = (double)i / fs; // current time
            data16Bit[i] = (short)(Math.Sin(2 * Math.PI * t * freq) * max);
        }
        IntPtr format1 = AudioCompressionManager.GetPcmFormat(1, 16, (int)fs);
        byte[] data1 = new byte[data16Bit.Length * 2];
        Buffer.BlockCopy(data16Bit, 0, data1, 0, data1.Length);
        format = format1;
        data = data1;
    }

    private static short dB2Short(double dB)
    {
        double times = Math.Pow(10, dB / 10);
        return (short)(short.MaxValue * times);
    }

Upvotes: 2

MusiGenesis
MusiGenesis

Reputation: 75296

If you want to do this in real-time (i.e. change the frequency dynamically in response to user input), this would be incredibly difficult and would entail your writing a software synthesizer. In that case, you might want to try using a library like NAudio (although I'm not 100% sure NAudio does realtime synthesis).

On the other hand, if you just want to pre-generate a WAV file with a continuously ascending tone and then play it, that's incredibly easy.

Edit: a third alternative is to play a MIDI sound and send control change messages to the MIDI device to gradually apply portmanteau to a playing note. This is also easy, but has the disadvantage that you can't be sure exactly how it will sound on somebody else's computer.

Upvotes: 6

Related Questions