Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to generate sounds according to frequency? [duplicate]

Tags:

c#

.net

audio

Possible Duplicate:
Creating sine or square wave in C#

I want to generate sounds. Either something like:

MakeSound(frequency, duration);

Or:

MakeSound(MyArrayOfSamples);

I've found something called: Microsoft.Directx.DirectSound but have read that it has been discontinued. And I couldn't find it as an option for a reference in Visual Studio (2010). I've found this link which according to what I've read, is supposed to include it, but am hesitant to use something from 2006 since it might not be supported anymore. And this one says it's for C/C++ (despite also saying: "managed code") and I don't want to waste weeks trying to understand how to wrap that into managed code, just to find out I can't do it. The most promising link I've found is WaveFormat but I couldn't find how to use it.

I'm not asking how to get the mathematical representation for the sound wave. Nor am I asking how to play an mp3 file or the like. Nor am I looking for third party software or wrappers. Just for a C# / .net solution for a very specific objective.

like image 873
ispiro Avatar asked Dec 26 '12 15:12

ispiro


People also ask

How does frequency make sound?

Sound moves through a medium such as air or water as waves. It is measured in terms of frequency and amplitude. Frequency, sometimes referred to as pitch, is the number of times per second that a sound pressure wave repeats itself.

What are the two types of frequency sound?

Low-frequency sounds are 500 Hz or lower while high-frequency waves are above 2000 Hz.

How does the sound change when frequency changes?

Because, the speed of the sound wave changes when the frequency is changed. Because, loudness of the sound wave takes time to adjust after a change in frequency. Because it takes time for sound to reach the listener, so the listener perceives the new frequency of sound wave after a delay.

Does frequency increase sound?

The higher the frequency waves oscillate, the higher the pitch of the sound we hear.


2 Answers

Either way you look at it, unless you want to used unmanaged code, you're going to have to build a WAV to play it. However, below is a code snippet from Eric Lippert's blog that will show you how to roll your own WAV file using frequencies.

namespace Wave
{
   using System;
   using System.IO;
   class MainClass {
      public static void Main() {
         FileStream stream = new FileStream("test.wav", FileMode.Create);
         BinaryWriter writer = new BinaryWriter(stream);
         int RIFF = 0x46464952;
         int WAVE = 0x45564157;
         int formatChunkSize = 16;
         int headerSize = 8;
         int format = 0x20746D66;
         short formatType = 1;
         short tracks = 1;
         int samplesPerSecond = 44100;
         short bitsPerSample = 16;
         short frameSize = (short)(tracks * ((bitsPerSample + 7)/8));
         int bytesPerSecond = samplesPerSecond * frameSize;
         int waveSize = 4;
         int data = 0x61746164;
         int samples = 88200 * 4;
         int dataChunkSize = samples * frameSize;
         int fileSize = waveSize + headerSize + formatChunkSize + headerSize + dataChunkSize;
         writer.Write(RIFF);
         writer.Write(fileSize);
         writer.Write(WAVE);
         writer.Write(format);
         writer.Write(formatChunkSize);
         writer.Write(formatType);
         writer.Write(tracks); 
         writer.Write(samplesPerSecond);
         writer.Write(bytesPerSecond);
         writer.Write(frameSize);
         writer.Write(bitsPerSample); 
         writer.Write(data);
         writer.Write(dataChunkSize);
         double aNatural = 220.0;
         double ampl = 10000;
         double perfect = 1.5;
         double concert = 1.498307077;
         double freq = aNatural * perfect;
         for (int i = 0; i < samples / 4; i++) {
            double t = (double)i / (double)samplesPerSecond;
            short s = (short)(ampl * (Math.Sin(t * freq * 2.0 * Math.PI)));
            writer.Write(s);
         }
         freq = aNatural * concert;
         for (int i = 0; i < samples / 4; i++) {
            double t = (double)i / (double)samplesPerSecond;
            short s = (short)(ampl * (Math.Sin(t * freq * 2.0 * Math.PI)));
            writer.Write(s);
         }
         for (int i = 0; i < samples / 4; i++) {
            double t = (double)i / (double)samplesPerSecond;
            short s = (short)(ampl * (Math.Sin(t * freq * 2.0 * Math.PI) + Math.Sin(t * freq * perfect * 2.0 * Math.PI)));
            writer.Write(s);
         }
         for (int i = 0; i < samples / 4; i++) {
            double t = (double)i / (double)samplesPerSecond;
            short s = (short)(ampl * (Math.Sin(t * freq * 2.0 * Math.PI) + Math.Sin(t * freq * concert * 2.0 * Math.PI)));
            writer.Write(s);
         }
         writer.Close();
         stream.Close();
      }
   }
}

Break it apart for your needs, but notice the aNatural variable - it's a frequency - just like what you're looking for.

Now, you can place that into a MemoryStream and then play it with SoundPlayer if you like.

like image 146
Mike Perrenoud Avatar answered Oct 22 '22 15:10

Mike Perrenoud


Here is a wrapper around the Beep function in the kernel, taking a duration and a frequency. Nowadays Beep uses the soundcard; in my days it used some piezo device glued on the motherboard.

using System;
using System.Runtime.InteropServices;

class BeepSample
{
    [DllImport("kernel32.dll", SetLastError=true)]
    static extern bool Beep(uint dwFreq, uint dwDuration);

    static void Main()
    {
        Console.WriteLine("Testing PC speaker...");
        for (uint i = 100; i <= 20000; i++)
        {
            Beep(i, 5);
        }
        Console.WriteLine("Testing complete.");
    }
}

On my Win10 box I need to set the duration (last parameter) much larger then the 5 ms here, more up to 50 ms but to get something reasonable I have to make it 100 ms.

Or use the Console.Beep(Int32, Int32) method if you want to take the easy route. That method was introduced in .Net 2.0.

like image 26
rene Avatar answered Oct 22 '22 15:10

rene