Onboard Device Memory UnderFlow
kperks
DAQmx_Scan/DEV="NI6259"/TRIG={"/NI6259/ao/starttrigger"}/BKG WAVES= "datawav, 1" //datawav receives the voltage trace recorded via DAC
DAQmx_WaveformGen/DEV="NI6259"/NPRD=1 "playwav, 0;" //playwav is the normalized and scaled version of the wave loaded by SndLoadWave
These commands are within a "for" loop that repeats the scan and playback however many times I specify.
The sample rate of the song is 44100Hz and both the datawav and playwav are scaled with a delta (SetScale operation) of 2.26757e-005
HOWEVER when I load and try to play .WAV files of short motifs that have been cut out of the song (~1 second duration) the waveform DOES NOT play reliably on each repetition.
IF I include the /BKG=-1 flag on the DAQmx_WaveformGen operation, then I get the following error (returned by fDAQmx_ErrorString()):
"NI-DAQmx driver error while calling function DAQmxWaitUntilTaskDone; device NI6259:-200016: Measurements: Onboard device memory underflow. Because of system and/or bus-bandwidth limitations, the driver could not write data to the device fast enough to keep up with the device output rate. Reduce your sample rate, alter the data transfer method (from interrupts to DMA), use a product with more onboard memory, or reduce the number of programs your computer is executing concurrently.
Extended info:
Measurements: Onboard device memory underflow. Because of system and/or bus-bandwidth limitations, the driver could not write data to the device fast enough to keep up with the device output rate. Reduce your sample rate, alter the data transfer method (from interrupts to DMA), use a product with more onboard memory, or reduce the number of programs your computer is executing concurrently.
Task Name: NI6259AO
Status Code: -200016"
If I play these short motifs (~1 second song segments) at half the sample rate (22050) so SetScale sets the delta of the waves to 4.53515e-005, but the number of samples remains the same (so it plays the sound file in slow motion) the playback using DAQmx_Scan followed by DAQmx_WaveformGen DOES work reliably every time.
adding neither fDAQmx_WF_WaitUntilFinished("NI6259",-1) nor fDAQmx_ScanWait("NI6259") after the DAQmx_WaveformGen operation helps.
I do not want to change the sample rate of my song playback.
And it seems that my NIDAQ device is set to use DMA transfer method if it is possible, but how can I make sure that I am making use of that method as opposed to "interrupts" in IGOR?
Is there any other advice/answers that anyone can provide who has had experience with problems like this?
Thank You in advance for your help!
(and below I have pasted the procedure I am using to accomplish my goals so it can be referenced if necessary... I apologize for my novice coding skills)
Function SongStim_IClamp()
DoOpenMultiFileDialog()
NVAR nlist = root:numFilesSelected
WAVE/T stimlist = root:stimlist
variable inval = nlist
variable basedur, nreps
Prompt nreps, "number reps song list"
Prompt basedur, "baseline time in sec"
DoPrompt "birdsong trial", nreps, basedur
variable rep
for(rep=0;rep<nreps;rep+=1)
permute(inval)
WAVE outseq=root:outseq
variable item, pick
for(item=0;item<nlist;item+=1) // Initialize variables;continue test
variable sampfreq, songsample, tdur, normval, scaley, sampdelta, basesample, datasample, delta, beginwav, endwav
string pathfromopen, sampfreqst, tit
pick=outseq[item]
pathfromopen = stimlist[item] //get the stim file path returned in outputPaths list of DoOpenMultiFileDialog() function using the randomized index generated by purmute(inval)
SndLoadWave/M=1/O anywav, (pathfromopen) //load the .WAV file from the stim file path determined by outputPaths list of DoOpenMultiFileDialog()
wavestats/Q anywav
sampfreqst=stringbykey("RATE", S_info) //gets the sample frequency of the original .WAV file from the info strings returned by SndLoadWave
//sampfreq=str2num(sampfreqst)
sampfreq=22050
tit=S_fileName
songsample = V_npnts
basesample =(basedur)*(sampfreq)
tdur=songsample/sampfreq
delta=1/sampfreq
Make/D/N=(songsample) datawav, playwav
WAVE anywav=root:anywav
playwav=anywav
InsertPoints 0,(basesample), playwav //insert x zeros to the beginning of the .WAV to be played so that there is a baseline measurement of the cell's activity
InsertPoints 0,(basesample), datawav
//I may want to figure out how to add points after as well
setscale/P x, 0, (delta), datawav, playwav
normval = max(V_max, abs(V_min))
playwav /=normval
scaley = 6
playwav *= scaley
DAQmx_Scan/DEV="NI6259"/TRIG={"/NI6259/ao/starttrigger"}/BKG WAVES= "datawav, 1"
DAQmx_WaveformGen/DEV="NI6259"/NPRD=1 "playwav, 0;"
//fDAQmx_WF_WaitUntilFinished("NI6259",-1)
fDAQmx_ScanWait("NI6259")
//fDAQmx_ScanStop("NI6259")
//fDAQmx_WaveformStop("NI6259")
string datawavst, basewavst
datawavst= (tit)+(num2str(rep))
rename datawav, $(datawavst)
rename playwav, $(datawavst) + "play"
KillWaves anywav
//, playwav
endfor
endfor
End
Function/S DoOpenMultiFileDialog()
Variable refNum
String message = "Select one or more files"
String outputPaths
String fileFilters = "Data Files (*.txt,*.dat,*.csv,*.wav):.txt,.dat,.csv,.wav;"
fileFilters += "All Files:.*;"
Open/D/R/MULT=1/F=fileFilters/M=message refNum
outputPaths = S_fileName
if (strlen(outputPaths) == 0)
Print "Cancelled"
else
Variable/G numFilesSelected = ItemsInList(outputPaths, "\r")
Make/T/N=(numFilesSelected)/O stimlist
Variable i
for(i=0; i<numFilesSelected; i+=1)
String path = StringFromList(i, outputPaths, "\r")
Printf "%d: %s\r", i, path
stimlist[i]=path
endfor
endif
return outputPaths // Will be empty if user canceled
End
Function/WAVE permute(inval)
variable inval
Make/O/N=(inval) outseq
variable i, j, val, fail, test, emax=(inval)/2
for (i=1; i<=inval; i+=1)
fail=0
do
val= floor(emax + enoise(emax))
fail=0
for(j=0; j<(i-1); j+=1)
if (val==outseq[j])
fail+=1
endif
print j, fail
endfor
while(fail!=0)
outseq[i-1]=val
print outseq
endfor
End
DoOpenMultiFileDialog()
NVAR nlist = root:numFilesSelected
WAVE/T stimlist = root:stimlist
variable inval = nlist
variable basedur, nreps
Prompt nreps, "number reps song list"
Prompt basedur, "baseline time in sec"
DoPrompt "birdsong trial", nreps, basedur
variable rep
for(rep=0;rep<nreps;rep+=1)
permute(inval)
WAVE outseq=root:outseq
variable item, pick
for(item=0;item<nlist;item+=1) // Initialize variables;continue test
variable sampfreq, songsample, tdur, normval, scaley, sampdelta, basesample, datasample, delta, beginwav, endwav
string pathfromopen, sampfreqst, tit
pick=outseq[item]
pathfromopen = stimlist[item] //get the stim file path returned in outputPaths list of DoOpenMultiFileDialog() function using the randomized index generated by purmute(inval)
SndLoadWave/M=1/O anywav, (pathfromopen) //load the .WAV file from the stim file path determined by outputPaths list of DoOpenMultiFileDialog()
wavestats/Q anywav
sampfreqst=stringbykey("RATE", S_info) //gets the sample frequency of the original .WAV file from the info strings returned by SndLoadWave
//sampfreq=str2num(sampfreqst)
sampfreq=22050
tit=S_fileName
songsample = V_npnts
basesample =(basedur)*(sampfreq)
tdur=songsample/sampfreq
delta=1/sampfreq
Make/D/N=(songsample) datawav, playwav
WAVE anywav=root:anywav
playwav=anywav
InsertPoints 0,(basesample), playwav //insert x zeros to the beginning of the .WAV to be played so that there is a baseline measurement of the cell's activity
InsertPoints 0,(basesample), datawav
//I may want to figure out how to add points after as well
setscale/P x, 0, (delta), datawav, playwav
normval = max(V_max, abs(V_min))
playwav /=normval
scaley = 6
playwav *= scaley
DAQmx_Scan/DEV="NI6259"/TRIG={"/NI6259/ao/starttrigger"}/BKG WAVES= "datawav, 1"
DAQmx_WaveformGen/DEV="NI6259"/NPRD=1 "playwav, 0;"
//fDAQmx_WF_WaitUntilFinished("NI6259",-1)
fDAQmx_ScanWait("NI6259")
//fDAQmx_ScanStop("NI6259")
//fDAQmx_WaveformStop("NI6259")
string datawavst, basewavst
datawavst= (tit)+(num2str(rep))
rename datawav, $(datawavst)
rename playwav, $(datawavst) + "play"
KillWaves anywav
//, playwav
endfor
endfor
End
Function/S DoOpenMultiFileDialog()
Variable refNum
String message = "Select one or more files"
String outputPaths
String fileFilters = "Data Files (*.txt,*.dat,*.csv,*.wav):.txt,.dat,.csv,.wav;"
fileFilters += "All Files:.*;"
Open/D/R/MULT=1/F=fileFilters/M=message refNum
outputPaths = S_fileName
if (strlen(outputPaths) == 0)
Print "Cancelled"
else
Variable/G numFilesSelected = ItemsInList(outputPaths, "\r")
Make/T/N=(numFilesSelected)/O stimlist
Variable i
for(i=0; i<numFilesSelected; i+=1)
String path = StringFromList(i, outputPaths, "\r")
Printf "%d: %s\r", i, path
stimlist[i]=path
endfor
endif
return outputPaths // Will be empty if user canceled
End
Function/WAVE permute(inval)
variable inval
Make/O/N=(inval) outseq
variable i, j, val, fail, test, emax=(inval)/2
for (i=1; i<=inval; i+=1)
fail=0
do
val= floor(emax + enoise(emax))
fail=0
for(j=0; j<(i-1); j+=1)
if (val==outseq[j])
fail+=1
endif
print j, fail
endfor
while(fail!=0)
outseq[i-1]=val
print outseq
endfor
End
October 14, 2010 at 06:04 pm - Permalink
You need to surround any code with <igor></igor> tags so that the text rendering engine doesn't treat stuff within angle brackets as (invalid) HTML tags.
I just edited your original post to add the tags.
October 15, 2010 at 08:35 am - Permalink
Do you have any insight on my problem of not being able to play short (~1sec) songs with a high sample rate (although I can play long songs with a high sample frequency just fine)?
October 15, 2010 at 09:43 am - Permalink
I did a little bit of searching on the NI support site about this issue. It seems like generating short sequences of waveform generation is paradoxically difficult for the hardware. One suggestion in a response to a similar problem was to apply a short delay after triggering the waveform generation. You might be able to try that out by using /STRT=0 on the call to DAQmx_WaveformGen, then calling fDAQmx_WaveformStart() afterward. I don't know if the small delay that would occur just due to the speed (or lack thereof) of Igor's function execution would be enough. So your code would change to something like this:
DAQmx_WaveformGen/DEV="NI6259"/NPRD=1/STRT=0 "playwav, 0;"
// maybe here insert a delay using the Sleep operation
fDAQmx_WaveformStart("NI6259", 1)
Another possibility might be to request that the samples be stored on the device. That requires the (pretty new) /DBUF flag. If your version of NIDAQ Tools MX doesn't have that flag, let me know and I will send you the information you need to update NIDAQ Tools MX. That requires adding "/DBUF=1" to your call to DAQmx_WaveformGen. The 6259 device has an 8192-point buffer, so your samples have to be no longer than 8192 samples. Is that a problem?
The same posting that suggested a delay before starting the waveform also suggested that using interrupt transfers would paradoxically *help* the problem. Unfortunately, I have to add the necessary option of it is required (probably should anyway). Let me know how you get on with the suggestions above, and if it comes to it I can add the necessary option to waveform generation.
John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
October 15, 2010 at 11:42 am - Permalink
I do have the NIDAQ Tools version with the /DBUF flag and I had tried to include it yesterday when I was trouble-shooting. It always returned an error, but I did not know that it was because the device only had 8192-point buffer. My stimuli are indeed usually an order of magnitude larger than that buffer.
Adding the /STRT=0 flag and the sleep operation seemed to help a little bit, but the playback is still not reliable on every repetition, even when adding a 3 second pause and inserting 3 seconds worth of zeros onto the beginning of each song motif wave. Should that have been enough of a sleep (and lengthening of the stimulus) to help the problem using this type of solution?
Is the "interrupts transfers flag" on the waveform generation still an option?
Thanks again,
Krista
October 15, 2010 at 01:23 pm - Permalink
Sounds like you've done what you can. I will look into the transfer method flag in the next day or two.
John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
October 18, 2010 at 09:38 am - Permalink
I was just reviewing that problem, when I noticed your statement about using /BKG=-1. Now I'm a bit confused, because the code you posted doesn't have that. I presume this is one of the things you tried- using either /BKG=-1 or fDAQmx_ScanWait or fDAQmx_WF_WaitUntilFinished.
Would it be possible for you to send me an Igor experiment that I can use to try it out? You would need to substitute pre-loaded waves for the SndLoadWave call to avoid sending me a whole bunch of sound files, etc. Naturally, the content of the waves doesn't matter. I just need to be able to run your code without having all your sound files, etc. Send it as an attachment to support@wavemetrics.com.
John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
October 18, 2010 at 11:14 am - Permalink
Here's another thing to try-
Swap the order of DAQmx_Scan and DAQmx_WaveformGen. Move the trigger from DAQmx_Scan to DAQmx_WaveformGen, changing the trigger source to "/NI6259/ai/starttrigger". Some NI Forum posts suggest that using a hardware trigger for the waveform generation might help; it's not clear why, but it's easy to try. Your code would then look like
DAQmx_Scan/DEV="NI6259"/BKG WAVES= "datawav, 1"
//fDAQmx_WF_WaitUntilFinished("NI6259",-1)
fDAQmx_ScanWait("NI6259")
John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
October 18, 2010 at 11:33 am - Permalink
Let me know if you are still interested in the /interrupts flag. Seems like it could be useful in the future.
October 18, 2010 at 03:17 pm - Permalink