공간 음향은 더욱 실감 나는 콘텐츠 사운드로 주인공이 된 듯한 느낌을 주는 몰입감 있는 오디오 경험입니다. 사운드가 '공간화'되어 멀티 스피커 효과(서라운드 사운드 환경과 유사)를 구현하지만 헤드폰을 통해 구현합니다.
예를 들어 영화에서 자동차의 소리가 사용자 뒤에서 시작되어 앞으로 이동한 후 멀리 사라질 수 있습니다. 영상 채팅에서는 음성을 구분하고 사용자 주위에 배치하여 화자를 더 쉽게 식별할 수 있습니다.
콘텐츠에서 지원되는 오디오 형식을 사용하는 경우 Android 13 (API 수준 33)부터 앱에 공간 오디오를 추가할 수 있습니다.
기능 쿼리
기기의 공간화 기능 및 동작을 쿼리하려면 Spatializer
클래스를 사용합니다. 먼저 AudioManager
에서 Spatializer
의 인스턴스를 가져옵니다.
Kotlin
val spatializer = audioManager.spatializer
자바
Spatializer spatializer = AudioManager.getSpatializer();
Spatializer
를 가져온 후 기기가 공간화된 오디오를 출력하려면 다음 네 가지 조건이 참이어야 함을 확인합니다.
기준 | 확인 |
---|---|
기기가 공간화를 지원하나요? |
getImmersiveAudioLevel() 가 SPATIALIZER_IMMERSIVE_LEVEL_NONE 가 아님
|
공간화를 사용할 수 있나요? 사용 가능 여부는 현재 오디오 출력 라우팅과의 호환성에 따라 다릅니다. |
isAvailable() 은 true 입니다. |
공간 음향이 사용 설정되어 있나요? | 현재 isEnabled() : true |
지정된 매개변수가 있는 오디오 트랙을 스페이셜라이즈할 수 있나요? | canBeSpatialized() 은 true 입니다. |
이러한 조건이 충족되지 않을 수도 있습니다. 예를 들어 현재 오디오 트랙에서 공간화를 사용할 수 없거나 오디오 출력 장치에서 공간화가 완전히 사용 중지된 경우입니다.
머리 추적
지원되는 헤드셋을 사용하면 플랫폼에서 사용자의 머리 위치에 따라 오디오의 공간화를 조정할 수 있습니다. 현재 오디오 출력 라우팅에 헤드 추적기를 사용할 수 있는지 확인하려면 isHeadTrackerAvailable()
를 호출하세요.
호환되는 콘텐츠
Spatializer.canBeSpatialized()
는 지정된 속성이 있는 오디오를 현재 출력 기기 라우팅으로 스테레오화할 수 있는지 여부를 나타냅니다. 이 메서드는 AudioAttributes
및 AudioFormat
를 사용하며, 둘 다 아래에 자세히 설명되어 있습니다.
AudioAttributes
AudioAttributes
객체는 오디오 스트림의 사용 (예: 게임 오디오 또는 표준 미디어)을 재생 동작 및 콘텐츠 유형과 함께 설명합니다.
canBeSpatialized()
를 호출할 때는 Player
에 설정된 것과 동일한 AudioAttributes
인스턴스를 사용합니다. 예를 들어 Jetpack Media3 라이브러리를 사용 중이고 AudioAttributes
를 맞춤설정하지 않은 경우 AudioAttributes.DEFAULT
를 사용합니다.
공간 음향 사용 중지
콘텐츠가 이미 공간화되었음을 나타내려면 오디오가 이중으로 처리되지 않도록 setIsContentSpatialized(true)
를 호출합니다. 또는 setSpatializationBehavior(AudioAttributes.SPATIALIZATION_BEHAVIOR_NEVER)
를 호출하여 공간화 동작을 조정하여 공간화를 완전히 사용 중지할 수 있습니다.
AudioFormat
AudioFormat
객체는 오디오 트랙의 형식 및 채널 구성에 관한 세부정보를 설명합니다.
AudioFormat
를 인스턴스화하여 canBeSpatialized()
에 전달할 때 인코딩을 디코더에서 예상되는 출력 형식과 동일하게 설정합니다. 콘텐츠의 채널 구성과 일치하는 채널 마스크도 설정해야 합니다. 사용할 특정 값에 관한 안내는 기본 공간화 동작 섹션을 참고하세요.
Spatializer
변경사항 수신 대기
Spatializer
의 상태 변경사항을 수신 대기하려면 Spatializer.addOnSpatializerStateChangedListener()
를 사용하여 리스너를 추가하면 됩니다.
마찬가지로 헤드 트래커의 사용 가능 여부 변경사항을 수신 대기하려면 Spatializer.addOnHeadTrackerAvailableListener()
를 호출합니다.
이는 리스너의 콜백을 사용하여 재생 중에 트랙 선택을 조정하려는 경우 유용할 수 있습니다. 예를 들어 사용자가 기기에 헤드셋을 연결하거나 연결 해제하면 onSpatializerAvailableChanged
콜백은 새 오디오 출력 라우팅에 스페이셜라이저 효과를 사용할 수 있는지 여부를 나타냅니다. 이때 기기의 새로운 기능에 맞게 플레이어의 트랙 선택 로직을 업데이트하는 것이 좋습니다. ExoPlayer의 트랙 선택 동작에 관한 자세한 내용은 ExoPlayer 및 공간 오디오 섹션을 참고하세요.
ExoPlayer 및 공간 음향
최근 출시된 ExoPlayer를 사용하면 서라운드 오디오를 더 쉽게 채택할 수 있습니다. 독립형 ExoPlayer 라이브러리 (패키지 이름 com.google.android.exoplayer2
)를 사용하는 경우 버전 2.17은 공간화된 오디오를 출력하도록 플랫폼을 구성하고 버전 2.18은 오디오 채널 수 제약조건을 도입합니다.
Media3 라이브러리의 ExoPlayer 모듈(패키지 이름 androidx.media3
)을 사용하면 1.0.0-beta01
이상 버전에 동일한 업데이트가 포함됩니다.
ExoPlayer 종속 항목을 최신 버전으로 업데이트한 후 앱에 공간화할 수 있는 콘텐츠를 포함하기만 하면 됩니다.
오디오 채널 수 제약 조건
공간 음향의 4가지 조건 모두가 충족되면 ExoPlayer는 다중 채널 오디오 트랙을 선택합니다. 그렇지 않으면 ExoPlayer는 대신 스테레오 트랙을 선택합니다.
Spatializer
속성이 변경되면 ExoPlayer는 새 트랙 선택을 트리거하여 현재 속성과 일치하는 오디오 트랙을 선택합니다. 이 새로운 트랙 선택으로 인해 짧은 리버퍼링 기간이 발생할 수 있습니다.
오디오 채널 수 제한을 사용 중지하려면 아래와 같이 플레이어에서 트랙 선택 매개변수를 설정하세요.
Kotlin
exoPlayer.trackSelectionParameters = DefaultTrackSelector.Parameters.Builder(context) .setConstrainAudioChannelCountToDeviceCapabilities(false) .build()
자바
exoPlayer.setTrackSelectionParameters( new DefaultTrackSelector.Parameters.Builder(context) .setConstrainAudioChannelCountToDeviceCapabilities(false) .build() );
마찬가지로 다음과 같이 기존 트랙 선택기의 매개변수를 업데이트하여 오디오 채널 개수 제약 조건을 사용 중지할 수 있습니다.
Kotlin
val trackSelector = DefaultTrackSelector(context) ... trackSelector.parameters = trackSelector.buildUponParameters() .setConstrainAudioChannelCountToDeviceCapabilities(false) .build()
자바
DefaultTrackSelector trackSelector = new DefaultTrackSelector(context); ... trackSelector.setParameters( trackSelector .buildUponParameters() .setConstrainAudioChannelCountToDeviceCapabilities(false) .build() );
오디오 채널 수 제약 조건을 사용 중지한 상태에서 콘텐츠에 오디오 트랙이 여러 개 있으면 ExoPlayer는 처음에 채널 수가 가장 많고 기기에서 재생할 수 있는 트랙을 선택합니다. 예를 들어 콘텐츠에 다중 채널 오디오 트랙과 스테레오 오디오 트랙이 포함되어 있고 기기가 둘 다의 재생을 지원하는 경우 ExoPlayer는 다중 채널 트랙을 선택합니다. 이 동작을 맞춤설정하는 방법에 관한 자세한 내용은 오디오 트랙 선택을 참고하세요.
오디오 트랙 선택
ExoPlayer의 오디오 채널 수 제약 조건 동작이 사용 중지되면 ExoPlayer는 기기의 스페이셜라이저 속성과 일치하는 오디오 트랙을 자동으로 선택하지 않습니다. 대신 재생 전이나 재생 중에 트랙 선택 매개변수를 설정하여 ExoPlayer의 트랙 선택 로직을 맞춤설정할 수 있습니다. 기본적으로 ExoPlayer는 MIME 유형(인코딩), 채널 수, 샘플링 레이트와 관련하여 초기 트랙과 동일한 오디오 트랙을 선택합니다.
트랙 선택 매개변수 변경
ExoPlayer의 트랙 선택 매개변수를 변경하려면 Player.setTrackSelectionParameters()
를 사용합니다.
마찬가지로 Player.getTrackSelectionParameters()
를 사용하여 ExoPlayer의 현재 매개변수를 가져올 수 있습니다.
예를 들어 재생 중간에 스테레오 오디오 트랙을 선택하려면 다음 단계를 따르세요.
Kotlin
exoPlayer.trackSelectionParameters = exoPlayer.trackSelectionParameters .buildUpon() .setMaxAudioChannelCount(2) .build()
자바
exoPlayer.setTrackSelectionParameters( exoPlayer.getTrackSelectionParameters() .buildUpon() .setMaxAudioChannelCount(2) .build() );
재생 중 트랙 선택 매개변수를 변경하면 재생이 중단될 수 있습니다. 플레이어의 트랙 선택 매개변수 조정에 관한 자세한 내용은 ExoPlayer 문서의 트랙 선택 섹션을 참고하세요.
기본 공간화 동작
Android의 기본 공간화 동작에는 OEM에서 맞춤설정할 수 있는 다음 동작이 포함됩니다.
스테레오 콘텐츠가 아닌 멀티채널 콘텐츠만 공간화됩니다. ExoPlayer를 사용하지 않는 경우 멀티채널 오디오 콘텐츠의 형식에 따라 오디오 디코더에서 출력할 수 있는 최대 채널 수를 더 큰 숫자로 구성해야 할 수 있습니다. 이렇게 하면 오디오 디코더가 플랫폼이 공간화할 수 있도록 다중 채널 PCM을 출력합니다.
Kotlin
val mediaFormat = MediaFormat() mediaFormat.setInteger(MediaFormat.KEY_MAX_OUTPUT_CHANNEL_COUNT, 99)
자바
MediaFormat mediaFormat = new MediaFormat(); mediaFormat.setInteger(MediaFormat.KEY_MAX_OUTPUT_CHANNEL_COUNT, 99);
실제 예는 ExoPlayer의
MediaCodecAudioRenderer.java
를 참고하세요. OEM 맞춤설정과 관계없이 공간화를 직접 사용 중지하려면 공간 음향 사용 중지를 참고하세요.AudioAttributes
:usage
이USAGE_MEDIA
또는USAGE_GAME
로 설정된 경우 오디오를 공간화할 수 있습니다.AudioFormat
: 오디오를 공간화할 수 있도록 최소한AudioFormat.CHANNEL_OUT_QUAD
채널 (앞쪽 왼쪽, 앞쪽 오른쪽, 뒤쪽 왼쪽, 뒤쪽 오른쪽)이 포함된 채널 마스크를 사용합니다. 아래 예에서는 5.1 오디오 트랙에AudioFormat.CHANNEL_OUT_5POINT1
을 사용합니다. 스테레오 오디오 트랙의 경우AudioFormat.CHANNEL_OUT_STEREO
을 사용합니다.Media3을 사용하는 경우
Util.getAudioTrackChannelConfig(int channelCount)
를 사용하여 채널 수를 채널 마스크로 변환할 수 있습니다.또한 다중 채널 PCM을 출력하도록 디코더를 구성한 경우 인코딩을
AudioFormat.ENCODING_PCM_16BIT
로 설정합니다.Kotlin
val audioFormat = AudioFormat.Builder() .setEncoding(AudioFormat.ENCODING_PCM_16BIT) .setChannelMask(AudioFormat.CHANNEL_OUT_5POINT1) .build()
자바
AudioFormat audioFormat = new AudioFormat.Builder() .setEncoding(AudioFormat.ENCODING_PCM_16BIT) .setChannelMask(AudioFormat.CHANNEL_OUT_5POINT1) .build();
서라운드 오디오 테스트
테스트 기기에서 공간 음향이 사용 설정되어 있는지 확인합니다.
- 유선 헤드셋의 경우 시스템 설정 > 소리 및 진동 > 공간 오디오로 이동합니다.
- 무선 헤드셋의 경우 시스템 설정 > 연결된 기기 > 무선 기기의 톱니바퀴 아이콘 > 공간 음향으로 이동합니다.
현재 라우팅에서 공간 음향 사용 가능 여부를 확인하려면 기기에서 adb shell dumpsys audio
명령어를 실행합니다. 재생이 진행되는 동안 출력에 다음과 같은 매개변수가 표시됩니다.
Spatial audio:
mHasSpatializerEffect:true (effect present)
isSpatializerEnabled:true (routing dependent)