Esta división ha sido probado por nuestros especialistas así garantizamos la exactitud de este post.
Solución:
Puede usar NAudio y crear un WaveStream derivado que genere ondas sinusoidales o cuadradas que podría enviar a la tarjeta de sonido o escribir en un archivo WAV. Si usó muestras de punto flotante de 32 bits, podría escribir los valores directamente fuera de la función sin tener que escalar, ya que ya va entre -1 y 1.
En cuanto a la precisión, ¿te refieres exactamente a la frecuencia correcta o exactamente a la forma de onda correcta? No existe tal cosa como un true onda cuadrada, e incluso la onda sinusoidal probablemente tendrá algunos artefactos muy silenciosos en otras frecuencias. Si lo que importa es la precisión de la frecuencia, depende de la estabilidad y precisión del reloj de su tarjeta de sonido. Habiendo dicho eso, me imagino que la precisión sería lo suficientemente buena para la mayoría de los usos.
Aquí hay un código de ejemplo que crea una muestra de 1 kHz a una frecuencia de muestreo de 8 kHz y con muestras de 16 bits (es decir, no en coma flotante):
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));
Esto le permite dar frecuencia, duración y amplitud, y es un código 100% .NET CLR. No hay archivos DLL externos. Funciona creando un formato WAV. MemoryStream
que es como crear un archivo solo en la memoria, sin almacenarlo en el disco. Entonces toca eso MemoryStream
con 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)
Intente crear seno y guárdelo en un archivo de onda en C #
private void TestSine()
IntPtr format;
byte[] data;
GetSineWave(1000, 100, 44100, -1, out format, out data);
WaveWriter ww = new WaveWriter(File.Create(@"d:worksine.wav"),
AudioCompressionManager.FormatBytes(format));
ww.WriteData(data);
ww.Close();
private void GetSineWave(double freq, int durationMs, int sampleRate, short decibel, out IntPtr format, out byte[] data)
short max = dB2Short(decibel);//short.MaxValue
double fs = sampleRate; // sample freq
int len = sampleRate * durationMs / 1000;
short[] data16Bit = new short[len];
for (int i = 0; i < len; i++)
double t = (double)i / fs; // current time
data16Bit[i] = (short)(Math.Sin(2 * Math.PI * t * freq) * max);
IntPtr format1 = AudioCompressionManager.GetPcmFormat(1, 16, (int)fs);
byte[] data1 = new byte[data16Bit.Length * 2];
Buffer.BlockCopy(data16Bit, 0, data1, 0, data1.Length);
format = format1;
data = data1;
private static short dB2Short(double dB)
double times = Math.Pow(10, dB / 10);
return (short)(short.MaxValue * times);