ALSA는 Audio Linux Sound Architecture의 약자.

리눅스에서 Audio를 구현하고자 할 때 사용되는 공개 라이브러리이다.

많이 사용되는 ALSA와 ALSA보다 몸집이 작은 tinyALSA, 이 두 라이브러리의 기본 API에 대해 설명한다.

 

 

  • ALSA Overview
  • tinyALSA

    • Data Structure

      • PCM config
      • PCM Structure
    • PCM Open
    • PCM Read
    • PCM Write
    • PCM Close
  • ALSA
    • Data Structures
    • PCM Open
    • PCM HW Params
    • PCM SW Params
    • PCM Prepare
    • PCM Start
    • PCM Avail
    • PCM Read
    • PCM Write
    • PCM Close
  • ALSA lib 참고 웹페이지

    • ALSA
    • Tiny ALSA

 

 


ALSA Overview

 

흔히 말하는 ALSA는 보통 User Space에서 ALSA library를 가져다 쓰는 것을 말한다.

ALSA application으로는 aplay, arecode, amixer, tinyplay 등이 있으며, 오디오 어플리케이션을 쓸 때 이 코드를 많이 참고하여 사용한다.


 

 

 

tinyALSA

Android에는 tinyALSA가 올라가있다.

tinyALSA의 경우에는 단순히 Open, Read/Write, Close만 해주면 audio 사용이 가능하다.

 

 

Data Structure

tinyALSA를 사용하기 위해서는 PCM Handler와 PCM Config가 필요하다.

 

PCM config

struct pcm_config {
    unsigned int channels;
    unsigned int rate;
    unsigned int period_size;
    unsigned int period_count;
    enum pcm_format format;
    /* Values to use for the ALSA start, stop and silence thresholds.  Setting
     * any one of these values to 0 will cause the default tinyalsa values to be
     * used instead.  Tinyalsa defaults are as follows.
     *
     * start_threshold   : period_count * period_size
     * stop_threshold    : period_count * period_size
     * silence_threshold : 0
     */
    unsigned int start_threshold;
    unsigned int stop_threshold;
    unsigned int silence_threshold;
    /* Minimum number of frames available before pcm_mmap_write() will actually
     * write into the kernel buffer. Only used if the stream is opened in mmap mode
     * (pcm_open() called with PCM_MMAP flag set).   Use 0 for default.
     */
    int avail_min;
};

pcm config 구조체에서는 channel 개수, rate, period size, period count, audio format에 대한 설정을 해준다.

  • format
    • PCM_FORMAT_S16_LE
      • Signed 16-bit, Little Endian
    • 그 외 PCM_FORMAT_S16_BE, PCM_FORMAT_S24_LE, PCM_FORMAT_S24_BE
    • tinyalsa\pcm.h 에서 확인 가능
  • period size
    • 한번에 읽어오는 frame의 개수
  • period count
    • buffer = period size * period count
  • start threshold
    • PCM start 하기에 최소한으로 필요한 frame 개수
  • stop threshold
    • PCM stop 하기에 최소한으로 필요한 frame 개수

 

PCM Structure

pcm 구조체

struct pcm {
    int fd;
    unsigned int flags;
    int running:1;
    int underruns;
    unsigned int buffer_size;
    unsigned int boundary;
    char error[PCM_ERROR_MAX];
    struct pcm_config config;
    struct snd_pcm_mmap_status *mmap_status;
    struct snd_pcm_mmap_control *mmap_control;
    struct snd_pcm_sync_ptr *sync_ptr;
    void *mmap_buffer;
    unsigned int noirq_frames_per_msec;
    int wait_for_avail_min;
};

 

PCM Open

struct pcm *pcm_open(unsigned int card, unsigned int device, unsigned int flags, const struct pcm_config *config)

Description

pcm open을 하고 pcm 구조체를 받아온다.

Parameters

card - sound card 번호

device - dai-link 번호

ex) device tree에서 sound card 0의 dai-link 0번 i2S를 사용한다면, card와 device에 각각 0을 넘겨주면 된다.

flags - pcm open flags

ex) PCM_OUT, PCM_IN, PCM_MMAP, PCM_NOIRQ, PCM_NORESTART, PCM_MONOTONIC, PCM_NONBLOCK, PCM_STATE_PREPARED .. etc

config - pcm config 구조체

Return

pcm 구조체

 

PCM Read

int pcm_read(struct pcm *pcm, void *data, unsigned int count)

Description

data에 pcm read한 데이터를 count만큼 가져온다.

Parameters

