Reproducir sonido en .NET utilizando los datos de forma de onda generada
Pregunta
¿Cómo puedo reproducir un sonido basado en los datos de forma de onda que mi programa .NET está generando a partir de las funciones de entrada de usuario y matemáticas?
Por "datos de forma de onda" me refiero a valores en una serie de tiempo de intervalo fijo SPL (nivel de presión sonora) (probablemente 44,1 kHz). Supongo que esto requiere algún tipo de streaming a disposición de tampón.
Tenga en cuenta, que esto tiene que ser vivo / en tiempo real, por lo que sólo la creación de un archivo .wav y luego jugar que no va a ser suficiente. se prefiere VB.NET, pero C # es aceptable también.
Solo para aclarar:. Lo que busco es un simple ejemplo de código de trabajo
Solución
Puede hacer esto utilizando NAudio . Se crea una corriente que se deriva de WaveStream y en su método Read overriden, regresar tus muestras que se pueden generar sobre la marcha. Usted tiene control sobre el tamaño de las memorias intermedias utilizadas por la tarjeta de sonido que le da control sobre la latencia.
Otros consejos
¿Cómo se juega a partir de una serie de dobles
PlayerEx pl = new PlayerEx();
private static void PlayArray(PlayerEx pl)
{
double fs = 8000; // sample freq
double freq = 1000; // desired tone
short[] mySound = new short[4000];
for (int i = 0; i < 4000; i++)
{
double t = (double)i / fs; // current time
mySound[i] = (short)(Math.Cos(t * freq) * (short.MaxValue));
}
IntPtr format = AudioCompressionManager.GetPcmFormat(1, 16, (int)fs);
pl.OpenPlayer(format);
byte[] mySoundByte = new byte[mySound.Length * 2];
Buffer.BlockCopy(mySound, 0, mySoundByte, 0, mySoundByte.Length);
pl.AddData(mySoundByte);
pl.StartPlay();
}
este hilo en carga hasta un DirectSound buffer con datos arbitrarios y jugarlo .
Por comentario: Sí, lo sé. Usted tendrá que traducir el C ++ en C # o VB.NET. Sin embargo, el concepto es lo importante. Se crea un búfer DirectSound secundaria y luego usarlo para transmitir a su memoria intermedia primaria y jugar.
Creo que tendrá que utilizar DirectSound ( DirectX API) para eso. Funciona fuera de tampones que se podría llenar con sus datos generados.
Tal vez algo así como este ( aquí en forma de máquina de nuevo) ayudará
tengo este código, sino que tendrá que tener código para generar el archivo WAV en la memoria.
Option Strict Off
Option Explicit On
Imports Microsoft.DirectX.DirectSound
Imports Microsoft.DirectX
Imports System.Threading
Public Class Form1
Const SRATE As Integer = 44100
Const FREQ As Integer = 440
Const DUR As Integer = 1
Private dsDesc As BufferDescription
Private wvFormat As WaveFormat
Private DS As Device
Dim SecondaryBuffer As Microsoft.DirectX.DirectSound.SecondaryBuffer
Dim BufferDescription As Microsoft.DirectX.DirectSound.BufferDescription
Dim DXFormat As Microsoft.DirectX.DirectSound.WaveFormat
Dim sbuf(DUR * SRATE) As Short
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Show()
DS = New Microsoft.DirectX.DirectSound.Device
DS.SetCooperativeLevel(Me, CooperativeLevel.Normal)
wvFormat.FormatTag = WaveFormatTag.Pcm
wvFormat.Channels = 1
wvFormat.SamplesPerSecond = SRATE
wvFormat.BitsPerSample = 16
wvFormat.AverageBytesPerSecond = 2 * SRATE
wvFormat.BlockAlign = 2
dsDesc = New BufferDescription(wvFormat)
dsDesc.BufferBytes = 2 * DUR * SRATE
dsDesc.Flags = 0
Dim buff1 = PlayWave(400)
Dim buff2 = PlayWave(600)
buff1 = PlayWave(400)
buff1.Play(0, Microsoft.DirectX.DirectSound.BufferPlayFlags.Default)
Thread.Sleep(1000)
buff1 = PlayWave(600)
buff1.Play(0, Microsoft.DirectX.DirectSound.BufferPlayFlags.Default)
' End
End Sub
Function PlayWave(FREQ As Integer) As SecondaryBuffer
' create a buffer
Dim dsBuffer As SecondaryBuffer
dsBuffer = New SecondaryBuffer(dsDesc, DS)
Dim sbuf(DUR * SRATE) As Short
' create tone
For i As Integer = 0 To DUR * SRATE
sbuf(i) = CShort(10000 * Math.Sin(2 * Math.PI * FREQ * i / SRATE))
Next
' copy to buffer
dsBuffer.Write(0, sbuf, LockFlag.EntireBuffer)
Return dsBuffer
End Function