ALSA:PCM 読み書き

読み書き
snd_pcm_writeiインターリーブフレームを書き込み
snd_pcm_writen非インターリーブフレームを書き込み
snd_pcm_readiインターリーブフレームを読み込む
snd_pcm_readn非インターリーブフレームを読み込み
MMAP
snd_pcm_mmap_beginmmap 領域へのアクセスを開始
snd_pcm_mmap_commit領域へのアクセスを完了
snd_pcm_mmap_writeimmap を使ってインターリーブ書き込み
snd_pcm_mmap_writenmmap を使って非インターリーブ書き込み
snd_pcm_mmap_readimmap を使ってインターリーブ読み込み
snd_pcm_mmap_readnmmap を使って非インターリーブ読み込み
channel_area
snd_pcm_area_silence領域を無音にする
snd_pcm_areas_silence領域を無音にする (複数のチャンネル)
snd_pcm_area_copy領域をコピー
snd_pcm_areas_copy領域をコピー (複数のチャンネル)
snd_pcm_areas_copy_wrap領域をコピー (複数のチャンネル、指定サイズ)
読み書き
snd_pcm_sframes_t snd_pcm_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size);
インターリーブフレームを書き込み。

ブロックモードで PCM が実行されている場合、すべてのフレームが、再生されるか、リングバッファに置かれるまで待機する。
シグナルまたはアンダーランが発生した場合、戻り値が size より小さくなる場合がある。

非ブロッキングモードの場合、関数はすぐに戻る。
size
書き込むフレーム数
戻り値
正の値で、実際に書き込まれたフレーム数。それ以外の場合は、負のエラーコード。

-EAGAIN: バッファがいっぱいでデータが書き込めない。
-EBADFD: PCM が正常な状態ではない (SND_PCM_STATE_PREPARED または SND_PCM_STATE_RUNNING 以外)。
-EPIPE: アンダーランが発生。
-ESTRPIPE: サスペンド状態が発生。
snd_pcm_sframes_t snd_pcm_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size);
非インターリーブフレームを書き込み
bufs
各チャンネルごとのバッファの配列
snd_pcm_sframes_t snd_pcm_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size);
インターリーブフレームを読み込む。

PCM がブロックモードで実行されている場合、要求されたフレームがすべて満たされるまで待機する。
シグナルまたはアンダーランが発生した場合、戻り値が size より小さくなる場合がある。

非ブロッキングモードの場合、関数はすぐに戻る。
size
読み込むフレーム数
戻り値
正の値で、実際に読み込まれたフレームの数。それ以外の場合は、負のエラーコード。
snd_pcm_sframes_t snd_pcm_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size);
非インターリーブフレームを読み込み
MMAP
int snd_pcm_mmap_begin(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas, snd_pcm_uframes_t *offset, snd_pcm_uframes_t *frames);

typedef struct _snd_pcm_channel_area {
    void *addr;         //ベースアドレス
    unsigned int first; //最初のサンプルのオフセット (ビット単位)
    unsigned int step;  //サンプルの距離 (ビット単位)
} snd_pcm_channel_area_t;
mmap 領域へのアクセスを開始。

この直前に、snd_pcm_avail_update() 関数を呼び出す必要がある。
でないとこの関数は、使用可能なフレームとして、間違った数を返す可能性がある。

※ソフトウェア構成の自動開始などは適用されないため、アプリケーション側がそれらの動作を処理する必要がある。
areas
各チャンネルごとの領域情報の配列ポインタが返る。
インターリーブなら、1つのみ。
offset
書き込む位置のオフセットが返る (フレーム単位)。
addr のベースアドレスに、この位置を加算する必要がある。
frames
読み書きしたいフレーム数をセットしておく。
実際に読み書きできるフレーム数が返る (入力値以下)。
リングバッファがいっぱいの時などは、0 が返る場合がある。
戻り値
0 で成功、負の値でエラーコード
snd_pcm_sframes_t snd_pcm_mmap_commit(snd_pcm_t *pcm, snd_pcm_uframes_t offset, snd_pcm_uframes_t frames);
領域へのアクセスを完了させる。
snd_pcm_mmap_begin() を呼び出すたびに、snd_pcm_mmap_commit() を呼び出す必要がある。
offset
snd_pcm_mmap_begin() の offset 引数で返されたオフセット値を渡す
frames
バッファに書き込んだ/読み込んだフレーム数。
snd_pcm_mmap_begin() の frames 引数で返された値を超えてはならない。
戻り値
転送されたフレームの数。負の値でエラーコード
snd_pcm_sframes_t snd_pcm_mmap_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size);
mmap を使ってインターリーブ書き込み。

ブロックモードを選択した場合、要求されたすべてのバイトが再生されるか、再生リングバッファに格納されるまで待機する。
バイト数は、シグナルまたはアンダーランが発生した場合にのみ少なくなる。

非ブロッキングモードを選択した場合、まったく待機しない。
size
書き込むフレーム数
戻り値
実際に書き込まれたフレームの数。負の値でエラーコード
snd_pcm_sframes_t snd_pcm_mmap_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size);
mmap を使って非インターリーブ書き込み
snd_pcm_sframes_t snd_pcm_mmap_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size);
mmap を使ってインターリーブ読み込み。

ブロックモードが選択された場合、要求されたバイトがすべて満たされるまで待機する。
バイト数は、シグナルまたはアンダーランが発生した場合にのみ少なくなる。
非ブロッキングモードを選択した場合、まったく待機しない。
size
読み込むフレーム数
戻り値
実際に読み込まれたフレームの数。負の値でエラーコード
snd_pcm_sframes_t snd_pcm_mmap_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size);
mmap を使って非インターリーブ読み込み
channel_area
int snd_pcm_area_silence(const snd_pcm_channel_area_t *dst_channel, snd_pcm_uframes_t dst_offset, unsigned int samples, snd_pcm_format_t format);
領域を無音にする
戻り値
0 で成功、負の値でエラーコード
int snd_pcm_areas_silence(const snd_pcm_channel_area_t *dst_channels, snd_pcm_uframes_t dst_offset,
    unsigned int channels, snd_pcm_uframes_t frames, snd_pcm_format_t format);
領域を無音にする (複数のチャンネル)
戻り値
0 で成功、負の値でエラーコード
int snd_pcm_area_copy(const snd_pcm_channel_area_t *dst_channel, snd_pcm_uframes_t dst_offset,
    const snd_pcm_channel_area_t *src_channel, snd_pcm_uframes_t src_offset,
    unsigned int samples, snd_pcm_format_t format);
領域をコピー
戻り値
0 で成功、負の値でエラーコード
int snd_pcm_areas_copy(const snd_pcm_channel_area_t *dst_channels, snd_pcm_uframes_t dst_offset,
    const snd_pcm_channel_area_t *src_channels, snd_pcm_uframes_t src_offset,
    unsigned int channels, snd_pcm_uframes_t frames, snd_pcm_format_t format);
領域をコピー (複数のチャンネル)
戻り値
0 で成功、負の値でエラーコード
int snd_pcm_areas_copy_wrap(const snd_pcm_channel_area_t *dst_channels, snd_pcm_uframes_t dst_offset, const snd_pcm_uframes_t dst_size,
    const snd_pcm_channel_area_t *src_channels, snd_pcm_uframes_t src_offset, const snd_pcm_uframes_t src_size,
    const unsigned int channels, snd_pcm_uframes_t frames, const snd_pcm_format_t format);
領域をコピー (複数のチャンネル、指定サイズ)
戻り値
0 で成功、負の値でエラーコード