요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
============================
ALSA PCM channel-mapping API
============================
Takashi Iwai <tiwai@suse.de>
General
=======
The channel mapping API allows user to query the possible channel maps
and the current channel map, also optionally to modify the channel map
of the current stream.
A channel map is an array of position for each PCM channel.
Typically, a stereo PCM stream has a channel map of
``{ front_left, front_right }``
while a 4.0 surround PCM stream has a channel map of
``{ front left, front right, rear left, rear right }.``
The problem, so far, was that we had no standard channel map
explicitly, and applications had no way to know which channel
corresponds to which (speaker) position. Thus, applications applied
wrong channels for 5.1 outputs, and you hear suddenly strange sound
from rear. Or, some devices secretly assume that center/LFE is the
third/fourth channels while others that C/LFE as 5th/6th channels.
Also, some devices such as HDMI are configurable for different speaker
positions even with the same number of total channels. However, there
was no way to specify this because of lack of channel map
specification. These are the main motivations for the new channel
mapping API.
Design
======
Actually, "the channel mapping API" doesn't introduce anything new in
the kernel/user-space ABI perspective. It uses only the existing
control element features.
As a ground design, each PCM substream may contain a control element
providing the channel mapping information and configuration. This
element is specified by:
* iface = SNDRV_CTL_ELEM_IFACE_PCM
* name = "Playback Channel Map" or "Capture Channel Map"
* device = the same device number for the assigned PCM substream
* index = the same index number for the assigned PCM substream
Note the name is different depending on the PCM substream direction.
Each control element provides at least the TLV read operation and the
read operation. Optionally, the write operation can be provided to
allow user to change the channel map dynamically.
TLV
---
The TLV operation gives the list of available channel
maps. A list item of a channel map is usually a TLV of
``type data-bytes ch0 ch1 ch2...``
where type is the TLV type value, the second argument is the total
bytes (not the numbers) of channel values, and the rest are the
position value for each channel.
As a TLV type, either ``SNDRV_CTL_TLVT_CHMAP_FIXED``,
``SNDRV_CTL_TLV_CHMAP_VAR`` or ``SNDRV_CTL_TLVT_CHMAP_PAIRED`` can be used.
The ``_FIXED`` type is for a channel map with the fixed channel position
while the latter two are for flexible channel positions. ``_VAR`` type is
for a channel map where all channels are freely swappable and ``_PAIRED``
type is where pair-wise channels are swappable. For example, when you
have {FL/FR/RL/RR} channel map, ``_PAIRED`` type would allow you to swap
only {RL/RR/FL/FR} while ``_VAR`` type would allow even swapping FL and
RR.
These new TLV types are defined in ``sound/tlv.h``.
The available channel position values are defined in ``sound/asound.h``,
here is a cut:
::
/* channel positions */
enum {
SNDRV_CHMAP_UNKNOWN = 0,
SNDRV_CHMAP_NA, /* N/A, silent */
SNDRV_CHMAP_MONO, /* mono stream */
/* this follows the alsa-lib mixer channel value + 3 */
SNDRV_CHMAP_FL, /* front left */
SNDRV_CHMAP_FR, /* front right */
SNDRV_CHMAP_RL, /* rear left */
SNDRV_CHMAP_RR, /* rear right */
SNDRV_CHMAP_FC, /* front center */
SNDRV_CHMAP_LFE, /* LFE */
SNDRV_CHMAP_SL, /* side left */
SNDRV_CHMAP_SR, /* side right */
SNDRV_CHMAP_RC, /* rear center */
/* new definitions */
SNDRV_CHMAP_FLC, /* front left center */
SNDRV_CHMAP_FRC, /* front right center */
SNDRV_CHMAP_RLC, /* rear left center */
SNDRV_CHMAP_RRC, /* rear right center */
SNDRV_CHMAP_FLW, /* front left wide */
SNDRV_CHMAP_FRW, /* front right wide */
SNDRV_CHMAP_FLH, /* front left high */
SNDRV_CHMAP_FCH, /* front center high */
SNDRV_CHMAP_FRH, /* front right high */
SNDRV_CHMAP_TC, /* top center */
SNDRV_CHMAP_TFL, /* top front left */
SNDRV_CHMAP_TFR, /* top front right */
SNDRV_CHMAP_TFC, /* top front center */
SNDRV_CHMAP_TRL, /* top rear left */
SNDRV_CHMAP_TRR, /* top rear right */
SNDRV_CHMAP_TRC, /* top rear center */
SNDRV_CHMAP_LAST = SNDRV_CHMAP_TRC,
};
When a PCM stream can provide more than one channel map, you can
provide multiple channel maps in a TLV container type. The TLV data
to be returned will contain such as:
::
SNDRV_CTL_TLVT_CONTAINER 96
SNDRV_CTL_TLVT_CHMAP_FIXED 4 SNDRV_CHMAP_FC
SNDRV_CTL_TLVT_CHMAP_FIXED 8 SNDRV_CHMAP_FL SNDRV_CHMAP_FR
SNDRV_CTL_TLVT_CHMAP_FIXED 16 NDRV_CHMAP_FL SNDRV_CHMAP_FR \
SNDRV_CHMAP_RL SNDRV_CHMAP_RR
The channel position is provided in LSB 16bits. The upper bits are
used for bit flags.
::
#define SNDRV_CHMAP_POSITION_MASK 0xffff
#define SNDRV_CHMAP_PHASE_INVERSE (0x01 << 16)
#define SNDRV_CHMAP_DRIVER_SPEC (0x02 << 16)
``SNDRV_CHMAP_PHASE_INVERSE`` indicates the channel is phase inverted,
(thus summing left and right channels would result in almost silence).
Some digital mic devices have this.
When ``SNDRV_CHMAP_DRIVER_SPEC`` is set, all the channel position values
don't follow the standard definition above but driver-specific.
Read Operation
--------------
The control read operation is for providing the current channel map of
the given stream. The control element returns an integer array
containing the position of each channel.
When this is performed before the number of the channel is specified
(i.e. hw_params is set), it should return all channels set to
``UNKNOWN``.
Write Operation
---------------
The control write operation is optional, and only for devices that can
change the channel configuration on the fly, such as HDMI. User needs
to pass an integer value containing the valid channel positions for
all channels of the assigned PCM substream.
This operation is allowed only at PCM PREPARED state. When called in
other states, it shall return an error.
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
목적과 채널 위치 문제
1-31저자는 Takashi Iwai(`tiwai@suse.de`)다. ALSA PCM channel-mapping API를 사용하면 응용 프로그램이 가능한 channel map과 현재 map을 조회하고, 선택적으로 현재 stream의 map을 바꿀 수 있다.
Channel map은 PCM channel마다 하나씩 대응하는 위치 값의 배열이다. 일반 stereo stream은 `{ front_left, front_right }`, 4.0 surround stream은 `{ front left, front right, rear left, rear right }`처럼 표현한다.
이 API 이전에는 명시적인 표준 channel map이 없어 응용 프로그램이 channel과 speaker 위치의 대응을 알 수 없었다. 그 결과 5.1 출력에서 잘못된 channel을 적용해 rear speaker에서 예상 밖의 소리가 나기도 했다. 일부 장치는 center/LFE를 세 번째·네 번째 channel로, 다른 장치는 다섯 번째·여섯 번째로 가정했다.
HDMI 같은 장치는 전체 channel 수가 같아도 서로 다른 speaker 위치로 구성할 수 있지만, channel map 명세가 없어 이를 지정할 수 없었다. 이런 문제들이 새 API의 주된 동기다.
배열 순서가 각 PCM channel의 물리적 speaker 위치를 뜻한다.
============================
ALSA PCM channel-mapping API
============================
Takashi Iwai <tiwai@suse.de>
General
=======
The channel mapping API allows user to query the possible channel maps
and the current channel map, also optionally to modify the channel map
of the current stream.
A channel map is an array of position for each PCM channel.
Typically, a stereo PCM stream has a channel map of
``{ front_left, front_right }``
while a 4.0 surround PCM stream has a channel map of
``{ front left, front right, rear left, rear right }.``
The problem, so far, was that we had no standard channel map
explicitly, and applications had no way to know which channel
corresponds to which (speaker) position. Thus, applications applied
wrong channels for 5.1 outputs, and you hear suddenly strange sound
from rear. Or, some devices secretly assume that center/LFE is the
third/fourth channels while others that C/LFE as 5th/6th channels.
Also, some devices such as HDMI are configurable for different speaker
positions even with the same number of total channels. However, there
was no way to specify this because of lack of channel map
specification. These are the main motivations for the new channel
mapping API.
기존 control element를 이용한 설계
32-55Channel-mapping API는 kernel/user-space ABI 관점에서 새 mechanism을 추가하지 않고 기존 ALSA control element 기능만 사용한다.
기본 설계에서 각 PCM substream은 channel map 정보와 구성을 제공하는 control element를 가질 수 있다. `iface`는 `SNDRV_CTL_ELEM_IFACE_PCM`, 이름은 방향에 따라 `Playback Channel Map` 또는 `Capture Channel Map`, `device`와 `index`는 연결된 PCM substream과 같은 번호다.
PCM substream 방향과 번호로 control element를 연결한다.
각 control element는 최소한 TLV read operation과 일반 read operation을 제공한다. 장치가 channel map을 동적으로 바꿀 수 있다면 선택적으로 write operation을 제공할 수 있다.
Design
======
Actually, "the channel mapping API" doesn't introduce anything new in
the kernel/user-space ABI perspective. It uses only the existing
control element features.
As a ground design, each PCM substream may contain a control element
providing the channel mapping information and configuration. This
element is specified by:
* iface = SNDRV_CTL_ELEM_IFACE_PCM
* name = "Playback Channel Map" or "Capture Channel Map"
* device = the same device number for the assigned PCM substream
* index = the same index number for the assigned PCM substream
Note the name is different depending on the PCM substream direction.
Each control element provides at least the TLV read operation and the
read operation. Optionally, the write operation can be provided to
allow user to change the channel map dynamically.
TLV 형식과 교환 가능 범위
56-77TLV operation은 사용 가능한 channel map 목록을 반환한다. 일반적인 한 map 항목은 `type data-bytes ch0 ch1 ch2...` 형식이다. `type`은 TLV type 값이고 두 번째 값은 channel 값의 개수가 아니라 전체 byte 수이며, 나머지는 channel별 위치 값이다.
TLV type으로 `SNDRV_CTL_TLVT_CHMAP_FIXED`, `SNDRV_CTL_TLV_CHMAP_VAR`, `SNDRV_CTL_TLVT_CHMAP_PAIRED`를 사용할 수 있다. `_FIXED`는 channel 위치가 고정된 map, `_VAR`와 `_PAIRED`는 위치를 바꿀 수 있는 map이다.
`_VAR`는 모든 channel을 자유롭게 교환할 수 있고 `_PAIRED`는 channel pair 단위로만 교환할 수 있다. `{FL/FR/RL/RR}`에서 `_PAIRED`는 `{RL/RR/FL/FR}`처럼 pair 순서만 바꿀 수 있지만, `_VAR`는 FL과 RR을 직접 맞바꾸는 것도 허용한다. 새 TLV type은 `sound/tlv.h`에 정의된다.
교환 가능한 위치의 범위를 구분한다.
TLV
---
The TLV operation gives the list of available channel
maps. A list item of a channel map is usually a TLV of
``type data-bytes ch0 ch1 ch2...``
where type is the TLV type value, the second argument is the total
bytes (not the numbers) of channel values, and the rest are the
position value for each channel.
As a TLV type, either ``SNDRV_CTL_TLVT_CHMAP_FIXED``,
``SNDRV_CTL_TLV_CHMAP_VAR`` or ``SNDRV_CTL_TLVT_CHMAP_PAIRED`` can be used.
The ``_FIXED`` type is for a channel map with the fixed channel position
while the latter two are for flexible channel positions. ``_VAR`` type is
for a channel map where all channels are freely swappable and ``_PAIRED``
type is where pair-wise channels are swappable. For example, when you
have {FL/FR/RL/RR} channel map, ``_PAIRED`` type would allow you to swap
only {RL/RR/FL/FR} while ``_VAR`` type would allow even swapping FL and
RR.
These new TLV types are defined in ``sound/tlv.h``.
표준 channel 위치 enum
78-116사용 가능한 channel 위치 값은 `sound/asound.h`에 정의된다. `UNKNOWN`, 무음인 `NA`, `MONO`를 시작으로 front/rear/side/LFE 위치와 wide, high, top 위치까지 포함한다. 원문의 enum 발췌는 다음과 같다.
/* channel positions */
enum {
SNDRV_CHMAP_UNKNOWN = 0,
SNDRV_CHMAP_NA, /* N/A, silent */
SNDRV_CHMAP_MONO, /* mono stream */
/* this follows the alsa-lib mixer channel value + 3 */
SNDRV_CHMAP_FL, /* front left */
SNDRV_CHMAP_FR, /* front right */
SNDRV_CHMAP_RL, /* rear left */
SNDRV_CHMAP_RR, /* rear right */
SNDRV_CHMAP_FC, /* front center */
SNDRV_CHMAP_LFE, /* LFE */
SNDRV_CHMAP_SL, /* side left */
SNDRV_CHMAP_SR, /* side right */
SNDRV_CHMAP_RC, /* rear center */
/* new definitions */
SNDRV_CHMAP_FLC, /* front left center */
SNDRV_CHMAP_FRC, /* front right center */
SNDRV_CHMAP_RLC, /* rear left center */
SNDRV_CHMAP_RRC, /* rear right center */
SNDRV_CHMAP_FLW, /* front left wide */
SNDRV_CHMAP_FRW, /* front right wide */
SNDRV_CHMAP_FLH, /* front left high */
SNDRV_CHMAP_FCH, /* front center high */
SNDRV_CHMAP_FRH, /* front right high */
SNDRV_CHMAP_TC, /* top center */
SNDRV_CHMAP_TFL, /* top front left */
SNDRV_CHMAP_TFR, /* top front right */
SNDRV_CHMAP_TFC, /* top front center */
SNDRV_CHMAP_TRL, /* top rear left */
SNDRV_CHMAP_TRR, /* top rear right */
SNDRV_CHMAP_TRC, /* top rear center */
SNDRV_CHMAP_LAST = SNDRV_CHMAP_TRC,
};
enum 이름의 위치 계층을 묶어 보여준다.
The available channel position values are defined in ``sound/asound.h``,
here is a cut:
::
/* channel positions */
enum {
SNDRV_CHMAP_UNKNOWN = 0,
SNDRV_CHMAP_NA, /* N/A, silent */
SNDRV_CHMAP_MONO, /* mono stream */
/* this follows the alsa-lib mixer channel value + 3 */
SNDRV_CHMAP_FL, /* front left */
SNDRV_CHMAP_FR, /* front right */
SNDRV_CHMAP_RL, /* rear left */
SNDRV_CHMAP_RR, /* rear right */
SNDRV_CHMAP_FC, /* front center */
SNDRV_CHMAP_LFE, /* LFE */
SNDRV_CHMAP_SL, /* side left */
SNDRV_CHMAP_SR, /* side right */
SNDRV_CHMAP_RC, /* rear center */
/* new definitions */
SNDRV_CHMAP_FLC, /* front left center */
SNDRV_CHMAP_FRC, /* front right center */
SNDRV_CHMAP_RLC, /* rear left center */
SNDRV_CHMAP_RRC, /* rear right center */
SNDRV_CHMAP_FLW, /* front left wide */
SNDRV_CHMAP_FRW, /* front right wide */
SNDRV_CHMAP_FLH, /* front left high */
SNDRV_CHMAP_FCH, /* front center high */
SNDRV_CHMAP_FRH, /* front right high */
SNDRV_CHMAP_TC, /* top center */
SNDRV_CHMAP_TFL, /* top front left */
SNDRV_CHMAP_TFR, /* top front right */
SNDRV_CHMAP_TFC, /* top front center */
SNDRV_CHMAP_TRL, /* top rear left */
SNDRV_CHMAP_TRR, /* top rear right */
SNDRV_CHMAP_TRC, /* top rear center */
SNDRV_CHMAP_LAST = SNDRV_CHMAP_TRC,
};
여러 map의 TLV container와 bit flag
117-143하나의 PCM stream이 여러 channel map을 제공할 수 있으면 TLV container type 안에 여러 map을 넣는다. 다음 예는 mono, stereo, 4-channel 고정 map을 한 container에 담는다. 4-channel 항목의 `NDRV_CHMAP_FL` 표기는 원문 그대로 보존한다.
SNDRV_CTL_TLVT_CONTAINER 96
SNDRV_CTL_TLVT_CHMAP_FIXED 4 SNDRV_CHMAP_FC
SNDRV_CTL_TLVT_CHMAP_FIXED 8 SNDRV_CHMAP_FL SNDRV_CHMAP_FR
SNDRV_CTL_TLVT_CHMAP_FIXED 16 NDRV_CHMAP_FL SNDRV_CHMAP_FR \
+ SNDRV_CHMAP_RL SNDRV_CHMAP_RR
Channel 위치는 하위 16bit에 저장하고 상위 bit는 flag로 사용한다.
#define SNDRV_CHMAP_POSITION_MASK 0xffff
#define SNDRV_CHMAP_PHASE_INVERSE (0x01 << 16)
#define SNDRV_CHMAP_DRIVER_SPEC (0x02 << 16)
`SNDRV_CHMAP_PHASE_INVERSE`는 channel 위상이 반전됐음을 나타낸다. 이 경우 좌우 channel을 합치면 거의 무음이 되며 일부 digital microphone 장치가 이 특성을 가진다. `SNDRV_CHMAP_DRIVER_SPEC`가 설정되면 모든 channel 위치 값은 위 표준 정의가 아니라 driver 전용 의미를 따른다.
하위 위치 값과 상위 flag를 구분한다.
When a PCM stream can provide more than one channel map, you can
provide multiple channel maps in a TLV container type. The TLV data
to be returned will contain such as:
::
SNDRV_CTL_TLVT_CONTAINER 96
SNDRV_CTL_TLVT_CHMAP_FIXED 4 SNDRV_CHMAP_FC
SNDRV_CTL_TLVT_CHMAP_FIXED 8 SNDRV_CHMAP_FL SNDRV_CHMAP_FR
SNDRV_CTL_TLVT_CHMAP_FIXED 16 NDRV_CHMAP_FL SNDRV_CHMAP_FR \
SNDRV_CHMAP_RL SNDRV_CHMAP_RR
The channel position is provided in LSB 16bits. The upper bits are
used for bit flags.
::
#define SNDRV_CHMAP_POSITION_MASK 0xffff
#define SNDRV_CHMAP_PHASE_INVERSE (0x01 << 16)
#define SNDRV_CHMAP_DRIVER_SPEC (0x02 << 16)
``SNDRV_CHMAP_PHASE_INVERSE`` indicates the channel is phase inverted,
(thus summing left and right channels would result in almost silence).
Some digital mic devices have this.
When ``SNDRV_CHMAP_DRIVER_SPEC`` is set, all the channel position values
don't follow the standard definition above but driver-specific.
Read와 선택적 write operation
144-164Control read operation은 지정 stream의 현재 channel map을 반환한다. 결과는 각 channel의 위치를 담은 integer 배열이다. Channel 수가 정해지기 전, 즉 `hw_params`가 설정되기 전에 읽으면 모든 channel을 `UNKNOWN`으로 반환해야 한다.
Control write operation은 선택 사항이며 HDMI처럼 channel 구성을 실행 중에 바꿀 수 있는 장치에만 사용한다. 사용자 공간은 연결된 PCM substream의 모든 channel에 대해 유효한 위치를 담은 integer 값을 전달해야 한다.
Write는 PCM 상태가 `PREPARED`일 때만 허용된다. 다른 상태에서 호출하면 오류를 반환해야 한다.
조회와 동적 변경의 반환·허용 조건이다.
Read Operation
--------------
The control read operation is for providing the current channel map of
the given stream. The control element returns an integer array
containing the position of each channel.
When this is performed before the number of the channel is specified
(i.e. hw_params is set), it should return all channels set to
``UNKNOWN``.
Write Operation
---------------
The control write operation is optional, and only for devices that can
change the channel configuration on the fly, such as HDMI. User needs
to pass an integer value containing the valid channel positions for
all channels of the assigned PCM substream.
This operation is allowed only at PCM PREPARED state. When called in
other states, it shall return an error.
요약·해설
channel-mapping-api.rst:1-164기존 ALSA control element와 TLV를 사용해 PCM channel의 speaker 위치를 조회·선택하는 API, 표준 위치 enum과 PREPARED 상태 write 규칙을 설명합니다.