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.
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.
Low-frequency sounds are 500 Hz or lower while high-frequency waves are above 2000 Hz.
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.
The higher the frequency waves oscillate, the higher the pitch of the sound we hear.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With