I am trying to generate a tone to the sound card (Frequency: 1950 hz, duration: 40 ms, level: -30 db, right-channel, on steam 1). Any recommendations on how to accomplish this using C++ or C#. Are there any libraries (C++ or C#) for generating such precise tone?
-
If it is possible to prepare the sound ahead of time and store it in a file, then you could use simple Win32 `PlaySound()` on Windows. – japreiss Sep 27 '12 at 01:51
2 Answers
David, playing audio to the speakers was built right into .NET (i think in the .NET 2.0 Framework). Using the System.Media.SoundPlayer you can play a sound from a memory stream that you build (in WAV format). Here is a function i coded that plays a simple frequency for a certain duration. Regarding the decibels and sending it to the sound card, i don't really understand what specifics you are referring to. For instance i fail to understand how audio as measured in decibels is sent to the sound card. My understanding is that decibels are simply a measure of how loud a sound is, thus after it's been reproduced by the speakers. Thus the volume control on the speakers affects what decibel your sounds will produce, and sending a certain decibel to the sound card thus makes no sense to me. Maybe you need something more detailed and maybe this doesn't work for you. But maybe you can run with this and get it to work for what you need. And maybe it is almost exactly what you are asking.
The process i use in this code allows one to build any audio you want, and plays it. So you can create 2 sine waves or many, many more, or triangle waves, or even speech synthesis with this method if you want. This method takes sound samples which are calculated and then plays those, so you need to code what each audio sample needs to be at the given moment in time. WAV allows stereo sound too, but this code sample only uses non-stereo sound. If you want stereo sound then it just needs modified to generate the bytes for a stereo WAV format instead. I expect it would not be too difficult.
Happy coding!
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)

- 1,425
- 15
- 17
-
"...The process I use in this code simply allows you to build any audio you want..." Misuse of the word "simply". – Baruch Atta Dec 26 '18 at 21:48
-
I see no misuse of 'simply' in my sentence. It is an adverb that describes the verb 'allows'. In my American English, we use 'simply' in this manner to mean that i am expressing a simpler description of what it does. This is very normal usage in my region, and as far as i know, it is completely correct grammar. If not, please enlighten me what is wrong with my use of 'simply'. – Shawn Kovac Aug 21 '19 at 05:31
-
I feel that the use of the word "simply" in any instructions more complex than "wash, wrinse, repeat" to be very irritating and condescending. Your choice. – Baruch Atta Aug 25 '19 at 11:40
-
@BaruchAtta, i thank you for sharing that. Please understand that i do not mean it in any condescending connotation, but merely as the denotation (meaning) of the word in Google's definition. I searched Google for 'simply definition' and the first definition fits my intended usage: "1: in a straightforward or plain manner. synonyms: straightforwardly, directly; clearly, plainly." – Shawn Kovac Aug 28 '19 at 19:37
-
@BaruchAtta, do you feel the same irritating and condescending connotation from the use of the word 'plainly' or 'straightforwardly'? (I don't feel that any have a condescending connotation from my culture, but i'm happy to update my post if you feel either of these words are better received by a wider audience, for you and for people with the same connotations of 'simply'. ) – Shawn Kovac Aug 28 '19 at 19:39
-
You should be ashamed to just copy and paste code that is obviously not yours without mentioning the original author... -1 for that one ( original answer here https://stackoverflow.com/a/19772815/2921691 ) – Markus Safar Mar 15 '21 at 17:13
NAudio provides a robust audio library for .NET.
NAudio is an open source .NET audio and MIDI library, containing dozens of useful audio related classes intended to speed development of audio related utilities in .NET. It has been in development since 2002 and has grown to include a wide variety of features. While some parts of the library are relatively new and incomplete, the more mature features have undergone extensive testing and can be quickly used to add audio capabilities to an existing .NET application. NAudio can be quickly added to your .NET application using NuGet.
Here's an article that walks step-by-step through using NAudio to create a sine wave. You can create the sine wave with any desired frequency, for any desired duration:

- 147,927
- 63
- 340
- 553
-
Thanks Eric. What I am trying to do is actually more complex: generate two tones (like the one above with different freq. level, different stereo channel and stream) with possibly a gap in the middle. Do you guys have suggestion of how to do this ideally in C++ (low latency). Thanks again. – David W. Sep 27 '12 at 01:04