2009-07-05 12 views
7

Come posso riprodurre un suono in base ai dati della forma d'onda che il mio programma .NET sta generando da input dell'utente e funzioni matematiche?Riproduci suono in .NET utilizzando i dati della forma d'onda generata

Per "dati forma d'onda" intendo i valori SPL (livello di pressione sonora) in serie temporali a intervallo fisso (probabilmente 44,1 kHz). Presumo che ciò richieda un qualche tipo di arrangiamento di streaming buffer.

Nota che questo deve essere live/in tempo reale, quindi è sufficiente creare un file .wav e quindi giocare non sarà sufficiente. VB.NET è preferito, ma anche C# è accettabile.

Giusto per chiarire: quello che sto cercando è un semplice esempio di codice funzionante.

+0

Sono finalmente riuscito a provare la soluzione di NAudio, ed è eccellente! Molto meglio e più facile di quanto avessi temuto, avrei dovuto provarlo tanto tempo fa. – RBarryYoung

+1

Una risposta più operativa a questa domanda è nella domanda Stack Overflow * [NAudio riproduce un'onda sinusoidale per x millisecondi usando C#] (http://stackoverflow.com/questions/5485577) *. –

risposta

4

È possibile farlo utilizzando NAudio. Si crea uno stream che deriva da WaveStream e nel suo metodo di lettura sovrascritto, si restituiscono i campioni che è possibile generare al volo. Hai il controllo sulla dimensione dei buffer utilizzati dalla scheda audio che ti dà il controllo sulla latenza.

+0

Ho finalmente avuto la possibilità di provare NAudio ed è eccellente. Grazie per il puntatore. – RBarryYoung

0

Penso che sarà necessario utilizzare DirectSound (DirectX API) per quello. Funziona su buffer che è possibile riempire con i dati generati.

Forse qualcosa di simile this (here in via del ritorno macchina) aiuterà

1

Partenza this thread sul caricamento di un buffer di DirectSound con dati arbitrari e giocare.

Per commento: Sì, lo so. Dovrai tradurre il C++ in C# o VB.NET. Ma il concetto è ciò che è importante. Si crea un buffer DirectSound secondario e quindi lo si utilizza per eseguire lo streaming sul buffer primario e riprodurre.

+0

Beh, questo * non * VB.net o C#. In realtà non sembra affatto .Net. – 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

ho questo codice, ma si dovrà avere il codice per generare il file wav in 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