I am trying to read real time data from an accelerometer. Sampling frequency of the accelerometer is 2650Hz. I am getting proper data from serial port, but unable to match with the sampling frequency. The sampling frequency is varying from 2100Hz to 2400Hz and it is not stable. I am using a stop watch for timing reference.
Here is my code for receiving serial data.
private void toolStripButton12_Click(object sender, EventArgs e)
{
serialPort1.PortName = comboBox1.Text;
serialPort1.BaudRate = Convert.ToInt32(115200);
if (!serialPort1.IsOpen)
{
serialPort1.Open();
}
sw.Start();
serialPort1.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(SerialPort1_DataReceived);
}
}
private void SerialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
{
byteCount = serialPort1.BytesToRead;
if (byteCount > 4000)
byteCount = 4000;
if (e.EventType == SerialData.Eof)
return;
byte[] buffer = new byte[byteCount];
int readBytes = serialPort1.Read(buffer, 0, buffer.Length);
// FIFO Implementation
buffer.ToList().ForEach(b => newrecievedData1.Enqueue(b));
if (newrecievedData1.Count < 4000) return;
processdata3();
int i = 0;
{
while (i <= packet3.Length-4)
{
while (packet3[i++] != 69) ;
data = packet3[i++];
a = data << 8;
b = a + packet3[i++];
c = b << 8;
d = c + packet3[i++];
Port1data.Add(d);
countbyte[0]++;
tick = (double)countbyte[0];
}
}
t = (double)sw.Elapsed.TotalSeconds;
Sampling frequency = tick / t;
}
try
{
this.Invoke(new EventHandler(DisplayText));
}
catch
{
}
}
Int32[] packet3;
private Int32[] processdata3()
{
if (newrecievedData1.Count >= 4000)
{
packet3 = Enumerable.Range(0, 4000).Select(h => newrecievedData1.Dequeue()).ToArray();
}
return packet3;
}
I want to exactly get 2650 Hz sampling frequency all the time.Any help is highly appreciated.
That is 0.337 ms per sample. That is really pushing the upper limits of how much code can be done per sample.
Without some major optimization to your algorithms (possibly using custom collections designed specifically for your workload) I don't think your requirements are reachable using managed code.
Related
I have recently created an app that is recieving data send through UART from my STM device. The data I try to send is an array of floats - float[512].
The data is send as pure binary - not string. Generally idea is 4xbyte = float.
I am sure that data that I'm sending is good. Checked it with program called "Terminal" and then IEEE 754 Converter.
My program
In program I choose COMport from available and other parameters.
(by default they are my COM adapter parameters). I open connection and then when by STM finishes sending data I'm clicking on "Odebrane" button so it will display data in TextBox
The problem is that I'm not recieving all data.
And I have no idea what is the cause.
private List<float> lista = new List<float>();
private float[] fDane = new float[1024];
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
getAvailablePorts();
tb_Rx.Text = "Wprowadź parametry transmisji";
cb_BaudRate.Text = "9600";
cb_DataBits.Text = "8";
cb_Handshake.Text = "None";
cb_Parity.Text = "None";
cb_StopBits.Text = "One";
}
private void SerialP_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
int size = sp.BytesToRead;
byte[] bArray = new byte[size];
float[] fArray = new float[size / 4];
sp.Read(bArray, 0, size);
for (uint i = 0; i < size / 4; i++)
{
fArray[i] = ByteToFloat(bArray, i); // change 4 bytes to float
lista.Add(fArray[i]);
}
}
private float ByteToFloat(byte[] input, UInt32 i)
{
byte[] Array = new[] { input[4 * i], input[4 * i + 1], input[4 * i + 2], input[4 * i + 3] };
return BitConverter.ToSingle(Array, 0);
}
private void bt_transform_Click(object sender, EventArgs e)
{
float[] fDane = lista.ToArray();
for(UInt32 i = 0; i < fDane.Length; i++)
{
RxPisz(fDane[i]);
}
}
------------------------- SOLVED ---------------------
changed dataRecieved interrupt handler
private void SerialP_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
byte[] bArray = new byte[4*numberOfSamples];
float[] fArray = new float[numberOfSamples];
int previouse = counterOfRecBytes;
counterOfRecBytes += sp.BytesToRead;
sp.Read(bArray, previouse, (counterOfRecBytes - previouse));
if (counterOfRecBytes == 4*numberOfSamples)
{
for (uint i = 0; i < numberOfSamples; i++)
{
fArray[i] = ByteToFloat(bArray, i); // change 4 bytes to float
lista.Add(fArray[i]);
}
counterOfRecBytes = 0;
}
}
I think you are not reading data at the good speed, try to change BaudRate from 9600 to 19200.
My purpose in below program is getting 16 bytes of data from microcontroller and processing data for appropriate instructions. There are a lot of related questions and answers here but I couldnt find anything about in below issue. I can get 16 bytes from MCU. Values of bytes are correct and I can see them in dataGridView but the sequence of bytes is changing . For example at first MCUData[0] = 0x01 , MCUData[1] = 0xFE , MCUData[2] = 0xCC then it changes to MCUData[0] = 0xFE , MCUData[1] = 0xCC , MCUData[2] = 0x01. İt is like some problem shifting my datas in byte array. I am sure my MCU is sending data correctly because I checked in one of serial terminal program. My code is in below
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
using System.Threading;
namespace SerialCommunicationMCU
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
dataGridView1.Columns.Add("MCUData", "Byte Name");
dataGridView1.Columns.Add("MCUData", "Byte Value");
}
public System.IO.Ports.SerialPort SerialPc;
#region Variables
public string AvailablePort;
public string[] Ports = SerialPort.GetPortNames();
byte[] MCUData = new byte[16];
#endregion
private void Connect_Click(object sender, EventArgs e)
{
DataGreedByteNameShow();
SerialConnectandRead();
ConnectButton.Enabled = false;
DisconnectButton.Enabled = true;
}
private void Disconnect_Click(object sender, EventArgs e)
{
SerialPc.Close();
ConnectButton.Enabled = true;
DisconnectButton.Enabled = false;
}
public void SerialConnectandRead()
{
SerialPc = new SerialPort(AvailablePort, 115200, Parity.None, 8, StopBits.One);
try
{
SerialPc.Open();
SerialPc.DataReceived += new SerialDataReceivedEventHandler(SerialPc_DataReceived);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "Serial Port Error");
}
}
private void SerialPc_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPc.DiscardNull = false;
SerialPc.Read(MCUData, 0, 16);
SerialPc.ReceivedBytesThreshold = 16;
DataGreedByteValueShow();
}
private void Form1_Load(object sender, EventArgs e)
{
foreach (string port in Ports)
{
comboBox1.Items.Add(port);
}
DisconnectButton.Enabled = false;
}
public void DataGreedByteNameShow()
{
dataGridView1.Rows.Add("MCUData[0]");
dataGridView1.Rows.Add("MCUData[1]");
dataGridView1.Rows.Add("MCUData[2]");
dataGridView1.Rows.Add("MCUData[3]");
dataGridView1.Rows.Add("MCUData[4]");
dataGridView1.Rows.Add("MCUData[5]");
dataGridView1.Rows.Add("MCUData[6]");
dataGridView1.Rows.Add("MCUData[7]");
dataGridView1.Rows.Add("MCUData[8]");
dataGridView1.Rows.Add("MCUData[9]");
dataGridView1.Rows.Add("MCUData[10]");
dataGridView1.Rows.Add("MCUData[11]");
dataGridView1.Rows.Add("MCUData[12]");
dataGridView1.Rows.Add("MCUData[13]");
dataGridView1.Rows.Add("MCUData[14]");
dataGridView1.Rows.Add("MCUData[15]");
}
private void DataGreedByteValueShow()
{
dataGridView1.Rows[0].Cells[1].Value = MCUData[0];
dataGridView1.Rows[1].Cells[1].Value = MCUData[1];
dataGridView1.Rows[2].Cells[1].Value = MCUData[2];
dataGridView1.Rows[3].Cells[1].Value = MCUData[3];
dataGridView1.Rows[4].Cells[1].Value = MCUData[4];
dataGridView1.Rows[5].Cells[1].Value = MCUData[5];
dataGridView1.Rows[6].Cells[1].Value = MCUData[6];
dataGridView1.Rows[7].Cells[1].Value = MCUData[7];
dataGridView1.Rows[8].Cells[1].Value = MCUData[8];
dataGridView1.Rows[9].Cells[1].Value = MCUData[9];
dataGridView1.Rows[10].Cells[1].Value = MCUData[10];
dataGridView1.Rows[11].Cells[1].Value = MCUData[11];
dataGridView1.Rows[12].Cells[1].Value = MCUData[12];
dataGridView1.Rows[13].Cells[1].Value = MCUData[13];
dataGridView1.Rows[14].Cells[1].Value = MCUData[14];
dataGridView1.Rows[15].Cells[1].Value = MCUData[15];
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
AvailablePort = comboBox1.SelectedItem.ToString();
}
}
}
According to the MSDN documentation: http://msdn.microsoft.com/en-us/library/ms143549(v=vs.110).aspx
Reads a number of bytes from the SerialPort input buffer and writes
those bytes into a byte array at the specified offset.
public int Read(
byte[] buffer,
int offset,
int count
)
Here's how your current code uses the function:
SerialPc.Read(MCUData, 0, 16);
Your buffer is a global variable defined as:
byte[] MCUData = new byte[16];
This is one way that you can use to solve your problem:
List<byte> MCUDataOverTime = new List<byte>();
private void SerialPc_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPc.DiscardNull = false;
SerialPc.Read(MCUData, 0, 16);
MCUDataOverTime.AddRange(MCUData);
SerialPc.ReceivedBytesThreshold = 16;
DataGreedByteValueShow();
}
private void DataGreedByteValueShow()
{
if (MCUDataOverTime.Count >= 16)
{
dataGridView1.Rows[0].Cells[1].Value = MCUDataOverTime[0];
dataGridView1.Rows[1].Cells[1].Value = MCUDataOverTime[1];
dataGridView1.Rows[2].Cells[1].Value = MCUDataOverTime[2];
dataGridView1.Rows[3].Cells[1].Value = MCUDataOverTime[3];
dataGridView1.Rows[4].Cells[1].Value = MCUDataOverTime[4];
dataGridView1.Rows[5].Cells[1].Value = MCUDataOverTime[5];
dataGridView1.Rows[6].Cells[1].Value = MCUDataOverTime[6];
dataGridView1.Rows[7].Cells[1].Value = MCUDataOverTime[7];
dataGridView1.Rows[8].Cells[1].Value = MCUDataOverTime[8];
dataGridView1.Rows[9].Cells[1].Value = MCUDataOverTime[9];
dataGridView1.Rows[10].Cells[1].Value = MCUDataOverTime[10];
dataGridView1.Rows[11].Cells[1].Value = MCUDataOverTime[11];
dataGridView1.Rows[12].Cells[1].Value = MCUDataOverTime[12];
dataGridView1.Rows[13].Cells[1].Value = MCUDataOverTime[13];
dataGridView1.Rows[14].Cells[1].Value = MCUDataOverTime[14];
dataGridView1.Rows[15].Cells[1].Value = MCUDataOverTime[15];
}
}
The code above would solve the problem where your values change over time. It's happening in the first place because every time SerialPc_DataReceived() is called, you've set it so that every "Read" will store its result in your MCUData byte array. Consequently, it will end up overwriting your MCUData array since you've hardcoded the start-from offset to 0.
That's why it looks like your data is being shifted. You have to understand, fundamentally, these streams don't conveniently store data for you in the way where an index of 0 means the beginning of time (when the stream first opened and started). If you want it to work that way, you'll have to store it yourself.
Please note that the code above does not attempt to empty the serial input buffer. You're pulling 16 bytes every time you do a read when the DataReceived is called, but I wonder if the MCU is sending a lot more than that with every DataReceived message.
Edit:
List<byte> MCUDataOverTime = new List<byte>();
private void SerialPc_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPc.DiscardNull = false;
int readcount = 0;
byte [] temp;
do
{
readcount = SerialPc.Read(MCUData, 0, 16);
if (readcount > 0)
{
temp = new byte[readcount];
Array.Copy(MCUData, 0, temp, 0, readcount);
MCUDataOverTime.AddRange(temp);
SerialPc.ReceivedBytesThreshold = 16;
DataGreedByteValueShow();
}
} while (readcount > 0);
}
private void DataGreedByteValueShow()
{
if (MCUDataOverTime.Count >= 16)
{
dataGridView1.Rows[0].Cells[1].Value = MCUDataOverTime[0];
dataGridView1.Rows[1].Cells[1].Value = MCUDataOverTime[1];
dataGridView1.Rows[2].Cells[1].Value = MCUDataOverTime[2];
dataGridView1.Rows[3].Cells[1].Value = MCUDataOverTime[3];
dataGridView1.Rows[4].Cells[1].Value = MCUDataOverTime[4];
dataGridView1.Rows[5].Cells[1].Value = MCUDataOverTime[5];
dataGridView1.Rows[6].Cells[1].Value = MCUDataOverTime[6];
dataGridView1.Rows[7].Cells[1].Value = MCUDataOverTime[7];
dataGridView1.Rows[8].Cells[1].Value = MCUDataOverTime[8];
dataGridView1.Rows[9].Cells[1].Value = MCUDataOverTime[9];
dataGridView1.Rows[10].Cells[1].Value = MCUDataOverTime[10];
dataGridView1.Rows[11].Cells[1].Value = MCUDataOverTime[11];
dataGridView1.Rows[12].Cells[1].Value = MCUDataOverTime[12];
dataGridView1.Rows[13].Cells[1].Value = MCUDataOverTime[13];
dataGridView1.Rows[14].Cells[1].Value = MCUDataOverTime[14];
dataGridView1.Rows[15].Cells[1].Value = MCUDataOverTime[15];
}
}
I'd increase the size of MCUData to 1024 bytes or more since 16 bytes seems kind of small. The next thing that you'd need to do is keep track of the start and end points of each frame. I'm guessing that it'll always be 16 in the case of your microcontroller but in general you should have the microcontroller throwing out null values or a special string of symbols to indicate the end of a message.
Whole day I was looking for some tutorial or piece of code, "just" to play simple sin wave for "infinity" time. I know it sounds a little crazy.
But I want to be able to change frequency of tone in time, for instance - increase it.
Imagine that I want to play tone A, and increase it to C in "+5" frequency steps each 3ms (it's really just example), don't want to have free places, stop the tone.
Is it possible? Or can you help me?
Use NAudio library for audio output.
Make notes wave provider:
class NotesWaveProvider : WaveProvider32
{
public NotesWaveProvider(Queue<Note> notes)
{
this.Notes = notes;
}
public readonly Queue<Note> Notes;
int sample = 0;
Note NextNote()
{
for (; ; )
{
if (Notes.Count == 0)
return null;
var note = Notes.Peek();
if (sample < note.Duration.TotalSeconds * WaveFormat.SampleRate)
return note;
Notes.Dequeue();
sample = 0;
}
}
public override int Read(float[] buffer, int offset, int sampleCount)
{
int sampleRate = WaveFormat.SampleRate;
for (int n = 0; n < sampleCount; n++)
{
var note = NextNote();
if (note == null)
buffer[n + offset] = 0;
else
buffer[n + offset] = (float)(note.Amplitude * Math.Sin((2 * Math.PI * sample * note.Frequency) / sampleRate));
sample++;
}
return sampleCount;
}
}
class Note
{
public float Frequency;
public float Amplitude = 1.0f;
public TimeSpan Duration = TimeSpan.FromMilliseconds(50);
}
start play:
WaveOut waveOut;
this.Notes = new Queue<Note>(new[] { new Note { Frequency = 1000 }, new Note { Frequency = 1100 } });
var waveProvider = new NotesWaveProvider(Notes);
waveProvider.SetWaveFormat(16000, 1); // 16kHz mono
waveOut = new WaveOut();
waveOut.Init(waveProvider);
waveOut.Play();
add new notes:
void Timer_Tick(...)
{
if (Notes.Count < 10)
Notes.Add(new Note{Frecuency = 900});
}
ps this code is idea only. for real using add mt-locking etc
use NAudio and SineWaveProvider32: http://mark-dot-net.blogspot.com/2009/10/playback-of-sine-wave-in-naudio.html
private WaveOut waveOut;
private void button1_Click(object sender, EventArgs e)
{
StartStopSineWave();
}
private void StartStopSineWave()
{
if (waveOut == null)
{
var sineWaveProvider = new SineWaveProvider32();
sineWaveProvider.SetWaveFormat(16000, 1); // 16kHz mono
sineWaveProvider.Frequency = 1000;
sineWaveProvider.Amplitude = 0.25f;
waveOut = new WaveOut();
waveOut.Init(sineWaveProvider);
waveOut.Play();
}
else
{
waveOut.Stop();
waveOut.Dispose();
waveOut = null;
}
}
I want to calculate download speed as kbps (kb per second). There's a problem in the code, it doesn't show actual speed. And I'm really tired of this work. Also, when using (TotalDownloadSize / ElapsedTime) formula it shows more realistic results but you know it will get average value and it will be stupidity.
It usually gives 4000 and it's basicly because of chunk 4096 when I set it to 128 that time I get 50/100/125 values.
DateTime dlElapsed;
private delegate void UpdateProgessCallback(Int64 BytesRead, Int64 TotalBytes, Int32 CurrentBytes);
private void UpdateProgress(Int64 BytesRead, Int64 TotalBytes, Int32 CurrentBytes)
{
DateTime Elapsed = DateTime.Now;
var progress = Convert.ToInt32((BytesRead * 100) / TotalBytes);
var elaps = (Elapsed - dlElapsed).TotalSeconds;
long kbps;
if (elaps > 0)
{
kbps = Convert.ToInt64((CurrentBytes / elaps) / 1024);
updateLabelText(String.Format("Downloading ({0} kbps)...", kbps));
}
// Make progress on the progress bar
if (progress < progressBar1.Maximum)
{
progressBar1.Value = progress;
}
else
{
progressBar1.Value = progressBar1.Maximum;
}
dlElapsed = DateTime.Now;
}
private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
// Some stuff here...
int byteSize = 0;
byte[] downBuffer = new byte[4096];
FileStream strLocal= new FileStream(path, FileMode.Create, FileAccess.Write);
dlElapsed = DateTime.Now;
while ((byteSize = stream.Read(downBuffer, 0, downBuffer.Length)) > 0)
{
strLocal.Write(downBuffer, 0, byteSize);
this.Invoke(new UpdateProgessCallback(this.UpdateProgress),
new object[] { strLocal.Length, totalbyte, byteSize});
}
updateLabelText("Download complete!");
strLocal.Close();
}
}
So where's the problem?
So where's the problem?
You're coarsely sampling something that varies a lot.
Consider buffering measurements and averaging the last 5 or so. Look for implementations of a "running average".
Well, my first comment would be that your code is not thread safe, so when you set dlElapsed = DateTime.Now;, it's not the same dlElapsed value that UpdateProgress is going to be checking.
at the moment im trying to figure out how i can manage to play a wave file in C# by filling up the secondary buffer with data from the wave file through threading and then play the wave file.
Any help or sample coding i can use?
thanks
sample code being used:
public delegate void PullAudio(short[] buffer, int length);
public class SoundPlayer : IDisposable
{
private Device soundDevice;
private SecondaryBuffer soundBuffer;
private int samplesPerUpdate;
private AutoResetEvent[] fillEvent = new AutoResetEvent[2];
private Thread thread;
private PullAudio pullAudio;
private short channels;
private bool halted;
private bool running;
public SoundPlayer(Control owner, PullAudio pullAudio, short channels)
{
this.channels = channels;
this.pullAudio = pullAudio;
this.soundDevice = new Device();
this.soundDevice.SetCooperativeLevel(owner, CooperativeLevel.Priority);
// Set up our wave format to 44,100Hz, with 16 bit resolution
WaveFormat wf = new WaveFormat();
wf.FormatTag = WaveFormatTag.Pcm;
wf.SamplesPerSecond = 44100;
wf.BitsPerSample = 16;
wf.Channels = channels;
wf.BlockAlign = (short)(wf.Channels * wf.BitsPerSample / 8);
wf.AverageBytesPerSecond = wf.SamplesPerSecond * wf.BlockAlign;
this.samplesPerUpdate = 512;
// Create a buffer with 2 seconds of sample data
BufferDescription bufferDesc = new BufferDescription(wf);
bufferDesc.BufferBytes = this.samplesPerUpdate * wf.BlockAlign * 2;
bufferDesc.ControlPositionNotify = true;
bufferDesc.GlobalFocus = true;
this.soundBuffer = new SecondaryBuffer(bufferDesc, this.soundDevice);
Notify notify = new Notify(this.soundBuffer);
fillEvent[0] = new AutoResetEvent(false);
fillEvent[1] = new AutoResetEvent(false);
// Set up two notification events, one at halfway, and one at the end of the buffer
BufferPositionNotify[] posNotify = new BufferPositionNotify[2];
posNotify[0] = new BufferPositionNotify();
posNotify[0].Offset = bufferDesc.BufferBytes / 2 - 1;
posNotify[0].EventNotifyHandle = fillEvent[0].Handle;
posNotify[1] = new BufferPositionNotify();
posNotify[1].Offset = bufferDesc.BufferBytes - 1;
posNotify[1].EventNotifyHandle = fillEvent[1].Handle;
notify.SetNotificationPositions(posNotify);
this.thread = new Thread(new ThreadStart(SoundPlayback));
this.thread.Priority = ThreadPriority.Highest;
this.Pause();
this.running = true;
this.thread.Start();
}
public void Pause()
{
if (this.halted) return;
this.halted = true;
Monitor.Enter(this.thread);
}
public void Resume()
{
if (!this.halted) return;
this.halted = false;
Monitor.Pulse(this.thread);
Monitor.Exit(this.thread);
}
private void SoundPlayback()
{
lock (this.thread)
{
if (!this.running) return;
// Set up the initial sound buffer to be the full length
int bufferLength = this.samplesPerUpdate * 2 * this.channels;
short[] soundData = new short[bufferLength];
// Prime it with the first x seconds of data
this.pullAudio(soundData, soundData.Length);
this.soundBuffer.Write(0, soundData, LockFlag.None);
// Start it playing
this.soundBuffer.Play(0, BufferPlayFlags.Looping);
int lastWritten = 0;
while (this.running)
{
if (this.halted)
{
Monitor.Pulse(this.thread);
Monitor.Wait(this.thread);
}
// Wait on one of the notification events
WaitHandle.WaitAny(this.fillEvent, 3, true);
// Get the current play position (divide by two because we are using 16 bit samples)
int tmp = this.soundBuffer.PlayPosition / 2;
// Generate new sounds from lastWritten to tmp in the sound buffer
if (tmp == lastWritten)
{
continue;
}
else
{
soundData = new short[(tmp - lastWritten + bufferLength) % bufferLength];
}
this.pullAudio(soundData, soundData.Length);
// Write in the generated data
soundBuffer.Write(lastWritten * 2, soundData, LockFlag.None);
// Save the position we were at
lastWritten = tmp;
}
}
}
public void Dispose()
{
this.running = false;
this.Resume();
if (this.soundBuffer != null)
{
this.soundBuffer.Dispose();
}
if (this.soundDevice != null)
{
this.soundDevice.Dispose();
}
}
}
}
The concept is the same that im using but i can't manage to get a set on wave byte [] data to play
I have not done this.
But the first place i would look is XNA.
I know that the c# managed directx project was ditched in favor of XNA and i have found it to be good for graphics - i prefer using it to directx.
what is the reason that you decided not to just use soundplayer, as per this msdn entry below?
private SoundPlayer Player = new SoundPlayer();
private void loadSoundAsync()
{
// Note: You may need to change the location specified based on
// the location of the sound to be played.
this.Player.SoundLocation = http://www.tailspintoys.com/sounds/stop.wav";
this.Player.LoadAsync();
}
private void Player_LoadCompleted (
object sender,
System.ComponentModel.AsyncCompletedEventArgs e)
{
if (this.Player.IsLoadCompleted)
{
this.Player.PlaySync();
}
}
usually i just load them all up in a thread, or asynch delegate, then play or playsynch them when needed.
You can use the DirectSound support in SlimDX: http://slimdx.org/ :-)
You can use nBASS or better FMOD both are great audio libraries and can work nicely together with .NET.
DirectSound is where you want to go. It's a piece of cake to use, but I'm not sure what formats it can play besides .wav
http://msdn.microsoft.com/en-us/library/windows/desktop/ee416960(v=vs.85).aspx