3

ALSAのsnd_pcm_hw_params_set_access関数は、SND_PCM_ACCESS_RW_NONINTERLEAVEDアクセスタイプで呼び出されると失敗し、無効な引数があったことを報告します。同じコードがSND_PCM_ACCESS_RW_INTERLEAVEDアクセスで正常に機能します。

snd_pcm_hw_params_*関数の呼び出し順序を変更しようとしましたが効果がありませんでした。

次に、私のハードウェアは非インターリーブ再生をサポートしていない可能性があると思いましたが、この投稿によると、 ALSAサブシステムは、非インターリーブ再生自体をサポートしていない場合、ハードウェアに送信する前に非インターリーブデータをインターリーブします。したがって、非インターリーブアクセスは常に利用可能である必要があります。

それでは、なぜインターリーブされていないアクセスがサポートされていないように見えるのですか?

以下は、インターリーブ再生では正常に機能するコードですが、非インターリーブ再生ではこの問題が発生します。

int err;
if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) {
    fprintf(stderr, "ALSA: allocate hw_params error: %s\n", snd_strerror(err));
    throw 5;
}
if ((err = snd_pcm_hw_params_any(pb_dev, hw_params)) < 0) {
    fprintf(stderr, "ALSA: hw_params_any error: %s\n", snd_strerror(err));
    throw 5;
}
if ((err = snd_pcm_hw_params_set_access(pb_dev, hw_params, (pAudioCtx->sample_fmt < AV_SAMPLE_FMT_U8P) ? SND_PCM_ACCESS_RW_INTERLEAVED : SND_PCM_ACCESS_RW_NONINTERLEAVED)) < 0) {
    fprintf(stderr, "ALSA: set access type error: %s\n", snd_strerror(err));
    throw 5;
}
if ((err = snd_pcm_hw_params_set_channels(pb_dev, hw_params, pAudioCtx->channels)) < 0) {
    fprintf(stderr, "ALSA: set channel count error: %s\n", snd_strerror(err));
    throw 5;
}

snd_pcm_format_t sample_format;
switch (pAudioCtx->sample_fmt) {
    case AV_SAMPLE_FMT_U8: case AV_SAMPLE_FMT_U8P: sample_format = SND_PCM_FORMAT_U8; break;
    case AV_SAMPLE_FMT_S16: case AV_SAMPLE_FMT_S16P: sample_format = SND_PCM_FORMAT_S16; break;
    case AV_SAMPLE_FMT_S32: case AV_SAMPLE_FMT_S32P: sample_format = SND_PCM_FORMAT_S32; break;
    case AV_SAMPLE_FMT_FLT: case AV_SAMPLE_FMT_FLTP: sample_format = SND_PCM_FORMAT_FLOAT; break;
    case AV_SAMPLE_FMT_DBL: case AV_SAMPLE_FMT_DBLP: sample_format = SND_PCM_FORMAT_FLOAT64; break;
    default: fprintf(stderr, "sampleformat %d is not supported\n", pAudioCtx->sample_fmt);
        throw 5;
}

if ((err = snd_pcm_hw_params_set_format(pb_dev, hw_params, sample_format)) < 0) {
    fprintf(stderr, "ALSA: set sample format error: %s\n", snd_strerror(err));
    throw 5;
}
if ((err = snd_pcm_hw_params_set_rate_near(pb_dev, hw_params, (unsigned int*)&pAudioCtx->sample_rate, 0)) < 0) {
    fprintf(stderr, "ALSA: set sample rate error: %s\n", snd_strerror(err));
    throw 5;
}

if ((err = snd_pcm_hw_params(pb_dev, hw_params)) < 0) {
    fprintf(stderr, "ALSA: set parameters error: %s\n", snd_strerror(err));
    throw 5;
}

これを実行すると、次の出力が得られます。

ALSA: set access type error: Invalid argument
4

1 に答える 1

5

関数はhw_params_set_*、デバイスでサポートされている値のみを受け入れます。

ほとんどのデフォルトデバイス(、、plughwなどdefault)は自動変換をサポートしているため、すべての形式を受け入れます。 hwデバイスはしません。

于 2012-11-15T14:09:41.817 に答える