Archived

This topic is now archived and is closed to further replies.

Gyannea

DirectSound Capture/Play rates

Recommended Posts

I have a thread where I am capturing sound. I need to be able to have different capture rates, so for a given format, I know how many bytes will (on average) need to be read. So to keep out of trouble, I start reading data 1.5 reads behind the saferead point. Since we all know Windows has no real time control, I keep adjusting the sleep time to be shorter or longer to keep (on average) 1.5 reads behind the safepoint. It works well (I set the ''timeSetTime()'' to the maximum resolution of 1 millisecond for best accurracy). Now I want to send data at the same time. To make life simple, I use the same format (same sample rate, bit depth, etc.) and thus send the same number of bytes every cycle that I capture. However, on my laptop I find that the load rate is too slow! The safeload pointer slowly catches up! Its as if the soundcard is sending faster than it is receiving, yet in both cases the samplerate, bit depth, and channel number are the same. This does not happen on my Soundblaster Live card. Is this possible or do I have a subtle bug? Is it (in general) possible to [simultaneously] capture at one rate and send at another? Capture in stereo and send mono? A very confused Brian Brian Reinhold

Share this post


Link to post
Share on other sites

Ok, I''ll try to tell you what I know.

In general, you cannot expect that every hardware supports input and output at different rates or number of channels. In fact, check your soundcard caps (with directx tools) to know if that kind of things are being emulated.

Make sure that your laptop''s soundcard supports full-duplex.

And, for that kind of applications, I prefer to use a lot of threads... it might sound strange, but since you are writing and reading to and from buffers, you don''t really need to do things in real time. Plus, as you might have to wait for an input or output operation, having many threads allows your application to keep doing things even where resources are locked.

In my app, the output was synthesized (sines) and the input was processed with a Goertzel algorithm (don''t mind about this). I use 2 threads for output and input (this means, generating the sines and processing the input). I wroted the processed data to a list, and readed the output data from another list. I had another two threads for ''working'' with that data. One of them readed the processed input signal and did some work; the other did the reverse thing. The data lists where synchronized with mutex objects (this is important, as the concurrency must be prevented in some way on this objects).

I hope this helps you, if your problem is more or less similar. When doing this project I measured that the performance grows quite noticeable using many threads (of course, this may not be useful for your needs).

Best regards,

Jose Juan Montes

Share this post


Link to post
Share on other sites
jjmontes,

The needs sound quite similar! I am synthesizing output and eventually will need to decode the input (which is an FSK signal derived from a radio). My understanding is that the Goertzel Algorithm is good for this, though right now I am thinking good old integrate and dump.

THe reason I wanted to do both in one thread is that I set the thread to a high priority and maximized the time resolution. I am ALWAYS capturing and only transmitting occassionally. I keep both capture and sending the same (same sample rate, bit depth, etc). If on average I read the buffer every 10 milliseconds, depending upon the sample rate etc, that will mean an average of ''X'' bytes read. So when I start I delay the first read by 15 milliseconds, take the time, read the data and handle it, take the time, and sleep the difference. I also check where I sit relative to the safe read position. If I start to catch up, I lengthen the sleep accordingly. If I start to lag, I shorten it. No notifies. It seems to work quite well.

For the sending I thought if I read ''X'' bytes in 10 milliseconds, then I could send the same number of bytes. So all I did was place the first data to send far enough ahead of the safe write point so it would not catch up and let the capture timing control when I write the data hunks.

I figured that having one high priority thread would be more efficient than having two threads (more overhead) and I am not sure how to set priorities in the latter case.

I guess I will need to look at some of the flags in that capability structure. All I really have looked at was the range of sampling rates. Laptops do tend to have pretty crappy sound cards. At least they don''t hold a candle to the Soundblaster live.

Are you also writing a radio coder/decoder? Sounds like it! If you are, you will understand why I want to be as close to the received signal as possible...scanning! You have to identify the signal in time before moving on to the next channel. The less the latency, the faster you can scan!

Brian

Brian Reinhold

Share this post


Link to post
Share on other sites