pcm - open할 때 반환받은 pcm 구조체

data - audio data를 저장할 buffer

count - frame 당 byte 개수

보통 하나의 frame에 몇 byte가 있는지 반환하는 pcm_frames_to_bytes(const struct pcm *pcm, unsigned int frames) 함수를 사용해서 count 값을 넣어준다.

Returns

0일 경우, 성공

-EPIPE의 경우, underrun이나 overrun 발생할 때 반환

-ESTRPIPE 의 경우, device가 suspend 상태일 때 반환

-EBADFD의 경우, 어플리케이션과 alsa-lib 사이에 연결이 끊어진 경우에 반환

-ENOTTY, -ENODEV 의 경우, device가 물리적으로 해제된 경우에 반환

 

PCM Write

int pcm_write(struct pcm *pcm, const void *data, unsigned int count)

Description

data에 저장된 데이터를 count만큼 쓴다.

Parameters

pcm - open할 때 반환받은 pcm 구조체

data - audio data를 저장된 buffer

count - frame 당 byte 개수

보통 하나의 frame에 몇 byte가 있는지 반환하는 pcm_frames_to_bytes(const struct pcm *pcm, unsigned int frames) 함수를 사용해서 count 값을 넣어준다.

Returns

0 일 경우, 성공

-EPIPE의 경우, underrun이나 overrun 발생할 때 반환

-ESTRPIPE 의 경우, device가 suspend 상태일 때 반환

-EBADFD의 경우, 어플리케이션과 alsa-lib 사이에 연결이 끊어진 경우에 반환

-ENOTTY, -ENODEV 의 경우, device가 물리적으로 해제된 경우에 반환


PCM Close

int pcm_close(struct pcm *pcm)

Description

pcm을 close한다.

Parameters

pcm - open할 때 반환받은 pcm 구조체

Returns

항상 0 반환

 

 

 

 

 

 

ALSA

Linux에서는 ALSA를 사용한다.

ALSA의 경우에는 open, hw parameter 설정, sw parameter 설정, prepare, start, (avail 체크), read/write, close 과정으로 audio를 다룬다.

 

 

Data Structures

PCM structure

typedef struct  _snd_pcm snd_pcm_t

PCM HW config

typedef struct  _snd_pcm_hw_params snd_pcm_hw_params_t

PCM SW config

typedef struct  _snd_pcm_sw_params snd_pcm_sw_params_t

 

PCM Open

int snd_pcm_open(snd_pcm_t **pcmp, const char *name, snd_pcm_stream_t stream, int mode)

Description

pcm을 open한다.

Parameters

pcmp - open할 때 반환 받을 pcm 구조체

name - PCM 식별자

(ex) "hw:0,2"

stream - playback 목적으로 pcm open을 하는지, capture 목적으로 pcm open을 하는지 넘겨줌

(ex) SND_PCM_STREAM_PLAYBACK, SND_PCM_STREAM_CAPTURE

mode - open mode

(ex) SND_PCM_NONBLOCK, SND_PCM_ASYNC

Returns

항상 0 반환

 

PCM HW Params

Hardware Parameter란 audio format, channel 개수, sampling rate, period size, buffer size 등을 말한다.

 

ALSA Library FunctionDescription

snd_pcm_hw_params_malloc snd_pcm_hw_params_t 구조체 메모리 할당
snd_pcm_hw_params_any snd_pcm_hw_params_t 구조체 초기화
snd_pcm_hw_params_set_access access type 설정 (ex) SND_PCM_ACCESS_RW_INTERLEAVED, SND_PCM_ACCESS_RW_NONINTERLEAVED
snd_pcm_hw_params_set_format audio format 설정 (ex) SND_PCM_FORMAT_S16_LE
snd_pcm_hw_params_set_channels audio channel 설정
snd_pcm_hw_params_set_buffer_size audio buffer size 설정
snd_pcm_hw_params_set_rate_near 샘플레이트 설정 시 하드웨어가 정확한 샘플레이트를 지원하지 않는다면 가장 근접한 가능한 레이트를 사용하도록 설정
snd_pcm_hw_params_set_period_size alsa period_size를 설정
snd_pcm_hw_params

snd_pcm_hw_params_t 구조체에 저장된 PCM hardware configuration을 하드웨어에 알려주고 snd_pcm_prepare를 호출

snd_pcm_hw_params_free snd_pcm_hw_params_t 구조체 free


참고 웹페이지  https://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m___h_w___params.html#ga6e2dd8efbb7a4084bd05e6cc458d84f7

 

 

 

