6

私は現在、Alsa でサンプリングを行う必要があるプロジェクトに取り組んでいます。すべてを正しく設定しようとしていますが、読み値のサイズを正しく設定する方法に行き詰まっています。

私のタスクにとって興味深いと思われる2つのプリミティブがあります。

snd_pcm_hw_params_get_period_time
snd_pcm_hw_params_get_buffer_size

最初の名前は、出力がサンプリング期間の時間長になることを示唆していますが、それは奇妙です:f = 44100Hzサンプリング期間にサンプリングレートを設定している場合 (ナノ秒単位) はT0 = 1e9 / 44100 ~= 22676 ns、関数が応答する間T1 = 725 us = 725000 nsです。

一方、非ロック プリミティブを使用するように依頼された場合でも、'readi' をロックするのに必要な時間をプロファイリングしようとしていT2 = 8028603 nsますT3 = 12436217 ns

最後に、次の 2 つの意味がわかりません。

snd_pcm_hw_params_get_buffer_time
snd_pcm_hw_params_get_period_size

バッファの時間と期間のサイズを測定する方法がわかりませんが、前者は と同じ値をget_buffer_size返し、後者は と同じ値を返しますget_period_time

ヒントはありますか?

4

3 に答える 3

6

ALSA には奇妙な ^W 固有の用語があります。

  • フレーム: サンプル x チャネル (つまり、ステレオ フレームは 2 つのサンプルで構成され、モノラル フレームは 1 つのサンプルで構成されます...)
  • 期間: デバイスがアプリケーションへの転送を確認した後に (通常は割り込みを介して) 転送されたサンプルの数。

*_size 関数はフレーム単位でサイズを返すようです。

HTH

于 2010-07-27T15:32:39.603 に答える
5

これは私のサウンドカード初期化関数です。

まず、必要なパラメータを設定します

static
int init_soundcard (snd_pcm_t *handle, unsigned *rate, uint8_t channels,
                    snd_pcm_uframes_t *nframes, unsigned *period)
{
    snd_pcm_hw_params_t *hwparams;
    int err;

    snd_pcm_hw_params_alloca(&hwparams);

    err = snd_pcm_hw_params_any(handle, hwparams);
    if (err < 0) return err;

    err = snd_pcm_hw_params_set_rate_near(handle, hwparams, rate, NULL);
    if (err < 0) return err;

    err = snd_pcm_hw_params_set_access(handle, hwparams,
                                       SND_PCM_ACCESS_RW_INTERLEAVED);
    if (err < 0) return err;

    err = snd_pcm_hw_params_set_format(handle, hwparams,
                                       SND_PCM_FORMAT_S16_LE);
    if (err < 0) return err;

    err = snd_pcm_hw_params_set_channels(handle, hwparams, channels);
    if (err < 0) return err;

すべてのパラメーターが正しく設定されると、パラメーターがハンドルに適用されます。

    err = snd_pcm_hw_params(handle, hwparams);
    if (err < 0) return err;

適用された後、勇敢なプログラマーは次のように必要なデータを取得できます。

get_period_size_min() は、サンプリングを含むバッファーのフレームの最小サイズを示します。このサイズのバッファーは十分な幅があります。

    err = snd_pcm_hw_params_get_period_size_min(hwparams, nframes, NULL);
    if (err < 0) return err;

これはかなり直感に反していますが、正しいサンプリング周期は、考えられるように 1/rate で与えられるわけではありません。get_period_time() プリミティブを使用して、サンプリング周期を取得できます!

    err = snd_pcm_hw_params_get_period_time(hwparams, period, NULL);
    if (err < 0) return err;

    return 0;
}
于 2010-08-06T08:30:23.890 に答える