LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Sound Mixer in Labview

Solved!
Go to solution

As part of experiment control and data recording project I need to control the subject's audio environment.  Doing so requires playing a continuous mask sound, usually white noise, with short audio prompts, typically a "beep", "ding" or "chimes" pulled from the Windows media folder, coming in as required by the particular experiment.  So far the audio output VIs are frustrating me.  Each requirement is easily accomplished independently, but when I try to combine them I get one blocking the other and/or simply no sound.  The best example I have found is the "Play 2 sounds.vi" but it assumes the two files start when the VI starts.  Everything I have tried to start one of the files after the other one has led to a case structure with an incomplete output node.  Is there any way to get independently starting and stopping  audio file to play together?

 

Thanks for your help.

Bill Monette, Indiana University, School of Optometry

0 Kudos
Message 1 of 11
(5,128 Views)

Think about what it means to "mix sounds" digitally.  Let's say you want "reasonable fidelity", which might mean you want to play sounds at CD rates of 44.1 kHz.  Unlike an analog amplifier/speaker, where you put in voltage and "instantly" get out sound, in the digital world, you first sample the signal (giving you an array of sound values) and then send the sample to a buffer that presents the data, one point at a time at the specified output rate (here 44.1 kHz).  

 

Let's say we want a buffer of 1000 points, representing about 1/44.1 seconds (or roughly 20 msec) of sound.  We could easily add two arrays of 1000 points in far less time than 20 msec, so you could have a loop updating your waveform and sending it (in 1000-point blocks) to your sound system.  It wouldn't respond "instantaeously" -- there's that 20 msec "delay" that can't be helped -- but that should do the trick.  You just need to take this delay into account when you compute reaction times.

 

Hope that makes sense to you.  The point is that with digital sound, you need to create the (summed, filtered, or whatever) processed waveform before you send it to the sound system.  If it is changing with respect to time (like starting/stopping, or changing frequency), you need to do this before you send it out.  As long as you know (and can "live with" this delay, you should be OK.

 

Bob Schor

0 Kudos
Message 2 of 11
(5,111 Views)

Thanks for the response.  Yes, I was aware of the timing problems.  Unfortunately, I am having a more basic issue: how to get Lab View to combine two streams of audio data and send it to the sound output VIs.  It's probably trivial but I haven't come up with an solution.

 

Thanks again.

Bill Monette, Indiana University, School of Optometry

0 Kudos
Message 3 of 11
(5,095 Views)

Use "Sound File Read" to get the sound as a waveform, then just use the Add function to combine them before sending them to Sound Output Write.

0 Kudos
Message 4 of 11
(5,071 Views)

Hi Bill,

 

The underlying DirectSound API will handle audio mixing - all you need to do is configure and run two tasks simultaneously.

 

One approach is to use a state machine with a queued message handler. The states would include configuring an audio output task, loading a sound file, playing the sound output, stopping the sound output, and checking for new messages on the queue. Two of these state machines would then run in parallel, and receive messages to start and stop playback as needed.

 

I recently made a SimCity 2000 toolkit for LabVIEW (video link, source code) which plays music, and simultaneously plays sound effects as required. The source code is LV2019, but I can back save it for you if needed. Look in the Sound.lvlib library at Effects Player.vi and Music Player.vi for an idea on the state machines. The Main.vi calls both of these VIs, and issues messages to play music and sound as needed.

 

Do you have any source code you can share?

Message 5 of 11
(5,051 Views)

Thanks for all of the replies.  Here is my latest attempt that doesn't work.  In this version there is some feedback that produces an awful noise.  I appreciate your help in fixing my problem.

 

Bill Monette, Indiana University, School of Optometry

0 Kudos
Message 6 of 11
(5,011 Views)
Solution
Accepted by topic author Indiana_Bill

Hi Bill,

 

Thanks for posting your code. I've modified it with the suggestions I made previously and have attached the changes. The updated code plays back two files simultaneously, which can be started and stopped independently.

 

If you want more control of the audio during playback (pausing, change volume, etc) then a continuous audio output approach would be needed, mixing the audio before sending it to the output. This is a little more involved, but certainly doable 🙂

 

There are a few reasons why your code was producing glitchy audio. The main issue is the boolean used to start / stop playback is switching. When it is true, it is continually loading and playing the waveform every time the audio output sample buffer was emptied. Similarly when it is false, it was forever stopping an already stopped audio task. This was remedied in the modified code by using an event structure, only acting on value changes to the boolean.

Message 7 of 11
(4,975 Views)
Solution
Accepted by topic author Indiana_Bill

Thank you, thank you, thank you!  This does the job.

 

You are using some of LabView that is not in my repertoire so it is taking me a bit to understand and adapt to my final project.

 

One question.  Why the main state machine?  It appears that all it does is send "Load and Play" and "Stop" commands along with file name and volume data to the sound player VIs.  Can't the state machine be combined with the sound player VI?  That is closer to what I was attempting to do and would fit better into how I envision my final project?

 

Again thank  you.

 

Bill Monette, Indiana University, School of Optometry

0 Kudos
Message 8 of 11
(4,947 Views)
Solution
Accepted by topic author Indiana_Bill

Hi Bill,

 

The main loop UI / event loop is primarily to decouple user inputs from the state machines. This makes any future modifications to code a lot easier, so new controls won't affect the state machine, and new state logic won't affect the UI. It also means sound playback can be controlled not just from the UI, but from anywhere by sending a message on the state machine's command queue.

 

The top level event loop could be rolled into the Wait On Input case in the sound player VI. Instead of an event structure, the front panel controls would be polled and some decision logic added to determine what state to run next (or to poll again if nothing has changed).

Message 9 of 11
(4,925 Views)

My thanks to all who replied to my post particularly Dataflow_G for your help.  I have attached my final version.  My changes are mostly to fit the vi into my much larger program.

Message 10 of 11
(4,820 Views)