2009-07-05 11 views
7

¿Cómo puedo reproducir un sonido basado en los datos de forma de onda que mi programa .NET está generando a partir de la entrada del usuario y las funciones matemáticas?Reproducir sonido en .NET usando datos de forma de onda generados

Por "datos de forma de onda" quiero decir valores de SPL (nivel de presión sonora) en una serie de tiempo de intervalo fijo (probablemente 44.1 kHz). Supongo que esto requiere algún tipo de disposición de memoria intermedia de transmisión.

Tenga en cuenta que esto tiene que ser en tiempo real/en vivo, por lo que simplemente crear un archivo .wav y luego reproducirlo no será suficiente. Se prefiere VB.NET, pero C# también es aceptable.

Solo para aclarar: Lo que estoy buscando es un ejemplo de código de trabajo simple.

+0

¡Finalmente me he dado a la tarea de probar la solución NAudio, y es excelente! Mucho mejor y más fácil de lo que temía, realmente debería haberlo intentado hace mucho tiempo. – RBarryYoung

+1

Una respuesta más operativa a esta pregunta es en Pregunta de desbordamiento de pila * [NAudio reproduce una onda sinusoidal durante x milisegundos usando C#] (http://stackoverflow.com/questions/5485577) *. –

Respuesta

4

Puede hacerlo usando NAudio. Usted crea una secuencia que se deriva de WaveStream y en su método de lectura modificado, usted devuelve sus muestras que puede generar sobre la marcha. Usted tiene control sobre el tamaño de los búferes utilizados por la tarjeta de sonido que le da control sobre la latencia.

+0

Finalmente tuve la oportunidad de probar NAudio y es excelente. Gracias por el puntero. – RBarryYoung

0

Creo que necesitarás usar DirectSound (DirectX API) para eso. Funciona con búferes que puede llenar con los datos generados.

tal vez algo como this (here en camino de regreso de la máquina) ayudará

1

Salida this thread de la carga de una memoria intermedia DirectSound con datos arbitrarios y jugarlo.

Por comentario: Sí, lo sé. Tendrá que traducir el C++ en C# o VB.NET. Pero, el concepto es lo importante. Usted crea un búfer de DirectSound secundario y luego lo usa para transmitir a su búfer principal y jugar.

+0

Bueno, eso es * no * VB.net o C#. De hecho, no se parece a .Net en absoluto. – RBarryYoung

3

How to play from an array of doubles

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(); 
    } 
0

tengo este código, pero que tendrá que tener el 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 
Cuestiones relacionadas