PCM ステータス
PCM の現在のステータスを取得するには、snd_pcm_status() を実行します。
ステータス関連の関数は、ステータス をご覧ください。
PCM の現在のステータス情報を取得します。
snd_pcm_status_t は、あらかじめ確保しておく必要があります。
ステータス関連の関数は、ステータス をご覧ください。
PCM ステータスの取得
int snd_pcm_status(snd_pcm_t *pcm, snd_pcm_status_t *status);
PCM の現在のステータス情報を取得します。
snd_pcm_status_t は、あらかじめ確保しておく必要があります。
snd_pcm_status_t
//サイズ取得 size_t snd_pcm_status_sizeof(void); //確保 int snd_pcm_status_malloc(snd_pcm_status_t **ptr); //解放 void snd_pcm_status_free(snd_pcm_status_t *obj);
PCM 状態の取得
PCM 状態 (state) は、PCM が実行中かなどの状態を示します。
//snd_pcm_status_t から取得 snd_pcm_state_t snd_pcm_status_get_state(const snd_pcm_status_t *obj); //PCM から直接取得 snd_pcm_state_t snd_pcm_state(snd_pcm_t *pcm);
PCM 状態
snd_pcm_state_t は、以下のような値です。
SND_PCM_STATE_OPEN | 開いている。 snd_pcm_open() 後。 |
---|---|
SND_PCM_STATE_SETUP | 構成がインストールされている。 snd_pcm_prepare() を待機している状態。 再生/録音が停止されると、この状態になる。 |
SND_PCM_STATE_PREPARED | snd_pcm_prepare() が行われ、PCM を開始する準備ができている。 |
SND_PCM_STATE_RUNNING | 再生/録音が実行されている。 snd_pcm_drop() または snd_pcm_drain() で停止できる。 |
SND_PCM_STATE_XRUN | アンダーラン (再生) またはオーバーラン (録音) 状態。 読み書き時に -EPIPE が返った場合は、この状態である。 回復するには、snd_pcm_recover() か prepare を実行する。 |
SND_PCM_STATE_DRAINING | drain によって停止を待っている |
SND_PCM_STATE_PAUSED | snd_pcm_pause() による一時停止中 |
SND_PCM_STATE_SUSPENDED | ハードウェアがサスペンド状態。 snd_pcm_resume() で再開できる。 |
SND_PCM_STATE_DISCONNECTED | ハードウェアが切断されている |
状態の遷移
まず、snd_pcm_open() 後、SND_PCM_STATE_OPEN 状態になります。
snd_pcm_hw_params() でハードウェア構成をインストールした場合、まずは SND_PCM_STATE_SETUP 状態になります。
関数内で自動的に snd_pcm_prepare() が実行されるので、インストールされた構成で PCM の準備が行われた後、SND_PCM_STATE_PREPARED 状態になります。
snd_pcm_hw_params() が戻った後は、PREPARED 状態になるので、SETUP 状態は捕捉できません。
PREPARED 状態は、再生や録音を開始する準備が出来ているということなので、再生/録音を開始するなら、snd_pcm_start() を実行します。
これにより、SND_PCM_STATE_RUNNING 状態になります。
snd_pcm_drop() で PCM を停止させると、SND_PCM_STATE_SETUP 状態になります。
この後、再び PCM を実行させたいなら、snd_pcm_prepare() を行う必要があります。
snd_pcm_hw_params() でハードウェア構成をインストールした場合、まずは SND_PCM_STATE_SETUP 状態になります。
関数内で自動的に snd_pcm_prepare() が実行されるので、インストールされた構成で PCM の準備が行われた後、SND_PCM_STATE_PREPARED 状態になります。
snd_pcm_hw_params() が戻った後は、PREPARED 状態になるので、SETUP 状態は捕捉できません。
PREPARED 状態は、再生や録音を開始する準備が出来ているということなので、再生/録音を開始するなら、snd_pcm_start() を実行します。
これにより、SND_PCM_STATE_RUNNING 状態になります。
snd_pcm_drop() で PCM を停止させると、SND_PCM_STATE_SETUP 状態になります。
この後、再び PCM を実行させたいなら、snd_pcm_prepare() を行う必要があります。
プログラム
実際に、PCM 状態の変化を見てみます。
$ cc -o 13-state 13-state.c -lasound
#include <stdio.h> #include <alsa/asoundlib.h> static void _put_state(snd_pcm_t *pcm) { snd_pcm_state_t state; state = snd_pcm_state(pcm); printf("> %s\n", snd_pcm_state_name(state)); } int main(void) { snd_pcm_t *pcm; snd_pcm_uframes_t buf,period; if(snd_pcm_open(&pcm, "default", SND_PCM_STREAM_PLAYBACK, 0)) { printf("open error\n"); return 1; } _put_state(pcm); //ハードウェア構成 snd_pcm_set_params(pcm, SND_PCM_FORMAT_S16_LE, SND_PCM_ACCESS_MMAP_INTERLEAVED, 1, 48000, 1, 100 * 1000); _put_state(pcm); snd_pcm_get_params(pcm, &buf, &period); printf("buf size: %lu\nperiod size: %lu\n", buf, period); //開始 snd_pcm_start(pcm); _put_state(pcm); // snd_pcm_close(pcm); return 0; }
実行結果
> OPEN > PREPARED buf size: 5120 period size: 1024 > RUNNING
「PCM を開いた後」「ハードウェア構成のインストール後」「再生の開始後」に、それぞれ PCM 状態を出力しています。
なお、ここではデータを全く書き込んでいませんが、特に問題は起きません。
ハードウェア構成を簡単にセット
ハードウェア構成の設定は少々面倒なので、snd_pcm_set_params() を使って、一部の値のみを指定して、簡単にインストールしています。
int snd_pcm_set_params(snd_pcm_t *pcm, snd_pcm_format_t format, snd_pcm_access_t access, unsigned int channels, unsigned int rate, int soft_resample, unsigned int latency);
soft_resample | リサンプリングを許可するか |
---|---|
latency | マイクロ秒単位。 バッファの長さの目安になる。 |
バッファとピリオドのサイズを取得
int snd_pcm_get_params(snd_pcm_t *pcm, snd_pcm_uframes_t *buffer_size, snd_pcm_uframes_t *period_size);
snd_pcm_hw_params_t を使わずに、バッファとピリオドのサイズ (フレーム単位) を取得します。
バッファの長さ
ここでは、latency を 100 ms に指定しています。
バッファの長さを 100 ms にしたい場合、フレーム数は以下のように計算できます。
(100*1000)/(1000*1000)*48000 = 4800 frames です。
ただし、バッファの長さはピリオド単位になるので、1024 フレーム単位で 4800 フレームが収まる値は、1024 * 5 = 5120 になります。
結果、バッファの長さは 5120 フレームになっています。
なお、バッファの長さの最大値は、PCM ごとに決まっているので、latency に大きい値を指定しても、一定以上の値にはなりません。
バッファの長さを 100 ms にしたい場合、フレーム数は以下のように計算できます。
frames = time(us) / (1000 * 1000) * samprate(Hz)
(100*1000)/(1000*1000)*48000 = 4800 frames です。
ただし、バッファの長さはピリオド単位になるので、1024 フレーム単位で 4800 フレームが収まる値は、1024 * 5 = 5120 になります。
結果、バッファの長さは 5120 フレームになっています。
なお、バッファの長さの最大値は、PCM ごとに決まっているので、latency に大きい値を指定しても、一定以上の値にはなりません。