<cf> interleaved access vs non-interleaved access

 

  • Interleaved mode
    • 하나의 buffer에 channel sample이 번갈아가며 저장
  • Non-interleaved mode
    • 각 채널별로 buffer가 존재하여 sample이 저장됨

 

 

 

PCM SW Params

Software Parameter란 start threshold, stop threshold, avail min 등을 말한다.

 

ALSA Library FunctionDescription

snd_pcm_sw_params_malloc snd_pcm_sw_params_t 구조체 할당
snd_pcm_sw_params_current 현재 SW config를 snd_pcm_sw_params_t 구조체에 저장
snd_pcm_sw_params_set_start_threshold start threshold 설정 (보통 period size로 설정) ※ byte 크기로 넘겨주는 것에 유의
snd_pcm_sw_params_set_avail_min 최소 avail 설정 (보통 period size으로 설정)
snd_pcm_sw_params snd_pcm_sw_params_t 구조체에 저장된 PCM software configuration을 아래 layer에 알려줌
snd_pcm_sw_params_free snd_pcm_sw_params_t 구조체 free

참고 웹페이지 https://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m___s_w___params.html

 

(cf) alsa에서 말하는 avail 이란, buffer에서 빈 공간 frame 개수를 말한다. delay는 buffer에 있는 데이터가 들은 frame 개수를 말한다.

 

PCM Prepare

int snd_pcm_prepare(snd_pcm_t *pcm)

Description

pcm을 prepare한다.

Parameters

pcm - open할 때 반환 받은 pcm 구조체

Returns

0 일 경우, 성공

-EPIPE의 경우, underrun이나 overrun 발생할 때 반환

-ESTRPIPE 의 경우, device가 suspend 상태일 때 반환

-EBADFD의 경우, 어플리케이션과 alsa-lib 사이에 연결이 끊어진 경우에 반환

-ENOTTY, -ENODEV 의 경우, device가 물리적으로 해제된 경우에 반환


PCM Start

int snd_pcm_start(snd_pcm_t *pcm)

Description

pcm을 start한다.

Parameters

pcm - open할 때 반환 받은 pcm 구조체

Returns

0 일 경우, 성공

-EPIPE의 경우, underrun이나 overrun 발생할 때 반환

-ESTRPIPE 의 경우, device가 suspend 상태일 때 반환

-EBADFD의 경우, 어플리케이션과 alsa-lib 사이에 연결이 끊어진 경우에 반환

-ENOTTY, -ENODEV 의 경우, device가 물리적으로 해제된 경우에 반환


PCM Avail

snd_pcm_sframes_t snd_pcm_avail(snd_pcm_t *pcm)

Description

읽히거나 쓸 준비가 된 frame 개수를 반환한다. (ALSA에서 보통 avail은 버퍼의 비어있는 공간, delay는 버퍼의 데이터가 있는 공간을 말한다.)

Parameters

pcm - open할 때 반환 받은 pcm 구조체

Returns

양수일 경우, frame 개수 반환

-EPIPE의 경우, underrun이나 overrun 발생할 때 반환

-ESTRPIPE 의 경우, device가 suspend 상태일 때 반환

-EBADFD의 경우, 어플리케이션과 alsa-lib 사이에 연결이 끊어진 경우에 반환

-ENOTTY, -ENODEV 의 경우, device가 물리적으로 해제된 경우에 반환

 

PCM Read

snd_pcm_sframes_t snd_pcm_readi(snd_pcm_t *pcm, void buffer, snd_pcm_uframes_t size)

Description

interleaved frame을 읽는다.

만일 PCM이 blocking mode로 열렸을 경우, 모든 frame이 찰 때까지 기다린다. underrun이 발생할 경우에만 읽어온 frame 개수가 적을 수 있다.

non-blocking mode일 경우, 기다리지 않는다.

Parameters

pcm - open할 때 반환 받은 pcm 구조체

buffer - 읽어오려는 frame을 담을 버퍼

size - 읽으려는 frame 개수

Returns

양수일 경우, 읽어온 frame 개수 반환

-EPIPE의 경우, underrun이나 overrun 발생할 때 반환

underrun이 발생 하는 경우, snd_pcm_prepare를 호출해야 함.

-ESTRPIPE 의 경우, device가 suspend 상태일 때 반환

suspend 상태인 경우, snd_pcm_resume을 해준 뒤 snd_pcm_prepare 호출해야 함.

-EBADFD의 경우, 올바른 state가 아닐 경우 반환

SND_PCM_STATE_PREPARED 상태나 SND_PCM_STATE_RUNNING 상태일 때만 read/write가 가능

