PCM ハードウェア構成
PCM を開いたら、まずは、ハードウェアの構成をインストールする必要があります。
ハードウェア構成には、サンプルのフォーマットタイプや、サンプリングレートなどの、重要な情報が含まれています。
ハードウェア構成は、再生/録音中は変更できません。
PCM を開いた直後は、ハードウェア構成がインストールされていないので、常にセットする必要があります。
PCM で利用可能な、すべてのハードウェア構成の情報を取得します。
すでにハードウェア構成がインストールされている場合は、先に snd_pcm_hw_free() で、ハードウェア構成を削除した方がいい。
ハードウェア構成には、サンプルのフォーマットタイプや、サンプリングレートなどの、重要な情報が含まれています。
ハードウェア構成は、再生/録音中は変更できません。
PCM を開いた直後は、ハードウェア構成がインストールされていないので、常にセットする必要があります。
ハードウェア構成の扱い方
ハードウェア構成は、少し珍しいやり方でセットします。
まず、開いた PCM 上で利用可能な、ハードウェア構成の情報を、snd_pcm_hw_params_t にすべて取得します。
アプリケーション側が選択できるいくつかの項目は、snd_pcm_hw_params_t 内で、複数の値が格納できるような状態になっています。
snd_pcm_hw_params_any() を実行すると、PCM で利用できる複数の値がセットされます。
その中から、各項目ごとに、実際に使用したいものを選択し、一つの値、または複数の値に絞って、セットします。
設定が決まったら、snd_pcm_hw_params() でハードウェア構成をインストールします。
一つの項目で複数の値がある場合は、項目ごとに、最初の値や、最小の値などが選択されます。
まず、開いた PCM 上で利用可能な、ハードウェア構成の情報を、snd_pcm_hw_params_t にすべて取得します。
アプリケーション側が選択できるいくつかの項目は、snd_pcm_hw_params_t 内で、複数の値が格納できるような状態になっています。
snd_pcm_hw_params_any() を実行すると、PCM で利用できる複数の値がセットされます。
その中から、各項目ごとに、実際に使用したいものを選択し、一つの値、または複数の値に絞って、セットします。
設定が決まったら、snd_pcm_hw_params() でハードウェア構成をインストールします。
一つの項目で複数の値がある場合は、項目ごとに、最初の値や、最小の値などが選択されます。
確保
まずは、snd_pcm_hw_params_t を確保する必要があります。
//サイズ取得 size_t snd_pcm_hw_params_sizeof(void); //確保 int snd_pcm_hw_params_malloc(snd_pcm_hw_params_t **ptr); //解放 void snd_pcm_hw_params_free(snd_pcm_hw_params_t *obj);
利用可能な情報を取得
int snd_pcm_hw_params_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
PCM で利用可能な、すべてのハードウェア構成の情報を取得します。
すでにハードウェア構成がインストールされている場合は、先に snd_pcm_hw_free() で、ハードウェア構成を削除した方がいい。
各項目のマスクを取得
ハードウェア構成で設定できる項目はいくつかありますが、ここでは、複数のタイプから選択できる項目を紹介します。
これらは、マスクの形で、複数の値を選択できます。
まずは、各項目のマスクを取得して、どのタイプが使用できるかをチェックしてみます。
snd_pcm_access_mask_t などは、非公開の構造体になっているため、それぞれ、取得する前にメモリを確保する必要があります。
マスクを操作するための各関数などは、以下をご覧ください。
アクセスタイプ/マスク
フォーマット/マスク
サブフォーマット/マスク
- アクセスタイプ
サンプルを読み書きする時の操作方法です。 - フォーマットタイプ
サンプルのフォーマットタイプ。 - サブフォーマット
サンプルのフォーマットの補足タイプ。
どのビットを使うか。
これらは、マスクの形で、複数の値を選択できます。
まずは、各項目のマスクを取得して、どのタイプが使用できるかをチェックしてみます。
//アクセスタイプのマスクを取得 int snd_pcm_hw_params_get_access_mask(snd_pcm_hw_params_t *params, snd_pcm_access_mask_t *mask); //フォーマットタイプのマスクを取得 void snd_pcm_hw_params_get_format_mask(snd_pcm_hw_params_t *params, snd_pcm_format_mask_t *mask); //サブフォーマットのマスクを取得 void snd_pcm_hw_params_get_subformat_mask(snd_pcm_hw_params_t *params, snd_pcm_subformat_mask_t *mask);
snd_pcm_access_mask_t などは、非公開の構造体になっているため、それぞれ、取得する前にメモリを確保する必要があります。
マスクを操作するための各関数などは、以下をご覧ください。
アクセスタイプ/マスク
フォーマット/マスク
サブフォーマット/マスク
プログラム
開いた PCM で利用可能な、アクセスタイプ・フォーマット・サブフォーマットを出力します。
$ cc -o 10-hwparam 10-hwparam.c -lasound
#include <stdio.h> #include <alsa/asoundlib.h> int main(int argc,char **argv) { snd_pcm_t *pcm; snd_pcm_hw_params_t *hw; snd_pcm_access_mask_t *amask; snd_pcm_format_mask_t *format; snd_pcm_subformat_mask_t *subformat; int i; if(snd_pcm_open(&pcm, (argc >= 2)? argv[1]: "default", SND_PCM_STREAM_PLAYBACK, 0)) { printf("open error\n"); return 1; } snd_pcm_hw_params_malloc(&hw); snd_pcm_hw_params_any(pcm, hw); //アクセスタイプ snd_pcm_access_mask_malloc(&amask); snd_pcm_hw_params_get_access_mask(hw, amask); printf("-- access --\n"); for(i = 0; i < SND_PCM_ACCESS_LAST; i++) { if(snd_pcm_access_mask_test(amask, i)) printf("%s\n", snd_pcm_access_name(i)); } snd_pcm_access_mask_free(amask); //フォーマット snd_pcm_format_mask_malloc(&format); snd_pcm_hw_params_get_format_mask(hw, format); printf("\n-- format --\n"); for(i = 0; i < SND_PCM_FORMAT_LAST; i++) { if(snd_pcm_format_mask_test(format, i)) printf("%s\n", snd_pcm_format_name(i)); } snd_pcm_format_mask_free(format); //サブフォーマット snd_pcm_subformat_mask_malloc(&subformat); snd_pcm_hw_params_get_subformat_mask(hw, subformat); printf("\n-- subformat --\n"); for(i = 0; i < SND_PCM_SUBFORMAT_LAST; i++) { if(snd_pcm_subformat_mask_test(subformat, i)) printf("%s\n", snd_pcm_subformat_name(i)); } snd_pcm_subformat_mask_free(subformat); // snd_pcm_hw_params_free(hw); snd_pcm_close(pcm); return 0; }
実行結果
default
デフォルトの PCM の場合は、各フォーマットが利用可能になっています。
-- access -- MMAP_INTERLEAVED MMAP_NONINTERLEAVED MMAP_COMPLEX RW_INTERLEAVED RW_NONINTERLEAVED -- format -- S8 U8 S16_LE S16_BE U16_LE U16_BE S24_LE S24_BE U24_LE U24_BE S32_LE S32_BE U32_LE U32_BE FLOAT_LE FLOAT_BE FLOAT64_LE FLOAT64_BE MU_LAW A_LAW IMA_ADPCM S20_LE S20_BE U20_LE U20_BE S24_3LE S24_3BE U24_3LE U24_3BE S20_3LE S20_3BE U20_3LE U20_3BE S18_3LE S18_3BE U18_3LE U18_3BE -- subformat -- STD MSBITS_MAX MSBITS_20 MSBITS_24
front
"front" は、前面のスピーカーという意味ですが、ステレオのみの状態であれば、デフォルトのアナログ入出力とほぼ同じ意味になります。
ただし、変換などが有効になっていないので、使用できるタイプは制限されています。
ただし、変換などが有効になっていないので、使用できるタイプは制限されています。
$ ./10-hwparam front -- access -- MMAP_INTERLEAVED RW_INTERLEAVED -- format -- S16_LE S32_LE -- subformat -- STD
HDMI
$ ./10-hwparam hdmi -- access -- MMAP_INTERLEAVED RW_INTERLEAVED -- format -- S16_LE S32_LE -- subformat -- STD MSBITS_MAX