LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Producer consumer - read sound input and handle user events

Hi,

I am working on a project that will be using sound input as an oscilloscope. VI should read sound input continuously, wait for user actions on the front panel and react. For example the acquisition has started, signal is being displayed on Waveform Chart and user changes range of the chart (XScale.Maximum Property Node). I know how to implement producer and consumer while loops with Event and Case structures to handle user actions on the front panel but what about data logging? Should I have another producer that continuously run "Sound Input Read.vi" and push acquired data into the same queue that another producer pushes user events to? If so how can I stop this another producer loop after user press Stop Button on the front panel?

 

Thanks in advance.

 

 

0 Kudos
Message 1 of 4
(3,288 Views)

The advantage to another Consumer/Producer loop for Data Storage is it offloads the "Storage" question from your original Consumer to yet another parallel routine, buffering the data in the Queue in case a little extra time is needed to open files, etc.  It also makes Starting and Stopping data storage fairly simple (just stop loading data into the Storage Queue).

 

As to how to stop the Storage Consumer when the entire program ends, you could use the technique of sending a Sentinel to signal "I'm done, exit".  I'm assuming that you would be sending an Array of data to the "Storage Consumer" (it doesn't make much sense to send single points ...).  To signal "I'm Done", you could have the first Consumer (acting as a Producer for the Storage) send an empty Array, a perfectly legal element for the Queue.  The Storage Consumer, when it dequeues the Array, would check "Is the Array Empty?", and if true, would know that its Producer is saying "That's all, time to exit".  The "Empty Array?" test, in fact, could be wired to the Stop Indicator of the Consumer's While Loop.

 

Bob Schor

0 Kudos
Message 2 of 4
(3,280 Views)

I managed to create a minimal working example presenting the idea of architecture that I want to use. Can you please try to run it and tell me if it looks anything like a proper Queued Message Handler architecture? I used C. Zeinitz WaveIO sound library available here https://www.zeitnitz.eu/scms/waveio?mid=10&PHPSESSID=69kfehcsa7a474l1dtmn31g7r3 instead of LabVIEW sound functions because I had a lot of problem with them. It simply didn't work. I added WaveIO library to the project so you should be able to run it. At first run you may get some warnings related to this lib but despite them everything works great for me.

 

I tried to comment code as clearly as I could but I realise that it might be difficult to understand. The aim of this VI is to  continously acquire sound data and display on the chart and react to user actions on the front panel. The problem was to let the user stop and start acquisition again (Run switch) and to clean stop all loops (without errors) after user presses stop button.

 

I wonder if I release queue in the right place of the code. I added "Remaining Elements" indicator to see what is still in the queue when I am releasing it. If the acquisition is running and I press the stop button I end with a last piece of acquired sound data (1000 elements array) remaining in the queue. Is it a good practice to stop VI immediately after user presses stop button or should I dequeue all other elements before?

 

I know I asked a lot of questions so if someone does not feel like answer all of them, the most important to me is to get feedback from anybody if the VI runs properly for you. Also a quick glance on code and assessment whether the whole idea is something acceptable, or it should be done in a completely different way would be appreciated.

 

Thanks in advance.

0 Kudos
Message 3 of 4
(3,247 Views)

Too many local variables and sequence structures.  Too many unneeded loops as well.  Here's how I cleaned this up:

1. Eliminate the top loop and move the sound acquisition and display into a single loop.  I use the timeout of the queue for stating whether or not I should be acquiring data.  Timeout of -1 means to wait forever, therefore will not acquire data.  Timeout of 0 means if there is no message, return the default (State will be an empty string) and acquire data in that state.

2. Get rid of ALL of the local variables.  Use wires whenever possible.  And reading from a terminal to write to its local variable does nothing but waste memory and CPU.  The value is already updated, no need to write it again with a local.

3. Move the cleanup into the acquisition loop's Exit state.  This also helps with decoupling.

 

So now what do you do if you want to save the acquired data to a file?  I would make another loop similar to my acquisition loop (no need for the timeout though) that recieves data and writes it to a file.  You should also have commands for creating the log file and closing it.


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
Message 4 of 4
(3,231 Views)