Read Method Problem in AudioRecord Class

public int read (byte [] audioData, int offsetInBytes, int sizeInBytes).

This method reads audio data from audio equipment for writing to the buffer.

Its parameters: audioData - an array into which recorded audio data is recorded. offsetInBytes index in audioData from which data is written in bytes. sizeInBytes the number of bytes requested.

It returns the number of bytes that were read, either by either ERROR_INVALID_OPERATION if the object was not initialized correctly, or ERROR_BAD_VALUE if the parameters do not allow valid data and indexes. The number of bytes will not exceed sizeInBytes.

I wrote this method in my code as follows: int num; byte [] buf = new byte [160]; num = record.read (buf, 0, 160);

The problem is that it always returns 160 (i.e. the requested byte to read) at least 160, even if the data is not available. what is the problem? Help me. Thanks in advance.

+4
source share
2 answers

UPDATE: this bug in Android was fixed somewhere after 4.2.2 and before 5.01. At 5.01, callbacks work just like the documents say they should.

It seems that read blocked due to some shortsighted developers.

In principle, when the audio recorder is initialized, it allocates a kind of ring buffer, and when .start() reports .start() , it starts writing to this buffer.

Then, when .read() is called, it reads up to half the size of the buffer (or the requested size, whichever is smaller) and returns.

If he wants to read 1000 samples and only 900 are available, he needs to wait another 100 samples before returning. If, however, there are more than 1000 samples, he instantly reads them, and then immediately returns.

Ideally, they would either provide a non-blocking read so that the returned everything that is available is available, or provide an opportunity to know when full data availability is available so that a non-blocking read can be performed.

I do not think they support the first. It looks like they are trying to support the second one using the given period callback method, but so far I can’t get this call at the right time to make a quick non-blocking read.

I cloned the full source (8.5G bytes) of the C ++ source code, and I'm trying to execute functionality across all layers to see how it should work.

The trick for non-blocking .read(0) ing should only be read when ready-made samples are ready. But determining when this condition is true is something that I have not yet understood.

References: Here is the java code for .read (), which calls its own C ++ function:

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.3.4_r1/android/Media/AudioRecord.java # AudioRecord.read% 28java.nio.ByteBuffer% 2Cint% 29

The above read () method calls native native_read_in_direct_buffer() , which is located in:

http://pdroid.googlecode.com/svn/android-2.3.4_r1/trunk/frameworks/base/core/jni/android_media_AudioRecord.cpp

which calls or points to android_media_AudioRecord_readInByteArray() , which in turn calls AudioRecord.read() in frameworks/base/media/libmedia/frameworks/base/media/libmedia/AudioRecord.cpp (as much as possible), and it looks like in this function has a do / while loop, which essentially blocks to the desired number (or half the buffering, whichever is less).

I tried to make the callbacks function well, but they only seemed to call back when read () had to wait for the sound buffer to fill before it could return - so that’s the point.

My next goal is to try to track down the source code of the notification callback so that I can guess what exactly should and when.

+13
source

read is a blocking method. It will return only after it reads so many bytes that you told him, or if the stream is closed, or if the stream indicates that there is no data available (for example, when reading a file).

AudioRecord is a continuous stream, the case of "more inaccessible data" is never applied.

+7
source

Source: https://habr.com/ru/post/1333883/


All Articles