Android ์ค๋์ค์ํคํ ์ฒ ์์ฝ
Android ํ๋ซํผ์์ ์ค๋์ค ์ฝ๋ฑ์ ์ ์ดํ๋ ๋ฐ๋ ALSA(Advanced Linux Sound Architecture) ๊ธฐ๋ฐ์ tinyalsa ๋๋ alsalib์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง๊ณ , ์ด๋ Android์ Audio HAL(Hardware Abstration Layer) ๊ตฌํ์ ํฌํจ๋จ.
+-------------------------------+
| App Layer |
+-------------------------------+
| Audio Framework |
| (AudioFlinger, AudioPolicy) |
+-------------------------------+
| Audio HAL Interface |
| (audio_hw.c ๋ฑ) |
+-------------------------------+
| tinyalsa / alsa-lib |
+-------------------------------+
| ALSA kernel driver |
+-------------------------------+
| I2S, I2C ๋ฑ H/W ์ธํฐํ์ด์ค |
+-------------------------------+
๐ง tinyalsa์ ์ญํ
- tinyalsa๋ AOSP์์ ์ฌ์ฉํ๋ ๊ฒฝ๋ ALSA ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก, Android์ ์ค๋์ค HAL ๋ ๋ฒจ์์ ์ง์ ALSA ๋๋ฐ์ด์ค๋ฅผ ์ ์ดํ๊ธฐ ์ํด ์ฌ์ฉ๋ฉ๋๋ค.
- ์ฌ์ฉ ๋ชฉ์ :
- PCM ์ถ๋ ฅ (Playback) ๋ฐ ์ ๋ ฅ (Capture)
- Mixer control (๋ณผ๋ฅจ, Mux, Mute ๋ฑ)
- Routing control
audio_hw.c ๋๋ xxx_audio_hw.c ๊ฐ์ HAL ํ์ผ ๋ด์์ tinyalsa API๋ฅผ ์ฌ์ฉํด ์ง์ PCM ์ฅ์น๋ฅผ open/read/write/close ํจ.
โ๏ธ ์ฐธ๊ณ : Tinyalsa vs alsa-lib
| ํญ๋ชฉ | tinyalsa | alsa-lib |
|---|---|---|
| ์ฉ๋ | Android HAL์์ ์ฃผ๋ก ์ฌ์ฉ | ์ผ๋ฐ Linux ๋ฐ์คํฌํ, ์๋ฒ ๋ฑ |
| ํน์ง | ๊ฒฝ๋, AOSP์ ํฌํจ | ๋ณต์กํ๊ณ ๋ค์ํ ๊ธฐ๋ฅ ์ ๊ณต |
| API | ๋จ์: pcm_open, mixer_get | ๋ณต์ก: snd_pcm_open, snd_ctl_* |
| AOSP ํฌํจ ์ฌ๋ถ | ํฌํจ (external/tinyalsa) | ๋ฏธํฌํจ (๋ณ๋ ํฌํ ํ์) |
Linux ํ๋ซํผ์์๋ ์ค๋์ค ์ ์ด ์ ์ผ๋ฐ์ ์ผ๋ก alsa-lib ๋ฅผ ์ฌ์ฉํ๋ฉฐ, ์ด๋ ALSA ์ปค๋ ๋๋ผ์ด๋ฒ์ ์ฌ์ฉ์ ๊ณต๊ฐ(user-space) ๊ฐ์ ์ธํฐํ์ด์ค ์ญํ ์ ํจ.
โ 1. alsa-lib ๊ฐ์
- ์ ์ ๋ช ์นญ: Advanced Linux Sound Architecture library
- ์์ค ์์น: https://github.com/alsa-project/alsa-lib
- ์ฃผ์ ํ์ผ: libasound.so, alsa/asoundlib.h
- ์ญํ :
- snd_pcm_* (PCM ๋๋ฐ์ด์ค ์ ์ด)
- snd_mixer_* (Mixer ์ ์ด)
- snd_ctl_* (์ปจํธ๋กค ์ ์ด)
- ~/.asoundrc, /etc/asound.conf ๋ฑ ๊ตฌ์ฑ ํ์ผ ๋ก๋ฉ
โ Linux ๊ธฐ๋ฐ์ ์ค๋์ค ์คํ ๊ฐ์
+-------------------------------+
| Application Layer |
| (e.g., aplay, GStreamer) |
+-------------------------------+
| Audio Libraries |
| alsa-lib, PulseAudio, PipeWire|
+-------------------------------+
| ALSA Kernel Interface |
| (soundcore, snd_pcm, etc.) |
+-------------------------------+
| H/W Driver Layer |
| (I2S, Codec Driver ๋ฑ) |
+-------------------------------+
๐ง ์ฃผ์ ์ค๋์ค ์ ์ด ์๋ฃจ์ 5๊ฐ์ง
- alsa-lib (Advanced Linux Sound Architecture Library)
- ํ์ค Linux ์ค๋์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ. ์ฌ์ฉ์ ๊ณต๊ฐ์์ ALSA ๋๋ฐ์ด์ค๋ฅผ ์ ์ด.
- ์ฌ์ฉ ๋ฐฉ์์ ๋ณต์กํ์ง๋ง, ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์ ์ ๊ณต.
- ๊ฐ๋ฐ์ ์์ค์ low-level control ๊ฐ๋ฅ.
- API ์: snd_pcm_open, snd_pcm_writei, snd_ctl_*
- asound.conf / .asoundrc
- ALSA ์ฅ์น์ ๋ผ์ฐํ , ๋ฏน์ฑ, ๋ณํ์ ๊ตฌ์ฑํ๋ ์ค์ ํ์ผ.
- ์์คํ ์์ค ๋๋ ์ฌ์ฉ์ ์์ค ์ค๋์ค ๋ผ์ฐํ ์ค์ ๊ฐ๋ฅ.
- ์: ํน์ PCM์ default๋ก ์ง์ , dmix ์ฌ์ฉ ์ค์ ๋ฑ
-
- amixer / alsamixer (CLI ๊ธฐ๋ฐ ๋ฏน์ ๋๊ตฌ)
- ALSA mixer ์ธํฐํ์ด์ค๋ฅผ ์ ์ดํ๋ CLI ๋๊ตฌ
- ๋ณผ๋ฅจ ์ ์ด, mux ์ ํ, ๋ง์ดํฌ ํ์ฑํ/๋นํ์ฑํ ๋ฑ ์ํ
- amixer, alsamixer ๋ชจ๋ mixer control์ ํธํ๊ฒ ์ค์ ๊ฐ๋ฅ
- PulseAudio (์ค๊ฐ ๋ ์ด์ด ์ฌ์ด๋ ์๋ฒ)
- ์ฌ์ฉ์๊ฐ ์ฌ๋ฌ ์ฑ์์ ๋์์ ์ค๋์ค๋ฅผ ์ฌ์ฉํ๋ ๋ฐ ํ์ํ ์ฌ์ด๋ ์๋ฒ
- ALSA ์์์ ๋์ํ๋ฉฐ, ๋คํธ์ํฌ ์ค๋์ค ์คํธ๋ฆฌ๋ฐ ๋ฑ ๊ณ ๊ธ ๊ธฐ๋ฅ ์ ๊ณต
- ๋ฐ์คํฌํ Linux์์๋ ๊ธฐ๋ณธ ๊ตฌ์ฑ (ex: Ubuntu)
- PipeWire (์ ํ ์ฌ์ด๋/๋ฏธ๋์ด ์๋ฒ)
- PulseAudio๋ฅผ ๋์ฒดํ๊ธฐ ์ํ ํ๋ก์ ํธ
- ์ค๋์ค + ๋น๋์ค ์ฒ๋ฆฌ๋ฅผ ํตํฉ์ ์ผ๋ก ๊ด๋ฆฌ
- ์ต์ GNOME ๊ธฐ๋ฐ ๋ฐ์คํฌํ์์ ๊ธฐ๋ณธ ์ฑํ ์ค (์: Ubuntu 22.04 ์ด์)
๐ง Embedded Linux์์๋ ์ด๋ป๊ฒ ์จ์ผ ํ ๊น?
- ๋ฆฌ์์ค๊ฐ ์ ๋ค๋ฉด alsa-lib + amixer ๊ธฐ๋ฐ ์ ์ด๋ฅผ ์ ํธ
- ์ค๋์ค ์ฝ๋ฑ ์ ์ด๋ Device Tree ๋๋ I2C ํตํด codec driver์์ ๋ค๋ฃธ
- ํ์ ์ UCM (Use Case Manager) ๋๋ ๊ฐ๋จํ ์ปค์คํ Audio HAL ๊ตฌํ ๊ฐ๋ฅ
โ ์ ์ ์กฐ๊ฑด
- AK7755๊ฐ I2C๋ก ์ฐ๊ฒฐ๋์ด ์๊ณ , ๊ด๋ จ ์ปค๋ ๋๋ผ์ด๋ฒ(sound/soc/codecs/ak7755.c)๊ฐ ๋ฑ๋ก.
- device tree ๋๋ platform data๋ฅผ ํตํด ๋ฑ๋ก๋ ์ํ
- ALSA Mixer ์ปจํธ๋กค๋ฌ๋ก ์ ์ด ๊ฐ๋ฅํ ์ํ
- amixer, alsamixer ๋๋ C ์ฝ๋์์ alsa-lib API๋ก ์ปจํธ๋กค ๊ฐ๋ฅ
โ 1. amixer ๋๋ alsamixer๋ฅผ ํตํ ์ ์ด ์์ AK7755 ๋๋ผ์ด๋ฒ๋ ALSA mixer control์ ์ฌ๋ฌ ์ปจํธ๋กค ๋ ธ๋๋ฅผ ์ ๊ณต.
# ์ ์ฒด Mixer ์ปจํธ๋กค ๋
ธ๋ ํ์ธ
amixer -c 0 scontrols
# ์์ ์ถ๋ ฅ:
# Simple mixer control 'AK7755 DAC Playback Volume',0
# Simple mixer control 'AK7755 ADC Capture Switch',0
# DAC ๋ณผ๋ฅจ ์ ์ด
amixer -c 0 sset 'AK7755 DAC Playback Volume' 80%
# ADC ๋ง์ดํฌ ์
๋ ฅ ํ์ฑํ
amixer -c 0 sset 'AK7755 ADC Capture Switch' onโ 2. C ์ฝ๋ ์์ (alsa-lib ๊ธฐ๋ฐ)
#include <alsa/asoundlib.h>
int main() {
snd_mixer_t *handle;
snd_mixer_elem_t *elem;
snd_mixer_selem_id_t *sid;
const char *card = "default"; // ๋๋ hw:0
const char *selem_name = "AK7755 DAC Playback Volume";
snd_mixer_open(&handle, 0);
snd_mixer_attach(handle, card);
snd_mixer_selem_register(handle, NULL, NULL);
snd_mixer_load(handle);
snd_mixer_selem_id_malloc(&sid);
snd_mixer_selem_id_set_index(sid, 0);
snd_mixer_selem_id_set_name(sid, selem_name);
elem = snd_mixer_find_selem(handle, sid);
if (!elem) {
printf("Control not found\n");
return 1;
}
// ๋ณผ๋ฅจ 80% ์ค์ (range: 0~max)
long minv, maxv;
snd_mixer_selem_get_playback_volume_range(elem, &minv, &maxv);
long set_vol = minv + (maxv - minv) * 0.8;
snd_mixer_selem_set_playback_volume_all(elem, set_vol);
snd_mixer_close(handle);
snd_mixer_selem_id_free(sid);
return 0;
}โ 3. DAPM ์ ์ด๋ ๊ฐ๋ฅ (Platform ์ธก) AK7755๋ **DAPM (Dynamic Audio Power Management)**์ ์ฌ์ฉํ๋ ์ฝ๋ฑ์ด๋ฏ๋ก, DAI ๋ผ์ฐํ ์ ์กฐ์ ํ๋ฉด ์๋์ผ๋ก ํ์ํ path๋ฅผ power on/off ํจ.
๋ง์ฝ platform driver์์ route๋ฅผ ์ง์ ์ค์ ํ๊ณ ์ถ๋ค๋ฉด:
static const struct snd_soc_dapm_route audio_routes[] = {
{"Headphone", NULL, "AK7755 DAC"},
{"AK7755 DAC", NULL, "Playback"},
{"AK7755 ADC", NULL, "Mic Bias"},
{"Capture", NULL, "AK7755 ADC"},
};