AceInfinity
Emeritus, Contributor
Here's a little snippet to write a beep in WAV format to a MemoryStream to be played by the system. Easily enough done with the kernel32.dll's internal function 'Beep' although here's a way to do it manually.
And to test, i've created a little Twinkle Twinkle little star melody for you guys :)
We use a BinaryWriter to write to a MemoryStream, so that we can load that data (bytes) using a System.Media.SoundPlayer. What needs to happen first though is that we write the WAV file header to the MemoryStream, then, we can start writing out the samples using a formulated value. Flush the rest of the data out of the BinaryWriter, and reset the start position of the MemoryStream back to the beginning for our SoundPlayer to use the data in the MemoryStream to be played. If you use the Play() method instead of PlaySound() you get a really cool distorted sound effect :)
To do that, look into the class and change:
To:
Just one of the things I noticed while doing this.
I got the idea from here: http://paste.blixt.org/543
Highest amplitude you'll want would be 1000, if you want to provide handling for that, you can probably check that parameter and throw an exception if it's too high:
Code:
using System;
using System.Windows.Forms;
using System.IO;
using System.Media;
using System.Linq;
public class Sound
{
public static void CreateBeep(int amp, int freq, int dur)
{
int smp = 441 * dur / 10;
int bytes = smp * 4;
int[] h = { 0X46464952, 0x24 + bytes, 0X45564157, 0X20746D66, 0x10, 0X20001, 0xAC44, 0x2B110, 0X100004, 0X61746164, bytes };
using (MemoryStream ms = new MemoryStream(44 + bytes))
{
using (BinaryWriter bw = new BinaryWriter(ms))
{
Array.ForEach(Enumerable.Range(0, h.Length).ToArray(), i => bw.Write(h[i]));
for (int i = 0; i < smp; i++)
{
Int16 s = Convert.ToInt16((((amp * (Math.Pow(2, 15))) / 1000) - 1) * Math.Sin((2 * Math.PI * freq / 44100.0) * i));
Array.ForEach(Enumerable.Range(1, 2).ToArray(), n => bw.Write(s));
}
bw.Flush();
ms.Seek(0, SeekOrigin.Begin);
using (SoundPlayer SP = new SoundPlayer(ms)) { SP.PlaySync(); }
}
}
}
}
And to test, i've created a little Twinkle Twinkle little star melody for you guys :)
Code:
new Thread(new ThreadStart(
(MethodInvoker)delegate
{
int[] freqs = {
131, 131, 196, 196, 220, 220, 196, 0,
175, 175, 165, 165, 147, 147, 131, 0,
196, 196, 175, 175, 165, 165, 147, 0,
196, 196, 175, 175, 165, 165, 147, 0,
131, 131, 196, 196, 220, 220, 196, 0,
175, 175, 165, 165, 147, 147, 131, 0
};
Array.ForEach(freqs, f => Sound.CreateBeep(1000, f, 400));
}
)).Start();
We use a BinaryWriter to write to a MemoryStream, so that we can load that data (bytes) using a System.Media.SoundPlayer. What needs to happen first though is that we write the WAV file header to the MemoryStream, then, we can start writing out the samples using a formulated value. Flush the rest of the data out of the BinaryWriter, and reset the start position of the MemoryStream back to the beginning for our SoundPlayer to use the data in the MemoryStream to be played. If you use the Play() method instead of PlaySound() you get a really cool distorted sound effect :)
To do that, look into the class and change:
Code:
using (SoundPlayer SP = new SoundPlayer(ms)) { SP.PlaySync(); }
To:
Code:
using (SoundPlayer SP = new SoundPlayer(ms)) { SP.Play(); }
Just one of the things I noticed while doing this.
I got the idea from here: http://paste.blixt.org/543
Highest amplitude you'll want would be 1000, if you want to provide handling for that, you can probably check that parameter and throw an exception if it's too high:
Code:
if (amp > 1000) throw new Exception("Amplitude too high");
Last edited: