Play sound in .NET using generated waveform data

后端 未结 6 1670
感情败类
感情败类 2021-02-02 03:55

How can I play a sound based on waveform data that my .NET program is generating from user input and mathematical functions?

By \"waveform data\" I mean SPL (sound press

相关标签:
6条回答
  • 2021-02-02 04:16

    You can do this using NAudio. You create a stream that derives from WaveStream and in its overriden Read method, you return your samples which you can generate on the fly. You have control over the size of the buffers used by the soundcard which gives you control over the latency.

    0 讨论(0)
  • 2021-02-02 04:16

    I have this code but you will have to have code to generate your wav file in memory.

    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
    
    0 讨论(0)
  • I think you'll need to use DirectSound (DirectX API) for that. It works off buffers which you could fill with your generated data.

    Maybe something like this (here in way back machine) will help

    0 讨论(0)
  • 2021-02-02 04:19

    Check out this thread on loading up a DirectSound buffer with arbitrary data and playing it.

    Per comment: Yes, I know. You will need to translate the C++ into C# or VB.NET. But, the concept is what's important. You create a secondary DirectSound buffer and then use it to stream over to your primary buffer and play.

    0 讨论(0)
  • 2021-02-02 04:31

    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 讨论(0)
  • 2021-02-02 04:35

    IrrKlang, BASS.net (under "Other APIs"), NAudio, CLAM, G3D, and others that can do this.

    0 讨论(0)
提交回复
热议问题