Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 234
Chev Avatar asked Sep 30 '11 22:09

Chev


2 Answers

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.

like image 153
MusiGenesis Avatar answered Sep 22 '22 21:09

MusiGenesis


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);
    }
like image 45
Basil Avatar answered Sep 21 '22 21:09

Basil