Problem with Java stream that captures sound card data

I have a program that creates a stream that captures data from a sound card at a frequency of 48 kHz and writes it to a buffer for collection. The heart of the stream code is as follows.

public void run() { // Run continously for (;;) { // get data from the audio device. getSample(); } } // Read in 2 bytes from the audio source combine them together into a single integer // then write that into the sound buffer private void getSample () { int sample,count,total=0,fsample; byte buffer[]=new byte[2]; try { while (total<1) { count=Line.read(buffer,0,2); total=total+count; } } catch (Exception e) { String err=e.getMessage(); } sample=(buffer[0]<<8)+buffer[1]; etc etc etc } 

The program works, except that the process seems to take 100% of the processor time. I suppose this is because the thread is sitting, waiting for the data to arrive in the Line.Read line. I tried to insert Thread.yield () at different points in the thread, but it doesn't seem to matter.

Can someone suggest ways to reduce the amount of processor time this thread takes?

thank you for your time

Yang

+4
source share
3 answers

Make sure the stream is blocked for input.

A thread takes up 100% of the processor time if it is not blocked. Blocking will cause the thread to start to sleep until some external stimulus appears to wake it up. Whenever you have a dedicated thread for processing input, you need to make sure that it blocks this input so that it sleeps in such a way as to avoid a thread that takes up 100% of the processor time in its cycle.

In this particular case, if Line is javax.sound.sampled.TargetDataLine , then the read() method is where you should do your lock. According to the API, "This method is blocked until the requested amount of data has been read," but "if the data line is closed, stopped, discharged, or reset before the requested amount is read, this method is no longer blocked, but returns the amount bytes read. "

So there are a couple of possibilities. I don’t see your definition of Line , so it’s possible that you are clearing or stripping the line in some code that you did not include. If you have done this, you should reorganize the solution so as not to use these methods.

Another possibility is that since you always read only two bytes at a time, you do not read enough to block it. Basically, there are always two bytes, because it takes too much time to process the two bytes you read, which is always two more bytes. Try increasing the buffer size to read as much as 4kb at a time. See If this makes the loop work less often and block more often.

+3
source

You need to use a read buffer that is significantly larger than size 2. Using a sufficiently large buffer size is almost always advisable in any situation, but for some reason javax.sound is especially inefficient when using small buffer sizes. I found out about this when implementing a Java-based VU meter.

+1
source

Put a Thread.sleep(a few ms); into your infinite loop or use java.util.Timer to call getSample () every few ms.

0
source

All Articles