지연 시간이 짧은 오디오

지연 시간이 짧은 오디오는 게임의 반응이 더욱 실감 나도록 만듭니다.

Android 게임에서 지연 시간이 짧은 오디오를 사용 설정하려면 다음 체크리스트를 완료하세요.

  1. Oboe 사용
  2. 성능 모드 '짧은 지연 시간' 요청
  3. 공유 모드 '독점' 요청
  4. 48,000Hz 또는 Oboe 샘플링 레이트 변환기 사용
  5. 사용량을 AAUDIO_USAGE_GAME으로 설정
  6. 데이터 콜백 사용
  7. 콜백에서 차단 작업 피하기
  8. 버퍼 크기를 '이중 버퍼'로 조정

1. Oboe API 사용

Oboe API는 Android 8.1(API 수준 27) 이상에서 AAudio를 호출하는 C++ 래퍼입니다. 이전 Android 버전에서 Oboe는 OpenSL ES를 사용합니다.

Oboe는 GitHub에서 또는 사전 빌드된 바이너리로 제공됩니다. 또한 Oboe에는 특정 기기의 문제를 수정하는 QuirksManager가 있으므로 앱이 더 많은 기기와 호환됩니다. Oboe를 사용할 수 없다면 AAudio를 직접 사용하세요.

2. 짧은 지연 시간 모드 요청

Oboe 또는 AAudio를 사용하여 짧은 지연 시간 모드를 요청합니다. 그러지 않으면 기본적으로 더 긴 지연 시간 모드가 설정됩니다.

Oboe

builder.setPerformanceMode(oboe::PerformanceMode::LowLatency);

AAudio

AAudioStreamBuilder_setPerformanceMode(builder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);

3. 독점 모드 요청

MMAP 버퍼에 대한 독점 액세스를 요청할 수도 있습니다. 앱이 독점적인 액세스 권한을 얻지 못할 수도 있지만, 독점 액세스를 얻는 경우 앱은 DSP가 읽는 버퍼에 직접 쓰므로 앱의 지연 시간이 가장 짧아집니다.

Oboe

builder.setSharingMode(oboe::SharingMode::Exclusive);

AAudio

AAudioStreamBuilder_setSharingMode(builder, AAUDIO_SHARING_MODE_EXCLUSIVE);

4. 샘플링 레이트 변환 피하기

기기의 자연 샘플링 레이트를 사용합니다. 샘플링 레이트를 지정하지 않으면 됩니다. 그러면 거의 확실히 48,000Hz를 얻게 됩니다. 샘플링 레이트를 지정하면 오디오 프레임워크는 지연 시간이 훨씬 더 길 수 있는 다른 경로로 데이터를 전송합니다.

다른 샘플링 레이트를 사용해야 한다면 Oboe를 사용하여 샘플링 레이트를 변환하세요.

builder->setSampleRateConversionQuality(oboe::SampleRateConversionQuality::Medium);

5. 적절한 사용 사례 선언

앱이 오디오를 재생하는 이유를 지정하는 것은 시스템에서 올바른 라우팅, 볼륨, 성능 설정을 적용하는 데 매우 중요합니다. 예를 들어 게임은 특히 블루투스 헤드셋에 연결될 때 지연 시간 최적화를 최대한 활용하기 위해 AAUDIO_USAGE_GAME 사용을 표시해야 합니다.

Oboe

builder.setUsage(oboe::Usage::Game);

AAudio

AAudioStreamBuilder_setUsage(builder, AAUDIO_USAGE_GAME);

6. 콜백 함수 사용

출력 스트림에 콜백을 사용합니다. 블로킹 쓰기를 사용하고 AAudio MMAP 모드를 지원하지 않는 기기를 사용하는 경우 지연 시간이 훨씬 길 수 있습니다.

Oboe

builder.setDataCallback(&myCallbackObject);

AAudio

AAudioStreamBuilder_setDataCallback(builder, &my_callback_proc);

7. 콜백에서 차단 피하기

지연 시간이 짧은 스트림을 사용하면 콜백 사이의 시간이 단 몇 밀리초로 매우 짧을 수 있습니다. 따라서 장시간 차단될 수 있는 콜백에서 어떤 작업도 하지 않는 것이 매우 중요합니다. 콜백이 차단되면 오디오에서 버퍼 언더플로 및 결함이 발생합니다.

콜백에서 다음을 실행하지 마세요.

  • 메모리 할당 또는 해제
  • 파일 또는 네트워크 I/O
  • 뮤텍스 또는 잠금 대기
  • 절전 모드
  • 과도한 일회성 CPU 계산

콜백은 문제 없이 원활하게 재생할 수 있도록 균등한 속도로 계산을 실행해야 합니다.

8. 버퍼 크기 조정

앱에서 오디오 스트림을 연 후에는 최적의 지연 시간을 위해 사용 가능한 버퍼 크기를 조정해야 합니다. Oboe는 버퍼 크기를 두 개의 버스트로 자동 설정합니다. 하지만 AAudio를 사용하면 기본값이 훨씬 더 높습니다. 버퍼 크기를 버스트 크기의 두 배로 설정하여 이중 버퍼링을 사용합니다. 버스트 크기는 최대 콜백 크기입니다.

AAudio:

int32_t frames = AAudioStream_getFramesPerBurst() * 2;
AAudioStream_setBufferSizeInFrames(stream, frames);

버퍼 크기가 너무 작으면 버퍼 언더런으로 인한 결함이 발생할 수 있습니다. AAudioStream_getXRunCount(stream)를 호출하여 결함 수를 확인할 수 있습니다. 필요에 따라 버퍼 크기를 늘립니다.

버퍼 관련 용어 설명은 GitHub Oboe 문서를 참고하세요.

OpenSL ES

Android 8.1 이전 버전을 지원하는 경우 OpenSL ES를 사용해야 합니다. Oboe를 사용하는 경우 지연 시간을 개선하도록 앱을 구성할 수 있습니다. GitHub 문서의 최적 지연 시간 구하기를 참고하세요.

체크리스트 결과

다음 표에는 왕복(입력-출력) 지연 시간에 관한 OboeTester 측정값이 포함되어 있습니다.

구성 지연 시간(ms)
모든 권장사항 따르기 20
짧은 지연 시간이 아닌 성능 모드 205
EXCLUSIVE 아님(SHARED임) 26
44,100Hz(AAudio) 160
44,100Hz(Oboe SRC) 23
출력 콜백을 사용하지 않음(MMAP) 21
출력 콜백을 사용하지 않음(MMAP 아님) 62
버퍼 크기가 최댓값으로 설정됨 53