Android: AudioRecord.read () возвращает мусор - PullRequest
0 голосов
/ 26 марта 2012

Я работаю над приложением, которое может воспроизводить звук с микрофона в режиме реального времени.Он устанавливает AudioRecorder, который вставляется без каких-либо ошибок.Тем не менее, при выполнении операций чтения он просто возвращает кучу значений, или большое число, близкое к максимальному значению short.Я действительно застрял, было бы очень любезно, если бы кто-нибудь мог мне помочь.Это мой код:

public class AudioIn extends Thread {
public static final int ERROR_RECORD_INIT = -1;
public static final int ERROR_RECORD_NOTIFICATION = -2;
public static final int ERROR_RECORD_READ = -3;
public static final int SUCCESS = 0;

public static final int audioFrequency = 44100;
public static final int channelConfig = AudioFormat.CHANNEL_IN_MONO;
public static final int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
final int ShortsReadPerCycle = 1024;


private boolean capture = true;
private AudioRecord recorder;
private int effectiveCaptureBufferSize;
private short[] buffer;

private AudioInHandler handler;

public AudioIn()
{
    int minDeviceBuffer = AudioRecord.getMinBufferSize(audioFrequency, channelConfig, audioFormat);
    Log.d("AudioIn", "Minimum device capture buffer is: " + Integer.toString(minDeviceBuffer) + " bytes");

    effectiveCaptureBufferSize = minDeviceBuffer;
    Log.d("AudioIn", "Setting capture buffer size to " + effectiveCaptureBufferSize + " bytes");
}

public void close()
{
    capture = false;
}

public int samplesPerBuffer()
{
    return effectiveCaptureBufferSize / 2;
}

@Override
public void run() {
    // TODO Auto-generated method stub
    android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_AUDIO);
    try
    {
        recorder = new AudioRecord(AudioSource.MIC, audioFrequency, channelConfig, audioFormat, effectiveCaptureBufferSize);
    }
    catch (Throwable t)
    {
        handler.onError(ERROR_RECORD_INIT);
        return;         
    }

    recorder.startRecording();

    while(capture)
    {
        buffer = new short[ShortsReadPerCycle];
        int shortsRead = recorder.read(buffer, 0, buffer.length);
        if (shortsRead < 0)
        {
            new Runnable() {

                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    handler.onError(ERROR_RECORD_READ);
                }
            }.run();
            this.close();
        }
        else
        {
            new Runnable() {

                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    handler.onNewData(buffer);
                }
            }.run();    
        }
    }
    Log.d("AudioIn.run()", "Stopping AudioRecord...");
    recorder.stop();
    Log.d("AudioIn.run()", "Stopped AudioRecord, now releasing...");
    recorder.release();
    Log.d("AudioIn.run()", "AudioRecord released");
    recorder = null;
}

public void setHandler(AudioInHandler handler) {
    this.handler = handler;
}
}

1 Ответ

3 голосов
/ 21 апреля 2012

Однократный вызов read () в AudioRecord не гарантирует заполнение всего короткого [].Вы должны проверить возвращаемое «shortsRead» для фактического короткого чтения и продолжать вызывать read (), пока не будет заполнено short [].Пример кода приведен ниже.

private void readFully(short[] data, int off, int length) {
        int read;
        while (length > 0) {
            read = mRec.read(data, off, length);
            length -= read;
            off += read;
        }
}

В вашем цикле записи

while (!released) {
    // fill the pktBuf
    short[] pktBuf = new short[pktSize];
    readFully(pktBuf, 0, pktSize);
    // Do something
}

Таким образом, каждый раз, когда вызывается метод read (), мы увеличиваем смещение на «read» иуменьшите оставшуюся длину на «чтение», продолжайте чтение, пока оставшаяся длина не достигнет 0. Затем вы получите заполненный короткий [] с записанными аудиоданными.

Аналогично, когда вы записываете данные в AudioTrack, вынужно сделать то же самое, что и writeFully (), чтобы гарантировать, что весь короткий [] будет записан в AudioTrack.

Надеюсь, это поможет.

...