Implement Dispose to my method - c#

I have a Winform application that uses Pcapdot.Net DLLs and plays Pcap files.
When I am playing a file in a loop I can see that the application memory is raised until a crash occurs and in stack trace I can see that this happens in the method that plays the file.
So I was thinking to add dispose method and see if it can solve this crash.
So I added to my class a variable private bool _disposed;
and methods:
public void Dispose()
{
Dispose(true);
}
private virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
}
_disposed = true;
}
}
my play method:
public bool sendBuffer(PacketDevice packetDevice)
{
int count = 0;
bool bContinuePlay = true;
PacketDevice selectedOutputDevice = packetDevice;
_shouldContinue = true;
_isStop = true;
_stopButton = true;
OfflinePacketDevice selectedInputDevice = new OfflinePacketDevice(_filePath.FullName); //open the capture file
DateTime time = DateTime.Now;
double totalTime = 0;
double totalDelayTime = 0;
double deletaTime = 0;
using (inputCommunicator = selectedInputDevice.Open(65536, PacketDeviceOpenAttributes.Promiscuous, 1000))
{
using (OutputCommunicator = selectedOutputDevice.Open(100, PacketDeviceOpenAttributes.Promiscuous, 1000))
{
ThreadStart tStarter = delegate { openAdapterForStatistics(selectedOutputDevice); };
Thread thread = new Thread(tStarter);
thread.IsBackground = true;
thread.Start();
DateTime lastTime = DateTime.MinValue;
double delayTime = 0;
Packet packet;
IEnumerable<Packet> packets;
while (inputCommunicator.ReceivePacket(out packet) == PacketCommunicatorReceiveResult.Ok && _isStop) //fill the buffer with the packets from the file
{
if (count < _numberOfPacketsInfile)
{
using (PacketSendBuffer mSendBuffer = new PacketSendBuffer((uint)packet.Length * 4))
{
if (_isBurst)
{
if (lastTime != DateTime.MinValue)
{
if (packet != null)
{
delayTime = (packet.Timestamp.Subtract(lastTime).TotalMilliseconds) / _playSpeed; //delay between packets
}
if (delayTime > 1000)
{
if (_startTimer != null)
{
_startTimer(delayTime, EventArgs.Empty);
}
_delayForNextPacket = delayTime;
}
totalDelayTime += delayTime;
delayTime = delayTime - deletaTime;
if (delayTime < 0)
{
delayTime = 0;
}
if (evePacketProgress != null)
{
int packetProgressPrecentage = (int)(((double)_numberOfSendPackets / _numberOfPacketsInfile) * 100);
evePacketProgress(packetProgressPrecentage);
}
_mrEvent.WaitOne((int)delayTime);
if (_stopTimer != null)
{
_stopTimer(delayTime, EventArgs.Empty);
}
} //end if
} // end if _brust
if (_fragmentation)
{
foreach (Packet item in splitPacket(packet, 1))
{
mSendBuffer.Enqueue(item);
}
}
else if (packet != null)
{
lastTime = packet.Timestamp;
mSendBuffer.Enqueue(packet);
}
if (evePacketProgress != null)
{
int packetProgressPrecentage = (int)(((double)_numberOfSendPackets / _numberOfPacketsInfile) * 100);
evePacketProgress(packetProgressPrecentage);
}
try
{
OutputCommunicator.Transmit(mSendBuffer, _isBurst); //send the packet
_numberOfSendPackets++;
}
catch (Exception)
{
}
}///
totalTime = DateTime.Now.Subtract(time).TotalMilliseconds;
deletaTime = totalTime - totalDelayTime;
count++;
}
} //end while
}
}
return bContinuePlay;
}
the crash occur in the line DateTime lastTime = DateTime.MinValue;
I am a new developer and do not know how to proceed from here.
Any help is welcome

The Dispose method is used to free unmanaged resources, in other words, what isn't in ".NET World", like a TCP or database connection.
When CLR finds that your program is running out of memory, it automaticaly invokes Garbage Collector, that free the objects you are not using anymore.
You only need to implement IDisposable if you have to free unmanaged resources. For details implementing IDisposable, you can find a lot of articles online. For instace, you are forgeting of implement your class finalizer.
So, if the problem is in the method that play the files, you must first find what is causing the memory to increase and cannot be released by GC.
I don't know Pcapdot.Net, but try to find a method for releasing the file being played, or something like this. Maybe you don't need to implement IDisposable, just add the call for this method.

