07-15-2016 06:34 AM
I have a c# .net application which is generating output samples on the NI-9263.
I am generating a random noise signal which cannot repeat. I need a method to write continuously to the output channels and modify the output signal based on user controls, ie Gain.
I have set up my task for Continous samples
Regeneration mode is set to DoNotAllowRegeneration
I have an EveryNSamplesWritten event setup to write more output samples periodically
I set EveryNSamplesWrittenEventInterval to the length of the output signal and buffer length which is currently 32768 (nice for FFT-ing)
My problem is that after a few seconds of the output running the output write position is way higher than the total samples generated
CurrentWritePosition = 2097152 TotalSamplesGeneratedPerChannel = 583073
I did some testing using a diagnoistic stopwatch to see how often the callback is exectued and it returned some surprising numbers.
It seems the callback for EveryNSamplesWritten, which should be called every 640mS (32768 samples / 51200 sample rate). Is actually being called WAY more frequencyly than that at the start.
Elapsed mS = 174 CurrentWritePosition = 32768 TotalSamplesGeneratedPerChannel = 395 WriteRelativeTo = CurrentWritePosition Elapsed mS = 4 CurrentWritePosition = 65536 TotalSamplesGeneratedPerChannel = 1293 WriteRelativeTo = CurrentWritePosition Elapsed mS = 43 CurrentWritePosition = 98304 TotalSamplesGeneratedPerChannel = 4291 WriteRelativeTo = CurrentWritePosition Elapsed mS = 10 CurrentWritePosition = 131072 TotalSamplesGeneratedPerChannel = 5100 WriteRelativeTo = CurrentWritePosition Elapsed mS = 9 CurrentWritePosition = 163840 TotalSamplesGeneratedPerChannel = 5824 WriteRelativeTo = CurrentWritePosition Elapsed mS = 9 CurrentWritePosition = 196608 TotalSamplesGeneratedPerChannel = 6614 WriteRelativeTo = CurrentWritePosition Elapsed mS = 5 CurrentWritePosition = 229376 TotalSamplesGeneratedPerChannel = 7413 WriteRelativeTo = CurrentWritePosition
....
....
....
//some time later
Elapsed mS = 636 CurrentWritePosition = 1769472 TotalSamplesGeneratedPerChannel = 255513 WriteRelativeTo = CurrentWritePosition
// At this point were writing 1,513,959 samples ahead of the generated count
I'm not sure why this happens, it is like the buffers need to be primed to a certain number of samples. But it means that I end up with a buffer write pointer 30 seconds ahead of the buffer read pointer. So any Gain changes the user makes, takes 30 seconds to appear.
I have tried comparing CurrentWritePosition to TotalSamplesGeneratedPerChannel to prevent buffer write runaway, but the device then runs out of samples because if I dont write any output samples then the callback is never triggered.
Once CurrentWritePosition == 1638400, the events start firing periodically at the correct rate.
1638400 / 51200 = 32 Seconds of output data!!
None of my buffers are set that high so I dont know why this is happening.
Any help would be much appreciated.
07-19-2016 09:06 AM
Hello alanbithell,
Could you please share some example code of how you are setting up the EveryNSamplesWritten event and contents?
Also, what do you mean by: "I have an EveryNSamplesWritten event setup to write more output samples periodically"?
Kind regards,
Christopher
07-19-2016 09:14 AM
Hi,
I set up the event below
analogOutTask.EveryNSamplesWritten += analogOutTask_EveryNSamplesWritten;
which should call every time a specified number of samples are written.
In this event I was comparing the written vs generated sample counter as below
if(_analogOutTask.Stream.CurrentWritePosition < _analogOutTask.Stream.TotalSamplesGeneratedPerChannel + OutputBlockSize){ _writer.WriteMultiSample(false, outputData); }
which checks if the Daq needs more samples in the buffer, I keep a difference of OutputBlockSize to ensure the event latency doesnt cause errors.
But the problem is due to the fact that this event only fired after the specified number of samples were written. So If i dont write any samples (because im 30 seconds ahead) then the event never fires.
So I moved the code into a System.Timers.Timer elapsed event, and applied all the same code there and it works fine now.
07-20-2016 01:00 AM
Ah, that makes sense.
Great to hear you figured it out!
Kind regards,
Christopher