7

如何根据 .NET 程序从用户输入和数学函数生成的波形数据播放声音?

“波形数据”是指固定间隔时间序列(可能为 44.1 kHz)中的 SPL(声压级)值。我认为这需要某种流缓冲安排。

请注意,这必须是实时/实时的,因此仅创建一个 .wav 文件然后播放是不够的。VB.NET 是首选,但 C# 也是可以接受的。

澄清一下:我正在寻找的是一个简单的工作代码示例。

4

6 回答 6

4

您可以使用NAudio做到这一点。您创建一个派生自 WaveStream 的流,并在其重写的 Read 方法中返回您可以即时生成的样本。您可以控制声卡使用的缓冲区大小,从而控制延迟。

于 2009-07-05T18:53:52.133 回答
3

如何从一系列双打中玩

    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();
    }
于 2014-02-02T16:11:03.463 回答
1

查看此线程,了解如何使用任意数据加载DirectSound缓冲区并进行播放。

每条评论:是的,我知道。您需要将 C++ 翻译成 C# 或 VB.NET。但是,概念才是最重要的。您创建一个辅助 DirectSound 缓冲区,然后使用它流式传输到您的主缓冲区并播放。

于 2009-07-05T18:17:33.710 回答
1

IrrKlangBASS.net(在“其他 API”下)、NAudioCLAMG3D和其他可以做到这一点的人。

于 2009-11-14T18:46:17.187 回答
0

我认为您需要为此使用DirectSoundDirectX API)。它适用于您可以用生成的数据填充的缓冲区。

也许像这样的东西(回程机器中)会有所帮助

于 2009-07-05T17:59:39.650 回答
0

我有这个代码,但你必须有代码才能在内存中生成你的 wav 文件。

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
于 2016-07-20T14:03:47.473 回答