https://stackoverflow.com/questi ... are-wave-in-c-sharp
You can use NAudio and create a derived WaveStream that outputs sine or square waves which you could output to the soundcard or write to a WAV file. If you used 32-bit floating point samples you could write the values directly out of the sin function without having to scale as it already goes between -1 and 1. As for accuracy, do you mean exactly the right frequency, or exactly the right wave shape? There is no such thing as a true square wave, and even the sine wave will likely have a few very quiet artifacts at other frequencies. If it's accuracy of frequency that matters, you are reliant on the stability and accuracy of the clock in your sound card. Having said that, I would imagine that the accuracy would be good enough for most uses. Here's some example code that makes a 1 kHz sample at a 8 kHz sample rate and with 16 bit samples (that is, not floating point): int sampleRate = 8000;short[] buffer = new short[8000];double amplitude = 0.25 * short.MaxValue;double frequency = 1000;for (int n = 0; n < buffer.Length; n++){ buffer[n = (short)(amplitude * Math.Sin((2 * Math.PI * n * frequency) / sampleRate));}
[url=]down vote[/url]
This lets you give frequency, duration, and amplitude, and it is 100% .NET CLR code. No external DLL's. It works by creating a WAV-formatted MemoryStream which is like creating a file in memory only, without storing it to disk. Then it plays that MemoryStream with System.Media.SoundPlayer. using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Windows.Forms;public static void PlayBeep(UInt16 frequency, int msDuration, UInt16 volume = 16383){ var mStrm = new MemoryStream(); BinaryWriter writer = new BinaryWriter(mStrm); const double TAU = 2 * Math.PI; int formatChunkSize = 16; int headerSize = 8; 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 samples = (int)((decimal)samplesPerSecond * msDuration / 1000); int dataChunkSize = samples * frameSize; int fileSize = waveSize + headerSize + formatChunkSize + headerSize + dataChunkSize; // var encoding = new System.Text.UTF8Encoding(); writer.Write(0x46464952); // = encoding.GetBytes("RIFF") writer.Write(fileSize); writer.Write(0x45564157); // = encoding.GetBytes("WAVE") writer.Write(0x20746D66); // = encoding.GetBytes("fmt ") writer.Write(formatChunkSize); writer.Write(formatType); writer.Write(tracks); writer.Write(samplesPerSecond); writer.Write(bytesPerSecond); writer.Write(frameSize); writer.Write(bitsPerSample); writer.Write(0x61746164); // = encoding.GetBytes("data") writer.Write(dataChunkSize); { double theta = frequency * TAU / (double)samplesPerSecond; // 'volume' is UInt16 with range 0 thru Uint16.MaxValue ( = 65 535) // we need 'amp' to have the range of 0 thru Int16.MaxValue ( = 32 767) double amp = volume >> 2; // so we simply set amp = volume / 2 for (int step = 0; step < samples; step++) { short s = (short)(amp * Math.Sin(theta * (double)step)); writer.Write(s); } } mStrm.Seek(0, SeekOrigin.Begin); new System.Media.SoundPlayer(mStrm).Play(); writer.Close(); mStrm.Close();} // public static void PlayBeep(UInt16 frequency, int msDuration, UInt16 volume = 16383)
shareimprove this answer
|