2009-07-05 48 views
7

.NETプログラムがユーザー入力と数学関数から生成している波形データに基づいてサウンドを再生するにはどうすればよいですか?生成された波形データを使用して.NETでサウンドを再生

「波形データ」とは、固定間隔の時系列(おそらく44.1 kHz)のSPL(音圧レベル)値を意味します。私は、これが何らかの種類のストリーミングバッファの配置を必要とすると推測します。

ライブ/リアルタイムでなければならないことに注意してください。だから.wavファイルを作成して再生するだけでは不十分です。 VB.NETが望ましいですが、C#も受け入れられます。

私が探しているのは、単純な作業コードの例です。

+0

最終的にNAudioソリューションを試してみたところ、それは素晴らしいです!私が恐れていたよりもはるかに良くて簡単でした。私はずっと前にそれを試していたはずです。 – RBarryYoung

+1

この質問に対するより運用的な答えは、Stack Overflowの質問* [C#を使用してxミリ秒の正弦波を再生するNAudio](http://stackoverflow.com/questions/5485577)*です。 –

答えて

4

NAudioを使用してこれを行うことができます。 WaveStreamから派生したストリームを作成し、そのオーバーライドされたReadメソッドで、生成したサンプルを即座に返します。サウンドカードで使用されるバッファのサイズを制御することができます。これにより、遅延を制御できます。

+0

私は最終的にNAudioを試してみました。ポインタありがとう。 – RBarryYoung

0

DirectSoundDirectX API)を使用する必要があると思います。生成されたデータで満たすことができるバッファーを無効にします。

たぶんthis(バックマシンのようにhere)のようなものが

1

は、任意のデータでDirectSoundバッファをロードし、それを再生するにthis threadをチェックするのに役立ちます。

コメント数:はい、わかっています。 C++をC#またはVB.NETに変換する必要があります。しかし、そのコンセプトは重要です。セカンダリDirectSoundバッファを作成し、それを使用してプライマリバッファにストリームして再生します。

+0

これはVB.netやC#ではありません。実際、それは.Netのようには見えません。 – RBarryYoung

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 
関連する問題