123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- 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.
|