Jump to content

Sound Output / Sample Rate Synchronization


Reds

Recommended Posts

I'm working on a project that requires sound output via the Windows audio subsystem, and so I've recently found myself using the LabVIEW "Sound" pallet vi's for the first time in.....well...ever!

 

The sound output ("Play") vi's allow you to setup and configure an output "task".  As part of that configuration, you define a buffer size.  Once that sound output task is configured, you effectively write your sound samples into this buffer over time, periodically refreshing this buffer with new audio sample data.

 

That's all fine and good, but unfortunately it seems like there is no mechanism to query the buffer status and find out if the buffer is about to overflow or underflow.  While this might not seem to matter if you're playing a sound file for a few minutes on a machine with lots of RAM, it definitely does matter if you're streaming live audio continuously through the system for several days or weeks. 

 

If you refresh the buffer with new audio sample data at rate that is just slightly faster than the audio card's configured sample rate, then it seems like the buffer will eventually use up all available PC RAM.  if you are refreshing that buffer just slightly slower than the audio card's configured sample rate, then it seems like the buffer will eventually underflow and create a glitch in the audio output.  And since there is no way to monitor whether the buffer is trending toward overflow or underflow, there is no way to figure out how to adjust the rate at which you feed new audio sample data into the buffers.

 

Am I missing something here?  Is the audio subsystem doing some sample rate conversion that I don't know about?  What is the proper way to ensure that the sound playback buffers do not overflow or underflow over an extended period of time?

 

 

 

 

Link to comment

Unfortunately the native sound card library does not include a way to poll for the buffer pointer.  You can get the 'is playing' status but that would probably not avoid glitching.

I think the correct way to do this is with a ring buffer scheme.

You might have better luck with this library since it can assign multiple output buffers...

 

http://www.zeitnitz.de/Christian/waveio?mid=9

Link to comment

I stream internet radio and FM radio amongst other things for hours on end, it is not so difficult.  These sources have a well-defined data rate determined either by sampling frequency or the stream parameters.  The only fundamental problem you face is whether you can decode the data for a frame of audio in less time than it will play.  For MP3 it is easy, for decoding FM radio it requires some work to get things right. 

 

The Write function for the sound buffer is blocking, it will not return until the data has been written to a buffer (or it reaches a specified timeout).  This means it fits very nicely into a producer-consumer scheme. If there is room in the buffer, the write returns immediately, when it is full, there is a wait while the buffer empties.  The queue of the P/C can take up the slack, and you can make it fixed size to limit the memory usage.  You effectively keep the buffer as full as possible, and you can monitor the queue size to see if there are any backups.  In fact, by using the P/C architecture up to the source of the data you can throttle the source with a fixed-size queue.  For example, instead of reading an entire file I read chunks in a producer loop and feed it to a consumer queue.  By making that queue one or two elements I can control how much is kept in memory at one time, much more effective than trying to read an entire file at once.  Similar chunking is done automatically by streaming sources such as internet radio, DLNA servers and the like.

 

In short, I would not abandon the sound VIs unless I encountered a real problem.

Edited by Darin
Link to comment
  • 3 years later...

This was a beginning of such a good discussion, that ended so abruptly.  Sorry for raising this corpse, but I have a .wav file that I stream for an hour long as a stress signal, then run a ref signal for 10 seconds, and stream the 1hr long file again.  Eventually the .wav file stops playing and the Sound Output Write.vi is hung.  It's not timing out (I thought the default timeout is 10s) it's just sitting there and I can't even end it.  My guess is the buffer is overflown and there is no audio output from the external usb soundcard (I use the nuforce).

I was writing 2000 samples / iteration (the NI example has 2500) and now scaling down to 1000, to see if this helps.   When I switch over from one file to another, I clean everything up by Sound File Close.vi, Sound Output Wait,vi and Sound Output Clear.vi.  I get the info of the file by Sound File Info,vi and feed it to the Sound Output Configure.vi and set it to continuous Samples

 

Some snippets are below

 

 

 

Snippet.Init.png

Snippet.Play.png

Snippet.Close.png

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.