AudioRecord / Воспроизведение имеет задержку около 1+ секунды - PullRequest
0 голосов
/ 07 мая 2018

Это мой CaptureThread:

  private class CaptureThread implements Runnable {

    @Override
    public void run() {
        Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_AUDIO);

        AudioRecord record = new AudioRecord(MediaRecorder.AudioSource.MIC,
                mCaptureSampleRate,
                AudioFormat.CHANNEL_IN_MONO,
                AudioFormat.ENCODING_PCM_16BIT,
                mCaptureBufferSize);

        record.startRecording();
        short[] captureBuffer = new short[mCaptureBufferLength];

        if(mDebugLoopback) {
            int count;
            while(mRunning) {
                count = record.read(mLoopbackBuffer, 0, mLoopbackBuffer.length);
                if(count < mLoopbackBuffer.length) throw new AssertionError("count < captureBuffer.length");
                synchronized (mLoopbackBufferCapturedNotifier) {
                    mLoopbackBufferCapturedNotifier.notifyAll();
                }
            }
        }
        else {
            int count;
            while (mRunning) {
                count = record.read(captureBuffer, 0, captureBuffer.length);

                try {
                    TS3Client.processCustomCaptureData(getDeviceId(), captureBuffer, count);
                } catch (TS3Exception e) {
                    e.printStackTrace();
                }
            }
        }

        record.stop();
        record.release();
    }
}

А это мой PlaybackThread:

  private class PlaybackThread implements Runnable {
    @Override
    public void run() {
        Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_AUDIO);

        AudioTrack audioTrack = new AudioTrack(
                AudioManager.STREAM_VOICE_CALL,
                mPlaybackSampleRate,
                AudioFormat.CHANNEL_OUT_MONO,
                AudioFormat.ENCODING_PCM_16BIT,
                mPlaybackBufferSize,
                AudioTrack.MODE_STREAM);

        audioTrack.play();

        short[] buffer = new short[mPlaybackBufferLength];

        if(mDebugLoopback) {
            while (mRunning) {
                try {
                    synchronized (mLoopbackBufferCapturedNotifier) {
                        mLoopbackBufferCapturedNotifier.wait();
                    }
                    audioTrack.write(mLoopbackBuffer, 0, mLoopbackBuffer.length);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        else {
            while (mRunning) {
                try {
                    TS3Client.acquireCustomPlaybackData(getDeviceId(), buffer, mPlaybackBufferLength);
                    audioTrack.write(buffer, 0, mPlaybackBufferLength);
                } catch (TS3Exception e) {
                    e.printStackTrace();
                }
            }
        }

        audioTrack.stop();
        audioTrack.release();
    }
}

И это значения, которые я установил для своих буферов:

   private void setupCaptureValues() {
    mCaptureSampleRate = getLowestSupportedCaptureSampleRate();
    if(mCaptureSampleRate == -1) {
        throw new RuntimeException("No supported capture sample rate known");
    }

    mCaptureBufferSize = AudioRecord.getMinBufferSize(mCaptureSampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
    mCaptureBufferLength = mCaptureBufferSize / 2; // 1 short = 2 bytes
    Log.i("","setupPlaybackValues mCaptureBufferSize is: " + mCaptureBufferSize);
    Log.i("","setupPlaybackValues mCaptureBufferLength is: " + mCaptureBufferLength);
}

private void setupPlaybackValues(AudioManager audioManager) {
    mPlaybackSampleRate = AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_VOICE_CALL);

    // By default use the min buffer size
    mPlaybackBufferSize = AudioTrack.getMinBufferSize(
            mPlaybackSampleRate,
            AudioFormat.CHANNEL_OUT_MONO,
            AudioFormat.ENCODING_PCM_16BIT);

    Log.d(TAG, "setupPlaybackValues: mPlaybackSampleRate: " + mPlaybackSampleRate);
    Log.d(TAG, "setupPlaybackValues: mPlaybackBufferSize: " + mPlaybackBufferSize);

    // If supported use the buffer size and sample rate required for a "low latency" streams
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
        String lowLatencyBufferSizeStr = audioManager.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER);
        mPlaybackBufferSize = Integer.parseInt(lowLatencyBufferSizeStr);
        // This value is in frames and not bytes, 1 short = 2 bytes
        mPlaybackBufferSize *= 2;

        String lowLatencySampleRateStr = audioManager.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
        mPlaybackSampleRate = Integer.parseInt(lowLatencySampleRateStr);

        Log.d(TAG, "setupPlaybackValues: using low latency stream values of");
        Log.d(TAG, "setupPlaybackValues: mPlaybackSampleRate: " + mPlaybackSampleRate);
        Log.d(TAG, "setupPlaybackValues: mPlaybackBufferSize: " + mPlaybackBufferSize);
    }

    mPlaybackBufferLength = mPlaybackBufferSize / 2; // 1 short = 2 bytes
}

Какие сообщения это:

05-07 17:03:19.858: D/TS3Client(15053): setupPlaybackValues mCaptureBufferSize is: 640
05-07 17:03:19.858: D/TS3Client(15053): setupPlaybackValues mCaptureBufferLength is: 320
05-07 17:03:19.861: D/AndroidAudioDevice(15053): setupPlaybackValues: mPlaybackSampleRate: 48000
05-07 17:03:19.861: D/AndroidAudioDevice(15053): setupPlaybackValues: mPlaybackBufferSize: 3848
05-07 17:03:19.863: D/AndroidAudioDevice(15053): setupPlaybackValues: using low latency stream values of
05-07 17:03:19.863: D/AndroidAudioDevice(15053): setupPlaybackValues: mPlaybackSampleRate: 48000
05-07 17:03:19.864: D/AndroidAudioDevice(15053): setupPlaybackValues: mPlaybackBufferSize: 480

Теперь я уже пытаюсь взять наименьшие возможные значения для буфера. Я регистрирую их, и если я пытаюсь использовать любое значение меньше, оно просто вылетает, говоря, что это недопустимое значение. Мне нужно найти способ уменьшить мою задержку, что может быть причиной, и есть ли другая возможность уменьшить ее, если не вмешиваться в буферы?

...