2009-07-05 85 views
7

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

所谓“波形数据”我的意思SPL(声压等级)在一个固定的时间间隔时间序列(可能44.1千赫)的值。我认为这需要某种流缓冲区安排。

注意,这必须是现场/实时性,所以只创建一个.wav文件,然后播放这将是不够的。 VB.NET是首选,但C#也可以接受。

只是为了澄清:我所寻找的是一个简单的工作代码示例。

+0

我终于开始尝试NAudio解决方案了,它非常出色!比我所担心的要容易得多,容易,我真的应该很久以前尝试过。 – RBarryYoung 2012-12-28 21:01:42

+1

这个问题更具操作性的答案是堆栈溢出问题* [NAudio使用C#播放正弦波x毫秒](http://stackoverflow.com/questions/5485577)*。 – 2015-03-29 16:41:29

回答

4

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

0

我认为你需要使用DirectSoundDirectX API)为。它处理缓冲区,您可以使用生成的数据填充缓冲区。

也许像thishere在回来的路上机)将帮助

1

退房上装载了一个DirectSound缓冲区任意数据和玩它this thread

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

+0

那是*不* VB.net或C#。事实上,它看起来不像.Net。 – RBarryYoung 2009-07-06 04:13:58

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

我有这样的代码,但是你必须有一些代码在内存中生成的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