Lire le son dans .NET à l'aide des données de forme d'onde générés
Question
Comment puis-je jouer un son basé sur des données de forme d'onde que mon programme .NET génère des fonctions d'entrée d'utilisateur et mathématiques?
Par « données de forme d'onde » Je veux dire SPL Valeurs (niveau de pression acoustique) dans une série de temps d'intervalle fixe (probablement 44,1 kHz). Je présume que cela nécessite une sorte de flux arrangement tampon.
Notez que cela doit être en direct / en temps réel, donc il suffit de créer un fichier .wav puis jouer ce ne sera pas suffisant. VB.NET est préférable, mais C # est également acceptable.
Juste pour préciser:. Ce que je cherche est un simple exemple de code de travail
La solution
Vous pouvez le faire en utilisant NAudio . Vous créez un flux qui découle de WaveStream et dans sa méthode Read surchargée, vous retournez vos échantillons que vous pouvez générer à la volée. Vous avez le contrôle sur la taille des tampons utilisés par la carte son qui vous permet de contrôler le temps d'attente.
Autres conseils
Comment jouer à partir d'un tableau de 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();
}
Consultez ce fil sur le chargement des DirectSound tampon avec des données arbitraires et jouer .
Par commentaire: Oui, je sais. Vous aurez besoin de traduire le C ++ en C # ou VB.NET. Mais, le concept est ce qui est important. Vous créez un tampon DirectSound secondaire, puis l'utiliser pour diffuser sur votre tampon primaire et jouer.
Je pense que vous aurez besoin d'utiliser DirectSound ( API DirectX ) pour cela. Il travaille à l'extérieur des tampons que vous pouvez remplir avec vos données générées.
Peut-être quelque chose comme cette (
J'ai ce code, mais vous devez avoir un code pour générer votre fichier wav dans la mémoire. 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