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

È stato utile?

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.

IrrKlang , BASS.net (tra le "Altre API"), NAudio , CLAM , G3D , e altri che possono fare questo.

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top