Related

Render to winforms picturebox over and over again

I have some bugs that need fixing, one of them involves an out of memory error.
Does anyone know how to do this properly? Thanks, I don't want it to be too messy, or too complicated. I just want to treat a new image as a buffer to render another image to (because of positional changes), and do it via a background thread. Not the UI thread (Too slow likely).
I get out of memory errors, and such. Also not able to access members of Form1 from within the thread function (images and the like throw access errors such as "Object already in use")
Here is my code:
System.Threading.Thread t;
public Image b;
public Bitmap c;
public Bitmap d;
public Bitmap e;
public Bitmap bg;
public Bitmap spr;
int spritex = 0;
int spritey = 0;
int spritedir = 1;
public Form1()
{
InitializeComponent();
Text = "Escape The Hypno Mansion!!".ToString();
t = new System.Threading.Thread(DoThisAllTheTime);
t.Start();
textBox1.Text = "Press Begin button to start!";
pictureBox1.Image = Image.FromFile(#"Images\introgirl.jpg");
b = new Bitmap(#"Images\introgirl.jpg");
c = new Bitmap(#"Images\sprite.png");
var graphics = Graphics.FromImage(b);
Pen blackpen = new Pen(Color.Black, 3);
graphics.DrawLine(blackpen, 0, 0, 100, 100);
graphics.DrawImage(c, new Point(500, 500));
pictureBox1.Image = b;
//pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
}
public void DoThisAllTheTime()
{
while (true)
{
Point p = new Point(spritex, spritey);
bg = new Bitmap(#"Images\test.bmp");
spr = new Bitmap(#"Images\sprite.png");
using (var graphics = Graphics.FromImage(bg))
{
graphics.DrawImage(spr, p);
}
if (pictureBox1.Image != null)
{
pictureBox1.Image.Dispose();
}
pictureBox1.Image = bg;
pictureBox1.Invalidate();
if (spritedir == 1) { spritex += 5; }
if (spritedir == 2) { spritex -= 5; }
if (spritex < 0) { spritex = 0; spritedir = 1; }
if (spritex > 700) { spritex = 700; spritedir = 2; }
}
}
The reason you can't change the image in your picturebox is because the thread that created the image is not the thread that created the picturebox.
In a debugger you can check this by asking the picturebox for InvokeRequired (function Control.IsInvokeRequired) just before changing the function.
So let's rewrite your function and show that modern classes Like Task are much easier to use the your thread.
I'll start your task when the form is loading, and try to stop it when the form is closing.
private Task myTask = null;
private CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
private void OnFormLoading(object sender, EventArgs e)
{
// Start the task
this.myTask = Task.Run( () => DoMyWork(this.cancellationTokenSource.Token));
}
private void OnFormClosing(object sender, FormClosingEventArgs e)
{
// if the Task is still running, ask it to stop itself:
if (myTask != null && !myTask.IsCompleted)
{ // ask the task to stop and wait until it is completed:
this.cancellationTokenSource.Cancel();
// all Tokens extractes from this source will get state CancellationRequested
// wait maximum 5 seconds until the task is completed:
this.UseWaitCursor = true;
this.myTask.Wait(TimeSpan.FromSeconds(5));
this.UseWaitCursor = false;
// cancel closing if the task is still not completed
e.Cancel = !this.myTask.Completed;
}
}
Now the function DoMyWork:
private void DoMyWork(CancellationToken cancellationToken)
{
// Do the same as in your DoThisAllTheTime
// except that you regularly check cancellationToken.IsCancelRequested:
while(!cancellationToken.IsCancelRequested)
{
// calculate the image to display
var imageToDisplay = ...
this.DisplayImage(imageToDisplay);
}
}
void DisplayImage(Image imageToDisplay)
{
if (this.pictureBox1.InvokeRequired)
{
this.Invoke(new MethodInvoker( () => this.DisplayImage(imageToDisplay)));
}
else
{
this.PictureBox1.Image = imageToDisplay;
}
}
See:
How to cancel a Task and its children
Use InvokeRequired with lambda expression
Dispose every disposable instances before the loop ends. Your memory leak is related with disposable items not being cleaned from memory, so you'll eventually run out of memory in your infinite loop.
At the very least, you'll want to dispose both bitmaps at the end of the loop:
bg = new Bitmap(#"Images\test.bmp");
spr = new Bitmap(#"Images\sprite.png");

Continuously getting data from heart rate monitor

I've been working on a project that reads a person's heart rate from a Polar H7 hrm. I've been successful in connecting the device and getting the heart rate which the program shows as text in the UI. However, there are instances where the program suddenly stops getting input from the device.
I have already checked the connection of the device to my Win 10 laptop and saw that it was stable, there were also no exceptions getting thrown by the program. The text simply stops changing.
Here is the code I've written:
public sealed partial class MainPage : Page
{
private GattDeviceService device;
public MainPage()
{
this.InitializeComponent();
init();
}
async void init()
{
var devices = await DeviceInformation.FindAllAsync(GattDeviceService.GetDeviceSelectorFromUuid(GattServiceUuids.HeartRate));
Status.Text = devices.Count.ToString();
device = await GattDeviceService.FromIdAsync(devices[0].Id);
enableSensor();
}
private async void enableSensor()
{
IReadOnlyList<GattCharacteristic> characteristicList;
characteristicList = device.GetAllCharacteristics();
if (characteristicList != null)
{
GattCharacteristic characteristic = characteristicList[0];
if (characteristic.CharacteristicProperties.HasFlag(GattCharacteristicProperties.Notify))
{
characteristic.ValueChanged += SendNotif;
await characteristic.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue.Notify);
}
}
}
async void SendNotif(GattCharacteristic sender, GattValueChangedEventArgs eventArgs)
{
if (eventArgs.CharacteristicValue.Length != 0) {
byte[] hrData = new byte[eventArgs.CharacteristicValue.Length];
DataReader.FromBuffer(eventArgs.CharacteristicValue).ReadBytes(hrData);
var hrValue = ProcessData(hrData);
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
Status.Text = hrValue.ToString();
});
}
}
private int ProcessData(byte[] data)
{
// Heart Rate profile defined flag values
const byte heartRateValueFormat = 0x01;
byte currentOffset = 0;
byte flags = data[currentOffset];
bool isHeartRateValueSizeLong = ((flags & heartRateValueFormat) != 0);
currentOffset++;
ushort heartRateMeasurementValue;
if (isHeartRateValueSizeLong)
{
heartRateMeasurementValue = (ushort)((data[currentOffset + 1] << 8) + data[currentOffset]);
currentOffset += 2;
}
else
{
heartRateMeasurementValue = data[currentOffset];
}
return heartRateMeasurementValue;
}
}

Logging Window in MTA thread: Access Violation

In our app we have a tracing window that we can enable on client locations to allow some debugging, it is accessed thought a static library.
Problem is, when there are a lot of log messages going to the window it crashes with an AccessViolation error. The link of code where is crashes is the RichTextBox.AppendText(..,..,..).
Here is where we create the window.
public static void Start(Form parent)
{
if (_runningThread == null || !_runningThread.IsAlive)
{
_runningThread = new Thread(() =>
{
_traceView = new TraceView(parent) { Text = "Tracing ~ " + parent.Text };
Application.Run(_traceView);
});
_runningThread.SetApartmentState(ApartmentState.MTA);
_runningThread.Start();
}
}
and here is were we write a line to the textbox
public void Write(string line, Color color)
{
try
{
_msgQueue.Enqueue(new Tuple<string, Color>(line, color));
MethodInvoker gui = delegate
{
try
{
// Was getting an overflow so trim out some lines
if (uiTrace.Lines.Length > 5000)
{
uiTrace.Lines = new string[0];
uiTrace.SelectionStart = uiTrace.TextLength;
Application.DoEvents();
}
while (_msgQueue.Count != 0)
{
bool retry;
var count = 0;
do
{
try
{
count++;
if (_indent < 0)
_indent = 0;
var msg = _msgQueue.Dequeue();
var selectionStart = uiTrace.TextLength;
uiTrace.AppendText(string.Format("[{0}] {1}{2}", _stopwatch.ElapsedMilliseconds, string.Empty.PadLeft(_indent * 4), msg.Item1));
uiTrace.Select(selectionStart, uiTrace.TextLength);
uiTrace.SelectionColor = msg.Item2;
uiTrace.SelectionStart = uiTrace.TextLength;
uiTrace.ScrollToCaret();
retry = false;
}
catch (Exception)
{
retry = true;
}
} while (retry && count < 5);
}
}
catch (Exception)
{
// We don't care about exceptions in here, for now anyway
}
};
if (uiTrace.InvokeRequired && !uiTrace.Disposing && !uiTrace.IsDisposed)
{
uiTrace.BeginInvoke(gui);
return;
}
gui();
}
catch (Exception)
{
// QIT_Backoffice.Processes.Errors.ErrorHandler.WriteErrorLog(Sources.SourceEnum.External, ex, "Error writing to trace");
}
}
I really have no idea how to get around this one, I thought calling BeginInvoke() is what was needed.
Looking for any help possible, or if anyone knows a third party tool that could handle this better I am happy to look at that.
Below is my modification of your logger. Note how _processing and lock are used to avoid reentrancy and protect _queue. Also, I use SynchronizationContext instead of Control.BeginInvoke to avoid any dependency on the window disposition state. TraceView can be created (with TraceView.Create) and used from any thread, but its window belongs to the parent window's thread and that's also where it's delivering text into richedit. It's possible to have a dedicated STA thread for that, but I don't feel that's necessary.
[EDITED] I've eliminated what might be a race condition in checking for _processing and added CreateOnOwnThread in case a dedicated thread for the logger UI is a requirement. I also decided to keep Application.DoEvents() for cases when Write is called from a tight loop, to keep the UI responsive.
Usage (stress-test):
private void Form1_Load(object sender, EventArgs ev)
{
var traceView = TraceView.Create(this);
for (var i = 0; i < 1000; i++)
{
var _i = i;
Task.Run(() =>
{
traceView.Write(String.Format("Line: {0}\n", _i), System.Drawing.Color.Green);
});
}
}
Implementation:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Logger
{
public partial class TraceView : Form
{
private Form _parent = null;
private SynchronizationContext _context = SynchronizationContext.Current;
private int _threadId = Thread.CurrentThread.ManagedThreadId;
private object _lock = new Object(); // sync lock to protect _queue and _processing
private Queue<Tuple<string, Color>> _queue = new Queue<Tuple<string, Color>>();
private volatile bool _processing = false; // reentracy check flag
public TraceView(Form parent)
{
_parent = parent;
InitializeComponent();
}
public static TraceView Create(Form parent)
{
TraceView view = null;
// create it on the parent window's thread
parent.Invoke(new Action(() => {
view = new TraceView(parent);
view.Show(parent);
}));
return view;
}
private void DequeueMessages()
{
// make sure we are on the UI thread
Debug.Assert(Thread.CurrentThread.ManagedThreadId == _threadId);
lock (_lock)
{
// prevent re-entracy
if (_processing)
return;
// mark the beginning of processing
_processing = true;
}
// process pending messages
for (; ; )
{
Tuple<string, Color> msg = null;
lock (_lock)
{
if (!_queue.Any())
{
// mark the end of processing
_processing = false;
return;
}
msg = _queue.Dequeue();
}
if (this.Disposing || this.IsDisposed)
{
// do not just loose messages if the window is disposed
Trace.Write(msg.Item1);
}
else
{
var selectionStart = _richTextBox.TextLength;
_richTextBox.AppendText(msg.Item1);
_richTextBox.Select(selectionStart, _richTextBox.TextLength);
_richTextBox.SelectionColor = msg.Item2;
_richTextBox.SelectionStart = _richTextBox.TextLength;
_richTextBox.ScrollToCaret();
_richTextBox.Refresh(); // redraw;
// DoEvents is required if logging from a tight loop,
// to keep the UI responsive
Application.DoEvents();
}
}
}
public void Write(string line, Color color)
{
lock (_lock)
{
_queue.Enqueue(new Tuple<string, Color>(line, color));
// prevent re-entracy
if (_processing)
return; // DequeueMessages is already in progress
}
if (Thread.CurrentThread.ManagedThreadId == _threadId)
DequeueMessages();
else
_context.Post((_) =>
{
DequeueMessages();
}, null);
}
public static TraceView CreateOnOwnThread()
{
TraceView view = null;
using (var sync = new ManualResetEventSlim())
{
// create it on its own thread
var thread = new Thread(() =>
{
SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext());
view = new TraceView(null);
view.Show();
sync.Set(); // ready Write calls
Application.Run(view); // view does Application.ExitThread() when closed
return;
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
sync.Wait();
}
return view;
}
}
}
I have a lot more .Net experience with VB than C#, but doesn't the following code:
if (uiTrace.InvokeRequired && !uiTrace.Disposing && !uiTrace.IsDisposed)
{
uiTrace.BeginInvoke(gui);
return;
}
gui();
result in gui being invoked if InvokeRequired etc. in the If statement, as well as being executed (again) in the current (presumably non-UI) thread in gui().
Wouldn't:
If (uiTrace.InvokeRequired && !uiTrace.Disposing && !uiTrace.IsDisposed)
{
uiTrace.BeginInvoke(gui);
return;
}
Else
gui();
be more appropriate?

Why doesn't this thread ever end?

I'm trying to control a piece of test equipment and I need to get the sequencing correct of how I communicate with it.
First I call StartGettingTraceData(). Then some time in the future I call StopGettingTraceData() to attempt to end the GetTraceData() function instead of it re-launching itself. But that NEVER happens. In fact, I never get to the line DoneTraces.Set() so on the line bool timedOut = !DoneTraces.WaitOne(10000), timedOut always is true;
private static AutoResetEvent DoneTraces = new AutoResetEvent(false);
private void GetTraceData()
{
byte[] receivedbytes = new byte[1];
if (Connection.ReadData(receivedbytes) && receivedbytes[0] == 192)
ProcessIncomingTrace();
Thread.Sleep(100);
if (RunTraceQueryWorker)
new Thread(GetTraceData).Start();
else
{
Thread.Sleep(200);
DoneTraces.Set();
}
}
private void StartGettingTraceData()
{
RunTraceQueryWorker = true;
new Thread(GetTraceData).Start();
}
private bool StopGettingTraceData()
{
RunTraceQueryWorker = false;
bool timedOut = !DoneTraces.WaitOne(10000);
return timedOut;
}
Any thoughts on what is going on?
EDIT:
Here is my Connection.ReadData(...) function. It's a serial connection by the way.
public bool ReadData(byte[] responseBytes)
{
int bytesExpected = responseBytes.Length, offset = 0, bytesRead;
while (bytesExpected > 0 && (bytesRead = MySerialPort.Read(responseBytes, offset, bytesExpected)) > 0)
{
offset += bytesRead;
bytesExpected -= bytesRead;
}
return bytesExpected == 0;
}
Rather than recusively calling GetTraceData again, you should use a while loop looking at your condition like this:
private static AutoResetEvent DoneTraces = new AutoResetEvent(false);
private void GetTraceData()
{
do
{
byte[] receivedbytes = new byte[1];
if (Connection.ReadData(receivedbytes) && receivedbytes[0] == 192)
ProcessIncomingTrace();
Thread.Sleep(100);
}
while (RunTraceQueryWorker)
Thread.Sleep(200);
DoneTraces.Set();
}
private void StartGettingTraceData()
{
RunTraceQueryWorker = true;
new Thread(GetTraceData).Start();
}
private bool StopGettingTraceData()
{
RunTraceQueryWorker = false;
bool timedOut = !DoneTraces.WaitOne(10000);
return timedOut;
}
It's impossible to know specifically why your code is freezing without understanding what ReadData & ProcessIncomingTrace() do.
Well, chances are that the ReadData call is blocking. As an aside, you're making it hard on yourself with all this recursive threading... Can't you just use a loop?
private void GetTraceData()
{
byte[] receivedbytes = new byte[1];
while( RunTraceQueryWorker )
{
if( Connection.ReadData(receivedbytes) && receivedbytes[0] == 192 )
{
ProcessIncomingTrace();
}
Sleep(100);
}
Thread.Sleep(200);
DoneTraces.Set();
}

Playing WAVE file in C# using DirectX and threading?

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

Categories