snd_pcm_sframes_t snd_pcm_readn(snd_pcm_t *pcm, void buffer, snd_pcm_uframes_t size)

Description

non-interleaved frame을 읽는다.

만일 PCM이 blocking mode로 열렸을 경우, 모든 frame이 찰 때까지 기다린다. underrun이 발생할 경우에만 읽어온 frame 개수가 적을 수 있다.

non-blocking mode일 경우, 기다리지 않는다.

Parameters

pcm - open할 때 반환 받은 pcm 구조체

buffer - 읽어오려는 frame을 담을 버퍼

size - 읽으려는 frame 개수

Returns

양수일 경우, 읽어온 frame 개수 반환

-EPIPE의 경우, underrun이나 overrun 발생할 때 반환

underrun이 발생 하는 경우, snd_pcm_prepare를 호출해야 함.

-ESTRPIPE 의 경우, device가 suspend 상태일 때 반환

suspend 상태인 경우, snd_pcm_resume을 해준 뒤 snd_pcm_prepare 호출해야 함.

-EBADFD의 경우, 올바른 state가 아닐 경우 반환

SND_PCM_STATE_PREPARED 상태나 SND_PCM_STATE_RUNNING 상태일 때만 read/write가 가능

PCM Write

snd_pcm_sframes_t snd_pcm_writei(snd_pcm_t *pcm, void buffer, snd_pcm_uframes_t size)

Description

interleaved frame을 쓴다.

만일 PCM이 blocking mode로 열렸을 경우, 모든 frame이 play 될때까지 기다리거나 playback ring buffer에 넣을 때까지 기다린다. underrun이 발생할 경우에만 읽어온 frame 개수가 적을 수 있다.

non-blocking mode일 경우, 기다리지 않는다.

Parameters

pcm - open할 때 반환 받은 pcm 구조체

buffer - 읽어오려는 frame을 담을 버퍼

size - 읽으려는 frame 개수

Returns

양수일 경우, 읽어온 frame 개수 반환

-EPIPE의 경우, underrun이 발생할 때 반환

underrun이 발생 하는 경우, snd_pcm_prepare를 호출해야 함

-ESTRPIPE 의 경우, device가 suspend 상태일 때 반환

suspend 상태인 경우, snd_pcm_resume을 해준 뒤 snd_pcm_prepare 호출해야 함

-EBADFD의 경우, 올바른 state가 아닐 경우 반환

SND_PCM_STATE_PREPARED 상태나 SND_PCM_STATE_RUNNING 상태일 때만 read/write가 가능

 

snd_pcm_sframes_t snd_pcm_writen(snd_pcm_t *pcm, void buffer, snd_pcm_uframes_t size)

Description

non-interleaved frame을 쓴다.

만일 PCM이 blocking mode로 열렸을 경우, 모든 frame이 play 될때까지 기다리거나 playback ring buffer에 넣을 때까지 기다린다. underrun이 발생할 경우에만 읽어온 frame 개수가 적을 수 있다.

non-blocking mode일 경우, 기다리지 않는다.

Parameters

pcm - open할 때 반환 받은 pcm 구조체

buffer - 읽어오려는 frame을 담을 버퍼

size - 읽으려는 frame 개수

Returns

양수일 경우, 읽어온 frame 개수 반환

-EPIPE의 경우, underrun이 발생할 때 반환

underrun이 발생 하는 경우, snd_pcm_prepare를 호출해야 함

-ESTRPIPE 의 경우, device가 suspend 상태일 때 반환

suspend 상태인 경우, snd_pcm_resume을 해준 뒤 snd_pcm_prepare 호출해야 함

-EBADFD의 경우, 올바른 state가 아닐 경우 반환

SND_PCM_STATE_PREPARED 상태나 SND_PCM_STATE_RUNNING 상태일 때만 read/write가 가능


PCM Close

int snd_pcm_close(snd_pcm_t *pcm)

Description

pcm을 close한다.

Parameters

pcm - open할 때 반환 받은 pcm 구조체

Returns

0 일 경우, 성공

음수의 경우 실패

 

 

 

ALSA library 참고 웹페이지

ALSA

ALSA libWeb Page

PCM interface https://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html#ga042aba7262a4cbb4d444b6fc08cb7124
HW params https://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m___h_w___params.html
SW Params https://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m___s_w___params.html#ga79b12cbbd309750156261e7f5a39167b

 

Tiny ALSA

ALSA libWeb Page

github https://github.com/tinyalsa/tinyalsa

 

 

+ Recent posts