代码之家  ›  专栏  ›  技术社区  ›  RBarryYoung

使用生成的波形数据在.NET中播放声音

  •  7
  • RBarryYoung  · 技术社区  · 15 年前

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

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

    注意,这必须是实时/实时的,所以只需创建一个.wav文件,然后播放就不够了。最好使用vb.net,但也可以使用c_。

    只是澄清一下:我要找的是一个简单的工作代码示例。

    6 回复  |  直到 7 年前
        1
  •  4
  •   Mark Heath    15 年前

    你可以用 NAudio . 您创建了一个从wavestream派生的流,在它的overriden read方法中,您将返回您可以动态生成的示例。您可以控制声卡使用的缓冲区的大小,从而控制延迟。

        2
  •  3
  •   Basil    11 年前

    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();
        }
    
        3
  •  1
  •   JP Alioto    15 年前

    退房 this thread 关于加载一个 DirectSound 用任意数据缓冲并播放。

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

        4
  •  1
  •   Peter Mortensen icecrime    11 年前

    IrrKlang , BASS.net (在“其他API”下) NAudio , CLAM , G3D 以及其他可以做到这一点的人。

        5
  •  0
  •   Donald Byrd    11 年前

    我想你需要用 DirectSound ( DirectX API)。它使用缓冲区,您可以用生成的数据填充这些缓冲区。

    可能有点像 this ( here 在返回机器的路上)会有帮助的。

        6
  •  0
  •   John Alexander    8 年前

    我有这段代码,但你必须有代码才能在内存中生成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