Jump to content
Reds

Sound Output / Sample Rate Synchronization

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?

 

 

 

 

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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.


  • Similar Content

    • By cpipkin
      Hello,
      I am working on code that will read a waveform of a sound pressure measurement and calculate the octave band levels. I would be incredibly grateful if someone could take a glance at my code to see what I have wired incorrectly...
      The issue I think I'm having: The output of the "Basic Averaged DC-RMS" output wont index when I put it into the for loop. I tried to get around this problem by building arrays for each RMS output and then indexing into the for loop. Doing this doesn't allow me to graph the output... Any ideas as to why the "Basic Averaged DC-RMS" wont index directly?
       
      The code (inspired by new NXG example) is attached, both VI's must be downloaded in order to run the "Octave Band Levels" VI. Also, I'm aware that LV has a toolkit for sound analysis & octave band analysis... but I do not have access to this toolkit, which is why i'm trying to write my own VI. 
      Thanks in advance!
      Octave Band Levels.vi
      Waveform Butterworth Filter.vi

    • By VI Shots
      Hey everyone,
       
      I'm very excited to let all NIWeek attendees know about a new podcast series I started in collaboration with NI. Aptly named the NIWeek Conference Podcast, you can listen to the first episode here.
       
      We'll be releasing one episode per week, to the run-up to August.
    • By FrankH
      Hi All!
       
      Since LabVIEW uses only Windows MME driver for sound in and out, I'm looking for an other way to get sound data into LabVIEW with much less latency.
       
      Has someone use ASIO4ALL for audio input?
       
      For sound out I use Midi via MME and the Windows own synthesizer. Its latency is really not high. But the input data comes with some hundred milliseconds lateness.
       
      With MME: I tested on 2 systems. About 350ms latency and not really depending of the system load. I tried also with small sample packages of 600 and 1200 byte/chn and a sound card acquisition rate of 96kS/s. In order to collect this data amount the time what the PC needs should be theoretical 6,25/12,5ms plus data transfer time and some reaction times of the system modules. But the response time of MME seems in-depending on it. It needs always around 320...380ms. And the processor load was very low.
       
      Maybe someone can help me to use a faster software interface (ASIO?).
       
      Best greetings,
      Frank
×
×
  • Create New...

Important Information

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