ALSA: доступ без чередования не поддерживается?

snd_pcm_acw_params_set_set не работает при вызове с типом доступа 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

person kassiopeia    schedule 15.11.2012    source источник


Ответы (1)


Функции hw_params_set_* принимают только те значения, которые поддерживаются устройством.

Большинство устройств по умолчанию (plughw, default и т. д.) поддерживают автоматическое преобразование и, следовательно, принимают все форматы. hw устройств нет.

person CL.    schedule 15.11.2012