Riproduci suono in .NET utilizzando i dati delle forme d'onda generate
Domanda
Come posso riprodurre un suono in base ai dati della forma d'onda che il mio programma .NET sta generando da funzioni di input utente e matematiche?
Per "forma d'onda" intendo valori in una serie temporale intervallo fisso SPL (livello di pressione sonora) (probabilmente 44,1 kHz). Presumo che questo richiede un qualche tipo di accordo in streaming buffer.
Si noti che questo deve essere / live in tempo reale, quindi basta creare un file wav e poi giocare che non sarà sufficiente. VB.NET è preferito, ma C # è accettabile anche.
Giusto per chiarire:. Quello che sto cercando è un semplice esempio di codice di lavoro
Soluzione
È possibile farlo utilizzando NAudio . Si crea un flusso che deriva dal WaveStream e nel suo metodo di lettura sovresposta, ritorni vostri campioni che è possibile generare al volo. Lei ha il controllo sulla dimensione dei buffer utilizzati dal scheda audio, che permette di controllare la latenza.
Altri suggerimenti
Come si gioca da una serie di doppie
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();
}
questo thread su di carico fino un DirectSound buffer con dati arbitrari e giocare .
Per commento: Sì, lo so. Avrete bisogno di tradurre il C ++ in C # o VB.NET. Ma, il concetto è quello che è importante. Si crea un buffer DirectSound secondario e quindi utilizzarlo per lo streaming verso il buffer primario e giocare.
Credo che avrete bisogno di utilizzare DirectSound ( DirectX API) per questo. Funziona fuori i buffer che si potrebbe riempire con i vostri dati generati.
Forse qualcosa di simile questo ( qui in via del ritorno macchina) vi aiuterà
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